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

Cache object: 524adb7e9448e07bf78a3fbb5eab1ef4


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