root/dev/i2o/ioprbs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ioprbs_match
  2. ioprbs_attach
  3. ioprbs_unconfig
  4. ioprbs_scsi_cmd
  5. ioprbsminphys
  6. ioprbs_intr
  7. ioprbs_intr_event
  8. ioprbs_adjqparam
  9. ioprbs_enqueue
  10. ioprbs_dequeue
  11. ioprbs_copy_internal_data
  12. ioprbs_internal_cache_cmd
  13. ioprbs_get_ccb
  14. ioprbs_free_ccb
  15. ioprbs_enqueue_ccb
  16. ioprbs_start_ccbs
  17. ioprbs_exec_ccb
  18. ioprbs_start
  19. ioprbs_timeout
  20. ioprbs_watchdog

    1 /*      $OpenBSD: ioprbs.c,v 1.11 2006/11/28 23:59:45 dlg Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2001 Niklas Hallqvist
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 /*-
   30  * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
   31  * All rights reserved.
   32  *
   33  * This code is derived from software contributed to The NetBSD Foundation
   34  * by Andrew Doran.
   35  *
   36  * Redistribution and use in source and binary forms, with or without
   37  * modification, are permitted provided that the following conditions
   38  * are met:
   39  * 1. Redistributions of source code must retain the above copyright
   40  *    notice, this list of conditions and the following disclaimer.
   41  * 2. Redistributions in binary form must reproduce the above copyright
   42  *    notice, this list of conditions and the following disclaimer in the
   43  *    documentation and/or other materials provided with the distribution.
   44  * 3. All advertising materials mentioning features or use of this software
   45  *    must display the following acknowledgement:
   46  *        This product includes software developed by the NetBSD
   47  *        Foundation, Inc. and its contributors.
   48  * 4. Neither the name of The NetBSD Foundation nor the names of its
   49  *    contributors may be used to endorse or promote products derived
   50  *    from this software without specific prior written permission.
   51  *
   52  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   53  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   54  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   55  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   56  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   57  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   58  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   59  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   60  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   61  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   62  * POSSIBILITY OF SUCH DAMAGE.
   63  */
   64 
   65 /*
   66  * A driver for I2O "Random block storage" devices, like RAID.
   67  */
   68 
   69 /*
   70  * This driver would not have been written if it was not for the hardware
   71  * donation from pi.se.  I want to thank them for their support.  It also
   72  * had been much harder without Andrew Doran's work in NetBSD's ld_iop.c
   73  * driver, from which I have both gotten inspiration and actual code.
   74  * - Niklas Hallqvist
   75  */
   76 
   77 #include <sys/param.h>
   78 #include <sys/buf.h>
   79 #include <sys/device.h>
   80 #include <sys/kernel.h>
   81 #include <sys/proc.h>
   82 #include <sys/systm.h>
   83 
   84 #include <machine/bus.h>
   85 
   86 #include <scsi/scsi_all.h>
   87 #include <scsi/scsi_disk.h>
   88 #include <scsi/scsiconf.h>
   89 
   90 #include <dev/i2o/i2o.h>
   91 #include <dev/i2o/iopio.h>
   92 #include <dev/i2o/iopvar.h>
   93 #include <dev/i2o/ioprbsvar.h>
   94 
   95 #ifdef I2ODEBUG
   96 #define DPRINTF(x)      printf x
   97 #else
   98 #define DPRINTF(x)
   99 #endif
  100 
  101 void    ioprbsminphys(struct buf *);
  102 void    ioprbs_adjqparam(struct device *, int);
  103 void    ioprbs_attach(struct device *, struct device *, void *);
  104 void    ioprbs_copy_internal_data(struct scsi_xfer *, u_int8_t *,
  105             size_t);
  106 struct scsi_xfer *ioprbs_dequeue(struct ioprbs_softc *);
  107 void    ioprbs_enqueue(struct ioprbs_softc *, struct scsi_xfer *, int);
  108 void    ioprbs_enqueue_ccb(struct ioprbs_softc *, struct ioprbs_ccb *);
  109 int     ioprbs_exec_ccb(struct ioprbs_ccb *);
  110 void    ioprbs_free_ccb(struct ioprbs_softc *, struct ioprbs_ccb *);
  111 struct ioprbs_ccb *ioprbs_get_ccb(struct ioprbs_softc *, int);
  112 void    ioprbs_internal_cache_cmd(struct scsi_xfer *);
  113 void    ioprbs_intr(struct device *, struct iop_msg *, void *);
  114 void    ioprbs_intr_event(struct device *, struct iop_msg *, void *);
  115 int     ioprbs_match(struct device *, void *, void *);
  116 int     ioprbs_scsi_cmd(struct scsi_xfer *);
  117 int     ioprbs_start(struct ioprbs_ccb *);
  118 void    ioprbs_start_ccbs(struct ioprbs_softc *);
  119 void    ioprbs_timeout(void *);
  120 void    ioprbs_unconfig(struct ioprbs_softc *, int);
  121 void    ioprbs_watchdog(void *);
  122 
  123 struct cfdriver ioprbs_cd = {
  124         NULL, "ioprbs", DV_DULL
  125 };
  126 
  127 struct cfattach ioprbs_ca = {
  128         sizeof(struct ioprbs_softc), ioprbs_match, ioprbs_attach
  129 };
  130 
  131 struct scsi_adapter ioprbs_switch = {
  132         ioprbs_scsi_cmd, ioprbsminphys, 0, 0,
  133 };
  134 
  135 struct scsi_device ioprbs_dev = {
  136         NULL, NULL, NULL, NULL
  137 };
  138 
  139 #ifdef I2OVERBOSE
  140 static const char *const ioprbs_errors[] = { 
  141         "success", 
  142         "media error", 
  143         "access error",
  144         "device failure",
  145         "device not ready",
  146         "media not present",
  147         "media locked",
  148         "media failure",
  149         "protocol failure",
  150         "bus failure",
  151         "access violation",
  152         "media write protected",
  153         "device reset",
  154         "volume changed, waiting for acknowledgement",
  155         "timeout",
  156 };
  157 #endif
  158 
  159 /*
  160  * Match a supported device.
  161  */
  162 int
  163 ioprbs_match(parent, match, aux)
  164         struct device *parent;
  165         void *match;
  166         void *aux;
  167 {
  168         struct iop_attach_args *ia = aux;
  169 
  170         return (ia->ia_class == I2O_CLASS_RANDOM_BLOCK_STORAGE);
  171 }
  172 
  173 /*
  174  * Attach a supported device.
  175  */
  176 void
  177 ioprbs_attach(struct device *parent, struct device *self, void *aux)
  178 {
  179         struct iop_attach_args *ia = aux;
  180         struct ioprbs_softc *sc = (struct ioprbs_softc *)self;
  181         struct iop_softc *iop = (struct iop_softc *)parent;
  182         struct scsibus_attach_args saa;
  183         int rv, state = 0;
  184         int enable;
  185         u_int32_t cachesz;
  186         char *typestr, *fixedstr;
  187         struct {
  188                 struct  i2o_param_op_results pr;
  189                 struct  i2o_param_read_results prr;
  190                 union {
  191                         struct  i2o_param_rbs_cache_control cc;
  192                         struct  i2o_param_rbs_device_info bdi;
  193                         struct  i2o_param_rbs_operation op;
  194                 } p;
  195         } param /* XXX gcc __attribute__ ((__packed__)) */;
  196         int i;
  197 
  198         TAILQ_INIT(&sc->sc_free_ccb);
  199         TAILQ_INIT(&sc->sc_ccbq);
  200         LIST_INIT(&sc->sc_queue);
  201 
  202         /* Initialize the ccbs */
  203         for (i = 0; i < IOPRBS_MAX_CCBS; i++)
  204                 TAILQ_INSERT_TAIL(&sc->sc_free_ccb, &sc->sc_ccbs[i],
  205                     ic_chain);
  206 
  207         /* Register us as an initiator. */
  208         sc->sc_ii.ii_dv = self;
  209         sc->sc_ii.ii_intr = ioprbs_intr;
  210         sc->sc_ii.ii_adjqparam = ioprbs_adjqparam;
  211         sc->sc_ii.ii_flags = 0;
  212         sc->sc_ii.ii_tid = ia->ia_tid;
  213         iop_initiator_register(iop, &sc->sc_ii);
  214 
  215         /* Register another initiator to handle events from the device. */
  216         sc->sc_eventii.ii_dv = self;
  217         sc->sc_eventii.ii_intr = ioprbs_intr_event;
  218         sc->sc_eventii.ii_flags = II_DISCARD | II_UTILITY;
  219         sc->sc_eventii.ii_tid = ia->ia_tid;
  220         iop_initiator_register(iop, &sc->sc_eventii);
  221 
  222         rv = iop_util_eventreg(iop, &sc->sc_eventii,
  223             I2O_EVENT_GEN_EVENT_MASK_MODIFIED | I2O_EVENT_GEN_DEVICE_RESET |
  224             I2O_EVENT_GEN_STATE_CHANGE | I2O_EVENT_GEN_GENERAL_WARNING);
  225         if (rv != 0) {
  226                 printf("%s: unable to register for events", self->dv_xname);
  227                 goto bad;
  228         }
  229         state++;
  230 
  231         /*
  232          * Start out with one queued command.  The `iop' driver will adjust
  233          * the queue parameters once we're up and running.
  234          */
  235         sc->sc_maxqueuecnt = 1;
  236 
  237         sc->sc_maxxfer = IOP_MAX_XFER;
  238 
  239         /* Say what the device is. */
  240         printf(":");
  241         iop_print_ident(iop, ia->ia_tid);
  242 
  243         /*
  244          * Claim the device so that we don't get any nasty surprises.  Allow
  245          * failure.
  246          */
  247         rv = iop_util_claim(iop, &sc->sc_ii, 0,
  248             I2O_UTIL_CLAIM_CAPACITY_SENSITIVE |
  249             I2O_UTIL_CLAIM_NO_PEER_SERVICE |
  250             I2O_UTIL_CLAIM_NO_MANAGEMENT_SERVICE |
  251             I2O_UTIL_CLAIM_PRIMARY_USER);
  252         sc->sc_flags = rv ? 0 : IOPRBS_CLAIMED;
  253 
  254         rv = iop_param_op(iop, ia->ia_tid, NULL, 0, I2O_PARAM_RBS_DEVICE_INFO,
  255             &param, sizeof param);
  256         if (rv != 0) {
  257                 printf("%s: unable to get parameters (0x%04x; %d)\n",
  258                    sc->sc_dv.dv_xname, I2O_PARAM_RBS_DEVICE_INFO, rv);
  259                 goto bad;
  260         }
  261 
  262         sc->sc_secsize = letoh32(param.p.bdi.blocksize);
  263         sc->sc_secperunit = (int)
  264             (letoh64(param.p.bdi.capacity) / sc->sc_secsize);
  265 
  266         switch (param.p.bdi.type) {
  267         case I2O_RBS_TYPE_DIRECT:
  268                 typestr = "direct access";
  269                 enable = 1;
  270                 break;
  271         case I2O_RBS_TYPE_WORM:
  272                 typestr = "WORM";
  273                 enable = 0;
  274                 break;
  275         case I2O_RBS_TYPE_CDROM:
  276                 typestr = "CD-ROM";
  277                 enable = 0;
  278                 break;
  279         case I2O_RBS_TYPE_OPTICAL:
  280                 typestr = "optical";
  281                 enable = 0;
  282                 break;
  283         default:
  284                 typestr = "unknown";
  285                 enable = 0;
  286                 break;
  287         }
  288 
  289         if ((letoh32(param.p.bdi.capabilities) & I2O_RBS_CAP_REMOVABLE_MEDIA)
  290             != 0) {
  291                 /* sc->sc_flags = IOPRBS_REMOVABLE; */
  292                 fixedstr = "removable";
  293                 enable = 0;
  294         } else
  295                 fixedstr = "fixed";
  296 
  297         printf(" %s, %s", typestr, fixedstr);
  298 
  299         /*
  300          * Determine if the device has an private cache.  If so, print the
  301          * cache size.  Even if the device doesn't appear to have a cache,
  302          * we perform a flush at shutdown.
  303          */
  304         rv = iop_param_op(iop, ia->ia_tid, NULL, 0,
  305             I2O_PARAM_RBS_CACHE_CONTROL, &param, sizeof(param));
  306         if (rv != 0) {
  307                 printf("%s: unable to get parameters (0x%04x; %d)\n",
  308                    sc->sc_dv.dv_xname, I2O_PARAM_RBS_CACHE_CONTROL, rv);
  309                 goto bad;
  310         }
  311 
  312         if ((cachesz = letoh32(param.p.cc.totalcachesize)) != 0)
  313                 printf(", %dkB cache", cachesz >> 10);
  314 
  315         printf("\n");
  316 
  317         /*
  318          * Configure the DDM's timeout functions to time out all commands
  319          * after 30 seconds.
  320          */
  321         rv = iop_param_op(iop, ia->ia_tid, NULL, 0, I2O_PARAM_RBS_OPERATION,
  322             &param, sizeof(param));
  323         if (rv != 0) {
  324                 printf("%s: unable to get parameters (0x%04x; %d)\n",
  325                    sc->sc_dv.dv_xname, I2O_PARAM_RBS_OPERATION, rv);
  326                 goto bad;
  327         }
  328 
  329         param.p.op.timeoutbase = htole32(IOPRBS_TIMEOUT * 1000); 
  330         param.p.op.rwvtimeoutbase = htole32(IOPRBS_TIMEOUT * 1000); 
  331         param.p.op.rwvtimeout = 0; 
  332 
  333         rv = iop_param_op(iop, ia->ia_tid, NULL, 1, I2O_PARAM_RBS_OPERATION,
  334             &param, sizeof(param));
  335 #ifdef notdef
  336         /*
  337          * Intel RAID adapters don't like the above, but do post a
  338          * `parameter changed' event.  Perhaps we're doing something
  339          * wrong...
  340          */
  341         if (rv != 0) {
  342                 printf("%s: unable to set parameters (0x%04x; %d)\n",
  343                    sc->sc_dv.dv_xname, I2O_PARAM_RBS_OPERATION, rv);
  344                 goto bad;
  345         }
  346 #endif
  347 
  348         if (enable)
  349                 sc->sc_flags |= IOPRBS_ENABLED;
  350         else
  351                 printf("%s: device not yet supported\n", self->dv_xname);
  352 
  353         /* Fill in the prototype scsi_link. */
  354         sc->sc_link.adapter_softc = sc;
  355         sc->sc_link.adapter = &ioprbs_switch;
  356         sc->sc_link.device = &ioprbs_dev;
  357         sc->sc_link.openings = 1;
  358         sc->sc_link.adapter_buswidth = 1;
  359         sc->sc_link.adapter_target = 1;
  360 
  361         bzero(&saa, sizeof(saa));
  362         saa.saa_sc_link = &sc->sc_link;
  363 
  364         config_found(&sc->sc_dv, &saa, scsiprint);
  365 
  366         return;
  367 
  368  bad:
  369         ioprbs_unconfig(sc, state > 0);
  370 }
  371 
  372 void
  373 ioprbs_unconfig(struct ioprbs_softc *sc, int evreg)
  374 {
  375         struct iop_softc *iop;
  376         int s;
  377 
  378         iop = (struct iop_softc *)sc->sc_dv.dv_parent;
  379 
  380         if ((sc->sc_flags & IOPRBS_CLAIMED) != 0)
  381                 iop_util_claim(iop, &sc->sc_ii, 1,
  382                     I2O_UTIL_CLAIM_PRIMARY_USER);
  383 
  384         if (evreg) {
  385                 /*
  386                  * Mask off events, and wait up to 5 seconds for a reply. 
  387                  * Note that some adapters won't reply to this (XXX We
  388                  * should check the event capabilities).
  389                  */
  390                 sc->sc_flags &= ~IOPRBS_NEW_EVTMASK;
  391                 iop_util_eventreg(iop, &sc->sc_eventii,
  392                     I2O_EVENT_GEN_EVENT_MASK_MODIFIED);
  393                 s = splbio();
  394                 if ((sc->sc_flags & IOPRBS_NEW_EVTMASK) == 0)
  395                         tsleep(&sc->sc_eventii, PRIBIO, "ioprbsevt", hz * 5);
  396                 splx(s);
  397 #ifdef I2ODEBUG
  398                 if ((sc->sc_flags & IOPRBS_NEW_EVTMASK) == 0)
  399                         printf("%s: didn't reply to event unregister",
  400                             sc->sc_dv.dv_xname);
  401 #endif
  402         }
  403 
  404         iop_initiator_unregister(iop, &sc->sc_eventii);
  405         iop_initiator_unregister(iop, &sc->sc_ii);
  406 }
  407 
  408 int
  409 ioprbs_scsi_cmd(xs)
  410         struct scsi_xfer *xs;
  411 {
  412         struct scsi_link *link = xs->sc_link;
  413         struct ioprbs_softc *sc = link->adapter_softc;
  414         struct ioprbs_ccb *ccb;
  415         u_int32_t blockno, blockcnt;
  416         struct scsi_rw *rw;
  417         struct scsi_rw_big *rwb;
  418         ioprbs_lock_t lock;
  419         int retval = SUCCESSFULLY_QUEUED;
  420 
  421         lock = IOPRBS_LOCK(sc);
  422 
  423         /* Don't double enqueue if we came from ioprbs_chain. */
  424         if (xs != LIST_FIRST(&sc->sc_queue))
  425                 ioprbs_enqueue(sc, xs, 0);
  426 
  427         while ((xs = ioprbs_dequeue(sc))) {
  428                 xs->error = XS_NOERROR;
  429 
  430                 ccb = NULL;
  431 
  432                 switch (xs->cmd->opcode) {
  433                 case TEST_UNIT_READY:
  434                 case REQUEST_SENSE:
  435                 case INQUIRY:
  436                 case MODE_SENSE:
  437                 case START_STOP:
  438                 case READ_CAPACITY:
  439 #if 0
  440                 case VERIFY:
  441 #endif
  442                         ioprbs_internal_cache_cmd(xs);
  443                         xs->flags |= ITSDONE;
  444                         scsi_done(xs);
  445                         goto ready;
  446 
  447                 case PREVENT_ALLOW:
  448                         DPRINTF(("PREVENT/ALLOW "));
  449                         /* XXX Not yet implemented */
  450                         xs->error = XS_NOERROR;
  451                         xs->flags |= ITSDONE;
  452                         scsi_done(xs);
  453                         goto ready;
  454 
  455                 case SYNCHRONIZE_CACHE:
  456                         DPRINTF(("SYNCHRONIZE_CACHE "));
  457                         /* XXX Not yet implemented */
  458                         xs->error = XS_NOERROR;
  459                         xs->flags |= ITSDONE;
  460                         scsi_done(xs);
  461                         goto ready;
  462 
  463                 default:
  464                         DPRINTF(("unknown opc %d ", xs->cmd->opcode));
  465                         /* XXX Not yet implemented */
  466                         xs->error = XS_DRIVER_STUFFUP;
  467                         xs->flags |= ITSDONE;
  468                         scsi_done(xs);
  469                         goto ready;
  470 
  471                 case READ_COMMAND:
  472                 case READ_BIG:
  473                 case WRITE_COMMAND:
  474                 case WRITE_BIG:
  475                         DPRINTF(("rw opc %d ", xs->cmd->opcode));
  476 
  477                         if (xs->cmd->opcode != SYNCHRONIZE_CACHE) {
  478                                 /* A read or write operation. */
  479                                 if (xs->cmdlen == 6) {
  480                                         rw = (struct scsi_rw *)xs->cmd;
  481                                         blockno = _3btol(rw->addr) &
  482                                             (SRW_TOPADDR << 16 | 0xffff);
  483                                         blockcnt =
  484                                             rw->length ? rw->length : 0x100;
  485                                 } else {
  486                                         rwb = (struct scsi_rw_big *)xs->cmd;
  487                                         blockno = _4btol(rwb->addr);
  488                                         blockcnt = _2btol(rwb->length);
  489                                 }
  490                                 if (blockno >= sc->sc_secperunit ||
  491                                     blockno + blockcnt > sc->sc_secperunit) {
  492                                         printf(
  493                                             "%s: out of bounds %u-%u >= %u\n",
  494                                             sc->sc_dv.dv_xname, blockno,
  495                                             blockcnt, sc->sc_secperunit);
  496                                         /*
  497                                          * XXX Should be XS_SENSE but that
  498                                          * would require setting up a faked
  499                                          * sense too.
  500                                          */
  501                                         xs->error = XS_DRIVER_STUFFUP;
  502                                         xs->flags |= ITSDONE;
  503                                         scsi_done(xs);
  504                                         goto ready;
  505                                 }
  506                         }
  507 
  508                         ccb = ioprbs_get_ccb(sc, xs->flags);
  509 
  510                         /*
  511                          * We are out of commands, try again in a little while.
  512                          */
  513                         if (ccb == NULL) {
  514                                 IOPRBS_UNLOCK(sc, lock);
  515                                 return (TRY_AGAIN_LATER);
  516                         }
  517 
  518                         ccb->ic_blockno = blockno;
  519                         ccb->ic_blockcnt = blockcnt;
  520                         ccb->ic_xs = xs;
  521                         ccb->ic_timeout = xs->timeout;
  522 
  523                         ioprbs_enqueue_ccb(sc, ccb);
  524 
  525                         /* XXX what if enqueue did not start a transfer? */
  526                         if (xs->flags & SCSI_POLL) {
  527 #if 0
  528                                 if (!ioprbs_wait(sc, ccb, ccb->ic_timeout)) {
  529                                         IOPRBS_UNLOCK(sc, lock);
  530                                         printf("%s: command timed out\n",
  531                                             sc->sc_dv.dv_xname);
  532                                         return (TRY_AGAIN_LATER);
  533                                 }
  534                                 xs->flags |= ITSDONE;
  535                                 scsi_done(xs);
  536 #endif
  537                         }
  538                 }
  539 
  540         ready:
  541                 /*
  542                  * Don't process the queue if we are polling.
  543                  */
  544                 if (xs->flags & SCSI_POLL) {
  545                         retval = COMPLETE;
  546                         break;
  547                 }
  548         }
  549 
  550         IOPRBS_UNLOCK(sc, lock);
  551         return (retval);
  552 }
  553 
  554 void
  555 ioprbsminphys(bp)
  556         struct buf *bp;
  557 {
  558         minphys(bp);
  559 }
  560 
  561 void
  562 ioprbs_intr(struct device *dv, struct iop_msg *im, void *reply)
  563 {
  564         struct i2o_rbs_reply *rb = reply;
  565         struct ioprbs_ccb *ccb = im->im_dvcontext;
  566         struct buf *bp = ccb->ic_xs->bp;
  567         struct ioprbs_softc *sc = (struct ioprbs_softc *)dv;
  568         struct iop_softc *iop = (struct iop_softc *)dv->dv_parent;
  569         int err, detail;
  570 #ifdef I2OVERBOSE
  571         const char *errstr;
  572 #endif
  573 
  574         DPRINTF(("ioprbs_intr(%p, %p, %p) ", dv, im, reply));
  575 
  576         timeout_del(&ccb->ic_xs->stimeout);
  577 
  578         err = ((rb->msgflags & I2O_MSGFLAGS_FAIL) != 0);
  579 
  580         if (!err && rb->reqstatus != I2O_STATUS_SUCCESS) {
  581                 detail = letoh16(rb->detail);
  582 #ifdef I2OVERBOSE
  583                 if (detail > sizeof(ioprbs_errors) / sizeof(ioprbs_errors[0]))
  584                         errstr = "<unknown>";
  585                 else
  586                         errstr = ioprbs_errors[detail];
  587                 printf("%s: error 0x%04x: %s\n", dv->dv_xname, detail, errstr);
  588 #else
  589                 printf("%s: error 0x%04x\n", dv->dv_xname, detail);
  590 #endif
  591                 err = 1;
  592         }
  593 
  594         if (bp) {
  595                 if (err) {
  596                         bp->b_flags |= B_ERROR;
  597                         bp->b_error = EIO;
  598                         bp->b_resid = bp->b_bcount;
  599                 } else
  600                         bp->b_resid = bp->b_bcount - letoh32(rb->transfercount);
  601         }
  602 
  603         iop_msg_unmap(iop, im);
  604         iop_msg_free(iop, im);
  605         scsi_done(ccb->ic_xs);
  606         ioprbs_free_ccb(sc, ccb);
  607 }
  608 
  609 void
  610 ioprbs_intr_event(struct device *dv, struct iop_msg *im, void *reply)
  611 {
  612         struct i2o_util_event_register_reply *rb;
  613         struct ioprbs_softc *sc;
  614         u_int event;
  615 
  616         rb = reply;
  617 
  618         if ((rb->msgflags & I2O_MSGFLAGS_FAIL) != 0)
  619                 return;
  620 
  621         event = letoh32(rb->event);
  622         sc = (struct ioprbs_softc *)dv;
  623 
  624         if (event == I2O_EVENT_GEN_EVENT_MASK_MODIFIED) {
  625                 sc->sc_flags |= IOPRBS_NEW_EVTMASK;
  626                 wakeup(&sc->sc_eventii);
  627 #ifndef I2ODEBUG
  628                 return;
  629 #endif
  630         }
  631 
  632         printf("%s: event 0x%08x received\n", dv->dv_xname, event);
  633 }
  634 
  635 void
  636 ioprbs_adjqparam(struct device *dv, int mpi)
  637 {
  638 #if 0
  639         struct iop_softc *iop;
  640 
  641         /*
  642          * AMI controllers seem to lose the plot if you hand off lots of
  643          * queued commands.
  644          */
  645         iop = (struct iop_softc *)dv->dv_parent;
  646         if (letoh16(I2O_ORG_AMI) == iop->sc_status.orgid && mpi > 64)
  647                 mpi = 64;
  648 
  649         ldadjqparam((struct ld_softc *)dv, mpi);
  650 #endif
  651 }
  652 
  653 /*
  654  * Insert a command into the driver queue, either at the front or at the tail.
  655  * It's ok to overload the freelist link as these structures are never on
  656  * the freelist at this time.
  657  */
  658 void
  659 ioprbs_enqueue(sc, xs, infront)
  660         struct ioprbs_softc *sc;
  661         struct scsi_xfer *xs;
  662         int infront;
  663 {
  664         if (infront || LIST_FIRST(&sc->sc_queue) == NULL) {
  665                 if (LIST_FIRST(&sc->sc_queue) == NULL)
  666                         sc->sc_queuelast = xs;
  667                 LIST_INSERT_HEAD(&sc->sc_queue, xs, free_list);
  668                 return;
  669         }
  670         LIST_INSERT_AFTER(sc->sc_queuelast, xs, free_list);
  671         sc->sc_queuelast = xs;
  672 }
  673 
  674 /*
  675  * Pull a command off the front of the driver queue.
  676  */
  677 struct scsi_xfer *
  678 ioprbs_dequeue(sc)
  679         struct ioprbs_softc *sc;
  680 {
  681         struct scsi_xfer *xs;
  682 
  683         xs = LIST_FIRST(&sc->sc_queue);
  684         if (xs == NULL)
  685                 return (NULL);
  686         LIST_REMOVE(xs, free_list);
  687 
  688         if (LIST_FIRST(&sc->sc_queue) == NULL)
  689                 sc->sc_queuelast = NULL;
  690 
  691         return (xs);
  692 }
  693 
  694 void
  695 ioprbs_copy_internal_data(xs, data, size)
  696         struct scsi_xfer *xs;
  697         u_int8_t *data;
  698         size_t size;
  699 {
  700         size_t copy_cnt;
  701 
  702         DPRINTF(("ioprbs_copy_internal_data "));
  703 
  704         if (!xs->datalen)
  705                 printf("uio move not yet supported\n");
  706         else {
  707                 copy_cnt = MIN(size, xs->datalen);
  708                 bcopy(data, xs->data, copy_cnt);
  709         }
  710 }
  711 
  712 /* Emulated SCSI operation on cache device */
  713 void
  714 ioprbs_internal_cache_cmd(xs)
  715         struct scsi_xfer *xs;
  716 {
  717         struct scsi_link *link = xs->sc_link;
  718         struct ioprbs_softc *sc = link->adapter_softc;
  719         u_int8_t target = link->target;
  720         struct scsi_inquiry_data inq;
  721         struct scsi_sense_data sd;
  722         struct scsi_read_cap_data rcd;
  723 
  724         DPRINTF(("ioprbs_internal_cache_cmd "));
  725 
  726         xs->error = XS_NOERROR;
  727 
  728         if (target > 0 || link->lun != 0) {
  729                 xs->error = XS_DRIVER_STUFFUP;
  730                 return;
  731         }
  732 
  733         switch (xs->cmd->opcode) {
  734         case TEST_UNIT_READY:
  735         case START_STOP:
  736 #if 0
  737         case VERIFY:
  738 #endif
  739                 DPRINTF(("opc %d tgt %d ", xs->cmd->opcode, target));
  740                 break;
  741 
  742         case REQUEST_SENSE:
  743                 DPRINTF(("REQUEST SENSE tgt %d ", target));
  744                 bzero(&sd, sizeof sd);
  745                 sd.error_code = 0x70;
  746                 sd.segment = 0;
  747                 sd.flags = SKEY_NO_SENSE;
  748                 bzero(sd.info, sizeof sd.info);
  749                 sd.extra_len = 0;
  750                 ioprbs_copy_internal_data(xs, (u_int8_t *)&sd, sizeof sd);
  751                 break;
  752 
  753         case INQUIRY:
  754                 DPRINTF(("INQUIRY tgt %d", target));
  755                 bzero(&inq, sizeof inq);
  756                 /* XXX How do we detect removable/CD-ROM devices?  */
  757                 inq.device = T_DIRECT;
  758                 inq.dev_qual2 = 0;
  759                 inq.version = 2;
  760                 inq.response_format = 2;
  761                 inq.additional_length = 32;
  762                 strlcpy(inq.vendor, "I2O", sizeof inq.vendor);
  763                 snprintf(inq.product, sizeof inq.product, "Container #%02d",
  764                     target);
  765                 strlcpy(inq.revision, "   ", sizeof inq.revision);
  766                 ioprbs_copy_internal_data(xs, (u_int8_t *)&inq, sizeof inq);
  767                 break;
  768 
  769         case READ_CAPACITY:
  770                 DPRINTF(("READ CAPACITY tgt %d ", target));
  771                 bzero(&rcd, sizeof rcd);
  772                 _lto4b(sc->sc_secperunit - 1, rcd.addr);
  773                 _lto4b(IOPRBS_BLOCK_SIZE, rcd.length);
  774                 ioprbs_copy_internal_data(xs, (u_int8_t *)&rcd, sizeof rcd);
  775                 break;
  776 
  777         default:
  778                 DPRINTF(("unsupported scsi command %#x tgt %d ",
  779                     xs->cmd->opcode, target));
  780                 xs->error = XS_DRIVER_STUFFUP;
  781                 return;
  782         }
  783 
  784         xs->error = XS_NOERROR;
  785 }
  786 
  787 struct ioprbs_ccb *
  788 ioprbs_get_ccb(sc, flags)
  789         struct ioprbs_softc *sc;
  790         int flags;
  791 {
  792         struct ioprbs_ccb *ccb;
  793         ioprbs_lock_t lock;
  794 
  795         DPRINTF(("ioprbs_get_ccb(%p, 0x%x) ", sc, flags));
  796 
  797         lock = IOPRBS_LOCK(sc);
  798 
  799         for (;;) {
  800                 ccb = TAILQ_FIRST(&sc->sc_free_ccb);
  801                 if (ccb != NULL)
  802                         break;
  803                 if (flags & SCSI_NOSLEEP)
  804                         goto bail_out;
  805                 tsleep(&sc->sc_free_ccb, PRIBIO, "ioprbs_ccb", 0);
  806         }
  807 
  808         TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ic_chain);
  809 
  810         /* initialise the command */
  811         ccb->ic_flags = 0;
  812 
  813  bail_out:
  814         IOPRBS_UNLOCK(sc, lock);
  815         return (ccb);
  816 }
  817 
  818 void
  819 ioprbs_free_ccb(sc, ccb)
  820         struct ioprbs_softc *sc;
  821         struct ioprbs_ccb *ccb;
  822 {
  823         ioprbs_lock_t lock;
  824 
  825         DPRINTF(("ioprbs_free_ccb(%p, %p) ", sc, ccb));
  826 
  827         lock = IOPRBS_LOCK(sc);
  828 
  829         TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, ic_chain);
  830 
  831         /* If the free list was empty, wake up potential waiters. */
  832         if (TAILQ_NEXT(ccb, ic_chain) == NULL)
  833                 wakeup(&sc->sc_free_ccb);
  834 
  835         IOPRBS_UNLOCK(sc, lock);
  836 }
  837 
  838 void
  839 ioprbs_enqueue_ccb(sc, ccb)
  840         struct ioprbs_softc *sc;
  841         struct ioprbs_ccb *ccb;
  842 {
  843         DPRINTF(("ioprbs_enqueue_ccb(%p, %p) ", sc, ccb));
  844 
  845         timeout_set(&ccb->ic_xs->stimeout, ioprbs_timeout, ccb);
  846         TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ic_chain);
  847         ioprbs_start_ccbs(sc);
  848 }
  849 
  850 void
  851 ioprbs_start_ccbs(sc)
  852         struct ioprbs_softc *sc;
  853 {
  854         struct ioprbs_ccb *ccb;
  855         struct scsi_xfer *xs;
  856 
  857         DPRINTF(("ioprbs_start_ccbs(%p) ", sc));
  858 
  859         while ((ccb = TAILQ_FIRST(&sc->sc_ccbq)) != NULL) {
  860 
  861                 xs = ccb->ic_xs;
  862                 if (ccb->ic_flags & IOPRBS_ICF_WATCHDOG)
  863                         timeout_del(&xs->stimeout);
  864 
  865                 if (ioprbs_exec_ccb(ccb) == 0) {
  866                         ccb->ic_flags |= IOPRBS_ICF_WATCHDOG;
  867                         timeout_set(&ccb->ic_xs->stimeout, ioprbs_watchdog,
  868                             ccb);
  869                         timeout_add(&xs->stimeout,
  870                             (IOPRBS_WATCH_TIMEOUT * hz) / 1000);
  871                         break;
  872                 }
  873                 TAILQ_REMOVE(&sc->sc_ccbq, ccb, ic_chain);
  874 
  875                 if ((xs->flags & SCSI_POLL) == 0) {
  876                         timeout_set(&ccb->ic_xs->stimeout, ioprbs_timeout,
  877                             ccb);
  878                         timeout_add(&xs->stimeout,
  879                             (ccb->ic_timeout * hz) / 1000);
  880                 }
  881         }
  882 }
  883 
  884 int
  885 ioprbs_exec_ccb(ccb)
  886         struct ioprbs_ccb *ccb;
  887 {
  888         struct scsi_xfer *xs = ccb->ic_xs;
  889 
  890         DPRINTF(("ioprbs_exec_ccb(%p, %p) ", xs, ccb));
  891 
  892         ioprbs_start(ccb);
  893 
  894         xs->error = XS_NOERROR;
  895         xs->resid = 0;
  896         return (1);
  897 }
  898 
  899 /*
  900  * Deliver a command to the controller; allocate controller resources at the
  901  * last moment when possible.
  902  */
  903 int
  904 ioprbs_start(struct ioprbs_ccb *ccb)
  905 {
  906         struct scsi_xfer *xs = ccb->ic_xs;
  907         struct scsi_link *link = xs->sc_link;
  908         struct ioprbs_softc *sc = link->adapter_softc;
  909 #ifdef I2ODEBUG
  910         u_int8_t target = link->target;
  911 #endif
  912         struct iop_msg *im;
  913         struct iop_softc *iop = (struct iop_softc *)sc->sc_dv.dv_parent;
  914         struct i2o_rbs_block_read *mf;
  915         u_int rv, flags = 0, mode = I2O_RBS_BLOCK_READ;
  916         u_int64_t ba;
  917         u_int32_t mb[IOP_MAX_MSG_SIZE / sizeof(u_int32_t)];
  918 
  919         im = iop_msg_alloc(iop, &sc->sc_ii, 0);
  920         im->im_dvcontext = ccb;
  921 
  922         switch (xs->cmd->opcode) {
  923         case PREVENT_ALLOW:
  924         case SYNCHRONIZE_CACHE:
  925                 if (xs->cmd->opcode == PREVENT_ALLOW) {
  926                         /* XXX PREVENT_ALLOW support goes here */
  927                 } else {
  928                         DPRINTF(("SYNCHRONIZE CACHE tgt %d ", target));
  929                 }
  930                 break;
  931 
  932         case WRITE_COMMAND:
  933         case WRITE_BIG:
  934                 flags = I2O_RBS_BLOCK_WRITE_CACHE_WB;
  935                 mode = I2O_RBS_BLOCK_WRITE;
  936                 /* FALLTHROUGH */
  937 
  938         case READ_COMMAND:
  939         case READ_BIG:
  940                 ba = (u_int64_t)ccb->ic_blockno * DEV_BSIZE;
  941 
  942                 /*
  943                  * Fill the message frame.  We can use the block_read
  944                  * structure for both reads and writes, as it's almost
  945                  * identical to the * block_write structure.
  946                  */
  947                 mf = (struct i2o_rbs_block_read *)mb;
  948                 mf->msgflags = I2O_MSGFLAGS(i2o_rbs_block_read);
  949                 mf->msgfunc = I2O_MSGFUNC(sc->sc_ii.ii_tid, mode);
  950                 mf->msgictx = sc->sc_ii.ii_ictx;
  951                 mf->msgtctx = im->im_tctx;
  952                 mf->flags = flags | (1 << 16);  /* flags & time multiplier */
  953                 mf->datasize = ccb->ic_blockcnt * DEV_BSIZE;
  954                 mf->lowoffset = (u_int32_t)ba;
  955                 mf->highoffset = (u_int32_t)(ba >> 32);
  956 
  957                 /* Map the data transfer and enqueue the command. */
  958                 rv = iop_msg_map_bio(iop, im, mb, xs->data,
  959                     ccb->ic_blockcnt * DEV_BSIZE, mode == I2O_RBS_BLOCK_WRITE);
  960                 if (rv == 0) {
  961                         if ((rv = iop_msg_post(iop, im, mb, 0)) != 0) {
  962                                 iop_msg_unmap(iop, im);
  963                                 iop_msg_free(iop, im);
  964                         }
  965                 }
  966                 break;
  967         }
  968         return (0);
  969 }
  970 
  971 void
  972 ioprbs_timeout(arg)
  973         void *arg;
  974 {
  975         struct ioprbs_ccb *ccb = arg;
  976         struct scsi_link *link = ccb->ic_xs->sc_link;
  977         struct ioprbs_softc *sc = link->adapter_softc;
  978         ioprbs_lock_t lock;
  979 
  980         sc_print_addr(link);
  981         printf("timed out\n");
  982 
  983         /* XXX Test for multiple timeouts */
  984 
  985         ccb->ic_xs->error = XS_TIMEOUT;
  986         lock = IOPRBS_LOCK(sc);
  987         ioprbs_enqueue_ccb(sc, ccb);
  988         IOPRBS_UNLOCK(sc, lock);
  989 }
  990 
  991 void
  992 ioprbs_watchdog(arg)
  993         void *arg;
  994 {
  995         struct ioprbs_ccb *ccb = arg;
  996         struct scsi_link *link = ccb->ic_xs->sc_link;
  997         struct ioprbs_softc *sc = link->adapter_softc;
  998         ioprbs_lock_t lock;
  999 
 1000         lock = IOPRBS_LOCK(sc);
 1001         ccb->ic_flags &= ~IOPRBS_ICF_WATCHDOG;
 1002         ioprbs_start_ccbs(sc);
 1003         IOPRBS_UNLOCK(sc, lock);
 1004 }

/* [<][>][^][v][top][bottom][index][help] */