LCOV - code coverage report
Current view: top level - dev/ic - qla.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1242 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 57 0.0 %
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.13