--- /dev/null
+/*
+ * Copyright (c) 1998,1999,2000
+ * Traakan, Inc., Los Altos, CA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Project: NDMJOB
+ * Ident: $Id: $
+ *
+ * Description:
+ *
+ */
+
+
+#include "smc_priv.h"
+
+
+#define WITH(P,V,T) { T * V = (T *) P;
+#define ENDWITH }
+
+int
+smc_parse_volume_tag (
+ struct smc_raw_volume_tag *raw,
+ struct smc_volume_tag *vtag)
+{
+ int i;
+
+ bzero (vtag, sizeof *vtag);
+
+ for (i = 31; i >= 0 && raw->volume_id[i] == ' '; i--)
+ continue;
+
+ for (; i >= 0; i--)
+ vtag->volume_id[i] = raw->volume_id[i];
+
+ vtag->volume_seq = SMC_GET2(raw->volume_seq);
+
+ return 0;
+}
+
+
+
+int
+smc_parse_element_status_data (
+ char * raw,
+ unsigned raw_len,
+ struct smc_element_descriptor elem_desc[],
+ unsigned max_elem_desc)
+{
+ unsigned char * p = (unsigned char *)raw;
+ unsigned char * raw_end = p + raw_len;
+ unsigned int n_elem = 0;
+
+ bzero (elem_desc, sizeof elem_desc[0] * max_elem_desc);
+
+ WITH(p, esdh, struct smc_raw_element_status_data_header)
+ unsigned byte_count = SMC_GET3(esdh->byte_count);
+
+ if (raw_len > byte_count+8) {
+ /* probably an error, but press on */
+ raw_len = byte_count+8;
+ }
+ raw_end = p + raw_len;
+ ENDWITH
+
+ p += 8;
+
+ while (p+8 < raw_end) { /* +8 for sizeof *esph */
+ WITH(p, esph, struct smc_raw_element_status_page_header)
+ unsigned desc_size = SMC_GET2(esph->elem_desc_len);
+ unsigned byte_count = SMC_GET3(esph->byte_count);
+ unsigned elem_type = esph->element_type;
+ unsigned char * pgend = p + byte_count + 8;
+ int PVolTag = 0;
+ int AVolTag = 0;
+
+ if (pgend > raw_end) {
+ /* malformed, really, but punt */
+ pgend = raw_end;
+ }
+
+ if (esph->flag1 & SMC_RAW_ESP_F1_PVolTag)
+ PVolTag = 1;
+ if (esph->flag1 & SMC_RAW_ESP_F1_AVolTag)
+ AVolTag = 1;
+
+ p += 8;
+
+ for (;p + desc_size <= pgend; p += desc_size) {
+ struct smc_element_descriptor *edp;
+
+ if (n_elem >= max_elem_desc) {
+ /* bust out */
+ goto done;
+ }
+ edp = &elem_desc[n_elem++];
+ WITH (p, red, struct smc_raw_element_descriptor)
+ unsigned char *p2;
+
+ edp->element_type_code = elem_type;
+ edp->element_address = SMC_GET2(red->element_address);
+ edp->PVolTag = PVolTag;
+ edp->AVolTag = AVolTag;
+#define FLAG(RAWMEM,BIT,MEM) if (red->RAWMEM & BIT) edp->MEM = 1;
+ FLAG(flags2, SMC_RAW_ED_F2_Full, Full);
+ FLAG(flags2, SMC_RAW_ED_F2_ImpExp, ImpExp);
+ FLAG(flags2, SMC_RAW_ED_F2_Except, Except);
+ FLAG(flags2, SMC_RAW_ED_F2_Access, Access);
+ FLAG(flags2, SMC_RAW_ED_F2_ExEnab, ExEnab);
+ FLAG(flags2, SMC_RAW_ED_F2_InEnab, InEnab);
+
+ edp->asc = red->asc;
+ edp->ascq = red->ascq;
+
+ edp->scsi_lun = red->flags6 & 7;
+ FLAG(flags6, SMC_RAW_ED_F6_LU_valid, LU_valid);
+ FLAG(flags6, SMC_RAW_ED_F6_ID_valid, ID_valid);
+ FLAG(flags6, SMC_RAW_ED_F6_Not_bus, Not_bus);
+
+ edp->scsi_sid = red->scsi_sid;
+
+ FLAG(flags9, SMC_RAW_ED_F9_Invert, Invert);
+ FLAG(flags9, SMC_RAW_ED_F9_SValid, SValid);
+#undef FLAG
+
+ edp->src_se_addr = SMC_GET2(red->src_se_addr);
+
+ p2 = (unsigned char *) &red->primary_vol_tag;
+ if (edp->PVolTag) {
+ smc_parse_volume_tag ((void*)p2,
+ &edp->primary_vol_tag);
+ p2 += SMC_VOL_TAG_LEN;
+ }
+ if (edp->AVolTag) {
+ smc_parse_volume_tag ((void*)p2,
+ &edp->alternate_vol_tag);
+ p2 += SMC_VOL_TAG_LEN;
+ }
+ p2 += 4; /* resv84 */
+ /* p2 ready for vendor_specific */
+ ENDWITH
+ }
+ p = pgend;
+ ENDWITH
+ }
+
+ done:
+ return n_elem;
+}
+
+
+
+int
+smc_parse_element_address_assignment (
+ struct smc_raw_element_address_assignment_page *raw,
+ struct smc_element_address_assignment *eaa)
+{
+ eaa->mte_addr = SMC_GET2(raw->mte_addr);
+ eaa->mte_count = SMC_GET2(raw->mte_count);
+ eaa->se_addr = SMC_GET2(raw->se_addr);
+ eaa->se_count = SMC_GET2(raw->se_count);
+ eaa->iee_addr = SMC_GET2(raw->iee_addr);
+ eaa->iee_count = SMC_GET2(raw->iee_count);
+ eaa->dte_addr = SMC_GET2(raw->dte_addr);
+ eaa->dte_count = SMC_GET2(raw->dte_count);
+
+ return 0;
+}
+