Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: sas_cnfg.cc | |
4 | // Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
5 | // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. | |
6 | // | |
7 | // The above named program is free software; you can redistribute it and/or | |
8 | // modify it under the terms of the GNU General Public | |
9 | // License version 2 as published by the Free Software Foundation. | |
10 | // | |
11 | // The above named program is distributed in the hope that it will be | |
12 | // useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | // General Public License for more details. | |
15 | // | |
16 | // You should have received a copy of the GNU General Public | |
17 | // License along with this work; if not, write to the Free Software | |
18 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
19 | // | |
20 | // ========== Copyright Header End ============================================ | |
21 | /* | |
22 | * "sas_cnfg.cc" LSI SAS1064E PCIE to 4-Port Serial Attached | |
23 | * SCSI Controller Simulator | |
24 | * SAS controller configuration | |
25 | * | |
26 | * Copyright (C) 2007 Sun Microsystems, Inc. | |
27 | * All rights reserved. | |
28 | * | |
29 | */ | |
30 | #include "sas.h" | |
31 | ||
32 | ||
33 | // 64-bit base SAS address, each port will be assigned | |
34 | // a consecutive value starting from this one. | |
35 | #define SAS_ADDRESS_LOW 0x12345678 | |
36 | #define SAS_ADDRESS_HIGH 0x9abcdef0 | |
37 | ||
38 | // device handle for the controller | |
39 | #define CNTL_DEV_HANDLE 0x1000 | |
40 | ||
41 | // device handles for devices attached to ports | |
42 | #define CHILD_DEV0_HANDLE 0x1001 | |
43 | #define CHILD_DEV1_HANDLE (CHILD_DEV0_HANDLE + 1) | |
44 | #define CHILD_DEV2_HANDLE (CHILD_DEV0_HANDLE + 2) | |
45 | #define CHILD_DEV3_HANDLE (CHILD_DEV0_HANDLE + 3) | |
46 | ||
47 | ||
48 | // manufacturing pages | |
49 | static config_page_header_t manufacturing_page_headers[8] = { | |
50 | {1, 19, 0, 0x39}, | |
51 | {1, 65, 1, 0x39}, | |
52 | {1, 3, 2, 0x39}, | |
53 | {1, 3, 3, 0x39}, | |
54 | {1, 21, 4, 0x39}, | |
55 | {1, 3, 5, 0x39}, | |
56 | {1, 2, 6, 0x39}, | |
57 | {1, 15, 7, 0x39}, | |
58 | }; | |
59 | ||
60 | ||
61 | static config_page_manufacturing_5_t config_page_manufacturing_5 = { | |
62 | {1, 3, 5, 0x39}, | |
63 | SAS_ADDRESS_LOW, | |
64 | SAS_ADDRESS_HIGH, | |
65 | }; | |
66 | ||
67 | ||
68 | // ioc pages | |
69 | static config_page_header_t ioc_page_headers[7] = { | |
70 | {1, 7, 0, 0x31}, | |
71 | {1, 4, 1, 0x21}, | |
72 | {1, 5, 2, 0x31}, | |
73 | {1, 3, 3, 0x31}, | |
74 | {1, 3, 4, 0x21}, | |
75 | {1, 4, 5, 0x31}, | |
76 | {1, 15, 6, 0x31}, | |
77 | }; | |
78 | ||
79 | ||
80 | static config_page_ioc_1_t config_page_ioc_1 = { | |
81 | {1, 4, 1, 0x21}, | |
82 | 0, 0, 0, 1, | |
83 | {0, 0}, | |
84 | }; | |
85 | ||
86 | ||
87 | static config_page_ioc_2_t config_page_ioc_2 = { | |
88 | {1, 5, 2, 0x31}, | |
89 | 0, 0, 0, 0, 0, | |
90 | {0, 0, 0, 0, 0, 0, 0}, | |
91 | }; | |
92 | ||
93 | ||
94 | // SAS io unit pages | |
95 | static config_extended_page_header sas_io_unit_page_headers[2] = { | |
96 | {1, 0, 0, 0x3f, 20, 0x10, 0}, | |
97 | {1, 0, 1, 0x3f, 17, 0x10, 0}, | |
98 | }; | |
99 | ||
100 | ||
101 | static config_page_sas_io_unit_0_t config_page_sas_io_unit_0 = { | |
102 | {1, 0, 0, 0x3f, 20, 0x10, 0}, | |
103 | 0, 4, 0, 0, | |
104 | {0, 0, 0, 0, 0x1c01, CHILD_DEV0_HANDLE, CNTL_DEV_HANDLE, 0}, | |
105 | }; | |
106 | ||
107 | ||
108 | // SAS device pages | |
109 | static config_extended_page_header sas_device_page_headers[2] = { | |
110 | {1, 0, 0, 0x3f, 9, 0x12, 0}, | |
111 | {1, 0, 1, 0x3f, 12, 0x12, 0}, | |
112 | }; | |
113 | ||
114 | ||
115 | static config_page_sas_device_0_t config_page_sas_device_0 = { | |
116 | {1, 0, 0, 0x3f, 9, 0x12, 0}, | |
117 | 0, | |
118 | SAS_ADDRESS_LOW, | |
119 | SAS_ADDRESS_HIGH, | |
120 | 0, | |
121 | CHILD_DEV0_HANDLE, | |
122 | 0, 0, // target, bus | |
123 | 0x1c01, // device info | |
124 | 0x7, // flags | |
125 | 0, // physical port | |
126 | 0, | |
127 | }; | |
128 | ||
129 | ||
130 | // SAS phy pages | |
131 | static config_extended_page_header sas_phy_page_headers[2] = { | |
132 | {1, 0, 0, 0x3f, 9, 0x13, 0}, | |
133 | {1, 0, 1, 0x3f, 7, 0x13, 0}, | |
134 | }; | |
135 | ||
136 | ||
137 | static config_page_sas_phy_0_t config_page_sas_phy_0 = { | |
138 | {1, 0, 0, 0x3f, 9, 0x13, 0}, | |
139 | 0, | |
140 | SAS_ADDRESS_LOW, | |
141 | SAS_ADDRESS_HIGH, | |
142 | CHILD_DEV0_HANDLE, | |
143 | 0x11, // attached phy identifier | |
144 | 0, | |
145 | 0x1c01, // device info | |
146 | 0x0909, // programmed link rate | |
147 | 0x0909, // hw link rate | |
148 | 0, // change count | |
149 | 0, | |
150 | 0x0909, // phy info | |
151 | }; | |
152 | ||
153 | ||
154 | void SAS::send_page_reply(msg_config_t *req, msg_config_reply_t *reply, config_page_header_t *page_header) { | |
155 | ||
156 | reply->Action = req->Action; | |
157 | reply->MsgLength = sizeof(msg_config_reply_t) >> 2; | |
158 | reply->Function = req->Function; | |
159 | reply->ExtPageLength = 0; | |
160 | reply->ExtPageType = 0; | |
161 | reply->MsgFlags = 0; | |
162 | reply->MsgContext = req->MsgContext; | |
163 | reply->IOCStatus = SAM_LE_16(MPI_IOCSTATUS_SUCCESS); | |
164 | reply->IOCLogInfo = 0; | |
165 | reply->Header.PageVersion = page_header->PageVersion; | |
166 | reply->Header.PageLength = page_header->PageLength; | |
167 | reply->Header.PageNumber = page_header->PageNumber; | |
168 | reply->Header.PageType = page_header->PageType; | |
169 | ||
170 | send_handshake_msg(); | |
171 | } | |
172 | ||
173 | ||
174 | void SAS::send_extended_page_reply(msg_config_t *req, msg_config_reply_t *reply, | |
175 | config_extended_page_header *extended_page_header, bool invalid) { | |
176 | reply->Action = req->Action; | |
177 | reply->MsgLength = sizeof(msg_config_reply_t) >> 2; | |
178 | reply->Function = req->Function; | |
179 | reply->ExtPageLength = SAM_LE_16(extended_page_header->ExtPageLength); | |
180 | reply->ExtPageType = extended_page_header->ExtPageType; | |
181 | reply->MsgFlags = 0; | |
182 | reply->MsgContext = req->MsgContext; | |
183 | reply->IOCStatus = SAM_LE_16(invalid ? MPI_IOCSTATUS_CONFIG_INVALID_PAGE : MPI_IOCSTATUS_SUCCESS); | |
184 | reply->IOCLogInfo = 0; | |
185 | reply->Header.PageVersion = extended_page_header->PageVersion; | |
186 | reply->Header.PageLength = 0; | |
187 | reply->Header.PageNumber = extended_page_header->PageNumber; | |
188 | reply->Header.PageType = extended_page_header->PageType; | |
189 | ||
190 | send_handshake_msg(); | |
191 | } | |
192 | ||
193 | ||
194 | // Access manufacturing pages | |
195 | void SAS::access_page_manufacturing(msg_config_t *req, msg_config_reply_t *reply) { | |
196 | config_page_manufacturing_5_t *page_5; | |
197 | ||
198 | uint8_t page_no = req->Header.PageNumber; | |
199 | uint8_t sge_flags = req->PageBufferSGE.u1.Simple.FlagsLength >> MPI_SGE_FLAGS_SHIFT; | |
200 | ||
201 | switch (req->Action) { | |
202 | case MPI_CONFIG_ACTION_PAGE_HEADER: | |
203 | send_page_reply(req, reply, &manufacturing_page_headers[page_no]); | |
204 | break; | |
205 | ||
206 | case MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT: | |
207 | case MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM: | |
208 | debug_err("%s: manufacturing page write is not support yet\n", getName()); | |
209 | exit(1); | |
210 | ||
211 | case MPI_CONFIG_ACTION_PAGE_READ_CURRENT: | |
212 | case MPI_CONFIG_ACTION_PAGE_READ_NVRAM: | |
213 | if ((sge_flags & MPI_SGE_FLAGS_ELEMENT_TYPE_MASK) == | |
214 | MPI_SGE_FLAGS_SIMPLE_ELEMENT) { | |
215 | ||
216 | if (page_no == 5) { | |
217 | // allocate space for page | |
218 | page_5 = (config_page_manufacturing_5_t *)calloc(1, sizeof(config_page_manufacturing_5_t)); | |
219 | bcopy(&config_page_manufacturing_5, page_5, sizeof(config_page_manufacturing_5_t)); | |
220 | page_5->BaseWWID_L = SAM_LE_32(page_5->BaseWWID_L); | |
221 | page_5->BaseWWID_H = SAM_LE_32(page_5->BaseWWID_H); | |
222 | ||
223 | // move the page to the main memory | |
224 | memory_transport((void *)&(req->PageBufferSGE), (void*)page_5, | |
225 | sizeof(config_page_manufacturing_5_t), true); | |
226 | ||
227 | // reply message | |
228 | send_page_reply(req, reply, &manufacturing_page_headers[page_no]); | |
229 | ||
230 | free(page_5); | |
231 | } | |
232 | else { | |
233 | debug_err("%s: manufacturing page read is not supported yet\n", getName()); | |
234 | exit(1); | |
235 | } | |
236 | } | |
237 | else { | |
238 | debug_err("%s: page buffer SGE is not simple element\n", getName()); | |
239 | exit(1); | |
240 | } | |
241 | ||
242 | break; | |
243 | ||
244 | case MPI_CONFIG_ACTION_PAGE_DEFAULT: | |
245 | case MPI_CONFIG_ACTION_PAGE_READ_DEFAULT: | |
246 | debug_err("%s: manufacturing page default is not supported yet\n", getName()); | |
247 | exit(1); | |
248 | ||
249 | default: | |
250 | debug_err("%s: unknown page configuration action\n", getName()); | |
251 | exit(1); | |
252 | } | |
253 | ||
254 | return; | |
255 | } | |
256 | ||
257 | ||
258 | // Access ioc pages | |
259 | void SAS::access_page_ioc(msg_config_t *req, msg_config_reply_t *reply) { | |
260 | config_page_ioc_1_t *page_1; | |
261 | config_page_ioc_2_t *page_2; | |
262 | ||
263 | uint8_t page_no = req->Header.PageNumber; | |
264 | uint8_t sge_flags = req->PageBufferSGE.u1.Simple.FlagsLength >> MPI_SGE_FLAGS_SHIFT; | |
265 | ||
266 | switch (req->Action) { | |
267 | case MPI_CONFIG_ACTION_PAGE_HEADER: | |
268 | send_page_reply(req, reply, &ioc_page_headers[page_no]); | |
269 | break; | |
270 | ||
271 | case MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT: | |
272 | case MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM: | |
273 | if ((sge_flags & MPI_SGE_FLAGS_ELEMENT_TYPE_MASK) == | |
274 | MPI_SGE_FLAGS_SIMPLE_ELEMENT) { | |
275 | ||
276 | if (page_no == 1) { | |
277 | // allocate space for page | |
278 | page_1 = (config_page_ioc_1_t *)calloc(1, sizeof(config_page_ioc_1_t)); | |
279 | ||
280 | // move the page from the main memory | |
281 | memory_transport((void *)&(req->PageBufferSGE), (void*)page_1, | |
282 | sizeof(config_page_ioc_1_t), false); | |
283 | ||
284 | page_1->Flags = SAM_LE_32(page_1->Flags); | |
285 | page_1->CoalescingTimeout = SAM_LE_32(page_1->CoalescingTimeout); | |
286 | bcopy(page_1, &config_page_ioc_1, sizeof(config_page_ioc_1_t)); | |
287 | ||
288 | // reply message | |
289 | send_page_reply(req, reply, &ioc_page_headers[page_no]); | |
290 | ||
291 | free(page_1); | |
292 | } | |
293 | else { | |
294 | debug_err("%s: ioc pages write is not supported yet\n", getName()); | |
295 | exit(1); | |
296 | } | |
297 | } | |
298 | else { | |
299 | debug_err("%s: page buffer SGE is not simple element\n", getName()); | |
300 | exit(1); | |
301 | } | |
302 | ||
303 | break; | |
304 | ||
305 | case MPI_CONFIG_ACTION_PAGE_READ_CURRENT: | |
306 | case MPI_CONFIG_ACTION_PAGE_READ_NVRAM: | |
307 | if ((sge_flags & MPI_SGE_FLAGS_ELEMENT_TYPE_MASK) == | |
308 | MPI_SGE_FLAGS_SIMPLE_ELEMENT) { | |
309 | ||
310 | switch (page_no) { | |
311 | case 1: | |
312 | // allocate space for page | |
313 | page_1 = (config_page_ioc_1_t *)calloc(1, sizeof(config_page_ioc_1_t)); | |
314 | bcopy(&config_page_ioc_1, page_1, sizeof(config_page_ioc_1_t)); | |
315 | page_1->Flags = SAM_LE_32(page_1->Flags); | |
316 | page_1->CoalescingTimeout = SAM_LE_32(page_1->CoalescingTimeout); | |
317 | ||
318 | // move the page to the main memory | |
319 | memory_transport((void *)&(req->PageBufferSGE), (void*)page_1, | |
320 | sizeof(config_page_ioc_1_t), true); | |
321 | ||
322 | // reply message | |
323 | send_page_reply(req, reply, &ioc_page_headers[page_no]); | |
324 | ||
325 | free(page_1); | |
326 | ||
327 | break; | |
328 | ||
329 | case 2: | |
330 | // allocate space for page | |
331 | page_2 = (config_page_ioc_2_t *)calloc(1, sizeof(config_page_ioc_2_t)); | |
332 | bcopy(&config_page_ioc_2, page_2, sizeof(config_page_ioc_2_t)); | |
333 | page_2->CapabilitiesFlags = SAM_LE_32(page_2->CapabilitiesFlags); | |
334 | ||
335 | // move the page to the main memory | |
336 | memory_transport((void *)&(req->PageBufferSGE), (void*)page_2, | |
337 | sizeof(config_page_ioc_2_t), true); | |
338 | ||
339 | // reply message | |
340 | send_page_reply(req, reply, &ioc_page_headers[page_no]); | |
341 | ||
342 | free(page_2); | |
343 | ||
344 | break; | |
345 | ||
346 | default: | |
347 | debug_err("%s: ioc page read is not supported yet\n", getName()); | |
348 | exit(1); | |
349 | } | |
350 | } | |
351 | else { | |
352 | debug_err("%s: page buffer SGE is not simple element\n", getName()); | |
353 | exit(1); | |
354 | } | |
355 | ||
356 | break; | |
357 | ||
358 | case MPI_CONFIG_ACTION_PAGE_DEFAULT: | |
359 | case MPI_CONFIG_ACTION_PAGE_READ_DEFAULT: | |
360 | debug_err("%s: ioc page default is not supported yet\n", getName()); | |
361 | exit(1); | |
362 | ||
363 | default: | |
364 | debug_err("%s: unknown page configuration action\n", getName()); | |
365 | exit(1); | |
366 | } | |
367 | ||
368 | return; | |
369 | } | |
370 | ||
371 | ||
372 | // Access sas io unit page | |
373 | void SAS::access_page_sas_io_unit(msg_config_t *req, msg_config_reply_t *reply) { | |
374 | config_page_sas_io_unit_0_t *page_0; | |
375 | ||
376 | uint8_t page_no = req->Header.PageNumber; | |
377 | uint8_t sge_flags = req->PageBufferSGE.u1.Simple.FlagsLength >> MPI_SGE_FLAGS_SHIFT; | |
378 | ||
379 | switch (req->Action) { | |
380 | case MPI_CONFIG_ACTION_PAGE_HEADER: { | |
381 | send_extended_page_reply(req, reply, &sas_io_unit_page_headers[page_no], false); | |
382 | break; | |
383 | } | |
384 | ||
385 | case MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT: | |
386 | case MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM: | |
387 | debug_err("%s: sas io unit page write is not support yet\n", getName()); | |
388 | exit(1); | |
389 | ||
390 | case MPI_CONFIG_ACTION_PAGE_READ_CURRENT: | |
391 | case MPI_CONFIG_ACTION_PAGE_READ_NVRAM: { | |
392 | // some times the driver forgets to set flag, just treat it as Simple Element | |
393 | if ((sge_flags & MPI_SGE_FLAGS_ELEMENT_TYPE_MASK) == 0) { | |
394 | debug_info("%s: flag of page buffer SGE in IO UNIT request is 0, change it to 1\n", getName()); | |
395 | sge_flags |= MPI_SGE_FLAGS_SIMPLE_ELEMENT; | |
396 | req->PageBufferSGE.u1.Simple.FlagsLength |= (MPI_SGE_FLAGS_SIMPLE_ELEMENT << MPI_SGE_FLAGS_SHIFT); | |
397 | } | |
398 | ||
399 | if ((sge_flags & MPI_SGE_FLAGS_ELEMENT_TYPE_MASK) == | |
400 | MPI_SGE_FLAGS_SIMPLE_ELEMENT) { | |
401 | if (page_no == 0) { | |
402 | page_0 = (config_page_sas_io_unit_0_t *)calloc(1, sizeof(config_page_sas_io_unit_0_t) + | |
403 | sizeof(mpi_sas_io_unit0_phy_data_t) * 3); | |
404 | bcopy(&config_page_sas_io_unit_0, page_0, sizeof(config_page_sas_io_unit_0_t)); | |
405 | page_0->Header.ExtPageLength = SAM_LE_16(page_0->Header.ExtPageLength); | |
406 | ||
407 | // construct information for all ports | |
408 | for (int i = 0; i < IOC_NUM_PORTS; i++) { | |
409 | bcopy(&config_page_sas_io_unit_0.PhyData[0], | |
410 | &page_0->PhyData[i], sizeof(mpi_sas_io_unit0_phy_data_t)); | |
411 | ||
412 | page_0->PhyData[i].Port = i; | |
413 | page_0->PhyData[i].AttachedDeviceHandle = SAM_LE_16(CHILD_DEV0_HANDLE + i); | |
414 | page_0->PhyData[i].ControllerDevHandle = SAM_LE_16(CNTL_DEV_HANDLE); | |
415 | ||
416 | if (_disk[i] == NULL) | |
417 | page_0->PhyData[i].ControllerPhyDeviceInfo = | |
418 | SAM_LE_32(page_0->PhyData[i].ControllerPhyDeviceInfo & ~3); | |
419 | else | |
420 | page_0->PhyData[i].ControllerPhyDeviceInfo = | |
421 | SAM_LE_32(page_0->PhyData[i].ControllerPhyDeviceInfo); | |
422 | } | |
423 | ||
424 | // move the page to the main memory | |
425 | memory_transport((void *)&(req->PageBufferSGE), (void*)page_0, | |
426 | sizeof(config_page_sas_io_unit_0_t) + sizeof(mpi_sas_io_unit0_phy_data_t) * 3, true); | |
427 | ||
428 | // reply message | |
429 | send_extended_page_reply(req, reply, &sas_io_unit_page_headers[page_no], false); | |
430 | ||
431 | free(page_0); | |
432 | } | |
433 | else { | |
434 | debug_err("%s: sas ioc unit page read not supported yet\n", getName()); | |
435 | exit(1); | |
436 | } | |
437 | } | |
438 | ||
439 | break; | |
440 | } | |
441 | ||
442 | case MPI_CONFIG_ACTION_PAGE_DEFAULT: | |
443 | case MPI_CONFIG_ACTION_PAGE_READ_DEFAULT: | |
444 | debug_err("%s: sas io unit page default is not supported yet\n", getName()); | |
445 | exit(1); | |
446 | ||
447 | default: | |
448 | debug_err("%s: unknown page configuration action\n", getName()); | |
449 | exit(1); | |
450 | } | |
451 | } | |
452 | ||
453 | ||
454 | // Access sas device pages | |
455 | // Page address can be one of three formats: get_next_handle, bus_target_id, and handle | |
456 | void SAS::access_page_sas_device(msg_config_t *req, msg_config_reply_t *reply) { | |
457 | config_page_sas_device_0_t *page_0; | |
458 | ||
459 | uint8_t page_no = req->Header.PageNumber; | |
460 | uint8_t sge_flags = req->PageBufferSGE.u1.Simple.FlagsLength >> MPI_SGE_FLAGS_SHIFT; | |
461 | ||
462 | uint16_t handle; | |
463 | uint8_t bus, target; | |
464 | bool invalid = false; | |
465 | ||
466 | // find the target | |
467 | switch ((req->PageAddress & MPI_SAS_DEVICE_PGAD_FORM_MASK) >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT) { | |
468 | case MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE: { | |
469 | handle = (req->PageAddress & MPI_SAS_DEVICE_PGAD_GNH_HANDLE_MASK) >> MPI_SAS_DEVICE_PGAD_GNH_HANDLE_SHIFT; | |
470 | ||
471 | if (handle == 0xffff) | |
472 | target = 0; | |
473 | else if (handle >= CHILD_DEV0_HANDLE && handle < CHILD_DEV3_HANDLE) | |
474 | target = handle - CHILD_DEV0_HANDLE + 1; | |
475 | else | |
476 | invalid = true; | |
477 | ||
478 | if (!invalid) { | |
479 | int i; | |
480 | for (i = target; i < IOC_NUM_PORTS; i++) | |
481 | if (_disk[i]) | |
482 | break; | |
483 | ||
484 | if (i < IOC_NUM_PORTS) | |
485 | target = i; | |
486 | else | |
487 | invalid = true; | |
488 | } | |
489 | ||
490 | break; | |
491 | } | |
492 | ||
493 | case MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID: { | |
494 | bus = (req->PageAddress & MPI_SAS_DEVICE_PGAD_BT_BUS_MASK) >> MPI_SAS_DEVICE_PGAD_BT_BUS_SHIFT; | |
495 | target = (req->PageAddress & MPI_SAS_DEVICE_PGAD_BT_TID_MASK) >> MPI_SAS_DEVICE_PGAD_BT_TID_SHIFT; | |
496 | ||
497 | if (bus != 0 || target > IOC_NUM_PORTS) | |
498 | invalid = true; | |
499 | ||
500 | if (!invalid) | |
501 | if (!_disk[target]) | |
502 | invalid = true; | |
503 | ||
504 | break; | |
505 | } | |
506 | ||
507 | case MPI_SAS_DEVICE_PGAD_FORM_HANDLE: { | |
508 | handle = (req->PageAddress & MPI_SAS_DEVICE_PGAD_GNH_HANDLE_MASK) >> MPI_SAS_DEVICE_PGAD_GNH_HANDLE_SHIFT; | |
509 | ||
510 | if (handle >= CHILD_DEV0_HANDLE && handle <= CHILD_DEV3_HANDLE) | |
511 | target = handle - CHILD_DEV0_HANDLE; | |
512 | else | |
513 | invalid = true; | |
514 | ||
515 | if (!invalid) | |
516 | if (!_disk[target]) | |
517 | invalid = true; | |
518 | ||
519 | break; | |
520 | ||
521 | } | |
522 | ||
523 | default: | |
524 | debug_err("%s: unknown sas device page address format\n", getName()); | |
525 | exit(1); | |
526 | } | |
527 | ||
528 | switch (req->Action) { | |
529 | case MPI_CONFIG_ACTION_PAGE_HEADER: { | |
530 | send_extended_page_reply(req, reply, &sas_device_page_headers[page_no], invalid); | |
531 | break; | |
532 | } | |
533 | ||
534 | case MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT: | |
535 | case MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM: | |
536 | debug_err("%s: sas device page write is not support yet\n", getName()); | |
537 | exit(1); | |
538 | ||
539 | case MPI_CONFIG_ACTION_PAGE_READ_CURRENT: | |
540 | case MPI_CONFIG_ACTION_PAGE_READ_NVRAM: { | |
541 | if (invalid) { | |
542 | send_extended_page_reply(req, reply, &sas_device_page_headers[page_no], true); | |
543 | } | |
544 | else { | |
545 | // some times the driver forgets to set flag, just treat it as Simple Element | |
546 | if ((sge_flags & MPI_SGE_FLAGS_ELEMENT_TYPE_MASK) == 0) { | |
547 | debug_info("%s: flag of page buffer SGE in DEVICE request is 0, change it to 1\n", getName()); | |
548 | sge_flags |= MPI_SGE_FLAGS_SIMPLE_ELEMENT; | |
549 | req->PageBufferSGE.u1.Simple.FlagsLength |= (MPI_SGE_FLAGS_SIMPLE_ELEMENT << MPI_SGE_FLAGS_SHIFT); | |
550 | } | |
551 | ||
552 | if ((sge_flags & MPI_SGE_FLAGS_ELEMENT_TYPE_MASK) == | |
553 | MPI_SGE_FLAGS_SIMPLE_ELEMENT) { | |
554 | ||
555 | if (page_no == 0) { | |
556 | // allocate space for page | |
557 | page_0 = (config_page_sas_device_0_t *)calloc(1, sizeof(config_page_sas_device_0_t)); | |
558 | bcopy(&config_page_sas_device_0, page_0, sizeof(config_page_sas_device_0_t)); | |
559 | page_0->Header.ExtPageLength = SAM_LE_16(page_0->Header.ExtPageLength); | |
560 | ||
561 | page_0->SASAddress_L = SAM_LE_32(page_0->SASAddress_L + target); | |
562 | page_0->SASAddress_H = SAM_LE_32(page_0->SASAddress_H); | |
563 | page_0->DevHandle = SAM_LE_16(page_0->DevHandle + target); | |
564 | page_0->TargetID = target; | |
565 | page_0->Bus = 0; | |
566 | page_0->DeviceInfo = SAM_LE_32(page_0->DeviceInfo); | |
567 | page_0->Flags = SAM_LE_16(page_0->Flags); | |
568 | ||
569 | // move the page to the main memory | |
570 | memory_transport((void *)&(req->PageBufferSGE), (void*)page_0, | |
571 | sizeof(config_page_sas_device_0_t), true); | |
572 | ||
573 | // reply message | |
574 | send_extended_page_reply(req, reply, &sas_device_page_headers[page_no], false); | |
575 | ||
576 | free(page_0); | |
577 | } | |
578 | else { | |
579 | debug_err("%s: sas device page write read not supported yet\n", getName()); | |
580 | exit(1); | |
581 | } | |
582 | } | |
583 | else { | |
584 | debug_err("%s: page buffer SGE is not simple element\n", getName()); | |
585 | exit(1); | |
586 | } | |
587 | } | |
588 | ||
589 | break; | |
590 | } | |
591 | ||
592 | case MPI_CONFIG_ACTION_PAGE_DEFAULT: | |
593 | case MPI_CONFIG_ACTION_PAGE_READ_DEFAULT: | |
594 | debug_err("%s: sas device page default is not supported yet\n", getName()); | |
595 | exit(1); | |
596 | ||
597 | default: | |
598 | debug_err("%s: unknown page configuration action\n", getName()); | |
599 | exit(1); | |
600 | } | |
601 | ||
602 | return; | |
603 | } | |
604 | ||
605 | ||
606 | // Access sas phy pages | |
607 | // Note: 1. it is a mistake that the driver use the same page address format as sas device pages. | |
608 | // 2. sas phy pages are not used by the new version of mpt driver any more. | |
609 | void SAS::access_page_sas_phy(msg_config_t *req, msg_config_reply_t *reply) { | |
610 | config_page_sas_phy_0_t *page_0; | |
611 | ||
612 | uint8_t page_no = req->Header.PageNumber; | |
613 | uint8_t sge_flags = req->PageBufferSGE.u1.Simple.FlagsLength >> MPI_SGE_FLAGS_SHIFT; | |
614 | ||
615 | uint16_t phynum; | |
616 | uint8_t bus, target; | |
617 | bool invalid = false; | |
618 | ||
619 | // find the target | |
620 | switch ((req->PageAddress & MPI_SAS_DEVICE_PGAD_FORM_MASK) >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT) { | |
621 | case MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE: { | |
622 | phynum = (req->PageAddress & MPI_SAS_PHY_PGAD_PHY_NUMBER_MASK) >> MPI_SAS_PHY_PGAD_PHY_NUMBER_SHIFT; | |
623 | ||
624 | if (phynum >= 0 && phynum < IOC_NUM_PORTS) | |
625 | target = phynum; | |
626 | else | |
627 | invalid = true; | |
628 | ||
629 | if (!invalid) { | |
630 | if (!_disk[target]) | |
631 | invalid = true; | |
632 | } | |
633 | ||
634 | break; | |
635 | } | |
636 | ||
637 | case MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID: { | |
638 | bus = (req->PageAddress & MPI_SAS_DEVICE_PGAD_BT_BUS_MASK) >> MPI_SAS_DEVICE_PGAD_BT_BUS_SHIFT; | |
639 | target = (req->PageAddress & MPI_SAS_DEVICE_PGAD_BT_TID_MASK) >> MPI_SAS_DEVICE_PGAD_BT_TID_SHIFT; | |
640 | ||
641 | if (bus != 0 || target > IOC_NUM_PORTS) | |
642 | invalid = true; | |
643 | ||
644 | if (!invalid) | |
645 | if (!_disk[target]) | |
646 | invalid = true; | |
647 | ||
648 | break; | |
649 | } | |
650 | ||
651 | default: | |
652 | debug_err("%s: unknown sas phy page address format\n", getName()); | |
653 | exit(1); | |
654 | } | |
655 | ||
656 | switch (req->Action) { | |
657 | case MPI_CONFIG_ACTION_PAGE_HEADER: | |
658 | send_extended_page_reply(req, reply, &sas_phy_page_headers[page_no], invalid); | |
659 | break; | |
660 | ||
661 | case MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT: | |
662 | case MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM: | |
663 | debug_err("%s: sas phy page write is not support yet\n", getName()); | |
664 | exit(1); | |
665 | ||
666 | case MPI_CONFIG_ACTION_PAGE_READ_CURRENT: | |
667 | case MPI_CONFIG_ACTION_PAGE_READ_NVRAM: { | |
668 | // some times the driver forgot to set flag, just treat it as Simple Element | |
669 | if ((sge_flags & MPI_SGE_FLAGS_ELEMENT_TYPE_MASK) == 0) { | |
670 | debug_info("%s: flag of page buffer SGE in PHY request is 0, change it to 1\n", getName()); | |
671 | sge_flags |= MPI_SGE_FLAGS_SIMPLE_ELEMENT; | |
672 | req->PageBufferSGE.u1.Simple.FlagsLength |= (MPI_SGE_FLAGS_SIMPLE_ELEMENT << MPI_SGE_FLAGS_SHIFT); | |
673 | } | |
674 | ||
675 | if ((sge_flags & MPI_SGE_FLAGS_ELEMENT_TYPE_MASK) == | |
676 | MPI_SGE_FLAGS_SIMPLE_ELEMENT) { | |
677 | ||
678 | // even for invalid target, page is still moved to the main memory, | |
679 | // but with some fields set to invalid. | |
680 | if (page_no == 0) { | |
681 | // allocate space for page | |
682 | page_0 = (config_page_sas_phy_0_t *)calloc(1, sizeof(config_page_sas_phy_0_t)); | |
683 | bcopy(&config_page_sas_phy_0, page_0, sizeof(config_page_sas_phy_0_t)); | |
684 | page_0->Header.ExtPageLength = SAM_LE_16(page_0->Header.ExtPageLength); | |
685 | page_0->SASAddress_L = SAM_LE_32(invalid ? 0 : page_0->SASAddress_L + target); | |
686 | page_0->SASAddress_H = SAM_LE_32(invalid ? 0 : page_0->SASAddress_H); | |
687 | page_0->AttachedDevHandle = SAM_LE_16(invalid ? 0 : page_0->AttachedDevHandle + target); | |
688 | page_0->AttachedDeviceInfo = SAM_LE_32(invalid ? 0 : page_0->AttachedDeviceInfo); | |
689 | page_0->PhyInfo = SAM_LE_32(page_0->PhyInfo); | |
690 | ||
691 | // move the page to the main memory | |
692 | memory_transport((void *)&(req->PageBufferSGE), (void*)page_0, | |
693 | sizeof(config_page_sas_phy_0_t), true); | |
694 | ||
695 | // reply message | |
696 | send_extended_page_reply(req, reply, &sas_phy_page_headers[page_no], invalid); | |
697 | ||
698 | free(page_0); | |
699 | } | |
700 | else { | |
701 | debug_err("%s: sas phy page read is not supported yet\n", getName()); | |
702 | exit(1); | |
703 | } | |
704 | } | |
705 | else { | |
706 | debug_err("%s: page buffer SGE is not simple element\n", getName()); | |
707 | exit(1); | |
708 | } | |
709 | ||
710 | break; | |
711 | } | |
712 | ||
713 | case MPI_CONFIG_ACTION_PAGE_DEFAULT: | |
714 | case MPI_CONFIG_ACTION_PAGE_READ_DEFAULT: | |
715 | debug_err("%s: sas phy page default is not supported yet\n", getName()); | |
716 | exit(1); | |
717 | ||
718 | default: | |
719 | debug_err("%s: unknown page configuration action\n", getName()); | |
720 | exit(1); | |
721 | } | |
722 | ||
723 | return; | |
724 | } |