xref: /freebsd/sys/dev/isci/scil/scic_sds_port.h (revision 4e579ad047720775ab580b74192c7de8a3386fea)
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