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