2 * This file is provided under a dual BSD/GPLv2 license. When using or
3 * redistributing this file, you may do so under either license.
7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of version 2 of the GNU General Public License as
11 * published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27 * All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
33 * * Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * * Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in
37 * the documentation and/or other materials provided with the
39 * * Neither the name of Intel Corporation nor the names of its
40 * contributors may be used to endorse or promote products derived
41 * from this software without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
47 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 #ifndef _SCIC_SDS_PORT_H_
57 #define _SCIC_SDS_PORT_H_
60 * This file contains the structures, constants and prototypes for the
61 * struct scic_sds_port object.
66 #include "sci_controller_constants.h"
67 #include "intel_sas.h"
68 #include "sci_base_port.h"
69 #include "sci_base_phy.h"
70 #include "scu_registers.h"
72 #define SCIC_SDS_DUMMY_PORT 0xFF
75 * enum SCIC_SDS_PORT_READY_SUBSTATES -
77 * This enumeration depicts all of the states for the core port ready substate
80 enum SCIC_SDS_PORT_READY_SUBSTATES {
82 * The substate where the port is started and ready but has no active phys.
84 SCIC_SDS_PORT_READY_SUBSTATE_WAITING,
87 * The substate where the port is started and ready and there is at least one
90 SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL,
93 * The substate where the port is started and there was an add/remove phy
94 * event. This state is only used in Automatic Port Configuration Mode (APC)
96 SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING,
98 SCIC_SDS_PORT_READY_MAX_SUBSTATES
101 struct scic_sds_controller;
103 struct scic_sds_remote_device;
104 struct scic_sds_request;
107 * struct scic_sds_port -
109 * The core port object provides the the abstraction for an SCU port.
111 struct scic_sds_port {
113 * This field is the oommon base port object.
115 struct sci_base_port parent;
118 * This field is the port index that is reported to the SCI USER. This allows
119 * the actual hardware physical port to change without the SCI USER getting a
120 * different answer for the get port index.
122 u8 logical_port_index;
125 * This field is the port index used to program the SCU hardware.
127 u8 physical_port_index;
130 * This field contains the active phy mask for the port. This mask is used in
131 * conjunction with the phy state to determine which phy to select for some
137 * This field contains the count of the io requests started on this port
138 * object. It is used to control controller shutdown.
140 u32 started_request_count;
143 * This field contains the number of devices assigned to this port. It is
144 * used to control port start requests.
146 u32 assigned_device_count;
149 * This field contains the reason for the port not going ready. It is
150 * assigned in the state handlers and used in the state transition.
152 u32 not_ready_reason;
155 * This field is the table of phys assigned to the port.
157 struct scic_sds_phy *phy_table[SCI_MAX_PHYS];
160 * This field is a pointer back to the controller that owns this port object.
162 struct scic_sds_controller *owning_controller;
165 * This field contains the port start/stop timer handle.
170 * This field points to the current set of state handlers for this port
171 * object. These state handlers are assigned at each enter state of the state
174 struct scic_sds_port_state_handler *state_handlers;
177 * This field is the ready substate machine for the port.
179 struct sci_base_state_machine ready_substate_machine;
181 /* / Memory mapped hardware register space */
183 * This field is the pointer to the transport layer register for the SCU
186 struct scu_transport_layer_registers *transport_layer_registers;
189 * This field is the pointer to the port task scheduler registers for the SCU
192 struct scu_port_task_scheduler_registers *port_task_scheduler_registers;
195 * This field is identical for all port objects and points to the port task
196 * scheduler group PE configuration registers. It is used to assign PEs to a
199 SCU_PORT_PE_CONFIGURATION_REGISTER_T *port_pe_configuration_register;
202 * This field is the VIIT register space for ths port object.
204 struct scu_viit_entry *viit_registers;
209 typedef enum sci_status (*SCIC_SDS_PORT_EVENT_HANDLER_T)(struct scic_sds_port *, u32);
211 typedef enum sci_status (*SCIC_SDS_PORT_FRAME_HANDLER_T)(struct scic_sds_port *, u32);
213 typedef void (*SCIC_SDS_PORT_LINK_HANDLER_T)(struct scic_sds_port *, struct scic_sds_phy *);
215 typedef enum sci_status (*SCIC_SDS_PORT_IO_REQUEST_HANDLER_T)(
216 struct scic_sds_port *,
217 struct scic_sds_remote_device *,
218 struct scic_sds_request *);
220 struct scic_sds_port_state_handler {
221 struct sci_base_port_state_handler parent;
223 SCIC_SDS_PORT_FRAME_HANDLER_T frame_handler;
224 SCIC_SDS_PORT_EVENT_HANDLER_T event_handler;
226 SCIC_SDS_PORT_LINK_HANDLER_T link_up_handler;
227 SCIC_SDS_PORT_LINK_HANDLER_T link_down_handler;
229 SCIC_SDS_PORT_IO_REQUEST_HANDLER_T start_io_handler;
230 SCIC_SDS_PORT_IO_REQUEST_HANDLER_T complete_io_handler;
234 extern const struct sci_base_state scic_sds_port_state_table[];
235 extern const struct sci_base_state scic_sds_port_ready_substate_table[];
237 extern struct scic_sds_port_state_handler scic_sds_port_state_handler_table[];
238 extern struct scic_sds_port_state_handler scic_sds_port_ready_substate_handler_table[];
241 * scic_sds_port_get_controller() -
243 * Helper macro to get the owning controller of this port
245 #define scic_sds_port_get_controller(this_port) \
246 ((this_port)->owning_controller)
249 * scic_sds_port_get_base_state_machine() -
251 * Helper macro to get the base state machine for this port
253 #define scic_sds_port_get_base_state_machine(this_port) \
254 (&(this_port)->parent.state_machine)
257 * scic_sds_port_set_base_state_handlers() -
259 * This macro will change the state handlers to those of the specified state id
261 #define scic_sds_port_set_base_state_handlers(this_port, state_id) \
262 scic_sds_port_set_state_handlers(\
263 (this_port), &scic_sds_port_state_handler_table[(state_id)])
266 * scic_sds_port_get_ready_substate_machine() -
268 * Helper macro to get the ready substate machine for this port
270 #define scic_sds_port_get_ready_substate_machine(this_port) \
271 (&(this_port)->ready_substate_machine)
274 * scic_sds_port_set_state_handlers() -
276 * Helper macro to set the port object state handlers
278 #define scic_sds_port_set_state_handlers(this_port, handlers) \
279 ((this_port)->state_handlers = (handlers))
282 * scic_sds_port_get_index() -
284 * This macro returns the physical port index for this port object
286 #define scic_sds_port_get_index(this_port) \
287 ((this_port)->physical_port_index)
290 * scic_sds_port_increment_request_count() -
292 * Helper macro to increment the started request count
294 #define scic_sds_port_increment_request_count(this_port) \
295 ((this_port)->started_request_count++)
297 #ifdef SCIC_DEBUG_ENABLED
299 * scic_sds_port_decrement_request_count() - This method decrements the started
300 * io request count. The method will not decrment the started io request
301 * count below 0 and will log a debug message if this is attempted.
305 void scic_sds_port_decrement_request_count(
306 struct scic_sds_port *this_port);
309 * scic_sds_port_decrement_request_count() -
311 * Helper macro to decrement the started io request count. The macro will not
312 * decrement the started io request count below 0.
314 #define scic_sds_port_decrement_request_count(this_port) \
316 (this_port)->started_request_count = (\
317 ((this_port)->started_request_count == 0) ? \
318 (this_port)->started_request_count : \
319 ((this_port)->started_request_count - 1) \
325 * scic_sds_port_write_phy_assignment() -
327 * Helper macro to write the phys port assignment
329 #define scic_sds_port_write_phy_assignment(port, phy) \
333 (port)->physical_port_index \
337 * scic_sds_port_read_phy_assignment() -
339 * Helper macro to read the phys port assignment
341 #define scic_sds_port_read_phy_assignment(port, phy) \
347 #define scic_sds_port_active_phy(port, phy) \
348 (((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0)
350 /* --------------------------------------------------------------------------- */
355 /* --------------------------------------------------------------------------- */
357 /* --------------------------------------------------------------------------- */
359 void scic_sds_port_construct(
360 struct scic_sds_port *this_port,
362 struct scic_sds_controller *owning_controller);
364 enum sci_status scic_sds_port_initialize(
365 struct scic_sds_port *this_port,
366 void *transport_layer_registers,
367 void *port_task_scheduler_registers,
368 void *port_configuration_regsiter,
369 void *viit_registers);
371 /* --------------------------------------------------------------------------- */
373 enum sci_status scic_sds_port_add_phy(
374 struct scic_sds_port *this_port,
375 struct scic_sds_phy *the_phy);
377 enum sci_status scic_sds_port_remove_phy(
378 struct scic_sds_port *this_port,
379 struct scic_sds_phy *the_phy);
381 void scic_sds_port_set_direct_attached_device_id(
382 struct scic_sds_port *this_port,
385 void scic_sds_port_activate_phy(
386 struct scic_sds_port *this_port,
387 struct scic_sds_phy *phy,
388 bool do_notify_user);
390 void scic_sds_port_deactivate_phy(
391 struct scic_sds_port *this_port,
392 struct scic_sds_phy *phy,
393 bool do_notify_user);
397 void scic_sds_port_general_link_up_handler(
398 struct scic_sds_port *this_port,
399 struct scic_sds_phy *the_phy,
400 bool do_notify_user);
402 bool scic_sds_port_link_detected(
403 struct scic_sds_port *this_port,
404 struct scic_sds_phy *phy);
406 void scic_sds_port_link_up(
407 struct scic_sds_port *this_port,
408 struct scic_sds_phy *phy);
410 void scic_sds_port_link_down(
411 struct scic_sds_port *this_port,
412 struct scic_sds_phy *phy);
414 /* --------------------------------------------------------------------------- */
417 /* --------------------------------------------------------------------------- */
419 enum sci_status scic_sds_port_start_io(
420 struct scic_sds_port *this_port,
421 struct scic_sds_remote_device *the_device,
422 struct scic_sds_request *the_io_request);
424 enum sci_status scic_sds_port_complete_io(
425 struct scic_sds_port *this_port,
426 struct scic_sds_remote_device *the_device,
427 struct scic_sds_request *the_io_request);
429 /* --------------------------------------------------------------------------- */
431 void scic_sds_port_update_viit_entry(
432 struct scic_sds_port *this_port);
434 /* --------------------------------------------------------------------------- */
436 enum sci_status scic_sds_port_default_start_handler(
437 struct sci_base_port *port);
440 enum sci_status scic_sds_port_default_destruct_handler(
441 struct sci_base_port *port);
443 enum sci_status scic_sds_port_default_reset_handler(
444 struct sci_base_port *port,
448 enum sci_status scic_sds_port_default_remove_phy_handler(
449 struct sci_base_port *port,
450 struct sci_base_phy *phy);
452 enum sci_status scic_sds_port_default_frame_handler(
453 struct scic_sds_port *port,
456 enum sci_status scic_sds_port_default_event_handler(
457 struct scic_sds_port *port,
460 void scic_sds_port_default_link_up_handler(
461 struct scic_sds_port *this_port,
462 struct scic_sds_phy *phy);
464 void scic_sds_port_default_link_down_handler(
465 struct scic_sds_port *this_port,
466 struct scic_sds_phy *phy);
468 enum sci_status scic_sds_port_default_start_io_handler(
469 struct scic_sds_port *port,
470 struct scic_sds_remote_device *device,
471 struct scic_sds_request *io_request);
474 enum sci_sas_link_rate scic_sds_port_get_max_allowed_speed(
475 struct scic_sds_port *this_port);
477 void scic_sds_port_broadcast_change_received(
478 struct scic_sds_port *this_port,
479 struct scic_sds_phy *this_phy);
481 bool scic_sds_port_is_valid_phy_assignment(
482 struct scic_sds_port *this_port,
485 bool scic_sds_port_is_phy_mask_valid(
486 struct scic_sds_port *this_port,
489 u32 scic_sds_port_get_phys(
490 struct scic_sds_port *this_port);
492 void scic_sds_port_get_sas_address(
493 struct scic_sds_port *this_port,
494 struct sci_sas_address *sas_address);
496 void scic_sds_port_get_attached_sas_address(
497 struct scic_sds_port *this_port,
498 struct sci_sas_address *sas_address);
500 void scic_sds_port_get_attached_protocols(
501 struct scic_sds_port *this_port,
502 struct sci_sas_identify_address_frame_protocols *protocols);
504 enum sci_status scic_sds_port_set_phy(
505 struct scic_sds_port *port,
506 struct scic_sds_phy *phy);
508 enum sci_status scic_sds_port_clear_phy(
509 struct scic_sds_port *port,
510 struct scic_sds_phy *phy);
514 #endif /* _SCIC_SDS_PORT_H_ */