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, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 /*
30 * hci1394_async.c
31 * These routines manipulate the 1394 asynchronous dma engines. This
32 * includes incoming and outgoing reads, writes, and locks and their
33 * associated responses.
34 */
35
36 #include <sys/conf.h>
37 #include <sys/ddi.h>
38 #include <sys/modctl.h>
39 #include <sys/stat.h>
40 #include <sys/sunddi.h>
41 #include <sys/cmn_err.h>
42 #include <sys/kmem.h>
43 #include <sys/types.h>
44 #include <sys/note.h>
45
46 #include <sys/1394/h1394.h>
47 #include <sys/1394/adapters/hci1394.h>
48
49
50 /*
51 * ASYNC_ARRESP_ACK_ERROR is or'd into the error status when we get an ACK error
52 * on an ARRESP. Since the 1394 response code overlaps with the OpenHCI ACK/EVT
53 * errors, we use this to distinguish between the errors in process_arresp().
54 */
55 #define ASYNC_ARRESP_ACK_ERROR 0x8000
56
57 /* Macro's to help extract 48-bit 1394 address into a uint64_t */
58 #define HCI1394_TO_ADDR_HI(data) (((uint64_t)((data) & 0xFFFF)) << 32)
59 #define HCI1394_TO_ADDR_LO(data) ((uint64_t)((data) & 0xFFFFFFFF))
60
61 /*
62 * Macro to convert a byte stream into a big endian quadlet or octlet or back
63 * the other way. 1394 arithmetic lock operations are done on big endian
64 * quadlets or octlets. compare swaps and bit masks are done on a byte streams.
65 * All data is treated as byte streams over the bus. These macros will convert
66 * the data to a big endian "integer" on x86 plaforms if the operation is an
67 * arithmetic lock operation. It will do nothing if it is not on x86 or is not
68 * an arithmetic lock operation.
69 */
70 #ifdef _LITTLE_ENDIAN
71 #define HCI1394_ARITH_LOCK_SWAP32(tcode, data) \
72 (((tcode) == CMD1394_LOCK_FETCH_ADD) || \
73 ((tcode) == CMD1394_LOCK_BOUNDED_ADD) || \
74 ((tcode) == CMD1394_LOCK_WRAP_ADD)) ? \
75 (ddi_swap32(data)) : (data)
76 #define HCI1394_ARITH_LOCK_SWAP64(tcode, data) \
77 (((tcode) == CMD1394_LOCK_FETCH_ADD) || \
78 ((tcode) == CMD1394_LOCK_BOUNDED_ADD) || \
79 ((tcode) == CMD1394_LOCK_WRAP_ADD)) ? \
80 (ddi_swap64(data)) : (data)
81 #else
82 #define HCI1394_ARITH_LOCK_SWAP32(tcode, data) (data)
83 #define HCI1394_ARITH_LOCK_SWAP64(tcode, data) (data)
84 #endif
85
86
87
88 static int hci1394_async_arresp_read(hci1394_async_handle_t async_handle,
89 hci1394_basic_pkt_t *pkt, uint_t *tcode, hci1394_async_cmd_t **hcicmd,
90 uint_t *size);
91 static int hci1394_async_arresp_size_get(uint_t tcode, hci1394_q_handle_t q,
92 uint32_t *addr, uint_t *size);
93
94 static int hci1394_async_arreq_read(hci1394_async_handle_t async_handle,
95 hci1394_basic_pkt_t *pkt, uint_t *tcode, hci1394_async_cmd_t **hcicmd,
96 uint_t *size);
97 static int hci1394_async_arreq_read_qrd(hci1394_async_handle_t async_handle,
98 hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size);
99 static int hci1394_async_arreq_read_qwr(hci1394_async_handle_t async_handle,
100 hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size);
101 static int hci1394_async_arreq_read_brd(hci1394_async_handle_t async_handle,
102 hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size);
103 static int hci1394_async_arreq_read_bwr(hci1394_async_handle_t async_handle,
104 hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size);
105 static int hci1394_async_arreq_read_lck(hci1394_async_handle_t async_handle,
106 hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size);
107 static int hci1394_async_arreq_read_phy(hci1394_async_handle_t async_handle,
108 hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size,
109 boolean_t *bus_reset_token);
110
111 static void hci1394_async_hcicmd_init(hci1394_async_handle_t async_handle,
112 cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv,
113 hci1394_async_cmd_t **hcicmd);
114
115 static void hci1394_async_atreq_start(void *async, uint32_t command_ptr);
116 static void hci1394_async_arresp_start(void *async, uint32_t command_ptr);
117 static void hci1394_async_arreq_start(void *async, uint32_t command_ptr);
118 static void hci1394_async_atresp_start(void *async, uint32_t command_ptr);
119
120 static void hci1394_async_atreq_wake(void *async);
121 static void hci1394_async_arresp_wake(void *async);
122 static void hci1394_async_arreq_wake(void *async);
123 static void hci1394_async_atresp_wake(void *async);
124
125 static void hci1394_async_atreq_flush(hci1394_async_handle_t async_handle);
126 static void hci1394_async_arresp_flush(hci1394_async_handle_t async_handle);
127 static void hci1394_async_arreq_flush(hci1394_async_handle_t async_handle);
128 static void hci1394_async_atresp_flush(hci1394_async_handle_t async_handle);
129 static void hci1394_async_pending_list_flush(hci1394_async_handle_t
130 async_handle);
131
132 static void hci1394_async_pending_timeout(hci1394_tlist_node_t *node,
133 void *arg);
134 static uint_t hci1394_async_timeout_calc(hci1394_async_handle_t async_handle,
135 uint_t current_time);
136
137 _NOTE(SCHEME_PROTECTS_DATA("unique", msgb))
138
139 /*
140 * hci1394_async_init()
141 * Initialize the async DMA engines and state. We init the tlabels; ATREQ
142 * pending Q; and ATREQ, ARRESP, ARREQ, and ATRESP Q's. init() returns a
143 * handle to be used in rest of the functions.
144 */
145 int
hci1394_async_init(hci1394_drvinfo_t * drvinfo,hci1394_ohci_handle_t ohci_handle,hci1394_csr_handle_t csr_handle,hci1394_async_handle_t * async_handle)146 hci1394_async_init(hci1394_drvinfo_t *drvinfo,
147 hci1394_ohci_handle_t ohci_handle, hci1394_csr_handle_t csr_handle,
148 hci1394_async_handle_t *async_handle)
149 {
150 hci1394_tlist_timer_t timer_info;
151 hci1394_q_info_t qinfo;
152 hci1394_async_t *async;
153 int status;
154
155
156 ASSERT(drvinfo != NULL);
157 ASSERT(ohci_handle != NULL);
158 ASSERT(csr_handle != NULL);
159 ASSERT(async_handle != NULL);
160 TNF_PROBE_0_DEBUG(hci1394_async_init_enter, HCI1394_TNF_HAL_STACK, "");
161
162 /* alloc the space to keep track of the list */
163 async = kmem_alloc(sizeof (hci1394_async_t), KM_SLEEP);
164
165 /* copy in parms to our local state */
166 async->as_drvinfo = drvinfo;
167 async->as_ohci = ohci_handle;
168 async->as_csr = csr_handle;
169 async->as_flushing_arreq = B_FALSE;
170 async->as_phy_reset = 0xFFFFFFFF;
171 mutex_init(&async->as_atomic_lookup, NULL, MUTEX_DRIVER,
172 drvinfo->di_iblock_cookie);
173
174 /*
175 * Initialize the tlabels. Reclaim a bad tlabel after the split timeout
176 * has gone by. This time is in reference to the point the transaction
177 * has been marked as bad. Therefore the tlabel will be reclaimed at
178 * twice the split_timeout. (i.e. if the split timeout was set to 100mS
179 * and the transaction has timed out, 100mS has already gone by. We need
180 * to wait for 100mS more before we can reuse the tlabel. Therefore, the
181 * reclaim time is split_timeout and not split_timeout * 2. The split
182 * timeout is stored as the number of bus cycles. We need to convert
183 * this to nS since the reclaim time is passed as nS.
184 */
185 hci1394_tlabel_init(drvinfo, OHCI_BUS_CYCLE_TO_nS(
186 hci1394_csr_split_timeout_get(csr_handle)), &async->as_tlabel);
187
188 /*
189 * Initialize ATREQ pending list. A pended ATREQ will be timed out after
190 * "split_timeout" has gone by. split timeout is in bus cycles so we
191 * need to convert that to nS for the tlist timer info. We will set the
192 * timer resolution to 1/2 of the timeout so that we will have a worst
193 * case timeout of split timeout + (1/2 * split timeout). See
194 * hci1394_tlist.h for more information about this.
195 */
196 timer_info.tlt_timeout =
197 OHCI_BUS_CYCLE_TO_nS(hci1394_csr_split_timeout_get(csr_handle));
198 timer_info.tlt_timer_resolution = timer_info.tlt_timeout / 2;
199 timer_info.tlt_callback = hci1394_async_pending_timeout;
200 timer_info.tlt_callback_arg = async;
201 hci1394_tlist_init(drvinfo, &timer_info, &async->as_pending_list);
202
203 /* Initialize ATREQ Q */
204 qinfo.qi_desc_size = ASYNC_ATREQ_DESC_SIZE;
205 qinfo.qi_data_size = ASYNC_ATREQ_DATA_SIZE;
206 qinfo.qi_mode = HCI1394_ATQ;
207 qinfo.qi_start = hci1394_async_atreq_start;
208 qinfo.qi_wake = hci1394_async_atreq_wake;
209 qinfo.qi_callback_arg = async;
210 status = hci1394_q_init(drvinfo, async->as_ohci, &qinfo,
211 &async->as_atreq_q);
212 if (status != DDI_SUCCESS) {
213 mutex_destroy(&async->as_atomic_lookup);
214 hci1394_tlist_fini(&async->as_pending_list);
215 hci1394_tlabel_fini(&async->as_tlabel);
216 kmem_free(async, sizeof (hci1394_async_t));
217 *async_handle = NULL;
218 TNF_PROBE_0(hci1394_async_q_init_fail, HCI1394_TNF_HAL_ERROR,
219 "");
220 TNF_PROBE_0_DEBUG(hci1394_async_init_exit,
221 HCI1394_TNF_HAL_STACK, "");
222 return (DDI_FAILURE);
223 }
224
225 /* Initialize ARRESP Q */
226 qinfo.qi_desc_size = ASYNC_ARRESP_DESC_SIZE;
227 qinfo.qi_data_size = ASYNC_ARRESP_DATA_SIZE;
228 qinfo.qi_mode = HCI1394_ARQ;
229 qinfo.qi_start = hci1394_async_arresp_start;
230 qinfo.qi_wake = hci1394_async_arresp_wake;
231 qinfo.qi_callback_arg = async;
232 status = hci1394_q_init(drvinfo, async->as_ohci, &qinfo,
233 &async->as_arresp_q);
234 if (status != DDI_SUCCESS) {
235 mutex_destroy(&async->as_atomic_lookup);
236 hci1394_tlist_fini(&async->as_pending_list);
237 hci1394_tlabel_fini(&async->as_tlabel);
238 hci1394_q_fini(&async->as_atreq_q);
239 kmem_free(async, sizeof (hci1394_async_t));
240 *async_handle = NULL;
241 TNF_PROBE_0(hci1394_async_q_init_fail, HCI1394_TNF_HAL_ERROR,
242 "");
243 TNF_PROBE_0_DEBUG(hci1394_async_init_exit,
244 HCI1394_TNF_HAL_STACK, "");
245 return (DDI_FAILURE);
246 }
247
248 /* Initialize ARREQ Q */
249 qinfo.qi_desc_size = ASYNC_ARREQ_DESC_SIZE;
250 qinfo.qi_data_size = ASYNC_ARREQ_DATA_SIZE;
251 qinfo.qi_mode = HCI1394_ARQ;
252 qinfo.qi_start = hci1394_async_arreq_start;
253 qinfo.qi_wake = hci1394_async_arreq_wake;
254 qinfo.qi_callback_arg = async;
255 status = hci1394_q_init(drvinfo, async->as_ohci, &qinfo,
256 &async->as_arreq_q);
257 if (status != DDI_SUCCESS) {
258 mutex_destroy(&async->as_atomic_lookup);
259 hci1394_tlist_fini(&async->as_pending_list);
260 hci1394_tlabel_fini(&async->as_tlabel);
261 hci1394_q_fini(&async->as_atreq_q);
262 hci1394_q_fini(&async->as_arresp_q);
263 kmem_free(async, sizeof (hci1394_async_t));
264 *async_handle = NULL;
265 TNF_PROBE_0(hci1394_async_q_init_fail, HCI1394_TNF_HAL_ERROR,
266 "");
267 TNF_PROBE_0_DEBUG(hci1394_async_init_exit,
268 HCI1394_TNF_HAL_STACK, "");
269 return (DDI_FAILURE);
270 }
271
272 /* Initialize ATRESP Q */
273 qinfo.qi_desc_size = ASYNC_ATRESP_DESC_SIZE;
274 qinfo.qi_data_size = ASYNC_ATRESP_DATA_SIZE;
275 qinfo.qi_mode = HCI1394_ATQ;
276 qinfo.qi_start = hci1394_async_atresp_start;
277 qinfo.qi_wake = hci1394_async_atresp_wake;
278 qinfo.qi_callback_arg = async;
279 status = hci1394_q_init(drvinfo, async->as_ohci, &qinfo,
280 &async->as_atresp_q);
281 if (status != DDI_SUCCESS) {
282 mutex_destroy(&async->as_atomic_lookup);
283 hci1394_tlist_fini(&async->as_pending_list);
284 hci1394_tlabel_fini(&async->as_tlabel);
285 hci1394_q_fini(&async->as_atreq_q);
286 hci1394_q_fini(&async->as_arresp_q);
287 hci1394_q_fini(&async->as_arreq_q);
288 kmem_free(async, sizeof (hci1394_async_t));
289 *async_handle = NULL;
290 TNF_PROBE_0(hci1394_async_q_init_fail, HCI1394_TNF_HAL_ERROR,
291 "");
292 TNF_PROBE_0_DEBUG(hci1394_async_init_exit,
293 HCI1394_TNF_HAL_STACK, "");
294 return (DDI_FAILURE);
295 }
296
297 *async_handle = async;
298
299 TNF_PROBE_0_DEBUG(hci1394_async_init_exit, HCI1394_TNF_HAL_STACK, "");
300
301 return (DDI_SUCCESS);
302 }
303
304
305 /*
306 * hci1394_async_fini()
307 * Free's up the space allocated in init(). Notice that a pointer to the
308 * handle is used for the parameter. fini() will set your handle to NULL
309 * before returning.
310 */
311 void
hci1394_async_fini(hci1394_async_handle_t * async_handle)312 hci1394_async_fini(hci1394_async_handle_t *async_handle)
313 {
314 hci1394_async_t *async;
315
316
317 ASSERT(async_handle != NULL);
318 TNF_PROBE_0_DEBUG(hci1394_async_fini_enter, HCI1394_TNF_HAL_STACK, "");
319
320 async = (hci1394_async_t *)*async_handle;
321
322 mutex_destroy(&async->as_atomic_lookup);
323 hci1394_tlabel_fini(&async->as_tlabel);
324 hci1394_tlist_fini(&async->as_pending_list);
325 hci1394_q_fini(&async->as_atreq_q);
326 hci1394_q_fini(&async->as_atresp_q);
327 hci1394_q_fini(&async->as_arreq_q);
328 hci1394_q_fini(&async->as_arresp_q);
329
330 kmem_free(async, sizeof (hci1394_async_t));
331
332 /* set handle to null. This helps catch bugs. */
333 *async_handle = NULL;
334
335 TNF_PROBE_0_DEBUG(hci1394_async_fini_exit, HCI1394_TNF_HAL_STACK, "");
336 }
337
338
339 /*
340 * hci1394_async_suspend()
341 * The system is getting ready to be suspended. Make sure that all of
342 * the Q's are clean and that the there are no scheduled timeouts in the
343 * pending Q.
344 */
345 void
hci1394_async_suspend(hci1394_async_handle_t async_handle)346 hci1394_async_suspend(hci1394_async_handle_t async_handle)
347 {
348 ASSERT(async_handle != NULL);
349 TNF_PROBE_0_DEBUG(hci1394_async_suspend_enter,
350 HCI1394_TNF_HAL_STACK, "");
351
352 /* Flush out async DMA Q's */
353 hci1394_async_flush(async_handle);
354
355 /* Cancel any scheduled pending timeouts */
356 hci1394_tlist_timeout_cancel(async_handle->as_pending_list);
357
358 TNF_PROBE_0_DEBUG(hci1394_async_suspend_exit,
359 HCI1394_TNF_HAL_STACK, "");
360 }
361
362
363 /*
364 * hci1394_async_resume()
365 * Re-setup the DMA Q's during a resume after a successful suspend. The
366 * tlabels will be re-initialized during the bus reset and the pending Q will
367 * be flushed during the suspend.
368 */
369 int
hci1394_async_resume(hci1394_async_handle_t async_handle)370 hci1394_async_resume(hci1394_async_handle_t async_handle)
371 {
372 ASSERT(async_handle != NULL);
373 TNF_PROBE_0_DEBUG(hci1394_async_resume_enter,
374 HCI1394_TNF_HAL_STACK, "");
375
376 hci1394_q_resume(async_handle->as_atreq_q);
377 hci1394_q_resume(async_handle->as_atresp_q);
378 hci1394_q_resume(async_handle->as_arreq_q);
379 hci1394_q_resume(async_handle->as_arresp_q);
380
381 TNF_PROBE_0_DEBUG(hci1394_async_resume_exit,
382 HCI1394_TNF_HAL_STACK, "");
383
384 return (DDI_SUCCESS);
385 }
386
387
388 /*
389 * hci1394_async_cmd_overhead()
390 * Return the size of the HAL private area to attach to every alloced 1394
391 * framework command. This allows us to track command state without having
392 * to alloc memory every time a command comes down the pipe.
393 */
394 uint_t
hci1394_async_cmd_overhead()395 hci1394_async_cmd_overhead()
396 {
397 return (sizeof (hci1394_async_cmd_t));
398 }
399
400
401 /*
402 * hci1394_async_flush()
403 * Flush out the Async Q's and the ATREQ pending list. This is called every
404 * bus reset so that we're sync'd up with the HW and when shutting down or
405 * suspending to make sure we cleanup after all commands.
406 */
407 void
hci1394_async_flush(hci1394_async_handle_t async_handle)408 hci1394_async_flush(hci1394_async_handle_t async_handle)
409 {
410 ASSERT(async_handle != NULL);
411 TNF_PROBE_0_DEBUG(hci1394_async_flush_enter, HCI1394_TNF_HAL_STACK, "");
412
413 hci1394_async_atreq_flush(async_handle);
414 hci1394_async_arresp_flush(async_handle);
415 hci1394_async_pending_list_flush(async_handle);
416 hci1394_async_arreq_flush(async_handle);
417 hci1394_async_atresp_flush(async_handle);
418 hci1394_tlabel_reset(async_handle->as_tlabel);
419
420 TNF_PROBE_0_DEBUG(hci1394_async_flush_exit, HCI1394_TNF_HAL_STACK, "");
421 }
422
423
424 /*
425 * hci1394_async_pending_timeout_update()
426 * Update the timeout for the pending list. This updates both the pending
427 * list timeout and time we wait to reclaim bad tlabels. timeout is the
428 * time in nS so we do not have to do any conversions. This routine will be
429 * called when the CSR split timeout registers are updated.
430 */
431 void
hci1394_async_pending_timeout_update(hci1394_async_handle_t async_handle,hrtime_t timeout)432 hci1394_async_pending_timeout_update(hci1394_async_handle_t async_handle,
433 hrtime_t timeout)
434 {
435 ASSERT(async_handle != NULL);
436 TNF_PROBE_0_DEBUG(hci1394_async_pending_timeout_update_enter,
437 HCI1394_TNF_HAL_STACK, "");
438 hci1394_tlist_timeout_update(async_handle->as_pending_list, timeout);
439 hci1394_tlabel_set_reclaim_time(async_handle->as_tlabel, timeout);
440 TNF_PROBE_0_DEBUG(hci1394_async_pending_timeout_update_exit,
441 HCI1394_TNF_HAL_STACK, "");
442 }
443
444
445 /*
446 * hci1394_async_atreq_process()
447 * Process an atreq, if one has completed. This is called during interrupt
448 * processing and will process a completed atreq. It returns status if an
449 * atreq was processed so that the ISR knows that it needs to be called
450 * again to see if another ATREQ has completed. flush_q set to B_TRUE tells
451 * this routine to process all commands regardless of their completion
452 * status. This is used during bus reset processing to remove all commands
453 * from the Q.
454 *
455 * There are a few race conditions that we have to watch for in atreq/arresp.
456 * They all have to do with pended responses so they are not applicable in
457 * the ARREQ/ATRESP engine (since ATRESP's can't be pended).
458 *
459 * Since the race conditions only exist for pended responses, we will only
460 * talk about that sequence here. We're also going to simplify the discussion
461 * so what the code does, so it won't exactly match what we say (e.g. we
462 * don't always setup a timeout for every single command, etc.)
463 *
464 * After Q'ing up an ATREQ, we will process the result of that command in
465 * one of a couple different paths. A normal condition would be that we Q up
466 * a command, we get an ATREQ complete interrupt and look at the ATREQ
467 * result. In the case it has been pended, we setup a timeout to wait for the
468 * response. If we receive the response before the timeout, the command is
469 * done and we send the response up the chain, if we do not, the command is
470 * done and we send a timeout notification up the chain.
471 *
472 * The first race condition is when we get the timeout at the same time as
473 * the response. At first glance a mutex around the command state would
474 * solve this problem. But on a multi-processor machine, we may have the
475 * ARRESP interrupt handler(ISR) running on one processor and the timeout on
476 * another. This means that the command state could change between two
477 * reads while in the ISR. This means we need to have a little more complex
478 * logic around changing the command state and have to be careful how and
479 * when we do this.
480 *
481 * The second race condition is that we could see the ARRESP before we
482 * process the ATREQ. We could be processing a few ARRESP from previous
483 * ATREQ's when the ATREQ completes and then the ARRESP comes in. Since we
484 * already are in the interrupt handler, the ATREQ complete will not preempt
485 * us.
486 *
487 * We will never see a race condition between the ATREQ interrupt for a
488 * command and the pending timeout since the command is not being timed until
489 * this routine is run for that command.
490 */
491 int
hci1394_async_atreq_process(hci1394_async_handle_t async_handle,boolean_t flush_q,boolean_t * request_available)492 hci1394_async_atreq_process(hci1394_async_handle_t async_handle,
493 boolean_t flush_q, boolean_t *request_available)
494 {
495 hci1394_async_cmd_t *hcicmd;
496 hci1394_q_cmd_t *qcmd;
497 int cmd_status;
498
499
500 ASSERT(async_handle != NULL);
501 ASSERT(request_available != NULL);
502
503 TNF_PROBE_0_DEBUG(hci1394_async_atreq_process_enter,
504 HCI1394_TNF_HAL_STACK, "");
505
506 /*
507 * Get the next ATREQ that has completed (if one has). Space is free'd
508 * up in atreq_q and atreq_data_q as part of this function call.
509 */
510 hci1394_q_at_next(async_handle->as_atreq_q, flush_q, &qcmd);
511
512 /*
513 * See if there were anymore requests on ATREQ Q. A NULL means there
514 * were no completed commands left on the Q
515 */
516 if (qcmd == NULL) {
517 *request_available = B_FALSE;
518 TNF_PROBE_0_DEBUG(hci1394_async_atreq_process_exit,
519 HCI1394_TNF_HAL_STACK, "");
520 return (DDI_SUCCESS);
521 }
522
523 /* There is a completed ATREQ, setup the HAL command pointer */
524 *request_available = B_TRUE;
525 hcicmd = (hci1394_async_cmd_t *)qcmd->qc_arg;
526
527 TNF_PROBE_1_DEBUG(hci1394_atreq_ack, HCI1394_TNF_HAL, "", tnf_uint,
528 atreq_ack, qcmd->qc_status);
529
530 /* save away the command completed timestamp for the services layer */
531 hcicmd->ac_priv->ack_tstamp = qcmd->qc_timestamp;
532
533 /*
534 * Make sure this command has not already been processed. This command
535 * may have already received a response. If the ACK was not an ACK
536 * pending, we have a HW error (i.e. The target HW sent a response to a
537 * non-pended request). There is a race condition where the software
538 * will see and complete a response before processing it's ACK Pending.
539 * This can only happen for ACK pendings. We have seen this race
540 * condition and response to a non-pended request during real-world
541 * testing :-)
542 */
543 if (hcicmd->ac_state != HCI1394_CMD_STATE_IN_PROGRESS) {
544 /*
545 * we already processed the ARRESP in arresp_process(), it
546 * better have been ACK pended. Otherwise the target device
547 * performed an illegal action.
548 */
549 if (qcmd->qc_status == OHCI_ACK_PENDING) {
550 /*
551 * Tell source that their command has completed. We're
552 * done with this command.
553 * NOTE: We use ac_status which was set in
554 * process_arresp()
555 */
556 h1394_cmd_is_complete(
557 async_handle->as_drvinfo->di_sl_private,
558 hcicmd->ac_cmd, H1394_AT_REQ,
559 hcicmd->ac_status);
560 TNF_PROBE_0_DEBUG(hci1394_async_atreq_process_exit,
561 HCI1394_TNF_HAL_STACK, "");
562 return (DDI_SUCCESS);
563 /*
564 * This is a HW error. Process the ACK like we never saw the
565 * response. We will do this below.
566 */
567 } else {
568 TNF_PROBE_1(hci1394_async_ack_fail,
569 HCI1394_TNF_HAL_ERROR, "", tnf_string, errmsg,
570 "response sent to non-pended ack");
571 }
572 }
573
574 /*
575 * if we got an ack pending, add it to the pending list and leave. We
576 * will either get an ARRESP or the pending list will timeout the
577 * response.
578 */
579 if (qcmd->qc_status == OHCI_ACK_PENDING) {
580 hcicmd->ac_state = HCI1394_CMD_STATE_PENDING;
581 /* Add this command to the pending list */
582 hcicmd->ac_plist_node.tln_addr = hcicmd;
583 hci1394_tlist_add(async_handle->as_pending_list,
584 &hcicmd->ac_plist_node);
585 TNF_PROBE_0_DEBUG(hci1394_async_atreq_process_exit,
586 HCI1394_TNF_HAL_STACK, "");
587 return (DDI_SUCCESS);
588 }
589
590 /*
591 * setup our return command status based on the ACK from the HW. See the
592 * OpenHCI 1.0 spec (table 3.2 on pg. 18) for more information about
593 * these ACK/EVT's.
594 */
595 switch (qcmd->qc_status) {
596 case OHCI_ACK_COMPLETE:
597 cmd_status = H1394_CMD_SUCCESS;
598 break;
599
600 /*
601 * we can get a nostatus during a bus reset (i.e. we shutdown the AT
602 * engine before it flushed all the commands)
603 */
604 case OHCI_EVT_FLUSHED:
605 case OHCI_EVT_NO_STATUS:
606 cmd_status = H1394_CMD_EBUSRESET;
607 break;
608
609 case OHCI_EVT_MISSING_ACK:
610 case OHCI_EVT_TIMEOUT:
611 TNF_PROBE_3(hci1394_atreq_ack_err, HCI1394_TNF_HAL_ERROR,
612 "", tnf_uint, nodeid,
613 IEEE1394_NODE_NUM(hcicmd->ac_tlabel.tbi_destination),
614 tnf_uint, tx_tlabel, hcicmd->ac_tlabel.tbi_tlabel,
615 tnf_uint, atreq_ack, qcmd->qc_status);
616 cmd_status = H1394_CMD_ETIMEOUT;
617 break;
618
619 case OHCI_ACK_BUSY_X:
620 case OHCI_ACK_BUSY_A:
621 case OHCI_ACK_BUSY_B:
622 cmd_status = H1394_CMD_EDEVICE_BUSY;
623 TNF_PROBE_3(hci1394_atreq_ack_err, HCI1394_TNF_HAL_ERROR,
624 "", tnf_uint, nodeid,
625 IEEE1394_NODE_NUM(hcicmd->ac_tlabel.tbi_destination),
626 tnf_uint, tx_tlabel, hcicmd->ac_tlabel.tbi_tlabel,
627 tnf_uint, atreq_ack, qcmd->qc_status);
628 break;
629
630 case OHCI_ACK_TARDY:
631 cmd_status = H1394_CMD_EDEVICE_POWERUP;
632 TNF_PROBE_3(hci1394_atreq_ack_err, HCI1394_TNF_HAL_ERROR,
633 "", tnf_uint, nodeid,
634 IEEE1394_NODE_NUM(hcicmd->ac_tlabel.tbi_destination),
635 tnf_uint, tx_tlabel, hcicmd->ac_tlabel.tbi_tlabel,
636 tnf_uint, atreq_ack, qcmd->qc_status);
637 break;
638
639 case OHCI_ACK_DATA_ERROR:
640 cmd_status = H1394_CMD_EDATA_ERROR;
641 TNF_PROBE_3(hci1394_atreq_ack_err, HCI1394_TNF_HAL_ERROR,
642 "", tnf_uint, nodeid,
643 IEEE1394_NODE_NUM(hcicmd->ac_tlabel.tbi_destination),
644 tnf_uint, tx_tlabel, hcicmd->ac_tlabel.tbi_tlabel,
645 tnf_uint, atreq_ack, qcmd->qc_status);
646 break;
647
648 case OHCI_ACK_TYPE_ERROR:
649 cmd_status = H1394_CMD_ETYPE_ERROR;
650 TNF_PROBE_3(hci1394_atreq_ack_err, HCI1394_TNF_HAL_ERROR,
651 "", tnf_uint, nodeid,
652 IEEE1394_NODE_NUM(hcicmd->ac_tlabel.tbi_destination),
653 tnf_uint, tx_tlabel, hcicmd->ac_tlabel.tbi_tlabel,
654 tnf_uint, atreq_ack, qcmd->qc_status);
655 break;
656
657 case OHCI_ACK_CONFLICT_ERROR:
658 cmd_status = H1394_CMD_ERSRC_CONFLICT;
659 TNF_PROBE_3(hci1394_atreq_ack_err, HCI1394_TNF_HAL_ERROR,
660 "", tnf_uint, nodeid,
661 IEEE1394_NODE_NUM(hcicmd->ac_tlabel.tbi_destination),
662 tnf_uint, tx_tlabel, hcicmd->ac_tlabel.tbi_tlabel,
663 tnf_uint, atreq_ack, qcmd->qc_status);
664 break;
665
666 case OHCI_ACK_ADDRESS_ERROR:
667 cmd_status = H1394_CMD_EADDR_ERROR;
668 TNF_PROBE_3(hci1394_atreq_ack_err, HCI1394_TNF_HAL_ERROR,
669 "", tnf_uint, nodeid,
670 IEEE1394_NODE_NUM(hcicmd->ac_tlabel.tbi_destination),
671 tnf_uint, tx_tlabel, hcicmd->ac_tlabel.tbi_tlabel,
672 tnf_uint, atreq_ack, qcmd->qc_status);
673 break;
674
675 case OHCI_EVT_UNDERRUN:
676 case OHCI_EVT_DATA_READ:
677 case OHCI_EVT_TCODE_ERR:
678 case OHCI_EVT_DESCRIPTOR_READ:
679 case OHCI_EVT_UNKNOWN:
680 default:
681 cmd_status = H1394_CMD_EUNKNOWN_ERROR;
682 TNF_PROBE_3(hci1394_atreq_ack_err, HCI1394_TNF_HAL_ERROR,
683 "", tnf_uint, nodeid,
684 IEEE1394_NODE_NUM(hcicmd->ac_tlabel.tbi_destination),
685 tnf_uint, tx_tlabel, hcicmd->ac_tlabel.tbi_tlabel,
686 tnf_uint, atreq_ack, qcmd->qc_status);
687 break;
688 }
689
690 /*
691 * Free the tlabel that was used for this transfer. We will not try and
692 * free the tlabel in the case that we already received a response or if
693 * we did not allocate one (PHY packet). If we already received a
694 * response, the tlabel would have been free'd in
695 * hci1394_async_arresp_process().
696 */
697 if ((hcicmd->ac_state == HCI1394_CMD_STATE_IN_PROGRESS) &&
698 (hcicmd->ac_tlabel_alloc == B_TRUE)) {
699 hci1394_tlabel_free(async_handle->as_tlabel,
700 &hcicmd->ac_tlabel);
701 }
702
703 /*
704 * if we got anything other than and ACK pending, we are done w/ this
705 * transaction.
706 */
707 hcicmd->ac_state = HCI1394_CMD_STATE_COMPLETED;
708
709 /* tell the services layer that the command has completed */
710 h1394_cmd_is_complete(async_handle->as_drvinfo->di_sl_private,
711 hcicmd->ac_cmd, H1394_AT_REQ, cmd_status);
712
713 TNF_PROBE_0_DEBUG(hci1394_async_atreq_process_exit,
714 HCI1394_TNF_HAL_STACK, "");
715
716 return (DDI_SUCCESS);
717 }
718
719
720 /*
721 * hci1394_async_arresp_process()
722 * Process an arresp, if one has completed. This is called during interrupt
723 * processing and will process a completed arresp. It returns status if an
724 * arresp was processed so that the ISR knows that it needs to be called
725 * again to see if another ARRESP has completed.
726 */
727 int
hci1394_async_arresp_process(hci1394_async_handle_t async_handle,boolean_t * response_available)728 hci1394_async_arresp_process(hci1394_async_handle_t async_handle,
729 boolean_t *response_available)
730 {
731 hci1394_async_cmd_t *hcicmd;
732 uint32_t *addr;
733 int cmd_status;
734 uint_t tcode;
735 uint_t size;
736 int status;
737
738
739 ASSERT(async_handle != NULL);
740 ASSERT(response_available != NULL);
741
742 TNF_PROBE_0_DEBUG(hci1394_async_arresp_process_enter,
743 HCI1394_TNF_HAL_STACK, "");
744
745 /*
746 * See if there were any responses on ARRESP Q. A NULL means there
747 * were no responses on the Q. This call does NOT free up space. We
748 * need to do that later after we figure out how much space the
749 * response takes up.
750 */
751 hci1394_q_ar_next(async_handle->as_arresp_q, &addr);
752 if (addr == NULL) {
753 *response_available = B_FALSE;
754 TNF_PROBE_0_DEBUG(hci1394_async_arresp_process_exit,
755 HCI1394_TNF_HAL_STACK, "");
756 return (DDI_SUCCESS);
757 }
758
759 /*
760 * We got a response. Lock out pending timeout callback from marking
761 * tlabel bad.
762 */
763 *response_available = B_TRUE;
764 mutex_enter(&async_handle->as_atomic_lookup);
765
766 /*
767 * Read in the response into the 1394 framework command. We could get a
768 * NULL for a command if we got a response with an error (i.e. tlabel
769 * that didn't match a request) This would be a successful read but with
770 * a NULL hcicmd returned. If we ever get a DDI_FAILURE, we will
771 * shutdown.
772 */
773 status = hci1394_async_arresp_read(async_handle,
774 (hci1394_basic_pkt_t *)addr, &tcode, &hcicmd, &size);
775 if (status != DDI_SUCCESS) {
776 mutex_exit(&async_handle->as_atomic_lookup);
777 h1394_error_detected(async_handle->as_drvinfo->di_sl_private,
778 H1394_SELF_INITIATED_SHUTDOWN, NULL);
779 cmn_err(CE_WARN, "hci1394(%d): driver shutdown: "
780 "unrecoverable error interrupt detected",
781 async_handle->as_drvinfo->di_instance);
782 hci1394_shutdown(async_handle->as_drvinfo->di_dip);
783 TNF_PROBE_0(hci1394_async_arresp_read_fail,
784 HCI1394_TNF_HAL_ERROR, "");
785 TNF_PROBE_0_DEBUG(hci1394_async_arresp_process_exit,
786 HCI1394_TNF_HAL_STACK, "");
787 return (DDI_FAILURE);
788 }
789
790 /* Free up the arresp Q space, we are done with the data */
791 hci1394_q_ar_free(async_handle->as_arresp_q, size);
792
793 /*
794 * if we did not get a valid command response (i.e. we got a bad tlabel
795 * or something like that) we don't have anything else to do. We will
796 * say that we processed a response and will return successfully. We
797 * still may have other responses on the Q.
798 */
799 if (hcicmd == NULL) {
800 mutex_exit(&async_handle->as_atomic_lookup);
801 TNF_PROBE_0_DEBUG(hci1394_async_arresp_process_exit,
802 HCI1394_TNF_HAL_STACK, "");
803 return (DDI_SUCCESS);
804 }
805
806 TNF_PROBE_1_DEBUG(hci1394_arresp_resp, HCI1394_TNF_HAL, "", tnf_uint,
807 atresp_resp, hcicmd->ac_status);
808
809 /*
810 * Make sure this is in the pending list. There is a small chance that
811 * we will see the response before we see the ACK PENDING. If it is the
812 * expected case, it is in the pending list. We will remove it since
813 * we are done with the command.
814 *
815 * NOTE: there is a race condition here with the pending timeout. Look
816 * at the comments before hci1394_async_atreq_process() for more info.
817 */
818 if (hcicmd->ac_state == HCI1394_CMD_STATE_PENDING) {
819 /* remove this transfer from our the pending list */
820 status = hci1394_tlist_delete(async_handle->as_pending_list,
821 &hcicmd->ac_plist_node);
822 if (status != DDI_SUCCESS) {
823 mutex_exit(&async_handle->as_atomic_lookup);
824 TNF_PROBE_0_DEBUG(hci1394_async_arresp_process_exit,
825 HCI1394_TNF_HAL_STACK, "");
826 return (DDI_SUCCESS);
827 }
828 }
829
830 /* allow pending timeout callback to mark tlabel as bad */
831 mutex_exit(&async_handle->as_atomic_lookup);
832
833 /*
834 * We got a valid response that we were able to read in. Free the tlabel
835 * that was used for this transfer.
836 */
837 hci1394_tlabel_free(async_handle->as_tlabel, &hcicmd->ac_tlabel);
838
839 /*
840 * Setup our return command status based on the RESP or ACK or SW error.
841 * See the IEEE1394-1995 spec (6.2.4.10 on pg. 159) for more information
842 * on response codes. See the OpenHCI 1.0 spec (table 3.2 on pg. 18) for
843 * more information about ACK/EVT's. ac_status could have an IEEE1394
844 * response in it, a 1394 EVT/ACK, or a special cmd1394 error for a
845 * device error caught in SW (e.g. for a block read request that got a
846 * quadlet read response). We use a special mask to separate the
847 * ACK/EVT's from the responses (ASYNC_ARRESP_ACK_ERROR).
848 */
849 switch (hcicmd->ac_status) {
850 case IEEE1394_RESP_COMPLETE:
851 cmd_status = H1394_CMD_SUCCESS;
852 break;
853 case IEEE1394_RESP_DATA_ERROR:
854 cmd_status = H1394_CMD_EDATA_ERROR;
855 break;
856 case IEEE1394_RESP_TYPE_ERROR:
857 cmd_status = H1394_CMD_ETYPE_ERROR;
858 break;
859 case IEEE1394_RESP_CONFLICT_ERROR:
860 cmd_status = H1394_CMD_ERSRC_CONFLICT;
861 break;
862 case IEEE1394_RESP_ADDRESS_ERROR:
863 cmd_status = H1394_CMD_EADDR_ERROR;
864 break;
865 case H1394_CMD_EDEVICE_ERROR:
866 cmd_status = H1394_CMD_EDEVICE_ERROR;
867 break;
868 case OHCI_ACK_DATA_ERROR | ASYNC_ARRESP_ACK_ERROR:
869 cmd_status = H1394_CMD_EDATA_ERROR;
870 break;
871 case OHCI_ACK_TYPE_ERROR | ASYNC_ARRESP_ACK_ERROR:
872 cmd_status = H1394_CMD_ETYPE_ERROR;
873 break;
874 case OHCI_EVT_UNDERRUN | ASYNC_ARRESP_ACK_ERROR:
875 case OHCI_EVT_DATA_READ | ASYNC_ARRESP_ACK_ERROR:
876 case OHCI_EVT_TCODE_ERR | ASYNC_ARRESP_ACK_ERROR:
877 cmd_status = H1394_CMD_EUNKNOWN_ERROR;
878 break;
879 default:
880 cmd_status = H1394_CMD_EUNKNOWN_ERROR;
881 TNF_PROBE_1(hci1394_async_ack_err, HCI1394_TNF_HAL_ERROR,
882 "", tnf_uint, arresp_resp, hcicmd->ac_status);
883 break;
884 }
885
886 /*
887 * if we have already processed the atreq and put it on the pending Q
888 * (normal case), tell the services layer it completed.
889 */
890 if (hcicmd->ac_state == HCI1394_CMD_STATE_PENDING) {
891 /* Set state indicating that we are done with this cmd */
892 hcicmd->ac_state = HCI1394_CMD_STATE_COMPLETED;
893
894 /* tell the services lyaer the command has completed */
895 h1394_cmd_is_complete(async_handle->as_drvinfo->di_sl_private,
896 hcicmd->ac_cmd, H1394_AT_REQ, cmd_status);
897
898 /*
899 * We have not seen the atreq status yet. We will call
900 * h1394_command_is_complete() in atreq_process() in case we did not get
901 * an ack pending (target HW error -> this is based on real world
902 * experience :-))
903 */
904 } else {
905 /* Set state indicating that we are done with this cmd */
906 hcicmd->ac_state = HCI1394_CMD_STATE_COMPLETED;
907
908 /* save away the status for atreq_process() */
909 hcicmd->ac_status = cmd_status;
910 }
911
912 TNF_PROBE_0_DEBUG(hci1394_async_arresp_process_exit,
913 HCI1394_TNF_HAL_STACK, "");
914
915 return (DDI_SUCCESS);
916 }
917
918
919 /*
920 * hci1394_async_arreq_process()
921 * Process an arreq, if one has arrived. This is called during interrupt
922 * processing and will process an arreq that has arrived. It returns status
923 * if an arreq was processed so that the ISR knows that it needs to be
924 * called again to see if another ARREQ has arrived.
925 */
926 int
hci1394_async_arreq_process(hci1394_async_handle_t async_handle,boolean_t * request_available)927 hci1394_async_arreq_process(hci1394_async_handle_t async_handle,
928 boolean_t *request_available)
929 {
930 hci1394_async_cmd_t *hcicmd;
931 uint32_t *addr;
932 uint_t tcode;
933 uint_t size;
934 int status;
935
936
937 ASSERT(async_handle != NULL);
938 ASSERT(request_available != NULL);
939
940 TNF_PROBE_0_DEBUG(hci1394_async_arreq_process_enter,
941 HCI1394_TNF_HAL_STACK, "");
942
943 /*
944 * See if there were any requests on ARREQ Q. A NULL means there
945 * were no requests on the Q. This call does NOT free up space. We
946 * need to do that later after we figure out how much space the
947 * request takes up.
948 */
949 hci1394_q_ar_next(async_handle->as_arreq_q, &addr);
950 if (addr == NULL) {
951 *request_available = B_FALSE;
952 TNF_PROBE_0_DEBUG(hci1394_async_arreq_process_exit,
953 HCI1394_TNF_HAL_STACK, "");
954 return (DDI_SUCCESS);
955 }
956
957 /*
958 * We got a request. Read the request into a 1394 framework command.
959 * We could get a NULL for a command if we got a request with an error
960 * (i.e. ARREQ ACK was not ack pending or ack complete). This would be a
961 * successful read but with a NULL hcicmd returned. If we ever get a
962 * DDI_FAILURE, we will shutdown.
963 */
964 *request_available = B_TRUE;
965 status = hci1394_async_arreq_read(async_handle,
966 (hci1394_basic_pkt_t *)addr, &tcode, &hcicmd, &size);
967 if (status != DDI_SUCCESS) {
968 h1394_error_detected(async_handle->as_drvinfo->di_sl_private,
969 H1394_SELF_INITIATED_SHUTDOWN, NULL);
970 cmn_err(CE_WARN, "hci1394(%d): driver shutdown: "
971 "unrecoverable error interrupt detected",
972 async_handle->as_drvinfo->di_instance);
973 hci1394_shutdown(async_handle->as_drvinfo->di_dip);
974 TNF_PROBE_0(hci1394_async_arreq_read_fail,
975 HCI1394_TNF_HAL_ERROR, "");
976 TNF_PROBE_0_DEBUG(hci1394_async_arreq_process_exit,
977 HCI1394_TNF_HAL_STACK, "");
978 return (DDI_FAILURE);
979 }
980
981 /* Free up the arreq Q space, we are done with the data */
982 hci1394_q_ar_free(async_handle->as_arreq_q, size);
983
984 /*
985 * if we did not get a valid request (i.e. The ARREQ had a bad ACK
986 * or something like that) we don't have anything else to do. We will
987 * say that we processed a request and will return successfully. We
988 * still may have other requests on the Q.
989 */
990 if (hcicmd == NULL) {
991 TNF_PROBE_0_DEBUG(hci1394_async_arreq_process_exit,
992 HCI1394_TNF_HAL_STACK, "");
993 return (DDI_SUCCESS);
994 }
995
996 /*
997 * If as_flushing_arreq is set, we do not want to send any requests up
998 * to the Services Layer. We are flushing the ARREQ until we see a bus
999 * reset token that matches the current bus generation. Free up the
1000 * alloc'd command and return success.
1001 */
1002 if (async_handle->as_flushing_arreq == B_TRUE) {
1003 hci1394_async_response_complete(async_handle, hcicmd->ac_cmd,
1004 hcicmd->ac_priv);
1005 TNF_PROBE_0_DEBUG(hci1394_async_arreq_process_exit,
1006 HCI1394_TNF_HAL_STACK, "");
1007 return (DDI_SUCCESS);
1008 }
1009
1010 TNF_PROBE_1_DEBUG(hci1394_arreq_ack, HCI1394_TNF_HAL, "", tnf_uint,
1011 arreq_ack, hcicmd->ac_status);
1012
1013 /*
1014 * We got a valid request that we were able to read in. Call into the
1015 * services layer based on the type of request.
1016 */
1017 switch (tcode) {
1018 case IEEE1394_TCODE_READ_QUADLET:
1019 case IEEE1394_TCODE_READ_BLOCK:
1020 h1394_read_request(async_handle->as_drvinfo->di_sl_private,
1021 hcicmd->ac_cmd);
1022 break;
1023 case IEEE1394_TCODE_WRITE_QUADLET:
1024 case IEEE1394_TCODE_WRITE_BLOCK:
1025 h1394_write_request(async_handle->as_drvinfo->di_sl_private,
1026 hcicmd->ac_cmd);
1027 break;
1028 case IEEE1394_TCODE_LOCK:
1029 h1394_lock_request(async_handle->as_drvinfo->di_sl_private,
1030 hcicmd->ac_cmd);
1031 break;
1032 case IEEE1394_TCODE_PHY:
1033 /*
1034 * OpenHCI only handles 1 PHY quadlet at a time. If a selfid
1035 * packet was received with multiple quadlets, we will treat
1036 * each quadlet as a separate call. We do not notify the
1037 * services layer through the normal command interface, we will
1038 * treat it like a command internally and then free up the
1039 * command ourselves when we are done with it.
1040 */
1041 h1394_phy_packet(async_handle->as_drvinfo->di_sl_private,
1042 &hcicmd->ac_cmd->cmd_u.q.quadlet_data, 1,
1043 hcicmd->ac_priv->recv_tstamp);
1044 /* free alloc'd command */
1045 hci1394_async_response_complete(async_handle, hcicmd->ac_cmd,
1046 hcicmd->ac_priv);
1047 break;
1048 default:
1049 /* free alloc'd command */
1050 hci1394_async_response_complete(async_handle, hcicmd->ac_cmd,
1051 hcicmd->ac_priv);
1052 TNF_PROBE_1(hci1394_async_arreq_tcode_err,
1053 HCI1394_TNF_HAL_ERROR, "", tnf_uint, arreq_tcode, tcode);
1054 break;
1055 }
1056
1057 TNF_PROBE_0_DEBUG(hci1394_async_arreq_process_exit,
1058 HCI1394_TNF_HAL_STACK, "");
1059
1060 return (DDI_SUCCESS);
1061 }
1062
1063
1064 /*
1065 * hci1394_async_atresp_process()
1066 * Process an atresp, if one has completed. This is called during interrupt
1067 * processing and will process a completed atresp. It returns status if an
1068 * atresp was processed so that the ISR knows that it needs to be called
1069 * again to see if another ATRESP has completed. flush_q set to B_TRUE tells
1070 * this routine to process all commands regardless of their completion
1071 * status. This is used during bus reset processing to remove all commands
1072 * from the Q.
1073 */
1074 int
hci1394_async_atresp_process(hci1394_async_handle_t async_handle,boolean_t flush_q,boolean_t * response_available)1075 hci1394_async_atresp_process(hci1394_async_handle_t async_handle,
1076 boolean_t flush_q, boolean_t *response_available)
1077 {
1078 hci1394_async_cmd_t *hcicmd;
1079 hci1394_q_cmd_t *qcmd;
1080 int cmd_status;
1081
1082
1083 ASSERT(async_handle != NULL);
1084 ASSERT(response_available != NULL);
1085
1086 TNF_PROBE_0_DEBUG(hci1394_async_atresp_process_enter,
1087 HCI1394_TNF_HAL_STACK, "");
1088
1089 /*
1090 * Get the next ATRESP that has completed (if one has). Space is free'd
1091 * up in atresp_q and atresp_data_q as part of this function call.
1092 */
1093 hci1394_q_at_next(async_handle->as_atresp_q, flush_q, &qcmd);
1094
1095 /*
1096 * See if there were anymore requests on ATRESP Q. A NULL means there
1097 * were no completed commands left on the Q.
1098 */
1099 if (qcmd == NULL) {
1100 *response_available = B_FALSE;
1101 TNF_PROBE_0_DEBUG(hci1394_async_atresp_process_exit,
1102 HCI1394_TNF_HAL_STACK, "");
1103 return (DDI_SUCCESS);
1104 }
1105
1106 /* There is a completed ATRESP, setup the HAL command pointer */
1107 *response_available = B_TRUE;
1108 hcicmd = (hci1394_async_cmd_t *)qcmd->qc_arg;
1109
1110 TNF_PROBE_1_DEBUG(hci1394_atresp_ack, HCI1394_TNF_HAL, "", tnf_uint,
1111 atresp_ack, qcmd->qc_status);
1112
1113 /* save away the command completed timestamp for the services layer */
1114 hcicmd->ac_priv->ack_tstamp = qcmd->qc_timestamp;
1115
1116 /*
1117 * setup our return command status based on the ACK from the HW. See the
1118 * OpenHCI 1.0 spec (table 3.2 on pg. 18) for more information about
1119 * these ACK/EVT's.
1120 */
1121 switch (qcmd->qc_status) {
1122 case OHCI_ACK_COMPLETE:
1123 cmd_status = H1394_CMD_SUCCESS;
1124 break;
1125
1126 /*
1127 * we can get a nostatus during a bus reset (i.e. we shutdown the AT
1128 * engine before it flushed all the commands)
1129 */
1130 case OHCI_EVT_FLUSHED:
1131 case OHCI_EVT_NO_STATUS:
1132 cmd_status = H1394_CMD_EBUSRESET;
1133 break;
1134
1135 case OHCI_EVT_MISSING_ACK:
1136 case OHCI_EVT_TIMEOUT:
1137 cmd_status = H1394_CMD_ETIMEOUT;
1138 TNF_PROBE_1(hci1394_atresp_ack_err, HCI1394_TNF_HAL_ERROR,
1139 "", tnf_uint, atresp_ack, qcmd->qc_status);
1140 break;
1141
1142 case OHCI_ACK_BUSY_X:
1143 case OHCI_ACK_BUSY_A:
1144 case OHCI_ACK_BUSY_B:
1145 cmd_status = H1394_CMD_EDEVICE_BUSY;
1146 TNF_PROBE_1(hci1394_atresp_ack_err, HCI1394_TNF_HAL_ERROR,
1147 "", tnf_uint, atresp_ack, qcmd->qc_status);
1148 break;
1149
1150 case OHCI_ACK_TARDY:
1151 cmd_status = H1394_CMD_EDEVICE_POWERUP;
1152 TNF_PROBE_1(hci1394_atresp_ack_err, HCI1394_TNF_HAL_ERROR,
1153 "", tnf_uint, atresp_ack, qcmd->qc_status);
1154 break;
1155
1156 case OHCI_ACK_DATA_ERROR:
1157 cmd_status = H1394_CMD_EDATA_ERROR;
1158 TNF_PROBE_1(hci1394_atresp_ack_err, HCI1394_TNF_HAL_ERROR,
1159 "", tnf_uint, atresp_ack, qcmd->qc_status);
1160 break;
1161
1162 case OHCI_ACK_TYPE_ERROR:
1163 cmd_status = H1394_CMD_ETYPE_ERROR;
1164 TNF_PROBE_1(hci1394_atresp_ack_err, HCI1394_TNF_HAL_ERROR,
1165 "", tnf_uint, atresp_ack, qcmd->qc_status);
1166 break;
1167
1168 case OHCI_ACK_CONFLICT_ERROR:
1169 cmd_status = H1394_CMD_ERSRC_CONFLICT;
1170 TNF_PROBE_1(hci1394_atresp_ack_err, HCI1394_TNF_HAL_ERROR,
1171 "", tnf_uint, atresp_ack, qcmd->qc_status);
1172 break;
1173
1174 case OHCI_ACK_ADDRESS_ERROR:
1175 cmd_status = H1394_CMD_EADDR_ERROR;
1176 TNF_PROBE_1(hci1394_atresp_ack_err, HCI1394_TNF_HAL_ERROR,
1177 "", tnf_uint, atresp_ack, qcmd->qc_status);
1178 break;
1179
1180 case OHCI_EVT_UNKNOWN:
1181 cmd_status = H1394_CMD_EUNKNOWN_ERROR;
1182 TNF_PROBE_1(hci1394_atresp_ack_err, HCI1394_TNF_HAL_ERROR,
1183 "", tnf_uint, atresp_ack, qcmd->qc_status);
1184 break;
1185
1186 case OHCI_EVT_UNDERRUN:
1187 case OHCI_EVT_DATA_READ:
1188 case OHCI_EVT_TCODE_ERR:
1189 case OHCI_EVT_DESCRIPTOR_READ:
1190 default:
1191 cmd_status = H1394_CMD_EUNKNOWN_ERROR;
1192 TNF_PROBE_1(hci1394_atresp_ack_err, HCI1394_TNF_HAL_ERROR,
1193 "", tnf_uint, atresp_ack, qcmd->qc_status);
1194 break;
1195 }
1196
1197 /* tell the services layer that the command has completed */
1198 h1394_cmd_is_complete(async_handle->as_drvinfo->di_sl_private,
1199 hcicmd->ac_cmd, H1394_AT_RESP, cmd_status);
1200
1201 TNF_PROBE_0_DEBUG(hci1394_async_atresp_process_exit,
1202 HCI1394_TNF_HAL_STACK, "");
1203
1204 return (DDI_SUCCESS);
1205 }
1206
1207
1208 /*
1209 * hci1394_async_arresp_read()
1210 * Read ARRESP in from memory into 1394 Framework command. We read the tcode
1211 * which tells us which kind of arresp the packet is, get the size of the
1212 * response, read in the sender, tlabel, and response code, and then
1213 * lookup the command based on the sender and tlabel. Once we get the command
1214 * (corresponding to the ATREQ), we will copy the rest of the response into
1215 * that command.
1216 *
1217 * The only time this routine should return DDI_FAILURE is if it was unable
1218 * to maintain a good state in the ARRESP Q (i.e. an unknown response was
1219 * received and we can not cleanup after it.) If we detect a recoverable
1220 * error, and it doesn't make sense to pass the response up to the Services
1221 * Layer, we should return DDI_SUCCESS with hcicmd = NULL.
1222 */
1223 static int
hci1394_async_arresp_read(hci1394_async_handle_t async_handle,hci1394_basic_pkt_t * pkt,uint_t * tcode,hci1394_async_cmd_t ** hcicmd,uint_t * size)1224 hci1394_async_arresp_read(hci1394_async_handle_t async_handle,
1225 hci1394_basic_pkt_t *pkt, uint_t *tcode, hci1394_async_cmd_t **hcicmd,
1226 uint_t *size)
1227 {
1228 hci1394_tlabel_info_t ac_tlabel;
1229 h1394_cmd_priv_t *cmd_priv;
1230 cmd1394_cmd_t *cmd;
1231 uint32_t *status_addr;
1232 uint_t data_length;
1233 uint32_t quadlet;
1234 void *command;
1235 uint_t rcode;
1236 uint_t ack;
1237 int status;
1238
1239
1240 ASSERT(async_handle != NULL);
1241 ASSERT(pkt != NULL);
1242 ASSERT(tcode != NULL);
1243 ASSERT(hcicmd != NULL);
1244 ASSERT(size != NULL);
1245
1246 TNF_PROBE_0_DEBUG(hci1394_async_arresp_read_enter,
1247 HCI1394_TNF_HAL_STACK, "");
1248
1249 /* read in the arresp tcode */
1250 quadlet = hci1394_q_ar_get32(async_handle->as_arresp_q, &pkt->q1);
1251 *tcode = HCI1394_DESC_TCODE_GET(quadlet);
1252
1253 /* Get the size of the arresp */
1254 status = hci1394_async_arresp_size_get(*tcode,
1255 async_handle->as_arresp_q, &pkt->q1, size);
1256 if (status != DDI_SUCCESS) {
1257 TNF_PROBE_0(hci1394_async_arresp_read_size_fail,
1258 HCI1394_TNF_HAL_ERROR, "");
1259 TNF_PROBE_0_DEBUG(hci1394_async_arresp_read_exit,
1260 HCI1394_TNF_HAL_STACK, "");
1261 return (DDI_FAILURE);
1262 }
1263
1264 /* Read in the tlabel, destination, and rcode (response code) */
1265 quadlet = hci1394_q_ar_get32(async_handle->as_arresp_q, &pkt->q1);
1266 ac_tlabel.tbi_tlabel = HCI1394_DESC_TLABEL_GET(quadlet);
1267 quadlet = hci1394_q_ar_get32(async_handle->as_arresp_q, &pkt->q2);
1268 ac_tlabel.tbi_destination = HCI1394_DESC_DESTID_GET(quadlet);
1269 rcode = HCI1394_DESC_RCODE_GET(quadlet);
1270
1271 /* Lookup the ATREQ framework command this response goes with */
1272 hci1394_tlabel_lookup(async_handle->as_tlabel, &ac_tlabel, &command);
1273
1274 /*
1275 * If there is not a cooresponding ATREQ command, this is an error. We
1276 * will ignore this response but still return success so we cleanup
1277 * after it and go on with other arresp's. This could happend if a
1278 * response was sent after the command has timed out or if the target
1279 * device is misbehaving. (we have seen both cases)
1280 */
1281 *hcicmd = (hci1394_async_cmd_t *)command;
1282 if ((*hcicmd) == NULL) {
1283 TNF_PROBE_2(hci1394_invalid_tlabel, HCI1394_TNF_HAL_ERROR,
1284 "", tnf_uint, nodeid,
1285 IEEE1394_NODE_NUM(ac_tlabel.tbi_destination), tnf_uint,
1286 rx_tlabel, ac_tlabel.tbi_tlabel);
1287 TNF_PROBE_0_DEBUG(hci1394_async_arresp_read_exit,
1288 HCI1394_TNF_HAL_STACK, "");
1289 return (DDI_SUCCESS);
1290 }
1291
1292 /*
1293 * copy the response code into the hal private command space. Setup
1294 * shortcuts to the 1394 framework command (cmd) and the HAL/SL private
1295 * area (cmd_priv). A command is made up of 4 parts. There is the public
1296 * part which is accessable to the target driver, there is the Services
1297 * Layer private part which is only accessible to the services layer,
1298 * there is the SL/HAL private area which is where the SL and HAL share
1299 * information about a particular command, and there is the HAL private
1300 * area where we keep track of our command specific state information.
1301 */
1302 (*hcicmd)->ac_status = rcode;
1303 cmd = (*hcicmd)->ac_cmd;
1304 cmd_priv = (*hcicmd)->ac_priv;
1305
1306 /*
1307 * Calculate the address where the status of the ARRESP and timestamp is
1308 * kept at. It is the last quadlet in the response. Save away the
1309 * timestamp.
1310 */
1311 status_addr = (uint32_t *)((uintptr_t)pkt + (uintptr_t)*size -
1312 (uintptr_t)IEEE1394_QUADLET);
1313 quadlet = hci1394_q_ar_get32(async_handle->as_arresp_q, status_addr);
1314 cmd_priv->recv_tstamp = HCI1394_DESC_TIMESTAMP_GET(quadlet);
1315
1316 /*
1317 * if we did not get an ACK_COMPLETE, we will use the ack error instead
1318 * of the response in the packet for our status. We use special mask to
1319 * separate the reponses from the ACKs (ASYNC_ARRESP_ACK_ERROR). We will
1320 * return success with hcicmd set to the command so that this error gets
1321 * sent up to the Services Layer.
1322 */
1323 ack = HCI1394_DESC_EVT_GET(quadlet);
1324 if (ack != OHCI_ACK_COMPLETE) {
1325 /* use the ack error instead of rcode for the command status */
1326 (*hcicmd)->ac_status = ack | ASYNC_ARRESP_ACK_ERROR;
1327 TNF_PROBE_1(hci1394_arresp_bad_ack, HCI1394_TNF_HAL_ERROR,
1328 "", tnf_uint, arresp_ack, ack);
1329 TNF_PROBE_0_DEBUG(hci1394_async_arresp_read_exit,
1330 HCI1394_TNF_HAL_STACK, "");
1331 return (DDI_SUCCESS);
1332 }
1333
1334 TNF_PROBE_1_DEBUG(hci1394_atrresp_resp, HCI1394_TNF_HAL, "", tnf_uint,
1335 arresp_resp, rcode);
1336
1337 /*
1338 * If we get to this point we have gotten a valid ACK on the response
1339 * and have matched up the response with an ATREQ. Now we check the
1340 * response code. If it is not resp_complete, we do not have anything
1341 * left to look at in the response. Return successfully.
1342 */
1343 if (rcode != IEEE1394_RESP_COMPLETE) {
1344 TNF_PROBE_0_DEBUG(hci1394_async_arresp_read_exit,
1345 HCI1394_TNF_HAL_STACK, "");
1346 return (DDI_SUCCESS);
1347 }
1348
1349 /*
1350 * Read the rest of the response (based on which kind of response it is)
1351 * into the 1394 framework command. In all of the different responses,
1352 * we check to make sure the response matches the original request. We
1353 * originally did not have this check but found a device or two which
1354 * did not behave very well and would cause us to corrupt our commands.
1355 * Now we check :-) We will return success when we get this error since
1356 * we can recover from it.
1357 */
1358 switch (*tcode) {
1359 case IEEE1394_TCODE_WRITE_RESP:
1360 /*
1361 * make sure the ATREQ was a quadlet/block write. The same
1362 * response is sent back for those two type of ATREQs.
1363 */
1364 if ((cmd->cmd_type != CMD1394_ASYNCH_WR_QUAD) &&
1365 (cmd->cmd_type != CMD1394_ASYNCH_WR_BLOCK)) {
1366 (*hcicmd)->ac_status = H1394_CMD_EDEVICE_ERROR;
1367 TNF_PROBE_2(hci1394_async_arresp_lockresp_fail,
1368 HCI1394_TNF_HAL_STACK, "", tnf_string, errmsg,
1369 "Invalid response sent for write request", tnf_uint,
1370 arresp_tcode, *tcode);
1371 TNF_PROBE_0_DEBUG(hci1394_async_arresp_read_exit,
1372 HCI1394_TNF_HAL_STACK, "");
1373 return (DDI_SUCCESS);
1374 }
1375 break;
1376
1377 case IEEE1394_TCODE_READ_QUADLET_RESP:
1378 /* make sure the ATREQ was a quadlet read */
1379 if (cmd->cmd_type != CMD1394_ASYNCH_RD_QUAD) {
1380 (*hcicmd)->ac_status = H1394_CMD_EDEVICE_ERROR;
1381 TNF_PROBE_2(hci1394_async_arresp_lockresp_fail,
1382 HCI1394_TNF_HAL_STACK, "", tnf_string, errmsg,
1383 "Invalid response sent for qrd request", tnf_uint,
1384 arresp_tcode, *tcode);
1385 TNF_PROBE_0_DEBUG(hci1394_async_arresp_read_exit,
1386 HCI1394_TNF_HAL_STACK, "");
1387 return (DDI_SUCCESS);
1388 }
1389
1390 /*
1391 * read the quadlet read response in. Data is treated as a byte
1392 * stream.
1393 */
1394 hci1394_q_ar_rep_get8(async_handle->as_arresp_q,
1395 (uint8_t *)&cmd->cmd_u.q.quadlet_data,
1396 (uint8_t *)&pkt->q4, IEEE1394_QUADLET);
1397 break;
1398
1399 case IEEE1394_TCODE_READ_BLOCK_RESP:
1400 /* make sure the ATREQ was a block read */
1401 if (cmd->cmd_type != CMD1394_ASYNCH_RD_BLOCK) {
1402 (*hcicmd)->ac_status = H1394_CMD_EDEVICE_ERROR;
1403 TNF_PROBE_2(hci1394_async_arresp_lockresp_fail,
1404 HCI1394_TNF_HAL_STACK, "", tnf_string, errmsg,
1405 "Invalid response sent for brd request", tnf_uint,
1406 arresp_tcode, *tcode);
1407 TNF_PROBE_0_DEBUG(hci1394_async_arresp_read_exit,
1408 HCI1394_TNF_HAL_STACK, "");
1409 return (DDI_SUCCESS);
1410 }
1411
1412 /*
1413 * read in the data length. Make sure the data length is the
1414 * same size as the read block request size that went out.
1415 */
1416 quadlet = hci1394_q_ar_get32(async_handle->as_arresp_q,
1417 &pkt->q4);
1418 data_length = HCI1394_DESC_DATALEN_GET(quadlet);
1419 if (data_length != cmd_priv->mblk.length) {
1420 (*hcicmd)->ac_status = H1394_CMD_EDEVICE_ERROR;
1421 TNF_PROBE_3(hci1394_async_arresp_brdsz_fail,
1422 HCI1394_TNF_HAL_STACK, "", tnf_string,
1423 errmsg, "Block read response size is bad",
1424 tnf_uint, requested_size, cmd_priv->mblk.length,
1425 tnf_uint, response_size, data_length);
1426 TNF_PROBE_0_DEBUG(hci1394_async_arresp_read_exit,
1427 HCI1394_TNF_HAL_STACK, "");
1428 return (DDI_SUCCESS);
1429 }
1430
1431 /* Copy the read block data into the command mblk */
1432 hci1394_q_ar_copy_to_mblk(async_handle->as_arresp_q,
1433 (uint8_t *)&pkt->q5, &cmd_priv->mblk);
1434 break;
1435
1436 case IEEE1394_TCODE_LOCK_RESP:
1437 /* read in the data length */
1438 quadlet = hci1394_q_ar_get32(async_handle->as_arresp_q,
1439 &pkt->q4);
1440 data_length = HCI1394_DESC_DATALEN_GET(quadlet);
1441
1442 if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) {
1443 /*
1444 * read in the data length. Make sure the data length
1445 * is the valid for a lock32 response (1 quadlet)
1446 */
1447 if (data_length != IEEE1394_QUADLET) {
1448 (*hcicmd)->ac_status = H1394_CMD_EDEVICE_ERROR;
1449 TNF_PROBE_2(hci1394_async_arresp_l32sz_fail,
1450 HCI1394_TNF_HAL_STACK, "", tnf_string,
1451 errmsg, "Invalid size for lock32 response",
1452 tnf_uint, data_size, data_length);
1453 TNF_PROBE_0_DEBUG(
1454 hci1394_async_arresp_read_exit,
1455 HCI1394_TNF_HAL_STACK, "");
1456 return (DDI_SUCCESS);
1457 }
1458
1459 /*
1460 * read the lock32 response in. Data is treated as a
1461 * byte stream unless it is an arithmetic lock
1462 * operation. In that case we treat data like a 32-bit
1463 * word.
1464 */
1465 hci1394_q_ar_rep_get8(async_handle->as_arresp_q,
1466 (uint8_t *)&cmd->cmd_u.l32.old_value,
1467 (uint8_t *)&pkt->q5, IEEE1394_QUADLET);
1468 cmd->cmd_u.l32.old_value = HCI1394_ARITH_LOCK_SWAP32(
1469 cmd->cmd_u.l32.lock_type, cmd->cmd_u.l32.old_value);
1470
1471 } else if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_64) {
1472 /*
1473 * read in the data length. Make sure the data length
1474 * is the valid for a lock64 response (1 octlet)
1475 */
1476 if (data_length != IEEE1394_OCTLET) {
1477 (*hcicmd)->ac_status = H1394_CMD_EDEVICE_ERROR;
1478 TNF_PROBE_2(hci1394_async_arresp_l64sz_fail,
1479 HCI1394_TNF_HAL_STACK, "", tnf_string,
1480 errmsg, "Invalid size for lock64 response",
1481 tnf_uint, data_size, data_length);
1482 TNF_PROBE_0_DEBUG(
1483 hci1394_async_arresp_read_exit,
1484 HCI1394_TNF_HAL_STACK, "");
1485 return (DDI_SUCCESS);
1486 }
1487
1488 /*
1489 * read the lock64 response in. Data is treated as a
1490 * byte stream unless it is an arithmetic lock
1491 * operation. In that case we treat data like a 64-bit
1492 * word.
1493 */
1494 hci1394_q_ar_rep_get8(async_handle->as_arresp_q,
1495 (uint8_t *)&cmd->cmd_u.l64.old_value,
1496 (uint8_t *)&pkt->q5, IEEE1394_OCTLET);
1497 cmd->cmd_u.l64.old_value = HCI1394_ARITH_LOCK_SWAP64(
1498 cmd->cmd_u.l64.lock_type, cmd->cmd_u.l64.old_value);
1499
1500 /*
1501 * we sent out a request that was NOT a lock request and got
1502 * back a lock response.
1503 */
1504 } else {
1505 (*hcicmd)->ac_status = H1394_CMD_EDEVICE_ERROR;
1506 TNF_PROBE_2(hci1394_async_arresp_lockresp_fail,
1507 HCI1394_TNF_HAL_STACK, "", tnf_string, errmsg,
1508 "Invalid response sent for lock request", tnf_uint,
1509 arresp_tcode, *tcode);
1510 TNF_PROBE_0_DEBUG(hci1394_async_arresp_read_exit,
1511 HCI1394_TNF_HAL_STACK, "");
1512 return (DDI_SUCCESS);
1513 }
1514 break;
1515
1516 default:
1517 /* we got a tcode that we don't know about. Return error */
1518 TNF_PROBE_2(hci1394_async_arresp_tcode_err,
1519 HCI1394_TNF_HAL_ERROR, "", tnf_string, errmsg,
1520 "unknown ARRESP received", tnf_uint, arresp_tcode, *tcode);
1521 TNF_PROBE_0_DEBUG(hci1394_async_arresp_read_exit,
1522 HCI1394_TNF_HAL_STACK, "");
1523 return (DDI_FAILURE);
1524 }
1525
1526 TNF_PROBE_0_DEBUG(hci1394_async_arresp_read_exit,
1527 HCI1394_TNF_HAL_STACK, "");
1528
1529 return (DDI_SUCCESS);
1530 }
1531
1532
1533 /*
1534 * hci1394_async_arreq_read()
1535 * Read ARREQ in from memory into a 1394 Framework command. Allocate a 1394
1536 * framework command, read in the ARREQ, and before passing it up to the
1537 * services layer, see if it was a valid broadcast request.
1538 *
1539 * The only time this routine should return DDI_FAILURE is if it was unable
1540 * to maintain a good state in the ARREQ Q (i.e. an unknown request was
1541 * received and we can not cleanup after it.) If we detect a recoverable
1542 * error we should return DDI_SUCCESS with hcicmd = NULL.
1543 */
1544 static int
hci1394_async_arreq_read(hci1394_async_handle_t async_handle,hci1394_basic_pkt_t * pkt,uint_t * tcode,hci1394_async_cmd_t ** hcicmd,uint_t * size)1545 hci1394_async_arreq_read(hci1394_async_handle_t async_handle,
1546 hci1394_basic_pkt_t *pkt, uint_t *tcode, hci1394_async_cmd_t **hcicmd,
1547 uint_t *size)
1548 {
1549 h1394_cmd_priv_t *cmd_priv;
1550 boolean_t is_reset_token;
1551 cmd1394_cmd_t *cmd;
1552 uint32_t quadlet;
1553 int status;
1554
1555
1556 ASSERT(async_handle != NULL);
1557 ASSERT(pkt != NULL);
1558 ASSERT(tcode != NULL);
1559 ASSERT(hcicmd != NULL);
1560 ASSERT(size != NULL);
1561
1562 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_enter,
1563 HCI1394_TNF_HAL_STACK, "");
1564
1565 /* read in the arresp tcode */
1566 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q1);
1567 *tcode = HCI1394_DESC_TCODE_GET(quadlet);
1568
1569 /*
1570 * Allocated 1394 framework command. The Services layer takes care of
1571 * cacheing commands. This is called during interrupt processing so we
1572 * do not want to sleep.
1573 */
1574 status = h1394_alloc_cmd(async_handle->as_drvinfo->di_sl_private,
1575 H1394_ALLOC_CMD_NOSLEEP, &cmd, &cmd_priv);
1576 if (status != DDI_SUCCESS) {
1577 TNF_PROBE_0(hci1394_async_arreq_read_cmdalloc_fail,
1578 HCI1394_TNF_HAL_ERROR, "");
1579 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_exit,
1580 HCI1394_TNF_HAL_STACK, "");
1581 return (DDI_FAILURE);
1582 }
1583
1584 /* Initialize the HAL private command info */
1585 hci1394_async_hcicmd_init(async_handle, cmd, cmd_priv, hcicmd);
1586
1587 /*
1588 * There are two generations in the command structure, one in the public
1589 * space and one in the HAL/SL private shared space. We need to fill in
1590 * both. We only use the private one internally.
1591 */
1592 cmd_priv->bus_generation = async_handle->as_drvinfo->di_gencnt;
1593 cmd->bus_generation = async_handle->as_drvinfo->di_gencnt;
1594
1595 /*
1596 * Read the request (based on which kind of request it is) into the 1394
1597 * framework command.
1598 */
1599 switch (*tcode) {
1600 case IEEE1394_TCODE_READ_QUADLET:
1601 /*
1602 * We got a ARREQ quadlet read request. Read in the packet.
1603 * If there is a problem with the packet (i.e. we don't get
1604 * DDI_SUCCESS), we will free up the command and return NULL in
1605 * hcicmd to indicate that we did not get a valid ARREQ to
1606 * process.
1607 */
1608 status = hci1394_async_arreq_read_qrd(async_handle, pkt,
1609 *hcicmd, size);
1610 if (status != DDI_SUCCESS) {
1611 hci1394_async_response_complete(async_handle, cmd,
1612 cmd_priv);
1613 *hcicmd = NULL;
1614 TNF_PROBE_0(hci1394_async_arreq_read_qrd_fail,
1615 HCI1394_TNF_HAL_ERROR, "");
1616 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_exit,
1617 HCI1394_TNF_HAL_STACK, "");
1618 return (DDI_SUCCESS);
1619 }
1620 break;
1621
1622 case IEEE1394_TCODE_WRITE_QUADLET:
1623 /*
1624 * We got a ARREQ quadlet write request. Read in the packet.
1625 * If there is a problem with the packet (i.e. we don't get
1626 * DDI_SUCCESS), we will free up the command and return NULL in
1627 * hcicmd to indicate that we did not get a valid ARREQ to
1628 * process.
1629 */
1630 status = hci1394_async_arreq_read_qwr(async_handle, pkt,
1631 *hcicmd, size);
1632 if (status != DDI_SUCCESS) {
1633 hci1394_async_response_complete(async_handle, cmd,
1634 cmd_priv);
1635 *hcicmd = NULL;
1636 TNF_PROBE_0(hci1394_async_arreq_read_qwr_fail,
1637 HCI1394_TNF_HAL_ERROR, "");
1638 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_exit,
1639 HCI1394_TNF_HAL_STACK, "");
1640 return (DDI_SUCCESS);
1641 }
1642 break;
1643
1644 case IEEE1394_TCODE_READ_BLOCK:
1645 /*
1646 * We got a ARREQ block read request. Read in the packet.
1647 * If there is a problem with the packet (i.e. we don't get
1648 * DDI_SUCCESS), we will free up the command and return NULL in
1649 * hcicmd to indicate that we did not get a valid ARREQ to
1650 * process.
1651 */
1652 status = hci1394_async_arreq_read_brd(async_handle, pkt,
1653 *hcicmd, size);
1654 if (status != DDI_SUCCESS) {
1655 hci1394_async_response_complete(async_handle, cmd,
1656 cmd_priv);
1657 *hcicmd = NULL;
1658 TNF_PROBE_0(hci1394_async_arreq_read_brd_fail,
1659 HCI1394_TNF_HAL_ERROR, "");
1660 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_exit,
1661 HCI1394_TNF_HAL_STACK, "");
1662 return (DDI_SUCCESS);
1663 }
1664 break;
1665
1666 case IEEE1394_TCODE_WRITE_BLOCK:
1667 /*
1668 * We got a ARREQ block write request. Read in the packet.
1669 * If there is a problem with the packet (i.e. we don't get
1670 * DDI_SUCCESS), we will free up the command and return NULL in
1671 * hcicmd to indicate that we did not get a valid ARREQ to
1672 * process.
1673 */
1674 status = hci1394_async_arreq_read_bwr(async_handle, pkt,
1675 *hcicmd, size);
1676 if (status != DDI_SUCCESS) {
1677 hci1394_async_response_complete(async_handle, cmd,
1678 cmd_priv);
1679 *hcicmd = NULL;
1680 TNF_PROBE_0(hci1394_async_arreq_read_bwr_fail,
1681 HCI1394_TNF_HAL_ERROR, "");
1682 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_exit,
1683 HCI1394_TNF_HAL_STACK, "");
1684 return (DDI_SUCCESS);
1685 }
1686 break;
1687
1688 case IEEE1394_TCODE_LOCK:
1689 /*
1690 * We got a ARREQ lock request. Read in the packet.
1691 * If there is a problem with the packet (i.e. we don't get
1692 * DDI_SUCCESS), we will free up the command and return NULL in
1693 * hcicmd to indicate that we did not get a valid ARREQ to
1694 * process.
1695 */
1696 status = hci1394_async_arreq_read_lck(async_handle, pkt,
1697 *hcicmd, size);
1698 if (status != DDI_SUCCESS) {
1699 hci1394_async_response_complete(async_handle, cmd,
1700 cmd_priv);
1701 *hcicmd = NULL;
1702 TNF_PROBE_0(hci1394_async_arreq_read_lck_fail,
1703 HCI1394_TNF_HAL_ERROR, "");
1704 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_exit,
1705 HCI1394_TNF_HAL_STACK, "");
1706 return (DDI_SUCCESS);
1707 }
1708 break;
1709
1710 case IEEE1394_TCODE_PHY:
1711 /*
1712 * We got a PHY packet in the ARREQ buffer. Read in the packet.
1713 * If there is a problem with the packet (i.e. we don't get
1714 * DDI_SUCCESS), we will free up the command and return NULL in
1715 * hcicmd to indicate that we did not get a valid ARREQ to
1716 * process.
1717 */
1718 status = hci1394_async_arreq_read_phy(async_handle, pkt,
1719 *hcicmd, size, &is_reset_token);
1720 if (status != DDI_SUCCESS) {
1721 hci1394_async_response_complete(async_handle, cmd,
1722 cmd_priv);
1723 *hcicmd = NULL;
1724 TNF_PROBE_0(hci1394_async_arreq_read_phy_fail,
1725 HCI1394_TNF_HAL_ERROR, "");
1726 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_exit,
1727 HCI1394_TNF_HAL_STACK, "");
1728 return (DDI_SUCCESS);
1729 }
1730
1731 /*
1732 * If we got a bus reset token, free up the command and return
1733 * NULL in hcicmd to indicate that we did not get a valid ARREQ
1734 * to process.
1735 */
1736 if (is_reset_token == B_TRUE) {
1737 hci1394_async_response_complete(async_handle, cmd,
1738 cmd_priv);
1739 *hcicmd = NULL;
1740 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_exit,
1741 HCI1394_TNF_HAL_STACK, "");
1742 return (DDI_SUCCESS);
1743 }
1744 break;
1745
1746 default:
1747 /* we got a tcode that we don't know about. Return error */
1748 TNF_PROBE_2(hci1394_async_arreq_tcode_err,
1749 HCI1394_TNF_HAL_ERROR, "", tnf_string, errmsg,
1750 "unknown ARREQ received", tnf_uint, arreq_tcode, *tcode);
1751 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_exit,
1752 HCI1394_TNF_HAL_STACK, "");
1753 return (DDI_FAILURE);
1754 }
1755
1756 /*
1757 * If this command was broadcast and it was not a write, drop the
1758 * command since it's an invalid request. We will free up the command
1759 * and return NULL in hcicmd to indicate that we did not get a valid
1760 * ARREQ to process.
1761 */
1762 if ((((*hcicmd)->ac_dest & IEEE1394_NODE_NUM_MASK) ==
1763 IEEE1394_BROADCAST_NODEID) && ((*tcode !=
1764 IEEE1394_TCODE_WRITE_QUADLET) && (*tcode !=
1765 IEEE1394_TCODE_WRITE_BLOCK))) {
1766 hci1394_async_response_complete(async_handle, cmd, cmd_priv);
1767 *hcicmd = NULL;
1768 TNF_PROBE_0(hci1394_async_arreq_read_bcast_fail,
1769 HCI1394_TNF_HAL_ERROR, "");
1770 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_exit,
1771 HCI1394_TNF_HAL_STACK, "");
1772 return (DDI_SUCCESS);
1773
1774 /*
1775 * It is a valid broadcast command, set that field in the public
1776 * command structure.
1777 */
1778 } else if ((((*hcicmd)->ac_dest & IEEE1394_NODE_NUM_MASK) ==
1779 IEEE1394_BROADCAST_NODEID)) {
1780 cmd->broadcast = 1;
1781 }
1782
1783 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_exit,
1784 HCI1394_TNF_HAL_STACK, "");
1785
1786 return (DDI_SUCCESS);
1787 }
1788
1789
1790 /*
1791 * hci1394_async_arreq_read_qrd()
1792 * Read ARREQ quadlet read into the 1394 Framework command. This routine will
1793 * return DDI_FAILURE if it was not able to read the request succesfully.
1794 */
1795 static int
hci1394_async_arreq_read_qrd(hci1394_async_handle_t async_handle,hci1394_basic_pkt_t * pkt,hci1394_async_cmd_t * hcicmd,uint_t * size)1796 hci1394_async_arreq_read_qrd(hci1394_async_handle_t async_handle,
1797 hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size)
1798 {
1799 h1394_cmd_priv_t *cmd_priv;
1800 cmd1394_cmd_t *cmd;
1801 uint32_t quadlet;
1802
1803
1804 ASSERT(async_handle != NULL);
1805 ASSERT(pkt != NULL);
1806 ASSERT(hcicmd != NULL);
1807 ASSERT(size != NULL);
1808 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_qrd_enter,
1809 HCI1394_TNF_HAL_STACK, "");
1810
1811 /* Setup shortcuts, command type, and size of request */
1812 cmd = hcicmd->ac_cmd;
1813 cmd_priv = hcicmd->ac_priv;
1814 cmd->cmd_type = CMD1394_ASYNCH_RD_QUAD;
1815 *size = DESC_SZ_AR_READQUAD_REQ;
1816
1817 /*
1818 * read in the ARREQ ACK/EVT, the speed, the time we received it, and
1819 * calculate the ATRESP timeout for when we send it.
1820 */
1821 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q4);
1822 hcicmd->ac_status = HCI1394_DESC_EVT_GET(quadlet);
1823 cmd_priv->speed = HCI1394_DESC_AR_SPD_GET(quadlet);
1824 cmd_priv->recv_tstamp = HCI1394_DESC_TIMESTAMP_GET(quadlet);
1825 hcicmd->ac_qcmd.qc_timestamp = hci1394_async_timeout_calc(async_handle,
1826 cmd_priv->recv_tstamp);
1827
1828 /*
1829 * if the ARREQ ACK was bad, we were unable to successfully read in this
1830 * request. Return failure.
1831 */
1832 if ((hcicmd->ac_status != OHCI_ACK_COMPLETE) &&
1833 (hcicmd->ac_status != OHCI_ACK_PENDING)) {
1834 TNF_PROBE_1(hci1394_async_arreq_qrd_ack_fail,
1835 HCI1394_TNF_HAL_ERROR, "", tnf_uint, arreq_ack,
1836 hcicmd->ac_status);
1837 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_qrd_exit,
1838 HCI1394_TNF_HAL_STACK, "");
1839 return (DDI_FAILURE);
1840 }
1841
1842 /*
1843 * Read in the tlabel and destination. We don't use an mblk for this
1844 * request.
1845 */
1846 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q1);
1847 hcicmd->ac_dest = HCI1394_DESC_DESTID_GET(quadlet);
1848 hcicmd->ac_tlabel.tbi_tlabel = HCI1394_DESC_TLABEL_GET(quadlet);
1849 hcicmd->ac_mblk_alloc = B_FALSE;
1850
1851 /*
1852 * Read in the sender so we know who to send the ATRESP to and read in
1853 * the 1394 48-bit address for this request.
1854 */
1855 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q2);
1856 cmd->nodeID = HCI1394_DESC_SRCID_GET(quadlet);
1857 cmd->cmd_addr = HCI1394_TO_ADDR_HI(quadlet);
1858 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q3);
1859 cmd->cmd_addr |= HCI1394_TO_ADDR_LO(quadlet);
1860
1861 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_qrd_exit,
1862 HCI1394_TNF_HAL_STACK, "");
1863
1864 return (DDI_SUCCESS);
1865 }
1866
1867
1868 /*
1869 * hci1394_async_arreq_read_qwr()
1870 * Read ARREQ quadlet write into the 1394 Framework command. This routine
1871 * will return DDI_FAILURE if it was not able to read the request
1872 * succesfully.
1873 */
1874 static int
hci1394_async_arreq_read_qwr(hci1394_async_handle_t async_handle,hci1394_basic_pkt_t * pkt,hci1394_async_cmd_t * hcicmd,uint_t * size)1875 hci1394_async_arreq_read_qwr(hci1394_async_handle_t async_handle,
1876 hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size)
1877 {
1878 h1394_cmd_priv_t *cmd_priv;
1879 cmd1394_cmd_t *cmd;
1880 uint32_t quadlet;
1881
1882
1883 ASSERT(async_handle != NULL);
1884 ASSERT(pkt != NULL);
1885 ASSERT(hcicmd != NULL);
1886 ASSERT(size != NULL);
1887 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_qwr_enter,
1888 HCI1394_TNF_HAL_STACK, "");
1889
1890 /* Setup shortcuts, command type, and size of request */
1891 cmd = hcicmd->ac_cmd;
1892 cmd_priv = hcicmd->ac_priv;
1893 cmd->cmd_type = CMD1394_ASYNCH_WR_QUAD;
1894 *size = DESC_SZ_AR_WRITEQUAD_REQ;
1895
1896 /*
1897 * read in the ARREQ ACK/EVT, the speed, the time we received it, and
1898 * calculate the ATRESP timeout for when we send it.
1899 */
1900 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q5);
1901 hcicmd->ac_status = HCI1394_DESC_EVT_GET(quadlet);
1902 cmd_priv->speed = HCI1394_DESC_AR_SPD_GET(quadlet);
1903 cmd_priv->recv_tstamp = HCI1394_DESC_TIMESTAMP_GET(quadlet);
1904 hcicmd->ac_qcmd.qc_timestamp = hci1394_async_timeout_calc(async_handle,
1905 cmd_priv->recv_tstamp);
1906
1907 /*
1908 * if the ARREQ ACK was bad, we were unable to successfully read in this
1909 * request. Return failure.
1910 */
1911 if ((hcicmd->ac_status != OHCI_ACK_COMPLETE) &&
1912 (hcicmd->ac_status != OHCI_ACK_PENDING)) {
1913 TNF_PROBE_1(hci1394_async_arreq_qwr_ack_fail,
1914 HCI1394_TNF_HAL_ERROR, "", tnf_uint, arreq_ack,
1915 hcicmd->ac_status);
1916 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_qwr_exit,
1917 HCI1394_TNF_HAL_STACK, "");
1918 return (DDI_FAILURE);
1919 }
1920
1921 /*
1922 * Read in the tlabel and destination. We don't use an mblk for this
1923 * request.
1924 */
1925 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q1);
1926 hcicmd->ac_dest = HCI1394_DESC_DESTID_GET(quadlet);
1927 hcicmd->ac_tlabel.tbi_tlabel = HCI1394_DESC_TLABEL_GET(quadlet);
1928 hcicmd->ac_mblk_alloc = B_FALSE;
1929
1930 /*
1931 * Read in the sender so we know who to send the ATRESP to. Read in
1932 * the 1394 48-bit address for this request. Copy the data quadlet into
1933 * the command. The data quadlet is treated like a byte stream.
1934 */
1935 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q2);
1936 cmd->nodeID = HCI1394_DESC_SRCID_GET(quadlet);
1937 cmd->cmd_addr = HCI1394_TO_ADDR_HI(quadlet);
1938 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q3);
1939 cmd->cmd_addr |= HCI1394_TO_ADDR_LO(quadlet);
1940 hci1394_q_ar_rep_get8(async_handle->as_arreq_q,
1941 (uint8_t *)&cmd->cmd_u.q.quadlet_data, (uint8_t *)&pkt->q4,
1942 IEEE1394_QUADLET);
1943
1944 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_qwr_exit,
1945 HCI1394_TNF_HAL_STACK, "");
1946
1947 return (DDI_SUCCESS);
1948 }
1949
1950
1951 /*
1952 * hci1394_async_arreq_read_brd()
1953 * Read ARREQ block read into the 1394 Framework command. This routine will
1954 * return DDI_FAILURE if it was not able to read the request succesfully.
1955 */
1956 static int
hci1394_async_arreq_read_brd(hci1394_async_handle_t async_handle,hci1394_basic_pkt_t * pkt,hci1394_async_cmd_t * hcicmd,uint_t * size)1957 hci1394_async_arreq_read_brd(hci1394_async_handle_t async_handle,
1958 hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size)
1959 {
1960 h1394_cmd_priv_t *cmd_priv;
1961 cmd1394_cmd_t *cmd;
1962 uint32_t quadlet;
1963
1964
1965 ASSERT(async_handle != NULL);
1966 ASSERT(pkt != NULL);
1967 ASSERT(hcicmd != NULL);
1968 ASSERT(size != NULL);
1969 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_brd_enter,
1970 HCI1394_TNF_HAL_STACK, "");
1971
1972 /* Setup shortcuts, command type, and size of request */
1973 cmd = hcicmd->ac_cmd;
1974 cmd_priv = hcicmd->ac_priv;
1975 cmd->cmd_type = CMD1394_ASYNCH_RD_BLOCK;
1976 *size = DESC_SZ_AR_READBLOCK_REQ;
1977
1978 /*
1979 * read in the ARREQ ACK/EVT, the speed, the time we received it, and
1980 * calculate the ATRESP timeout for when we send it.
1981 */
1982 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q5);
1983 hcicmd->ac_status = HCI1394_DESC_EVT_GET(quadlet);
1984 cmd_priv->speed = HCI1394_DESC_AR_SPD_GET(quadlet);
1985 cmd_priv->recv_tstamp = HCI1394_DESC_TIMESTAMP_GET(quadlet);
1986 hcicmd->ac_qcmd.qc_timestamp = hci1394_async_timeout_calc(async_handle,
1987 cmd_priv->recv_tstamp);
1988
1989 /*
1990 * if the ARREQ ACK was bad, we were unable to successfully read in this
1991 * request. Return failure.
1992 */
1993 if ((hcicmd->ac_status != OHCI_ACK_COMPLETE) &&
1994 (hcicmd->ac_status != OHCI_ACK_PENDING)) {
1995 TNF_PROBE_1(hci1394_async_arreq_brd_ack_fail,
1996 HCI1394_TNF_HAL_ERROR, "", tnf_uint, arreq_ack,
1997 hcicmd->ac_status);
1998 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_brd_exit,
1999 HCI1394_TNF_HAL_STACK, "");
2000 return (DDI_FAILURE);
2001 }
2002
2003 /* Read in the tlabel and destination */
2004 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q1);
2005 hcicmd->ac_dest = HCI1394_DESC_DESTID_GET(quadlet);
2006 hcicmd->ac_tlabel.tbi_tlabel = HCI1394_DESC_TLABEL_GET(quadlet);
2007
2008 /*
2009 * Read in the sender so we know who to send the ATRESP to. Read in
2010 * the 1394 48-bit address for this request. Read in the block data size
2011 * and allocate an mblk of that size.
2012 */
2013 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q2);
2014 cmd->nodeID = HCI1394_DESC_SRCID_GET(quadlet);
2015 cmd->cmd_addr = HCI1394_TO_ADDR_HI(quadlet);
2016 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q3);
2017 cmd->cmd_addr |= HCI1394_TO_ADDR_LO(quadlet);
2018 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q4);
2019 cmd->cmd_u.b.blk_length = HCI1394_DESC_DATALEN_GET(quadlet);
2020 cmd->cmd_u.b.data_block = allocb(cmd->cmd_u.b.blk_length, 0);
2021 if (cmd->cmd_u.b.data_block == NULL) {
2022 TNF_PROBE_0(hci1394_async_arreq_brd_mblk_fail,
2023 HCI1394_TNF_HAL_ERROR, "");
2024 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_brd_exit,
2025 HCI1394_TNF_HAL_STACK, "");
2026 return (DDI_FAILURE);
2027 }
2028 hcicmd->ac_mblk_alloc = B_TRUE;
2029
2030 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_brd_exit,
2031 HCI1394_TNF_HAL_STACK, "");
2032
2033 return (DDI_SUCCESS);
2034 }
2035
2036
2037 /*
2038 * hci1394_async_arreq_read_bwr()
2039 * Read ARREQ block write into the 1394 Framework command. This routine will
2040 * return DDI_FAILURE if it was not able to read the request succesfully.
2041 */
2042 static int
hci1394_async_arreq_read_bwr(hci1394_async_handle_t async_handle,hci1394_basic_pkt_t * pkt,hci1394_async_cmd_t * hcicmd,uint_t * size)2043 hci1394_async_arreq_read_bwr(hci1394_async_handle_t async_handle,
2044 hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size)
2045 {
2046 h1394_cmd_priv_t *cmd_priv;
2047 uint32_t *local_addr;
2048 cmd1394_cmd_t *cmd;
2049 uint32_t quadlet;
2050
2051
2052 ASSERT(async_handle != NULL);
2053 ASSERT(pkt != NULL);
2054 ASSERT(hcicmd != NULL);
2055 ASSERT(size != NULL);
2056 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_bwr_enter,
2057 HCI1394_TNF_HAL_STACK, "");
2058
2059 /*
2060 * Setup shortcuts, command type, and size of request. The size of the
2061 * request is in quadlets, therefore we need to make sure we count in
2062 * the padding when figureing out the size (i.e. data may be in bytes
2063 * but the HW always pads to quadlets)
2064 */
2065 cmd = hcicmd->ac_cmd;
2066 cmd_priv = hcicmd->ac_priv;
2067 cmd->cmd_type = CMD1394_ASYNCH_WR_BLOCK;
2068 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q4);
2069 cmd->cmd_u.b.blk_length = HCI1394_DESC_DATALEN_GET(quadlet);
2070 *size = DESC_SZ_AR_WRITEBLOCK_REQ +
2071 HCI1394_ALIGN_QUAD(cmd->cmd_u.b.blk_length);
2072
2073 /*
2074 * read in the ARREQ ACK/EVT, the speed, the time we received it, and
2075 * calculate the ATRESP timeout for when we send it. The status word is
2076 * the last quadlet in the packet.
2077 */
2078 local_addr = (uint32_t *)(((uintptr_t)(&pkt->q5)) +
2079 ((uintptr_t)HCI1394_ALIGN_QUAD(cmd->cmd_u.b.blk_length)));
2080 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, local_addr);
2081 hcicmd->ac_status = HCI1394_DESC_EVT_GET(quadlet);
2082 cmd_priv->speed = HCI1394_DESC_AR_SPD_GET(quadlet);
2083 cmd_priv->recv_tstamp = HCI1394_DESC_TIMESTAMP_GET(quadlet);
2084 hcicmd->ac_qcmd.qc_timestamp = hci1394_async_timeout_calc(async_handle,
2085 cmd_priv->recv_tstamp);
2086
2087 /*
2088 * if the ARREQ ACK was bad, we were unable to successfully read in this
2089 * request. Return failure.
2090 */
2091 if ((hcicmd->ac_status != OHCI_ACK_COMPLETE) &&
2092 (hcicmd->ac_status != OHCI_ACK_PENDING)) {
2093 TNF_PROBE_1(hci1394_async_arreq_bwr_ack_fail,
2094 HCI1394_TNF_HAL_ERROR, "", tnf_uint, arreq_ack,
2095 hcicmd->ac_status);
2096 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_bwr_exit,
2097 HCI1394_TNF_HAL_STACK, "");
2098 return (DDI_FAILURE);
2099 }
2100
2101 /* Read in the tlabel and destination */
2102 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q1);
2103 hcicmd->ac_dest = HCI1394_DESC_DESTID_GET(quadlet);
2104 hcicmd->ac_tlabel.tbi_tlabel = HCI1394_DESC_TLABEL_GET(quadlet);
2105
2106 /*
2107 * Read in the sender so we know who to send the ATRESP to. Read in
2108 * the 1394 48-bit address for this request. Read in the block data size
2109 * and allocate an mblk of that size.
2110 */
2111 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q2);
2112 cmd->nodeID = HCI1394_DESC_SRCID_GET(quadlet);
2113 cmd->cmd_addr = HCI1394_TO_ADDR_HI(quadlet);
2114 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q3);
2115 cmd->cmd_addr |= HCI1394_TO_ADDR_LO(quadlet);
2116 cmd->cmd_u.b.data_block = allocb(cmd->cmd_u.b.blk_length, 0);
2117 if (cmd->cmd_u.b.data_block == NULL) {
2118 TNF_PROBE_0(hci1394_async_arreq_bwr_mblk_fail,
2119 HCI1394_TNF_HAL_ERROR, "");
2120 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_bwr_exit,
2121 HCI1394_TNF_HAL_STACK, "");
2122 return (DDI_FAILURE);
2123 }
2124 hcicmd->ac_mblk_alloc = B_TRUE;
2125
2126 /* Copy ARREQ write data into mblk_t */
2127 hci1394_q_ar_rep_get8(async_handle->as_arreq_q,
2128 (uint8_t *)cmd->cmd_u.b.data_block->b_wptr,
2129 (uint8_t *)&pkt->q5, cmd->cmd_u.b.blk_length);
2130
2131 /* Update mblk_t wptr */
2132 cmd->cmd_u.b.data_block->b_wptr += cmd->cmd_u.b.blk_length;
2133
2134 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_bwr_exit,
2135 HCI1394_TNF_HAL_STACK, "");
2136
2137 return (DDI_SUCCESS);
2138 }
2139
2140
2141 /*
2142 * hci1394_async_arreq_read_lck()
2143 * Read ARREQ lock request into the 1394 Framework command. This routine will
2144 * return DDI_FAILURE if it was not able to read the request succesfully.
2145 */
2146 static int
hci1394_async_arreq_read_lck(hci1394_async_handle_t async_handle,hci1394_basic_pkt_t * pkt,hci1394_async_cmd_t * hcicmd,uint_t * size)2147 hci1394_async_arreq_read_lck(hci1394_async_handle_t async_handle,
2148 hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size)
2149 {
2150 h1394_cmd_priv_t *cmd_priv;
2151 uint32_t *local_addr;
2152 cmd1394_cmd_t *cmd;
2153 uint8_t *data_addr;
2154 uint32_t quadlet;
2155 uint32_t length;
2156
2157
2158 ASSERT(async_handle != NULL);
2159 ASSERT(pkt != NULL);
2160 ASSERT(hcicmd != NULL);
2161 ASSERT(size != NULL);
2162 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_qrd_enter,
2163 HCI1394_TNF_HAL_STACK, "");
2164
2165 /*
2166 * Setup shortcuts, command type, and size of request. The size of the
2167 * request is in quadlets, therefore we need to make sure we count in
2168 * the padding when figuring out the size (i.e. data may be in bytes
2169 * but the HW always pads to quadlets)
2170 */
2171 cmd = hcicmd->ac_cmd;
2172 cmd_priv = hcicmd->ac_priv;
2173 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q4);
2174 length = HCI1394_DESC_DATALEN_GET(quadlet);
2175 *size = DESC_SZ_AR_LOCK_REQ + HCI1394_ALIGN_QUAD(length);
2176
2177 /* make sure the length is a valid lock request length */
2178 if (length == DESC_TWO_QUADS) {
2179 cmd->cmd_type = CMD1394_ASYNCH_LOCK_32;
2180 cmd->cmd_u.l32.lock_type = HCI1394_DESC_EXTTCODE_GET(quadlet);
2181 } else if (length == DESC_TWO_OCTLETS) {
2182 cmd->cmd_type = CMD1394_ASYNCH_LOCK_64;
2183 cmd->cmd_u.l64.lock_type = HCI1394_DESC_EXTTCODE_GET(quadlet);
2184 } else {
2185 TNF_PROBE_2(hci1394_async_arreq_lck_sz_fail,
2186 HCI1394_TNF_HAL_ERROR, "", tnf_string, errmsg,
2187 "unexpected length received", tnf_uint, locklen, length);
2188 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_exit,
2189 HCI1394_TNF_HAL_STACK, "");
2190 return (DDI_FAILURE);
2191 }
2192
2193 /*
2194 * read in the ARREQ ACK/EVT, the speed, the time we received it, and
2195 * calculate the ATRESP timeout for when we send it. The status word is
2196 * the last quadlet in the packet.
2197 */
2198 local_addr = (uint32_t *)(((uintptr_t)(&pkt->q5)) +
2199 ((uintptr_t)HCI1394_ALIGN_QUAD(length)));
2200 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, local_addr);
2201 hcicmd->ac_status = HCI1394_DESC_EVT_GET(quadlet);
2202 cmd_priv->speed = HCI1394_DESC_AR_SPD_GET(quadlet);
2203 cmd_priv->recv_tstamp = HCI1394_DESC_TIMESTAMP_GET(quadlet);
2204 hcicmd->ac_qcmd.qc_timestamp = hci1394_async_timeout_calc(async_handle,
2205 cmd_priv->recv_tstamp);
2206
2207 /*
2208 * if the ARREQ ACK was bad, we were unable to successfully read in this
2209 * request. Return failure.
2210 */
2211 if ((hcicmd->ac_status != OHCI_ACK_COMPLETE) &&
2212 (hcicmd->ac_status != OHCI_ACK_PENDING)) {
2213 TNF_PROBE_1(hci1394_async_arreq_read_ack_fail,
2214 HCI1394_TNF_HAL_ERROR, "", tnf_uint, arreq_ack,
2215 hcicmd->ac_status);
2216 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_exit,
2217 HCI1394_TNF_HAL_STACK, "");
2218 return (DDI_FAILURE);
2219 }
2220
2221 /* Read in the tlabel and destination */
2222 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q1);
2223 hcicmd->ac_dest = HCI1394_DESC_DESTID_GET(quadlet);
2224 hcicmd->ac_tlabel.tbi_tlabel = HCI1394_DESC_TLABEL_GET(quadlet);
2225 hcicmd->ac_mblk_alloc = B_FALSE;
2226
2227 /*
2228 * Read in the sender so we know who to send the ATRESP to. Read in
2229 * the 1394 48-bit address for this request.
2230 */
2231 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q2);
2232 cmd->nodeID = HCI1394_DESC_SRCID_GET(quadlet);
2233 cmd->cmd_addr = HCI1394_TO_ADDR_HI(quadlet);
2234 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q3);
2235 cmd->cmd_addr |= HCI1394_TO_ADDR_LO(quadlet);
2236
2237 /* Copy ARREQ lock data into 1394 framework command */
2238 if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) {
2239 data_addr = (uint8_t *)&pkt->q5;
2240 hci1394_q_ar_rep_get8(async_handle->as_arreq_q,
2241 (uint8_t *)&cmd->cmd_u.l32.arg_value, data_addr,
2242 IEEE1394_QUADLET);
2243 data_addr = (uint8_t *)((uintptr_t)data_addr +
2244 (uintptr_t)IEEE1394_QUADLET);
2245 hci1394_q_ar_rep_get8(async_handle->as_arreq_q,
2246 (uint8_t *)&cmd->cmd_u.l32.data_value, data_addr,
2247 IEEE1394_QUADLET);
2248 /*
2249 * swap these for our correct architecture if we are doing
2250 * arithmetic lock operations
2251 */
2252 cmd->cmd_u.l32.arg_value = HCI1394_ARITH_LOCK_SWAP32(
2253 cmd->cmd_u.l32.lock_type, cmd->cmd_u.l32.arg_value);
2254 cmd->cmd_u.l32.data_value = HCI1394_ARITH_LOCK_SWAP32(
2255 cmd->cmd_u.l32.lock_type, cmd->cmd_u.l32.data_value);
2256 } else if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_64) {
2257 data_addr = (uint8_t *)&pkt->q5;
2258 hci1394_q_ar_rep_get8(async_handle->as_arreq_q,
2259 (uint8_t *)&cmd->cmd_u.l64.arg_value, data_addr,
2260 IEEE1394_OCTLET);
2261 data_addr = (uint8_t *)((uintptr_t)data_addr +
2262 (uintptr_t)IEEE1394_OCTLET);
2263 hci1394_q_ar_rep_get8(async_handle->as_arreq_q,
2264 (uint8_t *)&cmd->cmd_u.l64.data_value, data_addr,
2265 IEEE1394_OCTLET);
2266
2267 /*
2268 * swap these for our correct architecture if we are doing
2269 * arithmetic lock operations
2270 */
2271 cmd->cmd_u.l64.arg_value = HCI1394_ARITH_LOCK_SWAP64(
2272 cmd->cmd_u.l64.lock_type, cmd->cmd_u.l64.arg_value);
2273 cmd->cmd_u.l64.data_value = HCI1394_ARITH_LOCK_SWAP64(
2274 cmd->cmd_u.l64.lock_type, cmd->cmd_u.l64.data_value);
2275 }
2276
2277 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_qrd_exit,
2278 HCI1394_TNF_HAL_STACK, "");
2279
2280 return (DDI_SUCCESS);
2281 }
2282
2283
2284 /*
2285 * hci1394_async_arreq_read_phy()
2286 * Read ARREQ PHY quadlet into the 1394 Framework command. This routine will
2287 * return DDI_FAILURE if it was not able to read the request succesfully.
2288 */
2289 static int
hci1394_async_arreq_read_phy(hci1394_async_handle_t async_handle,hci1394_basic_pkt_t * pkt,hci1394_async_cmd_t * hcicmd,uint_t * size,boolean_t * bus_reset_token)2290 hci1394_async_arreq_read_phy(hci1394_async_handle_t async_handle,
2291 hci1394_basic_pkt_t *pkt, hci1394_async_cmd_t *hcicmd, uint_t *size,
2292 boolean_t *bus_reset_token)
2293 {
2294 cmd1394_cmd_t *cmd;
2295 uint32_t quadlet;
2296 uint32_t data1;
2297 uint32_t data2;
2298
2299
2300 ASSERT(async_handle != NULL);
2301 ASSERT(pkt != NULL);
2302 ASSERT(hcicmd != NULL);
2303 ASSERT(size != NULL);
2304 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_phy_enter,
2305 HCI1394_TNF_HAL_STACK, "");
2306
2307 /* Setup shortcuts, command type, and size of request */
2308 cmd = hcicmd->ac_cmd;
2309 cmd->cmd_type = CMD1394_ASYNCH_WR_QUAD;
2310 *size = DESC_SZ_AR_PHY;
2311
2312 /*
2313 * read in the ARREQ ACK/EVT, the speed, the time we received it, and
2314 * set state that we do not use an mblk for this request.
2315 */
2316 quadlet = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q4);
2317 hcicmd->ac_status = HCI1394_DESC_EVT_GET(quadlet);
2318 hcicmd->ac_priv->speed = HCI1394_DESC_AR_SPD_GET(quadlet);
2319 hcicmd->ac_priv->recv_tstamp = HCI1394_DESC_TIMESTAMP_GET(quadlet);
2320 hcicmd->ac_mblk_alloc = B_FALSE;
2321
2322 /* Read in the PHY packet quadlet and its check quadlet */
2323 data1 = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q2);
2324 data2 = hci1394_q_ar_get32(async_handle->as_arreq_q, &pkt->q3);
2325
2326 /*
2327 * if this is a bus reset token, save away the generation. If the bus
2328 * reset token is for the current generation, we do not need to flush
2329 * the ARREQ Q anymore.
2330 */
2331 if (hcicmd->ac_status == OHCI_EVT_BUS_RESET) {
2332 *bus_reset_token = B_TRUE;
2333 async_handle->as_phy_reset = HCI1394_DESC_PHYGEN_GET(data2);
2334 if (async_handle->as_phy_reset == hci1394_ohci_current_busgen(
2335 async_handle->as_ohci)) {
2336 async_handle->as_flushing_arreq = B_FALSE;
2337 }
2338 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_phy_exit,
2339 HCI1394_TNF_HAL_STACK, "");
2340 return (DDI_SUCCESS);
2341 }
2342
2343 *bus_reset_token = B_FALSE;
2344
2345 /* if there is a data error in the PHY packet, return failure */
2346 if (data1 != ~data2) {
2347 TNF_PROBE_2(hci1394_async_arreq_phy_xor_fail,
2348 HCI1394_TNF_HAL_ERROR, "", tnf_opaque, first_quadlet,
2349 data1, tnf_opaque, second_quadlet, data2);
2350 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_phy_exit,
2351 HCI1394_TNF_HAL_STACK, "");
2352 return (DDI_FAILURE);
2353 }
2354
2355 /* Copy the PHY quadlet to the command */
2356 cmd->cmd_u.q.quadlet_data = data1;
2357
2358 TNF_PROBE_0_DEBUG(hci1394_async_arreq_read_phy_exit,
2359 HCI1394_TNF_HAL_STACK, "");
2360
2361 return (DDI_SUCCESS);
2362 }
2363
2364
2365 /*
2366 * hci1394_async_phy()
2367 * Queue up ATREQ phy packet.
2368 */
2369 int
hci1394_async_phy(hci1394_async_handle_t async_handle,cmd1394_cmd_t * cmd,h1394_cmd_priv_t * cmd_priv,int * result)2370 hci1394_async_phy(hci1394_async_handle_t async_handle, cmd1394_cmd_t *cmd,
2371 h1394_cmd_priv_t *cmd_priv, int *result)
2372 {
2373 hci1394_basic_pkt_t header;
2374 hci1394_async_cmd_t *hcicmd;
2375 int status;
2376
2377
2378 ASSERT(async_handle != NULL);
2379 ASSERT(cmd != NULL);
2380 ASSERT(cmd_priv != NULL);
2381 ASSERT(result != NULL);
2382
2383 TNF_PROBE_0_DEBUG(hci1394_async_phy_enter, HCI1394_TNF_HAL_STACK, "");
2384
2385 /*
2386 * make sure this call is during the current bus generation (i.e. no
2387 * bus resets have occured since this request was made.
2388 */
2389 if (cmd_priv->bus_generation != hci1394_ohci_current_busgen(
2390 async_handle->as_ohci)) {
2391 *result = H1394_STATUS_INVALID_BUSGEN;
2392 TNF_PROBE_0_DEBUG(hci1394_async_phy_exit,
2393 HCI1394_TNF_HAL_STACK, "");
2394 return (DDI_FAILURE);
2395 }
2396
2397 /* Initialize the private HAL command structure */
2398 hci1394_async_hcicmd_init(async_handle, cmd, cmd_priv, &hcicmd);
2399
2400 /* We do not allocate a tlabel for a PHY packet */
2401 hcicmd->ac_tlabel_alloc = B_FALSE;
2402
2403 /*
2404 * Setup the packet header information for a ATREQ PHY packet Add in
2405 * the tcode, phy quadlet, and it's 1's complement.
2406 */
2407 header.q1 = DESC_ATREQ_Q1_PHY;
2408 header.q2 = cmd->cmd_u.q.quadlet_data;
2409 header.q3 = ~header.q2;
2410
2411 /* Write request into the ATREQ Q. If we fail, we're out of space */
2412 status = hci1394_q_at(async_handle->as_atreq_q, &hcicmd->ac_qcmd,
2413 &header, DESC_PKT_HDRLEN_AT_PHY, result);
2414 if (status != DDI_SUCCESS) {
2415 TNF_PROBE_0(hci1394_async_phy_q_fail, HCI1394_TNF_HAL_ERROR,
2416 "");
2417 TNF_PROBE_0_DEBUG(hci1394_async_phy_exit,
2418 HCI1394_TNF_HAL_STACK, "");
2419 return (DDI_FAILURE);
2420 }
2421
2422 TNF_PROBE_0_DEBUG(hci1394_async_phy_exit, HCI1394_TNF_HAL_STACK, "");
2423
2424 return (DDI_SUCCESS);
2425 }
2426
2427
2428 /*
2429 * hci1394_async_write()
2430 * Queue up ATREQ write. This could be either a block write or a quadlet
2431 * write.
2432 */
2433 int
hci1394_async_write(hci1394_async_handle_t async_handle,cmd1394_cmd_t * cmd,h1394_cmd_priv_t * cmd_priv,int * result)2434 hci1394_async_write(hci1394_async_handle_t async_handle, cmd1394_cmd_t *cmd,
2435 h1394_cmd_priv_t *cmd_priv, int *result)
2436 {
2437 hci1394_async_cmd_t *hcicmd;
2438 hci1394_basic_pkt_t header;
2439 int status;
2440
2441
2442 ASSERT(async_handle != NULL);
2443 ASSERT(cmd != NULL);
2444 ASSERT(cmd_priv != NULL);
2445 ASSERT(result != NULL);
2446
2447 TNF_PROBE_0_DEBUG(hci1394_async_write_enter, HCI1394_TNF_HAL_STACK, "");
2448
2449 /*
2450 * make sure this call is during the current bus generation (i.e. no
2451 * bus resets have occured since this request was made.
2452 */
2453 if (cmd_priv->bus_generation != hci1394_ohci_current_busgen(
2454 async_handle->as_ohci)) {
2455 *result = H1394_STATUS_INVALID_BUSGEN;
2456 TNF_PROBE_0_DEBUG(hci1394_async_write_exit,
2457 HCI1394_TNF_HAL_STACK, "");
2458 return (DDI_FAILURE);
2459 }
2460
2461 /* Initialize the private HAL command structure */
2462 hci1394_async_hcicmd_init(async_handle, cmd, cmd_priv, &hcicmd);
2463 hcicmd->ac_dest = (uint_t)(cmd->cmd_addr >> IEEE1394_ADDR_PHY_ID_SHIFT);
2464
2465 /* allocate a tlabel for this request */
2466 status = hci1394_tlabel_alloc(async_handle->as_tlabel, hcicmd->ac_dest,
2467 &hcicmd->ac_tlabel);
2468 if (status != DDI_SUCCESS) {
2469 *result = H1394_STATUS_EMPTY_TLABEL;
2470 TNF_PROBE_0(hci1394_async_write_tlb_fail,
2471 HCI1394_TNF_HAL_ERROR, "");
2472 TNF_PROBE_0_DEBUG(hci1394_async_write_exit,
2473 HCI1394_TNF_HAL_STACK, "");
2474 return (DDI_FAILURE);
2475 }
2476
2477 /*
2478 * Setup the packet header information for a ATREQ write packet. We
2479 * will set the tcode later on since this could be a block write or
2480 * a quadlet write. Set SRCBusId if this write is not a local bus
2481 * access. Copy in the speed, tlabel, and destination address.
2482 */
2483 header.q1 = 0;
2484 if ((hcicmd->ac_dest & IEEE1394_BUS_NUM_MASK) !=
2485 IEEE1394_BUS_NUM_MASK) {
2486 header.q1 |= DESC_AT_SRCBUSID;
2487 }
2488 header.q1 |= HCI1394_DESC_AT_SPD_SET(cmd_priv->speed) |
2489 HCI1394_DESC_TLABEL_SET(hcicmd->ac_tlabel.tbi_tlabel);
2490 header.q2 = (uint32_t)(cmd->cmd_addr >> 32);
2491 header.q3 = (uint32_t)(cmd->cmd_addr & DESC_PKT_DESTOFFLO_MASK);
2492
2493 /* Register this command w/ its tlabel */
2494 hci1394_tlabel_register(async_handle->as_tlabel, &hcicmd->ac_tlabel,
2495 hcicmd);
2496
2497 /* If this is a quadlet write ATREQ */
2498 if (cmd->cmd_type == CMD1394_ASYNCH_WR_QUAD) {
2499 /*
2500 * setup the tcode for a quadlet write request and copy in
2501 * the quadlet data. Endian issues will be taken care of in
2502 * hci1394_q_at().
2503 */
2504 header.q1 |= DESC_ATREQ_Q1_QWR;
2505 header.q4 = cmd->cmd_u.q.quadlet_data;
2506
2507 /*
2508 * Write the request into the ATREQ Q. If we fail, we are out
2509 * of space.
2510 */
2511 status = hci1394_q_at(async_handle->as_atreq_q,
2512 &hcicmd->ac_qcmd, &header, DESC_PKT_HDRLEN_AT_WRITEQUAD,
2513 result);
2514 if (status != DDI_SUCCESS) {
2515 TNF_PROBE_0(hci1394_async_write_q_fail,
2516 HCI1394_TNF_HAL_ERROR, "");
2517 TNF_PROBE_0_DEBUG(hci1394_async_write_exit,
2518 HCI1394_TNF_HAL_STACK, "");
2519 return (DDI_FAILURE);
2520 }
2521
2522 /* This is a block write ATREQ */
2523 } else {
2524 /* setup the tcode and the length of the block write */
2525 header.q1 |= DESC_ATREQ_Q1_BWR;
2526 header.q4 = HCI1394_DESC_DATALEN_SET(cmd_priv->mblk.length);
2527
2528 /*
2529 * Write the request into the ATREQ Q. If we fail, we are out
2530 * of space. The data is in a mblk(s). We use a special
2531 * interface in the HAL/SL private command block to handle
2532 * partial transfers out of the mblk due to packet size
2533 * restrictions.
2534 */
2535 status = hci1394_q_at_with_mblk(async_handle->as_atreq_q,
2536 &hcicmd->ac_qcmd, &header, DESC_PKT_HDRLEN_AT_WRITEBLOCK,
2537 &cmd_priv->mblk, result);
2538 if (status != DDI_SUCCESS) {
2539 TNF_PROBE_0(hci1394_async_write_qmblk_fail,
2540 HCI1394_TNF_HAL_ERROR, "");
2541 TNF_PROBE_0_DEBUG(hci1394_async_write_exit,
2542 HCI1394_TNF_HAL_STACK, "");
2543 return (DDI_FAILURE);
2544 }
2545 }
2546
2547 TNF_PROBE_0_DEBUG(hci1394_async_write_exit, HCI1394_TNF_HAL_STACK, "");
2548
2549 return (DDI_SUCCESS);
2550 }
2551
2552
2553 /*
2554 * hci1394_async_read()
2555 * Queue up ATREQ read. This could be either a block read or a quadlet
2556 * read.
2557 */
2558 int
hci1394_async_read(hci1394_async_handle_t async_handle,cmd1394_cmd_t * cmd,h1394_cmd_priv_t * cmd_priv,int * result)2559 hci1394_async_read(hci1394_async_handle_t async_handle, cmd1394_cmd_t *cmd,
2560 h1394_cmd_priv_t *cmd_priv, int *result)
2561 {
2562 hci1394_basic_pkt_t header;
2563 int status;
2564 hci1394_async_cmd_t *hcicmd;
2565
2566
2567 ASSERT(async_handle != NULL);
2568 ASSERT(cmd != NULL);
2569 ASSERT(cmd_priv != NULL);
2570 ASSERT(result != NULL);
2571
2572 TNF_PROBE_0_DEBUG(hci1394_async_read_enter, HCI1394_TNF_HAL_STACK, "");
2573
2574 /*
2575 * make sure this call is during the current bus generation (i.e. no
2576 * bus resets have occured since this request was made.
2577 */
2578 if (cmd_priv->bus_generation != hci1394_ohci_current_busgen(
2579 async_handle->as_ohci)) {
2580 *result = H1394_STATUS_INVALID_BUSGEN;
2581 TNF_PROBE_0_DEBUG(hci1394_async_read_exit,
2582 HCI1394_TNF_HAL_STACK, "");
2583 return (DDI_FAILURE);
2584 }
2585
2586 /* Initialize the private HAL command structure */
2587 hci1394_async_hcicmd_init(async_handle, cmd, cmd_priv, &hcicmd);
2588 hcicmd->ac_dest = (uint_t)(cmd->cmd_addr >> IEEE1394_ADDR_PHY_ID_SHIFT);
2589
2590 /* allocate a tlabel for this request */
2591 status = hci1394_tlabel_alloc(async_handle->as_tlabel, hcicmd->ac_dest,
2592 &hcicmd->ac_tlabel);
2593 if (status != DDI_SUCCESS) {
2594 *result = H1394_STATUS_EMPTY_TLABEL;
2595 TNF_PROBE_0(hci1394_async_read_tlb_fail,
2596 HCI1394_TNF_HAL_ERROR, "");
2597 TNF_PROBE_0_DEBUG(hci1394_async_read_exit,
2598 HCI1394_TNF_HAL_STACK, "");
2599 return (DDI_FAILURE);
2600 }
2601
2602 /*
2603 * Setup the packet header information for a ATREQ read packet. We
2604 * will set the tcode later on since this could be a block read or
2605 * a quadlet read. Set SRCBusId if this read is not a local bus
2606 * access. Copy in the speed, tlabel, and destination address.
2607 */
2608 header.q1 = 0;
2609 if ((hcicmd->ac_dest & IEEE1394_BUS_NUM_MASK) !=
2610 IEEE1394_BUS_NUM_MASK) {
2611 header.q1 |= DESC_AT_SRCBUSID;
2612 }
2613 header.q1 |= HCI1394_DESC_AT_SPD_SET(cmd_priv->speed) |
2614 HCI1394_DESC_TLABEL_SET(hcicmd->ac_tlabel.tbi_tlabel);
2615 header.q2 = (uint32_t)(cmd->cmd_addr >> 32);
2616 header.q3 = (uint32_t)(cmd->cmd_addr & DESC_PKT_DESTOFFLO_MASK);
2617
2618 /* Register this command w/ its tlabel */
2619 hci1394_tlabel_register(async_handle->as_tlabel, &hcicmd->ac_tlabel,
2620 hcicmd);
2621
2622 /* If this is a quadlet read ATREQ */
2623 if (cmd->cmd_type == CMD1394_ASYNCH_RD_QUAD) {
2624 /* setup the tcode for a quadlet read request */
2625 header.q1 |= DESC_ATREQ_Q1_QRD;
2626 header.q4 = 0;
2627
2628 /*
2629 * Write the request into the ATREQ Q. If we fail, we are out
2630 * of space.
2631 */
2632 status = hci1394_q_at(async_handle->as_atreq_q,
2633 &hcicmd->ac_qcmd, &header, DESC_PKT_HDRLEN_AT_READQUAD,
2634 result);
2635 if (status != DDI_SUCCESS) {
2636 TNF_PROBE_0(hci1394_async_read_q_fail,
2637 HCI1394_TNF_HAL_ERROR, "");
2638 TNF_PROBE_0_DEBUG(hci1394_async_read_exit,
2639 HCI1394_TNF_HAL_STACK, "");
2640 return (DDI_FAILURE);
2641 }
2642
2643 } else {
2644 /* setup the tcode and the length of the block read */
2645 header.q1 |= DESC_ATREQ_Q1_BRD;
2646 header.q4 = HCI1394_DESC_DATALEN_SET(cmd_priv->mblk.length);
2647
2648 /*
2649 * Write the request into the ATREQ Q. If we fail, we are out
2650 * of space.
2651 */
2652 status = hci1394_q_at(async_handle->as_atreq_q,
2653 &hcicmd->ac_qcmd, &header, DESC_PKT_HDRLEN_AT_READBLOCK,
2654 result);
2655 if (status != DDI_SUCCESS) {
2656 TNF_PROBE_0(hci1394_async_read_qb_fail,
2657 HCI1394_TNF_HAL_ERROR, "");
2658 TNF_PROBE_0_DEBUG(hci1394_async_read_exit,
2659 HCI1394_TNF_HAL_STACK, "");
2660 return (DDI_FAILURE);
2661 }
2662 }
2663
2664 TNF_PROBE_0_DEBUG(hci1394_async_read_exit, HCI1394_TNF_HAL_STACK, "");
2665
2666 return (DDI_SUCCESS);
2667 }
2668
2669
2670 /*
2671 * hci1394_async_lock()
2672 * Queue up ATREQ lock. This could be either a 32-bit or 64-bit lock
2673 * request.
2674 */
2675 int
hci1394_async_lock(hci1394_async_handle_t async_handle,cmd1394_cmd_t * cmd,h1394_cmd_priv_t * cmd_priv,int * result)2676 hci1394_async_lock(hci1394_async_handle_t async_handle, cmd1394_cmd_t *cmd,
2677 h1394_cmd_priv_t *cmd_priv, int *result)
2678 {
2679 hci1394_basic_pkt_t header;
2680 hci1394_async_cmd_t *hcicmd;
2681 uint32_t data32[2];
2682 uint64_t data64[2];
2683 uint8_t *datap;
2684 uint_t size;
2685 int status;
2686
2687
2688 ASSERT(async_handle != NULL);
2689 ASSERT(cmd != NULL);
2690 ASSERT(cmd_priv != NULL);
2691 ASSERT(result != NULL);
2692
2693 TNF_PROBE_0_DEBUG(hci1394_async_lock_enter, HCI1394_TNF_HAL_STACK, "");
2694
2695 /*
2696 * make sure this call is during the current bus generation (i.e. no
2697 * bus resets have occured since this request was made.
2698 */
2699 if (cmd_priv->bus_generation != hci1394_ohci_current_busgen(
2700 async_handle->as_ohci)) {
2701 *result = H1394_STATUS_INVALID_BUSGEN;
2702 TNF_PROBE_0_DEBUG(hci1394_async_lock_exit,
2703 HCI1394_TNF_HAL_STACK, "");
2704 return (DDI_FAILURE);
2705 }
2706
2707 /* Initialize the private HAL command structure */
2708 hci1394_async_hcicmd_init(async_handle, cmd, cmd_priv, &hcicmd);
2709 hcicmd->ac_dest = (uint_t)(cmd->cmd_addr >> IEEE1394_ADDR_PHY_ID_SHIFT);
2710
2711 /* allocate a tlabel for this request */
2712 status = hci1394_tlabel_alloc(async_handle->as_tlabel, hcicmd->ac_dest,
2713 &hcicmd->ac_tlabel);
2714 if (status != DDI_SUCCESS) {
2715 *result = H1394_STATUS_EMPTY_TLABEL;
2716 TNF_PROBE_0(hci1394_async_lock_tlb_fail,
2717 HCI1394_TNF_HAL_ERROR, "");
2718 TNF_PROBE_0_DEBUG(hci1394_async_lock_exit,
2719 HCI1394_TNF_HAL_STACK, "");
2720 return (DDI_FAILURE);
2721 }
2722
2723 /* Register this command w/ its tlabel */
2724 hci1394_tlabel_register(async_handle->as_tlabel, &hcicmd->ac_tlabel,
2725 hcicmd);
2726
2727 /*
2728 * Setup the packet header information for a ATREQ lock packet. Set
2729 * the tcode up as a lock request. Set SRCBusId if this lock is not a
2730 * local bus access. Copy in the speed, tlabel, and destination
2731 * address.
2732 */
2733 header.q1 = DESC_ATREQ_Q1_LCK;
2734 if ((hcicmd->ac_dest & IEEE1394_BUS_NUM_MASK) !=
2735 IEEE1394_BUS_NUM_MASK) {
2736 header.q1 |= DESC_AT_SRCBUSID;
2737 }
2738 header.q1 |= HCI1394_DESC_AT_SPD_SET(cmd_priv->speed) |
2739 HCI1394_DESC_TLABEL_SET(hcicmd->ac_tlabel.tbi_tlabel);
2740 header.q2 = (uint32_t)(cmd->cmd_addr >> 32);
2741 header.q3 = (uint32_t)(cmd->cmd_addr & DESC_PKT_DESTOFFLO_MASK);
2742
2743 /*
2744 * Setup the lock length based on what size lock operation we are
2745 * performing. If it isn't a lock32 or lock64, we have encountered an
2746 * internal error. Copy the lock data into a local data buffer. Perform
2747 * a byte swap if it is an arithmetic lock operation and we are on a
2748 * little endian machine.
2749 */
2750 if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) {
2751 size = DESC_TWO_QUADS;
2752 header.q4 = HCI1394_DESC_DATALEN_SET(size) |
2753 HCI1394_DESC_EXTTCODE_SET(cmd->cmd_u.l32.lock_type);
2754 data32[0] = HCI1394_ARITH_LOCK_SWAP32(
2755 cmd->cmd_u.l32.lock_type, cmd->cmd_u.l32.arg_value);
2756 data32[1] = HCI1394_ARITH_LOCK_SWAP32(
2757 cmd->cmd_u.l32.lock_type, cmd->cmd_u.l32.data_value);
2758 datap = (uint8_t *)data32;
2759 } else if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_64) {
2760 size = DESC_TWO_OCTLETS;
2761 header.q4 = HCI1394_DESC_DATALEN_SET(size) |
2762 HCI1394_DESC_EXTTCODE_SET(cmd->cmd_u.l64.lock_type);
2763 data64[0] = HCI1394_ARITH_LOCK_SWAP64(
2764 cmd->cmd_u.l64.lock_type, cmd->cmd_u.l64.arg_value);
2765 data64[1] = HCI1394_ARITH_LOCK_SWAP64(
2766 cmd->cmd_u.l64.lock_type, cmd->cmd_u.l64.data_value);
2767 datap = (uint8_t *)data64;
2768 } else {
2769 *result = H1394_STATUS_INTERNAL_ERROR;
2770 TNF_PROBE_0(hci1394_lock_length_fail,
2771 HCI1394_TNF_HAL_ERROR, "");
2772 TNF_PROBE_0_DEBUG(hci1394_async_lock_exit,
2773 HCI1394_TNF_HAL_STACK, "");
2774 return (DDI_FAILURE);
2775 }
2776
2777 /* Write request into the ATREQ Q. If we fail, we're out of space */
2778 status = hci1394_q_at_with_data(async_handle->as_atreq_q,
2779 &hcicmd->ac_qcmd, &header, DESC_PKT_HDRLEN_AT_LOCK, datap, size,
2780 result);
2781 if (status != DDI_SUCCESS) {
2782 TNF_PROBE_0(hci1394_async_lock_q_fail,
2783 HCI1394_TNF_HAL_ERROR, "");
2784 TNF_PROBE_0_DEBUG(hci1394_async_lock_exit,
2785 HCI1394_TNF_HAL_STACK, "");
2786 return (DDI_FAILURE);
2787 }
2788
2789 TNF_PROBE_0_DEBUG(hci1394_async_lock_exit, HCI1394_TNF_HAL_STACK, "");
2790
2791 return (DDI_SUCCESS);
2792 }
2793
2794
2795 /*
2796 * hci1394_async_write_response()
2797 * Send a write ATRESP. This routine should be called from the Services
2798 * layer to send a response to a received write request (ARREQ). The same
2799 * response is sent to a quadlet and block write request.
2800 */
2801 int
hci1394_async_write_response(hci1394_async_handle_t async_handle,cmd1394_cmd_t * cmd,h1394_cmd_priv_t * cmd_priv,int * result)2802 hci1394_async_write_response(hci1394_async_handle_t async_handle,
2803 cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result)
2804 {
2805 hci1394_basic_pkt_t header;
2806 int status;
2807 hci1394_async_cmd_t *hcicmd;
2808
2809
2810 ASSERT(async_handle != NULL);
2811 ASSERT(cmd != NULL);
2812 ASSERT(cmd_priv != NULL);
2813 ASSERT(result != NULL);
2814
2815 TNF_PROBE_0_DEBUG(hci1394_async_write_response_enter,
2816 HCI1394_TNF_HAL_STACK, "");
2817
2818 /*
2819 * make sure this call is during the current bus generation (i.e. no
2820 * bus resets have occured since this request was made.
2821 */
2822 if (cmd_priv->bus_generation != hci1394_ohci_current_busgen(
2823 async_handle->as_ohci)) {
2824 *result = H1394_STATUS_INVALID_BUSGEN;
2825 TNF_PROBE_0_DEBUG(hci1394_async_write_response_exit,
2826 HCI1394_TNF_HAL_STACK, "");
2827 return (DDI_FAILURE);
2828 }
2829
2830 /*
2831 * setup a shortcut to the hal private command area. Copy the generation
2832 * to the Q area so that we can check the generation when the AT Q is
2833 * locked. This prevents us from loosing commands due to race
2834 * conditions.
2835 */
2836 hcicmd = (hci1394_async_cmd_t *)cmd_priv->hal_overhead;
2837 hcicmd->ac_qcmd.qc_generation = cmd_priv->bus_generation;
2838
2839 /*
2840 * Setup the packet header information for a ATRESP write packet. Set
2841 * the tcode for a write response. Set SRCBusId if the addr is not a
2842 * local bus address. Copy in the speed, tlabel, and response code.
2843 */
2844 header.q1 = DESC_ATRESP_Q1_WR;
2845 if ((cmd->nodeID & IEEE1394_BUS_NUM_MASK) != IEEE1394_BUS_NUM_MASK) {
2846 header.q1 |= DESC_AT_SRCBUSID;
2847 }
2848 header.q1 |= HCI1394_DESC_AT_SPD_SET(cmd_priv->speed) |
2849 HCI1394_DESC_TLABEL_SET(hcicmd->ac_tlabel.tbi_tlabel);
2850 header.q2 = (HCI1394_DESC_DESTID_SET(cmd->nodeID) |
2851 HCI1394_DESC_RCODE_SET(cmd->cmd_result));
2852 header.q3 = 0;
2853
2854 /* Write response into the ATRESP Q. If we fail, we're out of space */
2855 status = hci1394_q_at(async_handle->as_atresp_q, &hcicmd->ac_qcmd,
2856 &header, DESC_PKT_HDRLEN_AT_WRITE_RESP, result);
2857 if (status != DDI_SUCCESS) {
2858 TNF_PROBE_0(hci1394_async_write_response_q_fail,
2859 HCI1394_TNF_HAL_ERROR, "");
2860 TNF_PROBE_0_DEBUG(hci1394_async_write_response_exit,
2861 HCI1394_TNF_HAL_STACK, "");
2862 return (DDI_FAILURE);
2863 }
2864
2865 TNF_PROBE_0_DEBUG(hci1394_async_write_response_exit,
2866 HCI1394_TNF_HAL_STACK, "");
2867
2868 return (DDI_SUCCESS);
2869 }
2870
2871
2872 /*
2873 * hci1394_async_read_response()
2874 * Send a read ATRESP. This routine should be called from the Services
2875 * layer to send a response to a received read request (ARREQ). The
2876 * response will differ between quadlet/block read requests.
2877 */
2878 int
hci1394_async_read_response(hci1394_async_handle_t async_handle,cmd1394_cmd_t * cmd,h1394_cmd_priv_t * cmd_priv,int * result)2879 hci1394_async_read_response(hci1394_async_handle_t async_handle,
2880 cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result)
2881 {
2882 hci1394_basic_pkt_t header;
2883 int status;
2884 hci1394_async_cmd_t *hcicmd;
2885
2886
2887 ASSERT(async_handle != NULL);
2888 ASSERT(cmd != NULL);
2889 ASSERT(cmd_priv != NULL);
2890 ASSERT(result != NULL);
2891
2892 TNF_PROBE_0_DEBUG(hci1394_async_read_response_enter,
2893 HCI1394_TNF_HAL_STACK, "");
2894
2895 /*
2896 * make sure this call is during the current bus generation (i.e. no
2897 * bus resets have occured since this request was made.
2898 */
2899 if (cmd_priv->bus_generation != hci1394_ohci_current_busgen(
2900 async_handle->as_ohci)) {
2901 *result = H1394_STATUS_INVALID_BUSGEN;
2902 TNF_PROBE_0_DEBUG(hci1394_async_read_response_exit,
2903 HCI1394_TNF_HAL_STACK, "");
2904 return (DDI_FAILURE);
2905 }
2906
2907 /*
2908 * setup a shortcut to the hal private command area. Copy the generation
2909 * to the Q area so that we can check the generation when the AT Q is
2910 * locked. This prevents us from loosing commands due to race
2911 * conditions.
2912 */
2913 hcicmd = (hci1394_async_cmd_t *)cmd_priv->hal_overhead;
2914 hcicmd->ac_qcmd.qc_generation = cmd_priv->bus_generation;
2915
2916 /*
2917 * Setup the packet header information for a ATRESP read packet. we
2918 * will set the tcode later based on type of read response. Set
2919 * SRCBusId if the addr is not a local bus address. Copy in the
2920 * speed, tlabel, and response code.
2921 */
2922 header.q1 = 0;
2923 if ((cmd->nodeID & IEEE1394_BUS_NUM_MASK) != IEEE1394_BUS_NUM_MASK) {
2924 header.q1 |= DESC_AT_SRCBUSID;
2925 }
2926 header.q1 |= HCI1394_DESC_AT_SPD_SET(cmd_priv->speed) |
2927 HCI1394_DESC_TLABEL_SET(hcicmd->ac_tlabel.tbi_tlabel);
2928 header.q2 = (uint32_t)(HCI1394_DESC_DESTID_SET(cmd->nodeID) |
2929 HCI1394_DESC_RCODE_SET(cmd->cmd_result));
2930 header.q3 = 0;
2931
2932 /* if the response is a read quadlet response */
2933 if (cmd->cmd_type == CMD1394_ASYNCH_RD_QUAD) {
2934 /*
2935 * setup the tcode for a quadlet read response, If the
2936 * response code is not resp complete.
2937 */
2938 header.q1 |= DESC_ATRESP_Q1_QRD;
2939 if (cmd->cmd_result == IEEE1394_RESP_COMPLETE) {
2940 header.q4 = cmd->cmd_u.q.quadlet_data;
2941 } else {
2942 header.q4 = 0x0;
2943 }
2944
2945 /*
2946 * Write response into the ATRESP Q. If we fail, we're out of
2947 * space.
2948 */
2949 status = hci1394_q_at(async_handle->as_atresp_q,
2950 &hcicmd->ac_qcmd, &header, DESC_PKT_HDRLEN_AT_READQUAD_RESP,
2951 result);
2952 if (status != DDI_SUCCESS) {
2953 TNF_PROBE_0(hci1394_async_read_response_q_fail,
2954 HCI1394_TNF_HAL_ERROR, "");
2955 TNF_PROBE_0_DEBUG(hci1394_async_read_response_exit,
2956 HCI1394_TNF_HAL_STACK, "");
2957 return (DDI_FAILURE);
2958 }
2959
2960 /*
2961 * the response is a block read response. If the result is not a
2962 * resp complete, we are not going to send any data back.
2963 */
2964 } else if ((cmd->cmd_type == CMD1394_ASYNCH_RD_BLOCK) &&
2965 (cmd->cmd_result != IEEE1394_RESP_COMPLETE)) {
2966 /*
2967 * Setup the tcode for a block read response, set the data
2968 * length to zero since we had an error.
2969 */
2970 header.q1 |= DESC_ATRESP_Q1_BRD;
2971 header.q4 = 0x0;
2972
2973 /*
2974 * Write response into the ATRESP Q. If we fail, we're out of
2975 * space.
2976 */
2977 status = hci1394_q_at(async_handle->as_atresp_q,
2978 &hcicmd->ac_qcmd, &header,
2979 DESC_PKT_HDRLEN_AT_READBLOCK_RESP, result);
2980 if (status != DDI_SUCCESS) {
2981 TNF_PROBE_0(hci1394_async_read_response_qbf_fail,
2982 HCI1394_TNF_HAL_ERROR, "");
2983 TNF_PROBE_0_DEBUG(hci1394_async_read_response_exit,
2984 HCI1394_TNF_HAL_STACK, "");
2985 return (DDI_FAILURE);
2986 }
2987
2988 /*
2989 * the response is a block read response with a resp complete for the
2990 * response code. Send back the read data.
2991 */
2992 } else {
2993 /*
2994 * Setup the tcode for a block read response, setup the data
2995 * length.
2996 */
2997 header.q1 |= DESC_ATRESP_Q1_BRD;
2998 header.q4 = HCI1394_DESC_DATALEN_SET(cmd->cmd_u.b.blk_length);
2999
3000 /*
3001 * Write response into the ATRESP Q. If we fail, we're out of
3002 * space. Use the data in the mblk.
3003 */
3004 status = hci1394_q_at_with_mblk(async_handle->as_atresp_q,
3005 &hcicmd->ac_qcmd, &header,
3006 DESC_PKT_HDRLEN_AT_READBLOCK_RESP, &cmd_priv->mblk, result);
3007 if (status != DDI_SUCCESS) {
3008 TNF_PROBE_0(hci1394_async_read_response_qb_fail,
3009 HCI1394_TNF_HAL_ERROR, "");
3010 TNF_PROBE_0_DEBUG(hci1394_async_read_response_exit,
3011 HCI1394_TNF_HAL_STACK, "");
3012 return (DDI_FAILURE);
3013 }
3014 }
3015
3016 TNF_PROBE_0_DEBUG(hci1394_async_read_response_exit,
3017 HCI1394_TNF_HAL_STACK, "");
3018
3019 return (DDI_SUCCESS);
3020 }
3021
3022
3023 /*
3024 * hci1394_async_lock_response()
3025 * Send a lock ATRESP. This routine should be called from the Services
3026 * layer to send a response to a received lock request (ARREQ). The
3027 * response will differ between 32-bit/64-bit lock requests.
3028 */
3029 int
hci1394_async_lock_response(hci1394_async_handle_t async_handle,cmd1394_cmd_t * cmd,h1394_cmd_priv_t * cmd_priv,int * result)3030 hci1394_async_lock_response(hci1394_async_handle_t async_handle,
3031 cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result)
3032 {
3033 hci1394_basic_pkt_t header;
3034 hci1394_async_cmd_t *hcicmd;
3035 uint32_t data32;
3036 uint64_t data64;
3037 uint8_t *datap;
3038 uint_t size;
3039 int status;
3040
3041
3042 ASSERT(async_handle != NULL);
3043 ASSERT(cmd != NULL);
3044 ASSERT(cmd_priv != NULL);
3045 ASSERT(result != NULL);
3046
3047 TNF_PROBE_0_DEBUG(hci1394_async_lock_response_enter,
3048 HCI1394_TNF_HAL_STACK, "");
3049
3050 /*
3051 * make sure this call is during the current bus generation (i.e. no
3052 * bus resets have occured since this request was made.
3053 */
3054 if (cmd_priv->bus_generation != hci1394_ohci_current_busgen(
3055 async_handle->as_ohci)) {
3056 *result = H1394_STATUS_INVALID_BUSGEN;
3057 TNF_PROBE_0_DEBUG(hci1394_async_lock_response_exit,
3058 HCI1394_TNF_HAL_STACK, "");
3059 return (DDI_FAILURE);
3060 }
3061
3062 /*
3063 * setup a shortcut to the hal private command area. Copy the generation
3064 * to the Q area so that we can check the generation when the AT Q is
3065 * locked. This prevents us from loosing commands due to race
3066 * conditions.
3067 */
3068 hcicmd = (hci1394_async_cmd_t *)cmd_priv->hal_overhead;
3069 hcicmd->ac_qcmd.qc_generation = cmd_priv->bus_generation;
3070
3071 /*
3072 * Setup the packet header information for a ATRESP lock packet. Set
3073 * the tcode for a lock response. Set SRCBusId if the addr is not a
3074 * local bus address. Copy in the speed, tlabel, and response code.
3075 */
3076 header.q1 = DESC_ATRESP_Q1_LCK;
3077 if ((cmd->nodeID & IEEE1394_BUS_NUM_MASK) != IEEE1394_BUS_NUM_MASK) {
3078 header.q1 |= DESC_AT_SRCBUSID;
3079 }
3080 header.q1 |= HCI1394_DESC_AT_SPD_SET(cmd_priv->speed) |
3081 HCI1394_DESC_TLABEL_SET(hcicmd->ac_tlabel.tbi_tlabel);
3082 header.q2 = (uint32_t)(HCI1394_DESC_DESTID_SET(cmd->nodeID) |
3083 HCI1394_DESC_RCODE_SET(cmd->cmd_result));
3084 header.q3 = 0;
3085
3086 /*
3087 * If the lock result is not a resp complete, we are not going to send
3088 * any data back.with the response.
3089 */
3090 if (cmd->cmd_result != IEEE1394_RESP_COMPLETE) {
3091 /* set response size to 0 for error. Set the extended tcode */
3092 size = 0;
3093 if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) {
3094 header.q4 = HCI1394_DESC_DATALEN_SET(size) |
3095 HCI1394_DESC_EXTTCODE_SET(cmd->cmd_u.l32.lock_type);
3096 } else {
3097 header.q4 = HCI1394_DESC_DATALEN_SET(size) |
3098 HCI1394_DESC_EXTTCODE_SET(cmd->cmd_u.l64.lock_type);
3099 }
3100
3101 /*
3102 * Write response into the ATRESP Q. If we fail, we're out of
3103 * space.
3104 */
3105 status = hci1394_q_at(async_handle->as_atresp_q,
3106 &hcicmd->ac_qcmd, &header, DESC_PKT_HDRLEN_AT_LOCK_RESP,
3107 result);
3108 if (status != DDI_SUCCESS) {
3109 TNF_PROBE_0(hci1394_q_alloc_fail,
3110 HCI1394_TNF_HAL_ERROR, "");
3111 TNF_PROBE_0_DEBUG(hci1394_async_lock_response_exit,
3112 HCI1394_TNF_HAL_STACK, "");
3113 return (DDI_FAILURE);
3114 }
3115 TNF_PROBE_0_DEBUG(hci1394_async_lock_response_exit,
3116 HCI1394_TNF_HAL_STACK, "");
3117 return (DDI_SUCCESS);
3118 }
3119
3120 /*
3121 * if the lock result is resp complete, setup the size of the response
3122 * depending on the lock size and copy the lock response data into a
3123 * local buffer. If the lock response is an arithmetic operation, swap
3124 * the data on little endian machines. If we don't know what type of
3125 * lock operation it is, someone has corrupted the command since we
3126 * had received the ARREQ.
3127 */
3128 if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_32) {
3129 size = IEEE1394_QUADLET;
3130 header.q4 = HCI1394_DESC_DATALEN_SET(size) |
3131 HCI1394_DESC_EXTTCODE_SET(cmd->cmd_u.l32.lock_type);
3132 data32 = HCI1394_ARITH_LOCK_SWAP32(
3133 cmd->cmd_u.l32.lock_type, cmd->cmd_u.l32.old_value);
3134 datap = (uint8_t *)&data32;
3135 } else if (cmd->cmd_type == CMD1394_ASYNCH_LOCK_64) {
3136 size = IEEE1394_OCTLET;
3137 header.q4 = HCI1394_DESC_DATALEN_SET(size) |
3138 HCI1394_DESC_EXTTCODE_SET(cmd->cmd_u.l64.lock_type);
3139 data64 = HCI1394_ARITH_LOCK_SWAP64(
3140 cmd->cmd_u.l64.lock_type, cmd->cmd_u.l64.old_value);
3141 datap = (uint8_t *)&data64;
3142 } else {
3143 *result = H1394_STATUS_INTERNAL_ERROR;
3144 TNF_PROBE_0(hci1394_lock_type_fail, HCI1394_TNF_HAL_ERROR, "");
3145 TNF_PROBE_0_DEBUG(hci1394_async_lock_response_exit,
3146 HCI1394_TNF_HAL_STACK, "");
3147 return (DDI_FAILURE);
3148 }
3149
3150 /*
3151 * Write response into the ATRESP Q. If we fail, we're out of space.
3152 * Use the local data buffer that we copied the data to above.
3153 */
3154 status = hci1394_q_at_with_data(async_handle->as_atresp_q,
3155 &hcicmd->ac_qcmd, &header, DESC_PKT_HDRLEN_AT_LOCK_RESP, datap,
3156 size, result);
3157 if (status != DDI_SUCCESS) {
3158 TNF_PROBE_0(hci1394_q_alloc_fail, HCI1394_TNF_HAL_ERROR, "");
3159 TNF_PROBE_0_DEBUG(hci1394_async_lock_response_exit,
3160 HCI1394_TNF_HAL_STACK, "");
3161 return (DDI_FAILURE);
3162 }
3163
3164 TNF_PROBE_0_DEBUG(hci1394_async_lock_response_exit,
3165 HCI1394_TNF_HAL_STACK, "");
3166
3167 return (DDI_SUCCESS);
3168 }
3169
3170
3171 /*
3172 * hci1394_async_response_complete()
3173 * Free up space allocted during an ARREQ. This is called when the target
3174 * driver and Services Layer are done with a command which was by the HAL
3175 * during ARREQ processing. This routine will also free up any allocated
3176 * mblks.
3177 *
3178 * NOTE: a target driver can hold on to a block write ARREQ mblk by setting
3179 * the mblk pointer to NULL. This ONLY applies to block write ARREQs. The
3180 * HAL will no longer track the mblk for this case.
3181 */
3182 void
hci1394_async_response_complete(hci1394_async_handle_t async_handle,cmd1394_cmd_t * cmd,h1394_cmd_priv_t * cmd_priv)3183 hci1394_async_response_complete(hci1394_async_handle_t async_handle,
3184 cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv)
3185 {
3186 hci1394_async_cmd_t *hcicmd;
3187
3188
3189 ASSERT(async_handle != NULL);
3190 ASSERT(cmd != NULL);
3191 ASSERT(cmd_priv != NULL);
3192
3193 TNF_PROBE_0_DEBUG(hci1394_async_response_complete_enter,
3194 HCI1394_TNF_HAL_STACK, "");
3195
3196 hcicmd = (hci1394_async_cmd_t *)cmd_priv->hal_overhead;
3197
3198 /* If we allocated an mblk for this command */
3199 if (hcicmd->ac_mblk_alloc == B_TRUE) {
3200 /*
3201 * Don't free mblk if it is set to NULL. This allows a target
3202 * driver to hold on to it in the case of a block write ARREQ.
3203 */
3204 if (cmd->cmd_u.b.data_block != NULL) {
3205 freeb(cmd->cmd_u.b.data_block);
3206 }
3207 }
3208
3209 /* free up the 1394 framework command */
3210 (void) h1394_free_cmd((void *)async_handle->as_drvinfo->di_sl_private,
3211 &cmd);
3212
3213 TNF_PROBE_0_DEBUG(hci1394_async_response_complete_exit,
3214 HCI1394_TNF_HAL_STACK, "");
3215 }
3216
3217
3218 /*
3219 * hci1394_async_pending_timeout()
3220 * This is the ARREQ Pending timeout callback routine. It is called from
3221 * the tlist code. There is a race condition with the ARRESP interrupt
3222 * handler (hci1394_async_arresp_process) which requires a mutex to
3223 * lock around the mark of the bad tlabel.
3224 *
3225 * Once we enter this routine, the command has timed out. If the command is
3226 * in both the ARRESP handler and here, we will consider it to have timed
3227 * out. That code path handles the race condition more easily.
3228 */
3229 static void
hci1394_async_pending_timeout(hci1394_tlist_node_t * node,void * arg)3230 hci1394_async_pending_timeout(hci1394_tlist_node_t *node, void *arg)
3231 {
3232 hci1394_async_handle_t async_handle;
3233 hci1394_async_cmd_t *hcicmd;
3234
3235
3236 async_handle = (hci1394_async_handle_t)arg;
3237 ASSERT(async_handle != NULL);
3238 ASSERT(node != NULL);
3239 TNF_PROBE_0_DEBUG(hci1394_async_pending_timeout_enter,
3240 HCI1394_TNF_HAL_STACK, "");
3241
3242 hcicmd = (hci1394_async_cmd_t *)node->tln_addr;
3243
3244 /*
3245 * We do NOT want to set the command state here. That should only be
3246 * done in the ISR. The state does nothing for us here.
3247 */
3248
3249 /*
3250 * We want a lock around tlabel_lookup/reading data into the cmd in the
3251 * ARRESP ISR processing and a lock around the tlabel_bad in this
3252 * routine. This ensures that we will not be touching the command
3253 * structure after we pass it up to the Services Layer. If we mark it as
3254 * bad first, the lookup will fail. If we get to the lookup first, the
3255 * pending list delete will fail in arresp_process() which will tell
3256 * that guy that we are in the middle of doing the timeout processing
3257 * for this command. The ARRESP logic will just drop the response and
3258 * continue on.
3259 */
3260 mutex_enter(&hcicmd->ac_async->as_atomic_lookup);
3261 hci1394_tlabel_bad(async_handle->as_tlabel, &hcicmd->ac_tlabel);
3262 mutex_exit(&hcicmd->ac_async->as_atomic_lookup);
3263
3264 /* Tell the Services Layer that the command has timed out */
3265 h1394_cmd_is_complete(async_handle->as_drvinfo->di_sl_private,
3266 hcicmd->ac_cmd, H1394_AT_REQ, H1394_CMD_ETIMEOUT);
3267
3268 TNF_PROBE_0_DEBUG(hci1394_async_pending_timeout_exit,
3269 HCI1394_TNF_HAL_STACK, "");
3270 }
3271
3272
3273 /*
3274 * hci1394_async_timeout_calc()
3275 * Calculate the timeout for an ATRESP. When an ARREQ is received, this
3276 * routine is called with the time the ARREQ was received. It returns the
3277 * time when the ATRESP is considered to have timed out. We timeout after
3278 * split_timeout has gone by. Split timeout and the returned value are in bus
3279 * cycles.
3280 */
3281 static uint_t
hci1394_async_timeout_calc(hci1394_async_handle_t async_handle,uint_t current_time)3282 hci1394_async_timeout_calc(hci1394_async_handle_t async_handle,
3283 uint_t current_time)
3284 {
3285 uint_t split_timeout;
3286 uint_t temp;
3287 uint_t carry;
3288 uint_t z;
3289
3290
3291 TNF_PROBE_0_DEBUG(hci1394_async_timeout_calc_enter,
3292 HCI1394_TNF_HAL_STACK, "");
3293
3294 /* Get the current split timeout */
3295 split_timeout = hci1394_csr_split_timeout_get(async_handle->as_csr);
3296
3297 /*
3298 * The cycle count is broken up into two sections, the 3-bit seconds
3299 * field and the 13-bit cycle count. The cycle count is in 125uS
3300 * increments. The maximum value of cycle count is 7999 (8000 is one
3301 * second). With 13-bits, we could store up to 8191. Therefore, we don't
3302 * have a simple 16-bit addition. Hence, the code we see below.
3303 */
3304
3305 /*
3306 * calculate the new cycle count based on the cycle count from current
3307 * time and the split timeout. If this new value is not greater than the
3308 * maximum cycle count, we don't have a carry. Go to the next step.
3309 */
3310 temp = (current_time & OHCI_CYCLE_CNT_MASK) + (split_timeout &
3311 OHCI_CYCLE_CNT_MASK);
3312 if (temp < OHCI_MAX_CYCLE_CNT) {
3313 carry = 0;
3314
3315 /*
3316 * the new cycle count adds up to more than the maximum cycle count,
3317 * set the carry state and adjust the total accordingly.
3318 */
3319 } else {
3320 temp = temp - OHCI_MAX_CYCLE_CNT;
3321 carry = 1;
3322 }
3323
3324 /*
3325 * The timeout time equals the seconds added with the carry (1 or 0
3326 * seconds), added with the adjusted (if necessary) cycle count.
3327 * Mask the final value to get rid of any second rollovers.
3328 */
3329 z = (current_time & OHCI_CYCLE_SEC_MASK) + (split_timeout &
3330 OHCI_CYCLE_SEC_MASK) + (carry << OHCI_CYCLE_SEC_SHIFT) + temp;
3331 z = z & OHCI_TIMESTAMP_MASK;
3332
3333 TNF_PROBE_0_DEBUG(hci1394_async_timeout_calc_exit,
3334 HCI1394_TNF_HAL_STACK, "");
3335
3336 return (z);
3337 }
3338
3339
3340 /*
3341 * hci1394_async_arresp_size_get()
3342 * Return the size of the arresp that was received in q_handle at addr.
3343 */
3344 static int
hci1394_async_arresp_size_get(uint_t tcode,hci1394_q_handle_t q_handle,uint32_t * addr,uint_t * size)3345 hci1394_async_arresp_size_get(uint_t tcode, hci1394_q_handle_t q_handle,
3346 uint32_t *addr, uint_t *size)
3347 {
3348 uint_t data_length;
3349 uint32_t quadlet;
3350
3351
3352 ASSERT(q_handle != NULL);
3353 ASSERT(addr != NULL);
3354 ASSERT(size != NULL);
3355
3356 TNF_PROBE_0_DEBUG(hci1394_get_arresp_size_enter,
3357 HCI1394_TNF_HAL_STACK, "");
3358
3359 if (tcode == IEEE1394_TCODE_WRITE_RESP) {
3360 *size = DESC_PKT_HDRLEN_AT_WRITE_RESP + IEEE1394_QUADLET;
3361 } else if (tcode == IEEE1394_TCODE_READ_QUADLET_RESP) {
3362 *size = DESC_PKT_HDRLEN_AT_READQUAD_RESP + IEEE1394_QUADLET;
3363 } else if (tcode == IEEE1394_TCODE_READ_BLOCK_RESP) {
3364 quadlet = hci1394_q_ar_get32(q_handle, &addr[3]);
3365 data_length = HCI1394_DESC_DATALEN_GET(quadlet);
3366 /*
3367 * response size is in quadlets, therefore we need to
3368 * make sure we count in the padding when figuring out
3369 * the size used up for this response
3370 */
3371 *size = DESC_PKT_HDRLEN_AT_READBLOCK_RESP +
3372 HCI1394_ALIGN_QUAD(data_length) + IEEE1394_QUADLET;
3373 } else if (tcode == IEEE1394_TCODE_LOCK_RESP) {
3374 quadlet = hci1394_q_ar_get32(q_handle, &addr[3]);
3375 data_length = HCI1394_DESC_DATALEN_GET(quadlet);
3376 /*
3377 * response size is in quadlets, therefore we need to
3378 * make sure we count in the padding when figuring out
3379 * the size used up for this response
3380 */
3381 *size = DESC_PKT_HDRLEN_AT_LOCK_RESP +
3382 HCI1394_ALIGN_QUAD(data_length) + IEEE1394_QUADLET;
3383 } else {
3384 TNF_PROBE_1(hci1394_async_arresp_size_tcode_err,
3385 HCI1394_TNF_HAL_ERROR,
3386 "unknown ARRESP received", tnf_uint, arresp_tcode, tcode);
3387 TNF_PROBE_0_DEBUG(hci1394_get_arresp_size_exit,
3388 HCI1394_TNF_HAL_STACK, "");
3389 return (DDI_FAILURE);
3390 }
3391
3392 TNF_PROBE_0_DEBUG(hci1394_get_arresp_size_exit,
3393 HCI1394_TNF_HAL_STACK, "");
3394
3395 return (DDI_SUCCESS);
3396 }
3397
3398
3399 /*
3400 * hci1394_async_pending_list_flush()
3401 * Flush out the ATREQ pending list. All commands still on the ATREQ pending
3402 * list are considered to be completed due to a bus reset. The ATREQ and
3403 * ARRESP Q's should be flushed before the pending Q is flushed. The ATREQ
3404 * could have more ACK pendings and the ARRESP could have valid responses to
3405 * pended requests.
3406 */
3407 void
hci1394_async_pending_list_flush(hci1394_async_handle_t async_handle)3408 hci1394_async_pending_list_flush(hci1394_async_handle_t async_handle)
3409 {
3410 hci1394_tlist_node_t *node;
3411 hci1394_async_cmd_t *hcicmd;
3412
3413
3414 ASSERT(async_handle != NULL);
3415
3416 TNF_PROBE_0_DEBUG(hci1394_async_pending_list_flush_enter,
3417 HCI1394_TNF_HAL_STACK, "");
3418
3419 do {
3420 /*
3421 * get the first node on the pending list. This routine also
3422 * removes the node from the list.
3423 */
3424 hci1394_tlist_get(async_handle->as_pending_list, &node);
3425 if (node != NULL) {
3426 /* set the command state to completed */
3427 hcicmd = (hci1394_async_cmd_t *)node->tln_addr;
3428 hcicmd->ac_state = HCI1394_CMD_STATE_COMPLETED;
3429
3430 /*
3431 * Send the command up to the Services Layer with
3432 * completed due to the bus reset for status.
3433 */
3434 h1394_cmd_is_complete(
3435 async_handle->as_drvinfo->di_sl_private,
3436 hcicmd->ac_cmd, H1394_AT_REQ,
3437 H1394_CMD_EBUSRESET);
3438 }
3439 } while (node != NULL);
3440
3441 TNF_PROBE_0_DEBUG(hci1394_async_pending_list_flush_exit,
3442 HCI1394_TNF_HAL_STACK, "");
3443 }
3444
3445
3446 /*
3447 * hci1394_async_atreq_start()
3448 * Setup the command pointer for the first descriptor to be fetched and
3449 * then set the run bit. This routine will be called the first time
3450 * a descriptor is added to the Q.
3451 */
3452 static void
hci1394_async_atreq_start(void * async,uint32_t command_ptr)3453 hci1394_async_atreq_start(void *async, uint32_t command_ptr)
3454 {
3455 hci1394_async_handle_t async_handle;
3456 ASSERT(async != NULL);
3457 TNF_PROBE_0_DEBUG(hci1394_async_atreq_start_enter,
3458 HCI1394_TNF_HAL_STACK, "");
3459 async_handle = (hci1394_async_handle_t)async;
3460 hci1394_ohci_atreq_start(async_handle->as_ohci, command_ptr);
3461 TNF_PROBE_0_DEBUG(hci1394_async_atreq_start_exit,
3462 HCI1394_TNF_HAL_STACK, "");
3463 }
3464
3465
3466 /*
3467 * hci1394_async_atreq_wake()
3468 * Set the wake bit for the ATREQ DMA engine. This routine will be called
3469 * from the Q logic after placing a descriptor on the Q.
3470 */
3471 static void
hci1394_async_atreq_wake(void * async)3472 hci1394_async_atreq_wake(void *async)
3473 {
3474 hci1394_async_handle_t async_handle;
3475 ASSERT(async != NULL);
3476 TNF_PROBE_0_DEBUG(hci1394_async_atreq_wake_enter,
3477 HCI1394_TNF_HAL_STACK, "");
3478 async_handle = (hci1394_async_handle_t)async;
3479 hci1394_ohci_atreq_wake(async_handle->as_ohci);
3480 TNF_PROBE_0_DEBUG(hci1394_async_atreq_wake_exit,
3481 HCI1394_TNF_HAL_STACK, "");
3482 }
3483
3484
3485 /*
3486 * hci1394_async_atreq_reset()
3487 * Reset the atreq Q. The AT DMA engines must be stopped every bus reset.
3488 * They will restart when the next descriptor is added to the Q. We will stop
3489 * the DMA engine and then notify the Q logic that it has been stopped so it
3490 * knows to do a start next time it puts a descriptor on the Q.
3491 */
3492 void
hci1394_async_atreq_reset(hci1394_async_handle_t async_handle)3493 hci1394_async_atreq_reset(hci1394_async_handle_t async_handle)
3494 {
3495 ASSERT(async_handle != NULL);
3496 TNF_PROBE_0_DEBUG(hci1394_async_atreq_reset_enter,
3497 HCI1394_TNF_HAL_STACK, "");
3498 hci1394_ohci_atreq_stop(async_handle->as_ohci);
3499 hci1394_q_stop(async_handle->as_atreq_q);
3500 TNF_PROBE_0_DEBUG(hci1394_async_atreq_reset_exit,
3501 HCI1394_TNF_HAL_STACK, "");
3502 }
3503
3504
3505 /*
3506 * hci1394_async_atreq_flush()
3507 * Flush out the atreq Q. This routine is called during bus reset processing.
3508 * it should be called before arresp_flush() and pending_list_flush().
3509 */
3510 static void
hci1394_async_atreq_flush(hci1394_async_handle_t async_handle)3511 hci1394_async_atreq_flush(hci1394_async_handle_t async_handle)
3512 {
3513 boolean_t request_available;
3514 int status;
3515
3516 ASSERT(async_handle != NULL);
3517
3518 TNF_PROBE_0_DEBUG(hci1394_async_atreq_flush_enter,
3519 HCI1394_TNF_HAL_STACK, "");
3520
3521 /* Clear reqTxComplete interrupt */
3522 hci1394_ohci_intr_clear(async_handle->as_ohci, OHCI_INTR_REQ_TX_CMPLT);
3523
3524 /*
3525 * Processes all Q'd AT requests. If the request is pended, it is
3526 * considered complete relative the the atreq engine.
3527 * flush_pending_list() will finish up the required processing for
3528 * pended requests.
3529 */
3530 do {
3531 /* Flush the atreq Q. Process all Q'd commands */
3532 status = hci1394_async_atreq_process(async_handle,
3533 B_TRUE, &request_available);
3534 if (status != DDI_SUCCESS) {
3535 TNF_PROBE_0(hci1394_async_atreq_process_fail,
3536 HCI1394_TNF_HAL_ERROR, "");
3537 }
3538 } while (request_available == B_TRUE);
3539
3540 TNF_PROBE_0_DEBUG(hci1394_async_atreq_flush_exit,
3541 HCI1394_TNF_HAL_STACK, "");
3542 }
3543
3544
3545 /*
3546 * hci1394_async_arresp_start()
3547 * Setup the command pointer for the first descriptor to be fetched and
3548 * then set the run bit. This routine will be called the first time
3549 * a descriptor is added to the Q.
3550 */
3551 static void
hci1394_async_arresp_start(void * async,uint32_t command_ptr)3552 hci1394_async_arresp_start(void *async, uint32_t command_ptr)
3553 {
3554 hci1394_async_handle_t async_handle;
3555 ASSERT(async != NULL);
3556 TNF_PROBE_0_DEBUG(hci1394_async_arresp_start_enter,
3557 HCI1394_TNF_HAL_STACK, "");
3558 async_handle = (hci1394_async_handle_t)async;
3559 hci1394_ohci_arresp_start(async_handle->as_ohci, command_ptr);
3560 TNF_PROBE_0_DEBUG(hci1394_async_arresp_start_exit,
3561 HCI1394_TNF_HAL_STACK, "");
3562 }
3563
3564
3565 /*
3566 * hci1394_async_arresp_wake()
3567 * Set the wake bit for the ARRESP DMA engine. This routine will be called
3568 * from the Q logic after placing a descriptor on the Q.
3569 */
3570 static void
hci1394_async_arresp_wake(void * async)3571 hci1394_async_arresp_wake(void *async)
3572 {
3573 hci1394_async_handle_t async_handle;
3574 ASSERT(async != NULL);
3575 TNF_PROBE_0_DEBUG(hci1394_async_arresp_wake_enter,
3576 HCI1394_TNF_HAL_STACK, "");
3577 async_handle = (hci1394_async_handle_t)async;
3578 hci1394_ohci_arresp_wake(async_handle->as_ohci);
3579 TNF_PROBE_0_DEBUG(hci1394_async_arresp_wake_exit,
3580 HCI1394_TNF_HAL_STACK, "");
3581 }
3582
3583
3584 /*
3585 * hci1394_async_arresp_flush()
3586 * Flush out the arresp Q. This routine is called during bus reset
3587 * processing. This should be called before pending_list_flush(). All
3588 * receive responses will be processed normally. The tlabels should
3589 * not be reset until after the ARRESP Q has been flushed. Otherwise
3590 * we would reject valid responses.
3591 */
3592 static void
hci1394_async_arresp_flush(hci1394_async_handle_t async_handle)3593 hci1394_async_arresp_flush(hci1394_async_handle_t async_handle)
3594 {
3595 boolean_t response_available;
3596 int status;
3597
3598
3599 ASSERT(async_handle != NULL);
3600
3601 TNF_PROBE_0_DEBUG(hci1394_async_arresp_flush_enter,
3602 HCI1394_TNF_HAL_STACK, "");
3603
3604 /* Clear reqTxComplete interrupt */
3605 hci1394_ohci_intr_clear(async_handle->as_ohci, OHCI_INTR_RSPKT);
3606
3607 do {
3608 /* Flush the arresp Q. Process all received commands */
3609 status = hci1394_async_arresp_process(async_handle,
3610 &response_available);
3611 if (status != DDI_SUCCESS) {
3612 TNF_PROBE_0(hci1394_async_arresp_process_fail,
3613 HCI1394_TNF_HAL_ERROR, "");
3614 }
3615 } while (response_available == B_TRUE);
3616
3617 TNF_PROBE_0_DEBUG(hci1394_async_arresp_flush_enter,
3618 HCI1394_TNF_HAL_STACK, "");
3619 }
3620
3621
3622 /*
3623 * hci1394_async_arreq_start()
3624 * Setup the command pointer for the first descriptor to be fetched and
3625 * then set the run bit. This routine will be called the first time
3626 * a descriptor is added to the Q.
3627 */
3628 static void
hci1394_async_arreq_start(void * async,uint32_t command_ptr)3629 hci1394_async_arreq_start(void *async, uint32_t command_ptr)
3630 {
3631 hci1394_async_handle_t async_handle;
3632 ASSERT(async != NULL);
3633 TNF_PROBE_0_DEBUG(hci1394_async_arreq_start_enter,
3634 HCI1394_TNF_HAL_STACK, "");
3635 async_handle = (hci1394_async_handle_t)async;
3636 hci1394_ohci_arreq_start(async_handle->as_ohci, command_ptr);
3637 TNF_PROBE_0_DEBUG(hci1394_async_arreq_start_exit,
3638 HCI1394_TNF_HAL_STACK, "");
3639 }
3640
3641
3642 /*
3643 * hci1394_async_arreq_wake()
3644 * Set the wake bit for the ARREQ DMA engine. This routine will be called
3645 * from the Q logic after placing a descriptor on the Q.
3646 */
3647 static void
hci1394_async_arreq_wake(void * async)3648 hci1394_async_arreq_wake(void *async)
3649 {
3650 hci1394_async_handle_t async_handle;
3651 ASSERT(async != NULL);
3652 TNF_PROBE_0_DEBUG(hci1394_async_arreq_wake_enter,
3653 HCI1394_TNF_HAL_STACK, "");
3654 async_handle = (hci1394_async_handle_t)async;
3655 hci1394_ohci_arreq_wake(async_handle->as_ohci);
3656 TNF_PROBE_0_DEBUG(hci1394_async_arreq_wake_exit,
3657 HCI1394_TNF_HAL_STACK, "");
3658 }
3659
3660
3661 /*
3662 * hci1394_async_arreq_flush()
3663 * Flush the ARREQ Q. This will flush up to the bus reset token in the
3664 * ARREQ. There is no order dependency for when routine should get called
3665 * (relative to the other Q flushing routines)
3666 */
3667 static void
hci1394_async_arreq_flush(hci1394_async_handle_t async_handle)3668 hci1394_async_arreq_flush(hci1394_async_handle_t async_handle)
3669 {
3670 boolean_t request_available;
3671 int status;
3672
3673
3674 ASSERT(async_handle != NULL);
3675 TNF_PROBE_0_DEBUG(hci1394_async_arreq_flush_enter,
3676 HCI1394_TNF_HAL_STACK, "");
3677
3678 /*
3679 * If the last bus reset token we have seen in
3680 * hci1394_async_arreq_read_phy() matches the current generation, the
3681 * ARREQ is already flushed. We have nothing further to do here so
3682 * return. This can happen if we are processing ARREQ's and a bus reset
3683 * occurs. Since we are already in the ISR, we will see the token before
3684 * the bus reset handler gets to run.
3685 */
3686 if (async_handle->as_phy_reset == hci1394_ohci_current_busgen(
3687 async_handle->as_ohci)) {
3688 TNF_PROBE_0_DEBUG(hci1394_async_arreq_flush_exit,
3689 HCI1394_TNF_HAL_STACK, "");
3690 return;
3691 }
3692
3693 /*
3694 * set flag to tell hci1394_async_arreq_process() that we should not
3695 * pass ARREQ's up to the Services Layer. This will be set to B_FALSE
3696 * in hci1394_async_arreq_read_phy() when a bus reset token matching
3697 * the current generation is found.
3698 */
3699 async_handle->as_flushing_arreq = B_TRUE;
3700
3701 /*
3702 * Process all requests that have been received or until we find the
3703 * correct bus reset token.
3704 */
3705 do {
3706 status = hci1394_async_arreq_process(async_handle,
3707 &request_available);
3708 if (status != DDI_SUCCESS) {
3709 TNF_PROBE_0(hci1394_isr_arreq_pr_fail,
3710 HCI1394_TNF_HAL_ERROR, "");
3711 }
3712 } while ((request_available == B_TRUE) &&
3713 (async_handle->as_flushing_arreq == B_TRUE));
3714
3715 /*
3716 * Clear the asserted interrupt if there are no more ARREQ's to process.
3717 * We could have ARREQ's in the Q after the bus reset token since we
3718 * will set as_flushing_arreq to FALSE when we see the correct bus reset
3719 * token in hci1394_async_arreq_read_phy(). If there are more ARREQ's,
3720 * we will process them later after finishing the reset of bus reset
3721 * processing. That is why we will leave the interrupt asserted.
3722 */
3723 if (request_available == B_FALSE) {
3724 hci1394_ohci_intr_clear(async_handle->as_ohci, OHCI_INTR_RQPKT);
3725 }
3726
3727 TNF_PROBE_0_DEBUG(hci1394_async_arreq_flush_exit,
3728 HCI1394_TNF_HAL_STACK, "");
3729 }
3730
3731
3732 /*
3733 * hci1394_async_atresp_start()
3734 * Setup the command pointer for the first descriptor to be fetched and
3735 * then set the run bit. This routine will be called the first time
3736 * a descriptor is added to the Q.
3737 */
3738 static void
hci1394_async_atresp_start(void * async,uint32_t command_ptr)3739 hci1394_async_atresp_start(void *async, uint32_t command_ptr)
3740 {
3741 hci1394_async_handle_t async_handle;
3742 ASSERT(async != NULL);
3743 TNF_PROBE_0_DEBUG(hci1394_async_atresp_start_enter,
3744 HCI1394_TNF_HAL_STACK, "");
3745 async_handle = (hci1394_async_handle_t)async;
3746 hci1394_ohci_atresp_start(async_handle->as_ohci, command_ptr);
3747 TNF_PROBE_0_DEBUG(hci1394_async_atresp_start_exit,
3748 HCI1394_TNF_HAL_STACK, "");
3749 }
3750
3751
3752 /*
3753 * hci1394_async_atresp_wake()
3754 * Set the wake bit for the ATRESP DMA engine. This routine will be called
3755 * from the Q logic after placing a descriptor on the Q.
3756 */
3757 static void
hci1394_async_atresp_wake(void * async)3758 hci1394_async_atresp_wake(void *async)
3759 {
3760 hci1394_async_handle_t async_handle;
3761 ASSERT(async != NULL);
3762 TNF_PROBE_0_DEBUG(hci1394_async_atresp_wake_enter,
3763 HCI1394_TNF_HAL_STACK, "");
3764 async_handle = (hci1394_async_handle_t)async;
3765 hci1394_ohci_atresp_wake(async_handle->as_ohci);
3766 TNF_PROBE_0_DEBUG(hci1394_async_atresp_wake_exit,
3767 HCI1394_TNF_HAL_STACK, "");
3768 }
3769
3770
3771 /*
3772 * hci1394_async_atresp_reset()
3773 * Reset the atresp Q. The AT DMA engines must be stopped every bus reset.
3774 * They will restart when the next descriptor is added to the Q. We will stop
3775 * the DMA engine and then notify the Q logic that it has been stopped so it
3776 * knows to do a start next time it puts a descriptor on the Q.
3777 */
3778 void
hci1394_async_atresp_reset(hci1394_async_handle_t async_handle)3779 hci1394_async_atresp_reset(hci1394_async_handle_t async_handle)
3780 {
3781 ASSERT(async_handle != NULL);
3782 TNF_PROBE_0_DEBUG(hci1394_async_atresp_reset_enter,
3783 HCI1394_TNF_HAL_STACK, "");
3784 hci1394_ohci_atresp_stop(async_handle->as_ohci);
3785 hci1394_q_stop(async_handle->as_atresp_q);
3786 TNF_PROBE_0_DEBUG(hci1394_async_atresp_reset_exit,
3787 HCI1394_TNF_HAL_STACK, "");
3788 }
3789
3790
3791 /*
3792 * hci1394_async_atresp_flush()
3793 * Flush all commands out of the atresp Q. This routine will be called
3794 * during bus reset processing. There is no order dependency for when
3795 * routine should get called (relative to the other Q flushing routines)
3796 */
3797 static void
hci1394_async_atresp_flush(hci1394_async_handle_t async_handle)3798 hci1394_async_atresp_flush(hci1394_async_handle_t async_handle)
3799 {
3800 boolean_t response_available;
3801 int status;
3802
3803 ASSERT(async_handle != NULL);
3804
3805 TNF_PROBE_0_DEBUG(hci1394_async_atresp_flush_enter,
3806 HCI1394_TNF_HAL_STACK, "");
3807
3808 /* Clear respTxComplete interrupt */
3809 hci1394_ohci_intr_clear(async_handle->as_ohci, OHCI_INTR_RESP_TX_CMPLT);
3810
3811 /* Processes all AT responses */
3812 do {
3813 /* Flush the atresp Q. Process all Q'd commands */
3814 status = hci1394_async_atresp_process(async_handle,
3815 B_TRUE, &response_available);
3816 if (status != DDI_SUCCESS) {
3817 TNF_PROBE_0(hci1394_async_atresp_process_fail,
3818 HCI1394_TNF_HAL_ERROR, "");
3819 }
3820 } while (response_available == B_TRUE);
3821
3822 TNF_PROBE_0_DEBUG(hci1394_async_atresp_flush_exit,
3823 HCI1394_TNF_HAL_STACK, "");
3824 }
3825
3826 /*
3827 * hci1394_async_hcicmd_init()
3828 * Initialize the private HAL command structure. This should be called from
3829 * ATREQ and ARREQ routines.
3830 */
3831 static void
hci1394_async_hcicmd_init(hci1394_async_handle_t async_handle,cmd1394_cmd_t * cmd,h1394_cmd_priv_t * cmd_priv,hci1394_async_cmd_t ** hcicmd)3832 hci1394_async_hcicmd_init(hci1394_async_handle_t async_handle,
3833 cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv,
3834 hci1394_async_cmd_t **hcicmd)
3835 {
3836 *hcicmd = (hci1394_async_cmd_t *)cmd_priv->hal_overhead;
3837 (*hcicmd)->ac_cmd = cmd;
3838 (*hcicmd)->ac_priv = cmd_priv;
3839 (*hcicmd)->ac_async = async_handle;
3840 (*hcicmd)->ac_state = HCI1394_CMD_STATE_IN_PROGRESS;
3841 (*hcicmd)->ac_dest = 0;
3842 (*hcicmd)->ac_tlabel_alloc = B_TRUE;
3843 (*hcicmd)->ac_tlabel.tbi_tlabel = 0;
3844 (*hcicmd)->ac_tlabel.tbi_destination = 0;
3845 (*hcicmd)->ac_status = 0;
3846 (*hcicmd)->ac_qcmd.qc_timestamp = 0;
3847 (*hcicmd)->ac_qcmd.qc_arg = *hcicmd;
3848 (*hcicmd)->ac_qcmd.qc_generation = cmd_priv->bus_generation;
3849 (*hcicmd)->ac_mblk_alloc = B_FALSE;
3850 }
3851