Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  esas2r_vda.c   Sprache: C

 
/*
 *  linux/drivers/scsi/esas2r/esas2r_vda.c
 *      esas2r driver VDA firmware interface functions
 *
 *  Copyright (c) 2001-2013 ATTO Technology, Inc.
 *  (mailto:linuxdrivers@attotech.com)
 */

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  NO WARRANTY
 *  THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
 *  CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
 *  LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
 *  MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
 *  solely responsible for determining the appropriateness of using and
 *  distributing the Program and assumes all risks associated with its
 *  exercise of rights under this Agreement, including but not limited to
 *  the risks and costs of program errors, damage to or loss of data,
 *  programs or equipment, and unavailability or interruption of operations.
 *
 *  DISCLAIMER OF LIABILITY
 *  NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
 *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 *  DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 *  USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
 *  HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

#include "esas2r.h"

static u8 esas2r_vdaioctl_versions[] = {
 ATTO_VDA_VER_UNSUPPORTED,
 ATTO_VDA_FLASH_VER,
 ATTO_VDA_VER_UNSUPPORTED,
 ATTO_VDA_VER_UNSUPPORTED,
 ATTO_VDA_CLI_VER,
 ATTO_VDA_VER_UNSUPPORTED,
 ATTO_VDA_CFG_VER,
 ATTO_VDA_MGT_VER,
 ATTO_VDA_GSV_VER
};

static void clear_vda_request(struct esas2r_request *rq);

static void esas2r_complete_vda_ioctl(struct esas2r_adapter *a,
          struct esas2r_request *rq);

/* Prepare a VDA IOCTL request to be sent to the firmware. */
bool esas2r_process_vda_ioctl(struct esas2r_adapter *a,
         struct atto_ioctl_vda *vi,
         struct esas2r_request *rq,
         struct esas2r_sg_context *sgc)
{
 u32 datalen = 0;
 struct atto_vda_sge *firstsg = NULL;
 u8 vercnt = (u8)ARRAY_SIZE(esas2r_vdaioctl_versions);

 vi->status = ATTO_STS_SUCCESS;
 vi->vda_status = RS_PENDING;

 if (vi->function >= vercnt) {
  vi->status = ATTO_STS_INV_FUNC;
  return false;
 }

 if (vi->version > esas2r_vdaioctl_versions[vi->function]) {
  vi->status = ATTO_STS_INV_VERSION;
  return false;
 }

 if (test_bit(AF_DEGRADED_MODE, &a->flags)) {
  vi->status = ATTO_STS_DEGRADED;
  return false;
 }

 if (vi->function != VDA_FUNC_SCSI)
  clear_vda_request(rq);

 rq->vrq->scsi.function = vi->function;
 rq->interrupt_cb = esas2r_complete_vda_ioctl;
 rq->interrupt_cx = vi;

 switch (vi->function) {
 case VDA_FUNC_FLASH:

  if (vi->cmd.flash.sub_func != VDA_FLASH_FREAD
      && vi->cmd.flash.sub_func != VDA_FLASH_FWRITE
      && vi->cmd.flash.sub_func != VDA_FLASH_FINFO) {
   vi->status = ATTO_STS_INV_FUNC;
   return false;
  }

  if (vi->cmd.flash.sub_func != VDA_FLASH_FINFO)
   datalen = vi->data_length;

  rq->vrq->flash.length = cpu_to_le32(datalen);
  rq->vrq->flash.sub_func = vi->cmd.flash.sub_func;

  memcpy(rq->vrq->flash.data.file.file_name,
         vi->cmd.flash.data.file.file_name,
         sizeof(vi->cmd.flash.data.file.file_name));

  firstsg = rq->vrq->flash.data.file.sge;
  break;

 case VDA_FUNC_CLI:

  datalen = vi->data_length;

  rq->vrq->cli.cmd_rsp_len =
   cpu_to_le32(vi->cmd.cli.cmd_rsp_len);
  rq->vrq->cli.length = cpu_to_le32(datalen);

  firstsg = rq->vrq->cli.sge;
  break;

 case VDA_FUNC_MGT:
 {
  u8 *cmdcurr_offset = sgc->cur_offset
         - offsetof(struct atto_ioctl_vda, data)
         + offsetof(struct atto_ioctl_vda, cmd)
         + offsetof(struct atto_ioctl_vda_mgt_cmd,
      data);
  /*
 * build the data payload SGL here first since
 * esas2r_sgc_init() will modify the S/G list offset for the
 * management SGL (which is built below where the data SGL is
 * usually built).
 */


  if (vi->data_length) {
   u32 payldlen = 0;

   if (vi->cmd.mgt.mgt_func == VDAMGT_DEV_HEALTH_REQ
       || vi->cmd.mgt.mgt_func == VDAMGT_DEV_METRICS) {
    rq->vrq->mgt.payld_sglst_offset =
     (u8)offsetof(struct atto_vda_mgmt_req,
           payld_sge);

    payldlen = vi->data_length;
    datalen = vi->cmd.mgt.data_length;
   } else if (vi->cmd.mgt.mgt_func == VDAMGT_DEV_INFO2
       || vi->cmd.mgt.mgt_func ==
       VDAMGT_DEV_INFO2_BYADDR) {
    datalen = vi->data_length;
    cmdcurr_offset = sgc->cur_offset;
   } else {
    vi->status = ATTO_STS_INV_PARAM;
    return false;
   }

   /* Setup the length so building the payload SGL works */
   rq->vrq->mgt.length = cpu_to_le32(datalen);

   if (payldlen) {
    rq->vrq->mgt.payld_length =
     cpu_to_le32(payldlen);

    esas2r_sgc_init(sgc, a, rq,
      rq->vrq->mgt.payld_sge);
    sgc->length = payldlen;

    if (!esas2r_build_sg_list(a, rq, sgc)) {
     vi->status = ATTO_STS_OUT_OF_RSRC;
     return false;
    }
   }
  } else {
   datalen = vi->cmd.mgt.data_length;

   rq->vrq->mgt.length = cpu_to_le32(datalen);
  }

  /*
 * Now that the payload SGL is built, if any, setup to build
 * the management SGL.
 */

  firstsg = rq->vrq->mgt.sge;
  sgc->cur_offset = cmdcurr_offset;

  /* Finish initializing the management request. */
  rq->vrq->mgt.mgt_func = vi->cmd.mgt.mgt_func;
  rq->vrq->mgt.scan_generation = vi->cmd.mgt.scan_generation;
  rq->vrq->mgt.dev_index =
   cpu_to_le32(vi->cmd.mgt.dev_index);

  esas2r_nuxi_mgt_data(rq->vrq->mgt.mgt_func, &vi->cmd.mgt.data);
  break;
 }

 case VDA_FUNC_CFG:

  if (vi->data_length
      || vi->cmd.cfg.data_length == 0) {
   vi->status = ATTO_STS_INV_PARAM;
   return false;
  }

  if (vi->cmd.cfg.cfg_func == VDA_CFG_INIT) {
   vi->status = ATTO_STS_INV_FUNC;
   return false;
  }

  rq->vrq->cfg.sub_func = vi->cmd.cfg.cfg_func;
  rq->vrq->cfg.length = cpu_to_le32(vi->cmd.cfg.data_length);

  if (vi->cmd.cfg.cfg_func == VDA_CFG_GET_INIT) {
   memcpy(&rq->vrq->cfg.data,
          &vi->cmd.cfg.data,
          vi->cmd.cfg.data_length);

   esas2r_nuxi_cfg_data(rq->vrq->cfg.sub_func,
          &rq->vrq->cfg.data);
  } else {
   vi->status = ATTO_STS_INV_FUNC;

   return false;
  }

  break;

 case VDA_FUNC_GSV:

  vi->cmd.gsv.rsp_len = vercnt;

  memcpy(vi->cmd.gsv.version_info, esas2r_vdaioctl_versions,
         vercnt);

  vi->vda_status = RS_SUCCESS;
  break;

 default:

  vi->status = ATTO_STS_INV_FUNC;
  return false;
 }

 if (datalen) {
  esas2r_sgc_init(sgc, a, rq, firstsg);
  sgc->length = datalen;

  if (!esas2r_build_sg_list(a, rq, sgc)) {
   vi->status = ATTO_STS_OUT_OF_RSRC;
   return false;
  }
 }

 esas2r_start_request(a, rq);

 return true;
}

static void esas2r_complete_vda_ioctl(struct esas2r_adapter *a,
          struct esas2r_request *rq)
{
 struct atto_ioctl_vda *vi = (struct atto_ioctl_vda *)rq->interrupt_cx;

 vi->vda_status = rq->req_stat;

 switch (vi->function) {
 case VDA_FUNC_FLASH:

  if (vi->cmd.flash.sub_func == VDA_FLASH_FINFO
      || vi->cmd.flash.sub_func == VDA_FLASH_FREAD)
   vi->cmd.flash.data.file.file_size =
    le32_to_cpu(rq->func_rsp.flash_rsp.file_size);

  break;

 case VDA_FUNC_MGT:

  vi->cmd.mgt.scan_generation =
   rq->func_rsp.mgt_rsp.scan_generation;
  vi->cmd.mgt.dev_index = le16_to_cpu(
   rq->func_rsp.mgt_rsp.dev_index);

  if (vi->data_length == 0)
   vi->cmd.mgt.data_length =
    le32_to_cpu(rq->func_rsp.mgt_rsp.length);

  esas2r_nuxi_mgt_data(rq->vrq->mgt.mgt_func, &vi->cmd.mgt.data);
  break;

 case VDA_FUNC_CFG:

  if (vi->cmd.cfg.cfg_func == VDA_CFG_GET_INIT) {
   struct atto_ioctl_vda_cfg_cmd *cfg = &vi->cmd.cfg;
   struct atto_vda_cfg_rsp *rsp = &rq->func_rsp.cfg_rsp;
   char buf[sizeof(cfg->data.init.fw_release) + 1];

   cfg->data_length =
    cpu_to_le32(sizeof(struct atto_vda_cfg_init));
   cfg->data.init.vda_version =
    le32_to_cpu(rsp->vda_version);
   cfg->data.init.fw_build = rsp->fw_build;

   snprintf(buf, sizeof(buf), "%1.1u.%2.2u",
     (int)LOBYTE(le16_to_cpu(rsp->fw_release)),
     (int)HIBYTE(le16_to_cpu(rsp->fw_release)));

   memcpy(&cfg->data.init.fw_release, buf,
          sizeof(cfg->data.init.fw_release));

   if (LOWORD(LOBYTE(cfg->data.init.fw_build)) == 'A')
    cfg->data.init.fw_version =
     cfg->data.init.fw_build;
   else
    cfg->data.init.fw_version =
     cfg->data.init.fw_release;
  } else {
   esas2r_nuxi_cfg_data(rq->vrq->cfg.sub_func,
          &vi->cmd.cfg.data);
  }

  break;

 case VDA_FUNC_CLI:

  vi->cmd.cli.cmd_rsp_len =
   le32_to_cpu(rq->func_rsp.cli_rsp.cmd_rsp_len);
  break;

 default:

  break;
 }
}

/* Build a flash VDA request. */
void esas2r_build_flash_req(struct esas2r_adapter *a,
       struct esas2r_request *rq,
       u8 sub_func,
       u8 cksum,
       u32 addr,
       u32 length)
{
 struct atto_vda_flash_req *vrq = &rq->vrq->flash;

 clear_vda_request(rq);

 rq->vrq->scsi.function = VDA_FUNC_FLASH;

 if (sub_func == VDA_FLASH_BEGINW
     || sub_func == VDA_FLASH_WRITE
     || sub_func == VDA_FLASH_READ)
  vrq->sg_list_offset = (u8)offsetof(struct atto_vda_flash_req,
         data.sge);

 vrq->length = cpu_to_le32(length);
 vrq->flash_addr = cpu_to_le32(addr);
 vrq->checksum = cksum;
 vrq->sub_func = sub_func;
}

/* Build a VDA management request. */
void esas2r_build_mgt_req(struct esas2r_adapter *a,
     struct esas2r_request *rq,
     u8 sub_func,
     u8 scan_gen,
     u16 dev_index,
     u32 length,
     void *data)
{
 struct atto_vda_mgmt_req *vrq = &rq->vrq->mgt;

 clear_vda_request(rq);

 rq->vrq->scsi.function = VDA_FUNC_MGT;

 vrq->mgt_func = sub_func;
 vrq->scan_generation = scan_gen;
 vrq->dev_index = cpu_to_le16(dev_index);
 vrq->length = cpu_to_le32(length);

 if (vrq->length) {
  if (test_bit(AF_LEGACY_SGE_MODE, &a->flags)) {
   vrq->sg_list_offset = (u8)offsetof(
    struct atto_vda_mgmt_req, sge);

   vrq->sge[0].length = cpu_to_le32(SGE_LAST | length);
   vrq->sge[0].address = cpu_to_le64(
    rq->vrq_md->phys_addr +
    sizeof(union atto_vda_req));
  } else {
   vrq->sg_list_offset = (u8)offsetof(
    struct atto_vda_mgmt_req, prde);

   vrq->prde[0].ctl_len = cpu_to_le32(length);
   vrq->prde[0].address = cpu_to_le64(
    rq->vrq_md->phys_addr +
    sizeof(union atto_vda_req));
  }
 }

 if (data) {
  esas2r_nuxi_mgt_data(sub_func, data);

  memcpy(&rq->vda_rsp_data->mgt_data.data.bytes[0], data,
         length);
 }
}

/* Build a VDA asyncronous event (AE) request. */
void esas2r_build_ae_req(struct esas2r_adapter *a, struct esas2r_request *rq)
{
 struct atto_vda_ae_req *vrq = &rq->vrq->ae;

 clear_vda_request(rq);

 rq->vrq->scsi.function = VDA_FUNC_AE;

 vrq->length = cpu_to_le32(sizeof(struct atto_vda_ae_data));

 if (test_bit(AF_LEGACY_SGE_MODE, &a->flags)) {
  vrq->sg_list_offset =
   (u8)offsetof(struct atto_vda_ae_req, sge);
  vrq->sge[0].length = cpu_to_le32(SGE_LAST | vrq->length);
  vrq->sge[0].address = cpu_to_le64(
   rq->vrq_md->phys_addr +
   sizeof(union atto_vda_req));
 } else {
  vrq->sg_list_offset = (u8)offsetof(struct atto_vda_ae_req,
         prde);
  vrq->prde[0].ctl_len = cpu_to_le32(vrq->length);
  vrq->prde[0].address = cpu_to_le64(
   rq->vrq_md->phys_addr +
   sizeof(union atto_vda_req));
 }
}

/* Build a VDA IOCTL request. */
void esas2r_build_ioctl_req(struct esas2r_adapter *a,
       struct esas2r_request *rq,
       u32 length,
       u8 sub_func)
{
 struct atto_vda_ioctl_req *vrq = &rq->vrq->ioctl;

 clear_vda_request(rq);

 rq->vrq->scsi.function = VDA_FUNC_IOCTL;

 vrq->length = cpu_to_le32(length);
 vrq->sub_func = sub_func;
 vrq->sg_list_offset = (u8)offsetof(struct atto_vda_ioctl_req, sge);
}

/* Build a VDA configuration request. */
void esas2r_build_cfg_req(struct esas2r_adapter *a,
     struct esas2r_request *rq,
     u8 sub_func,
     u32 length,
     void *data)
{
 struct atto_vda_cfg_req *vrq = &rq->vrq->cfg;

 clear_vda_request(rq);

 rq->vrq->scsi.function = VDA_FUNC_CFG;

 vrq->sub_func = sub_func;
 vrq->length = cpu_to_le32(length);

 if (data) {
  esas2r_nuxi_cfg_data(sub_func, data);

  memcpy(&vrq->data, data, length);
 }
}

static void clear_vda_request(struct esas2r_request *rq)
{
 u32 handle = rq->vrq->scsi.handle;

 memset(rq->vrq, 0, sizeof(*rq->vrq));

 rq->vrq->scsi.handle = handle;

 rq->req_stat = RS_PENDING;

 /* since the data buffer is separate clear that too */

 memset(rq->data_buf, 0, ESAS2R_DATA_BUF_LEN);

 /*
 * Setup next and prev pointer in case the request is not going through
 * esas2r_start_request().
 */


 INIT_LIST_HEAD(&rq->req_list);
}

Messung V0.5
C=96 H=95 G=95

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge