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