1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0 3 * 4 * This file is provided under a dual BSD/GPLv2 license. When using or 5 * redistributing this file, you may do so under either license. 6 * 7 * GPL LICENSE SUMMARY 8 * 9 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of version 2 of the GNU General Public License as 13 * published by the Free Software Foundation. 14 * 15 * This program is distributed in the hope that it will be useful, but 16 * WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 23 * The full GNU General Public License is included in this distribution 24 * in the file called LICENSE.GPL. 25 * 26 * BSD LICENSE 27 * 28 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 29 * All rights reserved. 30 * 31 * Redistribution and use in source and binary forms, with or without 32 * modification, are permitted provided that the following conditions 33 * are met: 34 * 35 * * Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * * Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditions and the following disclaimer in 39 * the documentation and/or other materials provided with the 40 * distribution. 41 * 42 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 43 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 44 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 45 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 46 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 47 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 48 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 49 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 50 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 51 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 52 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53 */ 54 #ifndef _SCIC_SDS_PORT_H_ 55 #define _SCIC_SDS_PORT_H_ 56 57 #ifdef __cplusplus 58 extern "C" { 59 #endif // __cplusplus 60 61 /** 62 * @file 63 * 64 * @brief This file contains the structures, constants and prototypes for the 65 * SCIC_SDS_PORT_T object. 66 */ 67 68 #include <dev/isci/scil/sci_controller_constants.h> 69 #include <dev/isci/scil/intel_sas.h> 70 #include <dev/isci/scil/sci_base_port.h> 71 #include <dev/isci/scil/sci_base_phy.h> 72 #include <dev/isci/scil/scu_registers.h> 73 74 #define SCIC_SDS_DUMMY_PORT 0xFF 75 76 /** 77 * @enum SCIC_SDS_PORT_READY_SUBSTATES 78 * 79 * This enumeration depicts all of the states for the core port ready substate 80 * machine. 81 */ 82 enum SCIC_SDS_PORT_READY_SUBSTATES 83 { 84 /** 85 * The substate where the port is started and ready but has no active phys. 86 */ 87 SCIC_SDS_PORT_READY_SUBSTATE_WAITING, 88 89 /** 90 * The substate where the port is started and ready and there is at least one 91 * phy operational. 92 */ 93 SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL, 94 95 /** 96 * The substate where the port is started and there was an add/remove phy 97 * event. This state is only used in Automatic Port Configuration Mode (APC) 98 */ 99 SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING, 100 101 SCIC_SDS_PORT_READY_MAX_SUBSTATES 102 }; 103 104 struct SCIC_SDS_CONTROLLER; 105 struct SCIC_SDS_PHY; 106 struct SCIC_SDS_REMOTE_DEVICE; 107 struct SCIC_SDS_REQUEST; 108 109 /** 110 * @struct SCIC_SDS_PORT 111 * 112 * The core port object provides the abstraction for an SCU port. 113 */ 114 typedef struct SCIC_SDS_PORT 115 { 116 /** 117 * This field is the oommon base port object. 118 */ 119 SCI_BASE_PORT_T parent; 120 121 /** 122 * This field is the port index that is reported to the SCI USER. This allows 123 * the actual hardware physical port to change without the SCI USER getting a 124 * different answer for the get port index. 125 */ 126 U8 logical_port_index; 127 128 /** 129 * This field is the port index used to program the SCU hardware. 130 */ 131 U8 physical_port_index; 132 133 /** 134 * This field contains the active phy mask for the port. This mask is used in 135 * conjunction with the phy state to determine which phy to select for some 136 * port operations. 137 */ 138 U8 active_phy_mask; 139 140 /** 141 * This field contains the phy mask for the port that are already part of the port. 142 */ 143 U8 enabled_phy_mask; 144 145 U16 reserved_rni; 146 U16 reserved_tci; 147 148 /** 149 * This field contains the count of the io requests started on this port 150 * object. It is used to control controller shutdown. 151 */ 152 U32 started_request_count; 153 154 /** 155 * This field contains the number of devices assigned to this port. It is 156 * used to control port start requests. 157 */ 158 U32 assigned_device_count; 159 160 /** 161 * This field contains the reason for the port not going ready. It is 162 * assigned in the state handlers and used in the state transition. 163 */ 164 U32 not_ready_reason; 165 166 /** 167 * This field is the table of phys assigned to the port. 168 */ 169 struct SCIC_SDS_PHY *phy_table[SCI_MAX_PHYS]; 170 171 /** 172 * This field is a pointer back to the controller that owns this port object. 173 */ 174 struct SCIC_SDS_CONTROLLER *owning_controller; 175 176 /** 177 * This field contains the port start/stop timer handle. 178 */ 179 void *timer_handle; 180 181 /** 182 * This field points to the current set of state handlers for this port 183 * object. These state handlers are assigned at each enter state of the state 184 * machine. 185 */ 186 struct SCIC_SDS_PORT_STATE_HANDLER *state_handlers; 187 188 /** 189 * This field is the ready substate machine for the port. 190 */ 191 SCI_BASE_STATE_MACHINE_T ready_substate_machine; 192 193 #ifdef SCI_LOGGING 194 /** 195 * This field is the ready substate machine logger. It logs each state 196 * transition request in the ready substate machine. 197 */ 198 SCI_BASE_STATE_MACHINE_LOGGER_T ready_substate_machine_logger; 199 #endif 200 201 /// Memory mapped hardware register space 202 203 /** 204 * This field is the pointer to the port task scheduler registers for the SCU 205 * hardware. 206 */ 207 SCU_PORT_TASK_SCHEDULER_REGISTERS_T *port_task_scheduler_registers; 208 209 /** 210 * This field is identical for all port objects and points to the port task 211 * scheduler group PE configuration registers. It is used to assign PEs to a 212 * port. 213 */ 214 SCU_PORT_PE_CONFIGURATION_REGISTER_T *port_pe_configuration_register; 215 216 /** 217 * This field is the VIIT register space for this port object. 218 */ 219 SCU_VIIT_ENTRY_T *viit_registers; 220 221 } SCIC_SDS_PORT_T; 222 223 224 typedef SCI_STATUS (*SCIC_SDS_PORT_EVENT_HANDLER_T)(struct SCIC_SDS_PORT *, U32); 225 226 typedef SCI_STATUS (*SCIC_SDS_PORT_FRAME_HANDLER_T)(struct SCIC_SDS_PORT *, U32); 227 228 typedef void (*SCIC_SDS_PORT_LINK_HANDLER_T)(struct SCIC_SDS_PORT *, struct SCIC_SDS_PHY *); 229 230 typedef SCI_STATUS (*SCIC_SDS_PORT_IO_REQUEST_HANDLER_T)( 231 struct SCIC_SDS_PORT *, 232 struct SCIC_SDS_REMOTE_DEVICE *, 233 struct SCIC_SDS_REQUEST *); 234 235 typedef struct SCIC_SDS_PORT_STATE_HANDLER 236 { 237 SCI_BASE_PORT_STATE_HANDLER_T parent; 238 239 SCIC_SDS_PORT_FRAME_HANDLER_T frame_handler; 240 SCIC_SDS_PORT_EVENT_HANDLER_T event_handler; 241 242 SCIC_SDS_PORT_LINK_HANDLER_T link_up_handler; 243 SCIC_SDS_PORT_LINK_HANDLER_T link_down_handler; 244 245 SCIC_SDS_PORT_IO_REQUEST_HANDLER_T start_io_handler; 246 SCIC_SDS_PORT_IO_REQUEST_HANDLER_T complete_io_handler; 247 248 } SCIC_SDS_PORT_STATE_HANDLER_T; 249 250 extern SCI_BASE_STATE_T scic_sds_port_state_table[]; 251 extern SCI_BASE_STATE_T scic_sds_port_ready_substate_table[]; 252 253 extern SCIC_SDS_PORT_STATE_HANDLER_T scic_sds_port_state_handler_table[]; 254 extern SCIC_SDS_PORT_STATE_HANDLER_T scic_sds_port_ready_substate_handler_table[]; 255 256 /** 257 * Helper macro to get the owning controller of this port 258 */ 259 #define scic_sds_port_get_controller(this_port) \ 260 ((this_port)->owning_controller) 261 262 /** 263 * Helper macro to get the base state machine for this port 264 */ 265 #define scic_sds_port_get_base_state_machine(this_port) \ 266 (&(this_port)->parent.state_machine) 267 268 /** 269 * This macro will change the state handlers to those of the specified state 270 * id 271 */ 272 #define scic_sds_port_set_base_state_handlers(this_port, state_id) \ 273 scic_sds_port_set_state_handlers( \ 274 (this_port), &scic_sds_port_state_handler_table[(state_id)]) 275 276 /** 277 * Helper macro to get the ready substate machine for this port 278 */ 279 #define scic_sds_port_get_ready_substate_machine(this_port) \ 280 (&(this_port)->ready_substate_machine) 281 282 /** 283 * Helper macro to set the port object state handlers 284 */ 285 #define scic_sds_port_set_state_handlers(this_port, handlers) \ 286 ((this_port)->state_handlers = (handlers)) 287 288 /** 289 * This macro returns the physical port index for this port object 290 */ 291 #define scic_sds_port_get_index(this_port) \ 292 ((this_port)->physical_port_index) 293 294 /** 295 * Helper macro to increment the started request count 296 */ 297 #define scic_sds_port_increment_request_count(this_port) \ 298 ((this_port)->started_request_count++) 299 300 #ifdef SCIC_DEBUG_ENABLED 301 /** 302 * @brief This method decrements the started io request count. The method 303 * will not decrment the started io request count below 0 and will 304 * log a debug message if this is attempted. 305 * 306 * @param[in] this_port 307 */ 308 void scic_sds_port_decrement_request_count( 309 SCIC_SDS_PORT_T *this_port 310 ); 311 #else 312 /** 313 * Helper macro to decrement the started io request count. The macro will 314 * not decrement the started io request count below 0. 315 */ 316 #define scic_sds_port_decrement_request_count(this_port) \ 317 ( \ 318 (this_port)->started_request_count = ( \ 319 ((this_port)->started_request_count == 0) ? \ 320 (this_port)->started_request_count : \ 321 ((this_port)->started_request_count - 1) \ 322 ) \ 323 ) 324 #endif 325 326 /** 327 * Helper macro to write the phys port assignment 328 */ 329 #define scic_sds_port_write_phy_assignment(port, phy) \ 330 SCU_PCSPExCR_WRITE( \ 331 (port), \ 332 (phy)->phy_index, \ 333 (port)->physical_port_index \ 334 ) 335 336 /** 337 * Helper macro to read the phys port assignment 338 */ 339 #define scic_sds_port_read_phy_assignment(port, phy) \ 340 SCU_PCSPExCR_READ( \ 341 (port), \ 342 (phy)->phy_index \ 343 ) 344 345 #define scic_sds_port_active_phy(port, phy) \ 346 (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0) 347 348 // --------------------------------------------------------------------------- 349 350 U32 scic_sds_port_get_object_size(void); 351 352 U32 scic_sds_port_get_min_timer_count(void); 353 354 U32 scic_sds_port_get_max_timer_count(void); 355 356 // --------------------------------------------------------------------------- 357 358 #ifdef SCI_LOGGING 359 void scic_sds_port_initialize_state_logging( 360 SCIC_SDS_PORT_T *this_port 361 ); 362 #else 363 #define scic_sds_port_initialize_state_logging(x) 364 #endif 365 366 // --------------------------------------------------------------------------- 367 368 void scic_sds_port_construct( 369 SCIC_SDS_PORT_T *this_port, 370 U8 port_index, 371 struct SCIC_SDS_CONTROLLER *owning_controller 372 ); 373 374 SCI_STATUS scic_sds_port_initialize( 375 SCIC_SDS_PORT_T *this_port, 376 void *port_task_scheduler_registers, 377 void *port_configuration_regsiter, 378 void *viit_registers 379 ); 380 381 // --------------------------------------------------------------------------- 382 383 SCI_STATUS scic_sds_port_add_phy( 384 struct SCIC_SDS_PORT * this_port, 385 struct SCIC_SDS_PHY * the_phy 386 ); 387 388 SCI_STATUS scic_sds_port_remove_phy( 389 struct SCIC_SDS_PORT * this_port, 390 struct SCIC_SDS_PHY * the_phy 391 ); 392 393 void scic_sds_port_setup_transports( 394 SCIC_SDS_PORT_T * this_port, 395 U32 device_id 396 ); 397 398 void scic_sds_port_activate_phy( 399 SCIC_SDS_PORT_T *this_port, 400 struct SCIC_SDS_PHY *phy, 401 BOOL do_notify_user, 402 BOOL do_resume_phy 403 ); 404 405 void scic_sds_port_deactivate_phy( 406 SCIC_SDS_PORT_T *this_port, 407 struct SCIC_SDS_PHY *phy, 408 BOOL do_notify_user 409 ); 410 411 struct SCIC_SDS_PHY * scic_sds_port_get_a_connected_phy( 412 SCIC_SDS_PORT_T * this_port 413 ); 414 415 void scic_sds_port_invalid_link_up( 416 SCIC_SDS_PORT_T *this_port, 417 struct SCIC_SDS_PHY *phy 418 ); 419 420 void scic_sds_port_general_link_up_handler( 421 SCIC_SDS_PORT_T *this_port, 422 struct SCIC_SDS_PHY *the_phy, 423 BOOL do_notify_user, 424 BOOL do_resume_phy 425 ); 426 427 BOOL scic_sds_port_link_detected( 428 SCIC_SDS_PORT_T *this_port, 429 struct SCIC_SDS_PHY *phy 430 ); 431 432 void scic_sds_port_link_up( 433 SCIC_SDS_PORT_T *this_port, 434 struct SCIC_SDS_PHY *phy 435 ); 436 437 void scic_sds_port_link_down( 438 SCIC_SDS_PORT_T *this_port, 439 struct SCIC_SDS_PHY *phy 440 ); 441 442 // --------------------------------------------------------------------------- 443 444 void scic_sds_port_timeout_handler( 445 void *port 446 ); 447 448 // --------------------------------------------------------------------------- 449 450 SCI_STATUS scic_sds_port_start_io( 451 SCIC_SDS_PORT_T *this_port, 452 struct SCIC_SDS_REMOTE_DEVICE *the_device, 453 struct SCIC_SDS_REQUEST *the_io_request 454 ); 455 456 SCI_STATUS scic_sds_port_complete_io( 457 SCIC_SDS_PORT_T *this_port, 458 struct SCIC_SDS_REMOTE_DEVICE *the_device, 459 struct SCIC_SDS_REQUEST *the_io_request 460 ); 461 462 // --------------------------------------------------------------------------- 463 464 void scic_sds_port_update_viit_entry( 465 SCIC_SDS_PORT_T *this_port 466 ); 467 468 // --------------------------------------------------------------------------- 469 470 SCI_STATUS scic_sds_port_default_start_handler( 471 SCI_BASE_PORT_T *port 472 ); 473 474 SCI_STATUS scic_sds_port_default_stop_handler( 475 SCI_BASE_PORT_T *port 476 ); 477 478 SCI_STATUS scic_sds_port_default_destruct_handler( 479 SCI_BASE_PORT_T *port 480 ); 481 482 SCI_STATUS scic_sds_port_default_reset_handler( 483 SCI_BASE_PORT_T * port, 484 U32 timeout 485 ); 486 487 SCI_STATUS scic_sds_port_default_add_phy_handler( 488 SCI_BASE_PORT_T *port, 489 SCI_BASE_PHY_T *phy 490 ); 491 492 SCI_STATUS scic_sds_port_default_remove_phy_handler( 493 SCI_BASE_PORT_T *port, 494 SCI_BASE_PHY_T *phy 495 ); 496 497 SCI_STATUS scic_sds_port_default_frame_handler( 498 struct SCIC_SDS_PORT * port, 499 U32 frame_index 500 ); 501 502 SCI_STATUS scic_sds_port_default_event_handler( 503 struct SCIC_SDS_PORT * port, 504 U32 event_code 505 ); 506 507 void scic_sds_port_default_link_up_handler( 508 struct SCIC_SDS_PORT *this_port, 509 struct SCIC_SDS_PHY *phy 510 ); 511 512 void scic_sds_port_default_link_down_handler( 513 struct SCIC_SDS_PORT *this_port, 514 struct SCIC_SDS_PHY *phy 515 ); 516 517 SCI_STATUS scic_sds_port_default_start_io_handler( 518 struct SCIC_SDS_PORT *port, 519 struct SCIC_SDS_REMOTE_DEVICE *device, 520 struct SCIC_SDS_REQUEST *io_request 521 ); 522 523 SCI_STATUS scic_sds_port_default_complete_io_handler( 524 struct SCIC_SDS_PORT *port, 525 struct SCIC_SDS_REMOTE_DEVICE *device, 526 struct SCIC_SDS_REQUEST *io_request 527 ); 528 529 SCI_SAS_LINK_RATE scic_sds_port_get_max_allowed_speed( 530 SCIC_SDS_PORT_T * this_port 531 ); 532 533 void scic_sds_port_broadcast_change_received( 534 struct SCIC_SDS_PORT * this_port, 535 struct SCIC_SDS_PHY * this_phy 536 ); 537 538 BOOL scic_sds_port_is_valid_phy_assignment( 539 SCIC_SDS_PORT_T *this_port, 540 U32 phy_index 541 ); 542 543 BOOL scic_sds_port_is_phy_mask_valid( 544 SCIC_SDS_PORT_T * this_port, 545 U32 phy_mask 546 ); 547 548 U32 scic_sds_port_get_phys( 549 SCIC_SDS_PORT_T * this_port 550 ); 551 552 void scic_sds_port_get_sas_address( 553 SCIC_SDS_PORT_T * this_port, 554 SCI_SAS_ADDRESS_T * sas_address 555 ); 556 557 void scic_sds_port_get_attached_sas_address( 558 SCIC_SDS_PORT_T * this_port, 559 SCI_SAS_ADDRESS_T * sas_address 560 ); 561 562 void scic_sds_port_get_attached_protocols( 563 SCIC_SDS_PORT_T * this_port, 564 SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols 565 ); 566 567 SCI_STATUS scic_sds_port_set_phy( 568 struct SCIC_SDS_PORT *port, 569 struct SCIC_SDS_PHY *phy 570 ); 571 572 SCI_STATUS scic_sds_port_clear_phy( 573 struct SCIC_SDS_PORT *port, 574 struct SCIC_SDS_PHY *phy 575 ); 576 577 void scic_sds_port_suspend_port_task_scheduler( 578 SCIC_SDS_PORT_T *this_port 579 ); 580 581 void scic_sds_port_resume_port_task_scheduler( 582 SCIC_SDS_PORT_T *this_port 583 ); 584 585 void scic_sds_port_release_resource( 586 struct SCIC_SDS_CONTROLLER * controller, 587 struct SCIC_SDS_PORT * port 588 ); 589 590 #ifdef __cplusplus 591 } 592 #endif // __cplusplus 593 594 595 #endif // _SCIC_SDS_PORT_H_ 596