Line data Source code
1 : /* $OpenBSD: qla.c,v 1.56 2017/06/05 04:57:37 dlg 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 <sys/param.h>
21 : #include <sys/systm.h>
22 : #include <sys/atomic.h>
23 : #include <sys/device.h>
24 : #include <sys/ioctl.h>
25 : #include <sys/malloc.h>
26 : #include <sys/kernel.h>
27 : #include <sys/mutex.h>
28 : #include <sys/rwlock.h>
29 : #include <sys/sensors.h>
30 : #include <sys/queue.h>
31 :
32 : #include <machine/bus.h>
33 :
34 : #include <scsi/scsi_all.h>
35 : #include <scsi/scsiconf.h>
36 :
37 : #include <dev/ic/qlareg.h>
38 : #include <dev/ic/qlavar.h>
39 :
40 : #ifdef QLA_DEBUG
41 : #define DPRINTF(m, f...) do { if ((qladebug & (m)) == (m)) printf(f); } \
42 : while (0)
43 : #define QLA_D_MBOX 0x01
44 : #define QLA_D_INTR 0x02
45 : #define QLA_D_PORT 0x04
46 : #define QLA_D_IO 0x08
47 : #define QLA_D_IOCB 0x10
48 : int qladebug = QLA_D_PORT;
49 : #else
50 : #define DPRINTF(m, f...)
51 : #endif
52 :
53 :
54 : #ifndef ISP_NOFIRMWARE
55 : #include <dev/microcode/isp/asm_2100.h>
56 : #include <dev/microcode/isp/asm_2200.h>
57 : #include <dev/microcode/isp/asm_2300.h>
58 : #endif
59 :
60 : struct cfdriver qla_cd = {
61 : NULL,
62 : "qla",
63 : DV_DULL
64 : };
65 :
66 : void qla_scsi_cmd(struct scsi_xfer *);
67 : int qla_scsi_probe(struct scsi_link *);
68 :
69 : u_int16_t qla_read(struct qla_softc *, bus_size_t);
70 : void qla_write(struct qla_softc *, bus_size_t, u_int16_t);
71 : void qla_host_cmd(struct qla_softc *sc, u_int16_t);
72 :
73 : u_int16_t qla_read_queue_2100(struct qla_softc *, bus_size_t);
74 :
75 : int qla_mbox(struct qla_softc *, int);
76 : int qla_sns_req(struct qla_softc *, struct qla_dmamem *, int);
77 : void qla_mbox_putaddr(u_int16_t *, struct qla_dmamem *);
78 : u_int16_t qla_read_mbox(struct qla_softc *, int);
79 : void qla_write_mbox(struct qla_softc *, int, u_int16_t);
80 :
81 : void qla_handle_intr(struct qla_softc *, u_int16_t, u_int16_t);
82 : void qla_set_ints(struct qla_softc *, int);
83 : int qla_read_isr_1G(struct qla_softc *, u_int16_t *, u_int16_t *);
84 : int qla_read_isr_2G(struct qla_softc *, u_int16_t *, u_int16_t *);
85 : void qla_clear_isr(struct qla_softc *, u_int16_t);
86 :
87 : void qla_update_start(struct qla_softc *, int);
88 : void qla_update_done(struct qla_softc *, int);
89 : void qla_do_update(void *);
90 :
91 : void qla_put_marker(struct qla_softc *, void *);
92 : void qla_put_cmd(struct qla_softc *, void *, struct scsi_xfer *,
93 : struct qla_ccb *);
94 : struct qla_ccb *qla_handle_resp(struct qla_softc *, u_int16_t);
95 :
96 : int qla_get_port_name_list(struct qla_softc *, u_int32_t);
97 : struct qla_fc_port *qla_next_fabric_port(struct qla_softc *, u_int32_t *,
98 : u_int32_t *);
99 : int qla_get_port_db(struct qla_softc *c, u_int16_t,
100 : struct qla_dmamem *);
101 : int qla_add_loop_port(struct qla_softc *, struct qla_fc_port *);
102 : int qla_add_fabric_port(struct qla_softc *, struct qla_fc_port *);
103 : int qla_add_logged_in_port(struct qla_softc *, int, u_int32_t);
104 : int qla_classify_port(struct qla_softc *, u_int32_t, u_int64_t,
105 : u_int64_t, struct qla_fc_port **);
106 : int qla_get_loop_id(struct qla_softc *sc, int);
107 : void qla_clear_port_lists(struct qla_softc *);
108 : int qla_softreset(struct qla_softc *);
109 : void qla_update_topology(struct qla_softc *);
110 : int qla_update_fabric(struct qla_softc *);
111 : int qla_fabric_plogi(struct qla_softc *, struct qla_fc_port *);
112 : void qla_fabric_plogo(struct qla_softc *, struct qla_fc_port *);
113 :
114 : void qla_update_start(struct qla_softc *, int);
115 : int qla_async(struct qla_softc *, u_int16_t);
116 :
117 : int qla_verify_firmware(struct qla_softc *sc, u_int16_t);
118 : int qla_load_firmware_words(struct qla_softc *, const u_int16_t *,
119 : u_int16_t);
120 : int qla_load_firmware_2100(struct qla_softc *);
121 : int qla_load_firmware_2200(struct qla_softc *);
122 : int qla_load_fwchunk_2300(struct qla_softc *,
123 : struct qla_dmamem *, const u_int16_t *, u_int32_t);
124 : int qla_load_firmware_2300(struct qla_softc *);
125 : int qla_load_firmware_2322(struct qla_softc *);
126 : int qla_read_nvram(struct qla_softc *);
127 :
128 : struct qla_dmamem *qla_dmamem_alloc(struct qla_softc *, size_t);
129 : void qla_dmamem_free(struct qla_softc *, struct qla_dmamem *);
130 :
131 : int qla_alloc_ccbs(struct qla_softc *);
132 : void qla_free_ccbs(struct qla_softc *);
133 : void *qla_get_ccb(void *);
134 : void qla_put_ccb(void *, void *);
135 :
136 : void qla_dump_iocb(struct qla_softc *, void *);
137 : void qla_dump_iocb_segs(struct qla_softc *, void *, int);
138 :
139 : static const struct qla_regs qla_regs_2100 = {
140 : qla_read_queue_2100,
141 : qla_read_isr_1G,
142 : QLA_MBOX_BASE_2100 + 0x8,
143 : QLA_MBOX_BASE_2100 + 0x8,
144 : QLA_MBOX_BASE_2100 + 0xa,
145 : QLA_MBOX_BASE_2100 + 0xa
146 : };
147 :
148 : static const struct qla_regs qla_regs_2200 = {
149 : qla_read,
150 : qla_read_isr_1G,
151 : QLA_MBOX_BASE_2200 + 0x8,
152 : QLA_MBOX_BASE_2200 + 0x8,
153 : QLA_MBOX_BASE_2200 + 0xa,
154 : QLA_MBOX_BASE_2200 + 0xa
155 : };
156 :
157 : static const struct qla_regs qla_regs_23XX = {
158 : qla_read,
159 : qla_read_isr_2G,
160 : QLA_REQ_IN,
161 : QLA_REQ_OUT,
162 : QLA_RESP_IN,
163 : QLA_RESP_OUT
164 : };
165 :
166 : #define qla_queue_read(_sc, _r) ((*(_sc)->sc_regs->read)((_sc), (_r)))
167 : #define qla_queue_write(_sc, _r, _v) qla_write((_sc), (_r), (_v))
168 :
169 : #define qla_read_isr(_sc, _isr, _info) \
170 : ((*(_sc)->sc_regs->read_isr)((_sc), (_isr), (_info)))
171 :
172 : struct scsi_adapter qla_switch = {
173 : qla_scsi_cmd,
174 : scsi_minphys,
175 : qla_scsi_probe,
176 : NULL, /* scsi_free */
177 : NULL /* ioctl */
178 : };
179 :
180 : int
181 0 : qla_classify_port(struct qla_softc *sc, u_int32_t location,
182 : u_int64_t port_name, u_int64_t node_name, struct qla_fc_port **prev)
183 : {
184 : struct qla_fc_port *port, *locmatch, *wwnmatch;
185 : locmatch = NULL;
186 : wwnmatch = NULL;
187 :
188 : /* make sure we don't try to add a port or location twice */
189 0 : TAILQ_FOREACH(port, &sc->sc_ports_new, update) {
190 0 : if ((port->port_name == port_name &&
191 0 : port->node_name == node_name) ||
192 0 : port->location == location) {
193 0 : *prev = port;
194 0 : return (QLA_PORT_DISP_DUP);
195 : }
196 : }
197 :
198 : /* if we're attaching, everything is new */
199 0 : if (sc->sc_scsibus == NULL) {
200 0 : *prev = NULL;
201 0 : return (QLA_PORT_DISP_NEW);
202 : }
203 :
204 0 : TAILQ_FOREACH(port, &sc->sc_ports, ports) {
205 0 : if (port->location == location)
206 0 : locmatch = port;
207 :
208 0 : if (port->port_name == port_name &&
209 0 : port->node_name == node_name)
210 0 : wwnmatch = port;
211 : }
212 :
213 0 : if (locmatch == NULL && wwnmatch == NULL) {
214 0 : *prev = NULL;
215 0 : return (QLA_PORT_DISP_NEW);
216 0 : } else if (locmatch == wwnmatch) {
217 0 : *prev = locmatch;
218 0 : return (QLA_PORT_DISP_SAME);
219 0 : } else if (wwnmatch != NULL) {
220 0 : *prev = wwnmatch;
221 0 : return (QLA_PORT_DISP_MOVED);
222 : } else {
223 0 : *prev = locmatch;
224 0 : return (QLA_PORT_DISP_CHANGED);
225 : }
226 0 : }
227 :
228 : int
229 0 : qla_get_loop_id(struct qla_softc *sc, int start)
230 : {
231 : int i, last;
232 :
233 0 : if (sc->sc_2k_logins) {
234 : i = QLA_2KL_MIN_HANDLE;
235 : last = QLA_2KL_MAX_HANDLE;
236 0 : } else {
237 : /* if we're an F port, we can have two ranges, but meh */
238 : i = QLA_MIN_HANDLE;
239 : last = QLA_MAX_HANDLE;
240 : }
241 0 : if (i < start)
242 0 : i = start;
243 :
244 0 : for (; i <= last; i++) {
245 0 : if (sc->sc_targets[i] == NULL)
246 0 : return (i);
247 : }
248 :
249 0 : return (-1);
250 0 : }
251 :
252 : int
253 0 : qla_get_port_db(struct qla_softc *sc, u_int16_t loopid, struct qla_dmamem *mem)
254 : {
255 0 : sc->sc_mbox[0] = QLA_MBOX_GET_PORT_DB;
256 0 : if (sc->sc_2k_logins) {
257 0 : sc->sc_mbox[1] = loopid;
258 0 : } else {
259 0 : sc->sc_mbox[1] = loopid << 8;
260 : }
261 :
262 0 : memset(QLA_DMA_KVA(mem), 0, sizeof(struct qla_get_port_db));
263 0 : qla_mbox_putaddr(sc->sc_mbox, mem);
264 0 : bus_dmamap_sync(sc->sc_dmat, QLA_DMA_MAP(mem), 0,
265 : sizeof(struct qla_get_port_db), BUS_DMASYNC_PREREAD);
266 0 : if (qla_mbox(sc, 0x00cf)) {
267 : DPRINTF(QLA_D_PORT, "%s: get port db %d failed: %x\n",
268 : DEVNAME(sc), loopid, sc->sc_mbox[0]);
269 0 : return (1);
270 : }
271 :
272 0 : bus_dmamap_sync(sc->sc_dmat, QLA_DMA_MAP(mem), 0,
273 : sizeof(struct qla_get_port_db), BUS_DMASYNC_POSTREAD);
274 0 : return (0);
275 0 : }
276 :
277 : int
278 0 : qla_add_loop_port(struct qla_softc *sc, struct qla_fc_port *port)
279 : {
280 : struct qla_get_port_db *pdb;
281 0 : struct qla_fc_port *pport = NULL;
282 : int disp;
283 :
284 0 : if (qla_get_port_db(sc, port->loopid, sc->sc_scratch)) {
285 0 : return (1);
286 : }
287 0 : pdb = QLA_DMA_KVA(sc->sc_scratch);
288 :
289 0 : if (letoh16(pdb->prli_svc_word3) & QLA_SVC3_TARGET_ROLE)
290 0 : port->flags |= QLA_PORT_FLAG_IS_TARGET;
291 :
292 0 : port->port_name = betoh64(pdb->port_name);
293 0 : port->node_name = betoh64(pdb->node_name);
294 0 : port->portid = (letoh16(pdb->port_id[0]) << 16) |
295 0 : letoh16(pdb->port_id[1]);
296 :
297 0 : mtx_enter(&sc->sc_port_mtx);
298 0 : disp = qla_classify_port(sc, port->location, port->port_name,
299 0 : port->node_name, &pport);
300 0 : switch (disp) {
301 : case QLA_PORT_DISP_CHANGED:
302 : case QLA_PORT_DISP_MOVED:
303 : case QLA_PORT_DISP_NEW:
304 0 : TAILQ_INSERT_TAIL(&sc->sc_ports_new, port, update);
305 0 : sc->sc_targets[port->loopid] = port;
306 0 : break;
307 : case QLA_PORT_DISP_DUP:
308 0 : free(port, M_DEVBUF, sizeof *port);
309 0 : break;
310 : case QLA_PORT_DISP_SAME:
311 0 : TAILQ_REMOVE(&sc->sc_ports_gone, pport, update);
312 0 : free(port, M_DEVBUF, sizeof *port);
313 0 : break;
314 : }
315 0 : mtx_leave(&sc->sc_port_mtx);
316 :
317 : switch (disp) {
318 : case QLA_PORT_DISP_CHANGED:
319 : case QLA_PORT_DISP_MOVED:
320 : case QLA_PORT_DISP_NEW:
321 : DPRINTF(QLA_D_PORT, "%s: %s %d; name %llx, port %06x\n",
322 : DEVNAME(sc), ISSET(port->flags, QLA_PORT_FLAG_IS_TARGET) ?
323 : "target" : "non-target", port->loopid, port->port_name,
324 : port->portid);
325 : break;
326 : }
327 0 : return (0);
328 0 : }
329 :
330 : int
331 0 : qla_add_fabric_port(struct qla_softc *sc, struct qla_fc_port *port)
332 : {
333 : struct qla_get_port_db *pdb;
334 :
335 0 : if (qla_get_port_db(sc, port->loopid, sc->sc_scratch)) {
336 0 : return (1);
337 : }
338 0 : pdb = QLA_DMA_KVA(sc->sc_scratch);
339 :
340 0 : if (letoh16(pdb->prli_svc_word3) & QLA_SVC3_TARGET_ROLE)
341 0 : port->flags |= QLA_PORT_FLAG_IS_TARGET;
342 :
343 : /*
344 : * if we only know about this port because qla_get_port_name_list
345 : * returned it, we don't have its port id or node name, so fill
346 : * those in and update its location.
347 : */
348 0 : if (port->location == QLA_LOCATION_FABRIC) {
349 0 : port->node_name = betoh64(pdb->node_name);
350 0 : port->port_name = betoh64(pdb->port_name);
351 0 : port->portid = (letoh16(pdb->port_id[0]) << 16) |
352 0 : letoh16(pdb->port_id[1]);
353 0 : port->location = QLA_LOCATION_PORT_ID(port->portid);
354 0 : }
355 :
356 0 : mtx_enter(&sc->sc_port_mtx);
357 0 : TAILQ_INSERT_TAIL(&sc->sc_ports_new, port, update);
358 0 : sc->sc_targets[port->loopid] = port;
359 0 : mtx_leave(&sc->sc_port_mtx);
360 :
361 : DPRINTF(QLA_D_PORT, "%s: %s %d; name %llx\n",
362 : DEVNAME(sc), ISSET(port->flags, QLA_PORT_FLAG_IS_TARGET) ?
363 : "target" : "non-target", port->loopid, port->port_name);
364 0 : return (0);
365 0 : }
366 :
367 : int
368 0 : qla_add_logged_in_port(struct qla_softc *sc, int loopid, u_int32_t portid)
369 : {
370 : struct qla_fc_port *port;
371 : struct qla_get_port_db *pdb;
372 : u_int64_t node_name, port_name;
373 : int flags, ret;
374 :
375 0 : ret = qla_get_port_db(sc, loopid, sc->sc_scratch);
376 0 : mtx_enter(&sc->sc_port_mtx);
377 0 : if (ret != 0) {
378 : /* put in a fake port to prevent use of this loop id */
379 0 : printf("%s: loop id %d used, but can't see what's using it\n",
380 0 : DEVNAME(sc), loopid);
381 : node_name = 0;
382 : port_name = 0;
383 : flags = 0;
384 0 : } else {
385 0 : pdb = QLA_DMA_KVA(sc->sc_scratch);
386 0 : node_name = betoh64(pdb->node_name);
387 0 : port_name = betoh64(pdb->port_name);
388 : flags = 0;
389 0 : if (letoh16(pdb->prli_svc_word3) & QLA_SVC3_TARGET_ROLE)
390 0 : flags |= QLA_PORT_FLAG_IS_TARGET;
391 :
392 : /* see if we've already found this port */
393 0 : TAILQ_FOREACH(port, &sc->sc_ports_found, update) {
394 0 : if ((port->node_name == node_name) &&
395 0 : (port->port_name == port_name) &&
396 0 : (port->portid == portid)) {
397 0 : mtx_leave(&sc->sc_port_mtx);
398 : DPRINTF(QLA_D_PORT, "%s: already found port "
399 : "%06x\n", DEVNAME(sc), portid);
400 0 : return (0);
401 : }
402 : }
403 : }
404 :
405 0 : port = malloc(sizeof(*port), M_DEVBUF, M_ZERO | M_NOWAIT);
406 0 : if (port == NULL) {
407 0 : mtx_leave(&sc->sc_port_mtx);
408 0 : printf("%s: failed to allocate a port structure\n",
409 0 : DEVNAME(sc));
410 0 : return (1);
411 : }
412 0 : port->location = QLA_LOCATION_PORT_ID(portid);
413 0 : port->port_name = port_name;
414 0 : port->node_name = node_name;
415 0 : port->loopid = loopid;
416 0 : port->portid = portid;
417 0 : port->flags = flags;
418 :
419 0 : TAILQ_INSERT_TAIL(&sc->sc_ports, port, ports);
420 0 : sc->sc_targets[port->loopid] = port;
421 0 : mtx_leave(&sc->sc_port_mtx);
422 :
423 : DPRINTF(QLA_D_PORT, "%s: added logged in port %06x at %d\n",
424 : DEVNAME(sc), portid, loopid);
425 0 : return (0);
426 0 : }
427 :
428 : int
429 0 : qla_attach(struct qla_softc *sc)
430 : {
431 0 : struct scsibus_attach_args saa;
432 : struct qla_init_cb *icb;
433 : #ifndef ISP_NOFIRMWARE
434 : int (*loadfirmware)(struct qla_softc *) = NULL;
435 : #endif
436 : u_int16_t firmware_addr = 0;
437 : u_int64_t dva;
438 : int i, rv;
439 :
440 0 : TAILQ_INIT(&sc->sc_ports);
441 0 : TAILQ_INIT(&sc->sc_ports_new);
442 0 : TAILQ_INIT(&sc->sc_ports_gone);
443 0 : TAILQ_INIT(&sc->sc_ports_found);
444 :
445 0 : switch (sc->sc_isp_gen) {
446 : case QLA_GEN_ISP2100:
447 0 : sc->sc_mbox_base = QLA_MBOX_BASE_2100;
448 0 : sc->sc_regs = &qla_regs_2100;
449 : #ifndef ISP_NOFIRMWARE
450 : loadfirmware = qla_load_firmware_2100;
451 : #endif
452 : firmware_addr = QLA_2100_CODE_ORG;
453 0 : break;
454 :
455 : case QLA_GEN_ISP2200:
456 0 : sc->sc_mbox_base = QLA_MBOX_BASE_2200;
457 0 : sc->sc_regs = &qla_regs_2200;
458 : #ifndef ISP_NOFIRMWARE
459 : loadfirmware = qla_load_firmware_2200;
460 : #endif
461 : firmware_addr = QLA_2200_CODE_ORG;
462 0 : break;
463 :
464 : case QLA_GEN_ISP23XX:
465 0 : sc->sc_mbox_base = QLA_MBOX_BASE_23XX;
466 0 : sc->sc_regs = &qla_regs_23XX;
467 : #ifndef ISP_NOFIRMWARE
468 0 : if (sc->sc_isp_type != QLA_ISP2322)
469 0 : loadfirmware = qla_load_firmware_2300;
470 : #endif
471 : firmware_addr = QLA_2300_CODE_ORG;
472 0 : break;
473 :
474 : default:
475 0 : printf("unknown isp type\n");
476 0 : return (ENXIO);
477 : }
478 :
479 : /* after reset, mbox registers 1-3 should contain the string "ISP " */
480 0 : if (qla_read_mbox(sc, 1) != 0x4953 ||
481 0 : qla_read_mbox(sc, 2) != 0x5020 ||
482 0 : qla_read_mbox(sc, 3) != 0x2020) {
483 : /* try releasing the risc processor */
484 0 : qla_host_cmd(sc, QLA_HOST_CMD_RELEASE);
485 0 : }
486 :
487 0 : qla_host_cmd(sc, QLA_HOST_CMD_PAUSE);
488 0 : if (qla_softreset(sc) != 0) {
489 0 : printf("softreset failed\n");
490 0 : return (ENXIO);
491 : }
492 :
493 0 : if (qla_read_nvram(sc) == 0) {
494 0 : sc->sc_nvram_valid = 1;
495 0 : if (sc->sc_port_name == 0)
496 0 : sc->sc_port_name = betoh64(sc->sc_nvram.port_name);
497 0 : if (sc->sc_node_name == 0)
498 0 : sc->sc_node_name = betoh64(sc->sc_nvram.node_name);
499 : }
500 :
501 0 : if (sc->sc_port_name == 0)
502 0 : sc->sc_port_name = QLA_DEFAULT_PORT_NAME;
503 :
504 : #ifdef ISP_NOFIRMWARE
505 : if (qla_verify_firmware(sc, firmware_addr)) {
506 : printf("%s: no firmware loaded\n", DEVNAME(sc));
507 : return (ENXIO);
508 : }
509 : #else
510 0 : if (loadfirmware && (loadfirmware)(sc)) {
511 0 : printf("%s: firmware load failed\n", DEVNAME(sc));
512 0 : return (ENXIO);
513 : }
514 : #endif
515 :
516 : /* execute firmware */
517 0 : sc->sc_mbox[0] = QLA_MBOX_EXEC_FIRMWARE;
518 0 : sc->sc_mbox[1] = firmware_addr;
519 : #ifdef ISP_NOFIRMWARE
520 : sc->sc_mbox[2] = 1;
521 : #else
522 0 : if (loadfirmware)
523 0 : sc->sc_mbox[2] = 0;
524 : else
525 0 : sc->sc_mbox[2] = 1;
526 : #endif
527 0 : if (qla_mbox(sc, 0x0007)) {
528 0 : printf("ISP couldn't exec firmware: %x\n", sc->sc_mbox[0]);
529 0 : return (ENXIO);
530 : }
531 :
532 0 : delay(250000); /* from isp(4) */
533 :
534 0 : sc->sc_mbox[0] = QLA_MBOX_ABOUT_FIRMWARE;
535 0 : if (qla_mbox(sc, 0x0001)) {
536 0 : printf("ISP not talking after firmware exec: %x\n",
537 0 : sc->sc_mbox[0]);
538 0 : return (ENXIO);
539 : }
540 0 : printf("%s: firmware rev %d.%d.%d, attrs 0x%x\n", DEVNAME(sc),
541 0 : sc->sc_mbox[1], sc->sc_mbox[2], sc->sc_mbox[3], sc->sc_mbox[6]);
542 :
543 0 : if (sc->sc_mbox[6] & QLA_FW_ATTR_EXPANDED_LUN)
544 0 : sc->sc_expanded_lun = 1;
545 0 : if (sc->sc_mbox[6] & QLA_FW_ATTR_FABRIC)
546 0 : sc->sc_fabric = 1;
547 0 : if (sc->sc_mbox[6] & QLA_FW_ATTR_2K_LOGINS)
548 0 : sc->sc_2k_logins = 1;
549 :
550 : /* work out how many ccbs to allocate */
551 0 : sc->sc_mbox[0] = QLA_MBOX_GET_FIRMWARE_STATUS;
552 0 : if (qla_mbox(sc, 0x0001)) {
553 0 : printf("couldn't get firmware status: %x\n", sc->sc_mbox[0]);
554 0 : return (ENXIO);
555 : }
556 0 : sc->sc_maxcmds = sc->sc_mbox[2];
557 :
558 0 : if (qla_alloc_ccbs(sc)) {
559 : /* error already printed */
560 0 : return (ENOMEM);
561 : }
562 0 : sc->sc_scratch = qla_dmamem_alloc(sc, QLA_SCRATCH_SIZE);
563 0 : if (sc->sc_scratch == NULL) {
564 0 : printf("%s: unable to allocate scratch\n", DEVNAME(sc));
565 0 : goto free_ccbs;
566 : }
567 :
568 : /* build init buffer thing */
569 0 : icb = (struct qla_init_cb *)QLA_DMA_KVA(sc->sc_scratch);
570 0 : memset(icb, 0, sizeof(*icb));
571 0 : icb->icb_version = QLA_ICB_VERSION;
572 : /* port and node names are big-endian in the icb */
573 0 : htobem32(&icb->icb_portname_hi, sc->sc_port_name >> 32);
574 0 : htobem32(&icb->icb_portname_lo, sc->sc_port_name);
575 0 : htobem32(&icb->icb_nodename_hi, sc->sc_node_name >> 32);
576 0 : htobem32(&icb->icb_nodename_lo, sc->sc_node_name);
577 0 : if (sc->sc_nvram_valid) {
578 0 : icb->icb_fw_options = sc->sc_nvram.fw_options;
579 0 : icb->icb_max_frame_len = sc->sc_nvram.frame_payload_size;
580 0 : icb->icb_max_alloc = sc->sc_nvram.max_iocb_allocation;
581 0 : icb->icb_exec_throttle = sc->sc_nvram.execution_throttle;
582 0 : icb->icb_retry_count = sc->sc_nvram.retry_count;
583 0 : icb->icb_retry_delay = sc->sc_nvram.retry_delay;
584 0 : icb->icb_hardaddr = sc->sc_nvram.hard_address;
585 0 : icb->icb_inquiry_data = sc->sc_nvram.inquiry_data;
586 0 : icb->icb_login_timeout = sc->sc_nvram.login_timeout;
587 0 : icb->icb_xfwoptions = sc->sc_nvram.add_fw_options;
588 0 : icb->icb_zfwoptions = sc->sc_nvram.special_options;
589 0 : } else {
590 : /* defaults copied from isp(4) */
591 0 : icb->icb_retry_count = 3;
592 0 : icb->icb_retry_delay = 5;
593 0 : icb->icb_exec_throttle = htole16(16);
594 0 : icb->icb_max_alloc = htole16(256);
595 0 : icb->icb_max_frame_len = htole16(1024);
596 0 : icb->icb_fw_options = htole16(QLA_ICB_FW_FAIRNESS |
597 : QLA_ICB_FW_ENABLE_PDB_CHANGED | QLA_ICB_FW_HARD_ADDR |
598 : QLA_ICB_FW_FULL_DUPLEX);
599 : }
600 : /* target mode stuff that we don't care about */
601 0 : icb->icb_lun_enables = 0;
602 0 : icb->icb_cmd_count = 0;
603 0 : icb->icb_notify_count = 0;
604 0 : icb->icb_lun_timeout = 0;
605 :
606 : /* "zero interrupt operation" */
607 0 : icb->icb_int_delaytimer = 0;
608 :
609 0 : icb->icb_req_out = 0;
610 0 : icb->icb_resp_in = 0;
611 0 : htolem16(&icb->icb_req_queue_len, sc->sc_maxcmds);
612 0 : htolem16(&icb->icb_resp_queue_len, sc->sc_maxcmds);
613 0 : dva = QLA_DMA_DVA(sc->sc_requests);
614 0 : htolem32(&icb->icb_req_queue_addr_lo, dva);
615 0 : htolem32(&icb->icb_req_queue_addr_hi, dva >> 32);
616 0 : dva = QLA_DMA_DVA(sc->sc_responses);
617 0 : htolem32(&icb->icb_resp_queue_addr_lo, dva);
618 0 : htolem32(&icb->icb_resp_queue_addr_hi, dva >> 32);
619 :
620 : /* adjust firmware options a bit */
621 0 : icb->icb_fw_options |= htole16(QLA_ICB_FW_EXTENDED_INIT_CB);
622 0 : icb->icb_fw_options &= ~htole16(QLA_ICB_FW_FAST_POST);
623 :
624 0 : sc->sc_mbox[0] = QLA_MBOX_INIT_FIRMWARE;
625 0 : sc->sc_mbox[4] = 0;
626 0 : sc->sc_mbox[5] = 0;
627 0 : qla_mbox_putaddr(sc->sc_mbox, sc->sc_scratch);
628 0 : bus_dmamap_sync(sc->sc_dmat, QLA_DMA_MAP(sc->sc_scratch), 0,
629 : sizeof(*icb), BUS_DMASYNC_PREWRITE);
630 0 : rv = qla_mbox(sc, 0x00fd);
631 0 : bus_dmamap_sync(sc->sc_dmat, QLA_DMA_MAP(sc->sc_scratch), 0,
632 : sizeof(*icb), BUS_DMASYNC_POSTWRITE);
633 :
634 0 : if (rv != 0) {
635 0 : printf("%s: ISP firmware init failed: %x\n", DEVNAME(sc),
636 0 : sc->sc_mbox[0]);
637 0 : goto free_scratch;
638 : }
639 :
640 : /* enable some more notifications */
641 0 : sc->sc_mbox[0] = QLA_MBOX_SET_FIRMWARE_OPTIONS;
642 0 : sc->sc_mbox[1] = QLA_FW_OPTION1_ASYNC_LIP_F8 |
643 : QLA_FW_OPTION1_ASYNC_LIP_RESET |
644 : QLA_FW_OPTION1_ASYNC_LIP_ERROR |
645 : QLA_FW_OPTION1_ASYNC_LOGIN_RJT;
646 0 : sc->sc_mbox[2] = 0;
647 0 : sc->sc_mbox[3] = 0;
648 0 : if (qla_mbox(sc, 0x000f)) {
649 0 : printf("%s: setting firmware options failed: %x\n",
650 0 : DEVNAME(sc), sc->sc_mbox[0]);
651 0 : goto free_scratch;
652 : }
653 :
654 0 : sc->sc_update_taskq = taskq_create(DEVNAME(sc), 1, IPL_BIO, 0);
655 0 : task_set(&sc->sc_update_task, qla_do_update, sc);
656 :
657 : /* wait a bit for link to come up so we can scan and attach devices */
658 0 : for (i = 0; i < QLA_WAIT_FOR_LOOP * 10000; i++) {
659 0 : u_int16_t isr, info;
660 :
661 0 : delay(100);
662 :
663 0 : if (qla_read_isr(sc, &isr, &info) == 0)
664 0 : continue;
665 :
666 0 : qla_handle_intr(sc, isr, info);
667 :
668 0 : if (sc->sc_loop_up)
669 0 : break;
670 0 : }
671 :
672 0 : if (sc->sc_loop_up) {
673 0 : qla_do_update(sc);
674 0 : } else {
675 : DPRINTF(QLA_D_PORT, "%s: loop still down, giving up\n",
676 : DEVNAME(sc));
677 : }
678 :
679 : /* we should be good to go now, attach scsibus */
680 0 : sc->sc_link.adapter = &qla_switch;
681 0 : sc->sc_link.adapter_softc = sc;
682 0 : if (sc->sc_2k_logins) {
683 0 : sc->sc_link.adapter_buswidth = QLA_2KL_BUSWIDTH;
684 0 : } else {
685 0 : sc->sc_link.adapter_buswidth = QLA_BUSWIDTH;
686 : }
687 0 : sc->sc_link.adapter_target = sc->sc_link.adapter_buswidth;
688 0 : sc->sc_link.openings = sc->sc_maxcmds;
689 0 : sc->sc_link.pool = &sc->sc_iopool;
690 0 : sc->sc_link.port_wwn = sc->sc_port_name;
691 0 : sc->sc_link.node_wwn = sc->sc_node_name;
692 0 : if (sc->sc_link.node_wwn == 0) {
693 : /*
694 : * mask out the port number from the port name to get
695 : * the node name.
696 : */
697 0 : sc->sc_link.node_wwn = sc->sc_link.port_wwn;
698 0 : sc->sc_link.node_wwn &= ~(0xfULL << 56);
699 0 : }
700 :
701 0 : memset(&saa, 0, sizeof(saa));
702 0 : saa.saa_sc_link = &sc->sc_link;
703 :
704 : /* config_found() returns the scsibus attached to us */
705 0 : sc->sc_scsibus = (struct scsibus_softc *)config_found(&sc->sc_dev,
706 : &saa, scsiprint);
707 :
708 0 : return(0);
709 :
710 : free_scratch:
711 0 : qla_dmamem_free(sc, sc->sc_scratch);
712 : free_ccbs:
713 0 : qla_free_ccbs(sc);
714 0 : return (ENXIO);
715 0 : }
716 :
717 : int
718 0 : qla_detach(struct qla_softc *sc, int flags)
719 : {
720 0 : return (0);
721 : }
722 :
723 : struct qla_ccb *
724 0 : qla_handle_resp(struct qla_softc *sc, u_int16_t id)
725 : {
726 : struct qla_ccb *ccb;
727 : struct qla_iocb_status *status;
728 : struct scsi_xfer *xs;
729 : u_int32_t handle;
730 : u_int8_t *entry;
731 :
732 : ccb = NULL;
733 0 : entry = QLA_DMA_KVA(sc->sc_responses) + (id * QLA_QUEUE_ENTRY_SIZE);
734 :
735 0 : bus_dmamap_sync(sc->sc_dmat,
736 : QLA_DMA_MAP(sc->sc_responses), id * QLA_QUEUE_ENTRY_SIZE,
737 : QLA_QUEUE_ENTRY_SIZE, BUS_DMASYNC_POSTREAD);
738 :
739 0 : qla_dump_iocb(sc, entry);
740 0 : switch (entry[0]) {
741 : case QLA_IOCB_STATUS:
742 0 : status = (struct qla_iocb_status *)entry;
743 0 : handle = status->handle;
744 0 : if (handle > sc->sc_maxcmds) {
745 0 : panic("bad completed command handle: %d (> %d)",
746 : handle, sc->sc_maxcmds);
747 : }
748 :
749 0 : ccb = &sc->sc_ccbs[handle];
750 0 : xs = ccb->ccb_xs;
751 0 : if (xs == NULL) {
752 : DPRINTF(QLA_D_INTR, "%s: got status for inactive"
753 : " ccb %d\n", DEVNAME(sc), handle);
754 : ccb = NULL;
755 0 : break;
756 : }
757 0 : if (xs->io != ccb) {
758 0 : panic("completed command handle doesn't match xs "
759 : "(handle %d, ccb %p, xs->io %p)", handle, ccb,
760 : xs->io);
761 : }
762 :
763 0 : if (xs->datalen > 0) {
764 0 : if (ccb->ccb_dmamap->dm_nsegs >
765 : QLA_IOCB_SEGS_PER_CMD) {
766 0 : bus_dmamap_sync(sc->sc_dmat,
767 : QLA_DMA_MAP(sc->sc_segments),
768 : ccb->ccb_seg_offset,
769 : sizeof(*ccb->ccb_t4segs) *
770 : ccb->ccb_dmamap->dm_nsegs,
771 : BUS_DMASYNC_POSTWRITE);
772 0 : }
773 :
774 0 : bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
775 : ccb->ccb_dmamap->dm_mapsize,
776 : (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
777 : BUS_DMASYNC_POSTWRITE);
778 0 : bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
779 0 : }
780 :
781 0 : xs->status = letoh16(status->scsi_status);
782 0 : switch (letoh16(status->completion)) {
783 : case QLA_IOCB_STATUS_COMPLETE:
784 0 : if (letoh16(status->scsi_status) &
785 : QLA_SCSI_STATUS_SENSE_VALID) {
786 0 : memcpy(&xs->sense, status->sense_data,
787 : sizeof(xs->sense));
788 0 : xs->error = XS_SENSE;
789 0 : } else {
790 0 : xs->error = XS_NOERROR;
791 : }
792 0 : xs->resid = 0;
793 0 : break;
794 :
795 : case QLA_IOCB_STATUS_DMA_ERROR:
796 : DPRINTF(QLA_D_INTR, "%s: dma error\n", DEVNAME(sc));
797 : /* set resid apparently? */
798 : break;
799 :
800 : case QLA_IOCB_STATUS_RESET:
801 : DPRINTF(QLA_D_IO, "%s: reset destroyed command\n",
802 : DEVNAME(sc));
803 0 : sc->sc_marker_required = 1;
804 0 : xs->error = XS_RESET;
805 0 : break;
806 :
807 : case QLA_IOCB_STATUS_ABORTED:
808 : DPRINTF(QLA_D_IO, "%s: aborted\n", DEVNAME(sc));
809 0 : sc->sc_marker_required = 1;
810 0 : xs->error = XS_DRIVER_STUFFUP;
811 0 : break;
812 :
813 : case QLA_IOCB_STATUS_TIMEOUT:
814 : DPRINTF(QLA_D_IO, "%s: command timed out\n",
815 : DEVNAME(sc));
816 0 : xs->error = XS_TIMEOUT;
817 0 : break;
818 :
819 : case QLA_IOCB_STATUS_DATA_OVERRUN:
820 : case QLA_IOCB_STATUS_DATA_UNDERRUN:
821 0 : xs->resid = letoh32(status->resid);
822 0 : xs->error = XS_NOERROR;
823 0 : break;
824 :
825 : case QLA_IOCB_STATUS_QUEUE_FULL:
826 : DPRINTF(QLA_D_IO, "%s: queue full\n", DEVNAME(sc));
827 0 : xs->error = XS_BUSY;
828 0 : break;
829 :
830 : case QLA_IOCB_STATUS_PORT_UNAVAIL:
831 : case QLA_IOCB_STATUS_PORT_LOGGED_OUT:
832 : case QLA_IOCB_STATUS_PORT_CHANGED:
833 : DPRINTF(QLA_D_IO, "%s: dev gone\n", DEVNAME(sc));
834 0 : xs->error = XS_SELTIMEOUT;
835 0 : break;
836 :
837 : default:
838 : DPRINTF(QLA_D_INTR, "%s: unexpected completion"
839 : " status %x\n", DEVNAME(sc), status->completion);
840 0 : xs->error = XS_DRIVER_STUFFUP;
841 0 : break;
842 : }
843 : break;
844 :
845 : case QLA_IOCB_STATUS_CONT:
846 : DPRINTF(QLA_D_INTR, "%s: ignoring status continuation iocb\n",
847 : DEVNAME(sc));
848 : break;
849 :
850 : /* check for requests that bounce back? */
851 : default:
852 : DPRINTF(QLA_D_INTR, "%s: unexpected response entry type %x\n",
853 : DEVNAME(sc), entry[0]);
854 : break;
855 : }
856 :
857 0 : return (ccb);
858 : }
859 :
860 : void
861 0 : qla_handle_intr(struct qla_softc *sc, u_int16_t isr, u_int16_t info)
862 : {
863 : int i;
864 : u_int16_t rspin;
865 : struct qla_ccb *ccb;
866 :
867 0 : switch (isr) {
868 : case QLA_INT_TYPE_ASYNC:
869 0 : qla_async(sc, info);
870 0 : break;
871 :
872 : case QLA_INT_TYPE_IO:
873 0 : rspin = qla_queue_read(sc, sc->sc_regs->res_in);
874 0 : if (rspin == sc->sc_last_resp_id) {
875 : /* seems to happen a lot on 2200s when mbox commands
876 : * complete but it doesn't want to give us the register
877 : * semaphore, or something.
878 : *
879 : * if we're waiting on a mailbox command, don't ack
880 : * the interrupt yet.
881 : */
882 0 : if (sc->sc_mbox_pending) {
883 : DPRINTF(QLA_D_MBOX, "%s: ignoring premature"
884 : " mbox int\n", DEVNAME(sc));
885 0 : return;
886 : }
887 :
888 : break;
889 : }
890 :
891 0 : if (sc->sc_responses == NULL)
892 : break;
893 :
894 : DPRINTF(QLA_D_IO, "%s: response queue %x=>%x\n",
895 : DEVNAME(sc), sc->sc_last_resp_id, rspin);
896 :
897 0 : do {
898 0 : ccb = qla_handle_resp(sc, sc->sc_last_resp_id);
899 0 : if (ccb)
900 0 : scsi_done(ccb->ccb_xs);
901 :
902 0 : sc->sc_last_resp_id++;
903 0 : sc->sc_last_resp_id %= sc->sc_maxcmds;
904 0 : } while (sc->sc_last_resp_id != rspin);
905 :
906 0 : qla_queue_write(sc, sc->sc_regs->res_out, rspin);
907 0 : break;
908 :
909 : case QLA_INT_TYPE_MBOX:
910 0 : mtx_enter(&sc->sc_mbox_mtx);
911 0 : if (sc->sc_mbox_pending) {
912 : DPRINTF(QLA_D_MBOX, "%s: mbox response %x\n",
913 : DEVNAME(sc), info);
914 0 : for (i = 0; i < nitems(sc->sc_mbox); i++) {
915 0 : sc->sc_mbox[i] = qla_read_mbox(sc, i);
916 : }
917 0 : sc->sc_mbox_pending = 2;
918 0 : wakeup(sc->sc_mbox);
919 0 : mtx_leave(&sc->sc_mbox_mtx);
920 0 : } else {
921 0 : mtx_leave(&sc->sc_mbox_mtx);
922 : DPRINTF(QLA_D_MBOX, "%s: unexpected mbox interrupt:"
923 : " %x\n", DEVNAME(sc), info);
924 : }
925 : break;
926 :
927 : default:
928 : /* maybe log something? */
929 : break;
930 : }
931 :
932 0 : qla_clear_isr(sc, isr);
933 0 : }
934 :
935 : int
936 0 : qla_intr(void *xsc)
937 : {
938 0 : struct qla_softc *sc = xsc;
939 0 : u_int16_t isr;
940 0 : u_int16_t info;
941 :
942 0 : if (qla_read_isr(sc, &isr, &info) == 0)
943 0 : return (0);
944 :
945 0 : qla_handle_intr(sc, isr, info);
946 0 : return (1);
947 0 : }
948 :
949 : int
950 0 : qla_scsi_probe(struct scsi_link *link)
951 : {
952 0 : struct qla_softc *sc = link->adapter_softc;
953 : int rv = 0;
954 :
955 0 : mtx_enter(&sc->sc_port_mtx);
956 0 : if (sc->sc_targets[link->target] == NULL)
957 0 : rv = ENXIO;
958 0 : else if (!ISSET(sc->sc_targets[link->target]->flags,
959 : QLA_PORT_FLAG_IS_TARGET))
960 0 : rv = ENXIO;
961 : else {
962 0 : link->port_wwn = sc->sc_targets[link->target]->port_name;
963 0 : link->node_wwn = sc->sc_targets[link->target]->node_name;
964 : }
965 0 : mtx_leave(&sc->sc_port_mtx);
966 :
967 0 : return (rv);
968 : }
969 :
970 : void
971 0 : qla_scsi_cmd(struct scsi_xfer *xs)
972 : {
973 0 : struct scsi_link *link = xs->sc_link;
974 0 : struct qla_softc *sc = link->adapter_softc;
975 : struct qla_ccb *ccb;
976 : struct qla_iocb_req34 *iocb;
977 0 : struct qla_ccb_list list;
978 : u_int16_t req, rspin;
979 : int offset, error, done;
980 : bus_dmamap_t dmap;
981 :
982 0 : if (xs->cmdlen > sizeof(iocb->req_cdb)) {
983 : DPRINTF(QLA_D_IO, "%s: cdb too big (%d)\n", DEVNAME(sc),
984 : xs->cmdlen);
985 0 : memset(&xs->sense, 0, sizeof(xs->sense));
986 0 : xs->sense.error_code = SSD_ERRCODE_VALID | SSD_ERRCODE_CURRENT;
987 0 : xs->sense.flags = SKEY_ILLEGAL_REQUEST;
988 0 : xs->sense.add_sense_code = 0x20;
989 0 : xs->error = XS_SENSE;
990 0 : scsi_done(xs);
991 0 : return;
992 : }
993 :
994 0 : ccb = xs->io;
995 0 : dmap = ccb->ccb_dmamap;
996 0 : if (xs->datalen > 0) {
997 0 : error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data,
998 : xs->datalen, NULL, (xs->flags & SCSI_NOSLEEP) ?
999 : BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
1000 0 : if (error) {
1001 0 : xs->error = XS_DRIVER_STUFFUP;
1002 0 : scsi_done(xs);
1003 0 : return;
1004 : }
1005 :
1006 0 : bus_dmamap_sync(sc->sc_dmat, dmap, 0,
1007 : dmap->dm_mapsize,
1008 : (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
1009 : BUS_DMASYNC_PREWRITE);
1010 0 : }
1011 :
1012 0 : mtx_enter(&sc->sc_queue_mtx);
1013 :
1014 : /* put in a sync marker if required */
1015 0 : if (sc->sc_marker_required) {
1016 0 : req = sc->sc_next_req_id++;
1017 0 : if (sc->sc_next_req_id == sc->sc_maxcmds)
1018 0 : sc->sc_next_req_id = 0;
1019 :
1020 : DPRINTF(QLA_D_IO, "%s: writing marker at request %d\n",
1021 : DEVNAME(sc), req);
1022 0 : offset = (req * QLA_QUEUE_ENTRY_SIZE);
1023 0 : iocb = QLA_DMA_KVA(sc->sc_requests) + offset;
1024 0 : bus_dmamap_sync(sc->sc_dmat, QLA_DMA_MAP(sc->sc_requests),
1025 : offset, QLA_QUEUE_ENTRY_SIZE, BUS_DMASYNC_POSTWRITE);
1026 0 : qla_put_marker(sc, iocb);
1027 0 : qla_queue_write(sc, sc->sc_regs->req_in, sc->sc_next_req_id);
1028 0 : sc->sc_marker_required = 0;
1029 0 : }
1030 :
1031 0 : req = sc->sc_next_req_id++;
1032 0 : if (sc->sc_next_req_id == sc->sc_maxcmds)
1033 0 : sc->sc_next_req_id = 0;
1034 :
1035 0 : offset = (req * QLA_QUEUE_ENTRY_SIZE);
1036 0 : iocb = QLA_DMA_KVA(sc->sc_requests) + offset;
1037 0 : bus_dmamap_sync(sc->sc_dmat, QLA_DMA_MAP(sc->sc_requests), offset,
1038 : QLA_QUEUE_ENTRY_SIZE, BUS_DMASYNC_POSTWRITE);
1039 :
1040 0 : ccb->ccb_xs = xs;
1041 :
1042 : DPRINTF(QLA_D_IO, "%s: writing cmd at request %d\n", DEVNAME(sc), req);
1043 0 : qla_put_cmd(sc, iocb, xs, ccb);
1044 :
1045 0 : qla_queue_write(sc, sc->sc_regs->req_in, sc->sc_next_req_id);
1046 :
1047 0 : if (!ISSET(xs->flags, SCSI_POLL)) {
1048 0 : mtx_leave(&sc->sc_queue_mtx);
1049 0 : return;
1050 : }
1051 :
1052 : done = 0;
1053 0 : SIMPLEQ_INIT(&list);
1054 0 : do {
1055 0 : u_int16_t isr, info;
1056 :
1057 0 : delay(100);
1058 :
1059 0 : if (qla_read_isr(sc, &isr, &info) == 0) {
1060 0 : continue;
1061 : }
1062 :
1063 0 : if (isr != QLA_INT_TYPE_IO) {
1064 0 : qla_handle_intr(sc, isr, info);
1065 0 : continue;
1066 : }
1067 :
1068 0 : rspin = qla_queue_read(sc, sc->sc_regs->res_in);
1069 0 : while (rspin != sc->sc_last_resp_id) {
1070 0 : ccb = qla_handle_resp(sc, sc->sc_last_resp_id);
1071 :
1072 0 : sc->sc_last_resp_id++;
1073 0 : if (sc->sc_last_resp_id == sc->sc_maxcmds)
1074 0 : sc->sc_last_resp_id = 0;
1075 :
1076 0 : if (ccb != NULL)
1077 0 : SIMPLEQ_INSERT_TAIL(&list, ccb, ccb_link);
1078 0 : if (ccb == xs->io)
1079 0 : done = 1;
1080 : }
1081 0 : qla_queue_write(sc, sc->sc_regs->res_out, rspin);
1082 0 : qla_clear_isr(sc, isr);
1083 0 : } while (done == 0);
1084 :
1085 0 : mtx_leave(&sc->sc_queue_mtx);
1086 :
1087 0 : while ((ccb = SIMPLEQ_FIRST(&list)) != NULL) {
1088 0 : SIMPLEQ_REMOVE_HEAD(&list, ccb_link);
1089 0 : scsi_done(ccb->ccb_xs);
1090 : }
1091 0 : }
1092 :
1093 : u_int16_t
1094 0 : qla_read(struct qla_softc *sc, bus_size_t offset)
1095 : {
1096 : u_int16_t v;
1097 0 : v = bus_space_read_2(sc->sc_iot, sc->sc_ioh, offset);
1098 0 : bus_space_barrier(sc->sc_iot, sc->sc_ioh, offset, 2,
1099 : BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
1100 0 : return (v);
1101 : }
1102 :
1103 : void
1104 0 : qla_write(struct qla_softc *sc, bus_size_t offset, u_int16_t value)
1105 : {
1106 0 : bus_space_write_2(sc->sc_iot, sc->sc_ioh, offset, value);
1107 0 : bus_space_barrier(sc->sc_iot, sc->sc_ioh, offset, 2,
1108 : BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
1109 0 : }
1110 :
1111 : u_int16_t
1112 0 : qla_read_mbox(struct qla_softc *sc, int mbox)
1113 : {
1114 : /* could range-check mboxes according to chip type? */
1115 0 : return (qla_read(sc, sc->sc_mbox_base + (mbox * 2)));
1116 : }
1117 :
1118 : void
1119 0 : qla_write_mbox(struct qla_softc *sc, int mbox, u_int16_t value)
1120 : {
1121 0 : qla_write(sc, sc->sc_mbox_base + (mbox * 2), value);
1122 0 : }
1123 :
1124 : void
1125 0 : qla_host_cmd(struct qla_softc *sc, u_int16_t cmd)
1126 : {
1127 0 : qla_write(sc, QLA_HOST_CMD_CTRL, cmd << QLA_HOST_CMD_SHIFT);
1128 0 : }
1129 :
1130 : #define MBOX_COMMAND_TIMEOUT 4000
1131 :
1132 : int
1133 0 : qla_mbox(struct qla_softc *sc, int maskin)
1134 : {
1135 : int i;
1136 : int result = 0;
1137 : int rv;
1138 :
1139 0 : sc->sc_mbox_pending = 1;
1140 0 : for (i = 0; i < nitems(sc->sc_mbox); i++) {
1141 0 : if (maskin & (1 << i)) {
1142 0 : qla_write_mbox(sc, i, sc->sc_mbox[i]);
1143 0 : }
1144 : }
1145 0 : qla_host_cmd(sc, QLA_HOST_CMD_SET_HOST_INT);
1146 :
1147 0 : if (sc->sc_scsibus != NULL) {
1148 0 : mtx_enter(&sc->sc_mbox_mtx);
1149 0 : sc->sc_mbox_pending = 1;
1150 0 : while (sc->sc_mbox_pending == 1) {
1151 0 : msleep(sc->sc_mbox, &sc->sc_mbox_mtx, PRIBIO,
1152 : "qlambox", 0);
1153 : }
1154 0 : result = sc->sc_mbox[0];
1155 0 : sc->sc_mbox_pending = 0;
1156 0 : mtx_leave(&sc->sc_mbox_mtx);
1157 0 : return (result == QLA_MBOX_COMPLETE ? 0 : result);
1158 : }
1159 :
1160 0 : for (i = 0; i < MBOX_COMMAND_TIMEOUT && result == 0; i++) {
1161 0 : u_int16_t isr, info;
1162 :
1163 0 : delay(100);
1164 :
1165 0 : if (qla_read_isr(sc, &isr, &info) == 0)
1166 0 : continue;
1167 :
1168 0 : switch (isr) {
1169 : case QLA_INT_TYPE_MBOX:
1170 0 : result = info;
1171 0 : break;
1172 :
1173 : default:
1174 0 : qla_handle_intr(sc, isr, info);
1175 0 : break;
1176 : }
1177 0 : }
1178 :
1179 0 : if (result == 0) {
1180 : /* timed out; do something? */
1181 : DPRINTF(QLA_D_MBOX, "%s: mbox timed out\n", DEVNAME(sc));
1182 : rv = 1;
1183 0 : } else {
1184 0 : for (i = 0; i < nitems(sc->sc_mbox); i++) {
1185 0 : sc->sc_mbox[i] = qla_read_mbox(sc, i);
1186 : }
1187 0 : rv = (result == QLA_MBOX_COMPLETE ? 0 : result);
1188 : }
1189 :
1190 0 : qla_clear_isr(sc, QLA_INT_TYPE_MBOX);
1191 0 : sc->sc_mbox_pending = 0;
1192 0 : return (rv);
1193 0 : }
1194 :
1195 : void
1196 0 : qla_mbox_putaddr(u_int16_t *mbox, struct qla_dmamem *mem)
1197 : {
1198 0 : mbox[2] = (QLA_DMA_DVA(mem) >> 16) & 0xffff;
1199 0 : mbox[3] = (QLA_DMA_DVA(mem) >> 0) & 0xffff;
1200 0 : mbox[6] = (QLA_DMA_DVA(mem) >> 48) & 0xffff;
1201 0 : mbox[7] = (QLA_DMA_DVA(mem) >> 32) & 0xffff;
1202 0 : }
1203 :
1204 : int
1205 0 : qla_sns_req(struct qla_softc *sc, struct qla_dmamem *mem, int reqsize)
1206 : {
1207 : struct qla_sns_req_hdr *header;
1208 : uint64_t dva;
1209 : int rv;
1210 :
1211 0 : memset(&sc->sc_mbox, 0, sizeof(sc->sc_mbox));
1212 0 : sc->sc_mbox[0] = QLA_MBOX_SEND_SNS;
1213 0 : sc->sc_mbox[1] = reqsize / 2;
1214 0 : qla_mbox_putaddr(sc->sc_mbox, mem);
1215 :
1216 0 : header = QLA_DMA_KVA(mem);
1217 0 : htolem16(&header->resp_len, (QLA_DMA_LEN(mem) - reqsize) / 2);
1218 0 : dva = QLA_DMA_DVA(mem) + reqsize;
1219 0 : htolem32(&header->resp_addr_lo, dva);
1220 0 : htolem32(&header->resp_addr_hi, dva >> 32);
1221 0 : header->subcmd_len = htole16((reqsize - sizeof(*header)) / 2);
1222 :
1223 0 : bus_dmamap_sync(sc->sc_dmat, QLA_DMA_MAP(mem), 0, QLA_DMA_LEN(mem),
1224 : BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1225 0 : rv = qla_mbox(sc, 0x00cf);
1226 0 : bus_dmamap_sync(sc->sc_dmat, QLA_DMA_MAP(mem), 0, QLA_DMA_LEN(mem),
1227 : BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1228 :
1229 0 : return (rv);
1230 : }
1231 :
1232 : void
1233 0 : qla_set_ints(struct qla_softc *sc, int enabled)
1234 : {
1235 0 : u_int16_t v = enabled ? (QLA_INT_REQ | QLA_RISC_INT_REQ) : 0;
1236 0 : qla_write(sc, QLA_INT_CTRL, v);
1237 0 : }
1238 :
1239 : int
1240 0 : qla_read_isr_1G(struct qla_softc *sc, u_int16_t *isr, u_int16_t *info)
1241 : {
1242 : u_int16_t int_status;
1243 :
1244 0 : if (qla_read(sc, QLA_SEMA) & QLA_SEMA_LOCK) {
1245 0 : *info = qla_read_mbox(sc, 0);
1246 0 : if (*info & QLA_MBOX_HAS_STATUS)
1247 0 : *isr = QLA_INT_TYPE_MBOX;
1248 : else
1249 0 : *isr = QLA_INT_TYPE_ASYNC;
1250 : } else {
1251 0 : int_status = qla_read(sc, QLA_INT_STATUS);
1252 0 : if ((int_status & QLA_INT_REQ) == 0)
1253 0 : return (0);
1254 :
1255 0 : *isr = QLA_INT_TYPE_IO;
1256 : }
1257 :
1258 0 : return (1);
1259 0 : }
1260 :
1261 : int
1262 0 : qla_read_isr_2G(struct qla_softc *sc, u_int16_t *isr, u_int16_t *info)
1263 : {
1264 : u_int32_t v;
1265 :
1266 0 : if ((qla_read(sc, QLA_INT_STATUS) & QLA_INT_REQ) == 0)
1267 0 : return (0);
1268 :
1269 0 : v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, QLA_RISC_STATUS_LOW);
1270 0 : bus_space_barrier(sc->sc_iot, sc->sc_ioh, QLA_RISC_STATUS_LOW,
1271 : 4, BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
1272 :
1273 0 : switch (v & QLA_INT_STATUS_MASK) {
1274 : case QLA_23XX_INT_ROM_MBOX:
1275 : case QLA_23XX_INT_ROM_MBOX_FAIL:
1276 : case QLA_23XX_INT_MBOX:
1277 : case QLA_23XX_INT_MBOX_FAIL:
1278 0 : *isr = QLA_INT_TYPE_MBOX;
1279 0 : break;
1280 :
1281 : case QLA_23XX_INT_ASYNC:
1282 0 : *isr = QLA_INT_TYPE_ASYNC;
1283 0 : break;
1284 :
1285 : case QLA_23XX_INT_RSPQ:
1286 0 : *isr = QLA_INT_TYPE_IO;
1287 0 : break;
1288 :
1289 : default:
1290 0 : *isr = QLA_INT_TYPE_OTHER;
1291 0 : break;
1292 : }
1293 :
1294 0 : *info = (v >> QLA_INT_INFO_SHIFT);
1295 :
1296 0 : return (1);
1297 0 : }
1298 :
1299 : void
1300 0 : qla_clear_isr(struct qla_softc *sc, u_int16_t isr)
1301 : {
1302 0 : qla_host_cmd(sc, QLA_HOST_CMD_CLR_RISC_INT);
1303 0 : switch (isr) {
1304 : case QLA_INT_TYPE_MBOX:
1305 : case QLA_INT_TYPE_ASYNC:
1306 0 : qla_write(sc, QLA_SEMA, 0);
1307 0 : break;
1308 : default:
1309 : break;
1310 : }
1311 0 : }
1312 :
1313 : u_int16_t
1314 0 : qla_read_queue_2100(struct qla_softc *sc, bus_size_t queue)
1315 : {
1316 : u_int16_t a, b, i;
1317 :
1318 0 : for (i = 0; i < 1000; i++) {
1319 0 : a = qla_read(sc, queue);
1320 0 : b = qla_read(sc, queue);
1321 :
1322 0 : if (a == b)
1323 0 : return (a);
1324 : }
1325 :
1326 : DPRINTF(QLA_D_INTR, "%s: queue ptr unstable\n", DEVNAME(sc));
1327 :
1328 0 : return (a);
1329 0 : }
1330 :
1331 : int
1332 0 : qla_softreset(struct qla_softc *sc)
1333 : {
1334 : int i;
1335 0 : qla_set_ints(sc, 0);
1336 :
1337 : /* reset */
1338 0 : qla_write(sc, QLA_CTRL_STATUS, QLA_CTRL_RESET);
1339 0 : delay(100);
1340 : /* clear data and control dma engines? */
1341 :
1342 : /* wait for soft reset to clear */
1343 0 : for (i = 0; i < 1000; i++) {
1344 0 : if ((qla_read(sc, QLA_CTRL_STATUS) & QLA_CTRL_RESET) == 0)
1345 : break;
1346 :
1347 0 : delay(100);
1348 : }
1349 :
1350 0 : if (i == 1000) {
1351 : DPRINTF(QLA_D_INTR, "%s: reset didn't clear\n", DEVNAME(sc));
1352 0 : qla_set_ints(sc, 0);
1353 0 : return (ENXIO);
1354 : }
1355 :
1356 : /* reset FPM */
1357 0 : qla_write(sc, QLA_CTRL_STATUS, QLA_CTRL_FPM0_REGS);
1358 0 : qla_write(sc, QLA_FPM_DIAG, QLA_FPM_RESET);
1359 0 : qla_write(sc, QLA_FPM_DIAG, 0); /* isp(4) doesn't do this? */
1360 0 : qla_write(sc, QLA_CTRL_STATUS, QLA_CTRL_RISC_REGS);
1361 :
1362 : /* reset risc processor */
1363 0 : qla_host_cmd(sc, QLA_HOST_CMD_RESET);
1364 0 : delay(100);
1365 0 : qla_write(sc, QLA_SEMA, 0);
1366 0 : qla_host_cmd(sc, QLA_HOST_CMD_MASK_PARITY); /* from isp(4) */
1367 0 : qla_host_cmd(sc, QLA_HOST_CMD_RELEASE);
1368 :
1369 : /* reset queue pointers */
1370 0 : qla_queue_write(sc, sc->sc_regs->req_in, 0);
1371 0 : qla_queue_write(sc, sc->sc_regs->req_out, 0);
1372 0 : qla_queue_write(sc, sc->sc_regs->res_in, 0);
1373 0 : qla_queue_write(sc, sc->sc_regs->res_out, 0);
1374 :
1375 0 : qla_set_ints(sc, 1);
1376 : /* isp(4) sends QLA_HOST_CMD_BIOS here.. not documented? */
1377 :
1378 : /* do a basic mailbox operation to check we're alive */
1379 0 : sc->sc_mbox[0] = QLA_MBOX_NOP;
1380 0 : if (qla_mbox(sc, 0x0001)) {
1381 : DPRINTF(QLA_D_INTR, "%s: ISP not responding after reset\n",
1382 : DEVNAME(sc));
1383 0 : return (ENXIO);
1384 : }
1385 :
1386 0 : return (0);
1387 0 : }
1388 :
1389 : void
1390 0 : qla_update_topology(struct qla_softc *sc)
1391 : {
1392 0 : sc->sc_mbox[0] = QLA_MBOX_GET_LOOP_ID;
1393 0 : if (qla_mbox(sc, 0x0001)) {
1394 : DPRINTF(QLA_D_PORT, "%s: unable to get loop id\n", DEVNAME(sc));
1395 0 : sc->sc_topology = QLA_TOPO_N_PORT_NO_TARGET;
1396 0 : } else {
1397 0 : sc->sc_topology = sc->sc_mbox[6];
1398 0 : sc->sc_loop_id = sc->sc_mbox[1];
1399 :
1400 0 : switch (sc->sc_topology) {
1401 : case QLA_TOPO_NL_PORT:
1402 : case QLA_TOPO_N_PORT:
1403 : DPRINTF(QLA_D_PORT, "%s: loop id %d\n", DEVNAME(sc),
1404 : sc->sc_loop_id);
1405 : break;
1406 :
1407 : case QLA_TOPO_FL_PORT:
1408 : case QLA_TOPO_F_PORT:
1409 0 : sc->sc_port_id = sc->sc_mbox[2] |
1410 0 : (sc->sc_mbox[3] << 16);
1411 : DPRINTF(QLA_D_PORT, "%s: fabric port id %06x\n",
1412 : DEVNAME(sc), sc->sc_port_id);
1413 0 : break;
1414 :
1415 : case QLA_TOPO_N_PORT_NO_TARGET:
1416 : default:
1417 : DPRINTF(QLA_D_PORT, "%s: not connected\n", DEVNAME(sc));
1418 : break;
1419 : }
1420 :
1421 0 : switch (sc->sc_topology) {
1422 : case QLA_TOPO_NL_PORT:
1423 : case QLA_TOPO_FL_PORT:
1424 0 : sc->sc_loop_max_id = 126;
1425 0 : break;
1426 :
1427 : case QLA_TOPO_N_PORT:
1428 0 : sc->sc_loop_max_id = 2;
1429 0 : break;
1430 :
1431 : default:
1432 0 : sc->sc_loop_max_id = 0;
1433 0 : break;
1434 : }
1435 : }
1436 0 : }
1437 :
1438 : int
1439 0 : qla_update_fabric(struct qla_softc *sc)
1440 : {
1441 : struct qla_sns_rft_id *rft;
1442 :
1443 0 : if (sc->sc_fabric == 0)
1444 0 : return (0);
1445 :
1446 0 : switch (sc->sc_topology) {
1447 : case QLA_TOPO_F_PORT:
1448 : case QLA_TOPO_FL_PORT:
1449 : break;
1450 :
1451 : default:
1452 0 : return (0);
1453 : }
1454 :
1455 : /* get the name server's port db entry */
1456 0 : sc->sc_mbox[0] = QLA_MBOX_GET_PORT_DB;
1457 0 : if (sc->sc_2k_logins) {
1458 0 : sc->sc_mbox[1] = QLA_F_PORT_HANDLE;
1459 0 : } else {
1460 0 : sc->sc_mbox[1] = QLA_F_PORT_HANDLE << 8;
1461 : }
1462 0 : qla_mbox_putaddr(sc->sc_mbox, sc->sc_scratch);
1463 0 : bus_dmamap_sync(sc->sc_dmat, QLA_DMA_MAP(sc->sc_scratch), 0,
1464 : sizeof(struct qla_get_port_db), BUS_DMASYNC_PREREAD);
1465 0 : if (qla_mbox(sc, 0x00cf)) {
1466 : DPRINTF(QLA_D_PORT, "%s: get port db for SNS failed: %x\n",
1467 : DEVNAME(sc), sc->sc_mbox[0]);
1468 0 : sc->sc_sns_port_name = 0;
1469 0 : } else {
1470 : struct qla_get_port_db *pdb;
1471 0 : bus_dmamap_sync(sc->sc_dmat, QLA_DMA_MAP(sc->sc_scratch), 0,
1472 : sizeof(struct qla_get_port_db), BUS_DMASYNC_POSTREAD);
1473 0 : pdb = QLA_DMA_KVA(sc->sc_scratch);
1474 : DPRINTF(QLA_D_PORT, "%s: SNS port name %llx\n", DEVNAME(sc),
1475 : betoh64(pdb->port_name));
1476 0 : sc->sc_sns_port_name = betoh64(pdb->port_name);
1477 : }
1478 :
1479 : /*
1480 : * register fc4 types with the fabric
1481 : * some switches do this automatically, but apparently
1482 : * some don't.
1483 : */
1484 0 : rft = QLA_DMA_KVA(sc->sc_scratch);
1485 0 : memset(rft, 0, sizeof(*rft) + sizeof(struct qla_sns_req_hdr));
1486 0 : rft->subcmd = htole16(QLA_SNS_RFT_ID);
1487 0 : rft->max_word = htole16(sizeof(struct qla_sns_req_hdr) / 4);
1488 0 : rft->port_id = htole32(sc->sc_port_id);
1489 0 : rft->fc4_types[0] = htole32(1 << QLA_FC4_SCSI);
1490 0 : if (qla_sns_req(sc, sc->sc_scratch, sizeof(*rft))) {
1491 : DPRINTF(QLA_D_PORT, "%s: RFT_ID failed\n", DEVNAME(sc));
1492 : /* we might be able to continue after this fails */
1493 : }
1494 :
1495 0 : return (1);
1496 0 : }
1497 :
1498 : int
1499 0 : qla_get_port_name_list(struct qla_softc *sc, u_int32_t match)
1500 : {
1501 : int i;
1502 : struct qla_port_name_list *l;
1503 : struct qla_fc_port *port;
1504 :
1505 0 : sc->sc_mbox[0] = QLA_MBOX_GET_PORT_NAME_LIST;
1506 0 : sc->sc_mbox[1] = 0x08; /* include initiators */
1507 0 : if (match & QLA_LOCATION_FABRIC)
1508 0 : sc->sc_mbox[1] |= 0x02; /* return all loop ids */
1509 0 : qla_mbox_putaddr(sc->sc_mbox, sc->sc_scratch);
1510 0 : bus_dmamap_sync(sc->sc_dmat, QLA_DMA_MAP(sc->sc_scratch), 0,
1511 : QLA_DMA_LEN(sc->sc_scratch), BUS_DMASYNC_PREREAD);
1512 0 : if (qla_mbox(sc, 0x04f)) {
1513 : DPRINTF(QLA_D_PORT, "%s: get port name list failed: %x\n",
1514 : DEVNAME(sc), sc->sc_mbox[0]);
1515 0 : return (1);
1516 : }
1517 0 : bus_dmamap_sync(sc->sc_dmat, QLA_DMA_MAP(sc->sc_scratch), 0,
1518 : QLA_DMA_LEN(sc->sc_scratch), BUS_DMASYNC_PREREAD);
1519 :
1520 : i = 0;
1521 0 : l = QLA_DMA_KVA(sc->sc_scratch);
1522 0 : mtx_enter(&sc->sc_port_mtx);
1523 0 : while (i * sizeof(*l) < sc->sc_mbox[1]) {
1524 : u_int16_t loopid;
1525 : u_int32_t loc;
1526 :
1527 0 : loopid = letoh16(l[i].loop_id);
1528 : /* skip special ports */
1529 0 : switch (loopid) {
1530 : case QLA_F_PORT_HANDLE:
1531 : case QLA_SNS_HANDLE:
1532 : case QLA_FABRIC_CTRL_HANDLE:
1533 : loc = 0;
1534 0 : break;
1535 : default:
1536 0 : if (loopid <= sc->sc_loop_max_id) {
1537 0 : loc = QLA_LOCATION_LOOP_ID(loopid);
1538 0 : } else {
1539 : /*
1540 : * we don't have the port id here, so just
1541 : * indicate it's a fabric port.
1542 : */
1543 : loc = QLA_LOCATION_FABRIC;
1544 : }
1545 : }
1546 :
1547 0 : if (match & loc) {
1548 0 : port = malloc(sizeof(*port), M_DEVBUF, M_ZERO |
1549 : M_NOWAIT);
1550 0 : if (port == NULL) {
1551 0 : printf("%s: failed to allocate port struct\n",
1552 0 : DEVNAME(sc));
1553 0 : break;
1554 : }
1555 0 : port->location = loc;
1556 0 : port->loopid = loopid;
1557 0 : port->port_name = letoh64(l[i].port_name);
1558 : DPRINTF(QLA_D_PORT, "%s: loop id %d, port name %llx\n",
1559 : DEVNAME(sc), port->loopid, port->port_name);
1560 0 : TAILQ_INSERT_TAIL(&sc->sc_ports_found, port, update);
1561 0 : }
1562 0 : i++;
1563 0 : }
1564 0 : mtx_leave(&sc->sc_port_mtx);
1565 :
1566 0 : return (0);
1567 0 : }
1568 :
1569 : struct qla_fc_port *
1570 0 : qla_next_fabric_port(struct qla_softc *sc, u_int32_t *firstport,
1571 : u_int32_t *lastport)
1572 : {
1573 : struct qla_sns_ga_nxt *ga;
1574 : struct qla_sns_ga_nxt_resp *gar;
1575 : struct qla_fc_port *fport;
1576 : int result;
1577 :
1578 : /* get the next port from the fabric nameserver */
1579 0 : ga = QLA_DMA_KVA(sc->sc_scratch);
1580 0 : memset(ga, 0, sizeof(*ga) + sizeof(*gar));
1581 0 : ga->subcmd = htole16(QLA_SNS_GA_NXT);
1582 0 : ga->max_word = htole16(sizeof(*gar) / 4);
1583 0 : ga->port_id = htole32(*lastport);
1584 0 : result = qla_sns_req(sc, sc->sc_scratch, sizeof(*ga));
1585 0 : if (result) {
1586 : DPRINTF(QLA_D_PORT, "%s: GA_NXT %06x failed: %x\n", DEVNAME(sc),
1587 : *lastport, result);
1588 0 : *lastport = 0xffffffff;
1589 0 : return (NULL);
1590 : }
1591 :
1592 0 : gar = (struct qla_sns_ga_nxt_resp *)(ga + 1);
1593 : /* if the response is all zeroes, try again */
1594 0 : if (gar->port_type_id == 0 && gar->port_name == 0 &&
1595 0 : gar->node_name == 0) {
1596 : DPRINTF(QLA_D_PORT, "%s: GA_NXT returned junk\n", DEVNAME(sc));
1597 0 : return (NULL);
1598 : }
1599 :
1600 : /* are we back at the start? */
1601 0 : *lastport = betoh32(gar->port_type_id) & 0xffffff;
1602 0 : if (*lastport == *firstport) {
1603 0 : *lastport = 0xffffffff;
1604 0 : return (NULL);
1605 : }
1606 0 : if (*firstport == 0xffffffff)
1607 0 : *firstport = *lastport;
1608 :
1609 : DPRINTF(QLA_D_PORT, "%s: GA_NXT: port id: %06x, wwpn %llx, wwnn %llx\n",
1610 : DEVNAME(sc), *lastport, betoh64(gar->port_name),
1611 : betoh64(gar->node_name));
1612 :
1613 : /* don't try to log in to ourselves */
1614 0 : if (*lastport == sc->sc_port_id) {
1615 0 : return (NULL);
1616 : }
1617 :
1618 0 : fport = malloc(sizeof(*fport), M_DEVBUF, M_ZERO | M_NOWAIT);
1619 0 : if (fport == NULL) {
1620 0 : printf("%s: failed to allocate a port struct\n",
1621 0 : DEVNAME(sc));
1622 0 : *lastport = 0xffffffff;
1623 0 : return (NULL);
1624 : }
1625 0 : fport->port_name = betoh64(gar->port_name);
1626 0 : fport->node_name = betoh64(gar->node_name);
1627 0 : fport->location = QLA_LOCATION_PORT_ID(*lastport);
1628 0 : fport->portid = *lastport;
1629 0 : return (fport);
1630 0 : }
1631 :
1632 : int
1633 0 : qla_fabric_plogi(struct qla_softc *sc, struct qla_fc_port *port)
1634 : {
1635 : int loopid, mboxin, err;
1636 : u_int32_t id;
1637 :
1638 0 : loopid = 0;
1639 : retry:
1640 0 : if (port->loopid == 0) {
1641 0 : mtx_enter(&sc->sc_port_mtx);
1642 0 : loopid = qla_get_loop_id(sc, loopid);
1643 0 : mtx_leave(&sc->sc_port_mtx);
1644 0 : if (loopid == -1) {
1645 : DPRINTF(QLA_D_PORT, "%s: ran out of loop ids\n",
1646 : DEVNAME(sc));
1647 0 : return (1);
1648 : }
1649 : }
1650 :
1651 : mboxin = 0x000f;
1652 0 : sc->sc_mbox[0] = QLA_MBOX_FABRIC_PLOGI;
1653 0 : sc->sc_mbox[2] = (port->portid >> 16) & 0xff;
1654 0 : sc->sc_mbox[3] = port->portid & 0xffff;
1655 0 : if (sc->sc_2k_logins) {
1656 0 : sc->sc_mbox[1] = loopid;
1657 0 : sc->sc_mbox[10] = 0;
1658 : mboxin |= (1 << 10);
1659 0 : } else {
1660 0 : sc->sc_mbox[1] = loopid << 8;
1661 : }
1662 :
1663 0 : err = qla_mbox(sc, mboxin);
1664 0 : switch (err) {
1665 : case 0:
1666 : DPRINTF(QLA_D_PORT, "%s: logged in to %06x as %d\n",
1667 : DEVNAME(sc), port->portid, loopid);
1668 0 : port->flags &= ~QLA_PORT_FLAG_NEEDS_LOGIN;
1669 0 : port->loopid = loopid;
1670 0 : return (0);
1671 :
1672 : case QLA_MBOX_PORT_USED:
1673 : DPRINTF(QLA_D_PORT, "%s: already logged in to %06x as %d\n",
1674 : DEVNAME(sc), port->portid, sc->sc_mbox[1]);
1675 0 : port->flags &= ~QLA_PORT_FLAG_NEEDS_LOGIN;
1676 0 : port->loopid = sc->sc_mbox[1];
1677 0 : return (0);
1678 :
1679 : case QLA_MBOX_LOOP_USED:
1680 0 : id = (sc->sc_mbox[1] << 16) | sc->sc_mbox[2];
1681 0 : if (qla_add_logged_in_port(sc, loopid, id)) {
1682 0 : return (1);
1683 : }
1684 0 : port->loopid = 0;
1685 0 : loopid++;
1686 0 : goto retry;
1687 :
1688 : default:
1689 : DPRINTF(QLA_D_PORT, "%s: error %x logging in to port %06x\n",
1690 : DEVNAME(sc), err, port->portid);
1691 0 : port->loopid = 0;
1692 0 : return (1);
1693 : }
1694 0 : }
1695 :
1696 : void
1697 0 : qla_fabric_plogo(struct qla_softc *sc, struct qla_fc_port *port)
1698 : {
1699 : int mboxin = 0x0003;
1700 0 : sc->sc_mbox[0] = QLA_MBOX_FABRIC_PLOGO;
1701 0 : if (sc->sc_2k_logins) {
1702 0 : sc->sc_mbox[1] = port->loopid;
1703 0 : sc->sc_mbox[10] = 0;
1704 : mboxin |= (1 << 10);
1705 0 : } else {
1706 0 : sc->sc_mbox[1] = port->loopid << 8;
1707 : }
1708 :
1709 0 : if (qla_mbox(sc, mboxin))
1710 : DPRINTF(QLA_D_PORT, "%s: loop id %d logout failed\n",
1711 : DEVNAME(sc), port->loopid);
1712 0 : }
1713 :
1714 : void
1715 0 : qla_update_done(struct qla_softc *sc, int task)
1716 : {
1717 0 : atomic_clearbits_int(&sc->sc_update_tasks, task);
1718 0 : }
1719 :
1720 : void
1721 0 : qla_update_start(struct qla_softc *sc, int task)
1722 : {
1723 0 : atomic_setbits_int(&sc->sc_update_tasks, task);
1724 0 : task_add(sc->sc_update_taskq, &sc->sc_update_task);
1725 0 : }
1726 :
1727 : void
1728 0 : qla_clear_port_lists(struct qla_softc *sc)
1729 : {
1730 : struct qla_fc_port *p;
1731 :
1732 0 : while (!TAILQ_EMPTY(&sc->sc_ports_found)) {
1733 : p = TAILQ_FIRST(&sc->sc_ports_found);
1734 0 : TAILQ_REMOVE(&sc->sc_ports_found, p, update);
1735 0 : free(p, M_DEVBUF, sizeof *p);
1736 : }
1737 :
1738 0 : while (!TAILQ_EMPTY(&sc->sc_ports_new)) {
1739 : p = TAILQ_FIRST(&sc->sc_ports_new);
1740 0 : TAILQ_REMOVE(&sc->sc_ports_new, p, update);
1741 0 : free(p, M_DEVBUF, sizeof *p);
1742 : }
1743 :
1744 0 : while (!TAILQ_EMPTY(&sc->sc_ports_gone)) {
1745 : p = TAILQ_FIRST(&sc->sc_ports_gone);
1746 0 : TAILQ_REMOVE(&sc->sc_ports_gone, p, update);
1747 : }
1748 0 : }
1749 :
1750 : void
1751 0 : qla_do_update(void *xsc)
1752 : {
1753 0 : struct qla_softc *sc = xsc;
1754 0 : int firstport, lastport;
1755 0 : struct qla_fc_port *port, *fport;
1756 :
1757 : DPRINTF(QLA_D_PORT, "%s: updating\n", DEVNAME(sc));
1758 0 : while (sc->sc_update_tasks != 0) {
1759 0 : if (sc->sc_update_tasks & QLA_UPDATE_TASK_CLEAR_ALL) {
1760 0 : TAILQ_HEAD(, qla_fc_port) detach;
1761 : DPRINTF(QLA_D_PORT, "%s: detaching everything\n",
1762 : DEVNAME(sc));
1763 :
1764 0 : mtx_enter(&sc->sc_port_mtx);
1765 0 : qla_clear_port_lists(sc);
1766 0 : TAILQ_INIT(&detach);
1767 0 : while (!TAILQ_EMPTY(&sc->sc_ports)) {
1768 0 : port = TAILQ_FIRST(&sc->sc_ports);
1769 0 : TAILQ_REMOVE(&sc->sc_ports, port, ports);
1770 0 : TAILQ_INSERT_TAIL(&detach, port, ports);
1771 : }
1772 0 : mtx_leave(&sc->sc_port_mtx);
1773 :
1774 0 : while (!TAILQ_EMPTY(&detach)) {
1775 0 : port = TAILQ_FIRST(&detach);
1776 0 : TAILQ_REMOVE(&detach, port, ports);
1777 0 : if (port->flags & QLA_PORT_FLAG_IS_TARGET) {
1778 0 : scsi_detach_target(sc->sc_scsibus,
1779 0 : port->loopid, -1);
1780 0 : }
1781 0 : sc->sc_targets[port->loopid] = NULL;
1782 0 : if (port->location & QLA_LOCATION_FABRIC)
1783 0 : qla_fabric_plogo(sc, port);
1784 :
1785 0 : free(port, M_DEVBUF, sizeof *port);
1786 : }
1787 :
1788 0 : qla_update_done(sc, QLA_UPDATE_TASK_CLEAR_ALL);
1789 : continue;
1790 0 : }
1791 :
1792 0 : if (sc->sc_update_tasks & QLA_UPDATE_TASK_SOFTRESET) {
1793 : /* what no */
1794 0 : qla_update_done(sc, QLA_UPDATE_TASK_SOFTRESET);
1795 0 : continue;
1796 : }
1797 :
1798 0 : if (sc->sc_update_tasks & QLA_UPDATE_TASK_UPDATE_TOPO) {
1799 : DPRINTF(QLA_D_PORT, "%s: updating topology\n",
1800 : DEVNAME(sc));
1801 0 : qla_update_topology(sc);
1802 0 : qla_update_done(sc, QLA_UPDATE_TASK_UPDATE_TOPO);
1803 0 : continue;
1804 : }
1805 :
1806 0 : if (sc->sc_update_tasks & QLA_UPDATE_TASK_GET_PORT_LIST) {
1807 : DPRINTF(QLA_D_PORT, "%s: getting port name list\n",
1808 : DEVNAME(sc));
1809 0 : mtx_enter(&sc->sc_port_mtx);
1810 0 : qla_clear_port_lists(sc);
1811 0 : mtx_leave(&sc->sc_port_mtx);
1812 :
1813 0 : qla_get_port_name_list(sc, QLA_LOCATION_LOOP |
1814 : QLA_LOCATION_FABRIC);
1815 0 : mtx_enter(&sc->sc_port_mtx);
1816 0 : TAILQ_FOREACH(port, &sc->sc_ports, ports) {
1817 0 : TAILQ_INSERT_TAIL(&sc->sc_ports_gone, port,
1818 : update);
1819 0 : if (port->location & QLA_LOCATION_FABRIC) {
1820 0 : port->flags |=
1821 : QLA_PORT_FLAG_NEEDS_LOGIN;
1822 0 : }
1823 : }
1824 :
1825 : /* take care of ports that haven't changed first */
1826 0 : TAILQ_FOREACH(fport, &sc->sc_ports_found, update) {
1827 0 : port = sc->sc_targets[fport->loopid];
1828 0 : if (port == NULL || fport->port_name !=
1829 0 : port->port_name) {
1830 : /* new or changed port, handled later */
1831 : continue;
1832 : }
1833 :
1834 : /*
1835 : * the port hasn't been logged out, which
1836 : * means we don't need to log in again, and,
1837 : * for loop ports, that the port still exists.
1838 : */
1839 0 : port->flags &= ~QLA_PORT_FLAG_NEEDS_LOGIN;
1840 0 : if (port->location & QLA_LOCATION_LOOP)
1841 0 : TAILQ_REMOVE(&sc->sc_ports_gone,
1842 : port, update);
1843 :
1844 0 : fport->location = 0;
1845 0 : }
1846 0 : mtx_leave(&sc->sc_port_mtx);
1847 0 : qla_update_start(sc, QLA_UPDATE_TASK_PORT_LIST);
1848 0 : qla_update_done(sc, QLA_UPDATE_TASK_GET_PORT_LIST);
1849 0 : continue;
1850 : }
1851 :
1852 0 : if (sc->sc_update_tasks & QLA_UPDATE_TASK_PORT_LIST) {
1853 0 : mtx_enter(&sc->sc_port_mtx);
1854 0 : fport = TAILQ_FIRST(&sc->sc_ports_found);
1855 0 : if (fport != NULL) {
1856 0 : TAILQ_REMOVE(&sc->sc_ports_found, fport,
1857 : update);
1858 0 : }
1859 0 : mtx_leave(&sc->sc_port_mtx);
1860 :
1861 0 : if (fport == NULL) {
1862 : DPRINTF(QLA_D_PORT, "%s: done with ports\n",
1863 : DEVNAME(sc));
1864 0 : qla_update_done(sc,
1865 : QLA_UPDATE_TASK_PORT_LIST);
1866 0 : qla_update_start(sc,
1867 : QLA_UPDATE_TASK_SCAN_FABRIC);
1868 0 : } else if (fport->location & QLA_LOCATION_LOOP) {
1869 : DPRINTF(QLA_D_PORT, "%s: loop port %d\n",
1870 : DEVNAME(sc), fport->loopid);
1871 0 : if (qla_add_loop_port(sc, fport) != 0)
1872 0 : free(fport, M_DEVBUF, sizeof *fport);
1873 0 : } else if (fport->location & QLA_LOCATION_FABRIC) {
1874 0 : qla_add_fabric_port(sc, fport);
1875 0 : } else {
1876 : /* already processed */
1877 0 : free(fport, M_DEVBUF, sizeof *fport);
1878 : }
1879 0 : continue;
1880 : }
1881 :
1882 0 : if (sc->sc_update_tasks & QLA_UPDATE_TASK_SCAN_FABRIC) {
1883 : DPRINTF(QLA_D_PORT, "%s: starting fabric scan\n",
1884 : DEVNAME(sc));
1885 0 : lastport = sc->sc_port_id;
1886 0 : firstport = 0xffffffff;
1887 0 : if (qla_update_fabric(sc))
1888 0 : qla_update_start(sc,
1889 : QLA_UPDATE_TASK_SCANNING_FABRIC);
1890 0 : qla_update_done(sc, QLA_UPDATE_TASK_SCAN_FABRIC);
1891 0 : continue;
1892 : }
1893 :
1894 0 : if (sc->sc_update_tasks & QLA_UPDATE_TASK_SCANNING_FABRIC) {
1895 0 : fport = qla_next_fabric_port(sc, &firstport, &lastport);
1896 0 : if (fport != NULL) {
1897 : int disp;
1898 :
1899 0 : mtx_enter(&sc->sc_port_mtx);
1900 0 : disp = qla_classify_port(sc, fport->location,
1901 0 : fport->port_name, fport->node_name, &port);
1902 0 : switch (disp) {
1903 : case QLA_PORT_DISP_CHANGED:
1904 : case QLA_PORT_DISP_MOVED:
1905 : /* we'll log out the old port later */
1906 : case QLA_PORT_DISP_NEW:
1907 : DPRINTF(QLA_D_PORT, "%s: new port "
1908 : "%06x\n", DEVNAME(sc),
1909 : fport->portid);
1910 0 : TAILQ_INSERT_TAIL(&sc->sc_ports_found,
1911 : fport, update);
1912 0 : break;
1913 : case QLA_PORT_DISP_DUP:
1914 0 : free(fport, M_DEVBUF, sizeof *fport);
1915 0 : break;
1916 : case QLA_PORT_DISP_SAME:
1917 : DPRINTF(QLA_D_PORT, "%s: existing port"
1918 : " %06x\n", DEVNAME(sc),
1919 : fport->portid);
1920 0 : TAILQ_REMOVE(&sc->sc_ports_gone, port,
1921 : update);
1922 0 : free(fport, M_DEVBUF, sizeof *fport);
1923 0 : break;
1924 : }
1925 0 : mtx_leave(&sc->sc_port_mtx);
1926 0 : }
1927 0 : if (lastport == 0xffffffff) {
1928 : DPRINTF(QLA_D_PORT, "%s: finished\n",
1929 : DEVNAME(sc));
1930 0 : qla_update_done(sc,
1931 : QLA_UPDATE_TASK_SCANNING_FABRIC);
1932 0 : qla_update_start(sc,
1933 : QLA_UPDATE_TASK_FABRIC_LOGIN);
1934 0 : }
1935 0 : continue;
1936 : }
1937 :
1938 0 : if (sc->sc_update_tasks & QLA_UPDATE_TASK_FABRIC_LOGIN) {
1939 0 : mtx_enter(&sc->sc_port_mtx);
1940 0 : port = TAILQ_FIRST(&sc->sc_ports_found);
1941 0 : if (port != NULL) {
1942 0 : TAILQ_REMOVE(&sc->sc_ports_found, port, update);
1943 0 : }
1944 0 : mtx_leave(&sc->sc_port_mtx);
1945 :
1946 0 : if (port != NULL) {
1947 : DPRINTF(QLA_D_PORT, "%s: found port %06x\n",
1948 : DEVNAME(sc), port->portid);
1949 0 : if (qla_fabric_plogi(sc, port) == 0) {
1950 0 : qla_add_fabric_port(sc, port);
1951 0 : } else {
1952 0 : free(port, M_DEVBUF, sizeof *port);
1953 : }
1954 : } else {
1955 : DPRINTF(QLA_D_PORT, "%s: done with logins\n",
1956 : DEVNAME(sc));
1957 0 : qla_update_done(sc,
1958 : QLA_UPDATE_TASK_FABRIC_LOGIN);
1959 0 : qla_update_start(sc,
1960 : QLA_UPDATE_TASK_ATTACH_TARGET |
1961 : QLA_UPDATE_TASK_DETACH_TARGET);
1962 : }
1963 0 : continue;
1964 : }
1965 :
1966 0 : if (sc->sc_update_tasks & QLA_UPDATE_TASK_FABRIC_RELOGIN) {
1967 0 : TAILQ_FOREACH(port, &sc->sc_ports, ports) {
1968 0 : if (port->flags & QLA_PORT_FLAG_NEEDS_LOGIN) {
1969 0 : qla_fabric_plogi(sc, port);
1970 0 : break;
1971 : }
1972 : }
1973 :
1974 0 : if (port == NULL)
1975 0 : qla_update_done(sc,
1976 : QLA_UPDATE_TASK_FABRIC_RELOGIN);
1977 0 : continue;
1978 : }
1979 :
1980 0 : if (sc->sc_update_tasks & QLA_UPDATE_TASK_DETACH_TARGET) {
1981 0 : mtx_enter(&sc->sc_port_mtx);
1982 0 : port = TAILQ_FIRST(&sc->sc_ports_gone);
1983 0 : if (port != NULL) {
1984 0 : sc->sc_targets[port->loopid] = NULL;
1985 0 : TAILQ_REMOVE(&sc->sc_ports_gone, port, update);
1986 0 : TAILQ_REMOVE(&sc->sc_ports, port, ports);
1987 0 : }
1988 0 : mtx_leave(&sc->sc_port_mtx);
1989 :
1990 0 : if (port != NULL) {
1991 : DPRINTF(QLA_D_PORT, "%s: detaching target %d\n",
1992 : DEVNAME(sc), port->loopid);
1993 0 : if (sc->sc_scsibus != NULL)
1994 0 : scsi_detach_target(sc->sc_scsibus,
1995 0 : port->loopid, -1);
1996 :
1997 0 : if (port->location & QLA_LOCATION_FABRIC)
1998 0 : qla_fabric_plogo(sc, port);
1999 :
2000 0 : free(port, M_DEVBUF, sizeof *port);
2001 0 : } else {
2002 0 : qla_update_done(sc,
2003 : QLA_UPDATE_TASK_DETACH_TARGET);
2004 : }
2005 0 : continue;
2006 : }
2007 :
2008 0 : if (sc->sc_update_tasks & QLA_UPDATE_TASK_ATTACH_TARGET) {
2009 0 : mtx_enter(&sc->sc_port_mtx);
2010 0 : port = TAILQ_FIRST(&sc->sc_ports_new);
2011 0 : if (port != NULL) {
2012 0 : TAILQ_REMOVE(&sc->sc_ports_new, port, update);
2013 0 : TAILQ_INSERT_TAIL(&sc->sc_ports, port, ports);
2014 0 : }
2015 0 : mtx_leave(&sc->sc_port_mtx);
2016 :
2017 0 : if (port != NULL) {
2018 0 : if (sc->sc_scsibus != NULL)
2019 0 : scsi_probe_target(sc->sc_scsibus,
2020 0 : port->loopid);
2021 : } else {
2022 0 : qla_update_done(sc,
2023 : QLA_UPDATE_TASK_ATTACH_TARGET);
2024 : }
2025 0 : continue;
2026 : }
2027 :
2028 : }
2029 :
2030 : DPRINTF(QLA_D_PORT, "%s: done updating\n", DEVNAME(sc));
2031 0 : }
2032 :
2033 : int
2034 0 : qla_async(struct qla_softc *sc, u_int16_t info)
2035 : {
2036 : u_int16_t id, exp;
2037 :
2038 0 : switch (info) {
2039 : case QLA_ASYNC_SYSTEM_ERROR:
2040 0 : qla_update_start(sc, QLA_UPDATE_TASK_SOFTRESET);
2041 0 : break;
2042 :
2043 : case QLA_ASYNC_REQ_XFER_ERROR:
2044 0 : qla_update_start(sc, QLA_UPDATE_TASK_SOFTRESET);
2045 0 : break;
2046 :
2047 : case QLA_ASYNC_RSP_XFER_ERROR:
2048 0 : qla_update_start(sc, QLA_UPDATE_TASK_SOFTRESET);
2049 0 : break;
2050 :
2051 : case QLA_ASYNC_LIP_OCCURRED:
2052 : DPRINTF(QLA_D_PORT, "%s: lip occurred\n", DEVNAME(sc));
2053 : break;
2054 :
2055 : case QLA_ASYNC_LOOP_UP:
2056 : DPRINTF(QLA_D_PORT, "%s: loop up\n", DEVNAME(sc));
2057 0 : sc->sc_loop_up = 1;
2058 0 : sc->sc_marker_required = 1;
2059 0 : qla_update_start(sc, QLA_UPDATE_TASK_UPDATE_TOPO |
2060 : QLA_UPDATE_TASK_GET_PORT_LIST);
2061 0 : break;
2062 :
2063 : case QLA_ASYNC_LOOP_DOWN:
2064 : DPRINTF(QLA_D_PORT, "%s: loop down\n", DEVNAME(sc));
2065 0 : sc->sc_loop_up = 0;
2066 0 : qla_update_start(sc, QLA_UPDATE_TASK_CLEAR_ALL);
2067 0 : break;
2068 :
2069 : case QLA_ASYNC_LIP_RESET:
2070 : DPRINTF(QLA_D_PORT, "%s: lip reset\n", DEVNAME(sc));
2071 0 : sc->sc_marker_required = 1;
2072 0 : qla_update_start(sc, QLA_UPDATE_TASK_FABRIC_RELOGIN);
2073 0 : break;
2074 :
2075 : case QLA_ASYNC_PORT_DB_CHANGE:
2076 : DPRINTF(QLA_D_PORT, "%s: port db changed %x\n", DEVNAME(sc),
2077 : qla_read_mbox(sc, 1));
2078 0 : qla_update_start(sc, QLA_UPDATE_TASK_GET_PORT_LIST);
2079 0 : break;
2080 :
2081 : case QLA_ASYNC_CHANGE_NOTIFY:
2082 : DPRINTF(QLA_D_PORT, "%s: name server change (%02x:%02x)\n",
2083 : DEVNAME(sc), qla_read_mbox(sc, 1), qla_read_mbox(sc, 2));
2084 0 : qla_update_start(sc, QLA_UPDATE_TASK_GET_PORT_LIST);
2085 0 : break;
2086 :
2087 : case QLA_ASYNC_LIP_F8:
2088 : DPRINTF(QLA_D_PORT, "%s: lip f8\n", DEVNAME(sc));
2089 : break;
2090 :
2091 : case QLA_ASYNC_LOOP_INIT_ERROR:
2092 : DPRINTF(QLA_D_PORT, "%s: loop initialization error: %x\n",
2093 : DEVNAME(sc), qla_read_mbox(sc, 1));
2094 : break;
2095 :
2096 : case QLA_ASYNC_LOGIN_REJECT:
2097 0 : id = qla_read_mbox(sc, 1);
2098 0 : exp = qla_read_mbox(sc, 2);
2099 : DPRINTF(QLA_D_PORT, "%s: login reject from %x (reason %d,"
2100 : " explanation %x)\n", DEVNAME(sc), id >> 8, id & 0xff, exp);
2101 0 : break;
2102 :
2103 : case QLA_ASYNC_SCSI_CMD_COMPLETE:
2104 : /* shouldn't happen, we disable fast posting */
2105 : break;
2106 :
2107 : case QLA_ASYNC_CTIO_COMPLETE:
2108 : /* definitely shouldn't happen, we don't do target mode */
2109 : break;
2110 :
2111 : case QLA_ASYNC_POINT_TO_POINT:
2112 : DPRINTF(QLA_D_PORT, "%s: connected in point-to-point mode\n",
2113 : DEVNAME(sc));
2114 : /* we get stuck handling these if we have the wrong loop
2115 : * topology; should somehow reinit with different things
2116 : * somehow.
2117 : */
2118 : break;
2119 :
2120 : case QLA_ASYNC_ZIO_RESP_UPDATE:
2121 : /* shouldn't happen, we don't do zio */
2122 : break;
2123 :
2124 : case QLA_ASYNC_RND_ERROR:
2125 : /* do nothing? */
2126 : break;
2127 :
2128 : case QLA_ASYNC_QUEUE_FULL:
2129 : break;
2130 :
2131 : default:
2132 : DPRINTF(QLA_D_INTR, "%s: unknown async %x\n", DEVNAME(sc),
2133 : info);
2134 : break;
2135 : }
2136 0 : return (1);
2137 : }
2138 :
2139 : void
2140 0 : qla_dump_iocb(struct qla_softc *sc, void *buf)
2141 : {
2142 : #ifdef QLA_DEBUG
2143 : u_int8_t *iocb = buf;
2144 : int l;
2145 : int b;
2146 :
2147 : if ((qladebug & QLA_D_IOCB) == 0)
2148 : return;
2149 :
2150 : printf("%s: iocb:\n", DEVNAME(sc));
2151 : for (l = 0; l < 4; l++) {
2152 : for (b = 0; b < 16; b++) {
2153 : printf(" %2.2x", iocb[(l*16)+b]);
2154 : }
2155 : printf("\n");
2156 : }
2157 : #endif
2158 0 : }
2159 :
2160 : void
2161 0 : qla_dump_iocb_segs(struct qla_softc *sc, void *segs, int n)
2162 : {
2163 : #ifdef QLA_DEBUG
2164 : u_int8_t *buf = segs;
2165 : int s, b;
2166 : if ((qladebug & QLA_D_IOCB) == 0)
2167 : return;
2168 :
2169 : printf("%s: iocb segs:\n", DEVNAME(sc));
2170 : for (s = 0; s < n; s++) {
2171 : for (b = 0; b < sizeof(struct qla_iocb_seg); b++) {
2172 : printf(" %2.2x", buf[(s*(sizeof(struct qla_iocb_seg)))
2173 : + b]);
2174 : }
2175 : printf("\n");
2176 : }
2177 : #endif
2178 0 : }
2179 :
2180 : void
2181 0 : qla_put_marker(struct qla_softc *sc, void *buf)
2182 : {
2183 0 : struct qla_iocb_marker *marker = buf;
2184 :
2185 0 : marker->entry_type = QLA_IOCB_MARKER;
2186 0 : marker->entry_count = 1;
2187 0 : marker->seqno = 0;
2188 0 : marker->flags = 0;
2189 :
2190 : /* could be more specific here; isp(4) isn't */
2191 0 : marker->target = 0;
2192 0 : marker->modifier = QLA_IOCB_MARKER_SYNC_ALL;
2193 0 : qla_dump_iocb(sc, buf);
2194 0 : }
2195 :
2196 : static inline void
2197 0 : qla_put_data_seg(struct qla_iocb_seg *seg, bus_dmamap_t dmap, int num)
2198 : {
2199 0 : uint64_t addr = dmap->dm_segs[num].ds_addr;
2200 :
2201 0 : htolem32(&seg->seg_addr_lo, addr);
2202 0 : htolem32(&seg->seg_addr_hi, addr >> 32);
2203 0 : htolem32(&seg->seg_len, dmap->dm_segs[num].ds_len);
2204 0 : }
2205 :
2206 : void
2207 0 : qla_put_cmd(struct qla_softc *sc, void *buf, struct scsi_xfer *xs,
2208 : struct qla_ccb *ccb)
2209 : {
2210 0 : struct qla_iocb_req34 *req = buf;
2211 : u_int16_t dir;
2212 : int seg;
2213 0 : int target = xs->sc_link->target;
2214 :
2215 0 : req->seqno = 0;
2216 0 : req->flags = 0;
2217 0 : req->entry_count = 1;
2218 :
2219 0 : if (xs->datalen == 0) {
2220 : dir = QLA_IOCB_CMD_NO_DATA;
2221 0 : req->req_seg_count = 0;
2222 0 : req->entry_type = QLA_IOCB_CMD_TYPE_3;
2223 0 : } else {
2224 0 : dir = xs->flags & SCSI_DATA_IN ? QLA_IOCB_CMD_READ_DATA :
2225 : QLA_IOCB_CMD_WRITE_DATA;
2226 0 : htolem16(&req->req_seg_count, ccb->ccb_dmamap->dm_nsegs);
2227 0 : if (ccb->ccb_dmamap->dm_nsegs > QLA_IOCB_SEGS_PER_CMD) {
2228 0 : req->entry_type = QLA_IOCB_CMD_TYPE_4;
2229 0 : for (seg = 0; seg < ccb->ccb_dmamap->dm_nsegs; seg++) {
2230 0 : qla_put_data_seg(&ccb->ccb_t4segs[seg],
2231 : ccb->ccb_dmamap, seg);
2232 : }
2233 0 : req->req_type.req4.req4_seg_type = htole16(1);
2234 0 : req->req_type.req4.req4_seg_base = 0;
2235 0 : req->req_type.req4.req4_seg_addr = ccb->ccb_seg_dva;
2236 0 : memset(req->req_type.req4.req4_reserved, 0,
2237 : sizeof(req->req_type.req4.req4_reserved));
2238 0 : bus_dmamap_sync(sc->sc_dmat,
2239 : QLA_DMA_MAP(sc->sc_segments), ccb->ccb_seg_offset,
2240 : sizeof(*ccb->ccb_t4segs) * ccb->ccb_dmamap->dm_nsegs,
2241 : BUS_DMASYNC_PREWRITE);
2242 0 : } else {
2243 0 : req->entry_type = QLA_IOCB_CMD_TYPE_3;
2244 0 : for (seg = 0; seg < ccb->ccb_dmamap->dm_nsegs; seg++) {
2245 0 : qla_put_data_seg(&req->req_type.req3_segs[seg],
2246 : ccb->ccb_dmamap, seg);
2247 : }
2248 : }
2249 : }
2250 :
2251 : /* isp(4) uses head of queue for 'request sense' commands */
2252 0 : htolem16(&req->req_flags, QLA_IOCB_CMD_SIMPLE_QUEUE | dir);
2253 :
2254 : /*
2255 : * timeout is in seconds. make sure it's at least 1 if a timeout
2256 : * was specified in xs
2257 : */
2258 0 : if (xs->timeout != 0)
2259 0 : htolem16(&req->req_time, MAX(1, xs->timeout/1000));
2260 :
2261 : /* lun and target layout vary with firmware attributes */
2262 0 : if (sc->sc_expanded_lun) {
2263 0 : if (sc->sc_2k_logins) {
2264 0 : req->req_target = htole16(target);
2265 0 : } else {
2266 0 : req->req_target = htole16(target << 8);
2267 : }
2268 0 : req->req_scclun = htole16(xs->sc_link->lun);
2269 0 : } else {
2270 0 : req->req_target = htole16(target << 8 | xs->sc_link->lun);
2271 : }
2272 0 : memcpy(req->req_cdb, xs->cmd, xs->cmdlen);
2273 0 : req->req_totalcnt = htole32(xs->datalen);
2274 :
2275 0 : req->req_handle = ccb->ccb_id;
2276 :
2277 0 : qla_dump_iocb(sc, buf);
2278 0 : }
2279 :
2280 : int
2281 0 : qla_verify_firmware(struct qla_softc *sc, u_int16_t addr)
2282 : {
2283 0 : sc->sc_mbox[0] = QLA_MBOX_VERIFY_CSUM;
2284 0 : sc->sc_mbox[1] = addr;
2285 0 : return (qla_mbox(sc, 0x0003));
2286 : }
2287 :
2288 : #ifndef ISP_NOFIRMWARE
2289 : int
2290 0 : qla_load_firmware_words(struct qla_softc *sc, const u_int16_t *src,
2291 : u_int16_t dest)
2292 : {
2293 : u_int16_t i;
2294 :
2295 0 : for (i = 0; i < src[3]; i++) {
2296 0 : sc->sc_mbox[0] = QLA_MBOX_WRITE_RAM_WORD;
2297 0 : sc->sc_mbox[1] = i + dest;
2298 0 : sc->sc_mbox[2] = src[i];
2299 0 : if (qla_mbox(sc, 0x07)) {
2300 0 : printf("firmware load failed\n");
2301 0 : return (1);
2302 : }
2303 : }
2304 :
2305 0 : return (qla_verify_firmware(sc, dest));
2306 0 : }
2307 :
2308 : int
2309 0 : qla_load_firmware_2100(struct qla_softc *sc)
2310 : {
2311 0 : return qla_load_firmware_words(sc, isp_2100_risc_code,
2312 : QLA_2100_CODE_ORG);
2313 : }
2314 :
2315 : int
2316 0 : qla_load_firmware_2200(struct qla_softc *sc)
2317 : {
2318 0 : return qla_load_firmware_words(sc, isp_2200_risc_code,
2319 : QLA_2200_CODE_ORG);
2320 : }
2321 :
2322 : int
2323 0 : qla_load_fwchunk_2300(struct qla_softc *sc, struct qla_dmamem *mem,
2324 : const u_int16_t *src, u_int32_t dest)
2325 : {
2326 : u_int16_t origin, done, total;
2327 : int i;
2328 :
2329 0 : origin = dest;
2330 : done = 0;
2331 0 : total = src[3];
2332 :
2333 0 : while (done < total) {
2334 : u_int16_t *copy;
2335 : u_int32_t words;
2336 :
2337 : /* limit transfer size otherwise it just doesn't work */
2338 0 : words = MIN(total - done, 1 << 10);
2339 0 : copy = QLA_DMA_KVA(mem);
2340 0 : for (i = 0; i < words; i++) {
2341 0 : copy[i] = htole16(src[done++]);
2342 : }
2343 0 : bus_dmamap_sync(sc->sc_dmat, QLA_DMA_MAP(mem), 0, words * 2,
2344 : BUS_DMASYNC_PREWRITE);
2345 :
2346 0 : sc->sc_mbox[0] = QLA_MBOX_LOAD_RAM_EXT;
2347 0 : sc->sc_mbox[1] = dest;
2348 0 : sc->sc_mbox[4] = words;
2349 0 : sc->sc_mbox[8] = dest >> 16;
2350 0 : qla_mbox_putaddr(sc->sc_mbox, mem);
2351 0 : if (qla_mbox(sc, 0x01ff)) {
2352 0 : printf("firmware load failed\n");
2353 0 : return (1);
2354 : }
2355 0 : bus_dmamap_sync(sc->sc_dmat, QLA_DMA_MAP(mem), 0, words * 2,
2356 : BUS_DMASYNC_POSTWRITE);
2357 :
2358 0 : dest += words;
2359 0 : }
2360 :
2361 0 : return (qla_verify_firmware(sc, origin));
2362 0 : }
2363 :
2364 : int
2365 0 : qla_load_firmware_2300(struct qla_softc *sc)
2366 : {
2367 : struct qla_dmamem *mem;
2368 : const u_int16_t *fw = isp_2300_risc_code;
2369 : int rv;
2370 :
2371 0 : mem = qla_dmamem_alloc(sc, 65536);
2372 0 : rv = qla_load_fwchunk_2300(sc, mem, fw, QLA_2300_CODE_ORG);
2373 0 : qla_dmamem_free(sc, mem);
2374 :
2375 0 : return (rv);
2376 : }
2377 :
2378 : int
2379 0 : qla_load_firmware_2322(struct qla_softc *sc)
2380 : {
2381 : /* we don't have the 2322 firmware image yet */
2382 : #if 0
2383 : struct qla_dmamem *mem;
2384 : const u_int16_t *fw = isp_2322_risc_code;
2385 : u_int32_t addr;
2386 : int i;
2387 :
2388 : mem = qla_dmamem_alloc(sc, 65536);
2389 : if (qla_load_fwchunk_2300(sc, mem, fw, QLA_2300_CODE_ORG)) {
2390 : qla_dmamem_free(sc, mem);
2391 : return (1);
2392 : }
2393 :
2394 : for (i = 0; i < 2; i++) {
2395 : fw += fw[3];
2396 : addr = fw[5] | ((fw[4] & 0x3f) << 16);
2397 : if (qla_load_fwchunk_2300(sc, mem, fw, addr)) {
2398 : qla_dmamem_free(sc, mem);
2399 : return (1);
2400 : }
2401 : }
2402 :
2403 : qla_dmamem_free(sc, mem);
2404 : #endif
2405 0 : return (0);
2406 : }
2407 :
2408 : #endif /* !ISP_NOFIRMWARE */
2409 :
2410 : int
2411 0 : qla_read_nvram(struct qla_softc *sc)
2412 : {
2413 0 : u_int16_t data[sizeof(sc->sc_nvram) >> 1];
2414 : u_int16_t req, cmd, val;
2415 : u_int8_t csum;
2416 : int i, base, bit;
2417 :
2418 0 : base = sc->sc_port * 0x80;
2419 :
2420 0 : qla_write(sc, QLA_NVRAM, QLA_NVRAM_CHIP_SEL);
2421 0 : delay(10);
2422 0 : qla_write(sc, QLA_NVRAM, QLA_NVRAM_CHIP_SEL | QLA_NVRAM_CLOCK);
2423 0 : delay(10);
2424 :
2425 0 : for (i = 0; i < nitems(data); i++) {
2426 0 : req = (i + base) | (QLA_NVRAM_CMD_READ << 8);
2427 :
2428 : /* write each bit out through the nvram register */
2429 0 : for (bit = 10; bit >= 0; bit--) {
2430 : cmd = QLA_NVRAM_CHIP_SEL;
2431 0 : if ((req >> bit) & 1) {
2432 : cmd |= QLA_NVRAM_DATA_OUT;
2433 0 : }
2434 0 : qla_write(sc, QLA_NVRAM, cmd);
2435 0 : delay(10);
2436 0 : qla_read(sc, QLA_NVRAM);
2437 :
2438 0 : qla_write(sc, QLA_NVRAM, cmd | QLA_NVRAM_CLOCK);
2439 0 : delay(10);
2440 0 : qla_read(sc, QLA_NVRAM);
2441 :
2442 0 : qla_write(sc, QLA_NVRAM, cmd);
2443 0 : delay(10);
2444 0 : qla_read(sc, QLA_NVRAM);
2445 : }
2446 :
2447 : /* read the result back */
2448 : val = 0;
2449 0 : for (bit = 0; bit < 16; bit++) {
2450 0 : val <<= 1;
2451 0 : qla_write(sc, QLA_NVRAM, QLA_NVRAM_CHIP_SEL |
2452 : QLA_NVRAM_CLOCK);
2453 0 : delay(10);
2454 0 : if (qla_read(sc, QLA_NVRAM) & QLA_NVRAM_DATA_IN)
2455 0 : val |= 1;
2456 0 : delay(10);
2457 :
2458 0 : qla_write(sc, QLA_NVRAM, QLA_NVRAM_CHIP_SEL);
2459 0 : delay(10);
2460 0 : qla_read(sc, QLA_NVRAM);
2461 : }
2462 :
2463 0 : qla_write(sc, QLA_NVRAM, 0);
2464 0 : delay(10);
2465 0 : qla_read(sc, QLA_NVRAM);
2466 :
2467 0 : data[i] = letoh16(val);
2468 : }
2469 :
2470 : csum = 0;
2471 0 : for (i = 0; i < nitems(data); i++) {
2472 0 : csum += data[i] & 0xff;
2473 0 : csum += data[i] >> 8;
2474 : }
2475 :
2476 0 : memcpy(&sc->sc_nvram, data, sizeof(sc->sc_nvram));
2477 : /* id field should be 'ISP ', version should be at least 1 */
2478 0 : if (sc->sc_nvram.id[0] != 'I' || sc->sc_nvram.id[1] != 'S' ||
2479 0 : sc->sc_nvram.id[2] != 'P' || sc->sc_nvram.id[3] != ' ' ||
2480 0 : sc->sc_nvram.nvram_version < 1 || (csum != 0)) {
2481 : /*
2482 : * onboard 2200s on Sun hardware don't have an nvram
2483 : * fitted, but will provide us with node and port name
2484 : * through Open Firmware; don't complain in that case.
2485 : */
2486 0 : if (sc->sc_node_name == 0 || sc->sc_port_name == 0)
2487 0 : printf("%s: nvram corrupt\n", DEVNAME(sc));
2488 0 : return (1);
2489 : }
2490 0 : return (0);
2491 0 : }
2492 :
2493 : struct qla_dmamem *
2494 0 : qla_dmamem_alloc(struct qla_softc *sc, size_t size)
2495 : {
2496 : struct qla_dmamem *m;
2497 0 : int nsegs;
2498 :
2499 0 : m = malloc(sizeof(*m), M_DEVBUF, M_NOWAIT | M_ZERO);
2500 0 : if (m == NULL)
2501 0 : return (NULL);
2502 :
2503 0 : m->qdm_size = size;
2504 :
2505 0 : if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
2506 0 : BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &m->qdm_map) != 0)
2507 : goto qdmfree;
2508 :
2509 0 : if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &m->qdm_seg, 1,
2510 0 : &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0)
2511 : goto destroy;
2512 :
2513 0 : if (bus_dmamem_map(sc->sc_dmat, &m->qdm_seg, nsegs, size, &m->qdm_kva,
2514 0 : BUS_DMA_NOWAIT) != 0)
2515 : goto free;
2516 :
2517 0 : if (bus_dmamap_load(sc->sc_dmat, m->qdm_map, m->qdm_kva, size, NULL,
2518 0 : BUS_DMA_NOWAIT) != 0)
2519 : goto unmap;
2520 :
2521 0 : return (m);
2522 :
2523 : unmap:
2524 0 : bus_dmamem_unmap(sc->sc_dmat, m->qdm_kva, m->qdm_size);
2525 : free:
2526 0 : bus_dmamem_free(sc->sc_dmat, &m->qdm_seg, 1);
2527 : destroy:
2528 0 : bus_dmamap_destroy(sc->sc_dmat, m->qdm_map);
2529 : qdmfree:
2530 0 : free(m, M_DEVBUF, sizeof(*m));
2531 :
2532 0 : return (NULL);
2533 0 : }
2534 :
2535 : void
2536 0 : qla_dmamem_free(struct qla_softc *sc, struct qla_dmamem *m)
2537 : {
2538 0 : bus_dmamap_unload(sc->sc_dmat, m->qdm_map);
2539 0 : bus_dmamem_unmap(sc->sc_dmat, m->qdm_kva, m->qdm_size);
2540 0 : bus_dmamem_free(sc->sc_dmat, &m->qdm_seg, 1);
2541 0 : bus_dmamap_destroy(sc->sc_dmat, m->qdm_map);
2542 0 : free(m, M_DEVBUF, sizeof(*m));
2543 0 : }
2544 :
2545 : int
2546 0 : qla_alloc_ccbs(struct qla_softc *sc)
2547 : {
2548 : struct qla_ccb *ccb;
2549 : u_int8_t *cmd;
2550 : int i;
2551 :
2552 0 : SIMPLEQ_INIT(&sc->sc_ccb_free);
2553 0 : mtx_init(&sc->sc_ccb_mtx, IPL_BIO);
2554 0 : mtx_init(&sc->sc_queue_mtx, IPL_BIO);
2555 0 : mtx_init(&sc->sc_port_mtx, IPL_BIO);
2556 0 : mtx_init(&sc->sc_mbox_mtx, IPL_BIO);
2557 :
2558 0 : sc->sc_ccbs = mallocarray(sc->sc_maxcmds, sizeof(struct qla_ccb),
2559 : M_DEVBUF, M_WAITOK | M_CANFAIL | M_ZERO);
2560 0 : if (sc->sc_ccbs == NULL) {
2561 0 : printf("%s: unable to allocate ccbs\n", DEVNAME(sc));
2562 0 : return (1);
2563 : }
2564 :
2565 0 : sc->sc_requests = qla_dmamem_alloc(sc, sc->sc_maxcmds *
2566 : QLA_QUEUE_ENTRY_SIZE);
2567 0 : if (sc->sc_requests == NULL) {
2568 0 : printf("%s: unable to allocate ccb dmamem\n", DEVNAME(sc));
2569 0 : goto free_ccbs;
2570 : }
2571 0 : sc->sc_responses = qla_dmamem_alloc(sc, sc->sc_maxcmds *
2572 : QLA_QUEUE_ENTRY_SIZE);
2573 0 : if (sc->sc_responses == NULL) {
2574 0 : printf("%s: unable to allocate rcb dmamem\n", DEVNAME(sc));
2575 0 : goto free_req;
2576 : }
2577 0 : sc->sc_segments = qla_dmamem_alloc(sc, sc->sc_maxcmds * QLA_MAX_SEGS *
2578 : sizeof(struct qla_iocb_seg));
2579 0 : if (sc->sc_segments == NULL) {
2580 0 : printf("%s: unable to allocate iocb segments\n", DEVNAME(sc));
2581 0 : goto free_res;
2582 : }
2583 :
2584 0 : cmd = QLA_DMA_KVA(sc->sc_requests);
2585 0 : memset(cmd, 0, QLA_QUEUE_ENTRY_SIZE * sc->sc_maxcmds);
2586 0 : for (i = 0; i < sc->sc_maxcmds; i++) {
2587 0 : ccb = &sc->sc_ccbs[i];
2588 :
2589 0 : if (bus_dmamap_create(sc->sc_dmat, MAXPHYS,
2590 : QLA_MAX_SEGS, MAXPHYS, 0,
2591 : BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
2592 0 : &ccb->ccb_dmamap) != 0) {
2593 0 : printf("%s: unable to create dma map\n", DEVNAME(sc));
2594 : goto free_maps;
2595 : }
2596 :
2597 0 : ccb->ccb_sc = sc;
2598 0 : ccb->ccb_id = i;
2599 :
2600 0 : ccb->ccb_seg_offset = i * QLA_MAX_SEGS *
2601 : sizeof(struct qla_iocb_seg);
2602 0 : htolem64(&ccb->ccb_seg_dva,
2603 : QLA_DMA_DVA(sc->sc_segments) + ccb->ccb_seg_offset);
2604 0 : ccb->ccb_t4segs = QLA_DMA_KVA(sc->sc_segments) +
2605 0 : ccb->ccb_seg_offset;
2606 :
2607 0 : qla_put_ccb(sc, ccb);
2608 : }
2609 :
2610 0 : scsi_iopool_init(&sc->sc_iopool, sc, qla_get_ccb, qla_put_ccb);
2611 0 : return (0);
2612 :
2613 : free_maps:
2614 0 : while ((ccb = qla_get_ccb(sc)) != NULL)
2615 0 : bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
2616 :
2617 0 : qla_dmamem_free(sc, sc->sc_segments);
2618 : free_res:
2619 0 : qla_dmamem_free(sc, sc->sc_responses);
2620 : free_req:
2621 0 : qla_dmamem_free(sc, sc->sc_requests);
2622 : free_ccbs:
2623 0 : free(sc->sc_ccbs, M_DEVBUF, 0);
2624 :
2625 0 : return (1);
2626 0 : }
2627 :
2628 : void
2629 0 : qla_free_ccbs(struct qla_softc *sc)
2630 : {
2631 : struct qla_ccb *ccb;
2632 :
2633 0 : scsi_iopool_destroy(&sc->sc_iopool);
2634 0 : while ((ccb = qla_get_ccb(sc)) != NULL)
2635 0 : bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
2636 0 : qla_dmamem_free(sc, sc->sc_segments);
2637 0 : qla_dmamem_free(sc, sc->sc_responses);
2638 0 : qla_dmamem_free(sc, sc->sc_requests);
2639 0 : free(sc->sc_ccbs, M_DEVBUF, 0);
2640 0 : }
2641 :
2642 : void *
2643 0 : qla_get_ccb(void *xsc)
2644 : {
2645 0 : struct qla_softc *sc = xsc;
2646 : struct qla_ccb *ccb;
2647 :
2648 0 : mtx_enter(&sc->sc_ccb_mtx);
2649 0 : ccb = SIMPLEQ_FIRST(&sc->sc_ccb_free);
2650 0 : if (ccb != NULL) {
2651 0 : SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ccb_link);
2652 : }
2653 0 : mtx_leave(&sc->sc_ccb_mtx);
2654 0 : return (ccb);
2655 : }
2656 :
2657 : void
2658 0 : qla_put_ccb(void *xsc, void *io)
2659 : {
2660 0 : struct qla_softc *sc = xsc;
2661 0 : struct qla_ccb *ccb = io;
2662 :
2663 0 : ccb->ccb_xs = NULL;
2664 0 : mtx_enter(&sc->sc_ccb_mtx);
2665 0 : SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ccb, ccb_link);
2666 0 : mtx_leave(&sc->sc_ccb_mtx);
2667 0 : }
|