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