xref: /qemu/hw/scsi/mptendian.c (revision 30456d5ba3736b8f0c73560e559cdd2f76a4885e)
1  /*
2   * QEMU LSI SAS1068 Host Bus Adapter emulation
3   * Endianness conversion for MPI data structures
4   *
5   * Copyright (c) 2016 Red Hat, Inc.
6   *
7   * Authors: Paolo Bonzini <pbonzini@redhat.com>
8   *
9   * This library is free software; you can redistribute it and/or
10   * modify it under the terms of the GNU Lesser General Public
11   * License as published by the Free Software Foundation; either
12   * version 2 of the License, or (at your option) any later version.
13   *
14   * This library is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21   */
22  
23  #include "qemu/osdep.h"
24  #include "hw/hw.h"
25  #include "hw/pci/pci.h"
26  #include "sysemu/dma.h"
27  #include "sysemu/block-backend.h"
28  #include "hw/pci/msi.h"
29  #include "qemu/iov.h"
30  #include "hw/scsi/scsi.h"
31  #include "block/scsi.h"
32  #include "trace.h"
33  
34  #include "mptsas.h"
35  #include "mpi.h"
36  
37  static void mptsas_fix_sgentry_endianness(MPISGEntry *sge)
38  {
39      le32_to_cpus(&sge->FlagsLength);
40      if (sge->FlagsLength & MPI_SGE_FLAGS_64_BIT_ADDRESSING) {
41         le64_to_cpus(&sge->u.Address64);
42      } else {
43         le32_to_cpus(&sge->u.Address32);
44      }
45  }
46  
47  static void mptsas_fix_sgentry_endianness_reply(MPISGEntry *sge)
48  {
49      if (sge->FlagsLength & MPI_SGE_FLAGS_64_BIT_ADDRESSING) {
50         cpu_to_le64s(&sge->u.Address64);
51      } else {
52         cpu_to_le32s(&sge->u.Address32);
53      }
54      cpu_to_le32s(&sge->FlagsLength);
55  }
56  
57  void mptsas_fix_scsi_io_endianness(MPIMsgSCSIIORequest *req)
58  {
59      le32_to_cpus(&req->MsgContext);
60      le32_to_cpus(&req->Control);
61      le32_to_cpus(&req->DataLength);
62      le32_to_cpus(&req->SenseBufferLowAddr);
63  }
64  
65  void mptsas_fix_scsi_io_reply_endianness(MPIMsgSCSIIOReply *reply)
66  {
67      cpu_to_le32s(&reply->MsgContext);
68      cpu_to_le16s(&reply->IOCStatus);
69      cpu_to_le32s(&reply->IOCLogInfo);
70      cpu_to_le32s(&reply->TransferCount);
71      cpu_to_le32s(&reply->SenseCount);
72      cpu_to_le32s(&reply->ResponseInfo);
73      cpu_to_le16s(&reply->TaskTag);
74  }
75  
76  void mptsas_fix_scsi_task_mgmt_endianness(MPIMsgSCSITaskMgmt *req)
77  {
78      le32_to_cpus(&req->MsgContext);
79      le32_to_cpus(&req->TaskMsgContext);
80  }
81  
82  void mptsas_fix_scsi_task_mgmt_reply_endianness(MPIMsgSCSITaskMgmtReply *reply)
83  {
84      cpu_to_le32s(&reply->MsgContext);
85      cpu_to_le16s(&reply->IOCStatus);
86      cpu_to_le32s(&reply->IOCLogInfo);
87      cpu_to_le32s(&reply->TerminationCount);
88  }
89  
90  void mptsas_fix_ioc_init_endianness(MPIMsgIOCInit *req)
91  {
92      le32_to_cpus(&req->MsgContext);
93      le16_to_cpus(&req->ReplyFrameSize);
94      le32_to_cpus(&req->HostMfaHighAddr);
95      le32_to_cpus(&req->SenseBufferHighAddr);
96      le32_to_cpus(&req->ReplyFifoHostSignalingAddr);
97      mptsas_fix_sgentry_endianness(&req->HostPageBufferSGE);
98      le16_to_cpus(&req->MsgVersion);
99      le16_to_cpus(&req->HeaderVersion);
100  }
101  
102  void mptsas_fix_ioc_init_reply_endianness(MPIMsgIOCInitReply *reply)
103  {
104      cpu_to_le32s(&reply->MsgContext);
105      cpu_to_le16s(&reply->IOCStatus);
106      cpu_to_le32s(&reply->IOCLogInfo);
107  }
108  
109  void mptsas_fix_ioc_facts_endianness(MPIMsgIOCFacts *req)
110  {
111      le32_to_cpus(&req->MsgContext);
112  }
113  
114  void mptsas_fix_ioc_facts_reply_endianness(MPIMsgIOCFactsReply *reply)
115  {
116      cpu_to_le16s(&reply->MsgVersion);
117      cpu_to_le16s(&reply->HeaderVersion);
118      cpu_to_le32s(&reply->MsgContext);
119      cpu_to_le16s(&reply->IOCExceptions);
120      cpu_to_le16s(&reply->IOCStatus);
121      cpu_to_le32s(&reply->IOCLogInfo);
122      cpu_to_le16s(&reply->ReplyQueueDepth);
123      cpu_to_le16s(&reply->RequestFrameSize);
124      cpu_to_le16s(&reply->ProductID);
125      cpu_to_le32s(&reply->CurrentHostMfaHighAddr);
126      cpu_to_le16s(&reply->GlobalCredits);
127      cpu_to_le32s(&reply->CurrentSenseBufferHighAddr);
128      cpu_to_le16s(&reply->CurReplyFrameSize);
129      cpu_to_le32s(&reply->FWImageSize);
130      cpu_to_le32s(&reply->IOCCapabilities);
131      cpu_to_le16s(&reply->HighPriorityQueueDepth);
132      mptsas_fix_sgentry_endianness_reply(&reply->HostPageBufferSGE);
133      cpu_to_le32s(&reply->ReplyFifoHostSignalingAddr);
134  }
135  
136  void mptsas_fix_config_endianness(MPIMsgConfig *req)
137  {
138      le16_to_cpus(&req->ExtPageLength);
139      le32_to_cpus(&req->MsgContext);
140      le32_to_cpus(&req->PageAddress);
141      mptsas_fix_sgentry_endianness(&req->PageBufferSGE);
142  }
143  
144  void mptsas_fix_config_reply_endianness(MPIMsgConfigReply *reply)
145  {
146      cpu_to_le16s(&reply->ExtPageLength);
147      cpu_to_le32s(&reply->MsgContext);
148      cpu_to_le16s(&reply->IOCStatus);
149      cpu_to_le32s(&reply->IOCLogInfo);
150  }
151  
152  void mptsas_fix_port_facts_endianness(MPIMsgPortFacts *req)
153  {
154      le32_to_cpus(&req->MsgContext);
155  }
156  
157  void mptsas_fix_port_facts_reply_endianness(MPIMsgPortFactsReply *reply)
158  {
159      cpu_to_le32s(&reply->MsgContext);
160      cpu_to_le16s(&reply->IOCStatus);
161      cpu_to_le32s(&reply->IOCLogInfo);
162      cpu_to_le16s(&reply->MaxDevices);
163      cpu_to_le16s(&reply->PortSCSIID);
164      cpu_to_le16s(&reply->ProtocolFlags);
165      cpu_to_le16s(&reply->MaxPostedCmdBuffers);
166      cpu_to_le16s(&reply->MaxPersistentIDs);
167      cpu_to_le16s(&reply->MaxLanBuckets);
168  }
169  
170  void mptsas_fix_port_enable_endianness(MPIMsgPortEnable *req)
171  {
172      le32_to_cpus(&req->MsgContext);
173  }
174  
175  void mptsas_fix_port_enable_reply_endianness(MPIMsgPortEnableReply *reply)
176  {
177      cpu_to_le32s(&reply->MsgContext);
178      cpu_to_le16s(&reply->IOCStatus);
179      cpu_to_le32s(&reply->IOCLogInfo);
180  }
181  
182  void mptsas_fix_event_notification_endianness(MPIMsgEventNotify *req)
183  {
184      le32_to_cpus(&req->MsgContext);
185  }
186  
187  void mptsas_fix_event_notification_reply_endianness(MPIMsgEventNotifyReply *reply)
188  {
189      int length = reply->EventDataLength;
190      int i;
191  
192      cpu_to_le16s(&reply->EventDataLength);
193      cpu_to_le32s(&reply->MsgContext);
194      cpu_to_le16s(&reply->IOCStatus);
195      cpu_to_le32s(&reply->IOCLogInfo);
196      cpu_to_le32s(&reply->Event);
197      cpu_to_le32s(&reply->EventContext);
198  
199      /* Really depends on the event kind.  This will do for now.  */
200      for (i = 0; i < length; i++) {
201          cpu_to_le32s(&reply->Data[i]);
202      }
203  }
204  
205