1 /*
2  * Copyright (c) 1998,1999,2000
3  *      Traakan, Inc., Los Altos, CA
4  *      All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice unmodified, this list of conditions, and the following
11  *    disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
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
20  * FOR 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 /*
30  * Project:  NDMJOB
31  * Ident:    $Id: $
32  *
33  * Description:
34  *
35  */
36 
37 
38 #include "smc_priv.h"
39 
40 
41 #define WITH(P, V, T) \
42   {                   \
43     T* V = (T*)P;
44 #define ENDWITH }
45 
smc_parse_volume_tag(struct smc_raw_volume_tag * raw,struct smc_volume_tag * vtag)46 int smc_parse_volume_tag(struct smc_raw_volume_tag* raw,
47                          struct smc_volume_tag* vtag)
48 {
49   int i;
50 
51   bzero(vtag, sizeof *vtag);
52 
53   for (i = 31; i >= 0 && raw->volume_id[i] == ' '; i--) continue;
54 
55   for (; i >= 0; i--) vtag->volume_id[i] = raw->volume_id[i];
56 
57   vtag->volume_seq = SMC_GET2(raw->volume_seq);
58 
59   return 0;
60 }
61 
62 
smc_cleanup_element_status_data(struct smc_ctrl_block * smc)63 void smc_cleanup_element_status_data(struct smc_ctrl_block* smc)
64 {
65   struct smc_element_descriptor *edp, *edp_next;
66 
67   edp = smc->elem_desc;
68   while (edp) {
69     edp_next = edp->next;
70     if (edp->primary_vol_tag) { NDMOS_API_FREE(edp->primary_vol_tag); }
71     if (edp->alternate_vol_tag) { NDMOS_API_FREE(edp->alternate_vol_tag); }
72     NDMOS_API_FREE(edp);
73     edp = edp_next;
74   }
75 
76   smc->elem_desc = (struct smc_element_descriptor*)NULL;
77   smc->elem_desc_tail = (struct smc_element_descriptor*)NULL;
78 }
79 
80 
smc_parse_element_status_data(char * raw,unsigned raw_len,struct smc_ctrl_block * smc,unsigned max_elem_desc)81 int smc_parse_element_status_data(char* raw,
82                                   unsigned raw_len,
83                                   struct smc_ctrl_block* smc,
84                                   unsigned max_elem_desc)
85 {
86   unsigned char* p = (unsigned char*)raw;
87   unsigned char* raw_end = p + raw_len;
88   unsigned int n_elem = 0;
89   struct smc_element_descriptor* edp;
90 
91   smc_cleanup_element_status_data(smc);
92 
93   WITH(p, esdh, struct smc_raw_element_status_data_header)
94   unsigned byte_count = SMC_GET3(esdh->byte_count);
95 
96   if (raw_len > byte_count + 8) {
97     /* probably an error, but press on */
98     raw_len = byte_count + 8;
99   }
100   raw_end = p + raw_len;
101   ENDWITH
102 
103   p += 8;
104 
105   while (p + 8 < raw_end) { /* +8 for sizeof *esph */
106     WITH(p, esph, struct smc_raw_element_status_page_header)
107     unsigned desc_size = SMC_GET2(esph->elem_desc_len);
108     unsigned byte_count = SMC_GET3(esph->byte_count);
109     unsigned elem_type = esph->element_type;
110     unsigned char* pgend = p + byte_count + 8;
111     int PVolTag = 0;
112     int AVolTag = 0;
113 
114     if (pgend > raw_end) {
115       /* malformed, really, but punt */
116       pgend = raw_end;
117     }
118 
119     if (esph->flag1 & SMC_RAW_ESP_F1_PVolTag) PVolTag = 1;
120     if (esph->flag1 & SMC_RAW_ESP_F1_AVolTag) AVolTag = 1;
121 
122     p += 8;
123 
124     for (; p + desc_size <= pgend; p += desc_size) {
125       if (n_elem >= max_elem_desc) {
126         /* bust out */
127         goto done;
128       }
129 
130       edp = NDMOS_API_MALLOC(sizeof(struct smc_element_descriptor));
131       NDMOS_MACRO_ZEROFILL(edp);
132 
133       WITH(p, red, struct smc_raw_element_descriptor)
134       unsigned char* p2;
135 
136       edp->element_type_code = elem_type;
137       edp->element_address = SMC_GET2(red->element_address);
138       edp->PVolTag = PVolTag;
139       edp->AVolTag = AVolTag;
140 #define FLAG(RAWMEM, BIT, MEM) \
141   if (red->RAWMEM & BIT) edp->MEM = 1;
142       FLAG(flags2, SMC_RAW_ED_F2_Full, Full);
143       FLAG(flags2, SMC_RAW_ED_F2_ImpExp, ImpExp);
144       FLAG(flags2, SMC_RAW_ED_F2_Except, Except);
145       FLAG(flags2, SMC_RAW_ED_F2_Access, Access);
146       FLAG(flags2, SMC_RAW_ED_F2_ExEnab, ExEnab);
147       FLAG(flags2, SMC_RAW_ED_F2_InEnab, InEnab);
148 
149       edp->asc = red->asc;
150       edp->ascq = red->ascq;
151 
152       edp->scsi_lun = red->flags6 & 7;
153       FLAG(flags6, SMC_RAW_ED_F6_LU_valid, LU_valid);
154       FLAG(flags6, SMC_RAW_ED_F6_ID_valid, ID_valid);
155       FLAG(flags6, SMC_RAW_ED_F6_Not_bus, Not_bus);
156 
157       edp->scsi_sid = red->scsi_sid;
158 
159       FLAG(flags9, SMC_RAW_ED_F9_Invert, Invert);
160       FLAG(flags9, SMC_RAW_ED_F9_SValid, SValid);
161 #undef FLAG
162 
163       edp->src_se_addr = SMC_GET2(red->src_se_addr);
164 
165       p2 = (unsigned char*)&red->data;
166       if (edp->PVolTag) {
167         edp->primary_vol_tag = NDMOS_API_MALLOC(sizeof(struct smc_volume_tag));
168         smc_parse_volume_tag((void*)p2, edp->primary_vol_tag);
169         p2 += SMC_VOL_TAG_LEN;
170       }
171       if (edp->AVolTag) {
172         edp->alternate_vol_tag =
173             NDMOS_API_MALLOC(sizeof(struct smc_volume_tag));
174         smc_parse_volume_tag((void*)p2, edp->alternate_vol_tag);
175         p2 += SMC_VOL_TAG_LEN;
176       }
177       p2 += 4; /* resv84 */
178                /* p2 ready for vendor_specific */
179       ENDWITH
180 
181       if (!smc->elem_desc_tail) {
182         smc->elem_desc = edp;
183         smc->elem_desc_tail = edp;
184       } else {
185         smc->elem_desc_tail->next = edp;
186         smc->elem_desc_tail = edp;
187       }
188     }
189     p = pgend;
190     ENDWITH
191   }
192 
193 done:
194   return n_elem;
195 }
196 
197 
smc_parse_element_address_assignment(struct smc_raw_element_address_assignment_page * raw,struct smc_element_address_assignment * eaa)198 int smc_parse_element_address_assignment(
199     struct smc_raw_element_address_assignment_page* raw,
200     struct smc_element_address_assignment* eaa)
201 {
202   eaa->mte_addr = SMC_GET2(raw->mte_addr);
203   eaa->mte_count = SMC_GET2(raw->mte_count);
204   eaa->se_addr = SMC_GET2(raw->se_addr);
205   eaa->se_count = SMC_GET2(raw->se_count);
206   eaa->iee_addr = SMC_GET2(raw->iee_addr);
207   eaa->iee_count = SMC_GET2(raw->iee_count);
208   eaa->dte_addr = SMC_GET2(raw->dte_addr);
209   eaa->dte_count = SMC_GET2(raw->dte_count);
210 
211   return 0;
212 }
213