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/aacraid/aacraid_cam.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 /*-
    2  * Copyright (c) 2002-2010 Adaptec, Inc.
    3  * Copyright (c) 2010-2012 PMC-Sierra, Inc.
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 /*
   32  * CAM front-end for communicating with non-DASD devices
   33  */
   34 
   35 #include "opt_aacraid.h"
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/kernel.h>
   40 #include <sys/sysctl.h>
   41 #include <sys/lock.h>
   42 #include <sys/malloc.h>
   43 #include <sys/module.h>
   44 #include <sys/mutex.h>
   45 
   46 #include <cam/cam.h>
   47 #include <cam/cam_ccb.h>
   48 #include <cam/cam_debug.h>
   49 #include <cam/cam_periph.h>
   50 #if __FreeBSD_version < 801000
   51 #include <cam/cam_xpt_periph.h>
   52 #endif
   53 #include <cam/cam_sim.h>
   54 #include <cam/cam_xpt_sim.h>
   55 #include <cam/scsi/scsi_all.h>
   56 #include <cam/scsi/scsi_message.h>
   57 
   58 #include <sys/bus.h>
   59 #include <sys/conf.h>
   60 #include <sys/disk.h>
   61 
   62 #include <machine/md_var.h>
   63 #include <machine/bus.h>
   64 #include <sys/rman.h>
   65 
   66 #include <vm/vm.h>
   67 #include <vm/pmap.h>
   68 
   69 #include <dev/aacraid/aacraid_reg.h>
   70 #include <sys/aac_ioctl.h>
   71 #include <dev/aacraid/aacraid_debug.h>
   72 #include <dev/aacraid/aacraid_var.h>
   73 
   74 #if __FreeBSD_version >= 700025
   75 #ifndef CAM_NEW_TRAN_CODE
   76 #define CAM_NEW_TRAN_CODE       1
   77 #endif
   78 #endif
   79 
   80 #ifndef SVPD_SUPPORTED_PAGE_LIST
   81 struct scsi_vpd_supported_page_list
   82 {
   83         u_int8_t device;
   84         u_int8_t page_code;
   85 #define SVPD_SUPPORTED_PAGE_LIST 0x00
   86         u_int8_t reserved;
   87         u_int8_t length;        /* number of VPD entries */
   88 #define SVPD_SUPPORTED_PAGES_SIZE       251
   89         u_int8_t list[SVPD_SUPPORTED_PAGES_SIZE];
   90 };
   91 #endif
   92 
   93 /************************** Version Compatibility *************************/
   94 #if     __FreeBSD_version < 700031
   95 #define aac_sim_alloc(a,b,c,d,e,f,g,h,i)        cam_sim_alloc(a,b,c,d,e,g,h,i)
   96 #else
   97 #define aac_sim_alloc                           cam_sim_alloc
   98 #endif
   99 
  100 struct aac_cam {
  101         device_t                dev;
  102         struct aac_sim          *inf;
  103         struct cam_sim          *sim;
  104         struct cam_path         *path;
  105 };
  106 
  107 static int aac_cam_probe(device_t dev);
  108 static int aac_cam_attach(device_t dev);
  109 static int aac_cam_detach(device_t dev);
  110 static void aac_cam_action(struct cam_sim *, union ccb *);
  111 static void aac_cam_poll(struct cam_sim *);
  112 static void aac_cam_complete(struct aac_command *);
  113 static void aac_container_complete(struct aac_command *);
  114 #if __FreeBSD_version >= 700000
  115 static void aac_cam_rescan(struct aac_softc *sc, uint32_t channel,
  116         uint32_t target_id);
  117 #endif
  118 static void aac_set_scsi_error(struct aac_softc *sc, union ccb *ccb, 
  119         u_int8_t status, u_int8_t key, u_int8_t asc, u_int8_t ascq);
  120 static int aac_load_map_command_sg(struct aac_softc *, struct aac_command *);
  121 static u_int64_t aac_eval_blockno(u_int8_t *);
  122 static void aac_container_rw_command(struct cam_sim *, union ccb *, u_int8_t *);
  123 static void aac_container_special_command(struct cam_sim *, union ccb *, 
  124         u_int8_t *);
  125 static void aac_passthrough_command(struct cam_sim *, union ccb *);
  126 
  127 static u_int32_t aac_cam_reset_bus(struct cam_sim *, union ccb *);
  128 static u_int32_t aac_cam_abort_ccb(struct cam_sim *, union ccb *);
  129 static u_int32_t aac_cam_term_io(struct cam_sim *, union ccb *);
  130 
  131 static devclass_t       aacraid_pass_devclass;
  132 
  133 static device_method_t  aacraid_pass_methods[] = {
  134         DEVMETHOD(device_probe,         aac_cam_probe),
  135         DEVMETHOD(device_attach,        aac_cam_attach),
  136         DEVMETHOD(device_detach,        aac_cam_detach),
  137         { 0, 0 }
  138 };
  139 
  140 static driver_t aacraid_pass_driver = {
  141         "aacraidp",
  142         aacraid_pass_methods,
  143         sizeof(struct aac_cam)
  144 };
  145 
  146 DRIVER_MODULE(aacraidp, aacraid, aacraid_pass_driver, aacraid_pass_devclass, 0, 0);
  147 MODULE_DEPEND(aacraidp, cam, 1, 1, 1);
  148 
  149 MALLOC_DEFINE(M_AACRAIDCAM, "aacraidcam", "AACRAID CAM info");
  150 
  151 static void
  152 aac_set_scsi_error(struct aac_softc *sc, union ccb *ccb, u_int8_t status, 
  153         u_int8_t key, u_int8_t asc, u_int8_t ascq)
  154 {
  155 #if __FreeBSD_version >= 900000
  156         struct scsi_sense_data_fixed *sense = 
  157                 (struct scsi_sense_data_fixed *)&ccb->csio.sense_data;
  158 #else
  159         struct scsi_sense_data *sense = &ccb->csio.sense_data;
  160 #endif
  161 
  162         fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "Error %d!", status);
  163 
  164         ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
  165         ccb->csio.scsi_status = status;
  166         if (status == SCSI_STATUS_CHECK_COND) {
  167                 ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
  168                 bzero(&ccb->csio.sense_data, ccb->csio.sense_len);
  169                 ccb->csio.sense_data.error_code = 
  170                         SSD_CURRENT_ERROR | SSD_ERRCODE_VALID;
  171                 sense->flags = key;
  172                 if (ccb->csio.sense_len >= 14) {
  173                         sense->extra_len = 6;
  174                         sense->add_sense_code = asc;
  175                         sense->add_sense_code_qual = ascq;
  176                 }
  177         }
  178 }
  179 
  180 #if __FreeBSD_version >= 700000
  181 static void
  182 aac_cam_rescan(struct aac_softc *sc, uint32_t channel, uint32_t target_id)
  183 {
  184         union ccb *ccb;
  185         struct aac_sim *sim;
  186         struct aac_cam *camsc;
  187 
  188         if (target_id == AAC_CAM_TARGET_WILDCARD)
  189                 target_id = CAM_TARGET_WILDCARD;
  190 
  191         TAILQ_FOREACH(sim, &sc->aac_sim_tqh, sim_link) {
  192                 camsc = sim->aac_cam;
  193                 if (camsc == NULL || camsc->inf == NULL ||
  194                     camsc->inf->BusNumber != channel)
  195                         continue;
  196 
  197                 ccb = xpt_alloc_ccb_nowait();
  198                 if (ccb == NULL) {
  199                         device_printf(sc->aac_dev,
  200                             "Cannot allocate ccb for bus rescan.\n");
  201                         return;
  202                 }
  203 
  204                 if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
  205                     cam_sim_path(camsc->sim),
  206                     target_id, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  207                         xpt_free_ccb(ccb);
  208                         device_printf(sc->aac_dev,
  209                             "Cannot create path for bus rescan.\n");
  210                         return;
  211                 }
  212                 xpt_rescan(ccb);
  213                 break;
  214         }
  215 }
  216 #endif
  217 
  218 static void
  219 aac_cam_event(struct aac_softc *sc, struct aac_event *event, void *arg)
  220 {
  221         union ccb *ccb;
  222         struct aac_cam *camsc;
  223 
  224         switch (event->ev_type) {
  225         case AAC_EVENT_CMFREE:
  226                 ccb = arg;
  227                 camsc = ccb->ccb_h.sim_priv.entries[0].ptr;
  228                 free(event, M_AACRAIDCAM);
  229                 xpt_release_simq(camsc->sim, 1);
  230                 ccb->ccb_h.status = CAM_REQUEUE_REQ;
  231                 xpt_done(ccb);
  232                 break;
  233         default:
  234                 device_printf(sc->aac_dev, "unknown event %d in aac_cam\n",
  235                     event->ev_type);
  236                 break;
  237         }
  238 
  239         return;
  240 }
  241 
  242 static int
  243 aac_cam_probe(device_t dev)
  244 {
  245         struct aac_softc *sc;
  246         struct aac_cam *camsc;
  247 
  248         camsc = (struct aac_cam *)device_get_softc(dev);
  249         if (!camsc->inf)
  250                 return (0);
  251         sc = camsc->inf->aac_sc;
  252         fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
  253         return (0);
  254 }
  255 
  256 static int
  257 aac_cam_detach(device_t dev)
  258 {
  259         struct aac_softc *sc;
  260         struct aac_cam *camsc;
  261 
  262         camsc = (struct aac_cam *)device_get_softc(dev);
  263         if (!camsc->inf) 
  264                 return (0);
  265         sc = camsc->inf->aac_sc;
  266         fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
  267         camsc->inf->aac_cam = NULL;
  268 
  269         mtx_lock(&sc->aac_io_lock);
  270 
  271         xpt_async(AC_LOST_DEVICE, camsc->path, NULL);
  272         xpt_free_path(camsc->path);
  273         xpt_bus_deregister(cam_sim_path(camsc->sim));
  274         cam_sim_free(camsc->sim, /*free_devq*/TRUE);
  275 
  276         sc->cam_rescan_cb = NULL;
  277 
  278         mtx_unlock(&sc->aac_io_lock);
  279 
  280         return (0);
  281 }
  282 
  283 /*
  284  * Register the driver as a CAM SIM
  285  */
  286 static int
  287 aac_cam_attach(device_t dev)
  288 {
  289         struct cam_devq *devq;
  290         struct cam_sim *sim;
  291         struct cam_path *path;
  292         struct aac_cam *camsc;
  293         struct aac_sim *inf;
  294 
  295         camsc = (struct aac_cam *)device_get_softc(dev);
  296         inf = (struct aac_sim *)device_get_ivars(dev);
  297         if (!inf)
  298                 return (EIO);
  299         fwprintf(inf->aac_sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
  300         camsc->inf = inf;
  301         camsc->inf->aac_cam = camsc;
  302 
  303         devq = cam_simq_alloc(inf->TargetsPerBus);
  304         if (devq == NULL)
  305                 return (EIO);
  306 
  307         sim = aac_sim_alloc(aac_cam_action, aac_cam_poll, "aacraidp", camsc,
  308             device_get_unit(dev), &inf->aac_sc->aac_io_lock, 1, 1, devq);
  309         if (sim == NULL) {
  310                 cam_simq_free(devq);
  311                 return (EIO);
  312         }
  313 
  314         /* Since every bus has it's own sim, every bus 'appears' as bus 0 */
  315         mtx_lock(&inf->aac_sc->aac_io_lock);
  316         if (aac_xpt_bus_register(sim, dev, 0) != CAM_SUCCESS) {
  317                 cam_sim_free(sim, TRUE);
  318                 mtx_unlock(&inf->aac_sc->aac_io_lock);
  319                 return (EIO);
  320         }
  321 
  322         if (xpt_create_path(&path, NULL, cam_sim_path(sim),
  323             CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  324                 xpt_bus_deregister(cam_sim_path(sim));
  325                 cam_sim_free(sim, TRUE);
  326                 mtx_unlock(&inf->aac_sc->aac_io_lock);
  327                 return (EIO);
  328         }
  329 
  330 #if __FreeBSD_version >= 700000
  331         inf->aac_sc->cam_rescan_cb = aac_cam_rescan;
  332 #endif
  333         mtx_unlock(&inf->aac_sc->aac_io_lock);
  334 
  335         camsc->sim = sim;
  336         camsc->path = path;
  337 
  338         return (0);
  339 }
  340 
  341 static u_int64_t 
  342 aac_eval_blockno(u_int8_t *cmdp) 
  343 {
  344         u_int64_t blockno;
  345 
  346         switch (cmdp[0]) {
  347         case READ_6:
  348         case WRITE_6:
  349                 blockno = scsi_3btoul(((struct scsi_rw_6 *)cmdp)->addr);        
  350                 break;
  351         case READ_10:
  352         case WRITE_10:
  353                 blockno = scsi_4btoul(((struct scsi_rw_10 *)cmdp)->addr);       
  354                 break;
  355         case READ_12:
  356         case WRITE_12:
  357                 blockno = scsi_4btoul(((struct scsi_rw_12 *)cmdp)->addr);       
  358                 break;
  359         case READ_16:
  360         case WRITE_16:
  361                 blockno = scsi_8btou64(((struct scsi_rw_16 *)cmdp)->addr);      
  362                 break;
  363         default:
  364                 blockno = 0;
  365                 break;
  366         }
  367         return(blockno);
  368 }               
  369 
  370 static void
  371 aac_container_rw_command(struct cam_sim *sim, union ccb *ccb, u_int8_t *cmdp)
  372 {
  373         struct  aac_cam *camsc;
  374         struct  aac_softc *sc;
  375         struct  aac_command *cm;
  376         struct  aac_fib *fib;
  377         u_int64_t blockno;
  378 
  379         camsc = (struct aac_cam *)cam_sim_softc(sim);
  380         sc = camsc->inf->aac_sc;
  381         mtx_assert(&sc->aac_io_lock, MA_OWNED);
  382 
  383         if (aacraid_alloc_command(sc, &cm)) {
  384                 struct aac_event *event;
  385 
  386                 xpt_freeze_simq(sim, 1);
  387                 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
  388                 ccb->ccb_h.sim_priv.entries[0].ptr = camsc;
  389                 event = malloc(sizeof(struct aac_event), M_AACRAIDCAM,
  390                     M_NOWAIT | M_ZERO);
  391                 if (event == NULL) {
  392                         device_printf(sc->aac_dev,
  393                             "Warning, out of memory for event\n");
  394                         return;
  395                 }
  396                 event->ev_callback = aac_cam_event;
  397                 event->ev_arg = ccb;
  398                 event->ev_type = AAC_EVENT_CMFREE;
  399                 aacraid_add_event(sc, event);
  400                 return;
  401         }
  402 
  403         fib = cm->cm_fib;
  404         switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
  405         case CAM_DIR_IN:
  406                 cm->cm_flags |= AAC_CMD_DATAIN;
  407                 break;
  408         case CAM_DIR_OUT:
  409                 cm->cm_flags |= AAC_CMD_DATAOUT;
  410                 break;
  411         case CAM_DIR_NONE:
  412                 break;
  413         default:
  414                 cm->cm_flags |= AAC_CMD_DATAIN | AAC_CMD_DATAOUT;
  415                 break;
  416         }
  417 
  418         blockno = aac_eval_blockno(cmdp);
  419 
  420         cm->cm_complete = aac_container_complete;
  421         cm->cm_ccb = ccb;
  422         cm->cm_timestamp = time_uptime;
  423         cm->cm_data = (void *)ccb->csio.data_ptr;
  424         cm->cm_datalen = ccb->csio.dxfer_len;
  425 
  426         fib->Header.Size = sizeof(struct aac_fib_header);
  427         fib->Header.XferState =
  428                 AAC_FIBSTATE_HOSTOWNED   |
  429                 AAC_FIBSTATE_INITIALISED |
  430                 AAC_FIBSTATE_EMPTY       |
  431                 AAC_FIBSTATE_FROMHOST    |
  432                 AAC_FIBSTATE_REXPECTED   |
  433                 AAC_FIBSTATE_NORM        |
  434                 AAC_FIBSTATE_ASYNC       |
  435                 AAC_FIBSTATE_FAST_RESPONSE;
  436 
  437         if (sc->flags & AAC_FLAGS_NEW_COMM_TYPE2) {
  438                 struct aac_raw_io2 *raw;
  439                 raw = (struct aac_raw_io2 *)&fib->data[0];
  440                 bzero(raw, sizeof(struct aac_raw_io2));
  441                 fib->Header.Command = RawIo2;
  442                 raw->strtBlkLow = (u_int32_t)blockno;
  443                 raw->strtBlkHigh = (u_int32_t)(blockno >> 32);
  444                 raw->byteCnt = cm->cm_datalen;
  445                 raw->ldNum = ccb->ccb_h.target_id;
  446                 fib->Header.Size += sizeof(struct aac_raw_io2);
  447                 cm->cm_sgtable = (struct aac_sg_table *)raw->sge;
  448                 if (cm->cm_flags & AAC_CMD_DATAIN) 
  449                         raw->flags = RIO2_IO_TYPE_READ | RIO2_SG_FORMAT_IEEE1212;
  450                 else
  451                         raw->flags = RIO2_IO_TYPE_WRITE | RIO2_SG_FORMAT_IEEE1212;
  452         } else if (sc->flags & AAC_FLAGS_RAW_IO) {
  453                 struct aac_raw_io *raw;
  454                 raw = (struct aac_raw_io *)&fib->data[0];
  455                 bzero(raw, sizeof(struct aac_raw_io));
  456                 fib->Header.Command = RawIo;
  457                 raw->BlockNumber = blockno;
  458                 raw->ByteCount = cm->cm_datalen;
  459                 raw->ContainerId = ccb->ccb_h.target_id;
  460                 fib->Header.Size += sizeof(struct aac_raw_io);
  461                 cm->cm_sgtable = (struct aac_sg_table *)
  462                         &raw->SgMapRaw;
  463                 if (cm->cm_flags & AAC_CMD_DATAIN) 
  464                         raw->Flags = 1;
  465         } else if ((sc->flags & AAC_FLAGS_SG_64BIT) == 0) {
  466                 fib->Header.Command = ContainerCommand;
  467                 if (cm->cm_flags & AAC_CMD_DATAIN) {
  468                         struct aac_blockread *br;
  469                         br = (struct aac_blockread *)&fib->data[0];
  470                         br->Command = VM_CtBlockRead;
  471                         br->ContainerId = ccb->ccb_h.target_id;
  472                         br->BlockNumber = blockno;
  473                         br->ByteCount = cm->cm_datalen;
  474                         fib->Header.Size += sizeof(struct aac_blockread);
  475                         cm->cm_sgtable = &br->SgMap;
  476                 } else {
  477                         struct aac_blockwrite *bw;
  478                         bw = (struct aac_blockwrite *)&fib->data[0];
  479                         bw->Command = VM_CtBlockWrite;
  480                         bw->ContainerId = ccb->ccb_h.target_id;
  481                         bw->BlockNumber = blockno;
  482                         bw->ByteCount = cm->cm_datalen;
  483                         bw->Stable = CUNSTABLE;
  484                         fib->Header.Size += sizeof(struct aac_blockwrite);
  485                         cm->cm_sgtable = &bw->SgMap;
  486                 }
  487         } else {
  488                 fib->Header.Command = ContainerCommand64;
  489                 if (cm->cm_flags & AAC_CMD_DATAIN) {
  490                         struct aac_blockread64 *br;
  491                         br = (struct aac_blockread64 *)&fib->data[0];
  492                         br->Command = VM_CtHostRead64;
  493                         br->ContainerId = ccb->ccb_h.target_id;
  494                         br->SectorCount = cm->cm_datalen/AAC_BLOCK_SIZE;
  495                         br->BlockNumber = blockno;
  496                         br->Pad = 0;
  497                         br->Flags = 0;
  498                         fib->Header.Size += sizeof(struct aac_blockread64);
  499                         cm->cm_sgtable = (struct aac_sg_table *)&br->SgMap64;
  500                 } else {
  501                         struct aac_blockwrite64 *bw;
  502                         bw = (struct aac_blockwrite64 *)&fib->data[0];
  503                         bw->Command = VM_CtHostWrite64;
  504                         bw->ContainerId = ccb->ccb_h.target_id;
  505                         bw->SectorCount = cm->cm_datalen/AAC_BLOCK_SIZE;
  506                         bw->BlockNumber = blockno;
  507                         bw->Pad = 0;
  508                         bw->Flags = 0;
  509                         fib->Header.Size += sizeof(struct aac_blockwrite64);
  510                         cm->cm_sgtable = (struct aac_sg_table *)&bw->SgMap64;
  511                 }
  512         }
  513         aac_enqueue_ready(cm);
  514         aacraid_startio(cm->cm_sc);
  515 }
  516 
  517 static void
  518 aac_container_special_command(struct cam_sim *sim, union ccb *ccb, 
  519         u_int8_t *cmdp)
  520 {
  521         struct  aac_cam *camsc;
  522         struct  aac_softc *sc;
  523         struct  aac_container *co;
  524 
  525         camsc = (struct aac_cam *)cam_sim_softc(sim);
  526         sc = camsc->inf->aac_sc;
  527         mtx_assert(&sc->aac_io_lock, MA_OWNED);
  528 
  529         TAILQ_FOREACH(co, &sc->aac_container_tqh, co_link) {
  530                 fwprintf(sc, HBA_FLAGS_DBG_ERROR_B, "found container %d search for %d", co->co_mntobj.ObjectId, ccb->ccb_h.target_id);
  531                 if (co->co_mntobj.ObjectId == ccb->ccb_h.target_id)
  532                         break;
  533         }
  534         if (co == NULL || ccb->ccb_h.target_lun != 0) {
  535                 fwprintf(sc, HBA_FLAGS_DBG_ERROR_B, 
  536                         "Container not present: cmd 0x%x id %d lun %d len %d", 
  537                         *cmdp, ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
  538                         ccb->csio.dxfer_len);
  539                 ccb->ccb_h.status = CAM_DEV_NOT_THERE;
  540                 xpt_done(ccb);
  541                 return;
  542         }
  543 
  544         if (ccb->csio.dxfer_len)
  545                 bzero(ccb->csio.data_ptr, ccb->csio.dxfer_len);
  546 
  547         switch (*cmdp) {
  548         case INQUIRY:
  549         {
  550                 struct scsi_inquiry *inq = (struct scsi_inquiry *)cmdp;
  551 
  552                 fwprintf(sc, HBA_FLAGS_DBG_COMM_B, 
  553                 "Container INQUIRY id %d lun %d len %d VPD 0x%x Page 0x%x", 
  554                         ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
  555                         ccb->csio.dxfer_len, inq->byte2, inq->page_code);
  556                 if (!(inq->byte2 & SI_EVPD)) {
  557                         struct scsi_inquiry_data *p = 
  558                                 (struct scsi_inquiry_data *)ccb->csio.data_ptr;
  559                         if (inq->page_code != 0) {
  560                                 aac_set_scsi_error(sc, ccb,
  561                                         SCSI_STATUS_CHECK_COND,
  562                                         SSD_KEY_ILLEGAL_REQUEST, 0x24, 0x00);   
  563                                 xpt_done(ccb);
  564                                 return; 
  565                         }       
  566                         p->device = T_DIRECT;
  567                         p->version = SCSI_REV_SPC2;
  568                         p->response_format = 2;
  569                         if (ccb->csio.dxfer_len >= 36) {
  570                                 p->additional_length = 31;
  571                                 p->flags = SID_WBus16|SID_Sync|SID_CmdQue;
  572                                 /* OEM Vendor defines */
  573                                 strncpy(p->vendor, "Adaptec ", sizeof(p->vendor));
  574                                 strncpy(p->product, "Array           ",
  575                                     sizeof(p->product));
  576                                 strncpy(p->revision, "V1.0",
  577                                     sizeof(p->revision));
  578                         }       
  579                 } else {
  580                         if (inq->page_code == SVPD_SUPPORTED_PAGE_LIST) {
  581                                 struct scsi_vpd_supported_page_list *p =
  582                                         (struct scsi_vpd_supported_page_list *)
  583                                         ccb->csio.data_ptr;
  584                                 p->device = T_DIRECT;
  585                                 p->page_code = SVPD_SUPPORTED_PAGE_LIST;
  586                                 p->length = 2;
  587                                 p->list[0] = SVPD_SUPPORTED_PAGE_LIST;
  588                                 p->list[1] = SVPD_UNIT_SERIAL_NUMBER;
  589                         } else if (inq->page_code == SVPD_UNIT_SERIAL_NUMBER) {
  590                                 struct scsi_vpd_unit_serial_number *p =
  591                                         (struct scsi_vpd_unit_serial_number *)
  592                                         ccb->csio.data_ptr;     
  593                                 p->device = T_DIRECT;
  594                                 p->page_code = SVPD_UNIT_SERIAL_NUMBER;
  595                                 p->length = sprintf((char *)p->serial_num, 
  596                                         "%08X%02X", co->co_uid, 
  597                                         ccb->ccb_h.target_id);
  598                         } else {
  599                                 aac_set_scsi_error(sc, ccb, 
  600                                         SCSI_STATUS_CHECK_COND,
  601                                         SSD_KEY_ILLEGAL_REQUEST, 0x24, 0x00);   
  602                                 xpt_done(ccb);
  603                                 return; 
  604                         }
  605                 }
  606                 ccb->ccb_h.status = CAM_REQ_CMP;
  607                 break;
  608         }
  609 
  610         case REPORT_LUNS:
  611                 fwprintf(sc, HBA_FLAGS_DBG_COMM_B, 
  612                 "Container REPORT_LUNS id %d lun %d len %d", 
  613                 ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
  614                 ccb->csio.dxfer_len);
  615                 ccb->ccb_h.status = CAM_REQ_CMP;
  616                 break;
  617 
  618         case START_STOP:
  619         {
  620                 struct scsi_start_stop_unit *ss = 
  621                         (struct scsi_start_stop_unit *)cmdp;
  622                 fwprintf(sc, HBA_FLAGS_DBG_COMM_B, 
  623                 "Container START_STOP id %d lun %d len %d", 
  624                 ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
  625                 ccb->csio.dxfer_len);
  626                 if (sc->aac_support_opt2 & AAC_SUPPORTED_POWER_MANAGEMENT) {
  627                         struct aac_command *cm;
  628                         struct aac_fib *fib;
  629                         struct aac_cnt_config *ccfg;
  630 
  631                         if (aacraid_alloc_command(sc, &cm)) {
  632                                 struct aac_event *event;
  633 
  634                                 xpt_freeze_simq(sim, 1);
  635                                 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
  636                                 ccb->ccb_h.sim_priv.entries[0].ptr = camsc;
  637                                 event = malloc(sizeof(struct aac_event), M_AACRAIDCAM,
  638                                         M_NOWAIT | M_ZERO);
  639                                 if (event == NULL) {
  640                                         device_printf(sc->aac_dev,
  641                                                 "Warning, out of memory for event\n");
  642                                         return;
  643                                 }
  644                                 event->ev_callback = aac_cam_event;
  645                                 event->ev_arg = ccb;
  646                                 event->ev_type = AAC_EVENT_CMFREE;
  647                                 aacraid_add_event(sc, event);
  648                                 return;
  649                         }
  650 
  651                         fib = cm->cm_fib;
  652                         cm->cm_timestamp = time_uptime;
  653                         cm->cm_datalen = 0;
  654 
  655                         fib->Header.Size = 
  656                                 sizeof(struct aac_fib_header) + sizeof(struct aac_cnt_config);
  657                         fib->Header.XferState =
  658                                 AAC_FIBSTATE_HOSTOWNED   |
  659                                 AAC_FIBSTATE_INITIALISED |
  660                                 AAC_FIBSTATE_EMPTY       |
  661                                 AAC_FIBSTATE_FROMHOST    |
  662                                 AAC_FIBSTATE_REXPECTED   |
  663                                 AAC_FIBSTATE_NORM        |
  664                                 AAC_FIBSTATE_ASYNC       |
  665                                 AAC_FIBSTATE_FAST_RESPONSE;
  666                         fib->Header.Command = ContainerCommand;
  667 
  668                         /* Start unit */
  669                         ccfg = (struct aac_cnt_config *)&fib->data[0];
  670                         bzero(ccfg, sizeof (*ccfg) - CT_PACKET_SIZE);
  671                         ccfg->Command = VM_ContainerConfig;
  672                         ccfg->CTCommand.command = CT_PM_DRIVER_SUPPORT;
  673                         ccfg->CTCommand.param[0] = (ss->how & SSS_START ?
  674                                 AAC_PM_DRIVERSUP_START_UNIT : 
  675                                 AAC_PM_DRIVERSUP_STOP_UNIT);
  676                         ccfg->CTCommand.param[1] = co->co_mntobj.ObjectId;
  677                         ccfg->CTCommand.param[2] = 0;   /* 1 - immediate */
  678 
  679                         if (aacraid_wait_command(cm) != 0 ||
  680                                 *(u_int32_t *)&fib->data[0] != 0) {
  681                                 printf("Power Management: Error start/stop container %d\n", 
  682                                 co->co_mntobj.ObjectId);
  683                         }
  684                         aacraid_release_command(cm);
  685                 }
  686                 ccb->ccb_h.status = CAM_REQ_CMP;
  687                 break;
  688         }
  689 
  690         case TEST_UNIT_READY:
  691                 fwprintf(sc, HBA_FLAGS_DBG_COMM_B, 
  692                 "Container TEST_UNIT_READY id %d lun %d len %d", 
  693                 ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
  694                 ccb->csio.dxfer_len);
  695                 ccb->ccb_h.status = CAM_REQ_CMP;
  696                 break;
  697 
  698         case REQUEST_SENSE:
  699                 fwprintf(sc, HBA_FLAGS_DBG_COMM_B, 
  700                 "Container REQUEST_SENSE id %d lun %d len %d", 
  701                 ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
  702                 ccb->csio.dxfer_len);
  703                 ccb->ccb_h.status = CAM_REQ_CMP;
  704                 break;
  705 
  706         case READ_CAPACITY:
  707         {
  708                 struct scsi_read_capacity_data *p = 
  709                         (struct scsi_read_capacity_data *)ccb->csio.data_ptr;
  710                 fwprintf(sc, HBA_FLAGS_DBG_COMM_B, 
  711                 "Container READ_CAPACITY id %d lun %d len %d", 
  712                 ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
  713                 ccb->csio.dxfer_len);
  714                 scsi_ulto4b(co->co_mntobj.ObjExtension.BlockDevice.BlockSize, p->length);
  715                 /* check if greater than 2TB */
  716                 if (co->co_mntobj.CapacityHigh) {
  717                         if (sc->flags & AAC_FLAGS_LBA_64BIT)
  718                                 scsi_ulto4b(0xffffffff, p->addr);
  719                 } else {
  720                         scsi_ulto4b(co->co_mntobj.Capacity-1, p->addr);
  721                 } 
  722                 ccb->ccb_h.status = CAM_REQ_CMP;
  723                 break;
  724         }
  725 
  726         case SERVICE_ACTION_IN:
  727         {       
  728                 struct scsi_read_capacity_data_long *p = 
  729                         (struct scsi_read_capacity_data_long *)
  730                         ccb->csio.data_ptr;
  731                 fwprintf(sc, HBA_FLAGS_DBG_COMM_B, 
  732                 "Container SERVICE_ACTION_IN id %d lun %d len %d", 
  733                 ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
  734                 ccb->csio.dxfer_len);
  735                 if (((struct scsi_read_capacity_16 *)cmdp)->service_action != 
  736                         SRC16_SERVICE_ACTION) {
  737                         aac_set_scsi_error(sc, ccb, SCSI_STATUS_CHECK_COND,
  738                                 SSD_KEY_ILLEGAL_REQUEST, 0x24, 0x00);   
  739                         xpt_done(ccb);
  740                         return; 
  741                 }
  742                 scsi_ulto4b(co->co_mntobj.ObjExtension.BlockDevice.BlockSize, p->length);
  743                 scsi_ulto4b(co->co_mntobj.CapacityHigh, p->addr);
  744                 scsi_ulto4b(co->co_mntobj.Capacity-1, &p->addr[4]);
  745 
  746                 if (ccb->csio.dxfer_len >= 14) {                
  747                         u_int32_t mapping = co->co_mntobj.ObjExtension.BlockDevice.bdLgclPhysMap;
  748                         p->prot_lbppbe = 0;
  749                         while (mapping > 1) {
  750                                 mapping >>= 1;
  751                                 p->prot_lbppbe++;
  752                         }
  753                         p->prot_lbppbe &= 0x0f;
  754                 }
  755 
  756                 ccb->ccb_h.status = CAM_REQ_CMP;
  757                 break;
  758         }
  759 
  760         case MODE_SENSE_6:
  761         {
  762                 struct scsi_mode_sense_6 *msp =(struct scsi_mode_sense_6 *)cmdp;
  763                 struct ms6_data {
  764                         struct scsi_mode_hdr_6 hd;
  765                         struct scsi_mode_block_descr bd;
  766                         char pages;
  767                 } *p = (struct ms6_data *)ccb->csio.data_ptr;
  768                 char *pagep;
  769                 int return_all_pages = FALSE;
  770 
  771                 fwprintf(sc, HBA_FLAGS_DBG_COMM_B, 
  772                 "Container MODE_SENSE id %d lun %d len %d page %d", 
  773                 ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
  774                 ccb->csio.dxfer_len, msp->page);
  775                 p->hd.datalen = sizeof(struct scsi_mode_hdr_6) - 1;
  776                 if (co->co_mntobj.ContentState & AAC_FSCS_READONLY)
  777                         p->hd.dev_specific = 0x80;      /* WP */
  778                 p->hd.dev_specific |= 0x10;     /* DPOFUA */
  779                 if (msp->byte2 & SMS_DBD) {
  780                         p->hd.block_descr_len = 0;
  781                 } else {
  782                         p->hd.block_descr_len = 
  783                                 sizeof(struct scsi_mode_block_descr);   
  784                         p->hd.datalen += p->hd.block_descr_len;
  785                         scsi_ulto3b(co->co_mntobj.ObjExtension.BlockDevice.BlockSize, p->bd.block_len);
  786                         if (co->co_mntobj.Capacity > 0xffffff ||
  787                                 co->co_mntobj.CapacityHigh) {
  788                                 p->bd.num_blocks[0] = 0xff;
  789                                 p->bd.num_blocks[1] = 0xff;
  790                                 p->bd.num_blocks[2] = 0xff;
  791                         } else {
  792                                 p->bd.num_blocks[0] = (u_int8_t)
  793                                         (co->co_mntobj.Capacity >> 16);
  794                                 p->bd.num_blocks[1] = (u_int8_t)
  795                                         (co->co_mntobj.Capacity >> 8);
  796                                 p->bd.num_blocks[2] = (u_int8_t)
  797                                         (co->co_mntobj.Capacity);
  798                         }
  799                 }
  800                 pagep = &p->pages;      
  801                 switch (msp->page & SMS_PAGE_CODE) {
  802                 case SMS_ALL_PAGES_PAGE:
  803                         return_all_pages = TRUE;
  804                 case SMS_CONTROL_MODE_PAGE:
  805                 {
  806                         struct scsi_control_page *cp = 
  807                                 (struct scsi_control_page *)pagep;
  808 
  809                         if (ccb->csio.dxfer_len <= p->hd.datalen + 8) {
  810                                 aac_set_scsi_error(sc, ccb,
  811                                         SCSI_STATUS_CHECK_COND,
  812                                         SSD_KEY_ILLEGAL_REQUEST, 0x24, 0x00);   
  813                                 xpt_done(ccb);
  814                                 return; 
  815                         }
  816                         cp->page_code = SMS_CONTROL_MODE_PAGE;
  817                         cp->page_length = 6;
  818                         p->hd.datalen += 8;
  819                         pagep += 8;
  820                         if (!return_all_pages)
  821                                 break;
  822                 }
  823                 case SMS_VENDOR_SPECIFIC_PAGE:
  824                         break;  
  825                 default:        
  826                         aac_set_scsi_error(sc, ccb, SCSI_STATUS_CHECK_COND,
  827                                 SSD_KEY_ILLEGAL_REQUEST, 0x24, 0x00);   
  828                         xpt_done(ccb);
  829                         return; 
  830                 }
  831                 ccb->ccb_h.status = CAM_REQ_CMP;
  832                 break;
  833         }
  834 
  835         case SYNCHRONIZE_CACHE:
  836                 fwprintf(sc, HBA_FLAGS_DBG_COMM_B, 
  837                 "Container SYNCHRONIZE_CACHE id %d lun %d len %d", 
  838                 ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
  839                 ccb->csio.dxfer_len);
  840                 ccb->ccb_h.status = CAM_REQ_CMP;
  841                 break;
  842 
  843         default:
  844                 fwprintf(sc, HBA_FLAGS_DBG_ERROR_B, 
  845                 "Container unsupp. cmd 0x%x id %d lun %d len %d", 
  846                 *cmdp, ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
  847                 ccb->csio.dxfer_len);
  848                 ccb->ccb_h.status = CAM_REQ_CMP; /*CAM_REQ_INVALID*/
  849                 break;
  850         }
  851         xpt_done(ccb);
  852 }
  853 
  854 static void
  855 aac_passthrough_command(struct cam_sim *sim, union ccb *ccb)
  856 {
  857         struct  aac_cam *camsc;
  858         struct  aac_softc *sc;
  859         struct  aac_command *cm;
  860         struct  aac_fib *fib;
  861         struct  aac_srb *srb;
  862 
  863         camsc = (struct aac_cam *)cam_sim_softc(sim);
  864         sc = camsc->inf->aac_sc;
  865         mtx_assert(&sc->aac_io_lock, MA_OWNED);
  866 
  867         if (aacraid_alloc_command(sc, &cm)) {
  868                 struct aac_event *event;
  869 
  870                 xpt_freeze_simq(sim, 1);
  871                 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
  872                 ccb->ccb_h.sim_priv.entries[0].ptr = camsc;
  873                 event = malloc(sizeof(struct aac_event), M_AACRAIDCAM,
  874                     M_NOWAIT | M_ZERO);
  875                 if (event == NULL) {
  876                         device_printf(sc->aac_dev,
  877                             "Warning, out of memory for event\n");
  878                         return;
  879                 }
  880                 event->ev_callback = aac_cam_event;
  881                 event->ev_arg = ccb;
  882                 event->ev_type = AAC_EVENT_CMFREE;
  883                 aacraid_add_event(sc, event);
  884                 return;
  885         }
  886 
  887         fib = cm->cm_fib;
  888         switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
  889         case CAM_DIR_IN:
  890                 cm->cm_flags |= AAC_CMD_DATAIN;
  891                 break;
  892         case CAM_DIR_OUT:
  893                 cm->cm_flags |= AAC_CMD_DATAOUT;
  894                 break;
  895         case CAM_DIR_NONE:
  896                 break;
  897         default:
  898                 cm->cm_flags |= AAC_CMD_DATAIN | AAC_CMD_DATAOUT;
  899                 break;
  900         }
  901 
  902         srb = (struct aac_srb *)&fib->data[0];
  903         srb->function = AAC_SRB_FUNC_EXECUTE_SCSI;
  904         if (cm->cm_flags & (AAC_CMD_DATAIN|AAC_CMD_DATAOUT)) 
  905                 srb->flags = AAC_SRB_FLAGS_UNSPECIFIED_DIRECTION;
  906         if (cm->cm_flags & AAC_CMD_DATAIN) 
  907                 srb->flags = AAC_SRB_FLAGS_DATA_IN;
  908         else if (cm->cm_flags & AAC_CMD_DATAOUT) 
  909                 srb->flags = AAC_SRB_FLAGS_DATA_OUT;
  910         else  
  911                 srb->flags = AAC_SRB_FLAGS_NO_DATA_XFER;
  912 
  913         /*
  914          * Copy the CDB into the SRB.  It's only 6-16 bytes,
  915          * so a copy is not too expensive.
  916          */
  917         srb->cdb_len = ccb->csio.cdb_len;
  918         if (ccb->ccb_h.flags & CAM_CDB_POINTER)
  919                 bcopy(ccb->csio.cdb_io.cdb_ptr, (u_int8_t *)&srb->cdb[0],
  920                         srb->cdb_len);
  921         else
  922                 bcopy(ccb->csio.cdb_io.cdb_bytes, (u_int8_t *)&srb->cdb[0],
  923                         srb->cdb_len);
  924 
  925         /* Set command */
  926         fib->Header.Command = (sc->flags & AAC_FLAGS_SG_64BIT) ? 
  927                 ScsiPortCommandU64 : ScsiPortCommand;
  928         fib->Header.Size = sizeof(struct aac_fib_header) +
  929                         sizeof(struct aac_srb);
  930 
  931         /* Map the s/g list */
  932         cm->cm_sgtable = &srb->sg_map;
  933         if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
  934                 /*
  935                  * Arrange things so that the S/G
  936                  * map will get set up automagically
  937                  */
  938                 cm->cm_data = (void *)ccb->csio.data_ptr;
  939                 cm->cm_datalen = ccb->csio.dxfer_len;
  940                 srb->data_len = ccb->csio.dxfer_len;
  941         } else {
  942                 cm->cm_data = NULL;
  943                 cm->cm_datalen = 0;
  944                 srb->data_len = 0;
  945         }
  946 
  947         srb->bus = camsc->inf->BusNumber - 1; /* Bus no. rel. to the card */
  948         srb->target = ccb->ccb_h.target_id;
  949         srb->lun = ccb->ccb_h.target_lun;
  950         srb->timeout = ccb->ccb_h.timeout;      /* XXX */
  951         srb->retry_limit = 0;
  952 
  953         cm->cm_complete = aac_cam_complete;
  954         cm->cm_ccb = ccb;
  955         cm->cm_timestamp = time_uptime;
  956 
  957         fib->Header.XferState =
  958                         AAC_FIBSTATE_HOSTOWNED  |
  959                         AAC_FIBSTATE_INITIALISED        |
  960                         AAC_FIBSTATE_FROMHOST   |
  961                         AAC_FIBSTATE_REXPECTED  |
  962                         AAC_FIBSTATE_NORM       |
  963                         AAC_FIBSTATE_ASYNC       |
  964                         AAC_FIBSTATE_FAST_RESPONSE;
  965 
  966         aac_enqueue_ready(cm);
  967         aacraid_startio(cm->cm_sc);
  968 }
  969 
  970 static void
  971 aac_cam_action(struct cam_sim *sim, union ccb *ccb)
  972 {
  973         struct  aac_cam *camsc;
  974         struct  aac_softc *sc;
  975 
  976         camsc = (struct aac_cam *)cam_sim_softc(sim);
  977         sc = camsc->inf->aac_sc;
  978         fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
  979         mtx_assert(&sc->aac_io_lock, MA_OWNED);
  980 
  981         /* Synchronous ops, and ops that don't require communication with the
  982          * controller */
  983         switch(ccb->ccb_h.func_code) {
  984         case XPT_SCSI_IO:
  985                 /* This is handled down below */
  986                 break;
  987         case XPT_CALC_GEOMETRY:
  988         {
  989                 struct ccb_calc_geometry *ccg;
  990                 u_int32_t size_mb;
  991                 u_int32_t secs_per_cylinder;
  992 
  993                 ccg = &ccb->ccg;
  994                 size_mb = ccg->volume_size /
  995                     ((1024L * 1024L) / ccg->block_size);
  996                 if (size_mb >= (2 * 1024)) {            /* 2GB */
  997                         ccg->heads = 255;
  998                         ccg->secs_per_track = 63;
  999                 } else if (size_mb >= (1 * 1024)) {     /* 1GB */
 1000                         ccg->heads = 128;
 1001                         ccg->secs_per_track = 32;
 1002                 } else {
 1003                         ccg->heads = 64;
 1004                         ccg->secs_per_track = 32;
 1005                 }
 1006                 secs_per_cylinder = ccg->heads * ccg->secs_per_track;
 1007                 ccg->cylinders = ccg->volume_size / secs_per_cylinder;
 1008 
 1009                 ccb->ccb_h.status = CAM_REQ_CMP;
 1010                 xpt_done(ccb);
 1011                 return;
 1012         }
 1013         case XPT_PATH_INQ:
 1014         {
 1015                 struct ccb_pathinq *cpi = &ccb->cpi;
 1016 
 1017                 cpi->version_num = 1;
 1018                 cpi->target_sprt = 0;
 1019                 cpi->hba_eng_cnt = 0;
 1020                 cpi->max_target = camsc->inf->TargetsPerBus;
 1021                 cpi->max_lun = 8;       /* Per the controller spec */
 1022                 cpi->initiator_id = camsc->inf->InitiatorBusId;
 1023                 cpi->bus_id = camsc->inf->BusNumber;
 1024 #if __FreeBSD_version >= 800000
 1025                 cpi->maxio = sc->aac_max_sectors << 9;
 1026 #endif
 1027 
 1028                 /*
 1029                  * Resetting via the passthrough or parallel bus scan
 1030                  * causes problems.
 1031                  */
 1032                 cpi->hba_misc = PIM_NOBUSRESET;
 1033                 cpi->hba_inquiry = PI_TAG_ABLE;
 1034                 cpi->base_transfer_speed = 300000;
 1035 #ifdef CAM_NEW_TRAN_CODE
 1036                 cpi->hba_misc |= PIM_SEQSCAN;
 1037                 cpi->protocol = PROTO_SCSI;
 1038                 cpi->transport = XPORT_SAS;
 1039                 cpi->transport_version = 0;
 1040                 cpi->protocol_version = SCSI_REV_SPC2;
 1041 #endif
 1042                 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
 1043                 strncpy(cpi->hba_vid, "PMC-Sierra", HBA_IDLEN);
 1044                 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
 1045                 cpi->unit_number = cam_sim_unit(sim);
 1046                 ccb->ccb_h.status = CAM_REQ_CMP;
 1047                 xpt_done(ccb);
 1048                 return;
 1049         }
 1050         case XPT_GET_TRAN_SETTINGS:
 1051         {
 1052 #ifdef CAM_NEW_TRAN_CODE
 1053                 struct ccb_trans_settings_scsi *scsi =
 1054                         &ccb->cts.proto_specific.scsi;
 1055                 struct ccb_trans_settings_spi *spi =
 1056                         &ccb->cts.xport_specific.spi;
 1057                 ccb->cts.protocol = PROTO_SCSI;
 1058                 ccb->cts.protocol_version = SCSI_REV_SPC2;
 1059                 ccb->cts.transport = XPORT_SAS;
 1060                 ccb->cts.transport_version = 0;
 1061                 scsi->valid = CTS_SCSI_VALID_TQ;
 1062                 scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
 1063                 spi->valid |= CTS_SPI_VALID_DISC;
 1064                 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
 1065 #else
 1066                 ccb->cts.flags = ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
 1067                 ccb->cts.valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
 1068 #endif
 1069                 ccb->ccb_h.status = CAM_REQ_CMP;
 1070                 xpt_done(ccb);
 1071                 return;
 1072         }
 1073         case XPT_SET_TRAN_SETTINGS:
 1074                 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
 1075                 xpt_done(ccb);
 1076                 return;
 1077         case XPT_RESET_BUS:
 1078                 if (!(sc->flags & AAC_FLAGS_CAM_NORESET) &&
 1079                         camsc->inf->BusType != CONTAINER_BUS) {
 1080                         ccb->ccb_h.status = aac_cam_reset_bus(sim, ccb);
 1081                 } else {
 1082                         ccb->ccb_h.status = CAM_REQ_CMP;
 1083                 }
 1084                 xpt_done(ccb);
 1085                 return;
 1086         case XPT_RESET_DEV:
 1087                 ccb->ccb_h.status = CAM_REQ_CMP;
 1088                 xpt_done(ccb);
 1089                 return;
 1090         case XPT_ABORT:
 1091                 ccb->ccb_h.status = aac_cam_abort_ccb(sim, ccb);
 1092                 xpt_done(ccb);
 1093                 return;
 1094         case XPT_TERM_IO:
 1095                 ccb->ccb_h.status = aac_cam_term_io(sim, ccb);
 1096                 xpt_done(ccb);
 1097                 return;
 1098         default:
 1099                 device_printf(sc->aac_dev, "Unsupported command 0x%x\n",
 1100                     ccb->ccb_h.func_code);
 1101                 ccb->ccb_h.status = CAM_PROVIDE_FAIL;
 1102                 xpt_done(ccb);
 1103                 return;
 1104         }
 1105 
 1106         /* Async ops that require communcation with the controller */
 1107         if (camsc->inf->BusType == CONTAINER_BUS) {
 1108                 u_int8_t *cmdp;
 1109 
 1110                 if (ccb->ccb_h.flags & CAM_CDB_POINTER)
 1111                         cmdp = ccb->csio.cdb_io.cdb_ptr;
 1112                 else    
 1113                         cmdp = &ccb->csio.cdb_io.cdb_bytes[0];
 1114 
 1115                 if (*cmdp==READ_6 || *cmdp==WRITE_6 || *cmdp==READ_10 ||
 1116                         *cmdp==WRITE_10 || *cmdp==READ_12 || *cmdp==WRITE_12 ||
 1117                         *cmdp==READ_16 || *cmdp==WRITE_16) 
 1118                         aac_container_rw_command(sim, ccb, cmdp);
 1119                 else
 1120                         aac_container_special_command(sim, ccb, cmdp);
 1121         } else {
 1122                 aac_passthrough_command(sim, ccb);
 1123         }
 1124 }
 1125 
 1126 static void
 1127 aac_cam_poll(struct cam_sim *sim)
 1128 {
 1129         /*
 1130          * Pinging the interrupt routine isn't very safe, nor is it
 1131          * really necessary.  Do nothing.
 1132          */
 1133 }
 1134 
 1135 static void
 1136 aac_container_complete(struct aac_command *cm)
 1137 {
 1138         struct  aac_softc *sc;
 1139         union   ccb *ccb;
 1140         u_int32_t status;
 1141 
 1142         sc = cm->cm_sc;
 1143         fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
 1144         ccb = cm->cm_ccb;
 1145         status = ((u_int32_t *)cm->cm_fib->data)[0];
 1146 
 1147         if (cm->cm_flags & AAC_CMD_RESET) {
 1148                 ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
 1149         } else if (status == ST_OK) {   
 1150                 ccb->ccb_h.status = CAM_REQ_CMP;
 1151         } else if (status == ST_NOT_READY) {
 1152                 ccb->ccb_h.status = CAM_BUSY;
 1153         } else {
 1154                 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
 1155         }
 1156 
 1157         aacraid_release_command(cm);
 1158         xpt_done(ccb);
 1159 }
 1160 
 1161 static void
 1162 aac_cam_complete(struct aac_command *cm)
 1163 {
 1164         union   ccb *ccb;
 1165         struct  aac_srb_response *srbr;
 1166         struct  aac_softc *sc;
 1167 
 1168         sc = cm->cm_sc;
 1169         fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
 1170         ccb = cm->cm_ccb;
 1171         srbr = (struct aac_srb_response *)&cm->cm_fib->data[0];
 1172 
 1173         if (cm->cm_flags & AAC_CMD_FASTRESP) {
 1174                 /* fast response */
 1175                 srbr->srb_status = CAM_REQ_CMP;
 1176                 srbr->scsi_status = SCSI_STATUS_OK;
 1177                 srbr->sense_len = 0;
 1178         }
 1179 
 1180         if (cm->cm_flags & AAC_CMD_RESET) {
 1181                 ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
 1182         } else if (srbr->fib_status != 0) {
 1183                 device_printf(sc->aac_dev, "Passthru FIB failed!\n");
 1184                 ccb->ccb_h.status = CAM_REQ_ABORTED;
 1185         } else {
 1186                 /*
 1187                  * The SRB error codes just happen to match the CAM error
 1188                  * codes.  How convienient!
 1189                  */
 1190                 ccb->ccb_h.status = srbr->srb_status;
 1191 
 1192                 /* Take care of SCSI_IO ops. */
 1193                 if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
 1194                         u_int8_t command, device;
 1195 
 1196                         ccb->csio.scsi_status = srbr->scsi_status;
 1197 
 1198                         /* Take care of autosense */
 1199                         if (srbr->sense_len) {
 1200                                 int sense_len, scsi_sense_len;
 1201 
 1202                                 scsi_sense_len = sizeof(struct scsi_sense_data);
 1203                                 bzero(&ccb->csio.sense_data, scsi_sense_len);
 1204                                 sense_len = (srbr->sense_len > 
 1205                                     scsi_sense_len) ? scsi_sense_len :
 1206                                     srbr->sense_len;
 1207                                 bcopy(&srbr->sense[0], &ccb->csio.sense_data,
 1208                                     srbr->sense_len);
 1209                                 ccb->csio.sense_len = sense_len;
 1210                                 ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
 1211                                 // scsi_sense_print(&ccb->csio);
 1212                         }
 1213 
 1214                         /* If this is an inquiry command, fake things out */
 1215                         if (ccb->ccb_h.flags & CAM_CDB_POINTER)
 1216                                 command = ccb->csio.cdb_io.cdb_ptr[0];
 1217                         else
 1218                                 command = ccb->csio.cdb_io.cdb_bytes[0];
 1219 
 1220                         if (command == INQUIRY) {
 1221                                 if (ccb->ccb_h.status == CAM_REQ_CMP) {
 1222                                   device = ccb->csio.data_ptr[0] & 0x1f;
 1223                                   /*
 1224                                    * We want DASD and PROC devices to only be
 1225                                    * visible through the pass device.
 1226                                    */
 1227                                   if ((device == T_DIRECT && 
 1228                                     !(sc->aac_feature_bits & AAC_SUPPL_SUPPORTED_JBOD)) ||
 1229                                     (device == T_PROCESSOR)) 
 1230                                     ccb->csio.data_ptr[0] =
 1231                                         ((device & 0xe0) | T_NODEVICE);
 1232                                         
 1233                                   /* handle phys. components of a log. drive */
 1234                                   if (ccb->csio.data_ptr[0] & 0x20) {
 1235                                         if (sc->hint_flags & 8) {
 1236                                           /* expose phys. device (daXX) */
 1237                                           ccb->csio.data_ptr[0] &= 0xdf;
 1238                                         } else {
 1239                                           /* phys. device only visible through pass device (passXX) */
 1240                                           ccb->csio.data_ptr[0] |= 0x10;
 1241                                         }
 1242                                   }
 1243                                 } else if (ccb->ccb_h.status == CAM_SEL_TIMEOUT &&
 1244                                   ccb->ccb_h.target_lun != 0) {
 1245                                   /* fix for INQUIRYs on Lun>0 */
 1246                                   ccb->ccb_h.status = CAM_DEV_NOT_THERE;
 1247                                 }
 1248                         }
 1249                 }
 1250         }
 1251 
 1252         aacraid_release_command(cm);
 1253         xpt_done(ccb);
 1254 }
 1255 
 1256 static u_int32_t
 1257 aac_cam_reset_bus(struct cam_sim *sim, union ccb *ccb)
 1258 {
 1259         struct aac_command *cm;
 1260         struct aac_fib *fib;
 1261         struct aac_softc *sc;
 1262         struct aac_cam *camsc;
 1263         struct aac_vmioctl *vmi;
 1264         struct aac_resetbus *rbc;
 1265         u_int32_t rval;
 1266 
 1267         camsc = (struct aac_cam *)cam_sim_softc(sim);
 1268         sc = camsc->inf->aac_sc;
 1269 
 1270         if (sc == NULL) {
 1271                 printf("aac: Null sc?\n");
 1272                 return (CAM_REQ_ABORTED);
 1273         }
 1274 
 1275         if (aacraid_alloc_command(sc, &cm)) {
 1276                 struct aac_event *event;
 1277 
 1278                 xpt_freeze_simq(sim, 1);
 1279                 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
 1280                 ccb->ccb_h.sim_priv.entries[0].ptr = camsc;
 1281                 event = malloc(sizeof(struct aac_event), M_AACRAIDCAM,
 1282                         M_NOWAIT | M_ZERO);
 1283                 if (event == NULL) {
 1284                         device_printf(sc->aac_dev,
 1285                                 "Warning, out of memory for event\n");
 1286                         return (CAM_REQ_ABORTED);
 1287                 }
 1288                 event->ev_callback = aac_cam_event;
 1289                 event->ev_arg = ccb;
 1290                 event->ev_type = AAC_EVENT_CMFREE;
 1291                 aacraid_add_event(sc, event);
 1292                 return (CAM_REQ_ABORTED);
 1293         }
 1294 
 1295         fib = cm->cm_fib;
 1296         cm->cm_timestamp = time_uptime;
 1297         cm->cm_datalen = 0;
 1298 
 1299         fib->Header.Size = 
 1300                 sizeof(struct aac_fib_header) + sizeof(struct aac_vmioctl);
 1301         fib->Header.XferState =
 1302                 AAC_FIBSTATE_HOSTOWNED   |
 1303                 AAC_FIBSTATE_INITIALISED |
 1304                 AAC_FIBSTATE_EMPTY       |
 1305                 AAC_FIBSTATE_FROMHOST    |
 1306                 AAC_FIBSTATE_REXPECTED   |
 1307                 AAC_FIBSTATE_NORM        |
 1308                 AAC_FIBSTATE_ASYNC       |
 1309                 AAC_FIBSTATE_FAST_RESPONSE;
 1310         fib->Header.Command = ContainerCommand;
 1311 
 1312         vmi = (struct aac_vmioctl *)&fib->data[0];
 1313         bzero(vmi, sizeof(struct aac_vmioctl));
 1314 
 1315         vmi->Command = VM_Ioctl;
 1316         vmi->ObjType = FT_DRIVE;
 1317         vmi->MethId = sc->scsi_method_id;
 1318         vmi->ObjId = 0;
 1319         vmi->IoctlCmd = ResetBus;
 1320 
 1321         rbc = (struct aac_resetbus *)&vmi->IoctlBuf[0];
 1322         rbc->BusNumber = camsc->inf->BusNumber - 1;
 1323 
 1324         if (aacraid_wait_command(cm) != 0) {
 1325                 device_printf(sc->aac_dev,"Error sending ResetBus command\n");
 1326                 rval = CAM_REQ_ABORTED;
 1327         } else {
 1328                 rval = CAM_REQ_CMP;
 1329         }
 1330         aacraid_release_command(cm);
 1331         return (rval);
 1332 }
 1333 
 1334 static u_int32_t
 1335 aac_cam_abort_ccb(struct cam_sim *sim, union ccb *ccb)
 1336 {
 1337         return (CAM_UA_ABORT);
 1338 }
 1339 
 1340 static u_int32_t
 1341 aac_cam_term_io(struct cam_sim *sim, union ccb *ccb)
 1342 {
 1343         return (CAM_UA_TERMIO);
 1344 }
 1345 
 1346 static int
 1347 aac_load_map_command_sg(struct aac_softc *sc, struct aac_command *cm)
 1348 {
 1349         int error;
 1350 
 1351         fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
 1352         error = bus_dmamap_load(sc->aac_buffer_dmat,
 1353                                 cm->cm_datamap, cm->cm_data, cm->cm_datalen,
 1354                                 aacraid_map_command_sg, cm, 0);
 1355         if (error == EINPROGRESS) {
 1356                 fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "freezing queue\n");
 1357                 sc->flags |= AAC_QUEUE_FRZN;
 1358                 error = 0;
 1359         } else if (error != 0) {
 1360                 panic("aac_load_map_command_sg: unexpected error %d from "
 1361                         "busdma", error);
 1362         }
 1363         return(error);
 1364 }
 1365 
 1366 /*
 1367  * Start as much queued I/O as possible on the controller
 1368  */
 1369 void
 1370 aacraid_startio(struct aac_softc *sc)
 1371 {
 1372         struct aac_command *cm;
 1373 
 1374         fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
 1375 
 1376         for (;;) {
 1377                 if (sc->aac_state & AAC_STATE_RESET) {
 1378                         fwprintf(sc, HBA_FLAGS_DBG_ERROR_B, "AAC_STATE_RESET");
 1379                         break;
 1380                 }
 1381                 /*
 1382                  * This flag might be set if the card is out of resources.
 1383                  * Checking it here prevents an infinite loop of deferrals.
 1384                  */
 1385                 if (sc->flags & AAC_QUEUE_FRZN) {
 1386                         fwprintf(sc, HBA_FLAGS_DBG_ERROR_B, "AAC_QUEUE_FRZN");
 1387                         break;
 1388                 }
 1389 
 1390                 /*
 1391                  * Try to get a command that's been put off for lack of
 1392                  * resources
 1393                  */
 1394                 if (sc->flags & AAC_FLAGS_SYNC_MODE) {
 1395                         /* sync. transfer mode */
 1396                         if (sc->aac_sync_cm) 
 1397                                 break;
 1398                         cm = aac_dequeue_ready(sc);
 1399                         sc->aac_sync_cm = cm;
 1400                 } else {
 1401                         cm = aac_dequeue_ready(sc);
 1402                 }
 1403 
 1404                 /* nothing to do? */
 1405                 if (cm == NULL)
 1406                         break;
 1407 
 1408                 /* don't map more than once */
 1409                 if (cm->cm_flags & AAC_CMD_MAPPED)
 1410                         panic("aac: command %p already mapped", cm);
 1411 
 1412                 /*
 1413                  * Set up the command to go to the controller.  If there are no
 1414                  * data buffers associated with the command then it can bypass
 1415                  * busdma.
 1416                  */
 1417                 if (cm->cm_datalen)
 1418                         aac_load_map_command_sg(sc, cm);
 1419                 else
 1420                         aacraid_map_command_sg(cm, NULL, 0, 0);
 1421         }
 1422 }

Cache object: 3e48e7def25dea06a425af5b72044e2c


[ 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.