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