The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/isp/isp_freebsd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $FreeBSD: src/sys/dev/isp/isp_freebsd.c,v 1.20.2.5 2000/03/04 06:04:52 mjacob Exp $ */
    2 /*
    3  * Platform (FreeBSD 2.X) dependent common attachment code for Qlogic adapters.
    4  *
    5  *---------------------------------------
    6  * Copyright (c) 1997, 1998 by Matthew Jacob
    7  * NASA/Ames Research Center
    8  * All rights reserved.
    9  *---------------------------------------
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice immediately at the beginning of the file, without modification,
   16  *    this list of conditions, and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. The name of the author may not be used to endorse or promote products
   21  *    derived from this software without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   27  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  */
   35 #include <dev/isp/isp_freebsd.h>
   36 
   37 static void ispminphys(struct buf *);
   38 static u_int32_t isp_adapter_info(int);
   39 static int ispcmd_slow(struct scsi_xfer *);
   40 static int ispcmd(struct scsi_xfer *);
   41 static struct scsi_adapter isp_switch = {
   42         ispcmd_slow, ispminphys, 0, 0, isp_adapter_info, "isp", { 0, 0 }
   43 };
   44 static struct scsi_device isp_dev = {
   45         NULL, NULL, NULL, NULL, "isp", 0, { 0, 0 }
   46 };
   47 static int isp_poll(struct ispsoftc *, struct scsi_xfer *, int);
   48 static void isp_watch(void *);
   49 static void isp_command_requeue(void *);
   50 static void isp_internal_restart(void *);
   51 
   52 /*
   53  * Complete attachment of hardware, include subdevices.
   54  */
   55 void
   56 isp_attach(struct ispsoftc *isp)
   57 {
   58         struct scsibus_data *scbus, *scbusb = NULL;
   59 
   60         scbus = scsi_alloc_bus(); 
   61         if(!scbus) {
   62                 return;
   63         }
   64 
   65         isp->isp_state = ISP_RUNSTATE;
   66 
   67         isp->isp_osinfo._link.adapter_unit = isp->isp_osinfo.unit;
   68         isp->isp_osinfo._link.adapter_softc = isp;
   69         isp->isp_osinfo._link.device = &isp_dev;
   70         isp->isp_osinfo._link.flags = 0;
   71         isp->isp_osinfo._link.opennings = isp->isp_maxcmds;
   72         isp->isp_osinfo._link.adapter = &isp_switch;
   73         isp->isp_osinfo.wqf = isp->isp_osinfo.wqt = NULL;
   74 
   75         if (IS_FC(isp)) {
   76                 int i, j;
   77                 fcparam *fcp = isp->isp_param;
   78                 SYS_DELAY(2 * 1000000);
   79                 for (j = 0; j < 5; j++) {
   80                         for (i = 0; i < 5; i++) {
   81                                 if (isp_control(isp, ISPCTL_FCLINK_TEST, NULL))
   82                                         continue;
   83 #ifdef  ISP2100_FABRIC
   84                                 /*
   85                                  * Wait extra time to see if the f/w
   86                                  * eventually completed an FLOGI that
   87                                  * will allow us to know we're on a
   88                                  * fabric.
   89                                  */
   90                                 if (fcp->isp_onfabric == 0) {
   91                                         SYS_DELAY(1 * 1000000);
   92                                         continue;
   93                                 }
   94 #endif
   95                                 break;
   96                         }
   97                         if (fcp->isp_fwstate == FW_READY &&
   98                             fcp->isp_loopstate >= LOOP_PDB_RCVD) { 
   99                                 break;
  100                         }
  101                 }
  102                 isp->isp_osinfo._link.adapter_targ = fcp->isp_loopid;
  103                 scbus->maxtarg = MAX_FC_TARG-1;
  104         } else {
  105                 int bus = 0;
  106                 sdparam *sdp = isp->isp_param;
  107 
  108                 (void) isp_control(isp, ISPCTL_RESET_BUS, &bus);
  109 
  110                 isp->isp_osinfo.discovered[0] = 1 << sdp->isp_initiator_id;
  111                 isp->isp_osinfo._link.adapter_targ = sdp->isp_initiator_id;
  112                 scbus->maxtarg = MAX_TARGETS-1;
  113                 if (IS_DUALBUS(isp) && (scbusb = scsi_alloc_bus()) != NULL) {
  114                         sdp++;
  115                         isp->isp_osinfo._link_b = isp->isp_osinfo._link;
  116                         isp->isp_osinfo._link_b.adapter_targ =
  117                             sdp->isp_initiator_id;
  118                         isp->isp_osinfo.discovered[1] =
  119                             1 << sdp->isp_initiator_id;
  120                         isp->isp_osinfo._link_b.adapter_bus = 1;
  121                         scbusb->maxtarg = MAX_TARGETS-1;
  122                         bus++;
  123                         (void) isp_control(isp, ISPCTL_RESET_BUS, &bus);
  124                 }
  125                 SYS_DELAY(2*1000000);
  126         }
  127 
  128 
  129         /*
  130          * Start the watchdog.
  131          */
  132         timeout(isp_watch, isp, WATCH_INTERVAL * hz);
  133         isp->isp_dogactive = 1;
  134 
  135         /*
  136          * Prepare the scsibus_data area for the upperlevel scsi code.
  137          */ 
  138         scbus->adapter_link = &isp->isp_osinfo._link;
  139 
  140         /*
  141          * ask the adapter what subunits are present
  142          */
  143         scsi_attachdevs(scbus);
  144 
  145         /*
  146          * Attach second bus if there.
  147          */
  148         if (scbusb) {
  149                 scbusb->adapter_link = &isp->isp_osinfo._link_b;
  150                 scsi_attachdevs(scbusb);
  151         }
  152 }
  153 
  154 
  155 /*
  156  * minphys our xfers
  157  *
  158  * Unfortunately, the buffer pointer describes the target device- not the
  159  * adapter device, so we can't use the pointer to find out what kind of
  160  * adapter we are and adjust accordingly.
  161  */
  162 
  163 static void
  164 ispminphys(struct buf *bp)
  165 {
  166         /*
  167          * Only the 1020/1040 has a 24 bit limit.
  168          */
  169         if (bp->b_bcount >= (1 << 24)) {
  170                 bp->b_bcount = (1 << 24);
  171         }
  172 }
  173 
  174 static u_int32_t
  175 isp_adapter_info(int unit)
  176 {
  177         return (2);
  178 }
  179 
  180 static int
  181 ispcmd_slow(struct scsi_xfer *xs)
  182 {
  183         struct ispsoftc *isp = XS_ISP(xs);
  184         /*
  185          * Have we completed discovery for this adapter?
  186          */
  187         if (IS_SCSI(isp) && (xs->flags & SCSI_NOMASK) == 0) {
  188                 sdparam *sdp = isp->isp_param;
  189                 int s = splbio();
  190                 int chan = XS_CHANNEL(xs), chmax = IS_DUALBUS(isp)? 2 : 1;
  191                 u_int16_t f = DPARM_DEFAULT;
  192 
  193                 sdp += chan;
  194                 if (xs->sc_link->quirks & SCSI_Q_NO_SYNC) {
  195                         f ^= DPARM_SYNC;
  196                 }
  197                 if (xs->sc_link->quirks & SCSI_Q_NO_WIDE) {
  198                         f ^= DPARM_WIDE;
  199                 }
  200                 if (xs->sc_link->quirks & SD_Q_NO_TAGS) {
  201                         f ^= DPARM_TQING;
  202                 }
  203                 sdp->isp_devparam[XS_TGT(xs)].dev_flags = f;
  204                 sdp->isp_devparam[XS_TGT(xs)].dev_update = 1;
  205                 isp->isp_update |= (1 << chan);
  206                 isp->isp_osinfo.discovered[chan] |= (1 << XS_TGT(xs));
  207                 for (chan = 0; chan < chmax; chan++) {
  208                         sdp = isp->isp_param;
  209                         sdp += chan;
  210                         f = 0xffff & ~(1 << sdp->isp_initiator_id);
  211                         if (isp->isp_osinfo.discovered[chan] != f) {
  212                                 break;
  213                         }
  214                 }
  215                 if (chan == chmax) {
  216                         isp_switch.scsi_cmd = ispcmd;
  217                 }
  218                 (void) splx(s);
  219         }
  220         return (ispcmd(xs));
  221 }
  222 
  223 static int
  224 ispcmd(struct scsi_xfer *xs)
  225 {
  226         struct ispsoftc *isp;
  227         int result, s;
  228 
  229         isp = XS_ISP(xs);
  230         s = splbio();
  231         if (isp->isp_state < ISP_RUNSTATE) {
  232                 DISABLE_INTS(isp);
  233                 isp_init(isp);
  234                 if (isp->isp_state != ISP_INITSTATE) {
  235                         ENABLE_INTS(isp);
  236                         (void) splx(s);
  237                         XS_SETERR(xs, HBA_BOTCH);
  238                         return (CMD_COMPLETE);
  239                 }
  240                 isp->isp_state = ISP_RUNSTATE;
  241                 ENABLE_INTS(isp);
  242         }
  243 
  244         /*
  245          * Check for queue blockage...
  246          */
  247         if (isp->isp_osinfo.blocked) {
  248                 if (xs->flags & SCSI_NOMASK) {
  249                         xs->error = XS_DRIVER_STUFFUP;
  250                         splx(s);
  251                         return (TRY_AGAIN_LATER);
  252                 }
  253                 if (isp->isp_osinfo.wqf != NULL) {
  254                         isp->isp_osinfo.wqt->next = xs;
  255                 } else {
  256                         isp->isp_osinfo.wqf = xs;
  257                 }
  258                 isp->isp_osinfo.wqt = xs;
  259                 xs->next = NULL;
  260                 splx(s);
  261                 return (SUCCESSFULLY_QUEUED);
  262         }
  263         DISABLE_INTS(isp);
  264         result = ispscsicmd(xs);
  265         ENABLE_INTS(isp);
  266 
  267         if ((xs->flags & SCSI_NOMASK) == 0) {
  268                 switch (result) {
  269                 case CMD_QUEUED:
  270                         result = SUCCESSFULLY_QUEUED;
  271                         break;
  272                 case CMD_EAGAIN:
  273                         result = TRY_AGAIN_LATER;
  274                         break;
  275                 case CMD_RQLATER:
  276                         result = SUCCESSFULLY_QUEUED;
  277                         timeout(isp_command_requeue, xs, hz);
  278                         break;
  279                 case CMD_COMPLETE:
  280                         result = COMPLETE;
  281                         break;
  282                 }
  283                 (void) splx(s);
  284                 return (result);
  285         }
  286 
  287         switch (result) {
  288         case CMD_QUEUED:
  289                 result = SUCCESSFULLY_QUEUED;
  290                 break;
  291         case CMD_RQLATER:
  292         case CMD_EAGAIN:
  293                 if (XS_NOERR(xs)) {
  294                         xs->error = XS_DRIVER_STUFFUP;
  295                 }
  296                 result = TRY_AGAIN_LATER;
  297                 break;
  298         case CMD_COMPLETE:
  299                 result = COMPLETE;
  300                 break;
  301                 
  302         }
  303 
  304         /*
  305          * We can't use interrupts so poll on completion.
  306          */
  307         if (result == SUCCESSFULLY_QUEUED) {
  308                 if (isp_poll(isp, xs, xs->timeout)) {
  309                         /*
  310                          * If no other error occurred but we didn't finish,
  311                          * something bad happened.
  312                          */
  313                         if (XS_IS_CMD_DONE(xs) == 0) {
  314                                 if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
  315                                         isp_restart(isp);
  316                                 }
  317                                 if (XS_NOERR(xs)) {
  318                                         XS_SETERR(xs, HBA_BOTCH);
  319                                 }
  320                         }
  321                 }
  322                 result = COMPLETE;
  323         }
  324         (void) splx(s);
  325         return (result);
  326 }
  327 
  328 static int
  329 isp_poll(struct ispsoftc *isp, struct scsi_xfer *xs, int mswait)
  330 {
  331 
  332         while (mswait) {
  333                 /* Try the interrupt handling routine */
  334                 (void)isp_intr((void *)isp);
  335 
  336                 /* See if the xs is now done */
  337                 if (XS_IS_CMD_DONE(xs))
  338                         return (0);
  339                 SYS_DELAY(1000);        /* wait one millisecond */
  340                 mswait--;
  341         }
  342         return (1);
  343 }
  344 
  345 static void
  346 isp_watch(void *arg)
  347 {
  348         int i;
  349         struct ispsoftc *isp = arg;
  350         struct scsi_xfer *xs;
  351         int s;
  352 
  353         /*
  354          * Look for completely dead commands (but not polled ones).
  355          */
  356         s = splbio();
  357         for (i = 0; i < isp->isp_maxcmds; i++) {
  358                 if ((xs = (struct scsi_xfer *) isp->isp_xflist[i]) == NULL) {
  359                         continue;
  360                 }
  361                 if (xs->timeout == 0 || (xs->flags & SCSI_NOMASK)) {
  362                         continue;
  363                 }
  364                 xs->timeout -= (WATCH_INTERVAL * 1000);
  365 
  366                 /*
  367                  * Avoid later thinking that this
  368                  * transaction is not being timed.
  369                  * Then give ourselves to watchdog
  370                  * periods of grace.
  371                  */
  372                 if (xs->timeout == 0) {
  373                         xs->timeout = 1;
  374                 } else if (xs->timeout > -(2 * WATCH_INTERVAL * 1000)) {
  375                         continue;
  376                 }
  377                 if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
  378                         printf("%s: isp_watch failed to abort command\n",
  379                             isp->isp_name);
  380                         isp_restart(isp);
  381                         break;
  382                 }
  383         }
  384         timeout(isp_watch, isp, WATCH_INTERVAL * hz);
  385         isp->isp_dogactive = 1;
  386         splx(s);
  387 }
  388 
  389 /*
  390  * Free any associated resources prior to decommissioning and
  391  * set the card to a known state (so it doesn't wake up and kick
  392  * us when we aren't expecting it to).
  393  *
  394  * Locks are held before coming here.
  395  */
  396 void
  397 isp_uninit(isp)
  398         struct ispsoftc *isp;
  399 {
  400         int s = splbio();
  401         /*
  402          * Leave with interrupts disabled.
  403          */
  404         ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
  405         DISABLE_INTS(isp);
  406 
  407         /*
  408          * Turn off the watchdog (if active).
  409          */
  410         if (isp->isp_dogactive) {
  411                 untimeout(isp_watch, isp);
  412                 isp->isp_dogactive = 0;
  413         }
  414         /*
  415          * And out...
  416          */
  417         splx(s);
  418 }
  419 
  420 /*
  421  * Restart function for a command to be requeued later.
  422  */
  423 static void
  424 isp_command_requeue(void *arg)
  425 {
  426         struct scsi_xfer *xs = arg;
  427         struct ispsoftc *isp = XS_ISP(xs);
  428         int s = splbio();
  429         switch (ispcmd_slow(xs)) {
  430         case SUCCESSFULLY_QUEUED:
  431                 printf("%s: isp_command_reque: queued %d.%d\n",
  432                     isp->isp_name, XS_TGT(xs), XS_LUN(xs));
  433                 break;
  434         case TRY_AGAIN_LATER:
  435                 printf("%s: EAGAIN for %d.%d\n",
  436                     isp->isp_name, XS_TGT(xs), XS_LUN(xs));
  437                 /* FALLTHROUGH */
  438         case COMPLETE:
  439                 /* can only be an error */
  440                 if (XS_NOERR(xs))
  441                         XS_SETERR(xs, XS_DRIVER_STUFFUP);
  442                 XS_CMD_DONE(xs);
  443                 break;
  444         }
  445         (void) splx(s);
  446 }
  447 
  448 /*
  449  * Restart function after a LOOP UP event (e.g.),
  450  * done as a timeout for some hysteresis.
  451  */
  452 static void
  453 isp_internal_restart(void *arg)
  454 {
  455         struct ispsoftc *isp = arg;
  456         int result, nrestarted = 0, s;
  457 
  458         s = splbio();
  459         if (isp->isp_osinfo.blocked == 0) {
  460                 struct scsi_xfer *xs;
  461                 while ((xs = isp->isp_osinfo.wqf) != NULL) {
  462                         isp->isp_osinfo.wqf = xs->next;
  463                         xs->next = NULL;
  464                         DISABLE_INTS(isp);
  465                         result = ispscsicmd(xs);
  466                         ENABLE_INTS(isp);
  467                         if (result != CMD_QUEUED) {
  468                                 printf("%s: botched command restart (0x%x)\n",
  469                                     isp->isp_name, result);
  470                                 if (XS_NOERR(xs))
  471                                         XS_SETERR(xs, XS_DRIVER_STUFFUP);
  472                                 XS_CMD_DONE(xs);
  473                         }
  474                         nrestarted++;
  475                 }
  476                 printf("%s: requeued %d commands\n", isp->isp_name, nrestarted);
  477         }
  478         (void) splx(s);
  479 }
  480 
  481 int
  482 isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg)
  483 {
  484         int bus, tgt;
  485         int s = splbio();
  486         switch (cmd) {
  487         case ISPASYNC_NEW_TGT_PARAMS:
  488         if (IS_SCSI(isp) && isp->isp_dblev) {
  489                 sdparam *sdp = isp->isp_param;
  490                 char *wt;
  491                 int mhz, flags, period;
  492 
  493                 tgt = *((int *) arg);
  494                 bus = (tgt >> 16) & 0xffff;
  495                 tgt &= 0xffff;
  496 
  497                 flags = sdp->isp_devparam[tgt].cur_dflags;
  498                 period = sdp->isp_devparam[tgt].cur_period;
  499                 if ((flags & DPARM_SYNC) && period &&
  500                     (sdp->isp_devparam[tgt].cur_offset) != 0) {
  501                         if (sdp->isp_lvdmode) {
  502                                 switch (period) {
  503                                 case 0x9:
  504                                         mhz = 80;
  505                                         break;
  506                                 case 0xa:
  507                                         mhz = 40;
  508                                         break;
  509                                 case 0xb:
  510                                         mhz = 33;
  511                                         break;
  512                                 case 0xc:
  513                                         mhz = 25;
  514                                         break;
  515                                 default:
  516                                         mhz = 1000 / (period * 4);
  517                                         break;
  518                                 }
  519                         } else {
  520                                 mhz = 1000 / (period * 4);
  521                         }
  522                 } else {
  523                         mhz = 0;
  524                 }
  525                 switch (flags & (DPARM_WIDE|DPARM_TQING)) {
  526                 case DPARM_WIDE:
  527                         wt = ", 16 bit wide\n";
  528                         break;
  529                 case DPARM_TQING:
  530                         wt = ", Tagged Queueing Enabled\n";
  531                         break;
  532                 case DPARM_WIDE|DPARM_TQING:
  533                         wt = ", 16 bit wide, Tagged Queueing Enabled\n";
  534                         break;
  535                 default:
  536                         wt = "\n";
  537                         break;
  538                 }
  539                 if (mhz) {
  540                         printf("%s: Bus %d Target %d at %dMHz Max "
  541                             "Offset %d%s", isp->isp_name, bus, tgt, mhz,
  542                             sdp->isp_devparam[tgt].cur_offset, wt);
  543                 } else {
  544                         printf("%s: Bus %d Target %d Async Mode%s",
  545                             isp->isp_name, bus, tgt, wt);
  546                 }
  547                 break;
  548         }
  549         case ISPASYNC_BUS_RESET:
  550                 if (arg)
  551                         bus = *((int *) arg);
  552                 else
  553                         bus = 0;
  554                 printf("%s: SCSI bus %d reset detected\n", isp->isp_name, bus);
  555                 break;
  556         case ISPASYNC_LOOP_DOWN:
  557                 /*
  558                  * Hopefully we get here in time to minimize the number
  559                  * of commands we are firing off that are sure to die.
  560                  */
  561                 isp->isp_osinfo.blocked = 1;
  562                 printf("%s: Loop DOWN\n", isp->isp_name);
  563                 break;
  564         case ISPASYNC_LOOP_UP:
  565                 isp->isp_osinfo.blocked = 0;
  566                 timeout(isp_internal_restart, isp, 1);
  567                 printf("%s: Loop UP\n", isp->isp_name);
  568                 break;
  569         case ISPASYNC_PDB_CHANGED:
  570         if (IS_FC(isp) && isp->isp_dblev) {
  571                 const char *fmt = "%s: Target %d (Loop 0x%x) Port ID 0x%x "
  572                     "role %s %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x\n";
  573                 const static char *roles[4] = {
  574                     "No", "Target", "Initiator", "Target/Initiator"
  575                 };
  576                 char *ptr;
  577                 fcparam *fcp = isp->isp_param;
  578                 int tgt = *((int *) arg);
  579                 struct lportdb *lp = &fcp->portdb[tgt]; 
  580 
  581                 if (lp->valid) {
  582                         ptr = "arrived";
  583                 } else {
  584                         ptr = "disappeared";
  585                 }
  586                 printf(fmt, isp->isp_name, tgt, lp->loopid, lp->portid,
  587                     roles[lp->roles & 0x3], ptr,
  588                     (u_int32_t) (lp->port_wwn >> 32),
  589                     (u_int32_t) (lp->port_wwn & 0xffffffffLL),
  590                     (u_int32_t) (lp->node_wwn >> 32),
  591                     (u_int32_t) (lp->node_wwn & 0xffffffffLL));
  592                 break;
  593         }
  594 #ifdef  ISP2100_FABRIC
  595         case ISPASYNC_CHANGE_NOTIFY:
  596                 printf("%s: Name Server Database Changed\n", isp->isp_name);
  597                 break;
  598         case ISPASYNC_FABRIC_DEV:
  599         {
  600                 int target;
  601                 struct lportdb *lp;
  602                 sns_scrsp_t *resp = (sns_scrsp_t *) arg;
  603                 u_int32_t portid;
  604                 u_int64_t wwn;
  605                 fcparam *fcp = isp->isp_param;
  606 
  607                 portid =
  608                     (((u_int32_t) resp->snscb_port_id[0]) << 16) |
  609                     (((u_int32_t) resp->snscb_port_id[1]) << 8) |
  610                     (((u_int32_t) resp->snscb_port_id[2]));
  611                 wwn =
  612                     (((u_int64_t)resp->snscb_portname[0]) << 56) |
  613                     (((u_int64_t)resp->snscb_portname[1]) << 48) |
  614                     (((u_int64_t)resp->snscb_portname[2]) << 40) |
  615                     (((u_int64_t)resp->snscb_portname[3]) << 32) |
  616                     (((u_int64_t)resp->snscb_portname[4]) << 24) |
  617                     (((u_int64_t)resp->snscb_portname[5]) << 16) |
  618                     (((u_int64_t)resp->snscb_portname[6]) <<  8) |
  619                     (((u_int64_t)resp->snscb_portname[7]));
  620                 printf("%s: Fabric Device (Type 0x%x)@PortID 0x%x WWN "
  621                     "0x%08x%08x\n", isp->isp_name, resp->snscb_port_type,
  622                     portid, ((u_int32_t)(wwn >> 32)),
  623                     ((u_int32_t)(wwn & 0xffffffff)));
  624                 if (resp->snscb_port_type != 2)
  625                         break;
  626                 for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) {
  627                         lp = &fcp->portdb[target];
  628                         if (lp->port_wwn == wwn)
  629                                 break;
  630                 }
  631                 if (target < MAX_FC_TARG) {
  632                         break;
  633                 }
  634                 for (target = FC_SNS_ID+1; target < MAX_FC_TARG; target++) {
  635                         lp = &fcp->portdb[target];
  636                         if (lp->port_wwn == 0)
  637                                 break;
  638                 }
  639                 if (target == MAX_FC_TARG) {
  640                         printf("%s: no more space for fabric devices\n",
  641                             isp->isp_name);
  642                         return (-1);
  643                 }
  644                 lp->port_wwn = lp->node_wwn = wwn;
  645                 lp->portid = portid;
  646                 break;
  647         }
  648 #endif
  649         default:
  650                 break;
  651         }
  652         (void) splx(s);
  653         return (0);
  654 }

Cache object: 1e6a79cb151478315638f9a235056751


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.