Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / sas / sas_cnfg.cc
CommitLineData
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
49static 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
61static 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
69static 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
80static 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
87static 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
95static 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
101static 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
109static 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
115static 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
131static 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
137static 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
154void 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
174void 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
195void 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
259void 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
373void 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
456void 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.
609void 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}