1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 /*
25  * This file provides prototype function definitions.
26  */
27 #ifndef	_PMCS_PROTO_H
28 #define	_PMCS_PROTO_H
29 #ifdef	__cplusplus
30 extern "C" {
31 #endif
32 
33 
34 typedef enum {
35 	PMCS_PRT_DEBUG = 0,
36 	PMCS_PRT_DEBUG1,
37 	PMCS_PRT_DEBUG2,
38 	PMCS_PRT_DEBUG3,
39 	PMCS_PRT_DEBUG_CONFIG,
40 	PMCS_PRT_DEBUG_IPORT,
41 	PMCS_PRT_DEBUG_MAP,
42 	PMCS_PRT_DEBUG_UNDERFLOW,
43 	PMCS_PRT_DEBUG_SCSI_STATUS,
44 	PMCS_PRT_DEBUG_PHY_LOCKING,
45 	PMCS_PRT_DEBUG_DEV_STATE,
46 	PMCS_PRT_DEBUG_DEVEL,
47 	PMCS_PRT_INFO,
48 	PMCS_PRT_WARN,
49 	PMCS_PRT_ERR
50 } pmcs_prt_level_t;
51 
52 #define	pmcs_prt(pwp, level, phy, tgt, fmt...) {		\
53 	int lvl = level;					\
54 	if (((pwp->debug_mask & (1 << lvl)) != 0) ||		\
55 	    (lvl > PMCS_PRT_DEBUG_DEVEL)) {			\
56 		pmcs_prt_impl(pwp, lvl, phy, tgt, fmt);		\
57 	}							\
58 }
59 
60 /*PRINTFLIKE5*/
61 void
62 pmcs_prt_impl(pmcs_hw_t *, pmcs_prt_level_t, pmcs_phy_t *, pmcs_xscsi_t *,
63     const char *, ...) __KPRINTFLIKE(5);
64 
65 boolean_t pmcs_assign_device(pmcs_hw_t *, pmcs_xscsi_t *);
66 void pmcs_remove_device(pmcs_hw_t *, pmcs_phy_t *);
67 void pmcs_handle_dead_phys(pmcs_hw_t *);
68 
69 int pmcs_acquire_scratch(pmcs_hw_t *, boolean_t);
70 void pmcs_release_scratch(pmcs_hw_t *);
71 
72 /* get a work structure */
73 pmcwork_t *pmcs_gwork(pmcs_hw_t *, uint32_t, pmcs_phy_t *);
74 
75 /* put a work structure */
76 void pmcs_pwork(pmcs_hw_t *, struct pmcwork *);
77 
78 /* given a tag, find a work structure */
79 pmcwork_t *pmcs_tag2wp(pmcs_hw_t *, uint32_t, boolean_t);
80 
81 /*
82  * Abort function
83  */
84 int pmcs_abort(pmcs_hw_t *, pmcs_phy_t *, uint32_t, int, int);
85 
86 /*
87  * SSP Task Management Function
88  */
89 int pmcs_ssp_tmf(pmcs_hw_t *, pmcs_phy_t *, uint8_t, uint32_t, uint64_t,
90     uint32_t *);
91 
92 /*
93  * Abort NCQ function
94  */
95 int pmcs_sata_abort_ncq(pmcs_hw_t *, pmcs_phy_t *);
96 
97 /*
98  * Interrupt Functions
99  */
100 void pmcs_general_intr(pmcs_hw_t *);
101 void pmcs_iodone_intr(pmcs_hw_t *);
102 void pmcs_event_intr(pmcs_hw_t *);
103 void pmcs_timed_out(pmcs_hw_t *, uint32_t, const char *);
104 
105 /*
106  * Abort handler
107  */
108 int pmcs_abort_handler(pmcs_hw_t *);
109 
110 /*
111  * Deregister all expander connected devices
112  */
113 void pmcs_deregister_devices(pmcs_hw_t *, pmcs_phy_t *);
114 int pmcs_register_device(pmcs_hw_t *, pmcs_phy_t *);
115 void pmcs_deregister_device(pmcs_hw_t *, pmcs_phy_t *);
116 
117 /*
118  * endian transform a data structure
119  */
120 void pmcs_endian_transform(pmcs_hw_t *, void *, void *, const uint8_t *);
121 
122 /* get the connection rate string */
123 const char *pmcs_get_rate(unsigned int);
124 
125 /* get the device type string */
126 const char *pmcs_get_typename(pmcs_dtype_t pmcs_dtype);
127 
128 /* get the SAS Task Management function name */
129 const char *pmcs_tmf2str(int);
130 
131 /* get the PMC status string */
132 const char *pmcs_status_str(uint32_t);
133 
134 /*
135  * WWN to Byte Array and vice versa conversion
136  */
137 uint64_t pmcs_barray2wwn(uint8_t[8]);
138 void pmcs_wwn2barray(uint64_t, uint8_t[8]);
139 
140 /*
141  * Print f/w version
142  */
143 void pmcs_report_fwversion(pmcs_hw_t *);
144 
145 /*
146  * Build a device name.
147  */
148 void pmcs_phy_name(pmcs_hw_t *, pmcs_phy_t *, char *, size_t);
149 
150 /*
151  * Find a PHY by wwn
152  */
153 pmcs_phy_t *pmcs_find_phy_by_wwn(pmcs_hw_t *, uint64_t);
154 
155 /*
156  * Find a PHY by sas_address
157  */
158 pmcs_phy_t *pmcs_find_phy_by_sas_address(pmcs_hw_t *, pmcs_iport_t *,
159     pmcs_phy_t *, char *);
160 
161 /*
162  * Print out a FIS
163  */
164 void pmcs_fis_dump(pmcs_hw_t *, fis_t);
165 
166 /*
167  * Print an IOMB
168  */
169 void pmcs_print_entry(pmcs_hw_t *, int, char *, void *);
170 
171 void pmcs_spinup_release(pmcs_hw_t *, pmcs_phy_t *phyp);
172 
173 /*
174  * Handler for events - can be called from interrupt level or from worker thread
175  */
176 void pmcs_ack_events(pmcs_hw_t *);
177 
178 /*
179  * This function does some initial setup and hardware validation
180  */
181 int pmcs_setup(pmcs_hw_t *);
182 
183 /*
184  * These functions start and stop the MPI (message passing interface)
185  */
186 int pmcs_start_mpi(pmcs_hw_t *);
187 int pmcs_stop_mpi(pmcs_hw_t *);
188 
189 /*
190  * This function checks firmware revisions against required revisions
191  * and attempts to flash new firmware (if possible).
192  */
193 int pmcs_firmware_update(pmcs_hw_t *);
194 
195 /*
196  * This function runs ECHO commands to test both interrupts and queues
197  */
198 int pmcs_echo_test(pmcs_hw_t *);
199 
200 /*
201  * These functions start, reset, and stop the physical chip PHYs
202  */
203 int pmcs_start_phy(pmcs_hw_t *, int, int, int);
204 int pmcs_start_phys(pmcs_hw_t *);
205 void pmcs_stop_phy(pmcs_hw_t *, int);
206 void pmcs_stop_phys(pmcs_hw_t *);
207 
208 /*
209  * These functions setup/teardown iport tgtmap
210  */
211 int pmcs_iport_tgtmap_create(pmcs_iport_t *);
212 int pmcs_iport_tgtmap_destroy(pmcs_iport_t *);
213 
214 /*
215  * Utility and wrapper functions for SAS_DIAG_EXECUTE
216  */
217 int pmcs_sas_diag_execute(pmcs_hw_t *, uint32_t, uint32_t, uint8_t);
218 int pmcs_get_diag_report(pmcs_hw_t *, uint32_t, uint8_t);
219 int pmcs_clear_diag_counters(pmcs_hw_t *, uint8_t);
220 
221 /*
222  * Register Dump (including "internal" registers)
223  */
224 void pmcs_register_dump(pmcs_hw_t *);
225 void pmcs_iqp_trace(pmcs_hw_t *, uint32_t);
226 void pmcs_register_dump_int(pmcs_hw_t *);
227 int pmcs_dump_binary(pmcs_hw_t *, uint32_t *, uint32_t,
228     uint32_t, caddr_t, uint32_t);
229 int pmcs_dump_feregs(pmcs_hw_t *, uint32_t *, uint8_t,
230     caddr_t, uint32_t);
231 
232 /*
233  * This function perform a soft reset.
234  * Hard reset is platform specific.
235  */
236 int pmcs_soft_reset(pmcs_hw_t *, boolean_t);
237 
238 /*
239  * This is a hot reset which will attempt reconfiguration after reset.
240  */
241 int pmcs_hot_reset(pmcs_hw_t *);
242 
243 /*
244  * Some more reset functions
245  */
246 int pmcs_reset_dev(pmcs_hw_t *, pmcs_phy_t *, uint64_t);
247 int pmcs_reset_phy(pmcs_hw_t *, pmcs_phy_t *, uint8_t);
248 
249 /*
250  * These functions do topology configuration changes
251  */
252 void pmcs_discover(pmcs_hw_t *);
253 void pmcs_set_changed(pmcs_hw_t *, pmcs_phy_t *, boolean_t, int);
254 void pmcs_kill_changed(pmcs_hw_t *, pmcs_phy_t *, int);
255 void pmcs_clear_phy(pmcs_hw_t *, pmcs_phy_t *);
256 int pmcs_kill_device(pmcs_hw_t *, pmcs_phy_t *);
257 
258 /*
259  * Firmware flash function
260  */
261 int pmcs_fw_flash(pmcs_hw_t *, pmcs_fw_hdr_t *, uint32_t);
262 
263 /*
264  * Set a new value for the interrupt coalescing timer.  If it's being set
265  * to zero (disabling), then re-enable auto clear if necessary.  If it's
266  * being changed from zero, turn off auto clear if it was on.
267  */
268 typedef enum {
269 	DECREASE_TIMER = 0,
270 	INCREASE_TIMER
271 } pmcs_coal_timer_adj_t;
272 
273 void pmcs_check_intr_coal(void *arg);
274 void pmcs_set_intr_coal_timer(pmcs_hw_t *pwp, pmcs_coal_timer_adj_t adj);
275 
276 /*
277  * Misc supporting routines
278  */
279 void pmcs_check_iomb_status(pmcs_hw_t *pwp, uint32_t *iomb);
280 void pmcs_clear_xp(pmcs_hw_t *, pmcs_xscsi_t *);
281 void pmcs_create_one_phy_stats(pmcs_iport_t *, pmcs_phy_t *);
282 int pmcs_run_sata_cmd(pmcs_hw_t *, pmcs_phy_t *, fis_t, uint32_t,
283     uint32_t, uint32_t);
284 int pmcs_sata_identify(pmcs_hw_t *, pmcs_phy_t *);
285 void pmcs_sata_work(pmcs_hw_t *);
286 boolean_t pmcs_dma_setup(pmcs_hw_t *pwp, ddi_dma_attr_t *dma_attr,
287     ddi_acc_handle_t *acch, ddi_dma_handle_t *dmah, size_t length,
288     caddr_t *kvap, uint64_t *dma_addr);
289 void pmcs_fm_ereport(pmcs_hw_t *pwp, char *detail);
290 int pmcs_check_dma_handle(ddi_dma_handle_t handle);
291 int pmcs_check_acc_handle(ddi_acc_handle_t handle);
292 int pmcs_check_acc_dma_handle(pmcs_hw_t *pwp);
293 int pmcs_get_nvmd(pmcs_hw_t *pwp, pmcs_nvmd_type_t nvmd_type, uint8_t nvmd,
294     uint32_t offset, char *buf, uint32_t size_left);
295 boolean_t pmcs_set_nvmd(pmcs_hw_t *pwp, pmcs_nvmd_type_t nvmd_type,
296     uint8_t *buf, size_t len);
297 void pmcs_complete_work_impl(pmcs_hw_t *pwp, pmcwork_t *pwrk, uint32_t *iomb,
298     size_t amt);
299 void pmcs_flush_target_queues(pmcs_hw_t *, pmcs_xscsi_t *, uint8_t);
300 boolean_t pmcs_iport_has_targets(pmcs_hw_t *, pmcs_iport_t *);
301 void pmcs_free_dma_chunklist(pmcs_hw_t *);
302 void pmcs_dev_state_recovery(pmcs_hw_t *, pmcs_phy_t *);
303 void pmcs_deregister_device_work(pmcs_hw_t *, pmcs_phy_t *);
304 int pmcs_send_err_recovery_cmd(pmcs_hw_t *, uint8_t, pmcs_phy_t *,
305     pmcs_xscsi_t *);
306 void pmcs_start_ssp_event_recovery(pmcs_hw_t *pwp, pmcwork_t *pwrk,
307     uint32_t *iomb, size_t amt);
308 void pmcs_ssp_event_recovery(pmcs_hw_t *);
309 
310 pmcs_iport_t *pmcs_get_iport_by_wwn(pmcs_hw_t *pwp, uint64_t wwn);
311 pmcs_phy_t *pmcs_promote_next_phy(pmcs_phy_t *pptr);
312 void pmcs_hold_iport(pmcs_iport_t *iport);
313 void pmcs_rele_iport(pmcs_iport_t *iport);
314 int pmcs_iport_configure_phys(pmcs_iport_t *iport);
315 void pmcs_iport_teardown_phys(pmcs_iport_t *iport);
316 
317 void pmcs_lock_phy(pmcs_phy_t *);
318 void pmcs_unlock_phy(pmcs_phy_t *);
319 
320 void pmcs_destroy_target(pmcs_xscsi_t *);
321 void pmcs_phymap_activate(void *, char *, void **);
322 void pmcs_phymap_deactivate(void *, char *, void *);
323 void pmcs_add_phy_to_iport(pmcs_iport_t *, pmcs_phy_t *);
324 void pmcs_remove_phy_from_iport(pmcs_iport_t *, pmcs_phy_t *);
325 void pmcs_free_all_phys(pmcs_hw_t *, pmcs_phy_t *);
326 void pmcs_free_phys(pmcs_hw_t *, pmcs_phy_t *);
327 
328 int pmcs_phy_constructor(void *, void *, int);
329 void pmcs_phy_destructor(void *, void *);
330 
331 void pmcs_inc_phy_ref_count(pmcs_phy_t *);
332 void pmcs_dec_phy_ref_count(pmcs_phy_t *);
333 
334 /* Worker thread */
335 void pmcs_worker(void *);
336 
337 pmcs_phy_t *pmcs_get_root_phy(pmcs_phy_t *);
338 pmcs_xscsi_t *pmcs_get_target(pmcs_iport_t *, char *, boolean_t);
339 
340 void pmcs_fatal_handler(pmcs_hw_t *);
341 
342 /*
343  * Schedule device state recovery for this device immediately
344  */
345 void pmcs_start_dev_state_recovery(pmcs_xscsi_t *, pmcs_phy_t *);
346 
347 /*
348  * Functions to serialize SMP requests
349  */
350 void pmcs_smp_acquire(pmcs_iport_t *iport);
351 void pmcs_smp_release(pmcs_iport_t *iport);
352 
353 /*
354  * Update attached-port-pm and target-port-pm properties on a PHY
355  */
356 void pmcs_update_phy_pm_props(pmcs_phy_t *, uint64_t, uint64_t, boolean_t);
357 
358 /*
359  * Determine whether it's worth retrying enumeration
360  */
361 void pmcs_status_disposition(pmcs_phy_t *, uint32_t);
362 
363 /*
364  * Write out firmware event log (if configured to do so) if it's filled up
365  */
366 void pmcs_gather_fwlog(pmcs_hw_t *);
367 
368 #ifdef	__cplusplus
369 }
370 #endif
371 #endif	/* _PMCS_PROTO_H */
372