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

          Line data    Source code
       1             : /*      $OpenBSD: qle.c,v 1.45 2018/07/30 07:34:37 jmatthew Exp $ */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2013, 2014 Jonathan Matthew <jmatthew@openbsd.org>
       5             :  *
       6             :  * Permission to use, copy, modify, and distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : #include "bio.h"
      20             : 
      21             : #include <sys/param.h>
      22             : #include <sys/systm.h>
      23             : #include <sys/atomic.h>
      24             : #include <sys/malloc.h>
      25             : #include <sys/device.h>
      26             : #include <sys/sensors.h>
      27             : #include <sys/rwlock.h>
      28             : #include <sys/task.h>
      29             : #include <sys/timeout.h>
      30             : 
      31             : #include <machine/bus.h>
      32             : 
      33             : #include <dev/pci/pcireg.h>
      34             : #include <dev/pci/pcivar.h>
      35             : #include <dev/pci/pcidevs.h>
      36             : 
      37             : #ifdef __sparc64__
      38             : #include <dev/ofw/openfirm.h>
      39             : #endif
      40             : 
      41             : #include <scsi/scsi_all.h>
      42             : #include <scsi/scsiconf.h>
      43             : 
      44             : #include <dev/pci/qlereg.h>
      45             : 
      46             : #ifdef QLE_DEBUG
      47             : #define DPRINTF(m, f...) do { if ((qledebug & (m)) == (m)) printf(f); } \
      48             :     while (0)
      49             : #define QLE_D_MBOX              0x01
      50             : #define QLE_D_INTR              0x02
      51             : #define QLE_D_PORT              0x04
      52             : #define QLE_D_IO                0x08
      53             : #define QLE_D_IOCB              0x10
      54             : int qledebug = QLE_D_PORT;
      55             : #else
      56             : #define DPRINTF(m, f...)
      57             : #endif
      58             : 
      59             : #ifndef QLE_NOFIRMWARE
      60             : #include <dev/microcode/isp/asm_2400.h>
      61             : #include <dev/microcode/isp/asm_2500.h>
      62             : #endif
      63             : 
      64             : #define QLE_PCI_MEM_BAR         0x14
      65             : #define QLE_PCI_IO_BAR          0x10
      66             : 
      67             : 
      68             : #define QLE_DEFAULT_PORT_NAME           0x400000007F000003ULL /* from isp(4) */
      69             : 
      70             : #define QLE_WAIT_FOR_LOOP               10      /* seconds */
      71             : #define QLE_LOOP_SETTLE                 200     /* ms */
      72             : 
      73             : /* rounded up range of assignable handles */
      74             : #define QLE_MAX_TARGETS                 2048
      75             : 
      76             : /* maximum number of segments allowed for in a single io */
      77             : #define QLE_MAX_SEGS                    32
      78             : 
      79             : enum qle_isp_gen {
      80             :         QLE_GEN_ISP24XX = 1,
      81             :         QLE_GEN_ISP25XX
      82             : };
      83             : 
      84             : enum qle_isp_type {
      85             :         QLE_ISP2422 = 1,
      86             :         QLE_ISP2432,
      87             :         QLE_ISP2512,
      88             :         QLE_ISP2522,
      89             :         QLE_ISP2532
      90             : };
      91             : 
      92             : /* port database things */
      93             : #define QLE_SCRATCH_SIZE                0x1000
      94             : 
      95             : enum qle_port_disp {
      96             :         QLE_PORT_DISP_NEW,
      97             :         QLE_PORT_DISP_GONE,
      98             :         QLE_PORT_DISP_SAME,
      99             :         QLE_PORT_DISP_CHANGED,
     100             :         QLE_PORT_DISP_MOVED,
     101             :         QLE_PORT_DISP_DUP
     102             : };
     103             : 
     104             : #define QLE_LOCATION_LOOP               (1 << 24)
     105             : #define QLE_LOCATION_FABRIC             (2 << 24)
     106             : #define QLE_LOCATION_LOOP_ID(l)         (l | QLE_LOCATION_LOOP)
     107             : #define QLE_LOCATION_PORT_ID(p)         (p | QLE_LOCATION_FABRIC)
     108             : 
     109             : struct qle_fc_port {
     110             :         TAILQ_ENTRY(qle_fc_port) ports;
     111             :         TAILQ_ENTRY(qle_fc_port) update;
     112             : 
     113             :         u_int64_t       node_name;
     114             :         u_int64_t       port_name;
     115             :         u_int32_t       location;       /* port id or loop id */
     116             : 
     117             :         int             flags;
     118             : #define QLE_PORT_FLAG_IS_TARGET         1
     119             : #define QLE_PORT_FLAG_NEEDS_LOGIN       2
     120             : 
     121             :         u_int32_t       portid;
     122             :         u_int16_t       loopid;
     123             : };
     124             : 
     125             : 
     126             : /* request/response queue stuff */
     127             : #define QLE_QUEUE_ENTRY_SIZE            64
     128             : 
     129             : struct qle_ccb {
     130             :         struct qle_softc        *ccb_sc;
     131             :         int                     ccb_id;
     132             :         struct scsi_xfer        *ccb_xs;
     133             : 
     134             :         bus_dmamap_t            ccb_dmamap;
     135             : 
     136             :         struct qle_iocb_seg     *ccb_segs;
     137             :         u_int64_t               ccb_seg_offset;
     138             : 
     139             :         SIMPLEQ_ENTRY(qle_ccb)  ccb_link;
     140             : };
     141             : 
     142             : SIMPLEQ_HEAD(qle_ccb_list, qle_ccb);
     143             : 
     144             : struct qle_dmamem {
     145             :         bus_dmamap_t            qdm_map;
     146             :         bus_dma_segment_t       qdm_seg;
     147             :         size_t                  qdm_size;
     148             :         caddr_t                 qdm_kva;
     149             : };
     150             : #define QLE_DMA_MAP(_qdm)       ((_qdm)->qdm_map)
     151             : #define QLE_DMA_LEN(_qdm)       ((_qdm)->qdm_size)
     152             : #define QLE_DMA_DVA(_qdm)       ((u_int64_t)(_qdm)->qdm_map->dm_segs[0].ds_addr)
     153             : #define QLE_DMA_KVA(_qdm)       ((void *)(_qdm)->qdm_kva)
     154             : 
     155             : struct qle_softc {
     156             :         struct device           sc_dev;
     157             : 
     158             :         pci_chipset_tag_t       sc_pc;
     159             :         pcitag_t                sc_tag;
     160             : 
     161             :         void                    *sc_ih;
     162             :         bus_space_tag_t         sc_iot;
     163             :         bus_space_handle_t      sc_ioh;
     164             :         bus_size_t              sc_ios;
     165             :         bus_dma_tag_t           sc_dmat;
     166             : 
     167             :         struct scsi_link        sc_link;
     168             : 
     169             :         struct scsibus_softc    *sc_scsibus;
     170             : 
     171             :         enum qle_isp_type       sc_isp_type;
     172             :         enum qle_isp_gen        sc_isp_gen;
     173             :         int                     sc_port;
     174             : 
     175             :         bus_space_handle_t      sc_mbox_ioh;
     176             :         u_int16_t               sc_mbox[QLE_MBOX_COUNT];
     177             :         int                     sc_mbox_pending;
     178             :         struct mutex            sc_mbox_mtx;
     179             : 
     180             :         int                     sc_loop_up;
     181             :         int                     sc_topology;
     182             :         int                     sc_loop_id;
     183             :         int                     sc_port_id;
     184             :         int                     sc_loop_max_id;
     185             :         u_int64_t               sc_sns_port_name;
     186             : 
     187             :         struct mutex            sc_port_mtx;
     188             :         TAILQ_HEAD(, qle_fc_port) sc_ports;
     189             :         TAILQ_HEAD(, qle_fc_port) sc_ports_new;
     190             :         TAILQ_HEAD(, qle_fc_port) sc_ports_gone;
     191             :         TAILQ_HEAD(, qle_fc_port) sc_ports_found;
     192             :         struct qle_fc_port      *sc_targets[QLE_MAX_TARGETS];
     193             : 
     194             :         struct taskq            *sc_update_taskq;
     195             :         struct task             sc_update_task;
     196             :         struct timeout          sc_update_timeout;
     197             :         int                     sc_update;
     198             :         int                     sc_update_tasks;
     199             : #define QLE_UPDATE_TASK_CLEAR_ALL       0x00000001
     200             : #define QLE_UPDATE_TASK_SOFTRESET       0x00000002
     201             : #define QLE_UPDATE_TASK_UPDATE_TOPO     0x00000004
     202             : #define QLE_UPDATE_TASK_GET_PORT_LIST   0x00000008
     203             : #define QLE_UPDATE_TASK_PORT_LIST       0x00000010
     204             : #define QLE_UPDATE_TASK_SCAN_FABRIC     0x00000020
     205             : #define QLE_UPDATE_TASK_SCANNING_FABRIC 0x00000040
     206             : #define QLE_UPDATE_TASK_FABRIC_LOGIN    0x00000080
     207             : #define QLE_UPDATE_TASK_FABRIC_RELOGIN  0x00000100
     208             : #define QLE_UPDATE_TASK_DETACH_TARGET   0x00000200
     209             : #define QLE_UPDATE_TASK_ATTACH_TARGET   0x00000400
     210             : 
     211             :         int                     sc_maxcmds;
     212             :         struct qle_dmamem       *sc_requests;
     213             :         struct qle_dmamem       *sc_responses;
     214             :         struct qle_dmamem       *sc_segments;
     215             :         struct qle_dmamem       *sc_pri_requests;
     216             :         struct qle_dmamem       *sc_scratch;
     217             :         struct qle_dmamem       *sc_fcp_cmnds;
     218             :         struct qle_ccb          *sc_ccbs;
     219             :         struct qle_ccb_list     sc_ccb_free;
     220             :         struct mutex            sc_ccb_mtx;
     221             :         struct mutex            sc_queue_mtx;
     222             :         struct scsi_iopool      sc_iopool;
     223             :         u_int32_t               sc_next_req_id;
     224             :         u_int32_t               sc_last_resp_id;
     225             :         int                     sc_marker_required;
     226             :         int                     sc_fabric_pending;
     227             :         u_int8_t                sc_fabric_response[QLE_QUEUE_ENTRY_SIZE];
     228             : 
     229             :         struct qle_nvram        sc_nvram;
     230             :         int                     sc_nvram_valid;
     231             : };
     232             : #define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname)
     233             : 
     234             : int     qle_intr(void *);
     235             : 
     236             : int     qle_match(struct device *, void *, void *);
     237             : void    qle_attach(struct device *, struct device *, void *);
     238             : int     qle_detach(struct device *, int);
     239             : 
     240             : struct cfattach qle_ca = {
     241             :         sizeof(struct qle_softc),
     242             :         qle_match,
     243             :         qle_attach,
     244             :         qle_detach
     245             : };
     246             : 
     247             : struct cfdriver qle_cd = {
     248             :         NULL,
     249             :         "qle",
     250             :         DV_DULL
     251             : };
     252             : 
     253             : void            qle_scsi_cmd(struct scsi_xfer *);
     254             : int             qle_scsi_probe(struct scsi_link *);
     255             : 
     256             : 
     257             : struct scsi_adapter qle_switch = {
     258             :         qle_scsi_cmd,
     259             :         scsi_minphys,
     260             :         qle_scsi_probe,
     261             :         NULL,   /* scsi_free */
     262             :         NULL    /* ioctl */
     263             : };
     264             : 
     265             : u_int32_t       qle_read(struct qle_softc *, int);
     266             : void            qle_write(struct qle_softc *, int, u_int32_t);
     267             : void            qle_host_cmd(struct qle_softc *sc, u_int32_t);
     268             : 
     269             : int             qle_mbox(struct qle_softc *, int);
     270             : int             qle_ct_pass_through(struct qle_softc *sc,
     271             :                     u_int32_t port_handle, struct qle_dmamem *mem,
     272             :                     size_t req_size, size_t resp_size);
     273             : void            qle_mbox_putaddr(u_int16_t *, struct qle_dmamem *);
     274             : u_int16_t       qle_read_mbox(struct qle_softc *, int);
     275             : void            qle_write_mbox(struct qle_softc *, int, u_int16_t);
     276             : 
     277             : void            qle_handle_intr(struct qle_softc *, u_int16_t, u_int16_t);
     278             : void            qle_set_ints(struct qle_softc *, int);
     279             : int             qle_read_isr(struct qle_softc *, u_int16_t *, u_int16_t *);
     280             : void            qle_clear_isr(struct qle_softc *, u_int16_t);
     281             : 
     282             : void            qle_put_marker(struct qle_softc *, void *);
     283             : void            qle_put_cmd(struct qle_softc *, void *, struct scsi_xfer *,
     284             :                     struct qle_ccb *, u_int32_t);
     285             : struct qle_ccb *qle_handle_resp(struct qle_softc *, u_int32_t);
     286             : void            qle_sge(struct qle_iocb_seg *, u_int64_t, u_int32_t);
     287             : 
     288             : struct qle_fc_port *qle_next_fabric_port(struct qle_softc *, u_int32_t *,
     289             :                     u_int32_t *);
     290             : int             qle_get_port_db(struct qle_softc *, u_int16_t,
     291             :                     struct qle_dmamem *);
     292             : int             qle_get_port_name_list(struct qle_softc *sc, u_int32_t);
     293             : int             qle_add_loop_port(struct qle_softc *, struct qle_fc_port *);
     294             : int             qle_add_fabric_port(struct qle_softc *, struct qle_fc_port *);
     295             : int             qle_add_logged_in_port(struct qle_softc *, u_int16_t,
     296             :                     u_int32_t);
     297             : int             qle_classify_port(struct qle_softc *, u_int32_t, u_int64_t,
     298             :                     u_int64_t, struct qle_fc_port **);
     299             : int             qle_get_loop_id(struct qle_softc *sc, int);
     300             : void            qle_clear_port_lists(struct qle_softc *);
     301             : int             qle_softreset(struct qle_softc *);
     302             : void            qle_update_topology(struct qle_softc *);
     303             : int             qle_update_fabric(struct qle_softc *);
     304             : int             qle_fabric_plogx(struct qle_softc *, struct qle_fc_port *, int,
     305             :                     u_int32_t *);
     306             : int             qle_fabric_plogi(struct qle_softc *, struct qle_fc_port *);
     307             : void            qle_fabric_plogo(struct qle_softc *, struct qle_fc_port *);
     308             : 
     309             : void            qle_update_start(struct qle_softc *, int);
     310             : void            qle_update_defer(struct qle_softc *, int);
     311             : void            qle_update_cancel(struct qle_softc *);
     312             : void            qle_update_done(struct qle_softc *, int);
     313             : void            qle_do_update(void *);
     314             : void            qle_deferred_update(void *);
     315             : int             qle_async(struct qle_softc *, u_int16_t);
     316             : 
     317             : int             qle_load_fwchunk(struct qle_softc *,
     318             :                     struct qle_dmamem *, const u_int32_t *);
     319             : u_int32_t       qle_read_ram_word(struct qle_softc *, u_int32_t);
     320             : int             qle_verify_firmware(struct qle_softc *, u_int32_t);
     321             : int             qle_load_firmware_chunks(struct qle_softc *, const u_int32_t *);
     322             : int             qle_read_nvram(struct qle_softc *);
     323             : 
     324             : struct qle_dmamem *qle_dmamem_alloc(struct qle_softc *, size_t);
     325             : void            qle_dmamem_free(struct qle_softc *, struct qle_dmamem *);
     326             : 
     327             : int             qle_alloc_ccbs(struct qle_softc *);
     328             : void            qle_free_ccbs(struct qle_softc *);
     329             : void            *qle_get_ccb(void *);
     330             : void            qle_put_ccb(void *, void *);
     331             : 
     332             : void            qle_dump_stuff(struct qle_softc *, void *, int);
     333             : void            qle_dump_iocb(struct qle_softc *, void *);
     334             : void            qle_dump_iocb_segs(struct qle_softc *, void *, int);
     335             : 
     336             : static const struct pci_matchid qle_devices[] = {
     337             :         { PCI_VENDOR_QLOGIC,    PCI_PRODUCT_QLOGIC_ISP2422 },
     338             :         { PCI_VENDOR_QLOGIC,    PCI_PRODUCT_QLOGIC_ISP2432 },
     339             :         { PCI_VENDOR_QLOGIC,    PCI_PRODUCT_QLOGIC_ISP2512 },
     340             :         { PCI_VENDOR_QLOGIC,    PCI_PRODUCT_QLOGIC_ISP2522 },
     341             :         { PCI_VENDOR_QLOGIC,    PCI_PRODUCT_QLOGIC_ISP2532 },
     342             : };
     343             : 
     344             : int
     345           0 : qle_match(struct device *parent, void *match, void *aux)
     346             : {
     347           0 :         return (pci_matchbyid(aux, qle_devices, nitems(qle_devices)));
     348             : }
     349             : 
     350             : void
     351           0 : qle_attach(struct device *parent, struct device *self, void *aux)
     352             : {
     353           0 :         struct qle_softc *sc = (void *)self;
     354           0 :         struct pci_attach_args *pa = aux;
     355           0 :         pci_intr_handle_t ih;
     356             :         const char *intrstr;
     357             :         u_int32_t pcictl;
     358           0 :         struct scsibus_attach_args saa;
     359             :         struct qle_init_cb *icb;
     360             :         bus_size_t mbox_base;
     361             :         u_int32_t firmware_addr;
     362             : #ifndef QLE_NOFIRMWARE
     363             :         const u_int32_t *firmware = NULL;
     364             : #endif
     365             : 
     366           0 :         pcireg_t bars[] = { QLE_PCI_MEM_BAR, QLE_PCI_IO_BAR };
     367             :         pcireg_t memtype;
     368             :         int r, i, rv, loop_up;
     369             : 
     370           0 :         sc->sc_pc = pa->pa_pc;
     371           0 :         sc->sc_tag = pa->pa_tag;
     372           0 :         sc->sc_ih = NULL;
     373           0 :         sc->sc_dmat = pa->pa_dmat;
     374           0 :         sc->sc_ios = 0;
     375             : 
     376           0 :         for (r = 0; r < nitems(bars); r++) {
     377           0 :                 memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, bars[r]);
     378           0 :                 if (pci_mapreg_map(pa, bars[r], memtype, 0,
     379           0 :                     &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_ios, 0) == 0)
     380             :                         break;
     381             : 
     382           0 :                 sc->sc_ios = 0;
     383             :         }
     384           0 :         if (sc->sc_ios == 0) {
     385           0 :                 printf(": unable to map registers\n");
     386           0 :                 return;
     387             :         }
     388             : 
     389           0 :         if (pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) {
     390           0 :                 printf(": unable to map interrupt\n");
     391           0 :                 goto unmap;
     392             :         }
     393           0 :         intrstr = pci_intr_string(sc->sc_pc, ih);
     394           0 :         sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_BIO,
     395           0 :             qle_intr, sc, DEVNAME(sc));
     396           0 :         if (sc->sc_ih == NULL) {
     397           0 :                 printf(": unable to establish interrupt");
     398           0 :                 if (intrstr != NULL)
     399           0 :                         printf(" at %s", intrstr);
     400           0 :                 printf("\n");
     401           0 :                 goto deintr;
     402             :         }
     403             : 
     404           0 :         printf(": %s\n", intrstr);
     405             : 
     406           0 :         pcictl = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
     407           0 :         pcictl |= PCI_COMMAND_INVALIDATE_ENABLE |
     408             :             PCI_COMMAND_PARITY_ENABLE | PCI_COMMAND_SERR_ENABLE;
     409           0 :         pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, pcictl);
     410             : 
     411           0 :         pcictl = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
     412           0 :         pcictl &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
     413           0 :         pcictl &= ~(PCI_CACHELINE_MASK << PCI_CACHELINE_SHIFT);
     414           0 :         pcictl |= (0x80 << PCI_LATTIMER_SHIFT);
     415           0 :         pcictl |= (0x10 << PCI_CACHELINE_SHIFT);
     416           0 :         pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, pcictl);
     417             : 
     418           0 :         pcictl = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG);
     419           0 :         pcictl &= ~1;
     420           0 :         pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, pcictl);
     421             : 
     422           0 :         switch (PCI_PRODUCT(pa->pa_id)) {
     423             :         case PCI_PRODUCT_QLOGIC_ISP2422:
     424           0 :                 sc->sc_isp_type = QLE_ISP2422;
     425           0 :                 sc->sc_isp_gen = QLE_GEN_ISP24XX;
     426           0 :                 break;
     427             :         case PCI_PRODUCT_QLOGIC_ISP2432:
     428           0 :                 sc->sc_isp_type = QLE_ISP2432;
     429           0 :                 sc->sc_isp_gen = QLE_GEN_ISP24XX;
     430           0 :                 break;
     431             :         case PCI_PRODUCT_QLOGIC_ISP2512:
     432           0 :                 sc->sc_isp_type = QLE_ISP2512;
     433           0 :                 sc->sc_isp_gen = QLE_GEN_ISP25XX;
     434           0 :                 break;
     435             :         case PCI_PRODUCT_QLOGIC_ISP2522:
     436           0 :                 sc->sc_isp_type = QLE_ISP2522;
     437           0 :                 sc->sc_isp_gen = QLE_GEN_ISP25XX;
     438           0 :                 break;
     439             :         case PCI_PRODUCT_QLOGIC_ISP2532:
     440           0 :                 sc->sc_isp_type = QLE_ISP2532;
     441           0 :                 sc->sc_isp_gen = QLE_GEN_ISP25XX;
     442           0 :                 break;
     443             : 
     444             :         default:
     445           0 :                 printf("unknown pci id %x", pa->pa_id);
     446           0 :                 goto deintr;
     447             :         }
     448             : 
     449             :         /* these are the same for 24xx and 25xx but may vary later */
     450             :         mbox_base = QLE_MBOX_BASE_24XX;
     451             :         firmware_addr = QLE_2400_CODE_ORG;
     452             : 
     453           0 :         if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, mbox_base,
     454           0 :             sizeof(sc->sc_mbox), &sc->sc_mbox_ioh) != 0) {
     455           0 :                 printf("%s: unable to map mbox registers\n", DEVNAME(sc));
     456           0 :                 goto deintr;
     457             :         }
     458             : 
     459           0 :         sc->sc_port = pa->pa_function;
     460             : 
     461           0 :         TAILQ_INIT(&sc->sc_ports);
     462           0 :         TAILQ_INIT(&sc->sc_ports_new);
     463           0 :         TAILQ_INIT(&sc->sc_ports_gone);
     464           0 :         TAILQ_INIT(&sc->sc_ports_found);
     465             : 
     466             :         /* after reset, mbox regs 1 and 2 contain the string "ISP " */
     467           0 :         if (qle_read_mbox(sc, 1) != 0x4953 ||
     468           0 :             qle_read_mbox(sc, 2) != 0x5020) {
     469             :                 /* try releasing the risc processor */
     470           0 :                 qle_host_cmd(sc, QLE_HOST_CMD_RELEASE);
     471           0 :         }
     472             : 
     473           0 :         qle_host_cmd(sc, QLE_HOST_CMD_PAUSE);
     474           0 :         if (qle_softreset(sc) != 0) {
     475           0 :                 printf("softreset failed\n");
     476           0 :                 goto deintr;
     477             :         }
     478             : 
     479           0 :         if (qle_read_nvram(sc) == 0)
     480           0 :                 sc->sc_nvram_valid = 1;
     481             : 
     482             : #ifdef QLE_NOFIRMWARE
     483             :         if (qle_verify_firmware(sc, firmware_addr)) {
     484             :                 printf("%s: no firmware loaded\n", DEVNAME(sc));
     485             :                 goto deintr;
     486             :         }
     487             : #else
     488           0 :         switch (sc->sc_isp_gen) {
     489             :         case QLE_GEN_ISP24XX:
     490             :                 firmware = isp_2400_risc_code;
     491           0 :                 break;
     492             :         case QLE_GEN_ISP25XX:
     493             :                 firmware = isp_2500_risc_code;
     494           0 :                 break;
     495             :         default:
     496           0 :                 printf("%s: no firmware to load?\n", DEVNAME(sc));
     497           0 :                 goto deintr;
     498             :         }
     499           0 :         if (qle_load_firmware_chunks(sc, firmware)) {
     500           0 :                 printf("%s: firmware load failed\n", DEVNAME(sc));
     501           0 :                 goto deintr;
     502             :         }
     503             : #endif
     504             : 
     505             :         /* execute firmware */
     506           0 :         sc->sc_mbox[0] = QLE_MBOX_EXEC_FIRMWARE;
     507           0 :         sc->sc_mbox[1] = firmware_addr >> 16;
     508           0 :         sc->sc_mbox[2] = firmware_addr & 0xffff;
     509             : #ifdef QLE_NOFIRMWARE
     510             :         sc->sc_mbox[3] = 1;
     511             : #else
     512           0 :         sc->sc_mbox[3] = 0;
     513             : #endif
     514           0 :         sc->sc_mbox[4] = 0;
     515           0 :         if (qle_mbox(sc, 0x001f)) {
     516           0 :                 printf("ISP couldn't exec firmware: %x\n", sc->sc_mbox[0]);
     517           0 :                 goto deintr;
     518             :         }
     519             : 
     520           0 :         delay(250000);          /* from isp(4) */
     521             : 
     522           0 :         sc->sc_mbox[0] = QLE_MBOX_ABOUT_FIRMWARE;
     523           0 :         if (qle_mbox(sc, 0x0001)) {
     524           0 :                 printf("ISP not talking after firmware exec: %x\n",
     525           0 :                     sc->sc_mbox[0]);
     526           0 :                 goto deintr;
     527             :         }
     528           0 :         printf("%s: firmware rev %d.%d.%d, attrs 0x%x\n", DEVNAME(sc),
     529           0 :             sc->sc_mbox[1], sc->sc_mbox[2], sc->sc_mbox[3], sc->sc_mbox[6]);
     530             : 
     531           0 :         sc->sc_maxcmds = 4096;
     532             : 
     533             :         /* reserve queue slots for markers and fabric ops */
     534           0 :         sc->sc_maxcmds -= 2;
     535             : 
     536           0 :         if (qle_alloc_ccbs(sc)) {
     537             :                 /* error already printed */
     538             :                 goto deintr;
     539             :         }
     540           0 :         sc->sc_scratch = qle_dmamem_alloc(sc, QLE_SCRATCH_SIZE);
     541           0 :         if (sc->sc_scratch == NULL) {
     542           0 :                 printf("%s: unable to allocate scratch\n", DEVNAME(sc));
     543           0 :                 goto free_ccbs;
     544             :         }
     545             : 
     546             :         /* build init buffer thing */
     547           0 :         icb = (struct qle_init_cb *)QLE_DMA_KVA(sc->sc_scratch);
     548           0 :         memset(icb, 0, sizeof(*icb));
     549           0 :         icb->icb_version = QLE_ICB_VERSION;
     550           0 :         if (sc->sc_nvram_valid) {
     551           0 :                 icb->icb_max_frame_len = sc->sc_nvram.frame_payload_size;
     552           0 :                 icb->icb_exec_throttle = sc->sc_nvram.execution_throttle;
     553           0 :                 icb->icb_hardaddr = sc->sc_nvram.hard_address;
     554           0 :                 icb->icb_portname = sc->sc_nvram.port_name;
     555           0 :                 icb->icb_nodename = sc->sc_nvram.node_name;
     556           0 :                 icb->icb_login_retry = sc->sc_nvram.login_retry;
     557           0 :                 icb->icb_login_timeout = sc->sc_nvram.login_timeout;
     558           0 :                 icb->icb_fwoptions1 = sc->sc_nvram.fwoptions1;
     559           0 :                 icb->icb_fwoptions2 = sc->sc_nvram.fwoptions2;
     560           0 :                 icb->icb_fwoptions3 = sc->sc_nvram.fwoptions3;
     561           0 :         } else {
     562             :                 /* defaults copied from isp(4) */
     563           0 :                 htolem16(&icb->icb_max_frame_len, 1024);
     564           0 :                 htolem16(&icb->icb_exec_throttle, 16);
     565           0 :                 icb->icb_portname = htobe64(QLE_DEFAULT_PORT_NAME);
     566           0 :                 icb->icb_nodename = 0;
     567           0 :                 icb->icb_login_retry = 3;
     568             : 
     569           0 :                 htolem32(&icb->icb_fwoptions1, QLE_ICB_FW1_FAIRNESS |
     570             :                     QLE_ICB_FW1_HARD_ADDR | QLE_ICB_FW1_FULL_DUPLEX);
     571           0 :                 htolem32(&icb->icb_fwoptions2, QLE_ICB_FW2_LOOP_PTP);
     572           0 :                 htolem32(&icb->icb_fwoptions3, QLE_ICB_FW3_FCP_RSP_24_0 |
     573             :                     QLE_ICB_FW3_AUTONEG);
     574             :         }
     575             : 
     576           0 :         icb->icb_exchange_count = 0;
     577             : 
     578           0 :         icb->icb_req_out = 0;
     579           0 :         icb->icb_resp_in = 0;
     580           0 :         icb->icb_pri_req_out = 0;
     581           0 :         htolem16(&icb->icb_req_queue_len, sc->sc_maxcmds);
     582           0 :         htolem16(&icb->icb_resp_queue_len, sc->sc_maxcmds);
     583           0 :         htolem16(&icb->icb_pri_req_queue_len, 8); /* apparently the minimum */
     584           0 :         htolem32(&icb->icb_req_queue_addr_lo,
     585             :             QLE_DMA_DVA(sc->sc_requests));
     586           0 :         htolem32(&icb->icb_req_queue_addr_hi,
     587             :             QLE_DMA_DVA(sc->sc_requests) >> 32);
     588           0 :         htolem32(&icb->icb_resp_queue_addr_lo,
     589             :             QLE_DMA_DVA(sc->sc_responses));
     590           0 :         htolem32(&icb->icb_resp_queue_addr_hi,
     591             :             QLE_DMA_DVA(sc->sc_responses) >> 32);
     592           0 :         htolem32(&icb->icb_pri_req_queue_addr_lo,
     593             :             QLE_DMA_DVA(sc->sc_pri_requests));
     594           0 :         htolem32(&icb->icb_pri_req_queue_addr_hi,
     595             :             QLE_DMA_DVA(sc->sc_pri_requests) >> 32);
     596             : 
     597           0 :         htolem16(&icb->icb_link_down_nos, 200);
     598           0 :         icb->icb_int_delay = 0;
     599           0 :         icb->icb_login_timeout = 0;
     600             : 
     601           0 :         sc->sc_mbox[0] = QLE_MBOX_INIT_FIRMWARE;
     602           0 :         sc->sc_mbox[4] = 0;
     603           0 :         sc->sc_mbox[5] = 0;
     604           0 :         qle_mbox_putaddr(sc->sc_mbox, sc->sc_scratch);
     605           0 :         bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(sc->sc_scratch), 0,
     606             :             sizeof(*icb), BUS_DMASYNC_PREWRITE);
     607           0 :         rv = qle_mbox(sc, 0x00fd);
     608           0 :         bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(sc->sc_scratch), 0,
     609             :             sizeof(*icb), BUS_DMASYNC_POSTWRITE);
     610             : 
     611           0 :         if (rv != 0) {
     612           0 :                 printf("%s: ISP firmware init failed: %x\n", DEVNAME(sc),
     613           0 :                     sc->sc_mbox[0]);
     614           0 :                 goto free_scratch;
     615             :         }
     616             : 
     617             :         /* enable some more notifications */
     618           0 :         sc->sc_mbox[0] = QLE_MBOX_SET_FIRMWARE_OPTIONS;
     619           0 :         sc->sc_mbox[1] = QLE_FW_OPTION1_ASYNC_LIP_F8 |
     620             :             QLE_FW_OPTION1_ASYNC_LIP_RESET |
     621             :             QLE_FW_OPTION1_ASYNC_LIP_ERROR |
     622             :             QLE_FW_OPTION1_ASYNC_LOGIN_RJT;
     623           0 :         sc->sc_mbox[2] = 0;
     624           0 :         sc->sc_mbox[3] = 0;
     625           0 :         if (qle_mbox(sc, 0x000f)) {
     626           0 :                 printf("%s: setting firmware options failed: %x\n",
     627           0 :                     DEVNAME(sc), sc->sc_mbox[0]);
     628           0 :                 goto free_scratch;
     629             :         }
     630             : 
     631           0 :         sc->sc_update_taskq = taskq_create(DEVNAME(sc), 1, IPL_BIO, 0);
     632           0 :         task_set(&sc->sc_update_task, qle_do_update, sc);
     633           0 :         timeout_set(&sc->sc_update_timeout, qle_deferred_update, sc);
     634             : 
     635             :         /* wait a bit for link to come up so we can scan and attach devices */
     636           0 :         for (i = 0; i < QLE_WAIT_FOR_LOOP * 1000; i++) {
     637           0 :                 u_int16_t isr, info;
     638             : 
     639           0 :                 if (sc->sc_loop_up) {
     640           0 :                         if (++loop_up == QLE_LOOP_SETTLE)
     641           0 :                                 break;
     642             :                 } else
     643             :                         loop_up = 0;
     644             : 
     645           0 :                 delay(1000);
     646             : 
     647           0 :                 if (qle_read_isr(sc, &isr, &info) == 0)
     648           0 :                         continue;
     649             : 
     650           0 :                 qle_handle_intr(sc, isr, info);
     651             : 
     652           0 :         }
     653             : 
     654           0 :         if (sc->sc_loop_up) {
     655           0 :                 qle_do_update(sc);
     656           0 :         } else {
     657             :                 DPRINTF(QLE_D_PORT, "%s: loop still down, giving up\n",
     658             :                     DEVNAME(sc));
     659             :         }
     660             : 
     661             :         /* we should be good to go now, attach scsibus */
     662           0 :         sc->sc_link.adapter = &qle_switch;
     663           0 :         sc->sc_link.adapter_softc = sc;
     664           0 :         sc->sc_link.adapter_target = QLE_MAX_TARGETS;
     665           0 :         sc->sc_link.adapter_buswidth = QLE_MAX_TARGETS;
     666           0 :         sc->sc_link.openings = sc->sc_maxcmds;
     667           0 :         sc->sc_link.pool = &sc->sc_iopool;
     668           0 :         if (sc->sc_nvram_valid) {
     669           0 :                 sc->sc_link.port_wwn = betoh64(sc->sc_nvram.port_name);
     670           0 :                 sc->sc_link.node_wwn = betoh64(sc->sc_nvram.node_name);
     671           0 :         } else {
     672           0 :                 sc->sc_link.port_wwn = QLE_DEFAULT_PORT_NAME;
     673           0 :                 sc->sc_link.node_wwn = 0;
     674             :         }
     675           0 :         if (sc->sc_link.node_wwn == 0) {
     676             :                 /*
     677             :                  * mask out the port number from the port name to get
     678             :                  * the node name.
     679             :                  */
     680           0 :                 sc->sc_link.node_wwn = sc->sc_link.port_wwn;
     681           0 :                 sc->sc_link.node_wwn &= ~(0xfULL << 56);
     682           0 :         }
     683             : 
     684           0 :         memset(&saa, 0, sizeof(saa));
     685           0 :         saa.saa_sc_link = &sc->sc_link;
     686             : 
     687             :         /* config_found() returns the scsibus attached to us */
     688           0 :         sc->sc_scsibus = (struct scsibus_softc *)config_found(&sc->sc_dev,
     689             :             &saa, scsiprint);
     690             : 
     691           0 :         return;
     692             : 
     693             : free_scratch:
     694           0 :         qle_dmamem_free(sc, sc->sc_scratch);
     695             : free_ccbs:
     696           0 :         qle_free_ccbs(sc);
     697             : deintr:
     698           0 :         pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
     699           0 :         sc->sc_ih = NULL;
     700             : unmap:
     701           0 :         bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
     702           0 :         sc->sc_ios = 0;
     703           0 : }
     704             : 
     705             : int
     706           0 : qle_detach(struct device *self, int flags)
     707             : {
     708           0 :         struct qle_softc *sc = (struct qle_softc *)self;
     709             : 
     710           0 :         if (sc->sc_ih == NULL) {
     711             :                 /* we didnt attach properly, so nothing to detach */
     712           0 :                 return (0);
     713             :         }
     714             : 
     715           0 :         pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
     716           0 :         sc->sc_ih = NULL;
     717             : 
     718           0 :         bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
     719           0 :         sc->sc_ios = 0;
     720             : 
     721           0 :         return (0);
     722           0 : }
     723             : 
     724             : int
     725           0 : qle_classify_port(struct qle_softc *sc, u_int32_t location,
     726             :     u_int64_t port_name, u_int64_t node_name, struct qle_fc_port **prev)
     727             : {
     728             :         struct qle_fc_port *port, *locmatch, *wwnmatch;
     729             :         locmatch = NULL;
     730             :         wwnmatch = NULL;
     731             : 
     732             :         /* make sure we don't try to add a port or location twice */
     733           0 :         TAILQ_FOREACH(port, &sc->sc_ports_new, update) {
     734           0 :                 if ((port->port_name == port_name &&
     735           0 :                     port->node_name == node_name) ||
     736           0 :                     port->location == location) {
     737           0 :                         *prev = port;
     738           0 :                         return (QLE_PORT_DISP_DUP);
     739             :                 }
     740             :         }
     741             : 
     742             :         /* if we're attaching, everything is new */
     743           0 :         if (sc->sc_scsibus == NULL) {
     744           0 :                 *prev = NULL;
     745           0 :                 return (QLE_PORT_DISP_NEW);
     746             :         }
     747             : 
     748           0 :         TAILQ_FOREACH(port, &sc->sc_ports, ports) {
     749           0 :                 if (port->location == location)
     750           0 :                         locmatch = port;
     751             : 
     752           0 :                 if (port->port_name == port_name &&
     753           0 :                     port->node_name == node_name)
     754           0 :                         wwnmatch = port;
     755             :         }
     756             : 
     757           0 :         if (locmatch == NULL && wwnmatch == NULL) {
     758           0 :                 *prev = NULL;
     759           0 :                 return (QLE_PORT_DISP_NEW);
     760           0 :         } else if (locmatch == wwnmatch) {
     761           0 :                 *prev = locmatch;
     762           0 :                 return (QLE_PORT_DISP_SAME);
     763           0 :         } else if (wwnmatch != NULL) {
     764           0 :                 *prev = wwnmatch;
     765           0 :                 return (QLE_PORT_DISP_MOVED);
     766             :         } else {
     767           0 :                 *prev = locmatch;
     768           0 :                 return (QLE_PORT_DISP_CHANGED);
     769             :         }
     770           0 : }
     771             : 
     772             : int
     773           0 : qle_get_loop_id(struct qle_softc *sc, int start)
     774             : {
     775             :         int i, last;
     776             : 
     777             :         i = QLE_MIN_HANDLE;
     778             :         last = QLE_MAX_HANDLE;
     779           0 :         if (i < start)
     780           0 :                 i = start;
     781             : 
     782           0 :         for (; i <= last; i++) {
     783           0 :                 if (sc->sc_targets[i] == NULL)
     784           0 :                         return (i);
     785             :         }
     786             : 
     787           0 :         return (-1);
     788           0 : }
     789             : 
     790             : int
     791           0 : qle_get_port_db(struct qle_softc *sc, u_int16_t loopid, struct qle_dmamem *mem)
     792             : {
     793           0 :         sc->sc_mbox[0] = QLE_MBOX_GET_PORT_DB;
     794           0 :         sc->sc_mbox[1] = loopid;
     795           0 :         qle_mbox_putaddr(sc->sc_mbox, mem);
     796           0 :         bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(mem), 0,
     797             :             sizeof(struct qle_get_port_db), BUS_DMASYNC_PREREAD);
     798           0 :         if (qle_mbox(sc, 0x00cf)) {
     799             :                 DPRINTF(QLE_D_PORT, "%s: get port db for %d failed: %x\n",
     800             :                     DEVNAME(sc), loopid, sc->sc_mbox[0]);
     801           0 :                 return (1);
     802             :         }
     803             : 
     804           0 :         bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(mem), 0,
     805             :             sizeof(struct qle_get_port_db), BUS_DMASYNC_POSTREAD);
     806           0 :         return (0);
     807           0 : }
     808             : 
     809             : int
     810           0 : qle_get_port_name_list(struct qle_softc *sc, u_int32_t match)
     811             : {
     812             :         struct qle_port_name_list *l;
     813             :         struct qle_fc_port *port;
     814             :         int i;
     815             : 
     816           0 :         sc->sc_mbox[0] = QLE_MBOX_GET_PORT_NAME_LIST;
     817           0 :         sc->sc_mbox[1] = 0;
     818           0 :         sc->sc_mbox[8] = QLE_DMA_LEN(sc->sc_scratch);
     819           0 :         sc->sc_mbox[9] = 0;
     820           0 :         qle_mbox_putaddr(sc->sc_mbox, sc->sc_scratch);
     821           0 :         bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(sc->sc_scratch), 0,
     822             :             QLE_DMA_LEN(sc->sc_scratch), BUS_DMASYNC_PREREAD);
     823           0 :         if (qle_mbox(sc, 0x03cf)) {
     824             :                 DPRINTF(QLE_D_PORT, "%s: get port name list failed: %x\n",
     825             :                     DEVNAME(sc), sc->sc_mbox[0]);
     826           0 :                 return (1);
     827             :         }
     828           0 :         bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(sc->sc_scratch), 0,
     829             :             sc->sc_mbox[1], BUS_DMASYNC_POSTREAD);
     830             : 
     831             :         i = 0;
     832           0 :         l = QLE_DMA_KVA(sc->sc_scratch);
     833           0 :         mtx_enter(&sc->sc_port_mtx);
     834           0 :         while (i * sizeof(*l) < sc->sc_mbox[1]) {
     835             :                 u_int16_t loopid;
     836             :                 u_int32_t loc;
     837             : 
     838           0 :                 loopid = lemtoh16(&l[i].loopid) & 0xfff;
     839             :                 /* skip special ports */
     840           0 :                 switch (loopid) {
     841             :                 case QLE_F_PORT_HANDLE:
     842             :                 case QLE_SNS_HANDLE:
     843             :                 case QLE_FABRIC_CTRL_HANDLE:
     844             :                 case QLE_IP_BCAST_HANDLE:
     845             :                         loc = 0;
     846           0 :                         break;
     847             :                 default:
     848           0 :                         if (loopid <= sc->sc_loop_max_id) {
     849           0 :                                 loc = QLE_LOCATION_LOOP_ID(loopid);
     850           0 :                         } else {
     851             :                                 /*
     852             :                                  * we don't have the port id here, so just
     853             :                                  * indicate it's a fabric port.
     854             :                                  */
     855             :                                 loc = QLE_LOCATION_FABRIC;
     856             :                         }
     857             :                         break;
     858             :                 }
     859             : 
     860           0 :                 if (match & loc) {
     861           0 :                         port = malloc(sizeof(*port), M_DEVBUF, M_ZERO |
     862             :                             M_NOWAIT);
     863           0 :                         if (port == NULL) {
     864           0 :                                 printf("%s: failed to allocate port struct\n",
     865           0 :                                     DEVNAME(sc));
     866           0 :                                 break;
     867             :                         }
     868           0 :                         port->location = loc;
     869           0 :                         port->loopid = loopid;
     870           0 :                         port->port_name = letoh64(l[i].port_name);
     871             :                         DPRINTF(QLE_D_PORT, "%s: loop id %d, port name %llx\n",
     872             :                             DEVNAME(sc), port->loopid, port->port_name);
     873           0 :                         TAILQ_INSERT_TAIL(&sc->sc_ports_found, port, update);
     874           0 :                 }
     875           0 :                 i++;
     876           0 :         }
     877           0 :         mtx_leave(&sc->sc_port_mtx);
     878             : 
     879           0 :         return (0);
     880           0 : }
     881             : 
     882             : int
     883           0 : qle_add_loop_port(struct qle_softc *sc, struct qle_fc_port *port)
     884             : {
     885             :         struct qle_get_port_db *pdb;
     886           0 :         struct qle_fc_port *pport;
     887             :         int disp;
     888             : 
     889           0 :         if (qle_get_port_db(sc, port->loopid, sc->sc_scratch) != 0) {
     890           0 :                 return (1);
     891             :         }
     892           0 :         pdb = QLE_DMA_KVA(sc->sc_scratch);
     893             : 
     894           0 :         if (lemtoh16(&pdb->prli_svc_word3) & QLE_SVC3_TARGET_ROLE)
     895           0 :                 port->flags |= QLE_PORT_FLAG_IS_TARGET;
     896             : 
     897           0 :         port->port_name = betoh64(pdb->port_name);
     898           0 :         port->node_name = betoh64(pdb->node_name);
     899           0 :         port->portid = (pdb->port_id[0] << 16) | (pdb->port_id[1] << 8) |
     900           0 :             pdb->port_id[2];
     901             : 
     902           0 :         mtx_enter(&sc->sc_port_mtx);
     903           0 :         disp = qle_classify_port(sc, port->location, port->port_name,
     904           0 :             port->node_name, &pport);
     905           0 :         switch (disp) {
     906             :         case QLE_PORT_DISP_CHANGED:
     907             :         case QLE_PORT_DISP_MOVED:
     908             :         case QLE_PORT_DISP_NEW:
     909           0 :                 TAILQ_INSERT_TAIL(&sc->sc_ports_new, port, update);
     910           0 :                 sc->sc_targets[port->loopid] = port;
     911           0 :                 break;
     912             :         case QLE_PORT_DISP_DUP:
     913           0 :                 free(port, M_DEVBUF, sizeof *port);
     914           0 :                 break;
     915             :         case QLE_PORT_DISP_SAME:
     916           0 :                 TAILQ_REMOVE(&sc->sc_ports_gone, pport, update);
     917           0 :                 free(port, M_DEVBUF, sizeof *port);
     918           0 :                 break;
     919             :         }
     920           0 :         mtx_leave(&sc->sc_port_mtx);
     921             : 
     922             :         switch (disp) {
     923             :         case QLE_PORT_DISP_CHANGED:
     924             :         case QLE_PORT_DISP_MOVED:
     925             :         case QLE_PORT_DISP_NEW:
     926             :                 DPRINTF(QLE_D_PORT, "%s: %s %d; name %llx\n",
     927             :                     DEVNAME(sc), ISSET(port->flags, QLE_PORT_FLAG_IS_TARGET) ?
     928             :                     "target" : "non-target", port->loopid,
     929             :                     betoh64(pdb->port_name));
     930             :                 break;
     931             :         default:
     932             :                 break;
     933             :         }
     934           0 :         return (0);
     935           0 : }
     936             : 
     937             : int
     938           0 : qle_add_fabric_port(struct qle_softc *sc, struct qle_fc_port *port)
     939             : {
     940             :         struct qle_get_port_db *pdb;
     941             : 
     942           0 :         if (qle_get_port_db(sc, port->loopid, sc->sc_scratch) != 0) {
     943           0 :                 free(port, M_DEVBUF, sizeof *port);
     944           0 :                 return (1);
     945             :         }
     946           0 :         pdb = QLE_DMA_KVA(sc->sc_scratch);
     947             : 
     948           0 :         if (lemtoh16(&pdb->prli_svc_word3) & QLE_SVC3_TARGET_ROLE)
     949           0 :                 port->flags |= QLE_PORT_FLAG_IS_TARGET;
     950             : 
     951             :         /*
     952             :          * if we only know about this port because qle_get_port_name_list
     953             :          * returned it, we don't have its port id or node name, so fill
     954             :          * those in and update its location.
     955             :          */
     956           0 :         if (port->location == QLE_LOCATION_FABRIC) {
     957           0 :                 port->node_name = betoh64(pdb->node_name);
     958           0 :                 port->port_name = betoh64(pdb->port_name);
     959           0 :                 port->portid = (pdb->port_id[0] << 16) |
     960           0 :                     (pdb->port_id[1] << 8) | pdb->port_id[2];
     961           0 :                 port->location = QLE_LOCATION_PORT_ID(port->portid);
     962           0 :         }
     963             : 
     964           0 :         mtx_enter(&sc->sc_port_mtx);
     965           0 :         TAILQ_INSERT_TAIL(&sc->sc_ports_new, port, update);
     966           0 :         sc->sc_targets[port->loopid] = port;
     967           0 :         mtx_leave(&sc->sc_port_mtx);
     968             : 
     969             :         DPRINTF(QLE_D_PORT, "%s: %s %d; name %llx\n",
     970             :             DEVNAME(sc), ISSET(port->flags, QLE_PORT_FLAG_IS_TARGET) ?
     971             :             "target" : "non-target", port->loopid, port->port_name);
     972           0 :         return (0);
     973           0 : }
     974             : 
     975             : int
     976           0 : qle_add_logged_in_port(struct qle_softc *sc, u_int16_t loopid,
     977             :     u_int32_t portid)
     978             : {
     979             :         struct qle_fc_port *port;
     980             :         struct qle_get_port_db *pdb;
     981             :         u_int64_t node_name, port_name;
     982             :         int flags, ret;
     983             : 
     984           0 :         ret = qle_get_port_db(sc, loopid, sc->sc_scratch);
     985           0 :         mtx_enter(&sc->sc_port_mtx);
     986           0 :         if (ret != 0) {
     987             :                 /* put in a fake port to prevent use of this loop id */
     988           0 :                 printf("%s: loop id %d used, but can't see what's using it\n",
     989           0 :                     DEVNAME(sc), loopid);
     990             :                 node_name = 0;
     991             :                 port_name = 0;
     992             :                 flags = 0;
     993           0 :         } else {
     994           0 :                 pdb = QLE_DMA_KVA(sc->sc_scratch);
     995           0 :                 node_name = betoh64(pdb->node_name);
     996           0 :                 port_name = betoh64(pdb->port_name);
     997             :                 flags = 0;
     998           0 :                 if (lemtoh16(&pdb->prli_svc_word3) & QLE_SVC3_TARGET_ROLE)
     999           0 :                         flags |= QLE_PORT_FLAG_IS_TARGET;
    1000             : 
    1001             :                 /* see if we've already found this port */
    1002           0 :                 TAILQ_FOREACH(port, &sc->sc_ports_found, update) {
    1003           0 :                         if ((port->node_name == node_name) &&
    1004           0 :                             (port->port_name == port_name) &&
    1005           0 :                             (port->portid == portid)) {
    1006           0 :                                 mtx_leave(&sc->sc_port_mtx);
    1007             :                                 DPRINTF(QLE_D_PORT, "%s: already found port "
    1008             :                                     "%06x\n", DEVNAME(sc), portid);
    1009           0 :                                 return (0);
    1010             :                         }
    1011             :                 }
    1012             :         }
    1013             : 
    1014           0 :         port = malloc(sizeof(*port), M_DEVBUF, M_ZERO | M_NOWAIT);
    1015           0 :         if (port == NULL) {
    1016           0 :                 mtx_leave(&sc->sc_port_mtx);
    1017           0 :                 printf("%s: failed to allocate a port structure\n",
    1018           0 :                     DEVNAME(sc));
    1019           0 :                 return (1);
    1020             :         }
    1021           0 :         port->location = QLE_LOCATION_PORT_ID(portid);
    1022           0 :         port->port_name = port_name;
    1023           0 :         port->node_name = node_name;
    1024           0 :         port->loopid = loopid;
    1025           0 :         port->portid = portid;
    1026           0 :         port->flags = flags;
    1027             : 
    1028           0 :         TAILQ_INSERT_TAIL(&sc->sc_ports, port, ports);
    1029           0 :         sc->sc_targets[port->loopid] = port;
    1030           0 :         mtx_leave(&sc->sc_port_mtx);
    1031             : 
    1032             :         DPRINTF(QLE_D_PORT, "%s: added logged in port %06x at %d\n",
    1033             :             DEVNAME(sc), portid, loopid);
    1034           0 :         return (0);
    1035           0 : }
    1036             : 
    1037             : struct qle_ccb *
    1038           0 : qle_handle_resp(struct qle_softc *sc, u_int32_t id)
    1039             : {
    1040             :         struct qle_ccb *ccb;
    1041             :         struct qle_iocb_status *status;
    1042             :         struct qle_iocb_req6 *req;
    1043             :         struct scsi_xfer *xs;
    1044             :         u_int32_t handle;
    1045             :         u_int16_t completion;
    1046             :         u_int8_t *entry;
    1047             :         u_int8_t *data;
    1048             : 
    1049             :         ccb = NULL;
    1050           0 :         entry = QLE_DMA_KVA(sc->sc_responses) + (id * QLE_QUEUE_ENTRY_SIZE);
    1051             :         
    1052           0 :         bus_dmamap_sync(sc->sc_dmat,
    1053             :             QLE_DMA_MAP(sc->sc_responses), id * QLE_QUEUE_ENTRY_SIZE,
    1054             :             QLE_QUEUE_ENTRY_SIZE, BUS_DMASYNC_POSTREAD);
    1055             : 
    1056           0 :         qle_dump_iocb(sc, entry);
    1057           0 :         switch(entry[0]) {
    1058             :         case QLE_IOCB_STATUS:
    1059           0 :                 status = (struct qle_iocb_status *)entry;
    1060           0 :                 handle = status->handle;
    1061           0 :                 if (handle > sc->sc_maxcmds) {
    1062           0 :                         panic("bad completed command handle: %d (> %d)",
    1063             :                             handle, sc->sc_maxcmds);
    1064             :                 }
    1065             : 
    1066           0 :                 ccb = &sc->sc_ccbs[handle];
    1067           0 :                 xs = ccb->ccb_xs;
    1068           0 :                 if (xs == NULL) {
    1069             :                         DPRINTF(QLE_D_IO, "%s: got status for inactive ccb %d\n",
    1070             :                             DEVNAME(sc), handle);
    1071             :                         ccb = NULL;
    1072           0 :                         break;
    1073             :                 }
    1074           0 :                 if (xs->io != ccb) {
    1075           0 :                         panic("completed command handle doesn't match xs "
    1076             :                             "(handle %d, ccb %p, xs->io %p)", handle, ccb,
    1077             :                             xs->io);
    1078             :                 }
    1079             : 
    1080           0 :                 if (xs->datalen > 0) {
    1081           0 :                         if (ccb->ccb_dmamap->dm_nsegs >
    1082             :                             QLE_IOCB_SEGS_PER_CMD) {
    1083           0 :                                 bus_dmamap_sync(sc->sc_dmat,
    1084             :                                     QLE_DMA_MAP(sc->sc_segments),
    1085             :                                     ccb->ccb_seg_offset,
    1086             :                                     sizeof(*ccb->ccb_segs) *
    1087             :                                     ccb->ccb_dmamap->dm_nsegs + 1,
    1088             :                                     BUS_DMASYNC_POSTWRITE);
    1089           0 :                         }
    1090             : 
    1091           0 :                         bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
    1092             :                             ccb->ccb_dmamap->dm_mapsize,
    1093             :                             (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
    1094             :                             BUS_DMASYNC_POSTWRITE);
    1095           0 :                         bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
    1096           0 :                 }
    1097             : 
    1098           0 :                 xs->status = lemtoh16(&status->scsi_status) & 0xff;
    1099           0 :                 xs->resid = 0;
    1100           0 :                 completion = lemtoh16(&status->completion);
    1101           0 :                 switch (completion) {
    1102             :                 case QLE_IOCB_STATUS_DATA_UNDERRUN:
    1103           0 :                         xs->resid = lemtoh32(&status->resid);
    1104             :                 case QLE_IOCB_STATUS_DATA_OVERRUN:
    1105             :                 case QLE_IOCB_STATUS_COMPLETE:
    1106           0 :                         if (lemtoh16(&status->scsi_status) &
    1107             :                             QLE_SCSI_STATUS_SENSE_VALID) {
    1108             :                                 u_int32_t *pp;
    1109             :                                 int sr;
    1110           0 :                                 data = status->data +
    1111           0 :                                     lemtoh32(&status->fcp_rsp_len);
    1112           0 :                                 sr = MIN(lemtoh32(&status->fcp_sense_len),
    1113             :                                     sizeof(xs->sense));
    1114           0 :                                 memcpy(&xs->sense, data, sr);
    1115           0 :                                 xs->error = XS_SENSE;
    1116           0 :                                 pp = (u_int32_t *)&xs->sense;
    1117           0 :                                 for (sr = 0; sr < sizeof(xs->sense)/4; sr++) {
    1118           0 :                                         pp[sr] = swap32(pp[sr]);
    1119             :                                 }
    1120           0 :                         } else {
    1121           0 :                                 xs->error = XS_NOERROR;
    1122             :                         }
    1123             :                         break;
    1124             : 
    1125             :                 case QLE_IOCB_STATUS_DMA_ERROR:
    1126             :                         DPRINTF(QLE_D_IO, "%s: dma error\n", DEVNAME(sc));
    1127             :                         /* set resid apparently? */
    1128             :                         break;
    1129             : 
    1130             :                 case QLE_IOCB_STATUS_RESET:
    1131             :                         DPRINTF(QLE_D_IO, "%s: reset destroyed command\n",
    1132             :                             DEVNAME(sc));
    1133           0 :                         sc->sc_marker_required = 1;
    1134           0 :                         xs->error = XS_RESET;
    1135           0 :                         break;
    1136             : 
    1137             :                 case QLE_IOCB_STATUS_ABORTED:
    1138             :                         DPRINTF(QLE_D_IO, "%s: aborted\n", DEVNAME(sc));
    1139           0 :                         sc->sc_marker_required = 1;
    1140           0 :                         xs->error = XS_DRIVER_STUFFUP;
    1141           0 :                         break;
    1142             :                 
    1143             :                 case QLE_IOCB_STATUS_TIMEOUT:
    1144             :                         DPRINTF(QLE_D_IO, "%s: command timed out\n",
    1145             :                             DEVNAME(sc));
    1146           0 :                         xs->error = XS_TIMEOUT;
    1147           0 :                         break;
    1148             : 
    1149             :                 case QLE_IOCB_STATUS_QUEUE_FULL:
    1150             :                         DPRINTF(QLE_D_IO, "%s: queue full\n", DEVNAME(sc));
    1151           0 :                         xs->error = XS_BUSY;
    1152           0 :                         break;
    1153             : 
    1154             :                 case QLE_IOCB_STATUS_PORT_UNAVAIL:
    1155             :                 case QLE_IOCB_STATUS_PORT_LOGGED_OUT:
    1156             :                 case QLE_IOCB_STATUS_PORT_CHANGED:
    1157             :                         DPRINTF(QLE_D_IO, "%s: dev gone\n", DEVNAME(sc));
    1158           0 :                         xs->error = XS_SELTIMEOUT;
    1159             :                         /* mark port as needing relogin? */
    1160           0 :                         break;
    1161             : 
    1162             :                 default:
    1163             :                         DPRINTF(QLE_D_IO, "%s: unexpected completion status "
    1164             :                             "%x\n", DEVNAME(sc), status->completion);
    1165           0 :                         xs->error = XS_DRIVER_STUFFUP;
    1166           0 :                         break;
    1167             :                 }
    1168             :                 break;
    1169             : 
    1170             :         case QLE_IOCB_STATUS_CONT:
    1171             :                 DPRINTF(QLE_D_IO, "%s: ignoring status continuation iocb\n",
    1172             :                     DEVNAME(sc));
    1173             :                 break;
    1174             : 
    1175             :         case QLE_IOCB_PLOGX:
    1176             :         case QLE_IOCB_CT_PASSTHROUGH:
    1177           0 :                 if (sc->sc_fabric_pending) {
    1178           0 :                         qle_dump_iocb(sc, entry);
    1179           0 :                         memcpy(sc->sc_fabric_response, entry,
    1180             :                             QLE_QUEUE_ENTRY_SIZE);
    1181           0 :                         sc->sc_fabric_pending = 2;
    1182           0 :                         wakeup(sc->sc_scratch);
    1183           0 :                 } else {
    1184             :                         DPRINTF(QLE_D_IO, "%s: unexpected fabric response %x\n",
    1185             :                             DEVNAME(sc), entry[0]);
    1186             :                 }
    1187             :                 break;
    1188             : 
    1189             :         case QLE_IOCB_MARKER:
    1190             :                 break;
    1191             : 
    1192             :         case QLE_IOCB_CMD_TYPE_6:
    1193             :         case QLE_IOCB_CMD_TYPE_7:
    1194             :                 DPRINTF(QLE_D_IO, "%s: request bounced back\n", DEVNAME(sc));
    1195           0 :                 req = (struct qle_iocb_req6 *)entry;
    1196           0 :                 handle = req->req_handle;
    1197           0 :                 if (handle > sc->sc_maxcmds) {
    1198           0 :                         panic("bad bounced command handle: %d (> %d)",
    1199             :                             handle, sc->sc_maxcmds);
    1200             :                 }
    1201             : 
    1202           0 :                 ccb = &sc->sc_ccbs[handle];
    1203           0 :                 xs = ccb->ccb_xs;
    1204           0 :                 xs->error = XS_DRIVER_STUFFUP;
    1205           0 :                 break;
    1206             :         default:
    1207             :                 DPRINTF(QLE_D_IO, "%s: unexpected response entry type %x\n",
    1208             :                     DEVNAME(sc), entry[0]);
    1209             :                 break;
    1210             :         }
    1211             : 
    1212           0 :         return (ccb);
    1213             : }
    1214             : 
    1215             : void
    1216           0 : qle_handle_intr(struct qle_softc *sc, u_int16_t isr, u_int16_t info)
    1217             : {
    1218             :         int i;
    1219             :         u_int32_t rspin;
    1220             :         struct qle_ccb *ccb;
    1221             : 
    1222           0 :         switch (isr) {
    1223             :         case QLE_INT_TYPE_ASYNC:
    1224           0 :                 qle_async(sc, info);
    1225           0 :                 break;
    1226             : 
    1227             :         case QLE_INT_TYPE_IO:
    1228           0 :                 rspin = qle_read(sc, QLE_RESP_IN);
    1229           0 :                 if (rspin == sc->sc_last_resp_id)
    1230             :                         break;
    1231             : 
    1232           0 :                 do {
    1233           0 :                         ccb = qle_handle_resp(sc, sc->sc_last_resp_id);
    1234           0 :                         if (ccb)
    1235           0 :                                 scsi_done(ccb->ccb_xs);
    1236             : 
    1237           0 :                         sc->sc_last_resp_id++;
    1238           0 :                         sc->sc_last_resp_id %= sc->sc_maxcmds;
    1239           0 :                 } while (sc->sc_last_resp_id != rspin);
    1240             : 
    1241           0 :                 qle_write(sc, QLE_RESP_OUT, sc->sc_last_resp_id);
    1242           0 :                 break;
    1243             : 
    1244             :         case QLE_INT_TYPE_MBOX:
    1245           0 :                 mtx_enter(&sc->sc_mbox_mtx);
    1246           0 :                 if (sc->sc_mbox_pending) {
    1247           0 :                         for (i = 0; i < nitems(sc->sc_mbox); i++) {
    1248           0 :                                 sc->sc_mbox[i] = qle_read_mbox(sc, i);
    1249             :                         }
    1250           0 :                         sc->sc_mbox_pending = 2;
    1251           0 :                         wakeup(sc->sc_mbox);
    1252           0 :                         mtx_leave(&sc->sc_mbox_mtx);
    1253           0 :                 } else {
    1254           0 :                         mtx_leave(&sc->sc_mbox_mtx);
    1255             :                         DPRINTF(QLE_D_INTR, "%s: unexpected mbox interrupt: "
    1256             :                             "%x\n", DEVNAME(sc), info);
    1257             :                 }
    1258             :                 break;
    1259             : 
    1260             :         default:
    1261             :                 break;
    1262             :         }
    1263             : 
    1264           0 :         qle_clear_isr(sc, isr);
    1265           0 : }
    1266             : 
    1267             : int
    1268           0 : qle_intr(void *xsc)
    1269             : {
    1270           0 :         struct qle_softc *sc = xsc;
    1271           0 :         u_int16_t isr;
    1272           0 :         u_int16_t info;
    1273             : 
    1274           0 :         if (qle_read_isr(sc, &isr, &info) == 0)
    1275           0 :                 return (0);
    1276             : 
    1277           0 :         qle_handle_intr(sc, isr, info);
    1278           0 :         return (1);
    1279           0 : }
    1280             : 
    1281             : int
    1282           0 : qle_scsi_probe(struct scsi_link *link)
    1283             : {
    1284           0 :         struct qle_softc *sc = link->adapter_softc;
    1285             :         int rv = 0;
    1286             : 
    1287           0 :         mtx_enter(&sc->sc_port_mtx);
    1288           0 :         if (sc->sc_targets[link->target] == NULL)
    1289           0 :                 rv = ENXIO;
    1290           0 :         else if (!ISSET(sc->sc_targets[link->target]->flags,
    1291             :             QLE_PORT_FLAG_IS_TARGET))
    1292           0 :                 rv = ENXIO;
    1293           0 :         mtx_leave(&sc->sc_port_mtx);
    1294             : 
    1295           0 :         return (rv);
    1296             : }
    1297             : 
    1298             : void
    1299           0 : qle_scsi_cmd(struct scsi_xfer *xs)
    1300             : {
    1301           0 :         struct scsi_link        *link = xs->sc_link;
    1302           0 :         struct qle_softc        *sc = link->adapter_softc;
    1303             :         struct qle_ccb          *ccb;
    1304             :         void                    *iocb;
    1305           0 :         struct qle_ccb_list     list;
    1306             :         u_int16_t               req;
    1307             :         u_int32_t               portid;
    1308             :         int                     offset, error, done;
    1309             :         bus_dmamap_t            dmap;
    1310             : 
    1311           0 :         if (xs->cmdlen > 16) {
    1312             :                 DPRINTF(QLE_D_IO, "%s: cmd too big (%d)\n", DEVNAME(sc),
    1313             :                     xs->cmdlen);
    1314           0 :                 memset(&xs->sense, 0, sizeof(xs->sense));
    1315           0 :                 xs->sense.error_code = SSD_ERRCODE_VALID | SSD_ERRCODE_CURRENT;
    1316           0 :                 xs->sense.flags = SKEY_ILLEGAL_REQUEST;
    1317           0 :                 xs->sense.add_sense_code = 0x20;
    1318           0 :                 xs->error = XS_SENSE;
    1319           0 :                 scsi_done(xs);
    1320           0 :                 return;
    1321             :         }
    1322             : 
    1323             :         portid = 0xffffffff;
    1324           0 :         mtx_enter(&sc->sc_port_mtx);
    1325           0 :         if (sc->sc_targets[xs->sc_link->target] != NULL) {
    1326           0 :                 portid = sc->sc_targets[xs->sc_link->target]->portid;
    1327           0 :         }
    1328           0 :         mtx_leave(&sc->sc_port_mtx);
    1329           0 :         if (portid == 0xffffffff) {
    1330           0 :                 xs->error = XS_DRIVER_STUFFUP;
    1331           0 :                 scsi_done(xs);
    1332           0 :                 return;
    1333             :         }
    1334             : 
    1335           0 :         ccb = xs->io;
    1336           0 :         dmap = ccb->ccb_dmamap;
    1337           0 :         if (xs->datalen > 0) {
    1338           0 :                 error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data,
    1339             :                     xs->datalen, NULL, (xs->flags & SCSI_NOSLEEP) ?
    1340             :                     BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
    1341           0 :                 if (error) {
    1342           0 :                         xs->error = XS_DRIVER_STUFFUP;
    1343           0 :                         scsi_done(xs);
    1344           0 :                         return;
    1345             :                 }
    1346             : 
    1347           0 :                 bus_dmamap_sync(sc->sc_dmat, dmap, 0,
    1348             :                     dmap->dm_mapsize,
    1349             :                     (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
    1350             :                     BUS_DMASYNC_PREWRITE);
    1351           0 :         }
    1352             : 
    1353           0 :         mtx_enter(&sc->sc_queue_mtx);
    1354             : 
    1355             :         /* put in a sync marker if required */
    1356           0 :         if (sc->sc_marker_required) {
    1357           0 :                 req = sc->sc_next_req_id++;
    1358           0 :                 if (sc->sc_next_req_id == sc->sc_maxcmds)
    1359           0 :                         sc->sc_next_req_id = 0;
    1360             : 
    1361             :                 DPRINTF(QLE_D_IO, "%s: writing marker at request %d\n",
    1362             :                     DEVNAME(sc), req);
    1363           0 :                 offset = (req * QLE_QUEUE_ENTRY_SIZE);
    1364           0 :                 iocb = QLE_DMA_KVA(sc->sc_requests) + offset;
    1365           0 :                 bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(sc->sc_requests),
    1366             :                     offset, QLE_QUEUE_ENTRY_SIZE, BUS_DMASYNC_POSTWRITE);
    1367           0 :                 qle_put_marker(sc, iocb);
    1368           0 :                 qle_write(sc, QLE_REQ_IN, sc->sc_next_req_id);
    1369           0 :                 sc->sc_marker_required = 0;
    1370           0 :         }
    1371             : 
    1372           0 :         req = sc->sc_next_req_id++;
    1373           0 :         if (sc->sc_next_req_id == sc->sc_maxcmds)
    1374           0 :                 sc->sc_next_req_id = 0;
    1375             : 
    1376           0 :         offset = (req * QLE_QUEUE_ENTRY_SIZE);
    1377           0 :         iocb = QLE_DMA_KVA(sc->sc_requests) + offset;
    1378           0 :         bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(sc->sc_requests), offset,
    1379             :             QLE_QUEUE_ENTRY_SIZE, BUS_DMASYNC_POSTWRITE);
    1380             :             
    1381           0 :         ccb->ccb_xs = xs;
    1382             : 
    1383           0 :         qle_put_cmd(sc, iocb, xs, ccb, portid);
    1384             : 
    1385           0 :         bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(sc->sc_requests), offset,
    1386             :             QLE_QUEUE_ENTRY_SIZE, BUS_DMASYNC_PREREAD);
    1387           0 :         qle_write(sc, QLE_REQ_IN, sc->sc_next_req_id);
    1388             : 
    1389           0 :         if (!ISSET(xs->flags, SCSI_POLL)) {
    1390           0 :                 mtx_leave(&sc->sc_queue_mtx);
    1391           0 :                 return;
    1392             :         }
    1393             : 
    1394             :         done = 0;
    1395           0 :         SIMPLEQ_INIT(&list);
    1396           0 :         do {
    1397           0 :                 u_int16_t isr, info;
    1398             :                 u_int32_t rspin;
    1399           0 :                 delay(100);
    1400             : 
    1401           0 :                 if (qle_read_isr(sc, &isr, &info) == 0) {
    1402           0 :                         continue;
    1403             :                 }
    1404             : 
    1405           0 :                 if (isr != QLE_INT_TYPE_IO) {
    1406           0 :                         qle_handle_intr(sc, isr, info);
    1407           0 :                         continue;
    1408             :                 }
    1409             : 
    1410           0 :                 rspin = qle_read(sc, QLE_RESP_IN);
    1411           0 :                 while (rspin != sc->sc_last_resp_id) {
    1412           0 :                         ccb = qle_handle_resp(sc, sc->sc_last_resp_id);
    1413             : 
    1414           0 :                         sc->sc_last_resp_id++;
    1415           0 :                         if (sc->sc_last_resp_id == sc->sc_maxcmds)
    1416           0 :                                 sc->sc_last_resp_id = 0;
    1417             : 
    1418           0 :                         if (ccb != NULL)
    1419           0 :                                 SIMPLEQ_INSERT_TAIL(&list, ccb, ccb_link);
    1420           0 :                         if (ccb == xs->io)
    1421           0 :                                 done = 1;
    1422             :                 }
    1423           0 :                 qle_write(sc, QLE_RESP_OUT, sc->sc_last_resp_id);
    1424           0 :                 qle_clear_isr(sc, isr);
    1425           0 :         } while (done == 0);
    1426             : 
    1427           0 :         mtx_leave(&sc->sc_queue_mtx);
    1428             : 
    1429           0 :         while ((ccb = SIMPLEQ_FIRST(&list)) != NULL) {
    1430           0 :                 SIMPLEQ_REMOVE_HEAD(&list, ccb_link);
    1431           0 :                 scsi_done(ccb->ccb_xs);
    1432             :         }
    1433           0 : }
    1434             : 
    1435             : u_int32_t
    1436           0 : qle_read(struct qle_softc *sc, int offset)
    1437             : {
    1438             :         u_int32_t v;
    1439           0 :         v = bus_space_read_4(sc->sc_iot, sc->sc_ioh, offset);
    1440           0 :         bus_space_barrier(sc->sc_iot, sc->sc_ioh, offset, 4,
    1441             :             BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
    1442           0 :         return (v);
    1443             : }
    1444             : 
    1445             : void
    1446           0 : qle_write(struct qle_softc *sc, int offset, u_int32_t value)
    1447             : {
    1448           0 :         bus_space_write_4(sc->sc_iot, sc->sc_ioh, offset, value);
    1449           0 :         bus_space_barrier(sc->sc_iot, sc->sc_ioh, offset, 4,
    1450             :             BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
    1451           0 : }
    1452             : 
    1453             : u_int16_t
    1454           0 : qle_read_mbox(struct qle_softc *sc, int mbox)
    1455             : {
    1456             :         u_int16_t v;
    1457           0 :         bus_size_t offset = mbox * 2;
    1458           0 :         v = bus_space_read_2(sc->sc_iot, sc->sc_mbox_ioh, offset);
    1459           0 :         bus_space_barrier(sc->sc_iot, sc->sc_mbox_ioh, offset, 2,
    1460             :             BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
    1461           0 :         return (v);
    1462             : }
    1463             : 
    1464             : void
    1465           0 : qle_write_mbox(struct qle_softc *sc, int mbox, u_int16_t value)
    1466             : {
    1467           0 :         bus_size_t offset = (mbox * 2);
    1468           0 :         bus_space_write_2(sc->sc_iot, sc->sc_mbox_ioh, offset, value);
    1469           0 :         bus_space_barrier(sc->sc_iot, sc->sc_mbox_ioh, offset, 2,
    1470             :             BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
    1471           0 : }
    1472             : 
    1473             : void
    1474           0 : qle_host_cmd(struct qle_softc *sc, u_int32_t cmd)
    1475             : {
    1476           0 :         qle_write(sc, QLE_HOST_CMD_CTRL, cmd << QLE_HOST_CMD_SHIFT);
    1477           0 : }
    1478             : 
    1479             : #define MBOX_COMMAND_TIMEOUT    400000
    1480             : 
    1481             : int
    1482           0 : qle_mbox(struct qle_softc *sc, int maskin)
    1483             : {
    1484             :         int i;
    1485             :         int result = 0;
    1486             :         int rv;
    1487             : 
    1488           0 :         for (i = 0; i < nitems(sc->sc_mbox); i++) {
    1489           0 :                 if (maskin & (1 << i)) {
    1490           0 :                         qle_write_mbox(sc, i, sc->sc_mbox[i]);
    1491           0 :                 }
    1492             :         }
    1493           0 :         qle_host_cmd(sc, QLE_HOST_CMD_SET_HOST_INT);
    1494             : 
    1495           0 :         if (sc->sc_scsibus != NULL) {
    1496           0 :                 mtx_enter(&sc->sc_mbox_mtx);
    1497           0 :                 sc->sc_mbox_pending = 1;
    1498           0 :                 while (sc->sc_mbox_pending == 1) {
    1499           0 :                         msleep(sc->sc_mbox, &sc->sc_mbox_mtx, PRIBIO,
    1500             :                             "qlembox", 0);
    1501             :                 }
    1502           0 :                 result = sc->sc_mbox[0];
    1503           0 :                 sc->sc_mbox_pending = 0;
    1504           0 :                 mtx_leave(&sc->sc_mbox_mtx);
    1505           0 :                 return (result == QLE_MBOX_COMPLETE ? 0 : result);
    1506             :         }
    1507             : 
    1508           0 :         for (i = 0; i < MBOX_COMMAND_TIMEOUT && result == 0; i++) {
    1509           0 :                 u_int16_t isr, info;
    1510             : 
    1511           0 :                 delay(100);
    1512             : 
    1513           0 :                 if (qle_read_isr(sc, &isr, &info) == 0)
    1514           0 :                         continue;
    1515             : 
    1516           0 :                 switch (isr) {
    1517             :                 case QLE_INT_TYPE_MBOX:
    1518           0 :                         result = info;
    1519           0 :                         break;
    1520             : 
    1521             :                 default:
    1522           0 :                         qle_handle_intr(sc, isr, info);
    1523           0 :                         break;
    1524             :                 }
    1525           0 :         }
    1526             : 
    1527           0 :         if (result == 0) {
    1528             :                 /* timed out; do something? */
    1529             :                 DPRINTF(QLE_D_MBOX, "%s: mbox timed out\n", DEVNAME(sc));
    1530             :                 rv = 1;
    1531           0 :         } else {
    1532           0 :                 for (i = 0; i < nitems(sc->sc_mbox); i++) {
    1533           0 :                         sc->sc_mbox[i] = qle_read_mbox(sc, i);
    1534             :                 }
    1535           0 :                 rv = (result == QLE_MBOX_COMPLETE ? 0 : result);
    1536             :         }
    1537             : 
    1538           0 :         qle_clear_isr(sc, QLE_INT_TYPE_MBOX);
    1539           0 :         return (rv);
    1540           0 : }
    1541             : 
    1542             : void
    1543           0 : qle_mbox_putaddr(u_int16_t *mbox, struct qle_dmamem *mem)
    1544             : {
    1545           0 :         mbox[2] = (QLE_DMA_DVA(mem) >> 16) & 0xffff;
    1546           0 :         mbox[3] = (QLE_DMA_DVA(mem) >> 0) & 0xffff;
    1547           0 :         mbox[6] = (QLE_DMA_DVA(mem) >> 48) & 0xffff;
    1548           0 :         mbox[7] = (QLE_DMA_DVA(mem) >> 32) & 0xffff;
    1549           0 : }
    1550             : 
    1551             : void
    1552           0 : qle_set_ints(struct qle_softc *sc, int enabled)
    1553             : {
    1554           0 :         u_int32_t v = enabled ? QLE_INT_CTRL_ENABLE : 0;
    1555           0 :         qle_write(sc, QLE_INT_CTRL, v);
    1556           0 : }
    1557             : 
    1558             : int
    1559           0 : qle_read_isr(struct qle_softc *sc, u_int16_t *isr, u_int16_t *info)
    1560             : {
    1561             :         u_int32_t v;
    1562             : 
    1563           0 :         switch (sc->sc_isp_gen) {
    1564             :         case QLE_GEN_ISP24XX:
    1565             :         case QLE_GEN_ISP25XX:
    1566           0 :                 if ((qle_read(sc, QLE_INT_STATUS) & QLE_RISC_INT_REQ) == 0)
    1567           0 :                         return (0);
    1568             : 
    1569           0 :                 v = qle_read(sc, QLE_RISC_STATUS);
    1570             : 
    1571           0 :                 switch (v & QLE_INT_STATUS_MASK) {
    1572             :                 case QLE_24XX_INT_ROM_MBOX:
    1573             :                 case QLE_24XX_INT_ROM_MBOX_FAIL:
    1574             :                 case QLE_24XX_INT_MBOX:
    1575             :                 case QLE_24XX_INT_MBOX_FAIL:
    1576           0 :                         *isr = QLE_INT_TYPE_MBOX;
    1577           0 :                         break;
    1578             : 
    1579             :                 case QLE_24XX_INT_ASYNC:
    1580           0 :                         *isr = QLE_INT_TYPE_ASYNC;
    1581           0 :                         break;
    1582             : 
    1583             :                 case QLE_24XX_INT_RSPQ:
    1584           0 :                         *isr = QLE_INT_TYPE_IO;
    1585           0 :                         break;
    1586             : 
    1587             :                 default:
    1588           0 :                         *isr = QLE_INT_TYPE_OTHER;
    1589           0 :                         break;
    1590             :                 }
    1591             : 
    1592           0 :                 *info = (v >> QLE_INT_INFO_SHIFT);
    1593           0 :                 return (1);
    1594             : 
    1595             :         default:
    1596           0 :                 return (0);
    1597             :         }
    1598           0 : }
    1599             : 
    1600             : void
    1601           0 : qle_clear_isr(struct qle_softc *sc, u_int16_t isr)
    1602             : {
    1603           0 :         qle_host_cmd(sc, QLE_HOST_CMD_CLR_RISC_INT);
    1604           0 : }
    1605             : 
    1606             : void
    1607           0 : qle_update_done(struct qle_softc *sc, int task)
    1608             : {
    1609           0 :         atomic_clearbits_int(&sc->sc_update_tasks, task);
    1610           0 : }
    1611             : 
    1612             : void
    1613           0 : qle_update_cancel(struct qle_softc *sc)
    1614             : {
    1615           0 :         atomic_swap_uint(&sc->sc_update_tasks, 0);
    1616           0 :         timeout_del(&sc->sc_update_timeout);
    1617           0 :         task_del(sc->sc_update_taskq, &sc->sc_update_task);
    1618           0 : }
    1619             : 
    1620             : void
    1621           0 : qle_update_start(struct qle_softc *sc, int task)
    1622             : {
    1623           0 :         atomic_setbits_int(&sc->sc_update_tasks, task);
    1624           0 :         if (!timeout_pending(&sc->sc_update_timeout))
    1625           0 :                 task_add(sc->sc_update_taskq, &sc->sc_update_task);
    1626           0 : }
    1627             : 
    1628             : void
    1629           0 : qle_update_defer(struct qle_softc *sc, int task)
    1630             : {
    1631           0 :         atomic_setbits_int(&sc->sc_update_tasks, task);
    1632           0 :         timeout_del(&sc->sc_update_timeout);
    1633           0 :         task_del(sc->sc_update_taskq, &sc->sc_update_task);
    1634           0 :         timeout_add_msec(&sc->sc_update_timeout, QLE_LOOP_SETTLE);
    1635           0 : }
    1636             : 
    1637             : void
    1638           0 : qle_clear_port_lists(struct qle_softc *sc)
    1639             : {
    1640             :         struct qle_fc_port *port;
    1641           0 :         while (!TAILQ_EMPTY(&sc->sc_ports_found)) {
    1642             :                 port = TAILQ_FIRST(&sc->sc_ports_found);
    1643           0 :                 TAILQ_REMOVE(&sc->sc_ports_found, port, update);
    1644           0 :                 free(port, M_DEVBUF, sizeof *port);
    1645             :         }
    1646             : 
    1647           0 :         while (!TAILQ_EMPTY(&sc->sc_ports_new)) {
    1648             :                 port = TAILQ_FIRST(&sc->sc_ports_new);
    1649           0 :                 TAILQ_REMOVE(&sc->sc_ports_new, port, update);
    1650           0 :                 free(port, M_DEVBUF, sizeof *port);
    1651             :         }
    1652             : 
    1653           0 :         while (!TAILQ_EMPTY(&sc->sc_ports_gone)) {
    1654             :                 port = TAILQ_FIRST(&sc->sc_ports_gone);
    1655           0 :                 TAILQ_REMOVE(&sc->sc_ports_gone, port, update);
    1656             :         }
    1657           0 : }
    1658             : 
    1659             : int
    1660           0 : qle_softreset(struct qle_softc *sc)
    1661             : {
    1662             :         int i;
    1663           0 :         qle_set_ints(sc, 0);
    1664             : 
    1665             :         /* set led control bits, stop dma */
    1666           0 :         qle_write(sc, QLE_GPIO_DATA, 0);
    1667           0 :         qle_write(sc, QLE_CTRL_STATUS, QLE_CTRL_DMA_SHUTDOWN);
    1668           0 :         while (qle_read(sc, QLE_CTRL_STATUS) & QLE_CTRL_DMA_ACTIVE) {
    1669             :                 DPRINTF(QLE_D_IO, "%s: dma still active\n", DEVNAME(sc));
    1670           0 :                 delay(100);
    1671             :         }
    1672             : 
    1673             :         /* reset */
    1674           0 :         qle_write(sc, QLE_CTRL_STATUS, QLE_CTRL_RESET | QLE_CTRL_DMA_SHUTDOWN);
    1675           0 :         delay(100);
    1676             :         /* clear data and control dma engines? */
    1677             : 
    1678             :         /* wait for soft reset to clear */
    1679           0 :         for (i = 0; i < 1000; i++) {
    1680           0 :                 if (qle_read_mbox(sc, 0) == 0x0000)
    1681             :                         break;
    1682             : 
    1683           0 :                 delay(100);
    1684             :         }
    1685             : 
    1686           0 :         if (i == 1000) {
    1687           0 :                 printf("%s: reset mbox didn't clear\n", DEVNAME(sc));
    1688           0 :                 qle_set_ints(sc, 0);
    1689           0 :                 return (ENXIO);
    1690             :         }
    1691             : 
    1692           0 :         for (i = 0; i < 500000; i++) {
    1693           0 :                 if ((qle_read(sc, QLE_CTRL_STATUS) & QLE_CTRL_RESET) == 0)
    1694             :                         break;
    1695           0 :                 delay(5);
    1696             :         }
    1697           0 :         if (i == 500000) {
    1698           0 :                 printf("%s: reset status didn't clear\n", DEVNAME(sc));
    1699           0 :                 return (ENXIO);
    1700             :         }
    1701             : 
    1702             :         /* reset risc processor */
    1703           0 :         qle_host_cmd(sc, QLE_HOST_CMD_RESET);
    1704           0 :         qle_host_cmd(sc, QLE_HOST_CMD_RELEASE);
    1705           0 :         qle_host_cmd(sc, QLE_HOST_CMD_CLEAR_RESET);
    1706             : 
    1707             :         /* wait for reset to clear */
    1708           0 :         for (i = 0; i < 1000; i++) {
    1709           0 :                 if (qle_read_mbox(sc, 0) == 0x0000)
    1710             :                         break;
    1711           0 :                 delay(100);
    1712             :         }
    1713           0 :         if (i == 1000) {
    1714           0 :                 printf("%s: risc not ready after reset\n", DEVNAME(sc));
    1715           0 :                 return (ENXIO);
    1716             :         }
    1717             : 
    1718             :         /* reset queue pointers */
    1719           0 :         qle_write(sc, QLE_REQ_IN, 0);
    1720           0 :         qle_write(sc, QLE_REQ_OUT, 0);
    1721           0 :         qle_write(sc, QLE_RESP_IN, 0);
    1722           0 :         qle_write(sc, QLE_RESP_OUT, 0);
    1723             : 
    1724           0 :         qle_set_ints(sc, 1);
    1725             : 
    1726             :         /* do a basic mailbox operation to check we're alive */
    1727           0 :         sc->sc_mbox[0] = QLE_MBOX_NOP;
    1728           0 :         if (qle_mbox(sc, 0x0001)) {
    1729           0 :                 printf("ISP not responding after reset\n");
    1730           0 :                 return (ENXIO);
    1731             :         }
    1732             : 
    1733           0 :         return (0);
    1734           0 : }
    1735             : 
    1736             : void
    1737           0 : qle_update_topology(struct qle_softc *sc)
    1738             : {
    1739           0 :         sc->sc_mbox[0] = QLE_MBOX_GET_ID;
    1740           0 :         if (qle_mbox(sc, 0x0001)) {
    1741             :                 DPRINTF(QLE_D_PORT, "%s: unable to get loop id\n", DEVNAME(sc));
    1742           0 :                 sc->sc_topology = QLE_TOPO_N_PORT_NO_TARGET;
    1743           0 :         } else {
    1744           0 :                 sc->sc_topology = sc->sc_mbox[6];
    1745           0 :                 sc->sc_loop_id = sc->sc_mbox[1];
    1746             : 
    1747           0 :                 switch (sc->sc_topology) {
    1748             :                 case QLE_TOPO_NL_PORT:
    1749             :                 case QLE_TOPO_N_PORT:
    1750             :                         DPRINTF(QLE_D_PORT, "%s: loop id %d\n", DEVNAME(sc),
    1751             :                             sc->sc_loop_id);
    1752             :                         break;
    1753             : 
    1754             :                 case QLE_TOPO_FL_PORT:
    1755             :                 case QLE_TOPO_F_PORT:
    1756           0 :                         sc->sc_port_id = sc->sc_mbox[2] |
    1757           0 :                             (sc->sc_mbox[3] << 16);
    1758             :                         DPRINTF(QLE_D_PORT, "%s: fabric port id %06x\n",
    1759             :                             DEVNAME(sc), sc->sc_port_id);
    1760           0 :                         break;
    1761             : 
    1762             :                 case QLE_TOPO_N_PORT_NO_TARGET:
    1763             :                 default:
    1764             :                         DPRINTF(QLE_D_PORT, "%s: not useful\n", DEVNAME(sc));
    1765             :                         break;
    1766             :                 }
    1767             : 
    1768           0 :                 switch (sc->sc_topology) {
    1769             :                 case QLE_TOPO_NL_PORT:
    1770             :                 case QLE_TOPO_FL_PORT:
    1771           0 :                         sc->sc_loop_max_id = 126;
    1772           0 :                         break;
    1773             : 
    1774             :                 case QLE_TOPO_N_PORT:
    1775           0 :                         sc->sc_loop_max_id = 2;
    1776           0 :                         break;
    1777             : 
    1778             :                 default:
    1779           0 :                         sc->sc_loop_max_id = 0;
    1780           0 :                         break;
    1781             :                 }
    1782             :         }
    1783           0 : }
    1784             : 
    1785             : int
    1786           0 : qle_update_fabric(struct qle_softc *sc)
    1787             : {
    1788             :         /*struct qle_sns_rft_id *rft;*/
    1789             : 
    1790           0 :         switch (sc->sc_topology) {
    1791             :         case QLE_TOPO_F_PORT:
    1792             :         case QLE_TOPO_FL_PORT:
    1793             :                 break;
    1794             : 
    1795             :         default:
    1796           0 :                 return (0);
    1797             :         }
    1798             : 
    1799             :         /* get the name server's port db entry */
    1800           0 :         sc->sc_mbox[0] = QLE_MBOX_GET_PORT_DB;
    1801           0 :         sc->sc_mbox[1] = QLE_F_PORT_HANDLE;
    1802           0 :         qle_mbox_putaddr(sc->sc_mbox, sc->sc_scratch);
    1803           0 :         bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(sc->sc_scratch), 0,
    1804             :             sizeof(struct qle_get_port_db), BUS_DMASYNC_PREREAD);
    1805           0 :         if (qle_mbox(sc, 0x00cf)) {
    1806             :                 DPRINTF(QLE_D_PORT, "%s: get port db for SNS failed: %x\n",
    1807             :                     DEVNAME(sc), sc->sc_mbox[0]);
    1808           0 :                 sc->sc_sns_port_name = 0;
    1809           0 :         } else {
    1810             :                 struct qle_get_port_db *pdb;
    1811           0 :                 bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(sc->sc_scratch), 0,
    1812             :                     sizeof(struct qle_get_port_db), BUS_DMASYNC_POSTREAD);
    1813           0 :                 pdb = QLE_DMA_KVA(sc->sc_scratch);
    1814             :                 DPRINTF(QLE_D_PORT, "%s: SNS port name %llx\n", DEVNAME(sc),
    1815             :                     betoh64(pdb->port_name));
    1816           0 :                 sc->sc_sns_port_name = betoh64(pdb->port_name);
    1817             :         }
    1818             : 
    1819             :         /*
    1820             :          * register fc4 types with the fabric
    1821             :          * some switches do this automatically, but apparently
    1822             :          * some don't.
    1823             :          */
    1824             :         /*
    1825             :         rft = QLE_DMA_KVA(sc->sc_scratch);
    1826             :         memset(rft, 0, sizeof(*rft) + sizeof(struct qle_sns_req_hdr));
    1827             :         htolem16(&rft->subcmd, QLE_SNS_RFT_ID);
    1828             :         htolem16(&rft->max_word, sizeof(struct qle_sns_req_hdr) / 4);
    1829             :         htolem32(&rft->port_id, sc->sc_port_id);
    1830             :         rft->fc4_types[0] = (1 << QLE_FC4_SCSI);
    1831             :         if (qle_sns_req(sc, sc->sc_scratch, sizeof(*rft))) {
    1832             :                 printf("%s: RFT_ID failed\n", DEVNAME(sc));
    1833             :                 / * we might be able to continue after this fails * /
    1834             :         }
    1835             :         */
    1836             : 
    1837           0 :         return (1);
    1838           0 : }
    1839             : 
    1840             : int
    1841           0 : qle_ct_pass_through(struct qle_softc *sc, u_int32_t port_handle,
    1842             :     struct qle_dmamem *mem, size_t req_size, size_t resp_size)
    1843             : {
    1844             :         struct qle_iocb_ct_passthrough *iocb;
    1845             :         u_int16_t req;
    1846             :         u_int64_t offset;
    1847             :         int rv;
    1848             :         
    1849           0 :         mtx_enter(&sc->sc_queue_mtx);
    1850             : 
    1851           0 :         req = sc->sc_next_req_id++;
    1852           0 :         if (sc->sc_next_req_id == sc->sc_maxcmds)
    1853           0 :                 sc->sc_next_req_id = 0;
    1854             : 
    1855           0 :         offset = (req * QLE_QUEUE_ENTRY_SIZE);
    1856           0 :         iocb = QLE_DMA_KVA(sc->sc_requests) + offset;
    1857           0 :         bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(sc->sc_requests), offset,
    1858             :             QLE_QUEUE_ENTRY_SIZE, BUS_DMASYNC_POSTWRITE);
    1859             :             
    1860           0 :         memset(iocb, 0, QLE_QUEUE_ENTRY_SIZE);
    1861           0 :         iocb->entry_type = QLE_IOCB_CT_PASSTHROUGH;
    1862           0 :         iocb->entry_count = 1;
    1863             : 
    1864           0 :         iocb->req_handle = 9;
    1865           0 :         htolem16(&iocb->req_nport_handle, port_handle);
    1866           0 :         htolem16(&iocb->req_dsd_count, 1);
    1867           0 :         htolem16(&iocb->req_resp_dsd_count, 1);
    1868           0 :         htolem32(&iocb->req_cmd_byte_count, req_size);
    1869           0 :         htolem32(&iocb->req_resp_byte_count, resp_size);
    1870           0 :         qle_sge(&iocb->req_cmd_seg, QLE_DMA_DVA(mem), req_size);
    1871           0 :         qle_sge(&iocb->req_resp_seg, QLE_DMA_DVA(mem) + req_size, resp_size);
    1872             : 
    1873           0 :         bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(mem), 0, QLE_DMA_LEN(mem),
    1874             :             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    1875           0 :         qle_write(sc, QLE_REQ_IN, sc->sc_next_req_id);
    1876           0 :         sc->sc_fabric_pending = 1;
    1877           0 :         mtx_leave(&sc->sc_queue_mtx);
    1878             : 
    1879             :         /* maybe put a proper timeout on this */
    1880             :         rv = 0;
    1881           0 :         while (sc->sc_fabric_pending == 1) {
    1882           0 :                 if (sc->sc_scsibus == NULL) {
    1883           0 :                         u_int16_t isr, info;
    1884             : 
    1885           0 :                         delay(100);
    1886           0 :                         if (qle_read_isr(sc, &isr, &info) != 0)
    1887           0 :                                 qle_handle_intr(sc, isr, info);
    1888           0 :                 } else {
    1889           0 :                         tsleep(sc->sc_scratch, PRIBIO, "qle_fabric", 100);
    1890             :                 }
    1891             :         }
    1892           0 :         if (rv == 0)
    1893           0 :                 bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(mem), 0,
    1894             :                     QLE_DMA_LEN(mem), BUS_DMASYNC_POSTREAD |
    1895             :                     BUS_DMASYNC_POSTWRITE);
    1896             : 
    1897           0 :         sc->sc_fabric_pending = 0;
    1898             : 
    1899           0 :         return (rv);
    1900             : }
    1901             : 
    1902             : struct qle_fc_port *
    1903           0 : qle_next_fabric_port(struct qle_softc *sc, u_int32_t *firstport,
    1904             :     u_int32_t *lastport)
    1905             : {
    1906             :         struct qle_ct_ga_nxt_req *ga;
    1907             :         struct qle_ct_ga_nxt_resp *gar;
    1908             :         struct qle_fc_port *fport;
    1909             :         int result;
    1910             : 
    1911             :         /* get the next port from the fabric nameserver */
    1912           0 :         ga = QLE_DMA_KVA(sc->sc_scratch);
    1913           0 :         memset(ga, 0, sizeof(*ga) + sizeof(*gar));
    1914           0 :         ga->header.ct_revision = 0x01;
    1915           0 :         ga->header.ct_gs_type = 0xfc;
    1916           0 :         ga->header.ct_gs_subtype = 0x02;
    1917           0 :         ga->subcmd = htobe16(QLE_SNS_GA_NXT);
    1918           0 :         ga->max_word = htobe16((sizeof(*gar) - 16) / 4);
    1919           0 :         ga->port_id = htobe32(*lastport);
    1920           0 :         result = qle_ct_pass_through(sc, QLE_SNS_HANDLE, sc->sc_scratch,
    1921             :             sizeof(*ga), sizeof(*gar));
    1922           0 :         if (result) {
    1923             :                 DPRINTF(QLE_D_PORT, "%s: GA_NXT %06x failed: %x\n", DEVNAME(sc),
    1924             :                     *lastport, result);
    1925           0 :                 *lastport = 0xffffffff;
    1926           0 :                 return (NULL);
    1927             :         }
    1928             : 
    1929           0 :         gar = (struct qle_ct_ga_nxt_resp *)(ga + 1);
    1930             :         /* if the response is all zeroes, try again */
    1931           0 :         if (gar->port_type_id == 0 && gar->port_name == 0 &&
    1932           0 :             gar->node_name == 0) {
    1933             :                 DPRINTF(QLE_D_PORT, "%s: GA_NXT returned junk\n", DEVNAME(sc));
    1934           0 :                 return (NULL);
    1935             :         }
    1936             : 
    1937             :         /* are we back at the start? */
    1938           0 :         *lastport = betoh32(gar->port_type_id) & 0xffffff;
    1939           0 :         if (*lastport == *firstport) {
    1940           0 :                 *lastport = 0xffffffff;
    1941           0 :                 return (NULL);
    1942             :         }
    1943           0 :         if (*firstport == 0xffffffff)
    1944           0 :                 *firstport = *lastport;
    1945             : 
    1946             :         DPRINTF(QLE_D_PORT, "%s: GA_NXT: port id: %06x, wwpn %llx, wwnn %llx\n",
    1947             :             DEVNAME(sc), *lastport, betoh64(gar->port_name),
    1948             :             betoh64(gar->node_name));
    1949             : 
    1950             :         /* don't try to log in to ourselves */
    1951           0 :         if (*lastport == sc->sc_port_id) {
    1952           0 :                 return (NULL);
    1953             :         }
    1954             : 
    1955           0 :         fport = malloc(sizeof(*fport), M_DEVBUF, M_ZERO | M_NOWAIT);
    1956           0 :         if (fport == NULL) {
    1957           0 :                 printf("%s: failed to allocate a port struct\n",
    1958           0 :                     DEVNAME(sc));
    1959           0 :                 *lastport = 0xffffffff;
    1960           0 :                 return (NULL);
    1961             :         }
    1962           0 :         fport->port_name = betoh64(gar->port_name);
    1963           0 :         fport->node_name = betoh64(gar->node_name);
    1964           0 :         fport->location = QLE_LOCATION_PORT_ID(*lastport);
    1965           0 :         fport->portid = *lastport;
    1966           0 :         return (fport);
    1967           0 : }
    1968             : 
    1969             : int
    1970           0 : qle_fabric_plogx(struct qle_softc *sc, struct qle_fc_port *port, int flags,
    1971             :     u_int32_t *info)
    1972             : {
    1973             :         struct qle_iocb_plogx *iocb;
    1974             :         u_int16_t req;
    1975             :         u_int64_t offset;
    1976             :         int rv;
    1977             : 
    1978           0 :         mtx_enter(&sc->sc_queue_mtx);
    1979             : 
    1980           0 :         req = sc->sc_next_req_id++;
    1981           0 :         if (sc->sc_next_req_id == sc->sc_maxcmds)
    1982           0 :                 sc->sc_next_req_id = 0;
    1983             : 
    1984           0 :         offset = (req * QLE_QUEUE_ENTRY_SIZE);
    1985           0 :         iocb = QLE_DMA_KVA(sc->sc_requests) + offset;
    1986           0 :         bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(sc->sc_requests), offset,
    1987             :             QLE_QUEUE_ENTRY_SIZE, BUS_DMASYNC_POSTWRITE);
    1988             :             
    1989           0 :         memset(iocb, 0, QLE_QUEUE_ENTRY_SIZE);
    1990           0 :         iocb->entry_type = QLE_IOCB_PLOGX;
    1991           0 :         iocb->entry_count = 1;
    1992             : 
    1993           0 :         iocb->req_handle = 7;
    1994           0 :         htolem16(&iocb->req_nport_handle, port->loopid);
    1995           0 :         htolem16(&iocb->req_port_id_lo, port->portid);
    1996           0 :         iocb->req_port_id_hi = port->portid >> 16;
    1997           0 :         htolem16(&iocb->req_flags, flags);
    1998             : 
    1999             :         DPRINTF(QLE_D_PORT, "%s: plogx loop id %d port %06x, flags %x\n",
    2000             :             DEVNAME(sc), port->loopid, port->portid, flags);
    2001           0 :         qle_dump_iocb(sc, iocb);
    2002             : 
    2003           0 :         qle_write(sc, QLE_REQ_IN, sc->sc_next_req_id);
    2004           0 :         sc->sc_fabric_pending = 1;
    2005           0 :         mtx_leave(&sc->sc_queue_mtx);
    2006             : 
    2007             :         /* maybe put a proper timeout on this */
    2008             :         rv = 0;
    2009           0 :         while (sc->sc_fabric_pending == 1) {
    2010           0 :                 if (sc->sc_scsibus == NULL) {
    2011           0 :                         u_int16_t isr, info;
    2012             : 
    2013           0 :                         delay(100);
    2014           0 :                         if (qle_read_isr(sc, &isr, &info) != 0)
    2015           0 :                                 qle_handle_intr(sc, isr, info);
    2016           0 :                 } else {
    2017           0 :                         tsleep(sc->sc_scratch, PRIBIO, "qle_fabric", 100);
    2018             :                 }
    2019             :         }
    2020           0 :         sc->sc_fabric_pending = 0;
    2021             : 
    2022           0 :         iocb = (struct qle_iocb_plogx *)&sc->sc_fabric_response;
    2023           0 :         rv = lemtoh16(&iocb->req_status);
    2024           0 :         if (rv == QLE_PLOGX_ERROR) {
    2025           0 :                 rv = lemtoh32(&iocb->req_ioparms[0]);
    2026           0 :                 *info = lemtoh32(&iocb->req_ioparms[1]);
    2027           0 :         }
    2028             : 
    2029           0 :         return (rv);
    2030             : }
    2031             : 
    2032             : int
    2033           0 : qle_fabric_plogi(struct qle_softc *sc, struct qle_fc_port *port)
    2034             : {
    2035           0 :         u_int32_t info;
    2036             :         int err, loopid;
    2037             : 
    2038           0 :         loopid = 0;
    2039             : retry:
    2040           0 :         if (port->loopid == 0) {
    2041             : 
    2042           0 :                 mtx_enter(&sc->sc_port_mtx);
    2043           0 :                 loopid = qle_get_loop_id(sc, loopid);
    2044           0 :                 mtx_leave(&sc->sc_port_mtx);
    2045           0 :                 if (loopid == -1) {
    2046           0 :                         printf("%s: ran out of loop ids\n", DEVNAME(sc));
    2047           0 :                         return (1);
    2048             :                 }
    2049             : 
    2050           0 :                 port->loopid = loopid;
    2051           0 :         }
    2052             : 
    2053           0 :         err = qle_fabric_plogx(sc, port, QLE_PLOGX_LOGIN, &info);
    2054           0 :         switch (err) {
    2055             :         case 0:
    2056             :                 DPRINTF(QLE_D_PORT, "%s: logged in to %06x as %d\n",
    2057             :                     DEVNAME(sc), port->portid, port->loopid);
    2058           0 :                 port->flags &= ~QLE_PORT_FLAG_NEEDS_LOGIN;
    2059           0 :                 return (0);
    2060             : 
    2061             :         case QLE_PLOGX_ERROR_PORT_ID_USED:
    2062             :                 DPRINTF(QLE_D_PORT, "%s: already logged in to %06x as %d\n",
    2063             :                     DEVNAME(sc), port->portid, info);
    2064           0 :                 port->loopid = info;
    2065           0 :                 port->flags &= ~QLE_PORT_FLAG_NEEDS_LOGIN;
    2066           0 :                 return (0);
    2067             : 
    2068             :         case QLE_PLOGX_ERROR_HANDLE_USED:
    2069           0 :                 if (qle_add_logged_in_port(sc, loopid, info)) {
    2070           0 :                         return (1);
    2071             :                 }
    2072           0 :                 port->loopid = 0;
    2073           0 :                 loopid++;
    2074           0 :                 goto retry;
    2075             : 
    2076             :         default:
    2077             :                 DPRINTF(QLE_D_PORT, "%s: error %x logging in to port %06x\n",
    2078             :                     DEVNAME(sc), err, port->portid);
    2079           0 :                 port->loopid = 0;
    2080           0 :                 return (1);
    2081             :         }
    2082           0 : }
    2083             : 
    2084             : void
    2085           0 : qle_fabric_plogo(struct qle_softc *sc, struct qle_fc_port *port)
    2086             : {
    2087             :         int err;
    2088           0 :         u_int32_t info;
    2089             : 
    2090             :         /*
    2091             :          * we only log out if we can't see the port any more, so we always
    2092             :          * want to do an explicit logout and free the n-port handle.
    2093             :          */
    2094           0 :         err = qle_fabric_plogx(sc, port, QLE_PLOGX_LOGOUT |
    2095             :             QLE_PLOGX_LOGOUT_EXPLICIT | QLE_PLOGX_LOGOUT_FREE_HANDLE, &info);
    2096             :         if (err == 0) {
    2097             :                 DPRINTF(QLE_D_PORT, "%s: logged out of port %06x\n",
    2098             :                     DEVNAME(sc), port->portid);
    2099             :         } else {
    2100             :                 DPRINTF(QLE_D_PORT, "%s: failed to log out of port %06x: "
    2101             :                     "%x %x\n", DEVNAME(sc), port->portid, err, info);
    2102             :         }
    2103           0 : }
    2104             : 
    2105             : void
    2106           0 : qle_deferred_update(void *xsc)
    2107             : {
    2108           0 :         struct qle_softc *sc = xsc;
    2109           0 :         task_add(sc->sc_update_taskq, &sc->sc_update_task);
    2110           0 : }
    2111             : 
    2112             : void
    2113           0 : qle_do_update(void *xsc)
    2114             : {
    2115           0 :         struct qle_softc *sc = xsc;
    2116           0 :         int firstport, lastport;
    2117           0 :         struct qle_fc_port *port, *fport;
    2118             : 
    2119             :         DPRINTF(QLE_D_PORT, "%s: updating\n", DEVNAME(sc));
    2120           0 :         while (sc->sc_update_tasks != 0) {
    2121           0 :                 if (sc->sc_update_tasks & QLE_UPDATE_TASK_CLEAR_ALL) {
    2122           0 :                         TAILQ_HEAD(, qle_fc_port) detach;
    2123             :                         DPRINTF(QLE_D_PORT, "%s: detaching everything\n",
    2124             :                             DEVNAME(sc));
    2125             : 
    2126           0 :                         mtx_enter(&sc->sc_port_mtx);
    2127           0 :                         qle_clear_port_lists(sc);
    2128           0 :                         TAILQ_INIT(&detach);
    2129           0 :                         while (!TAILQ_EMPTY(&sc->sc_ports)) {
    2130           0 :                                 port = TAILQ_FIRST(&sc->sc_ports);
    2131           0 :                                 TAILQ_REMOVE(&sc->sc_ports, port, ports);
    2132           0 :                                 TAILQ_INSERT_TAIL(&detach, port, ports);
    2133             :                         }
    2134           0 :                         mtx_leave(&sc->sc_port_mtx);
    2135             : 
    2136           0 :                         while (!TAILQ_EMPTY(&detach)) {
    2137           0 :                                 port = TAILQ_FIRST(&detach);
    2138           0 :                                 TAILQ_REMOVE(&detach, port, ports);
    2139           0 :                                 if (port->flags & QLE_PORT_FLAG_IS_TARGET) {
    2140           0 :                                         scsi_detach_target(sc->sc_scsibus,
    2141           0 :                                             port->loopid, -1);
    2142           0 :                                         sc->sc_targets[port->loopid] = NULL;
    2143           0 :                                 }
    2144           0 :                                 if (port->location & QLE_LOCATION_FABRIC)
    2145           0 :                                         qle_fabric_plogo(sc, port);
    2146             : 
    2147           0 :                                 free(port, M_DEVBUF, sizeof *port);
    2148             :                         }
    2149             : 
    2150           0 :                         qle_update_done(sc, QLE_UPDATE_TASK_CLEAR_ALL);
    2151             :                         continue;
    2152           0 :                 }
    2153             : 
    2154           0 :                 if (sc->sc_update_tasks & QLE_UPDATE_TASK_SOFTRESET) {
    2155             :                         DPRINTF(QLE_D_IO, "%s: attempting softreset\n",
    2156             :                             DEVNAME(sc));
    2157           0 :                         if (qle_softreset(sc) != 0) {
    2158             :                                 DPRINTF(QLE_D_IO, "%s: couldn't softreset\n",
    2159             :                                     DEVNAME(sc));
    2160             :                         }
    2161           0 :                         qle_update_done(sc, QLE_UPDATE_TASK_SOFTRESET);
    2162           0 :                         continue;
    2163             :                 }
    2164             : 
    2165           0 :                 if (sc->sc_update_tasks & QLE_UPDATE_TASK_UPDATE_TOPO) {
    2166             :                         DPRINTF(QLE_D_PORT, "%s: updating topology\n",
    2167             :                             DEVNAME(sc));
    2168           0 :                         qle_update_topology(sc);
    2169           0 :                         qle_update_done(sc, QLE_UPDATE_TASK_UPDATE_TOPO);
    2170           0 :                         continue;
    2171             :                 }
    2172             : 
    2173           0 :                 if (sc->sc_update_tasks & QLE_UPDATE_TASK_GET_PORT_LIST) {
    2174             :                         DPRINTF(QLE_D_PORT, "%s: getting port name list\n",
    2175             :                             DEVNAME(sc));
    2176           0 :                         mtx_enter(&sc->sc_port_mtx);
    2177           0 :                         qle_clear_port_lists(sc);
    2178           0 :                         mtx_leave(&sc->sc_port_mtx);
    2179             : 
    2180           0 :                         qle_get_port_name_list(sc, QLE_LOCATION_LOOP |
    2181             :                             QLE_LOCATION_FABRIC);
    2182           0 :                         mtx_enter(&sc->sc_port_mtx);
    2183           0 :                         TAILQ_FOREACH(port, &sc->sc_ports, ports) {
    2184           0 :                                 TAILQ_INSERT_TAIL(&sc->sc_ports_gone, port,
    2185             :                                     update);
    2186           0 :                                 if (port->location & QLE_LOCATION_FABRIC) {
    2187           0 :                                         port->flags |=
    2188             :                                             QLE_PORT_FLAG_NEEDS_LOGIN;
    2189           0 :                                 }
    2190             :                         }
    2191             : 
    2192             :                         /* take care of ports that haven't changed first */
    2193           0 :                         TAILQ_FOREACH(fport, &sc->sc_ports_found, update) {
    2194           0 :                                 port = sc->sc_targets[fport->loopid];
    2195           0 :                                 if (port == NULL || fport->port_name !=
    2196           0 :                                     port->port_name) {
    2197             :                                         /* new or changed port, handled later */
    2198             :                                         continue;
    2199             :                                 }
    2200             : 
    2201             :                                 /*
    2202             :                                  * the port hasn't been logged out, which
    2203             :                                  * means we don't need to log in again, and,
    2204             :                                  * for loop ports, that the port still exists
    2205             :                                  */
    2206           0 :                                 port->flags &= ~QLE_PORT_FLAG_NEEDS_LOGIN;
    2207           0 :                                 if (port->location & QLE_LOCATION_LOOP)
    2208           0 :                                         TAILQ_REMOVE(&sc->sc_ports_gone,
    2209             :                                             port, update);
    2210             : 
    2211           0 :                                 fport->location = 0;
    2212           0 :                         }
    2213           0 :                         mtx_leave(&sc->sc_port_mtx);
    2214           0 :                         qle_update_start(sc, QLE_UPDATE_TASK_PORT_LIST);
    2215           0 :                         qle_update_done(sc, QLE_UPDATE_TASK_GET_PORT_LIST);
    2216           0 :                         continue;
    2217             :                 }
    2218             : 
    2219           0 :                 if (sc->sc_update_tasks & QLE_UPDATE_TASK_PORT_LIST) {
    2220           0 :                         mtx_enter(&sc->sc_port_mtx);
    2221           0 :                         fport = TAILQ_FIRST(&sc->sc_ports_found);
    2222           0 :                         if (fport != NULL) {
    2223           0 :                                 TAILQ_REMOVE(&sc->sc_ports_found, fport,
    2224             :                                     update);
    2225           0 :                         }
    2226           0 :                         mtx_leave(&sc->sc_port_mtx);
    2227             : 
    2228           0 :                         if (fport == NULL) {
    2229             :                                 DPRINTF(QLE_D_PORT, "%s: done with ports\n",
    2230             :                                     DEVNAME(sc));
    2231           0 :                                 qle_update_done(sc,
    2232             :                                     QLE_UPDATE_TASK_PORT_LIST);
    2233           0 :                                 qle_update_start(sc,
    2234             :                                     QLE_UPDATE_TASK_SCAN_FABRIC);
    2235           0 :                         } else if (fport->location & QLE_LOCATION_LOOP) {
    2236             :                                 DPRINTF(QLE_D_PORT, "%s: loop port %04x\n",
    2237             :                                     DEVNAME(sc), fport->loopid);
    2238           0 :                                 if (qle_add_loop_port(sc, fport) != 0)
    2239           0 :                                         free(fport, M_DEVBUF, sizeof *port);
    2240           0 :                         } else if (fport->location & QLE_LOCATION_FABRIC) {
    2241           0 :                                 qle_add_fabric_port(sc, fport);
    2242           0 :                         } else {
    2243             :                                 /* already processed */
    2244           0 :                                 free(fport, M_DEVBUF, sizeof *port);
    2245             :                         }
    2246           0 :                         continue;
    2247             :                 }
    2248             : 
    2249           0 :                 if (sc->sc_update_tasks & QLE_UPDATE_TASK_SCAN_FABRIC) {
    2250             :                         DPRINTF(QLE_D_PORT, "%s: starting fabric scan\n",
    2251             :                             DEVNAME(sc));
    2252           0 :                         lastport = sc->sc_port_id;
    2253           0 :                         firstport = 0xffffffff;
    2254           0 :                         if (qle_update_fabric(sc))
    2255           0 :                                 qle_update_start(sc,
    2256             :                                     QLE_UPDATE_TASK_SCANNING_FABRIC);
    2257             :                         else
    2258           0 :                                 qle_update_start(sc,
    2259             :                                     QLE_UPDATE_TASK_ATTACH_TARGET |
    2260             :                                     QLE_UPDATE_TASK_DETACH_TARGET);
    2261             : 
    2262           0 :                         qle_update_done(sc, QLE_UPDATE_TASK_SCAN_FABRIC);
    2263           0 :                         continue;
    2264             :                 }
    2265             : 
    2266           0 :                 if (sc->sc_update_tasks & QLE_UPDATE_TASK_SCANNING_FABRIC) {
    2267           0 :                         fport = qle_next_fabric_port(sc, &firstport, &lastport);
    2268           0 :                         if (fport != NULL) {
    2269             :                                 int disp;
    2270             : 
    2271           0 :                                 mtx_enter(&sc->sc_port_mtx);
    2272           0 :                                 disp = qle_classify_port(sc, fport->location,
    2273           0 :                                     fport->port_name, fport->node_name, &port);
    2274           0 :                                 switch (disp) {
    2275             :                                 case QLE_PORT_DISP_CHANGED:
    2276             :                                 case QLE_PORT_DISP_MOVED:
    2277             :                                         /* we'll log out the old port later */
    2278             :                                 case QLE_PORT_DISP_NEW:
    2279             :                                         DPRINTF(QLE_D_PORT, "%s: new port "
    2280             :                                             "%06x\n", DEVNAME(sc),
    2281             :                                             fport->portid);
    2282           0 :                                         TAILQ_INSERT_TAIL(&sc->sc_ports_found,
    2283             :                                             fport, update);
    2284           0 :                                         break;
    2285             :                                 case QLE_PORT_DISP_DUP:
    2286           0 :                                         free(fport, M_DEVBUF, sizeof *port);
    2287           0 :                                         break;
    2288             :                                 case QLE_PORT_DISP_SAME:
    2289             :                                         DPRINTF(QLE_D_PORT, "%s: existing port "
    2290             :                                             " %06x\n", DEVNAME(sc),
    2291             :                                             fport->portid);
    2292           0 :                                         TAILQ_REMOVE(&sc->sc_ports_gone, port,
    2293             :                                             update);
    2294           0 :                                         free(fport, M_DEVBUF, sizeof *port);
    2295           0 :                                         break;
    2296             :                                 }
    2297           0 :                                 mtx_leave(&sc->sc_port_mtx);
    2298           0 :                         }
    2299           0 :                         if (lastport == 0xffffffff) {
    2300             :                                 DPRINTF(QLE_D_PORT, "%s: finished\n",
    2301             :                                     DEVNAME(sc));
    2302           0 :                                 qle_update_done(sc,
    2303             :                                     QLE_UPDATE_TASK_SCANNING_FABRIC);
    2304           0 :                                 qle_update_start(sc,
    2305             :                                     QLE_UPDATE_TASK_FABRIC_LOGIN);
    2306           0 :                         }
    2307           0 :                         continue;
    2308             :                 }
    2309             : 
    2310           0 :                 if (sc->sc_update_tasks & QLE_UPDATE_TASK_FABRIC_LOGIN) {
    2311           0 :                         mtx_enter(&sc->sc_port_mtx);
    2312           0 :                         port = TAILQ_FIRST(&sc->sc_ports_found);
    2313           0 :                         if (port != NULL) {
    2314           0 :                                 TAILQ_REMOVE(&sc->sc_ports_found, port, update);
    2315           0 :                         }
    2316           0 :                         mtx_leave(&sc->sc_port_mtx);
    2317             : 
    2318           0 :                         if (port != NULL) {
    2319             :                                 DPRINTF(QLE_D_PORT, "%s: found port %06x\n",
    2320             :                                     DEVNAME(sc), port->portid);
    2321           0 :                                 if (qle_fabric_plogi(sc, port) == 0) {
    2322           0 :                                         qle_add_fabric_port(sc, port);
    2323           0 :                                 } else {
    2324             :                                         DPRINTF(QLE_D_PORT, "%s: plogi %06x "
    2325             :                                             "failed\n", DEVNAME(sc),
    2326             :                                             port->portid);
    2327           0 :                                         free(port, M_DEVBUF, sizeof *port);
    2328             :                                 }
    2329             :                         } else {
    2330             :                                 DPRINTF(QLE_D_PORT, "%s: done with logins\n",
    2331             :                                     DEVNAME(sc));
    2332           0 :                                 qle_update_done(sc,
    2333             :                                     QLE_UPDATE_TASK_FABRIC_LOGIN);
    2334           0 :                                 qle_update_start(sc,
    2335             :                                     QLE_UPDATE_TASK_ATTACH_TARGET |
    2336             :                                     QLE_UPDATE_TASK_DETACH_TARGET);
    2337             :                         }
    2338           0 :                         continue;
    2339             :                 }
    2340             : 
    2341           0 :                 if (sc->sc_update_tasks & QLE_UPDATE_TASK_FABRIC_RELOGIN) {
    2342           0 :                         TAILQ_FOREACH(port, &sc->sc_ports, ports) {
    2343           0 :                                 if (port->flags & QLE_PORT_FLAG_NEEDS_LOGIN) {
    2344           0 :                                         qle_fabric_plogi(sc, port);
    2345           0 :                                         break;
    2346             :                                 }
    2347             :                         }
    2348             : 
    2349           0 :                         if (port == NULL)
    2350           0 :                                 qle_update_done(sc,
    2351             :                                     QLE_UPDATE_TASK_FABRIC_RELOGIN);
    2352           0 :                         continue;
    2353             :                 }
    2354             : 
    2355           0 :                 if (sc->sc_update_tasks & QLE_UPDATE_TASK_DETACH_TARGET) {
    2356           0 :                         mtx_enter(&sc->sc_port_mtx);
    2357           0 :                         port = TAILQ_FIRST(&sc->sc_ports_gone);
    2358           0 :                         if (port != NULL) {
    2359           0 :                                 sc->sc_targets[port->loopid] = NULL;
    2360           0 :                                 TAILQ_REMOVE(&sc->sc_ports_gone, port, update);
    2361           0 :                                 TAILQ_REMOVE(&sc->sc_ports, port, ports);
    2362           0 :                         }
    2363           0 :                         mtx_leave(&sc->sc_port_mtx);
    2364             : 
    2365           0 :                         if (port != NULL) {
    2366             :                                 DPRINTF(QLE_D_PORT, "%s: detaching port %06x\n",
    2367             :                                     DEVNAME(sc), port->portid);
    2368           0 :                                 if (sc->sc_scsibus != NULL)
    2369           0 :                                         scsi_detach_target(sc->sc_scsibus,
    2370           0 :                                             port->loopid, -1);
    2371             : 
    2372           0 :                                 if (port->location & QLE_LOCATION_FABRIC)
    2373           0 :                                         qle_fabric_plogo(sc, port);
    2374             : 
    2375           0 :                                 free(port, M_DEVBUF, sizeof *port);
    2376           0 :                         } else {
    2377             :                                 DPRINTF(QLE_D_PORT, "%s: nothing to detach\n",
    2378             :                                     DEVNAME(sc));
    2379           0 :                                 qle_update_done(sc,
    2380             :                                     QLE_UPDATE_TASK_DETACH_TARGET);
    2381             :                         }
    2382           0 :                         continue;
    2383             :                 }
    2384             : 
    2385           0 :                 if (sc->sc_update_tasks & QLE_UPDATE_TASK_ATTACH_TARGET) {
    2386           0 :                         mtx_enter(&sc->sc_port_mtx);
    2387           0 :                         port = TAILQ_FIRST(&sc->sc_ports_new);
    2388           0 :                         if (port != NULL) {
    2389           0 :                                 TAILQ_REMOVE(&sc->sc_ports_new, port, update);
    2390           0 :                                 TAILQ_INSERT_TAIL(&sc->sc_ports, port, ports);
    2391           0 :                         }
    2392           0 :                         mtx_leave(&sc->sc_port_mtx);
    2393             : 
    2394           0 :                         if (port != NULL) {
    2395           0 :                                 if (sc->sc_scsibus != NULL)
    2396           0 :                                         scsi_probe_target(sc->sc_scsibus,
    2397           0 :                                             port->loopid);
    2398             :                         } else {
    2399           0 :                                 qle_update_done(sc,
    2400             :                                     QLE_UPDATE_TASK_ATTACH_TARGET);
    2401             :                         }
    2402           0 :                         continue;
    2403             :                 }
    2404             : 
    2405             :         }
    2406             : 
    2407             :         DPRINTF(QLE_D_PORT, "%s: done updating\n", DEVNAME(sc));
    2408           0 : }
    2409             : 
    2410             : int
    2411           0 : qle_async(struct qle_softc *sc, u_int16_t info)
    2412             : {
    2413           0 :         switch (info) {
    2414             :         case QLE_ASYNC_SYSTEM_ERROR:
    2415           0 :                 qle_update_start(sc, QLE_UPDATE_TASK_SOFTRESET);
    2416           0 :                 break;
    2417             : 
    2418             :         case QLE_ASYNC_REQ_XFER_ERROR:
    2419           0 :                 qle_update_start(sc, QLE_UPDATE_TASK_SOFTRESET);
    2420           0 :                 break;
    2421             : 
    2422             :         case QLE_ASYNC_RSP_XFER_ERROR:
    2423           0 :                 qle_update_start(sc, QLE_UPDATE_TASK_SOFTRESET);
    2424           0 :                 break;
    2425             : 
    2426             :         case QLE_ASYNC_LIP_OCCURRED:
    2427             :                 DPRINTF(QLE_D_INTR, "%s: lip occurred\n", DEVNAME(sc));
    2428             :                 break;
    2429             : 
    2430             :         case QLE_ASYNC_LOOP_UP:
    2431             :                 DPRINTF(QLE_D_PORT, "%s: loop up\n", DEVNAME(sc));
    2432           0 :                 sc->sc_loop_up = 1;
    2433           0 :                 sc->sc_marker_required = 1;
    2434           0 :                 qle_update_defer(sc, QLE_UPDATE_TASK_UPDATE_TOPO |
    2435             :                     QLE_UPDATE_TASK_GET_PORT_LIST);
    2436           0 :                 break;
    2437             : 
    2438             :         case QLE_ASYNC_LOOP_DOWN:
    2439             :                 DPRINTF(QLE_D_PORT, "%s: loop down\n", DEVNAME(sc));
    2440           0 :                 sc->sc_loop_up = 0;
    2441           0 :                 qle_update_cancel(sc);
    2442           0 :                 qle_update_start(sc, QLE_UPDATE_TASK_CLEAR_ALL);
    2443           0 :                 break;
    2444             : 
    2445             :         case QLE_ASYNC_LIP_RESET:
    2446             :                 DPRINTF(QLE_D_PORT, "%s: lip reset\n", DEVNAME(sc));
    2447           0 :                 sc->sc_marker_required = 1;
    2448           0 :                 qle_update_defer(sc, QLE_UPDATE_TASK_FABRIC_RELOGIN);
    2449           0 :                 break;
    2450             : 
    2451             :         case QLE_ASYNC_PORT_DB_CHANGE:
    2452             :                 DPRINTF(QLE_D_PORT, "%s: port db changed %x\n", DEVNAME(sc),
    2453             :                     qle_read_mbox(sc, 1));
    2454           0 :                 qle_update_start(sc, QLE_UPDATE_TASK_GET_PORT_LIST);
    2455           0 :                 break;
    2456             : 
    2457             :         case QLE_ASYNC_CHANGE_NOTIFY:
    2458             :                 DPRINTF(QLE_D_PORT, "%s: name server change (%02x:%02x)\n",
    2459             :                     DEVNAME(sc), qle_read_mbox(sc, 1), qle_read_mbox(sc, 2));
    2460           0 :                 qle_update_start(sc, QLE_UPDATE_TASK_GET_PORT_LIST);
    2461           0 :                 break;
    2462             : 
    2463             :         case QLE_ASYNC_LIP_F8:
    2464             :                 DPRINTF(QLE_D_INTR, "%s: lip f8\n", DEVNAME(sc));
    2465             :                 break;
    2466             : 
    2467             :         case QLE_ASYNC_LOOP_INIT_ERROR:
    2468             :                 DPRINTF(QLE_D_PORT, "%s: loop initialization error: %x\n",
    2469             :                     DEVNAME(sc), qle_read_mbox(sc, 1));
    2470             :                 break;
    2471             : 
    2472             :         case QLE_ASYNC_POINT_TO_POINT:
    2473             :                 DPRINTF(QLE_D_PORT, "%s: connected in point-to-point mode\n",
    2474             :                     DEVNAME(sc));
    2475             :                 break;
    2476             : 
    2477             :         case QLE_ASYNC_ZIO_RESP_UPDATE:
    2478             :                 /* shouldn't happen, we don't do zio */
    2479             :                 break;
    2480             : 
    2481             :         default:
    2482             :                 DPRINTF(QLE_D_INTR, "%s: unknown async %x\n", DEVNAME(sc), info);
    2483             :                 break;
    2484             :         }
    2485           0 :         return (1);
    2486             : }
    2487             : 
    2488             : void
    2489           0 : qle_dump_stuff(struct qle_softc *sc, void *buf, int n)
    2490             : {
    2491             : #ifdef QLE_DEBUG
    2492             :         u_int8_t *d = buf;
    2493             :         int l;
    2494             : 
    2495             :         if ((qledebug & QLE_D_IOCB) == 0)
    2496             :                 return;
    2497             : 
    2498             :         printf("%s: stuff\n", DEVNAME(sc));
    2499             :         for (l = 0; l < n; l++) {
    2500             :                 printf(" %2.2x", d[l]);
    2501             :                 if (l % 16 == 15)
    2502             :                         printf("\n");
    2503             :         }
    2504             :         if (n % 16 != 0)
    2505             :                 printf("\n");
    2506             : #endif
    2507           0 : }
    2508             : 
    2509             : void
    2510           0 : qle_dump_iocb(struct qle_softc *sc, void *buf)
    2511             : {
    2512             : #ifdef QLE_DEBUG
    2513             :         u_int8_t *iocb = buf;
    2514             :         int l;
    2515             :         int b;
    2516             : 
    2517             :         if ((qledebug & QLE_D_IOCB) == 0)
    2518             :                 return;
    2519             : 
    2520             :         printf("%s: iocb:\n", DEVNAME(sc));
    2521             :         for (l = 0; l < 4; l++) {
    2522             :                 for (b = 0; b < 16; b++) {
    2523             :                         printf(" %2.2x", iocb[(l*16)+b]);
    2524             :                 }
    2525             :                 printf("\n");
    2526             :         }
    2527             : #endif
    2528           0 : }
    2529             : 
    2530             : void
    2531           0 : qle_dump_iocb_segs(struct qle_softc *sc, void *segs, int n)
    2532             : {
    2533             : #ifdef QLE_DEBUG
    2534             :         u_int8_t *buf = segs;
    2535             :         int s, b;
    2536             : 
    2537             :         if ((qledebug & QLE_D_IOCB) == 0)
    2538             :                 return;
    2539             : 
    2540             :         printf("%s: iocb segs:\n", DEVNAME(sc));
    2541             :         for (s = 0; s < n; s++) {
    2542             :                 for (b = 0; b < sizeof(struct qle_iocb_seg); b++) {
    2543             :                         printf(" %2.2x", buf[(s*(sizeof(struct qle_iocb_seg)))
    2544             :                             + b]);
    2545             :                 }
    2546             :                 printf("\n");
    2547             :         }
    2548             : #endif
    2549           0 : }
    2550             : 
    2551             : void
    2552           0 : qle_put_marker(struct qle_softc *sc, void *buf)
    2553             : {
    2554           0 :         struct qle_iocb_marker *marker = buf;
    2555             : 
    2556           0 :         marker->entry_type = QLE_IOCB_MARKER;
    2557           0 :         marker->entry_count = 1;
    2558           0 :         marker->seqno = 0;
    2559           0 :         marker->flags = 0;
    2560             : 
    2561             :         /* could be more specific here; isp(4) isn't */
    2562           0 :         marker->target = 0;
    2563           0 :         marker->modifier = QLE_IOCB_MARKER_SYNC_ALL;
    2564           0 : }
    2565             : 
    2566             : void
    2567           0 : qle_sge(struct qle_iocb_seg *seg, u_int64_t addr, u_int32_t len)
    2568             : {
    2569           0 :         htolem32(&seg->seg_addr_lo, addr);
    2570           0 :         htolem32(&seg->seg_addr_hi, addr >> 32);
    2571           0 :         htolem32(&seg->seg_len, len);
    2572           0 : }
    2573             : 
    2574             : void
    2575           0 : qle_put_cmd(struct qle_softc *sc, void *buf, struct scsi_xfer *xs,
    2576             :     struct qle_ccb *ccb, u_int32_t target_port)
    2577             : {
    2578           0 :         bus_dmamap_t dmap = ccb->ccb_dmamap;
    2579           0 :         struct qle_iocb_req6 *req = buf;
    2580             :         struct qle_fcp_cmnd *cmnd;
    2581             :         u_int64_t fcp_cmnd_offset;
    2582             :         u_int32_t fcp_dl;
    2583             :         int seg;
    2584           0 :         int target = xs->sc_link->target;
    2585           0 :         int lun = xs->sc_link->lun;
    2586             :         u_int16_t flags;
    2587             : 
    2588           0 :         memset(req, 0, sizeof(*req));
    2589           0 :         req->entry_type = QLE_IOCB_CMD_TYPE_6;
    2590           0 :         req->entry_count = 1;
    2591             : 
    2592           0 :         req->req_handle = ccb->ccb_id;
    2593           0 :         htolem16(&req->req_nport_handle, target);
    2594             :         
    2595             :         /*
    2596             :          * timeout is in seconds.  make sure it's at least 1 if a timeout
    2597             :          * was specified in xs
    2598             :          */
    2599           0 :         if (xs->timeout != 0)
    2600           0 :                 htolem16(&req->req_timeout, MAX(1, xs->timeout/1000));
    2601             : 
    2602           0 :         if (xs->datalen > 0) {
    2603           0 :                 flags = (xs->flags & SCSI_DATA_IN) ?
    2604             :                     QLE_IOCB_CTRL_FLAG_READ : QLE_IOCB_CTRL_FLAG_WRITE;
    2605           0 :                 if (dmap->dm_nsegs == 1) {
    2606           0 :                         qle_sge(&req->req_data_seg, dmap->dm_segs[0].ds_addr,
    2607           0 :                             dmap->dm_segs[0].ds_len);
    2608           0 :                 } else {
    2609           0 :                         flags |= QLE_IOCB_CTRL_FLAG_EXT_SEG;
    2610           0 :                         for (seg = 0; seg < dmap->dm_nsegs; seg++) {
    2611           0 :                                 qle_sge(&ccb->ccb_segs[seg],
    2612           0 :                                     dmap->dm_segs[seg].ds_addr,
    2613           0 :                                     dmap->dm_segs[seg].ds_len);
    2614             :                         }
    2615           0 :                         qle_sge(&ccb->ccb_segs[seg++], 0, 0);
    2616             : 
    2617           0 :                         bus_dmamap_sync(sc->sc_dmat,
    2618             :                             QLE_DMA_MAP(sc->sc_segments), ccb->ccb_seg_offset,
    2619             :                             seg * sizeof(*ccb->ccb_segs),
    2620             :                             BUS_DMASYNC_PREWRITE);
    2621             : 
    2622           0 :                         qle_sge(&req->req_data_seg,
    2623           0 :                             QLE_DMA_DVA(sc->sc_segments) + ccb->ccb_seg_offset,
    2624           0 :                             seg * sizeof(struct qle_iocb_seg));
    2625             :                 }
    2626             : 
    2627           0 :                 htolem16(&req->req_data_seg_count, dmap->dm_nsegs);
    2628           0 :                 htolem32(&req->req_data_len, xs->datalen);
    2629           0 :                 htolem16(&req->req_ctrl_flags, flags);
    2630           0 :         }
    2631             : 
    2632           0 :         htobem16(&req->req_fcp_lun[0], lun);
    2633           0 :         htobem16(&req->req_fcp_lun[1], lun >> 16);
    2634           0 :         htolem32(&req->req_target_id, target_port & 0xffffff);
    2635             : 
    2636           0 :         fcp_cmnd_offset = ccb->ccb_id * sizeof(*cmnd);
    2637             :         /* set up FCP_CMND */
    2638           0 :         cmnd = (struct qle_fcp_cmnd *)QLE_DMA_KVA(sc->sc_fcp_cmnds) +
    2639             :             ccb->ccb_id;
    2640             : 
    2641           0 :         memset(cmnd, 0, sizeof(*cmnd));
    2642           0 :         htobem16(&cmnd->fcp_lun[0], lun);
    2643           0 :         htobem16(&cmnd->fcp_lun[1], lun >> 16);
    2644             :         /* cmnd->fcp_task_attr = TSK_SIMPLE; */
    2645             :         /* cmnd->fcp_task_mgmt = 0; */
    2646           0 :         memcpy(cmnd->fcp_cdb, xs->cmd, xs->cmdlen);
    2647             : 
    2648             :         /* FCP_DL goes after the cdb */
    2649           0 :         fcp_dl = htobe32(xs->datalen);
    2650           0 :         if (xs->cmdlen > 16) {
    2651           0 :                 htolem16(&req->req_fcp_cmnd_len, 12 + xs->cmdlen + 4);
    2652           0 :                 cmnd->fcp_add_cdb_len = xs->cmdlen - 16;
    2653           0 :                 memcpy(cmnd->fcp_cdb + xs->cmdlen, &fcp_dl, sizeof(fcp_dl));
    2654           0 :         } else {
    2655           0 :                 htolem16(&req->req_fcp_cmnd_len, 12 + 16 + 4);
    2656           0 :                 cmnd->fcp_add_cdb_len = 0;
    2657           0 :                 memcpy(cmnd->fcp_cdb + 16, &fcp_dl, sizeof(fcp_dl));
    2658             :         }
    2659           0 :         if (xs->datalen > 0)
    2660           0 :                 cmnd->fcp_add_cdb_len |= (xs->flags & SCSI_DATA_IN) ? 2 : 1;
    2661             :         
    2662           0 :         bus_dmamap_sync(sc->sc_dmat,
    2663             :             QLE_DMA_MAP(sc->sc_fcp_cmnds), fcp_cmnd_offset,
    2664             :             sizeof(*cmnd), BUS_DMASYNC_PREWRITE);
    2665             : 
    2666             :         /* link req to cmnd */
    2667           0 :         fcp_cmnd_offset += QLE_DMA_DVA(sc->sc_fcp_cmnds);
    2668           0 :         htolem32(&req->req_fcp_cmnd_addr_lo, fcp_cmnd_offset);
    2669           0 :         htolem32(&req->req_fcp_cmnd_addr_hi, fcp_cmnd_offset >> 32);
    2670           0 : }
    2671             : 
    2672             : int
    2673           0 : qle_load_fwchunk(struct qle_softc *sc, struct qle_dmamem *mem,
    2674             :     const u_int32_t *src)
    2675             : {
    2676             :         u_int32_t dest, done, total;
    2677             :         int i;
    2678             : 
    2679           0 :         dest = src[2];
    2680             :         done = 0;
    2681           0 :         total = src[3];
    2682             : 
    2683           0 :         while (done < total) {
    2684             :                 u_int32_t *copy;
    2685             :                 u_int32_t words;
    2686             : 
    2687             :                 /* limit transfer size otherwise it just doesn't work */
    2688           0 :                 words = MIN(total - done, 1 << 10);
    2689           0 :                 copy = QLE_DMA_KVA(mem);
    2690           0 :                 for (i = 0; i < words; i++) {
    2691           0 :                         htolem32(&copy[i], src[done++]);
    2692             :                 }
    2693           0 :                 bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(mem), 0, words * 4,
    2694             :                     BUS_DMASYNC_PREWRITE);
    2695             : 
    2696           0 :                 sc->sc_mbox[0] = QLE_MBOX_LOAD_RISC_RAM;
    2697           0 :                 sc->sc_mbox[1] = dest;
    2698           0 :                 sc->sc_mbox[4] = words >> 16;
    2699           0 :                 sc->sc_mbox[5] = words & 0xffff;
    2700           0 :                 sc->sc_mbox[8] = dest >> 16;
    2701           0 :                 qle_mbox_putaddr(sc->sc_mbox, mem);
    2702           0 :                 if (qle_mbox(sc, 0x01ff)) {
    2703           0 :                         printf("firmware load failed\n");
    2704           0 :                         return (1);
    2705             :                 }
    2706           0 :                 bus_dmamap_sync(sc->sc_dmat, QLE_DMA_MAP(mem), 0, words * 4,
    2707             :                     BUS_DMASYNC_POSTWRITE);
    2708             : 
    2709           0 :                 dest += words;
    2710           0 :         }
    2711             : 
    2712           0 :         return (qle_verify_firmware(sc, src[2]));
    2713           0 : }
    2714             : 
    2715             : int
    2716           0 : qle_load_firmware_chunks(struct qle_softc *sc, const u_int32_t *fw)
    2717             : {
    2718             :         struct qle_dmamem *mem;
    2719             :         int res = 0;
    2720             : 
    2721           0 :         mem = qle_dmamem_alloc(sc, 65536);
    2722           0 :         for (;;) {
    2723           0 :                 if (qle_load_fwchunk(sc, mem, fw)) {
    2724             :                         res = 1;
    2725           0 :                         break;
    2726             :                 }
    2727           0 :                 if (fw[1] == 0)
    2728             :                         break;
    2729           0 :                 fw += fw[3];
    2730             :         }
    2731             : 
    2732           0 :         qle_dmamem_free(sc, mem);
    2733           0 :         return (res);
    2734             : }
    2735             : 
    2736             : u_int32_t
    2737           0 : qle_read_ram_word(struct qle_softc *sc, u_int32_t addr)
    2738             : {
    2739           0 :         sc->sc_mbox[0] = QLE_MBOX_READ_RISC_RAM;
    2740           0 :         sc->sc_mbox[1] = addr & 0xffff;
    2741           0 :         sc->sc_mbox[8] = addr >> 16;
    2742           0 :         if (qle_mbox(sc, 0x0103)) {
    2743           0 :                 return (0);
    2744             :         }
    2745           0 :         return ((sc->sc_mbox[3] << 16) | sc->sc_mbox[2]);
    2746           0 : }
    2747             : 
    2748             : int
    2749           0 : qle_verify_firmware(struct qle_softc *sc, u_int32_t addr)
    2750             : {
    2751             :         /*
    2752             :          * QLE_MBOX_VERIFY_CSUM requires at least the firmware header
    2753             :          * to be correct, otherwise it wanders all over ISP memory and
    2754             :          * gets lost.  Check that chunk address (addr+2) is right and
    2755             :          * size (addr+3) is plausible first.
    2756             :          */
    2757           0 :         if ((qle_read_ram_word(sc, addr+2) != addr) ||
    2758           0 :             (qle_read_ram_word(sc, addr+3) > 0xffff)) {
    2759           0 :                 return (1);
    2760             :         }
    2761             : 
    2762           0 :         sc->sc_mbox[0] = QLE_MBOX_VERIFY_CSUM;
    2763           0 :         sc->sc_mbox[1] = addr >> 16;
    2764           0 :         sc->sc_mbox[2] = addr;
    2765           0 :         if (qle_mbox(sc, 0x0007)) {
    2766           0 :                 return (1);
    2767             :         }
    2768           0 :         return (0);
    2769           0 : }
    2770             : 
    2771             : int
    2772           0 : qle_read_nvram(struct qle_softc *sc)
    2773             : {
    2774           0 :         u_int32_t data[sizeof(sc->sc_nvram) / 4];
    2775             :         u_int32_t csum, tmp, v;
    2776             :         int i, base, l;
    2777             : 
    2778           0 :         switch (sc->sc_isp_gen) {
    2779             :         case QLE_GEN_ISP24XX:
    2780             :                 base = 0x7ffe0080;
    2781           0 :                 break;
    2782             :         case QLE_GEN_ISP25XX:
    2783             :                 base = 0x7ff48080;
    2784           0 :                 break;
    2785             :         }
    2786           0 :         base += sc->sc_port * 0x100;
    2787             :         
    2788             :         csum = 0;
    2789           0 :         for (i = 0; i < nitems(data); i++) {
    2790           0 :                 data[i] = 0xffffffff;
    2791           0 :                 qle_write(sc, QLE_FLASH_NVRAM_ADDR, base + i);
    2792           0 :                 for (l = 0; l < 5000; l++) {
    2793           0 :                         delay(10);
    2794           0 :                         tmp = qle_read(sc, QLE_FLASH_NVRAM_ADDR);
    2795           0 :                         if (tmp & (1U << 31)) {
    2796           0 :                                 v = qle_read(sc, QLE_FLASH_NVRAM_DATA);
    2797           0 :                                 csum += v;
    2798           0 :                                 data[i] = letoh32(v);
    2799           0 :                                 break;
    2800             :                         }
    2801             :                 }
    2802             :         }
    2803             : 
    2804           0 :         bcopy(data, &sc->sc_nvram, sizeof(sc->sc_nvram));
    2805             :         /* id field should be 'ISP' */
    2806           0 :         if (sc->sc_nvram.id[0] != 'I' || sc->sc_nvram.id[1] != 'S' ||
    2807           0 :             sc->sc_nvram.id[2] != 'P' || csum != 0) {
    2808           0 :                 printf("%s: nvram corrupt\n", DEVNAME(sc));
    2809           0 :                 return (1);
    2810             :         }
    2811           0 :         return (0);
    2812           0 : }
    2813             : 
    2814             : struct qle_dmamem *
    2815           0 : qle_dmamem_alloc(struct qle_softc *sc, size_t size)
    2816             : {
    2817             :         struct qle_dmamem *m;
    2818           0 :         int nsegs;
    2819             : 
    2820           0 :         m = malloc(sizeof(*m), M_DEVBUF, M_NOWAIT | M_ZERO);
    2821           0 :         if (m == NULL)
    2822           0 :                 return (NULL);
    2823             : 
    2824           0 :         m->qdm_size = size;
    2825             : 
    2826           0 :         if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
    2827           0 :             BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &m->qdm_map) != 0)
    2828             :                 goto qdmfree;
    2829             : 
    2830           0 :         if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &m->qdm_seg, 1,
    2831           0 :             &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0)
    2832             :                 goto destroy;
    2833             : 
    2834           0 :         if (bus_dmamem_map(sc->sc_dmat, &m->qdm_seg, nsegs, size, &m->qdm_kva,
    2835           0 :             BUS_DMA_NOWAIT) != 0)
    2836             :                 goto free;
    2837             : 
    2838           0 :         if (bus_dmamap_load(sc->sc_dmat, m->qdm_map, m->qdm_kva, size, NULL,
    2839           0 :             BUS_DMA_NOWAIT) != 0)
    2840             :                 goto unmap;
    2841             : 
    2842           0 :         return (m);
    2843             : 
    2844             : unmap:
    2845           0 :         bus_dmamem_unmap(sc->sc_dmat, m->qdm_kva, m->qdm_size);
    2846             : free:
    2847           0 :         bus_dmamem_free(sc->sc_dmat, &m->qdm_seg, 1);
    2848             : destroy:
    2849           0 :         bus_dmamap_destroy(sc->sc_dmat, m->qdm_map);
    2850             : qdmfree:
    2851           0 :         free(m, M_DEVBUF, sizeof *m);
    2852             : 
    2853           0 :         return (NULL);
    2854           0 : }
    2855             : 
    2856             : void
    2857           0 : qle_dmamem_free(struct qle_softc *sc, struct qle_dmamem *m)
    2858             : {
    2859           0 :         bus_dmamap_unload(sc->sc_dmat, m->qdm_map);
    2860           0 :         bus_dmamem_unmap(sc->sc_dmat, m->qdm_kva, m->qdm_size);
    2861           0 :         bus_dmamem_free(sc->sc_dmat, &m->qdm_seg, 1);
    2862           0 :         bus_dmamap_destroy(sc->sc_dmat, m->qdm_map);
    2863           0 :         free(m, M_DEVBUF, sizeof *m);
    2864           0 : }
    2865             : 
    2866             : int
    2867           0 : qle_alloc_ccbs(struct qle_softc *sc)
    2868             : {
    2869             :         struct qle_ccb          *ccb;
    2870             :         u_int8_t                *cmd;
    2871             :         int                     i;
    2872             : 
    2873           0 :         SIMPLEQ_INIT(&sc->sc_ccb_free);
    2874           0 :         mtx_init(&sc->sc_ccb_mtx, IPL_BIO);
    2875           0 :         mtx_init(&sc->sc_queue_mtx, IPL_BIO);
    2876           0 :         mtx_init(&sc->sc_port_mtx, IPL_BIO);
    2877           0 :         mtx_init(&sc->sc_mbox_mtx, IPL_BIO);
    2878             : 
    2879           0 :         sc->sc_ccbs = mallocarray(sc->sc_maxcmds, sizeof(struct qle_ccb),
    2880             :             M_DEVBUF, M_WAITOK | M_CANFAIL | M_ZERO);
    2881           0 :         if (sc->sc_ccbs == NULL) {
    2882           0 :                 printf("%s: unable to allocate ccbs\n", DEVNAME(sc));
    2883           0 :                 return (1);
    2884             :         }
    2885             : 
    2886           0 :         sc->sc_requests = qle_dmamem_alloc(sc, sc->sc_maxcmds *
    2887             :             QLE_QUEUE_ENTRY_SIZE);
    2888           0 :         if (sc->sc_requests == NULL) {
    2889           0 :                 printf("%s: unable to allocate ccb dmamem\n", DEVNAME(sc));
    2890           0 :                 goto free_ccbs;
    2891             :         }
    2892           0 :         sc->sc_responses = qle_dmamem_alloc(sc, sc->sc_maxcmds *
    2893             :             QLE_QUEUE_ENTRY_SIZE);
    2894           0 :         if (sc->sc_responses == NULL) {
    2895           0 :                 printf("%s: unable to allocate rcb dmamem\n", DEVNAME(sc));
    2896           0 :                 goto free_req;
    2897             :         }
    2898           0 :         sc->sc_pri_requests = qle_dmamem_alloc(sc, 8 * QLE_QUEUE_ENTRY_SIZE);
    2899           0 :         if (sc->sc_pri_requests == NULL) {
    2900           0 :                 printf("%s: unable to allocate pri ccb dmamem\n", DEVNAME(sc));
    2901           0 :                 goto free_pri;
    2902             :         }
    2903           0 :         sc->sc_segments = qle_dmamem_alloc(sc, sc->sc_maxcmds * QLE_MAX_SEGS *
    2904             :             sizeof(struct qle_iocb_seg));
    2905           0 :         if (sc->sc_segments == NULL) {
    2906           0 :                 printf("%s: unable to allocate iocb segments\n", DEVNAME(sc));
    2907           0 :                 goto free_res;
    2908             :         }
    2909             : 
    2910           0 :         sc->sc_fcp_cmnds = qle_dmamem_alloc(sc, sc->sc_maxcmds *
    2911             :             sizeof(struct qle_fcp_cmnd));
    2912           0 :         if (sc->sc_fcp_cmnds == NULL) {
    2913           0 :                 printf("%s: unable to allocate FCP_CMNDs\n", DEVNAME(sc));
    2914           0 :                 goto free_seg;
    2915             :         }
    2916             : 
    2917           0 :         cmd = QLE_DMA_KVA(sc->sc_requests);
    2918           0 :         memset(cmd, 0, QLE_QUEUE_ENTRY_SIZE * sc->sc_maxcmds);
    2919           0 :         for (i = 0; i < sc->sc_maxcmds; i++) {
    2920           0 :                 ccb = &sc->sc_ccbs[i];
    2921             : 
    2922           0 :                 if (bus_dmamap_create(sc->sc_dmat, MAXPHYS,
    2923             :                     QLE_MAX_SEGS-1, MAXPHYS, 0,
    2924             :                     BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
    2925           0 :                     &ccb->ccb_dmamap) != 0) {
    2926           0 :                         printf("%s: unable to create dma map\n", DEVNAME(sc));
    2927             :                         goto free_maps;
    2928             :                 }
    2929             : 
    2930           0 :                 ccb->ccb_sc = sc;
    2931           0 :                 ccb->ccb_id = i;
    2932             : 
    2933           0 :                 ccb->ccb_seg_offset = i * QLE_MAX_SEGS *
    2934             :                     sizeof(struct qle_iocb_seg);
    2935           0 :                 ccb->ccb_segs = QLE_DMA_KVA(sc->sc_segments) +
    2936             :                     ccb->ccb_seg_offset;
    2937             : 
    2938           0 :                 qle_put_ccb(sc, ccb);
    2939             :         }
    2940             : 
    2941           0 :         scsi_iopool_init(&sc->sc_iopool, sc, qle_get_ccb, qle_put_ccb);
    2942           0 :         return (0);
    2943             : 
    2944             : free_maps:
    2945           0 :         while ((ccb = qle_get_ccb(sc)) != NULL)
    2946           0 :                 bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
    2947             : 
    2948           0 :         qle_dmamem_free(sc, sc->sc_fcp_cmnds);
    2949             : free_seg:
    2950           0 :         qle_dmamem_free(sc, sc->sc_segments);
    2951             : free_pri:
    2952           0 :         qle_dmamem_free(sc, sc->sc_pri_requests);
    2953             : free_res:
    2954           0 :         qle_dmamem_free(sc, sc->sc_responses);
    2955             : free_req:
    2956           0 :         qle_dmamem_free(sc, sc->sc_requests);
    2957             : free_ccbs:
    2958           0 :         free(sc->sc_ccbs, M_DEVBUF, 0);
    2959             : 
    2960           0 :         return (1);
    2961           0 : }
    2962             : 
    2963             : void
    2964           0 : qle_free_ccbs(struct qle_softc *sc)
    2965             : {
    2966             :         struct qle_ccb          *ccb;
    2967             : 
    2968           0 :         scsi_iopool_destroy(&sc->sc_iopool);
    2969           0 :         while ((ccb = qle_get_ccb(sc)) != NULL)
    2970           0 :                 bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
    2971           0 :         qle_dmamem_free(sc, sc->sc_segments);
    2972           0 :         qle_dmamem_free(sc, sc->sc_responses);
    2973           0 :         qle_dmamem_free(sc, sc->sc_requests);
    2974           0 :         free(sc->sc_ccbs, M_DEVBUF, 0);
    2975           0 : }
    2976             : 
    2977             : void *
    2978           0 : qle_get_ccb(void *xsc)
    2979             : {
    2980           0 :         struct qle_softc        *sc = xsc;
    2981             :         struct qle_ccb          *ccb;
    2982             : 
    2983           0 :         mtx_enter(&sc->sc_ccb_mtx);
    2984           0 :         ccb = SIMPLEQ_FIRST(&sc->sc_ccb_free);
    2985           0 :         if (ccb != NULL) {
    2986           0 :                 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ccb_link);
    2987             :         }
    2988           0 :         mtx_leave(&sc->sc_ccb_mtx);
    2989           0 :         return (ccb);
    2990             : }
    2991             : 
    2992             : void
    2993           0 : qle_put_ccb(void *xsc, void *io)
    2994             : {
    2995           0 :         struct qle_softc        *sc = xsc;
    2996           0 :         struct qle_ccb          *ccb = io;
    2997             : 
    2998           0 :         ccb->ccb_xs = NULL;
    2999           0 :         mtx_enter(&sc->sc_ccb_mtx);
    3000           0 :         SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ccb, ccb_link);
    3001           0 :         mtx_leave(&sc->sc_ccb_mtx);
    3002           0 : }

Generated by: LCOV version 1.13