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 * $FreeBSD$ 55 */ 56 #ifndef _SCIC_SDS_PORT_H_ 57 #define _SCIC_SDS_PORT_H_ 58 59 #ifdef __cplusplus 60 extern "C" { 61 #endif // __cplusplus 62 63 /** 64 * @file 65 * 66 * @brief This file contains the structures, constants and prototypes for the 67 * SCIC_SDS_PORT_T object. 68 */ 69 70 #include <dev/isci/scil/sci_controller_constants.h> 71 #include <dev/isci/scil/intel_sas.h> 72 #include <dev/isci/scil/sci_base_port.h> 73 #include <dev/isci/scil/sci_base_phy.h> 74 #include <dev/isci/scil/scu_registers.h> 75 76 #define SCIC_SDS_DUMMY_PORT 0xFF 77 78 /** 79 * @enum SCIC_SDS_PORT_READY_SUBSTATES 80 * 81 * This enumeration depicts all of the states for the core port ready substate 82 * machine. 83 */ 84 enum SCIC_SDS_PORT_READY_SUBSTATES 85 { 86 /** 87 * The substate where the port is started and ready but has no active phys. 88 */ 89 SCIC_SDS_PORT_READY_SUBSTATE_WAITING, 90 91 /** 92 * The substate where the port is started and ready and there is at least one 93 * phy operational. 94 */ 95 SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL, 96 97 /** 98 * The substate where the port is started and there was an add/remove phy 99 * event. This state is only used in Automatic Port Configuration Mode (APC) 100 */ 101 SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING, 102 103 SCIC_SDS_PORT_READY_MAX_SUBSTATES 104 }; 105 106 struct SCIC_SDS_CONTROLLER; 107 struct SCIC_SDS_PHY; 108 struct SCIC_SDS_REMOTE_DEVICE; 109 struct SCIC_SDS_REQUEST; 110 111 /** 112 * @struct SCIC_SDS_PORT 113 * 114 * The core port object provides the abstraction for an SCU port. 115 */ 116 typedef struct SCIC_SDS_PORT 117 { 118 /** 119 * This field is the oommon base port object. 120 */ 121 SCI_BASE_PORT_T parent; 122 123 /** 124 * This field is the port index that is reported to the SCI USER. This allows 125 * the actual hardware physical port to change without the SCI USER getting a 126 * different answer for the get port index. 127 */ 128 U8 logical_port_index; 129 130 /** 131 * This field is the port index used to program the SCU hardware. 132 */ 133 U8 physical_port_index; 134 135 /** 136 * This field contains the active phy mask for the port. This mask is used in 137 * conjunction with the phy state to determine which phy to select for some 138 * port operations. 139 */ 140 U8 active_phy_mask; 141 142 /** 143 * This field contains the phy mask for the port that are already part of the port. 144 */ 145 U8 enabled_phy_mask; 146 147 U16 reserved_rni; 148 U16 reserved_tci; 149 150 /** 151 * This field contains the count of the io requests started on this port 152 * object. It is used to control controller shutdown. 153 */ 154 U32 started_request_count; 155 156 /** 157 * This field contains the number of devices assigned to this port. It is 158 * used to control port start requests. 159 */ 160 U32 assigned_device_count; 161 162 /** 163 * This field contains the reason for the port not going ready. It is 164 * assigned in the state handlers and used in the state transition. 165 */ 166 U32 not_ready_reason; 167 168 /** 169 * This field is the table of phys assigned to the port. 170 */ 171 struct SCIC_SDS_PHY *phy_table[SCI_MAX_PHYS]; 172 173 /** 174 * This field is a pointer back to the controller that owns this port object. 175 */ 176 struct SCIC_SDS_CONTROLLER *owning_controller; 177 178 /** 179 * This field contains the port start/stop timer handle. 180 */ 181 void *timer_handle; 182 183 /** 184 * This field points to the current set of state handlers for this port 185 * object. These state handlers are assigned at each enter state of the state 186 * machine. 187 */ 188 struct SCIC_SDS_PORT_STATE_HANDLER *state_handlers; 189 190 /** 191 * This field is the ready substate machine for the port. 192 */ 193 SCI_BASE_STATE_MACHINE_T ready_substate_machine; 194 195 #ifdef SCI_LOGGING 196 /** 197 * This field is the ready substate machine logger. It logs each state 198 * transition request in the ready substate machine. 199 */ 200 SCI_BASE_STATE_MACHINE_LOGGER_T ready_substate_machine_logger; 201 #endif 202 203 /// Memory mapped hardware register space 204 205 /** 206 * This field is the pointer to the port task scheduler registers for the SCU 207 * hardware. 208 */ 209 SCU_PORT_TASK_SCHEDULER_REGISTERS_T *port_task_scheduler_registers; 210 211 /** 212 * This field is identical for all port objects and points to the port task 213 * scheduler group PE configuration registers. It is used to assign PEs to a 214 * port. 215 */ 216 SCU_PORT_PE_CONFIGURATION_REGISTER_T *port_pe_configuration_register; 217 218 /** 219 * This field is the VIIT register space for this port object. 220 */ 221 SCU_VIIT_ENTRY_T *viit_registers; 222 223 } SCIC_SDS_PORT_T; 224 225 226 typedef SCI_STATUS (*SCIC_SDS_PORT_EVENT_HANDLER_T)(struct SCIC_SDS_PORT *, U32); 227 228 typedef SCI_STATUS (*SCIC_SDS_PORT_FRAME_HANDLER_T)(struct SCIC_SDS_PORT *, U32); 229 230 typedef void (*SCIC_SDS_PORT_LINK_HANDLER_T)(struct SCIC_SDS_PORT *, struct SCIC_SDS_PHY *); 231 232 typedef SCI_STATUS (*SCIC_SDS_PORT_IO_REQUEST_HANDLER_T)( 233 struct SCIC_SDS_PORT *, 234 struct SCIC_SDS_REMOTE_DEVICE *, 235 struct SCIC_SDS_REQUEST *); 236 237 typedef struct SCIC_SDS_PORT_STATE_HANDLER 238 { 239 SCI_BASE_PORT_STATE_HANDLER_T parent; 240 241 SCIC_SDS_PORT_FRAME_HANDLER_T frame_handler; 242 SCIC_SDS_PORT_EVENT_HANDLER_T event_handler; 243 244 SCIC_SDS_PORT_LINK_HANDLER_T link_up_handler; 245 SCIC_SDS_PORT_LINK_HANDLER_T link_down_handler; 246 247 SCIC_SDS_PORT_IO_REQUEST_HANDLER_T start_io_handler; 248 SCIC_SDS_PORT_IO_REQUEST_HANDLER_T complete_io_handler; 249 250 } SCIC_SDS_PORT_STATE_HANDLER_T; 251 252 extern SCI_BASE_STATE_T scic_sds_port_state_table[]; 253 extern SCI_BASE_STATE_T scic_sds_port_ready_substate_table[]; 254 255 extern SCIC_SDS_PORT_STATE_HANDLER_T scic_sds_port_state_handler_table[]; 256 extern SCIC_SDS_PORT_STATE_HANDLER_T scic_sds_port_ready_substate_handler_table[]; 257 258 /** 259 * Helper macro to get the owning controller of this port 260 */ 261 #define scic_sds_port_get_controller(this_port) \ 262 ((this_port)->owning_controller) 263 264 /** 265 * Helper macro to get the base state machine for this port 266 */ 267 #define scic_sds_port_get_base_state_machine(this_port) \ 268 (&(this_port)->parent.state_machine) 269 270 /** 271 * This macro will change the state handlers to those of the specified state 272 * id 273 */ 274 #define scic_sds_port_set_base_state_handlers(this_port, state_id) \ 275 scic_sds_port_set_state_handlers( \ 276 (this_port), &scic_sds_port_state_handler_table[(state_id)]) 277 278 /** 279 * Helper macro to get the ready substate machine for this port 280 */ 281 #define scic_sds_port_get_ready_substate_machine(this_port) \ 282 (&(this_port)->ready_substate_machine) 283 284 /** 285 * Helper macro to set the port object state handlers 286 */ 287 #define scic_sds_port_set_state_handlers(this_port, handlers) \ 288 ((this_port)->state_handlers = (handlers)) 289 290 /** 291 * This macro returns the physical port index for this port object 292 */ 293 #define scic_sds_port_get_index(this_port) \ 294 ((this_port)->physical_port_index) 295 296 /** 297 * Helper macro to increment the started request count 298 */ 299 #define scic_sds_port_increment_request_count(this_port) \ 300 ((this_port)->started_request_count++) 301 302 #ifdef SCIC_DEBUG_ENABLED 303 /** 304 * @brief This method decrements the started io request count. The method 305 * will not decrment the started io request count below 0 and will 306 * log a debug message if this is attempted. 307 * 308 * @param[in] this_port 309 */ 310 void scic_sds_port_decrement_request_count( 311 SCIC_SDS_PORT_T *this_port 312 ); 313 #else 314 /** 315 * Helper macro to decrement the started io request count. The macro will 316 * not decrement the started io request count below 0. 317 */ 318 #define scic_sds_port_decrement_request_count(this_port) \ 319 ( \ 320 (this_port)->started_request_count = ( \ 321 ((this_port)->started_request_count == 0) ? \ 322 (this_port)->started_request_count : \ 323 ((this_port)->started_request_count - 1) \ 324 ) \ 325 ) 326 #endif 327 328 /** 329 * Helper macro to write the phys port assignment 330 */ 331 #define scic_sds_port_write_phy_assignment(port, phy) \ 332 SCU_PCSPExCR_WRITE( \ 333 (port), \ 334 (phy)->phy_index, \ 335 (port)->physical_port_index \ 336 ) 337 338 /** 339 * Helper macro to read the phys port assignment 340 */ 341 #define scic_sds_port_read_phy_assignment(port, phy) \ 342 SCU_PCSPExCR_READ( \ 343 (port), \ 344 (phy)->phy_index \ 345 ) 346 347 #define scic_sds_port_active_phy(port, phy) \ 348 (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0) 349 350 // --------------------------------------------------------------------------- 351 352 U32 scic_sds_port_get_object_size(void); 353 354 U32 scic_sds_port_get_min_timer_count(void); 355 356 U32 scic_sds_port_get_max_timer_count(void); 357 358 // --------------------------------------------------------------------------- 359 360 #ifdef SCI_LOGGING 361 void scic_sds_port_initialize_state_logging( 362 SCIC_SDS_PORT_T *this_port 363 ); 364 #else 365 #define scic_sds_port_initialize_state_logging(x) 366 #endif 367 368 // --------------------------------------------------------------------------- 369 370 void scic_sds_port_construct( 371 SCIC_SDS_PORT_T *this_port, 372 U8 port_index, 373 struct SCIC_SDS_CONTROLLER *owning_controller 374 ); 375 376 SCI_STATUS scic_sds_port_initialize( 377 SCIC_SDS_PORT_T *this_port, 378 void *port_task_scheduler_registers, 379 void *port_configuration_regsiter, 380 void *viit_registers 381 ); 382 383 // --------------------------------------------------------------------------- 384 385 SCI_STATUS scic_sds_port_add_phy( 386 struct SCIC_SDS_PORT * this_port, 387 struct SCIC_SDS_PHY * the_phy 388 ); 389 390 SCI_STATUS scic_sds_port_remove_phy( 391 struct SCIC_SDS_PORT * this_port, 392 struct SCIC_SDS_PHY * the_phy 393 ); 394 395 void scic_sds_port_setup_transports( 396 SCIC_SDS_PORT_T * this_port, 397 U32 device_id 398 ); 399 400 void scic_sds_port_activate_phy( 401 SCIC_SDS_PORT_T *this_port, 402 struct SCIC_SDS_PHY *phy, 403 BOOL do_notify_user, 404 BOOL do_resume_phy 405 ); 406 407 void scic_sds_port_deactivate_phy( 408 SCIC_SDS_PORT_T *this_port, 409 struct SCIC_SDS_PHY *phy, 410 BOOL do_notify_user 411 ); 412 413 struct SCIC_SDS_PHY * scic_sds_port_get_a_connected_phy( 414 SCIC_SDS_PORT_T * this_port 415 ); 416 417 void scic_sds_port_invalid_link_up( 418 SCIC_SDS_PORT_T *this_port, 419 struct SCIC_SDS_PHY *phy 420 ); 421 422 void scic_sds_port_general_link_up_handler( 423 SCIC_SDS_PORT_T *this_port, 424 struct SCIC_SDS_PHY *the_phy, 425 BOOL do_notify_user, 426 BOOL do_resume_phy 427 ); 428 429 BOOL scic_sds_port_link_detected( 430 SCIC_SDS_PORT_T *this_port, 431 struct SCIC_SDS_PHY *phy 432 ); 433 434 void scic_sds_port_link_up( 435 SCIC_SDS_PORT_T *this_port, 436 struct SCIC_SDS_PHY *phy 437 ); 438 439 void scic_sds_port_link_down( 440 SCIC_SDS_PORT_T *this_port, 441 struct SCIC_SDS_PHY *phy 442 ); 443 444 // --------------------------------------------------------------------------- 445 446 void scic_sds_port_timeout_handler( 447 void *port 448 ); 449 450 // --------------------------------------------------------------------------- 451 452 SCI_STATUS scic_sds_port_start_io( 453 SCIC_SDS_PORT_T *this_port, 454 struct SCIC_SDS_REMOTE_DEVICE *the_device, 455 struct SCIC_SDS_REQUEST *the_io_request 456 ); 457 458 SCI_STATUS scic_sds_port_complete_io( 459 SCIC_SDS_PORT_T *this_port, 460 struct SCIC_SDS_REMOTE_DEVICE *the_device, 461 struct SCIC_SDS_REQUEST *the_io_request 462 ); 463 464 // --------------------------------------------------------------------------- 465 466 void scic_sds_port_update_viit_entry( 467 SCIC_SDS_PORT_T *this_port 468 ); 469 470 // --------------------------------------------------------------------------- 471 472 SCI_STATUS scic_sds_port_default_start_handler( 473 SCI_BASE_PORT_T *port 474 ); 475 476 SCI_STATUS scic_sds_port_default_stop_handler( 477 SCI_BASE_PORT_T *port 478 ); 479 480 SCI_STATUS scic_sds_port_default_destruct_handler( 481 SCI_BASE_PORT_T *port 482 ); 483 484 SCI_STATUS scic_sds_port_default_reset_handler( 485 SCI_BASE_PORT_T * port, 486 U32 timeout 487 ); 488 489 SCI_STATUS scic_sds_port_default_add_phy_handler( 490 SCI_BASE_PORT_T *port, 491 SCI_BASE_PHY_T *phy 492 ); 493 494 SCI_STATUS scic_sds_port_default_remove_phy_handler( 495 SCI_BASE_PORT_T *port, 496 SCI_BASE_PHY_T *phy 497 ); 498 499 SCI_STATUS scic_sds_port_default_frame_handler( 500 struct SCIC_SDS_PORT * port, 501 U32 frame_index 502 ); 503 504 SCI_STATUS scic_sds_port_default_event_handler( 505 struct SCIC_SDS_PORT * port, 506 U32 event_code 507 ); 508 509 void scic_sds_port_default_link_up_handler( 510 struct SCIC_SDS_PORT *this_port, 511 struct SCIC_SDS_PHY *phy 512 ); 513 514 void scic_sds_port_default_link_down_handler( 515 struct SCIC_SDS_PORT *this_port, 516 struct SCIC_SDS_PHY *phy 517 ); 518 519 SCI_STATUS scic_sds_port_default_start_io_handler( 520 struct SCIC_SDS_PORT *port, 521 struct SCIC_SDS_REMOTE_DEVICE *device, 522 struct SCIC_SDS_REQUEST *io_request 523 ); 524 525 SCI_STATUS scic_sds_port_default_complete_io_handler( 526 struct SCIC_SDS_PORT *port, 527 struct SCIC_SDS_REMOTE_DEVICE *device, 528 struct SCIC_SDS_REQUEST *io_request 529 ); 530 531 SCI_SAS_LINK_RATE scic_sds_port_get_max_allowed_speed( 532 SCIC_SDS_PORT_T * this_port 533 ); 534 535 void scic_sds_port_broadcast_change_received( 536 struct SCIC_SDS_PORT * this_port, 537 struct SCIC_SDS_PHY * this_phy 538 ); 539 540 BOOL scic_sds_port_is_valid_phy_assignment( 541 SCIC_SDS_PORT_T *this_port, 542 U32 phy_index 543 ); 544 545 BOOL scic_sds_port_is_phy_mask_valid( 546 SCIC_SDS_PORT_T * this_port, 547 U32 phy_mask 548 ); 549 550 U32 scic_sds_port_get_phys( 551 SCIC_SDS_PORT_T * this_port 552 ); 553 554 void scic_sds_port_get_sas_address( 555 SCIC_SDS_PORT_T * this_port, 556 SCI_SAS_ADDRESS_T * sas_address 557 ); 558 559 void scic_sds_port_get_attached_sas_address( 560 SCIC_SDS_PORT_T * this_port, 561 SCI_SAS_ADDRESS_T * sas_address 562 ); 563 564 void scic_sds_port_get_attached_protocols( 565 SCIC_SDS_PORT_T * this_port, 566 SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T * protocols 567 ); 568 569 SCI_STATUS scic_sds_port_set_phy( 570 struct SCIC_SDS_PORT *port, 571 struct SCIC_SDS_PHY *phy 572 ); 573 574 SCI_STATUS scic_sds_port_clear_phy( 575 struct SCIC_SDS_PORT *port, 576 struct SCIC_SDS_PHY *phy 577 ); 578 579 void scic_sds_port_suspend_port_task_scheduler( 580 SCIC_SDS_PORT_T *this_port 581 ); 582 583 void scic_sds_port_resume_port_task_scheduler( 584 SCIC_SDS_PORT_T *this_port 585 ); 586 587 void scic_sds_port_release_resource( 588 struct SCIC_SDS_CONTROLLER * controller, 589 struct SCIC_SDS_PORT * port 590 ); 591 592 #ifdef __cplusplus 593 } 594 #endif // __cplusplus 595 596 597 #endif // _SCIC_SDS_PORT_H_ 598