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/cam/scsi/scsi_enc_safte.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) 2000 Matthew Jacob
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions, and the following disclaimer,
   10  *    without modification, immediately at the beginning of the file.
   11  * 2. The name of the author may not be used to endorse or promote products
   12  *    derived from this software without specific prior written permission.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   18  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: releng/10.0/sys/cam/scsi/scsi_enc_safte.c 239213 2012-08-12 17:01:07Z mjacob $");
   29 
   30 #include <sys/param.h>
   31 
   32 #include <sys/conf.h>
   33 #include <sys/errno.h>
   34 #include <sys/kernel.h>
   35 #include <sys/malloc.h>
   36 #include <sys/mutex.h>
   37 #include <sys/queue.h>
   38 #include <sys/sx.h>
   39 #include <sys/systm.h>
   40 #include <sys/sysctl.h>
   41 #include <sys/types.h>
   42 
   43 #include <cam/cam.h>
   44 #include <cam/cam_ccb.h>
   45 #include <cam/cam_periph.h>
   46 
   47 #include <cam/scsi/scsi_enc.h>
   48 #include <cam/scsi/scsi_enc_internal.h>
   49 #include <cam/scsi/scsi_message.h>
   50 
   51 /*
   52  * SAF-TE Type Device Emulation
   53  */
   54 
   55 static int safte_set_enc_status(enc_softc_t *enc, uint8_t encstat, int slpflag);
   56 
   57 #define ALL_ENC_STAT (SES_ENCSTAT_CRITICAL | SES_ENCSTAT_UNRECOV | \
   58         SES_ENCSTAT_NONCRITICAL | SES_ENCSTAT_INFO)
   59 /*
   60  * SAF-TE specific defines- Mandatory ones only...
   61  */
   62 
   63 /*
   64  * READ BUFFER ('get' commands) IDs- placed in offset 2 of cdb
   65  */
   66 #define SAFTE_RD_RDCFG  0x00    /* read enclosure configuration */
   67 #define SAFTE_RD_RDESTS 0x01    /* read enclosure status */
   68 #define SAFTE_RD_RDDSTS 0x04    /* read drive slot status */
   69 #define SAFTE_RD_RDGFLG 0x05    /* read global flags */
   70 
   71 /*
   72  * WRITE BUFFER ('set' commands) IDs- placed in offset 0 of databuf
   73  */
   74 #define SAFTE_WT_DSTAT  0x10    /* write device slot status */
   75 #define SAFTE_WT_SLTOP  0x12    /* perform slot operation */
   76 #define SAFTE_WT_FANSPD 0x13    /* set fan speed */
   77 #define SAFTE_WT_ACTPWS 0x14    /* turn on/off power supply */
   78 #define SAFTE_WT_GLOBAL 0x15    /* send global command */
   79 
   80 #define SAFT_SCRATCH    64
   81 #define SCSZ            0x8000
   82 
   83 typedef enum {
   84         SAFTE_UPDATE_NONE,
   85         SAFTE_UPDATE_READCONFIG,
   86         SAFTE_UPDATE_READGFLAGS,
   87         SAFTE_UPDATE_READENCSTATUS,
   88         SAFTE_UPDATE_READSLOTSTATUS,
   89         SAFTE_PROCESS_CONTROL_REQS,
   90         SAFTE_NUM_UPDATE_STATES
   91 } safte_update_action;
   92 
   93 static fsm_fill_handler_t safte_fill_read_buf_io;
   94 static fsm_fill_handler_t safte_fill_control_request;
   95 static fsm_done_handler_t safte_process_config;
   96 static fsm_done_handler_t safte_process_gflags;
   97 static fsm_done_handler_t safte_process_status;
   98 static fsm_done_handler_t safte_process_slotstatus;
   99 static fsm_done_handler_t safte_process_control_request;
  100 
  101 static struct enc_fsm_state enc_fsm_states[SAFTE_NUM_UPDATE_STATES] =
  102 {
  103         { "SAFTE_UPDATE_NONE", 0, 0, 0, NULL, NULL, NULL },
  104         {
  105                 "SAFTE_UPDATE_READCONFIG",
  106                 SAFTE_RD_RDCFG,
  107                 SAFT_SCRATCH,
  108                 60 * 1000,
  109                 safte_fill_read_buf_io,
  110                 safte_process_config,
  111                 enc_error
  112         },
  113         {
  114                 "SAFTE_UPDATE_READGFLAGS",
  115                 SAFTE_RD_RDGFLG,
  116                 16,
  117                 60 * 1000,
  118                 safte_fill_read_buf_io,
  119                 safte_process_gflags,
  120                 enc_error
  121         },
  122         {
  123                 "SAFTE_UPDATE_READENCSTATUS",
  124                 SAFTE_RD_RDESTS,
  125                 SCSZ,
  126                 60 * 1000,
  127                 safte_fill_read_buf_io,
  128                 safte_process_status,
  129                 enc_error
  130         },
  131         {
  132                 "SAFTE_UPDATE_READSLOTSTATUS",
  133                 SAFTE_RD_RDDSTS,
  134                 SCSZ,
  135                 60 * 1000,
  136                 safte_fill_read_buf_io,
  137                 safte_process_slotstatus,
  138                 enc_error
  139         },
  140         {
  141                 "SAFTE_PROCESS_CONTROL_REQS",
  142                 0,
  143                 SCSZ,
  144                 60 * 1000,
  145                 safte_fill_control_request,
  146                 safte_process_control_request,
  147                 enc_error
  148         }
  149 };
  150 
  151 typedef struct safte_control_request {
  152         int     elm_idx;
  153         uint8_t elm_stat[4];
  154         int     result;
  155         TAILQ_ENTRY(safte_control_request) links;
  156 } safte_control_request_t;
  157 TAILQ_HEAD(safte_control_reqlist, safte_control_request);
  158 typedef struct safte_control_reqlist safte_control_reqlist_t;
  159 enum {
  160         SES_SETSTATUS_ENC_IDX = -1
  161 };
  162 
  163 static void
  164 safte_terminate_control_requests(safte_control_reqlist_t *reqlist, int result)
  165 {
  166         safte_control_request_t *req;
  167 
  168         while ((req = TAILQ_FIRST(reqlist)) != NULL) {
  169                 TAILQ_REMOVE(reqlist, req, links);
  170                 req->result = result;
  171                 wakeup(req);
  172         }
  173 }
  174 
  175 struct scfg {
  176         /*
  177          * Cached Configuration
  178          */
  179         uint8_t Nfans;          /* Number of Fans */
  180         uint8_t Npwr;           /* Number of Power Supplies */
  181         uint8_t Nslots;         /* Number of Device Slots */
  182         uint8_t DoorLock;       /* Door Lock Installed */
  183         uint8_t Ntherm;         /* Number of Temperature Sensors */
  184         uint8_t Nspkrs;         /* Number of Speakers */
  185         uint8_t Ntstats;        /* Number of Thermostats */
  186         /*
  187          * Cached Flag Bytes for Global Status
  188          */
  189         uint8_t flag1;
  190         uint8_t flag2;
  191         /*
  192          * What object index ID is where various slots start.
  193          */
  194         uint8_t pwroff;
  195         uint8_t slotoff;
  196 #define SAFT_ALARM_OFFSET(cc)   (cc)->slotoff - 1
  197 
  198         encioc_enc_status_t     adm_status;
  199         encioc_enc_status_t     enc_status;
  200         encioc_enc_status_t     slot_status;
  201 
  202         safte_control_reqlist_t requests;
  203         safte_control_request_t *current_request;
  204         int                     current_request_stage;
  205         int                     current_request_stages;
  206 };
  207 
  208 #define SAFT_FLG1_ALARM         0x1
  209 #define SAFT_FLG1_GLOBFAIL      0x2
  210 #define SAFT_FLG1_GLOBWARN      0x4
  211 #define SAFT_FLG1_ENCPWROFF     0x8
  212 #define SAFT_FLG1_ENCFANFAIL    0x10
  213 #define SAFT_FLG1_ENCPWRFAIL    0x20
  214 #define SAFT_FLG1_ENCDRVFAIL    0x40
  215 #define SAFT_FLG1_ENCDRVWARN    0x80
  216 
  217 #define SAFT_FLG2_LOCKDOOR      0x4
  218 #define SAFT_PRIVATE            sizeof (struct scfg)
  219 
  220 static char *safte_2little = "Too Little Data Returned (%d) at line %d\n";
  221 #define SAFT_BAIL(r, x) \
  222         if ((r) >= (x)) { \
  223                 ENC_VLOG(enc, safte_2little, x, __LINE__);\
  224                 return (EIO); \
  225         }
  226 
  227 int emulate_array_devices = 1;
  228 SYSCTL_DECL(_kern_cam_enc);
  229 SYSCTL_INT(_kern_cam_enc, OID_AUTO, emulate_array_devices, CTLFLAG_RW,
  230            &emulate_array_devices, 0, "Emulate Array Devices for SAF-TE");
  231 TUNABLE_INT("kern.cam.enc.emulate_array_devices", &emulate_array_devices);
  232 
  233 static int
  234 safte_fill_read_buf_io(enc_softc_t *enc, struct enc_fsm_state *state,
  235                        union ccb *ccb, uint8_t *buf)
  236 {
  237 
  238         if (state->page_code != SAFTE_RD_RDCFG &&
  239             enc->enc_cache.nelms == 0) {
  240                 enc_update_request(enc, SAFTE_UPDATE_READCONFIG);
  241                 return (-1);
  242         }
  243 
  244         if (enc->enc_type == ENC_SEMB_SAFT) {
  245                 semb_read_buffer(&ccb->ataio, /*retries*/5,
  246                                 enc_done, MSG_SIMPLE_Q_TAG,
  247                                 state->page_code, buf, state->buf_size,
  248                                 state->timeout);
  249         } else {
  250                 scsi_read_buffer(&ccb->csio, /*retries*/5,
  251                                 enc_done, MSG_SIMPLE_Q_TAG, 1,
  252                                 state->page_code, 0, buf, state->buf_size,
  253                                 SSD_FULL_SIZE, state->timeout);
  254         }
  255         return (0);
  256 }
  257 
  258 static int
  259 safte_process_config(enc_softc_t *enc, struct enc_fsm_state *state,
  260     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
  261 {
  262         struct scfg *cfg;
  263         uint8_t *buf = *bufp;
  264         int i, r;
  265 
  266         cfg = enc->enc_private;
  267         if (cfg == NULL)
  268                 return (ENXIO);
  269         if (error != 0)
  270                 return (error);
  271         if (xfer_len < 6) {
  272                 ENC_VLOG(enc, "too little data (%d) for configuration\n",
  273                     xfer_len);
  274                 return (EIO);
  275         }
  276         cfg->Nfans = buf[0];
  277         cfg->Npwr = buf[1];
  278         cfg->Nslots = buf[2];
  279         cfg->DoorLock = buf[3];
  280         cfg->Ntherm = buf[4];
  281         cfg->Nspkrs = buf[5];
  282         if (xfer_len >= 7)
  283                 cfg->Ntstats = buf[6] & 0x0f;
  284         else
  285                 cfg->Ntstats = 0;
  286         ENC_VLOG(enc, "Nfans %d Npwr %d Nslots %d Lck %d Ntherm %d Nspkrs %d "
  287             "Ntstats %d\n",
  288             cfg->Nfans, cfg->Npwr, cfg->Nslots, cfg->DoorLock, cfg->Ntherm,
  289             cfg->Nspkrs, cfg->Ntstats);
  290 
  291         enc->enc_cache.nelms = cfg->Nfans + cfg->Npwr + cfg->Nslots +
  292             cfg->DoorLock + cfg->Ntherm + cfg->Nspkrs + cfg->Ntstats + 1;
  293         ENC_FREE_AND_NULL(enc->enc_cache.elm_map);
  294         enc->enc_cache.elm_map =
  295             ENC_MALLOCZ(enc->enc_cache.nelms * sizeof(enc_element_t));
  296         if (enc->enc_cache.elm_map == NULL) {
  297                 enc->enc_cache.nelms = 0;
  298                 return (ENOMEM);
  299         }
  300 
  301         r = 0;
  302         /*
  303          * Note that this is all arranged for the convenience
  304          * in later fetches of status.
  305          */
  306         for (i = 0; i < cfg->Nfans; i++)
  307                 enc->enc_cache.elm_map[r++].enctype = ELMTYP_FAN;
  308         cfg->pwroff = (uint8_t) r;
  309         for (i = 0; i < cfg->Npwr; i++)
  310                 enc->enc_cache.elm_map[r++].enctype = ELMTYP_POWER;
  311         for (i = 0; i < cfg->DoorLock; i++)
  312                 enc->enc_cache.elm_map[r++].enctype = ELMTYP_DOORLOCK;
  313         if (cfg->Nspkrs > 0)
  314                 enc->enc_cache.elm_map[r++].enctype = ELMTYP_ALARM;
  315         for (i = 0; i < cfg->Ntherm; i++)
  316                 enc->enc_cache.elm_map[r++].enctype = ELMTYP_THERM;
  317         for (i = 0; i <= cfg->Ntstats; i++)
  318                 enc->enc_cache.elm_map[r++].enctype = ELMTYP_THERM;
  319         cfg->slotoff = (uint8_t) r;
  320         for (i = 0; i < cfg->Nslots; i++)
  321                 enc->enc_cache.elm_map[r++].enctype =
  322                     emulate_array_devices ? ELMTYP_ARRAY_DEV :
  323                      ELMTYP_DEVICE;
  324 
  325         enc_update_request(enc, SAFTE_UPDATE_READGFLAGS);
  326         enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
  327         enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
  328 
  329         return (0);
  330 }
  331 
  332 static int
  333 safte_process_gflags(enc_softc_t *enc, struct enc_fsm_state *state,
  334     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
  335 {
  336         struct scfg *cfg;
  337         uint8_t *buf = *bufp;
  338 
  339         cfg = enc->enc_private;
  340         if (cfg == NULL)
  341                 return (ENXIO);
  342         if (error != 0)
  343                 return (error);
  344         SAFT_BAIL(3, xfer_len);
  345         cfg->flag1 = buf[1];
  346         cfg->flag2 = buf[2];
  347 
  348         cfg->adm_status = 0;
  349         if (cfg->flag1 & SAFT_FLG1_GLOBFAIL)
  350                 cfg->adm_status |= SES_ENCSTAT_CRITICAL;
  351         else if (cfg->flag1 & SAFT_FLG1_GLOBWARN)
  352                 cfg->adm_status |= SES_ENCSTAT_NONCRITICAL;
  353 
  354         return (0);
  355 }
  356 
  357 static int
  358 safte_process_status(enc_softc_t *enc, struct enc_fsm_state *state,
  359     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
  360 {
  361         struct scfg *cfg;
  362         uint8_t *buf = *bufp;
  363         int oid, r, i, nitems;
  364         uint16_t tempflags;
  365         enc_cache_t *cache = &enc->enc_cache;
  366 
  367         cfg = enc->enc_private;
  368         if (cfg == NULL)
  369                 return (ENXIO);
  370         if (error != 0)
  371                 return (error);
  372 
  373         oid = r = 0;
  374         cfg->enc_status = 0;
  375 
  376         for (nitems = i = 0; i < cfg->Nfans; i++) {
  377                 SAFT_BAIL(r, xfer_len);
  378                 /*
  379                  * 0 = Fan Operational
  380                  * 1 = Fan is malfunctioning
  381                  * 2 = Fan is not present
  382                  * 0x80 = Unknown or Not Reportable Status
  383                  */
  384                 cache->elm_map[oid].encstat[1] = 0;     /* resvd */
  385                 cache->elm_map[oid].encstat[2] = 0;     /* resvd */
  386                 if (cfg->flag1 & SAFT_FLG1_ENCFANFAIL)
  387                         cache->elm_map[oid].encstat[3] |= 0x40;
  388                 else
  389                         cache->elm_map[oid].encstat[3] &= ~0x40;
  390                 switch ((int)buf[r]) {
  391                 case 0:
  392                         nitems++;
  393                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
  394                         if ((cache->elm_map[oid].encstat[3] & 0x37) == 0)
  395                                 cache->elm_map[oid].encstat[3] |= 0x27;
  396                         break;
  397 
  398                 case 1:
  399                         cache->elm_map[oid].encstat[0] =
  400                             SES_OBJSTAT_CRIT;
  401                         /*
  402                          * FAIL and FAN STOPPED synthesized
  403                          */
  404                         cache->elm_map[oid].encstat[3] |= 0x10;
  405                         cache->elm_map[oid].encstat[3] &= ~0x07;
  406                         /*
  407                          * Enclosure marked with CRITICAL error
  408                          * if only one fan or no thermometers,
  409                          * else the NONCRITICAL error is set.
  410                          */
  411                         if (cfg->Nfans == 1 || (cfg->Ntherm + cfg->Ntstats) == 0)
  412                                 cfg->enc_status |= SES_ENCSTAT_CRITICAL;
  413                         else
  414                                 cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
  415                         break;
  416                 case 2:
  417                         cache->elm_map[oid].encstat[0] =
  418                             SES_OBJSTAT_NOTINSTALLED;
  419                         cache->elm_map[oid].encstat[3] |= 0x10;
  420                         cache->elm_map[oid].encstat[3] &= ~0x07;
  421                         /*
  422                          * Enclosure marked with CRITICAL error
  423                          * if only one fan or no thermometers,
  424                          * else the NONCRITICAL error is set.
  425                          */
  426                         if (cfg->Nfans == 1)
  427                                 cfg->enc_status |= SES_ENCSTAT_CRITICAL;
  428                         else
  429                                 cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
  430                         break;
  431                 case 0x80:
  432                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
  433                         cache->elm_map[oid].encstat[3] = 0;
  434                         cfg->enc_status |= SES_ENCSTAT_INFO;
  435                         break;
  436                 default:
  437                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNSUPPORTED;
  438                         ENC_VLOG(enc, "Unknown fan%d status 0x%x\n", i,
  439                             buf[r] & 0xff);
  440                         break;
  441                 }
  442                 cache->elm_map[oid++].svalid = 1;
  443                 r++;
  444         }
  445 
  446         /*
  447          * No matter how you cut it, no cooling elements when there
  448          * should be some there is critical.
  449          */
  450         if (cfg->Nfans && nitems == 0)
  451                 cfg->enc_status |= SES_ENCSTAT_CRITICAL;
  452 
  453         for (i = 0; i < cfg->Npwr; i++) {
  454                 SAFT_BAIL(r, xfer_len);
  455                 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
  456                 cache->elm_map[oid].encstat[1] = 0;     /* resvd */
  457                 cache->elm_map[oid].encstat[2] = 0;     /* resvd */
  458                 cache->elm_map[oid].encstat[3] = 0x20;  /* requested on */
  459                 switch (buf[r]) {
  460                 case 0x00:      /* pws operational and on */
  461                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
  462                         break;
  463                 case 0x01:      /* pws operational and off */
  464                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
  465                         cache->elm_map[oid].encstat[3] = 0x10;
  466                         cfg->enc_status |= SES_ENCSTAT_INFO;
  467                         break;
  468                 case 0x10:      /* pws is malfunctioning and commanded on */
  469                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
  470                         cache->elm_map[oid].encstat[3] = 0x61;
  471                         cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
  472                         break;
  473 
  474                 case 0x11:      /* pws is malfunctioning and commanded off */
  475                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NONCRIT;
  476                         cache->elm_map[oid].encstat[3] = 0x51;
  477                         cfg->enc_status |= SES_ENCSTAT_NONCRITICAL;
  478                         break;
  479                 case 0x20:      /* pws is not present */
  480                         cache->elm_map[oid].encstat[0] =
  481                             SES_OBJSTAT_NOTINSTALLED;
  482                         cache->elm_map[oid].encstat[3] = 0;
  483                         cfg->enc_status |= SES_ENCSTAT_INFO;
  484                         break;
  485                 case 0x21:      /* pws is present */
  486                         /*
  487                          * This is for enclosures that cannot tell whether the
  488                          * device is on or malfunctioning, but know that it is
  489                          * present. Just fall through.
  490                          */
  491                         /* FALLTHROUGH */
  492                 case 0x80:      /* Unknown or Not Reportable Status */
  493                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
  494                         cache->elm_map[oid].encstat[3] = 0;
  495                         cfg->enc_status |= SES_ENCSTAT_INFO;
  496                         break;
  497                 default:
  498                         ENC_VLOG(enc, "unknown power supply %d status (0x%x)\n",
  499                             i, buf[r] & 0xff);
  500                         break;
  501                 }
  502                 enc->enc_cache.elm_map[oid++].svalid = 1;
  503                 r++;
  504         }
  505 
  506         /*
  507          * Copy Slot SCSI IDs
  508          */
  509         for (i = 0; i < cfg->Nslots; i++) {
  510                 SAFT_BAIL(r, xfer_len);
  511                 if (cache->elm_map[cfg->slotoff + i].enctype == ELMTYP_DEVICE)
  512                         cache->elm_map[cfg->slotoff + i].encstat[1] = buf[r];
  513                 r++;
  514         }
  515 
  516         /*
  517          * We always have doorlock status, no matter what,
  518          * but we only save the status if we have one.
  519          */
  520         SAFT_BAIL(r, xfer_len);
  521         if (cfg->DoorLock) {
  522                 /*
  523                  * 0 = Door Locked
  524                  * 1 = Door Unlocked, or no Lock Installed
  525                  * 0x80 = Unknown or Not Reportable Status
  526                  */
  527                 cache->elm_map[oid].encstat[1] = 0;
  528                 cache->elm_map[oid].encstat[2] = 0;
  529                 switch (buf[r]) {
  530                 case 0:
  531                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
  532                         cache->elm_map[oid].encstat[3] = 0;
  533                         break;
  534                 case 1:
  535                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
  536                         cache->elm_map[oid].encstat[3] = 1;
  537                         break;
  538                 case 0x80:
  539                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNKNOWN;
  540                         cache->elm_map[oid].encstat[3] = 0;
  541                         cfg->enc_status |= SES_ENCSTAT_INFO;
  542                         break;
  543                 default:
  544                         cache->elm_map[oid].encstat[0] =
  545                             SES_OBJSTAT_UNSUPPORTED;
  546                         ENC_VLOG(enc, "unknown lock status 0x%x\n",
  547                             buf[r] & 0xff);
  548                         break;
  549                 }
  550                 cache->elm_map[oid++].svalid = 1;
  551         }
  552         r++;
  553 
  554         /*
  555          * We always have speaker status, no matter what,
  556          * but we only save the status if we have one.
  557          */
  558         SAFT_BAIL(r, xfer_len);
  559         if (cfg->Nspkrs) {
  560                 cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
  561                 cache->elm_map[oid].encstat[1] = 0;
  562                 cache->elm_map[oid].encstat[2] = 0;
  563                 if (buf[r] == 0) {
  564                         cache->elm_map[oid].encstat[0] |= SESCTL_DISABLE;
  565                         cache->elm_map[oid].encstat[3] |= 0x40;
  566                 }
  567                 cache->elm_map[oid++].svalid = 1;
  568         }
  569         r++;
  570 
  571         /*
  572          * Now, for "pseudo" thermometers, we have two bytes
  573          * of information in enclosure status- 16 bits. Actually,
  574          * the MSB is a single TEMP ALERT flag indicating whether
  575          * any other bits are set, but, thanks to fuzzy thinking,
  576          * in the SAF-TE spec, this can also be set even if no
  577          * other bits are set, thus making this really another
  578          * binary temperature sensor.
  579          */
  580 
  581         SAFT_BAIL(r + cfg->Ntherm, xfer_len);
  582         tempflags = buf[r + cfg->Ntherm];
  583         SAFT_BAIL(r + cfg->Ntherm + 1, xfer_len);
  584         tempflags |= (tempflags << 8) | buf[r + cfg->Ntherm + 1];
  585 
  586         for (i = 0; i < cfg->Ntherm; i++) {
  587                 SAFT_BAIL(r, xfer_len);
  588                 /*
  589                  * Status is a range from -10 to 245 deg Celsius,
  590                  * which we need to normalize to -20 to -245 according
  591                  * to the latest SCSI spec, which makes little
  592                  * sense since this would overflow an 8bit value.
  593                  * Well, still, the base normalization is -20,
  594                  * not -10, so we have to adjust.
  595                  *
  596                  * So what's over and under temperature?
  597                  * Hmm- we'll state that 'normal' operating
  598                  * is 10 to 40 deg Celsius.
  599                  */
  600 
  601                 /*
  602                  * Actually.... All of the units that people out in the world
  603                  * seem to have do not come even close to setting a value that
  604                  * complies with this spec.
  605                  *
  606                  * The closest explanation I could find was in an
  607                  * LSI-Logic manual, which seemed to indicate that
  608                  * this value would be set by whatever the I2C code
  609                  * would interpolate from the output of an LM75
  610                  * temperature sensor.
  611                  *
  612                  * This means that it is impossible to use the actual
  613                  * numeric value to predict anything. But we don't want
  614                  * to lose the value. So, we'll propagate the *uncorrected*
  615                  * value and set SES_OBJSTAT_NOTAVAIL. We'll depend on the
  616                  * temperature flags for warnings.
  617                  */
  618                 if (tempflags & (1 << i)) {
  619                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
  620                         cfg->enc_status |= SES_ENCSTAT_CRITICAL;
  621                 } else
  622                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
  623                 cache->elm_map[oid].encstat[1] = 0;
  624                 cache->elm_map[oid].encstat[2] = buf[r];
  625                 cache->elm_map[oid].encstat[3] = 0;
  626                 cache->elm_map[oid++].svalid = 1;
  627                 r++;
  628         }
  629 
  630         for (i = 0; i <= cfg->Ntstats; i++) {
  631                 cache->elm_map[oid].encstat[1] = 0;
  632                 if (tempflags & (1 <<
  633                     ((i == cfg->Ntstats) ? 15 : (cfg->Ntherm + i)))) {
  634                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
  635                         cache->elm_map[4].encstat[2] = 0xff;
  636                         /*
  637                          * Set 'over temperature' failure.
  638                          */
  639                         cache->elm_map[oid].encstat[3] = 8;
  640                         cfg->enc_status |= SES_ENCSTAT_CRITICAL;
  641                 } else {
  642                         /*
  643                          * We used to say 'not available' and synthesize a
  644                          * nominal 30 deg (C)- that was wrong. Actually,
  645                          * Just say 'OK', and use the reserved value of
  646                          * zero.
  647                          */
  648                         if ((cfg->Ntherm + cfg->Ntstats) == 0)
  649                                 cache->elm_map[oid].encstat[0] =
  650                                     SES_OBJSTAT_NOTAVAIL;
  651                         else
  652                                 cache->elm_map[oid].encstat[0] =
  653                                     SES_OBJSTAT_OK;
  654                         cache->elm_map[oid].encstat[2] = 0;
  655                         cache->elm_map[oid].encstat[3] = 0;
  656                 }
  657                 cache->elm_map[oid++].svalid = 1;
  658         }
  659         r += 2;
  660 
  661         cache->enc_status =
  662             cfg->enc_status | cfg->slot_status | cfg->adm_status;
  663         return (0);
  664 }
  665 
  666 static int
  667 safte_process_slotstatus(enc_softc_t *enc, struct enc_fsm_state *state,
  668     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
  669 {
  670         struct scfg *cfg;
  671         uint8_t *buf = *bufp;
  672         enc_cache_t *cache = &enc->enc_cache;
  673         int oid, r, i;
  674 
  675         cfg = enc->enc_private;
  676         if (cfg == NULL)
  677                 return (ENXIO);
  678         if (error != 0)
  679                 return (error);
  680         cfg->slot_status = 0;
  681         oid = cfg->slotoff;
  682         for (r = i = 0; i < cfg->Nslots; i++, r += 4) {
  683                 SAFT_BAIL(r+3, xfer_len);
  684                 if (cache->elm_map[oid].enctype == ELMTYP_ARRAY_DEV)
  685                         cache->elm_map[oid].encstat[1] = 0;
  686                 cache->elm_map[oid].encstat[2] &= SESCTL_RQSID;
  687                 cache->elm_map[oid].encstat[3] = 0;
  688                 if ((buf[r+3] & 0x01) == 0) {   /* no device */
  689                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NOTINSTALLED;
  690                 } else if (buf[r+0] & 0x02) {
  691                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_CRIT;
  692                         cfg->slot_status |= SES_ENCSTAT_CRITICAL;
  693                 } else if (buf[r+0] & 0x40) {
  694                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_NONCRIT;
  695                         cfg->slot_status |= SES_ENCSTAT_NONCRITICAL;
  696                 } else {
  697                         cache->elm_map[oid].encstat[0] = SES_OBJSTAT_OK;
  698                 }
  699                 if (buf[r+3] & 0x2) {
  700                         if (buf[r+3] & 0x01)
  701                                 cache->elm_map[oid].encstat[2] |= SESCTL_RQSRMV;
  702                         else
  703                                 cache->elm_map[oid].encstat[2] |= SESCTL_RQSINS;
  704                 }
  705                 if ((buf[r+3] & 0x04) == 0)
  706                         cache->elm_map[oid].encstat[3] |= SESCTL_DEVOFF;
  707                 if (buf[r+0] & 0x02)
  708                         cache->elm_map[oid].encstat[3] |= SESCTL_RQSFLT;
  709                 if (buf[r+0] & 0x40)
  710                         cache->elm_map[oid].encstat[0] |= SESCTL_PRDFAIL;
  711                 if (cache->elm_map[oid].enctype == ELMTYP_ARRAY_DEV) {
  712                         if (buf[r+0] & 0x01)
  713                                 cache->elm_map[oid].encstat[1] |= 0x80;
  714                         if (buf[r+0] & 0x04)
  715                                 cache->elm_map[oid].encstat[1] |= 0x02;
  716                         if (buf[r+0] & 0x08)
  717                                 cache->elm_map[oid].encstat[1] |= 0x04;
  718                         if (buf[r+0] & 0x10)
  719                                 cache->elm_map[oid].encstat[1] |= 0x08;
  720                         if (buf[r+0] & 0x20)
  721                                 cache->elm_map[oid].encstat[1] |= 0x10;
  722                         if (buf[r+1] & 0x01)
  723                                 cache->elm_map[oid].encstat[1] |= 0x20;
  724                         if (buf[r+1] & 0x02)
  725                                 cache->elm_map[oid].encstat[1] |= 0x01;
  726                 }
  727                 cache->elm_map[oid++].svalid = 1;
  728         }
  729 
  730         cache->enc_status =
  731             cfg->enc_status | cfg->slot_status | cfg->adm_status;
  732         return (0);
  733 }
  734 
  735 static int
  736 safte_fill_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
  737                        union ccb *ccb, uint8_t *buf)
  738 {
  739         struct scfg *cfg;
  740         enc_element_t *ep, *ep1;
  741         safte_control_request_t *req;
  742         int i, idx, xfer_len;
  743 
  744         cfg = enc->enc_private;
  745         if (cfg == NULL)
  746                 return (ENXIO);
  747 
  748         if (enc->enc_cache.nelms == 0) {
  749                 enc_update_request(enc, SAFTE_UPDATE_READCONFIG);
  750                 return (-1);
  751         }
  752 
  753         if (cfg->current_request == NULL) {
  754                 cfg->current_request = TAILQ_FIRST(&cfg->requests);
  755                 TAILQ_REMOVE(&cfg->requests, cfg->current_request, links);
  756                 cfg->current_request_stage = 0;
  757                 cfg->current_request_stages = 1;
  758         }
  759         req = cfg->current_request;
  760 
  761         idx = (int)req->elm_idx;
  762         if (req->elm_idx == SES_SETSTATUS_ENC_IDX) {
  763                 cfg->adm_status = req->elm_stat[0] & ALL_ENC_STAT;
  764                 cfg->flag1 &= ~(SAFT_FLG1_GLOBFAIL|SAFT_FLG1_GLOBWARN);
  765                 if (req->elm_stat[0] & (SES_ENCSTAT_CRITICAL|SES_ENCSTAT_UNRECOV))
  766                         cfg->flag1 |= SAFT_FLG1_GLOBFAIL;
  767                 else if (req->elm_stat[0] & SES_ENCSTAT_NONCRITICAL)
  768                         cfg->flag1 |= SAFT_FLG1_GLOBWARN;
  769                 buf[0] = SAFTE_WT_GLOBAL;
  770                 buf[1] = cfg->flag1;
  771                 buf[2] = cfg->flag2;
  772                 buf[3] = 0;
  773                 xfer_len = 16;
  774         } else {
  775                 ep = &enc->enc_cache.elm_map[idx];
  776 
  777                 switch (ep->enctype) {
  778                 case ELMTYP_DEVICE:
  779                 case ELMTYP_ARRAY_DEV:
  780                         switch (cfg->current_request_stage) {
  781                         case 0:
  782                                 ep->priv = 0;
  783                                 if (req->elm_stat[0] & SESCTL_PRDFAIL)
  784                                         ep->priv |= 0x40;
  785                                 if (req->elm_stat[3] & SESCTL_RQSFLT)
  786                                         ep->priv |= 0x02;
  787                                 if (ep->enctype == ELMTYP_ARRAY_DEV) {
  788                                         if (req->elm_stat[1] & 0x01)
  789                                                 ep->priv |= 0x200;
  790                                         if (req->elm_stat[1] & 0x02)
  791                                                 ep->priv |= 0x04;
  792                                         if (req->elm_stat[1] & 0x04)
  793                                                 ep->priv |= 0x08;
  794                                         if (req->elm_stat[1] & 0x08)
  795                                                 ep->priv |= 0x10;
  796                                         if (req->elm_stat[1] & 0x10)
  797                                                 ep->priv |= 0x20;
  798                                         if (req->elm_stat[1] & 0x20)
  799                                                 ep->priv |= 0x100;
  800                                         if (req->elm_stat[1] & 0x80)
  801                                                 ep->priv |= 0x01;
  802                                 }
  803                                 if (ep->priv == 0)
  804                                         ep->priv |= 0x01;       /* no errors */
  805 
  806                                 buf[0] = SAFTE_WT_DSTAT;
  807                                 for (i = 0; i < cfg->Nslots; i++) {
  808                                         ep1 = &enc->enc_cache.elm_map[cfg->slotoff + i];
  809                                         buf[1 + (3 * i)] = ep1->priv;
  810                                         buf[2 + (3 * i)] = ep1->priv >> 8;
  811                                 }
  812                                 xfer_len = cfg->Nslots * 3 + 1;
  813 #define DEVON(x)        (!(((x)[2] & SESCTL_RQSINS) |   \
  814                            ((x)[2] & SESCTL_RQSRMV) |   \
  815                            ((x)[3] & SESCTL_DEVOFF)))
  816                                 if (DEVON(req->elm_stat) != DEVON(ep->encstat))
  817                                         cfg->current_request_stages++;
  818 #define IDON(x)         (!!((x)[2] & SESCTL_RQSID))
  819                                 if (IDON(req->elm_stat) != IDON(ep->encstat))
  820                                         cfg->current_request_stages++;
  821                                 break;
  822                         case 1:
  823                         case 2:
  824                                 buf[0] = SAFTE_WT_SLTOP;
  825                                 buf[1] = idx - cfg->slotoff;
  826                                 if (cfg->current_request_stage == 1 &&
  827                                     DEVON(req->elm_stat) != DEVON(ep->encstat)) {
  828                                         if (DEVON(req->elm_stat))
  829                                                 buf[2] = 0x01;
  830                                         else
  831                                                 buf[2] = 0x02;
  832                                 } else {
  833                                         if (IDON(req->elm_stat))
  834                                                 buf[2] = 0x04;
  835                                         else
  836                                                 buf[2] = 0x00;
  837                                         ep->encstat[2] &= ~SESCTL_RQSID;
  838                                         ep->encstat[2] |= req->elm_stat[2] &
  839                                             SESCTL_RQSID;
  840                                 }
  841                                 xfer_len = 64;
  842                                 break;
  843                         default:
  844                                 return (EINVAL);
  845                         }
  846                         break;
  847                 case ELMTYP_POWER:
  848                         cfg->current_request_stages = 2;
  849                         switch (cfg->current_request_stage) {
  850                         case 0:
  851                                 if (req->elm_stat[3] & SESCTL_RQSTFAIL) {
  852                                         cfg->flag1 |= SAFT_FLG1_ENCPWRFAIL;
  853                                 } else {
  854                                         cfg->flag1 &= ~SAFT_FLG1_ENCPWRFAIL;
  855                                 }
  856                                 buf[0] = SAFTE_WT_GLOBAL;
  857                                 buf[1] = cfg->flag1;
  858                                 buf[2] = cfg->flag2;
  859                                 buf[3] = 0;
  860                                 xfer_len = 16;
  861                                 break;
  862                         case 1:
  863                                 buf[0] = SAFTE_WT_ACTPWS;
  864                                 buf[1] = idx - cfg->pwroff;
  865                                 if (req->elm_stat[3] & SESCTL_RQSTON)
  866                                         buf[2] = 0x01;
  867                                 else
  868                                         buf[2] = 0x00;
  869                                 buf[3] = 0;
  870                                 xfer_len = 16;
  871                         default:
  872                                 return (EINVAL);
  873                         }
  874                         break;
  875                 case ELMTYP_FAN:
  876                         if ((req->elm_stat[3] & 0x7) != 0)
  877                                 cfg->current_request_stages = 2;
  878                         switch (cfg->current_request_stage) {
  879                         case 0:
  880                                 if (req->elm_stat[3] & SESCTL_RQSTFAIL)
  881                                         cfg->flag1 |= SAFT_FLG1_ENCFANFAIL;
  882                                 else
  883                                         cfg->flag1 &= ~SAFT_FLG1_ENCFANFAIL;
  884                                 buf[0] = SAFTE_WT_GLOBAL;
  885                                 buf[1] = cfg->flag1;
  886                                 buf[2] = cfg->flag2;
  887                                 buf[3] = 0;
  888                                 xfer_len = 16;
  889                                 break;
  890                         case 1:
  891                                 buf[0] = SAFTE_WT_FANSPD;
  892                                 buf[1] = idx;
  893                                 if (req->elm_stat[3] & SESCTL_RQSTON) {
  894                                         if ((req->elm_stat[3] & 0x7) == 7)
  895                                                 buf[2] = 4;
  896                                         else if ((req->elm_stat[3] & 0x7) >= 5)
  897                                                 buf[2] = 3;
  898                                         else if ((req->elm_stat[3] & 0x7) >= 3)
  899                                                 buf[2] = 2;
  900                                         else
  901                                                 buf[2] = 1;
  902                                 } else
  903                                         buf[2] = 0;
  904                                 buf[3] = 0;
  905                                 xfer_len = 16;
  906                                 ep->encstat[3] = req->elm_stat[3] & 0x67;
  907                         default:
  908                                 return (EINVAL);
  909                         }
  910                         break;
  911                 case ELMTYP_DOORLOCK:
  912                         if (req->elm_stat[3] & 0x1)
  913                                 cfg->flag2 &= ~SAFT_FLG2_LOCKDOOR;
  914                         else
  915                                 cfg->flag2 |= SAFT_FLG2_LOCKDOOR;
  916                         buf[0] = SAFTE_WT_GLOBAL;
  917                         buf[1] = cfg->flag1;
  918                         buf[2] = cfg->flag2;
  919                         buf[3] = 0;
  920                         xfer_len = 16;
  921                         break;
  922                 case ELMTYP_ALARM:
  923                         if ((req->elm_stat[0] & SESCTL_DISABLE) ||
  924                             (req->elm_stat[3] & 0x40)) {
  925                                 cfg->flag2 &= ~SAFT_FLG1_ALARM;
  926                         } else if ((req->elm_stat[3] & 0x0f) != 0) {
  927                                 cfg->flag2 |= SAFT_FLG1_ALARM;
  928                         } else {
  929                                 cfg->flag2 &= ~SAFT_FLG1_ALARM;
  930                         }
  931                         buf[0] = SAFTE_WT_GLOBAL;
  932                         buf[1] = cfg->flag1;
  933                         buf[2] = cfg->flag2;
  934                         buf[3] = 0;
  935                         xfer_len = 16;
  936                         ep->encstat[3] = req->elm_stat[3];
  937                         break;
  938                 default:
  939                         return (EINVAL);
  940                 }
  941         }
  942 
  943         if (enc->enc_type == ENC_SEMB_SAFT) {
  944                 semb_write_buffer(&ccb->ataio, /*retries*/5,
  945                                 enc_done, MSG_SIMPLE_Q_TAG,
  946                                 buf, xfer_len, state->timeout);
  947         } else {
  948                 scsi_write_buffer(&ccb->csio, /*retries*/5,
  949                                 enc_done, MSG_SIMPLE_Q_TAG, 1,
  950                                 0, 0, buf, xfer_len,
  951                                 SSD_FULL_SIZE, state->timeout);
  952         }
  953         return (0);
  954 }
  955 
  956 static int
  957 safte_process_control_request(enc_softc_t *enc, struct enc_fsm_state *state,
  958     union ccb *ccb, uint8_t **bufp, int error, int xfer_len)
  959 {
  960         struct scfg *cfg;
  961         safte_control_request_t *req;
  962         int idx, type;
  963 
  964         cfg = enc->enc_private;
  965         if (cfg == NULL)
  966                 return (ENXIO);
  967 
  968         req = cfg->current_request;
  969         if (req->result == 0)
  970                 req->result = error;
  971         if (++cfg->current_request_stage >= cfg->current_request_stages) {
  972                 idx = req->elm_idx;
  973                 if (idx == SES_SETSTATUS_ENC_IDX)
  974                         type = -1;
  975                 else
  976                         type = enc->enc_cache.elm_map[idx].enctype;
  977                 if (type == ELMTYP_DEVICE || type == ELMTYP_ARRAY_DEV)
  978                         enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
  979                 else
  980                         enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
  981                 cfg->current_request = NULL;
  982                 wakeup(req);
  983         } else {
  984                 enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
  985         }
  986         return (0);
  987 }
  988 
  989 static void
  990 safte_softc_invalidate(enc_softc_t *enc)
  991 {
  992         struct scfg *cfg;
  993 
  994         cfg = enc->enc_private;
  995         safte_terminate_control_requests(&cfg->requests, ENXIO);
  996 }
  997 
  998 static void
  999 safte_softc_cleanup(enc_softc_t *enc)
 1000 {
 1001 
 1002         ENC_FREE_AND_NULL(enc->enc_cache.elm_map);
 1003         ENC_FREE_AND_NULL(enc->enc_private);
 1004         enc->enc_cache.nelms = 0;
 1005 }
 1006 
 1007 static int
 1008 safte_init_enc(enc_softc_t *enc)
 1009 {
 1010         struct scfg *cfg;
 1011         int err;
 1012         static char cdb0[6] = { SEND_DIAGNOSTIC };
 1013 
 1014         cfg = enc->enc_private;
 1015         if (cfg == NULL)
 1016                 return (ENXIO);
 1017 
 1018         err = enc_runcmd(enc, cdb0, 6, NULL, 0);
 1019         if (err) {
 1020                 return (err);
 1021         }
 1022         DELAY(5000);
 1023         cfg->flag1 = 0;
 1024         cfg->flag2 = 0;
 1025         err = safte_set_enc_status(enc, 0, 1);
 1026         return (err);
 1027 }
 1028 
 1029 static int
 1030 safte_get_enc_status(enc_softc_t *enc, int slpflg)
 1031 {
 1032 
 1033         return (0);
 1034 }
 1035 
 1036 static int
 1037 safte_set_enc_status(enc_softc_t *enc, uint8_t encstat, int slpflag)
 1038 {
 1039         struct scfg *cfg;
 1040         safte_control_request_t req;
 1041 
 1042         cfg = enc->enc_private;
 1043         if (cfg == NULL)
 1044                 return (ENXIO);
 1045 
 1046         req.elm_idx = SES_SETSTATUS_ENC_IDX;
 1047         req.elm_stat[0] = encstat & 0xf;
 1048         req.result = 0;
 1049         
 1050         TAILQ_INSERT_TAIL(&cfg->requests, &req, links);
 1051         enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
 1052         cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0);
 1053 
 1054         return (req.result);
 1055 }
 1056 
 1057 static int
 1058 safte_get_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflg)
 1059 {
 1060         int i = (int)elms->elm_idx;
 1061 
 1062         elms->cstat[0] = enc->enc_cache.elm_map[i].encstat[0];
 1063         elms->cstat[1] = enc->enc_cache.elm_map[i].encstat[1];
 1064         elms->cstat[2] = enc->enc_cache.elm_map[i].encstat[2];
 1065         elms->cstat[3] = enc->enc_cache.elm_map[i].encstat[3];
 1066         return (0);
 1067 }
 1068 
 1069 static int
 1070 safte_set_elm_status(enc_softc_t *enc, encioc_elm_status_t *elms, int slpflag)
 1071 {
 1072         struct scfg *cfg;
 1073         safte_control_request_t req;
 1074 
 1075         cfg = enc->enc_private;
 1076         if (cfg == NULL)
 1077                 return (ENXIO);
 1078 
 1079         /* If this is clear, we don't do diddly.  */
 1080         if ((elms->cstat[0] & SESCTL_CSEL) == 0)
 1081                 return (0);
 1082 
 1083         req.elm_idx = elms->elm_idx;
 1084         memcpy(&req.elm_stat, elms->cstat, sizeof(req.elm_stat));
 1085         req.result = 0;
 1086 
 1087         TAILQ_INSERT_TAIL(&cfg->requests, &req, links);
 1088         enc_update_request(enc, SAFTE_PROCESS_CONTROL_REQS);
 1089         cam_periph_sleep(enc->periph, &req, PUSER, "encstat", 0);
 1090 
 1091         return (req.result);
 1092 }
 1093 
 1094 static void
 1095 safte_poll_status(enc_softc_t *enc)
 1096 {
 1097 
 1098         enc_update_request(enc, SAFTE_UPDATE_READENCSTATUS);
 1099         enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
 1100 }
 1101 
 1102 static struct enc_vec safte_enc_vec =
 1103 {
 1104         .softc_invalidate       = safte_softc_invalidate,
 1105         .softc_cleanup  = safte_softc_cleanup,
 1106         .init_enc       = safte_init_enc,
 1107         .get_enc_status = safte_get_enc_status,
 1108         .set_enc_status = safte_set_enc_status,
 1109         .get_elm_status = safte_get_elm_status,
 1110         .set_elm_status = safte_set_elm_status,
 1111         .poll_status    = safte_poll_status
 1112 };
 1113 
 1114 int
 1115 safte_softc_init(enc_softc_t *enc)
 1116 {
 1117         struct scfg *cfg;
 1118 
 1119         enc->enc_vec = safte_enc_vec;
 1120         enc->enc_fsm_states = enc_fsm_states;
 1121 
 1122         if (enc->enc_private == NULL) {
 1123                 enc->enc_private = ENC_MALLOCZ(SAFT_PRIVATE);
 1124                 if (enc->enc_private == NULL)
 1125                         return (ENOMEM);
 1126         }
 1127         cfg = enc->enc_private;
 1128 
 1129         enc->enc_cache.nelms = 0;
 1130         enc->enc_cache.enc_status = 0;
 1131 
 1132         TAILQ_INIT(&cfg->requests);
 1133         return (0);
 1134 }
 1135 

Cache object: 284b703e93a80b2ad5722d5beea09b38


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