xref: /openbsd/sys/dev/pci/qla_pci.c (revision 8529ddd3)
1 /*	$OpenBSD: qla_pci.c,v 1.8 2014/04/03 20:01:47 brad Exp $ */
2 
3 /*
4  * Copyright (c) 2011 David Gwynne <dlg@openbsd.org>
5  * Copyright (c) 2013, 2014 Jonathan Matthew <jmatthew@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "bio.h"
21 
22 #include <sys/param.h>
23 #include <sys/systm.h>
24 #include <sys/kernel.h>
25 #include <sys/malloc.h>
26 #include <sys/device.h>
27 #include <sys/sensors.h>
28 #include <sys/rwlock.h>
29 
30 #include <machine/bus.h>
31 
32 #include <dev/pci/pcireg.h>
33 #include <dev/pci/pcivar.h>
34 #include <dev/pci/pcidevs.h>
35 
36 #ifdef __sparc64__
37 #include <dev/ofw/openfirm.h>
38 #endif
39 
40 #include <scsi/scsi_all.h>
41 #include <scsi/scsiconf.h>
42 
43 #include <dev/ic/qlareg.h>
44 #include <dev/ic/qlavar.h>
45 
46 #define QLA_PCI_MEM_BAR		0x14
47 #define QLA_PCI_IO_BAR		0x10
48 
49 int	qla_pci_match(struct device *, void *, void *);
50 void	qla_pci_attach(struct device *, struct device *, void *);
51 int	qla_pci_detach(struct device *, int);
52 
53 struct qla_pci_softc {
54 	struct qla_softc	psc_qla;
55 
56 	pci_chipset_tag_t	psc_pc;
57 	pcitag_t		psc_tag;
58 
59 	void			*psc_ih;
60 };
61 
62 struct cfattach qla_pci_ca = {
63 	sizeof(struct qla_pci_softc),
64 	qla_pci_match,
65 	qla_pci_attach
66 };
67 
68 #define PREAD(s, r)	pci_conf_read((s)->psc_pc, (s)->psc_tag, (r))
69 #define PWRITE(s, r, v)	pci_conf_write((s)->psc_pc, (s)->psc_tag, (r), (v))
70 
71 static const struct pci_matchid qla_devices[] = {
72 	{ PCI_VENDOR_QLOGIC,	PCI_PRODUCT_QLOGIC_ISP2100 },
73 	{ PCI_VENDOR_QLOGIC,	PCI_PRODUCT_QLOGIC_ISP2200 },
74 	{ PCI_VENDOR_QLOGIC,	PCI_PRODUCT_QLOGIC_ISP2300 },
75 	{ PCI_VENDOR_QLOGIC,	PCI_PRODUCT_QLOGIC_ISP2312 },
76 	{ PCI_VENDOR_QLOGIC,	PCI_PRODUCT_QLOGIC_ISP2322 },
77 	{ PCI_VENDOR_QLOGIC,	PCI_PRODUCT_QLOGIC_ISP6312 },
78 	{ PCI_VENDOR_QLOGIC,	PCI_PRODUCT_QLOGIC_ISP6322 },
79 };
80 
81 int
82 qla_pci_match(struct device *parent, void *match, void *aux)
83 {
84 	return (pci_matchbyid(aux, qla_devices, nitems(qla_devices)) * 2);
85 }
86 
87 void
88 qla_pci_attach(struct device *parent, struct device *self, void *aux)
89 {
90 	struct qla_pci_softc *psc = (void *)self;
91 	struct qla_softc *sc = &psc->psc_qla;
92 	struct pci_attach_args *pa = aux;
93 	pci_intr_handle_t ih;
94 	const char *intrstr;
95 	u_int32_t pcictl;
96 #ifdef __sparc64__
97 	u_int64_t wwn;
98 	int node;
99 #endif
100 
101 	pcireg_t bars[] = { QLA_PCI_MEM_BAR, QLA_PCI_IO_BAR };
102 	pcireg_t memtype;
103 	int r;
104 
105 	psc->psc_pc = pa->pa_pc;
106 	psc->psc_tag = pa->pa_tag;
107 	psc->psc_ih = NULL;
108 	sc->sc_dmat = pa->pa_dmat;
109 	sc->sc_ios = 0;
110 
111 	for (r = 0; r < nitems(bars); r++) {
112 		memtype = pci_mapreg_type(psc->psc_pc, psc->psc_tag, bars[r]);
113 		if (pci_mapreg_map(pa, bars[r], memtype, 0,
114 		    &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_ios, 0) == 0)
115 			break;
116 
117 		sc->sc_ios = 0;
118 	}
119 	if (sc->sc_ios == 0) {
120 		printf(": unable to map registers\n");
121 		return;
122 	}
123 
124 	if (pci_intr_map(pa, &ih)) {
125 		printf(": unable to map interrupt\n");
126 		goto unmap;
127 	}
128 	intrstr = pci_intr_string(psc->psc_pc, ih);
129 	psc->psc_ih = pci_intr_establish(psc->psc_pc, ih, IPL_BIO,
130 	    qla_intr, sc, DEVNAME(sc));
131 	if (psc->psc_ih == NULL) {
132 		printf(": unable to establish interrupt");
133 		if (intrstr != NULL)
134 			printf(" at %s", intrstr);
135 		printf("\n");
136 		goto deintr;
137 	}
138 
139 	printf(": %s\n", intrstr);
140 
141 	pcictl = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
142 	pcictl |= PCI_COMMAND_INVALIDATE_ENABLE |
143 	    PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE;
144 	/* fw manual says to enable bus master here, then disable it while
145 	 * resetting.. hm.
146 	 */
147 	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, pcictl);
148 
149 	pcictl = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
150 	pcictl &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
151 	pcictl &= ~(PCI_CACHELINE_MASK << PCI_CACHELINE_SHIFT);
152 	pcictl |= (0x80 << PCI_LATTIMER_SHIFT);
153 	pcictl |= (0x10 << PCI_CACHELINE_SHIFT);
154 	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, pcictl);
155 
156 	pcictl = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG);
157 	pcictl &= ~1;
158 	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, pcictl);
159 
160 	switch (PCI_PRODUCT(pa->pa_id)) {
161 	case PCI_PRODUCT_QLOGIC_ISP2100:
162 		sc->sc_isp_gen = QLA_GEN_ISP2100;
163 		sc->sc_isp_type = QLA_ISP2100;
164 		break;
165 
166 	case PCI_PRODUCT_QLOGIC_ISP2200:
167 		sc->sc_isp_gen = QLA_GEN_ISP2200;
168 		sc->sc_isp_type = QLA_ISP2200;
169 		break;
170 
171 	case PCI_PRODUCT_QLOGIC_ISP2300:
172 		sc->sc_isp_type = QLA_ISP2300;
173 		sc->sc_isp_gen = QLA_GEN_ISP23XX;
174 		break;
175 
176 	case PCI_PRODUCT_QLOGIC_ISP2312:
177 	case PCI_PRODUCT_QLOGIC_ISP6312:
178 		sc->sc_isp_type = QLA_ISP2312;
179 		sc->sc_isp_gen = QLA_GEN_ISP23XX;
180 		break;
181 
182 	case PCI_PRODUCT_QLOGIC_ISP2322:
183 	case PCI_PRODUCT_QLOGIC_ISP6322:
184 		sc->sc_isp_type = QLA_ISP2322;
185 		sc->sc_isp_gen = QLA_GEN_ISP23XX;
186 		break;
187 
188 	default:
189 		printf("unknown pci id %x", pa->pa_id);
190 		return;
191 	}
192 
193 #ifdef __sparc64__
194 	node = PCITAG_NODE(pa->pa_tag);
195 	if (OF_getprop(node, "port-wwn", &wwn, sizeof(wwn)) == sizeof(wwn))
196 		sc->sc_port_name = wwn;
197 	if (OF_getprop(node, "node-wwn", &wwn, sizeof(wwn)) == sizeof(wwn))
198 		sc->sc_node_name = wwn;
199 #endif
200 
201 	sc->sc_port = pa->pa_function;
202 
203 	if (qla_attach(sc) != 0) {
204 		/* error printed by qla_attach */
205 		goto deintr;
206 	}
207 
208 	return;
209 
210 deintr:
211 	pci_intr_disestablish(psc->psc_pc, psc->psc_ih);
212 	psc->psc_ih = NULL;
213 unmap:
214 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
215 	sc->sc_ios = 0;
216 }
217 
218 int
219 qla_pci_detach(struct device *self, int flags)
220 {
221 	struct qla_pci_softc *psc = (struct qla_pci_softc *)self;
222 	struct qla_softc *sc = &psc->psc_qla;
223 	int rv;
224 
225 	if (psc->psc_ih == NULL) {
226 		/* we didnt attach properly, so nothing to detach */
227 		return (0);
228 	}
229 
230 	rv = qla_detach(sc, flags);
231 	if (rv != 0)
232 		return (rv);
233 
234 	pci_intr_disestablish(psc->psc_pc, psc->psc_ih);
235 	psc->psc_ih = NULL;
236 
237 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
238 	sc->sc_ios = 0;
239 
240 	return (0);
241 }
242