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
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.
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]
23 * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
31 * These routines manipulate the 1394 asynchronous dma engines. This
32 * includes incoming and outgoing reads, writes, and locks and their
33 * associated responses.
38 #include <sys/modctl.h>
40 #include <sys/sunddi.h>
41 #include <sys/cmn_err.h>
43 #include <sys/types.h>
46 #include <sys/1394/h1394.h>
47 #include <sys/1394/adapters/hci1394.h>
51 * ASYNC_ARRESP_ACK_ERROR is or'd into the error status when we get an ACK error
52 * on an ARRESP. Since the 1394 response code overlaps with the OpenHCI ACK/EVT
53 * errors, we use this to distinguish between the errors in process_arresp().
55 #define ASYNC_ARRESP_ACK_ERROR 0x8000
57 /* Macro's to help extract 48-bit 1394 address into a uint64_t */
58 #define HCI1394_TO_ADDR_HI(data) (((uint64_t)((data) & 0xFFFF)) << 32)
59 #define HCI1394_TO_ADDR_LO(data) ((uint64_t)((data) & 0xFFFFFFFF))
62 * Macro to convert a byte stream into a big endian quadlet or octlet or back
63 * the other way. 1394 arithmetic lock operations are done on big endian
64 * quadlets or octlets. compare swaps and bit masks are done on a byte streams.
65 * All data is treated as byte streams over the bus. These macros will convert
66 * the data to a big endian "integer" on x86 plaforms if the operation is an
67 * arithmetic lock operation. It will do nothing if it is not on x86 or is not
68 * an arithmetic lock operation.
71 #define HCI1394_ARITH_LOCK_SWAP32(tcode, data) \
72 (((tcode) == CMD1394_LOCK_FETCH_ADD) || \
73 ((tcode) == CMD1394_LOCK_BOUNDED_ADD) || \
74 ((tcode) == CMD1394_LOCK_WRAP_ADD)) ? \
75 (ddi_swap32(data)) : (data)
76 #define HCI1394_ARITH_LOCK_SWAP64(tcode, data) \
77 (((tcode) == CMD1394_LOCK_FETCH_ADD) || \
78 ((tcode) == CMD1394_LOCK_BOUNDED_ADD) || \
79 ((tcode) == CMD1394_LOCK_WRAP_ADD)) ? \
80 (ddi_swap64(data)) : (data)
82 #define HCI1394_ARITH_LOCK_SWAP32(tcode, data) (data)
83 #define HCI1394_ARITH_LOCK_SWAP64(tcode, data) (data)
88 static int hci1394_async_arresp_read(hci1394_async_handle_t async_handle
,
89 hci1394_basic_pkt_t
*pkt
, uint_t
*tcode
, hci1394_async_cmd_t
**hcicmd
,
91 static int hci1394_async_arresp_size_get(uint_t tcode
, hci1394_q_handle_t q
,
92 uint32_t *addr
, uint_t
*size
);
94 static int hci1394_async_arreq_read(hci1394_async_handle_t async_handle
,
95 hci1394_basic_pkt_t
*pkt
, uint_t
*tcode
, hci1394_async_cmd_t
**hcicmd
,
97 static int hci1394_async_arreq_read_qrd(hci1394_async_handle_t async_handle
,
98 hci1394_basic_pkt_t
*pkt
, hci1394_async_cmd_t
*hcicmd
, uint_t
*size
);
99 static int hci1394_async_arreq_read_qwr(hci1394_async_handle_t async_handle
,
100 hci1394_basic_pkt_t
*pkt
, hci1394_async_cmd_t
*hcicmd
, uint_t
*size
);
101 static int hci1394_async_arreq_read_brd(hci1394_async_handle_t async_handle
,
102 hci1394_basic_pkt_t
*pkt
, hci1394_async_cmd_t
*hcicmd
, uint_t
*size
);
103 static int hci1394_async_arreq_read_bwr(hci1394_async_handle_t async_handle
,
104 hci1394_basic_pkt_t
*pkt
, hci1394_async_cmd_t
*hcicmd
, uint_t
*size
);
105 static int hci1394_async_arreq_read_lck(hci1394_async_handle_t async_handle
,
106 hci1394_basic_pkt_t
*pkt
, hci1394_async_cmd_t
*hcicmd
, uint_t
*size
);
107 static int hci1394_async_arreq_read_phy(hci1394_async_handle_t async_handle
,
108 hci1394_basic_pkt_t
*pkt
, hci1394_async_cmd_t
*hcicmd
, uint_t
*size
,
109 boolean_t
*bus_reset_token
);
111 static void hci1394_async_hcicmd_init(hci1394_async_handle_t async_handle
,
112 cmd1394_cmd_t
*cmd
, h1394_cmd_priv_t
*cmd_priv
,
113 hci1394_async_cmd_t
**hcicmd
);
115 static void hci1394_async_atreq_start(void *async
, uint32_t command_ptr
);
116 static void hci1394_async_arresp_start(void *async
, uint32_t command_ptr
);
117 static void hci1394_async_arreq_start(void *async
, uint32_t command_ptr
);
118 static void hci1394_async_atresp_start(void *async
, uint32_t command_ptr
);
120 static void hci1394_async_atreq_wake(void *async
);
121 static void hci1394_async_arresp_wake(void *async
);
122 static void hci1394_async_arreq_wake(void *async
);
123 static void hci1394_async_atresp_wake(void *async
);
125 static void hci1394_async_atreq_flush(hci1394_async_handle_t async_handle
);
126 static void hci1394_async_arresp_flush(hci1394_async_handle_t async_handle
);
127 static void hci1394_async_arreq_flush(hci1394_async_handle_t async_handle
);
128 static void hci1394_async_atresp_flush(hci1394_async_handle_t async_handle
);
129 static void hci1394_async_pending_list_flush(hci1394_async_handle_t
132 static void hci1394_async_pending_timeout(hci1394_tlist_node_t
*node
,
134 static uint_t
hci1394_async_timeout_calc(hci1394_async_handle_t async_handle
,
135 uint_t current_time
);
137 _NOTE(SCHEME_PROTECTS_DATA("unique", msgb
))
140 * hci1394_async_init()
141 * Initialize the async DMA engines and state. We init the tlabels; ATREQ
142 * pending Q; and ATREQ, ARRESP, ARREQ, and ATRESP Q's. init() returns a
143 * handle to be used in rest of the functions.
146 hci1394_async_init(hci1394_drvinfo_t
*drvinfo
,
147 hci1394_ohci_handle_t ohci_handle
, hci1394_csr_handle_t csr_handle
,
148 hci1394_async_handle_t
*async_handle
)
150 hci1394_tlist_timer_t timer_info
;
151 hci1394_q_info_t qinfo
;
152 hci1394_async_t
*async
;
156 ASSERT(drvinfo
!= NULL
);
157 ASSERT(ohci_handle
!= NULL
);
158 ASSERT(csr_handle
!= NULL
);
159 ASSERT(async_handle
!= NULL
);
161 /* alloc the space to keep track of the list */
162 async
= kmem_alloc(sizeof (hci1394_async_t
), KM_SLEEP
);
164 /* copy in parms to our local state */
165 async
->as_drvinfo
= drvinfo
;
166 async
->as_ohci
= ohci_handle
;
167 async
->as_csr
= csr_handle
;
168 async
->as_flushing_arreq
= B_FALSE
;
169 async
->as_phy_reset
= 0xFFFFFFFF;
170 mutex_init(&async
->as_atomic_lookup
, NULL
, MUTEX_DRIVER
,
171 drvinfo
->di_iblock_cookie
);
174 * Initialize the tlabels. Reclaim a bad tlabel after the split timeout
175 * has gone by. This time is in reference to the point the transaction
176 * has been marked as bad. Therefore the tlabel will be reclaimed at
177 * twice the split_timeout. (i.e. if the split timeout was set to 100mS
178 * and the transaction has timed out, 100mS has already gone by. We need
179 * to wait for 100mS more before we can reuse the tlabel. Therefore, the
180 * reclaim time is split_timeout and not split_timeout * 2. The split
181 * timeout is stored as the number of bus cycles. We need to convert
182 * this to nS since the reclaim time is passed as nS.
184 hci1394_tlabel_init(drvinfo
, OHCI_BUS_CYCLE_TO_nS(
185 hci1394_csr_split_timeout_get(csr_handle
)), &async
->as_tlabel
);
188 * Initialize ATREQ pending list. A pended ATREQ will be timed out after
189 * "split_timeout" has gone by. split timeout is in bus cycles so we
190 * need to convert that to nS for the tlist timer info. We will set the
191 * timer resolution to 1/2 of the timeout so that we will have a worst
192 * case timeout of split timeout + (1/2 * split timeout). See
193 * hci1394_tlist.h for more information about this.
195 timer_info
.tlt_timeout
=
196 OHCI_BUS_CYCLE_TO_nS(hci1394_csr_split_timeout_get(csr_handle
));
197 timer_info
.tlt_timer_resolution
= timer_info
.tlt_timeout
/ 2;
198 timer_info
.tlt_callback
= hci1394_async_pending_timeout
;
199 timer_info
.tlt_callback_arg
= async
;
200 hci1394_tlist_init(drvinfo
, &timer_info
, &async
->as_pending_list
);
202 /* Initialize ATREQ Q */
203 qinfo
.qi_desc_size
= ASYNC_ATREQ_DESC_SIZE
;
204 qinfo
.qi_data_size
= ASYNC_ATREQ_DATA_SIZE
;
205 qinfo
.qi_mode
= HCI1394_ATQ
;
206 qinfo
.qi_start
= hci1394_async_atreq_start
;
207 qinfo
.qi_wake
= hci1394_async_atreq_wake
;
208 qinfo
.qi_callback_arg
= async
;
209 status
= hci1394_q_init(drvinfo
, async
->as_ohci
, &qinfo
,
211 if (status
!= DDI_SUCCESS
) {
212 mutex_destroy(&async
->as_atomic_lookup
);
213 hci1394_tlist_fini(&async
->as_pending_list
);
214 hci1394_tlabel_fini(&async
->as_tlabel
);
215 kmem_free(async
, sizeof (hci1394_async_t
));
216 *async_handle
= NULL
;
217 return (DDI_FAILURE
);
220 /* Initialize ARRESP Q */
221 qinfo
.qi_desc_size
= ASYNC_ARRESP_DESC_SIZE
;
222 qinfo
.qi_data_size
= ASYNC_ARRESP_DATA_SIZE
;
223 qinfo
.qi_mode
= HCI1394_ARQ
;
224 qinfo
.qi_start
= hci1394_async_arresp_start
;
225 qinfo
.qi_wake
= hci1394_async_arresp_wake
;
226 qinfo
.qi_callback_arg
= async
;
227 status
= hci1394_q_init(drvinfo
, async
->as_ohci
, &qinfo
,
228 &async
->as_arresp_q
);
229 if (status
!= DDI_SUCCESS
) {
230 mutex_destroy(&async
->as_atomic_lookup
);
231 hci1394_tlist_fini(&async
->as_pending_list
);
232 hci1394_tlabel_fini(&async
->as_tlabel
);
233 hci1394_q_fini(&async
->as_atreq_q
);
234 kmem_free(async
, sizeof (hci1394_async_t
));
235 *async_handle
= NULL
;
236 return (DDI_FAILURE
);
239 /* Initialize ARREQ Q */
240 qinfo
.qi_desc_size
= ASYNC_ARREQ_DESC_SIZE
;
241 qinfo
.qi_data_size
= ASYNC_ARREQ_DATA_SIZE
;
242 qinfo
.qi_mode
= HCI1394_ARQ
;
243 qinfo
.qi_start
= hci1394_async_arreq_start
;
244 qinfo
.qi_wake
= hci1394_async_arreq_wake
;
245 qinfo
.qi_callback_arg
= async
;
246 status
= hci1394_q_init(drvinfo
, async
->as_ohci
, &qinfo
,
248 if (status
!= DDI_SUCCESS
) {
249 mutex_destroy(&async
->as_atomic_lookup
);
250 hci1394_tlist_fini(&async
->as_pending_list
);
251 hci1394_tlabel_fini(&async
->as_tlabel
);
252 hci1394_q_fini(&async
->as_atreq_q
);
253 hci1394_q_fini(&async
->as_arresp_q
);
254 kmem_free(async
, sizeof (hci1394_async_t
));
255 *async_handle
= NULL
;
256 return (DDI_FAILURE
);
259 /* Initialize ATRESP Q */
260 qinfo
.qi_desc_size
= ASYNC_ATRESP_DESC_SIZE
;
261 qinfo
.qi_data_size
= ASYNC_ATRESP_DATA_SIZE
;
262 qinfo
.qi_mode
= HCI1394_ATQ
;
263 qinfo
.qi_start
= hci1394_async_atresp_start
;
264 qinfo
.qi_wake
= hci1394_async_atresp_wake
;
265 qinfo
.qi_callback_arg
= async
;
266 status
= hci1394_q_init(drvinfo
, async
->as_ohci
, &qinfo
,
267 &async
->as_atresp_q
);
268 if (status
!= DDI_SUCCESS
) {
269 mutex_destroy(&async
->as_atomic_lookup
);
270 hci1394_tlist_fini(&async
->as_pending_list
);
271 hci1394_tlabel_fini(&async
->as_tlabel
);
272 hci1394_q_fini(&async
->as_atreq_q
);
273 hci1394_q_fini(&async
->as_arresp_q
);
274 hci1394_q_fini(&async
->as_arreq_q
);
275 kmem_free(async
, sizeof (hci1394_async_t
));
276 *async_handle
= NULL
;
277 return (DDI_FAILURE
);
280 *async_handle
= async
;
282 return (DDI_SUCCESS
);
287 * hci1394_async_fini()
288 * Free's up the space allocated in init(). Notice that a pointer to the
289 * handle is used for the parameter. fini() will set your handle to NULL
293 hci1394_async_fini(hci1394_async_handle_t
*async_handle
)
295 hci1394_async_t
*async
;
298 ASSERT(async_handle
!= NULL
);
300 async
= (hci1394_async_t
*)*async_handle
;
302 mutex_destroy(&async
->as_atomic_lookup
);
303 hci1394_tlabel_fini(&async
->as_tlabel
);
304 hci1394_tlist_fini(&async
->as_pending_list
);
305 hci1394_q_fini(&async
->as_atreq_q
);
306 hci1394_q_fini(&async
->as_atresp_q
);
307 hci1394_q_fini(&async
->as_arreq_q
);
308 hci1394_q_fini(&async
->as_arresp_q
);
310 kmem_free(async
, sizeof (hci1394_async_t
));
312 /* set handle to null. This helps catch bugs. */
313 *async_handle
= NULL
;
318 * hci1394_async_suspend()
319 * The system is getting ready to be suspended. Make sure that all of
320 * the Q's are clean and that the there are no scheduled timeouts in the
324 hci1394_async_suspend(hci1394_async_handle_t async_handle
)
326 ASSERT(async_handle
!= NULL
);
328 /* Flush out async DMA Q's */
329 hci1394_async_flush(async_handle
);
331 /* Cancel any scheduled pending timeouts */
332 hci1394_tlist_timeout_cancel(async_handle
->as_pending_list
);
337 * hci1394_async_resume()
338 * Re-setup the DMA Q's during a resume after a successful suspend. The
339 * tlabels will be re-initialized during the bus reset and the pending Q will
340 * be flushed during the suspend.
343 hci1394_async_resume(hci1394_async_handle_t async_handle
)
345 ASSERT(async_handle
!= NULL
);
347 hci1394_q_resume(async_handle
->as_atreq_q
);
348 hci1394_q_resume(async_handle
->as_atresp_q
);
349 hci1394_q_resume(async_handle
->as_arreq_q
);
350 hci1394_q_resume(async_handle
->as_arresp_q
);
352 return (DDI_SUCCESS
);
357 * hci1394_async_cmd_overhead()
358 * Return the size of the HAL private area to attach to every alloced 1394
359 * framework command. This allows us to track command state without having
360 * to alloc memory every time a command comes down the pipe.
363 hci1394_async_cmd_overhead()
365 return (sizeof (hci1394_async_cmd_t
));
370 * hci1394_async_flush()
371 * Flush out the Async Q's and the ATREQ pending list. This is called every
372 * bus reset so that we're sync'd up with the HW and when shutting down or
373 * suspending to make sure we cleanup after all commands.
376 hci1394_async_flush(hci1394_async_handle_t async_handle
)
378 ASSERT(async_handle
!= NULL
);
380 hci1394_async_atreq_flush(async_handle
);
381 hci1394_async_arresp_flush(async_handle
);
382 hci1394_async_pending_list_flush(async_handle
);
383 hci1394_async_arreq_flush(async_handle
);
384 hci1394_async_atresp_flush(async_handle
);
385 hci1394_tlabel_reset(async_handle
->as_tlabel
);
390 * hci1394_async_pending_timeout_update()
391 * Update the timeout for the pending list. This updates both the pending
392 * list timeout and time we wait to reclaim bad tlabels. timeout is the
393 * time in nS so we do not have to do any conversions. This routine will be
394 * called when the CSR split timeout registers are updated.
397 hci1394_async_pending_timeout_update(hci1394_async_handle_t async_handle
,
400 ASSERT(async_handle
!= NULL
);
401 hci1394_tlist_timeout_update(async_handle
->as_pending_list
, timeout
);
402 hci1394_tlabel_set_reclaim_time(async_handle
->as_tlabel
, timeout
);
407 * hci1394_async_atreq_process()
408 * Process an atreq, if one has completed. This is called during interrupt
409 * processing and will process a completed atreq. It returns status if an
410 * atreq was processed so that the ISR knows that it needs to be called
411 * again to see if another ATREQ has completed. flush_q set to B_TRUE tells
412 * this routine to process all commands regardless of their completion
413 * status. This is used during bus reset processing to remove all commands
416 * There are a few race conditions that we have to watch for in atreq/arresp.
417 * They all have to do with pended responses so they are not applicable in
418 * the ARREQ/ATRESP engine (since ATRESP's can't be pended).
420 * Since the race conditions only exist for pended responses, we will only
421 * talk about that sequence here. We're also going to simplify the discussion
422 * so what the code does, so it won't exactly match what we say (e.g. we
423 * don't always setup a timeout for every single command, etc.)
425 * After Q'ing up an ATREQ, we will process the result of that command in
426 * one of a couple different paths. A normal condition would be that we Q up
427 * a command, we get an ATREQ complete interrupt and look at the ATREQ
428 * result. In the case it has been pended, we setup a timeout to wait for the
429 * response. If we receive the response before the timeout, the command is
430 * done and we send the response up the chain, if we do not, the command is
431 * done and we send a timeout notification up the chain.
433 * The first race condition is when we get the timeout at the same time as
434 * the response. At first glance a mutex around the command state would
435 * solve this problem. But on a multi-processor machine, we may have the
436 * ARRESP interrupt handler(ISR) running on one processor and the timeout on
437 * another. This means that the command state could change between two
438 * reads while in the ISR. This means we need to have a little more complex
439 * logic around changing the command state and have to be careful how and
442 * The second race condition is that we could see the ARRESP before we
443 * process the ATREQ. We could be processing a few ARRESP from previous
444 * ATREQ's when the ATREQ completes and then the ARRESP comes in. Since we
445 * already are in the interrupt handler, the ATREQ complete will not preempt
448 * We will never see a race condition between the ATREQ interrupt for a
449 * command and the pending timeout since the command is not being timed until
450 * this routine is run for that command.
453 hci1394_async_atreq_process(hci1394_async_handle_t async_handle
,
454 boolean_t flush_q
, boolean_t
*request_available
)
456 hci1394_async_cmd_t
*hcicmd
;
457 hci1394_q_cmd_t
*qcmd
;
461 ASSERT(async_handle
!= NULL
);
462 ASSERT(request_available
!= NULL
);
465 * Get the next ATREQ that has completed (if one has). Space is free'd
466 * up in atreq_q and atreq_data_q as part of this function call.
468 hci1394_q_at_next(async_handle
->as_atreq_q
, flush_q
, &qcmd
);
471 * See if there were anymore requests on ATREQ Q. A NULL means there
472 * were no completed commands left on the Q
475 *request_available
= B_FALSE
;
476 return (DDI_SUCCESS
);
479 /* There is a completed ATREQ, setup the HAL command pointer */
480 *request_available
= B_TRUE
;
481 hcicmd
= (hci1394_async_cmd_t
*)qcmd
->qc_arg
;
483 /* save away the command completed timestamp for the services layer */
484 hcicmd
->ac_priv
->ack_tstamp
= qcmd
->qc_timestamp
;
487 * Make sure this command has not already been processed. This command
488 * may have already received a response. If the ACK was not an ACK
489 * pending, we have a HW error (i.e. The target HW sent a response to a
490 * non-pended request). There is a race condition where the software
491 * will see and complete a response before processing it's ACK Pending.
492 * This can only happen for ACK pendings. We have seen this race
493 * condition and response to a non-pended request during real-world
496 if (hcicmd
->ac_state
!= HCI1394_CMD_STATE_IN_PROGRESS
) {
498 * we already processed the ARRESP in arresp_process(), it
499 * better have been ACK pended. Otherwise the target device
500 * performed an illegal action.
502 if (qcmd
->qc_status
== OHCI_ACK_PENDING
) {
504 * Tell source that their command has completed. We're
505 * done with this command.
506 * NOTE: We use ac_status which was set in
509 h1394_cmd_is_complete(
510 async_handle
->as_drvinfo
->di_sl_private
,
511 hcicmd
->ac_cmd
, H1394_AT_REQ
,
513 return (DDI_SUCCESS
);
515 * This is a HW error. Process the ACK like we never saw the
516 * response. We will do this below.
523 * if we got an ack pending, add it to the pending list and leave. We
524 * will either get an ARRESP or the pending list will timeout the
527 if (qcmd
->qc_status
== OHCI_ACK_PENDING
) {
528 hcicmd
->ac_state
= HCI1394_CMD_STATE_PENDING
;
529 /* Add this command to the pending list */
530 hcicmd
->ac_plist_node
.tln_addr
= hcicmd
;
531 hci1394_tlist_add(async_handle
->as_pending_list
,
532 &hcicmd
->ac_plist_node
);
533 return (DDI_SUCCESS
);
537 * setup our return command status based on the ACK from the HW. See the
538 * OpenHCI 1.0 spec (table 3.2 on pg. 18) for more information about
541 switch (qcmd
->qc_status
) {
542 case OHCI_ACK_COMPLETE
:
543 cmd_status
= H1394_CMD_SUCCESS
;
547 * we can get a nostatus during a bus reset (i.e. we shutdown the AT
548 * engine before it flushed all the commands)
550 case OHCI_EVT_FLUSHED
:
551 case OHCI_EVT_NO_STATUS
:
552 cmd_status
= H1394_CMD_EBUSRESET
;
555 case OHCI_EVT_MISSING_ACK
:
556 case OHCI_EVT_TIMEOUT
:
557 cmd_status
= H1394_CMD_ETIMEOUT
;
560 case OHCI_ACK_BUSY_X
:
561 case OHCI_ACK_BUSY_A
:
562 case OHCI_ACK_BUSY_B
:
563 cmd_status
= H1394_CMD_EDEVICE_BUSY
;
567 cmd_status
= H1394_CMD_EDEVICE_POWERUP
;
570 case OHCI_ACK_DATA_ERROR
:
571 cmd_status
= H1394_CMD_EDATA_ERROR
;
574 case OHCI_ACK_TYPE_ERROR
:
575 cmd_status
= H1394_CMD_ETYPE_ERROR
;
578 case OHCI_ACK_CONFLICT_ERROR
:
579 cmd_status
= H1394_CMD_ERSRC_CONFLICT
;
582 case OHCI_ACK_ADDRESS_ERROR
:
583 cmd_status
= H1394_CMD_EADDR_ERROR
;
586 case OHCI_EVT_UNDERRUN
:
587 case OHCI_EVT_DATA_READ
:
588 case OHCI_EVT_TCODE_ERR
:
589 case OHCI_EVT_DESCRIPTOR_READ
:
590 case OHCI_EVT_UNKNOWN
:
592 cmd_status
= H1394_CMD_EUNKNOWN_ERROR
;
597 * Free the tlabel that was used for this transfer. We will not try and
598 * free the tlabel in the case that we already received a response or if
599 * we did not allocate one (PHY packet). If we already received a
600 * response, the tlabel would have been free'd in
601 * hci1394_async_arresp_process().
603 if ((hcicmd
->ac_state
== HCI1394_CMD_STATE_IN_PROGRESS
) &&
604 (hcicmd
->ac_tlabel_alloc
== B_TRUE
)) {
605 hci1394_tlabel_free(async_handle
->as_tlabel
,
610 * if we got anything other than and ACK pending, we are done w/ this
613 hcicmd
->ac_state
= HCI1394_CMD_STATE_COMPLETED
;
615 /* tell the services layer that the command has completed */
616 h1394_cmd_is_complete(async_handle
->as_drvinfo
->di_sl_private
,
617 hcicmd
->ac_cmd
, H1394_AT_REQ
, cmd_status
);
619 return (DDI_SUCCESS
);
624 * hci1394_async_arresp_process()
625 * Process an arresp, if one has completed. This is called during interrupt
626 * processing and will process a completed arresp. It returns status if an
627 * arresp was processed so that the ISR knows that it needs to be called
628 * again to see if another ARRESP has completed.
631 hci1394_async_arresp_process(hci1394_async_handle_t async_handle
,
632 boolean_t
*response_available
)
634 hci1394_async_cmd_t
*hcicmd
;
642 ASSERT(async_handle
!= NULL
);
643 ASSERT(response_available
!= NULL
);
646 * See if there were any responses on ARRESP Q. A NULL means there
647 * were no responses on the Q. This call does NOT free up space. We
648 * need to do that later after we figure out how much space the
651 hci1394_q_ar_next(async_handle
->as_arresp_q
, &addr
);
653 *response_available
= B_FALSE
;
654 return (DDI_SUCCESS
);
658 * We got a response. Lock out pending timeout callback from marking
661 *response_available
= B_TRUE
;
662 mutex_enter(&async_handle
->as_atomic_lookup
);
665 * Read in the response into the 1394 framework command. We could get a
666 * NULL for a command if we got a response with an error (i.e. tlabel
667 * that didn't match a request) This would be a successful read but with
668 * a NULL hcicmd returned. If we ever get a DDI_FAILURE, we will
671 status
= hci1394_async_arresp_read(async_handle
,
672 (hci1394_basic_pkt_t
*)addr
, &tcode
, &hcicmd
, &size
);
673 if (status
!= DDI_SUCCESS
) {
674 mutex_exit(&async_handle
->as_atomic_lookup
);
675 h1394_error_detected(async_handle
->as_drvinfo
->di_sl_private
,
676 H1394_SELF_INITIATED_SHUTDOWN
, NULL
);
677 cmn_err(CE_WARN
, "hci1394(%d): driver shutdown: "
678 "unrecoverable error interrupt detected",
679 async_handle
->as_drvinfo
->di_instance
);
680 hci1394_shutdown(async_handle
->as_drvinfo
->di_dip
);
681 return (DDI_FAILURE
);
684 /* Free up the arresp Q space, we are done with the data */
685 hci1394_q_ar_free(async_handle
->as_arresp_q
, size
);
688 * if we did not get a valid command response (i.e. we got a bad tlabel
689 * or something like that) we don't have anything else to do. We will
690 * say that we processed a response and will return successfully. We
691 * still may have other responses on the Q.
693 if (hcicmd
== NULL
) {
694 mutex_exit(&async_handle
->as_atomic_lookup
);
695 return (DDI_SUCCESS
);
699 * Make sure this is in the pending list. There is a small chance that
700 * we will see the response before we see the ACK PENDING. If it is the
701 * expected case, it is in the pending list. We will remove it since
702 * we are done with the command.
704 * NOTE: there is a race condition here with the pending timeout. Look
705 * at the comments before hci1394_async_atreq_process() for more info.
707 if (hcicmd
->ac_state
== HCI1394_CMD_STATE_PENDING
) {
708 /* remove this transfer from our the pending list */
709 status
= hci1394_tlist_delete(async_handle
->as_pending_list
,
710 &hcicmd
->ac_plist_node
);
711 if (status
!= DDI_SUCCESS
) {
712 mutex_exit(&async_handle
->as_atomic_lookup
);
713 return (DDI_SUCCESS
);
717 /* allow pending timeout callback to mark tlabel as bad */
718 mutex_exit(&async_handle
->as_atomic_lookup
);
721 * We got a valid response that we were able to read in. Free the tlabel
722 * that was used for this transfer.
724 hci1394_tlabel_free(async_handle
->as_tlabel
, &hcicmd
->ac_tlabel
);
727 * Setup our return command status based on the RESP or ACK or SW error.
728 * See the IEEE1394-1995 spec (6.2.4.10 on pg. 159) for more information
729 * on response codes. See the OpenHCI 1.0 spec (table 3.2 on pg. 18) for
730 * more information about ACK/EVT's. ac_status could have an IEEE1394
731 * response in it, a 1394 EVT/ACK, or a special cmd1394 error for a
732 * device error caught in SW (e.g. for a block read request that got a
733 * quadlet read response). We use a special mask to separate the
734 * ACK/EVT's from the responses (ASYNC_ARRESP_ACK_ERROR).
736 switch (hcicmd
->ac_status
) {
737 case IEEE1394_RESP_COMPLETE
:
738 cmd_status
= H1394_CMD_SUCCESS
;
740 case IEEE1394_RESP_DATA_ERROR
:
741 cmd_status
= H1394_CMD_EDATA_ERROR
;
743 case IEEE1394_RESP_TYPE_ERROR
:
744 cmd_status
= H1394_CMD_ETYPE_ERROR
;
746 case IEEE1394_RESP_CONFLICT_ERROR
:
747 cmd_status
= H1394_CMD_ERSRC_CONFLICT
;
749 case IEEE1394_RESP_ADDRESS_ERROR
:
750 cmd_status
= H1394_CMD_EADDR_ERROR
;
752 case H1394_CMD_EDEVICE_ERROR
:
753 cmd_status
= H1394_CMD_EDEVICE_ERROR
;
755 case OHCI_ACK_DATA_ERROR
| ASYNC_ARRESP_ACK_ERROR
:
756 cmd_status
= H1394_CMD_EDATA_ERROR
;
758 case OHCI_ACK_TYPE_ERROR
| ASYNC_ARRESP_ACK_ERROR
:
759 cmd_status
= H1394_CMD_ETYPE_ERROR
;
761 case OHCI_EVT_UNDERRUN
| ASYNC_ARRESP_ACK_ERROR
:
762 case OHCI_EVT_DATA_READ
| ASYNC_ARRESP_ACK_ERROR
:
763 case OHCI_EVT_TCODE_ERR
| ASYNC_ARRESP_ACK_ERROR
:
764 cmd_status
= H1394_CMD_EUNKNOWN_ERROR
;
767 cmd_status
= H1394_CMD_EUNKNOWN_ERROR
;
772 * if we have already processed the atreq and put it on the pending Q
773 * (normal case), tell the services layer it completed.
775 if (hcicmd
->ac_state
== HCI1394_CMD_STATE_PENDING
) {
776 /* Set state indicating that we are done with this cmd */
777 hcicmd
->ac_state
= HCI1394_CMD_STATE_COMPLETED
;
779 /* tell the services lyaer the command has completed */
780 h1394_cmd_is_complete(async_handle
->as_drvinfo
->di_sl_private
,
781 hcicmd
->ac_cmd
, H1394_AT_REQ
, cmd_status
);
784 * We have not seen the atreq status yet. We will call
785 * h1394_command_is_complete() in atreq_process() in case we did not get
786 * an ack pending (target HW error -> this is based on real world
790 /* Set state indicating that we are done with this cmd */
791 hcicmd
->ac_state
= HCI1394_CMD_STATE_COMPLETED
;
793 /* save away the status for atreq_process() */
794 hcicmd
->ac_status
= cmd_status
;
797 return (DDI_SUCCESS
);
802 * hci1394_async_arreq_process()
803 * Process an arreq, if one has arrived. This is called during interrupt
804 * processing and will process an arreq that has arrived. It returns status
805 * if an arreq was processed so that the ISR knows that it needs to be
806 * called again to see if another ARREQ has arrived.
809 hci1394_async_arreq_process(hci1394_async_handle_t async_handle
,
810 boolean_t
*request_available
)
812 hci1394_async_cmd_t
*hcicmd
;
819 ASSERT(async_handle
!= NULL
);
820 ASSERT(request_available
!= NULL
);
823 * See if there were any requests on ARREQ Q. A NULL means there
824 * were no requests on the Q. This call does NOT free up space. We
825 * need to do that later after we figure out how much space the
828 hci1394_q_ar_next(async_handle
->as_arreq_q
, &addr
);
830 *request_available
= B_FALSE
;
831 return (DDI_SUCCESS
);
835 * We got a request. Read the request into a 1394 framework command.
836 * We could get a NULL for a command if we got a request with an error
837 * (i.e. ARREQ ACK was not ack pending or ack complete). This would be a
838 * successful read but with a NULL hcicmd returned. If we ever get a
839 * DDI_FAILURE, we will shutdown.
841 *request_available
= B_TRUE
;
842 status
= hci1394_async_arreq_read(async_handle
,
843 (hci1394_basic_pkt_t
*)addr
, &tcode
, &hcicmd
, &size
);
844 if (status
!= DDI_SUCCESS
) {
845 h1394_error_detected(async_handle
->as_drvinfo
->di_sl_private
,
846 H1394_SELF_INITIATED_SHUTDOWN
, NULL
);
847 cmn_err(CE_WARN
, "hci1394(%d): driver shutdown: "
848 "unrecoverable error interrupt detected",
849 async_handle
->as_drvinfo
->di_instance
);
850 hci1394_shutdown(async_handle
->as_drvinfo
->di_dip
);
851 return (DDI_FAILURE
);
854 /* Free up the arreq Q space, we are done with the data */
855 hci1394_q_ar_free(async_handle
->as_arreq_q
, size
);
858 * if we did not get a valid request (i.e. The ARREQ had a bad ACK
859 * or something like that) we don't have anything else to do. We will
860 * say that we processed a request and will return successfully. We
861 * still may have other requests on the Q.
863 if (hcicmd
== NULL
) {
864 return (DDI_SUCCESS
);
868 * If as_flushing_arreq is set, we do not want to send any requests up
869 * to the Services Layer. We are flushing the ARREQ until we see a bus
870 * reset token that matches the current bus generation. Free up the
871 * alloc'd command and return success.
873 if (async_handle
->as_flushing_arreq
== B_TRUE
) {
874 hci1394_async_response_complete(async_handle
, hcicmd
->ac_cmd
,
876 return (DDI_SUCCESS
);
880 * We got a valid request that we were able to read in. Call into the
881 * services layer based on the type of request.
884 case IEEE1394_TCODE_READ_QUADLET
:
885 case IEEE1394_TCODE_READ_BLOCK
:
886 h1394_read_request(async_handle
->as_drvinfo
->di_sl_private
,
889 case IEEE1394_TCODE_WRITE_QUADLET
:
890 case IEEE1394_TCODE_WRITE_BLOCK
:
891 h1394_write_request(async_handle
->as_drvinfo
->di_sl_private
,
894 case IEEE1394_TCODE_LOCK
:
895 h1394_lock_request(async_handle
->as_drvinfo
->di_sl_private
,
898 case IEEE1394_TCODE_PHY
:
900 * OpenHCI only handles 1 PHY quadlet at a time. If a selfid
901 * packet was received with multiple quadlets, we will treat
902 * each quadlet as a separate call. We do not notify the
903 * services layer through the normal command interface, we will
904 * treat it like a command internally and then free up the
905 * command ourselves when we are done with it.
907 h1394_phy_packet(async_handle
->as_drvinfo
->di_sl_private
,
908 &hcicmd
->ac_cmd
->cmd_u
.q
.quadlet_data
, 1,
909 hcicmd
->ac_priv
->recv_tstamp
);
910 /* free alloc'd command */
911 hci1394_async_response_complete(async_handle
, hcicmd
->ac_cmd
,
915 /* free alloc'd command */
916 hci1394_async_response_complete(async_handle
, hcicmd
->ac_cmd
,
921 return (DDI_SUCCESS
);
926 * hci1394_async_atresp_process()
927 * Process an atresp, if one has completed. This is called during interrupt
928 * processing and will process a completed atresp. It returns status if an
929 * atresp was processed so that the ISR knows that it needs to be called
930 * again to see if another ATRESP has completed. flush_q set to B_TRUE tells
931 * this routine to process all commands regardless of their completion
932 * status. This is used during bus reset processing to remove all commands
936 hci1394_async_atresp_process(hci1394_async_handle_t async_handle
,
937 boolean_t flush_q
, boolean_t
*response_available
)
939 hci1394_async_cmd_t
*hcicmd
;
940 hci1394_q_cmd_t
*qcmd
;
944 ASSERT(async_handle
!= NULL
);
945 ASSERT(response_available
!= NULL
);
948 * Get the next ATRESP that has completed (if one has). Space is free'd
949 * up in atresp_q and atresp_data_q as part of this function call.
951 hci1394_q_at_next(async_handle
->as_atresp_q
, flush_q
, &qcmd
);
954 * See if there were anymore requests on ATRESP Q. A NULL means there
955 * were no completed commands left on the Q.
958 *response_available
= B_FALSE
;
959 return (DDI_SUCCESS
);
962 /* There is a completed ATRESP, setup the HAL command pointer */
963 *response_available
= B_TRUE
;
964 hcicmd
= (hci1394_async_cmd_t
*)qcmd
->qc_arg
;
966 /* save away the command completed timestamp for the services layer */
967 hcicmd
->ac_priv
->ack_tstamp
= qcmd
->qc_timestamp
;
970 * setup our return command status based on the ACK from the HW. See the
971 * OpenHCI 1.0 spec (table 3.2 on pg. 18) for more information about
974 switch (qcmd
->qc_status
) {
975 case OHCI_ACK_COMPLETE
:
976 cmd_status
= H1394_CMD_SUCCESS
;
980 * we can get a nostatus during a bus reset (i.e. we shutdown the AT
981 * engine before it flushed all the commands)
983 case OHCI_EVT_FLUSHED
:
984 case OHCI_EVT_NO_STATUS
:
985 cmd_status
= H1394_CMD_EBUSRESET
;
988 case OHCI_EVT_MISSING_ACK
:
989 case OHCI_EVT_TIMEOUT
:
990 cmd_status
= H1394_CMD_ETIMEOUT
;
993 case OHCI_ACK_BUSY_X
:
994 case OHCI_ACK_BUSY_A
:
995 case OHCI_ACK_BUSY_B
:
996 cmd_status
= H1394_CMD_EDEVICE_BUSY
;
1000 cmd_status
= H1394_CMD_EDEVICE_POWERUP
;
1003 case OHCI_ACK_DATA_ERROR
:
1004 cmd_status
= H1394_CMD_EDATA_ERROR
;
1007 case OHCI_ACK_TYPE_ERROR
:
1008 cmd_status
= H1394_CMD_ETYPE_ERROR
;
1011 case OHCI_ACK_CONFLICT_ERROR
:
1012 cmd_status
= H1394_CMD_ERSRC_CONFLICT
;
1015 case OHCI_ACK_ADDRESS_ERROR
:
1016 cmd_status
= H1394_CMD_EADDR_ERROR
;
1019 case OHCI_EVT_UNKNOWN
:
1020 cmd_status
= H1394_CMD_EUNKNOWN_ERROR
;
1023 case OHCI_EVT_UNDERRUN
:
1024 case OHCI_EVT_DATA_READ
:
1025 case OHCI_EVT_TCODE_ERR
:
1026 case OHCI_EVT_DESCRIPTOR_READ
:
1028 cmd_status
= H1394_CMD_EUNKNOWN_ERROR
;
1032 /* tell the services layer that the command has completed */
1033 h1394_cmd_is_complete(async_handle
->as_drvinfo
->di_sl_private
,
1034 hcicmd
->ac_cmd
, H1394_AT_RESP
, cmd_status
);
1036 return (DDI_SUCCESS
);
1041 * hci1394_async_arresp_read()
1042 * Read ARRESP in from memory into 1394 Framework command. We read the tcode
1043 * which tells us which kind of arresp the packet is, get the size of the
1044 * response, read in the sender, tlabel, and response code, and then
1045 * lookup the command based on the sender and tlabel. Once we get the command
1046 * (corresponding to the ATREQ), we will copy the rest of the response into
1049 * The only time this routine should return DDI_FAILURE is if it was unable
1050 * to maintain a good state in the ARRESP Q (i.e. an unknown response was
1051 * received and we can not cleanup after it.) If we detect a recoverable
1052 * error, and it doesn't make sense to pass the response up to the Services
1053 * Layer, we should return DDI_SUCCESS with hcicmd = NULL.
1056 hci1394_async_arresp_read(hci1394_async_handle_t async_handle
,
1057 hci1394_basic_pkt_t
*pkt
, uint_t
*tcode
, hci1394_async_cmd_t
**hcicmd
,
1060 hci1394_tlabel_info_t ac_tlabel
;
1061 h1394_cmd_priv_t
*cmd_priv
;
1063 uint32_t *status_addr
;
1072 ASSERT(async_handle
!= NULL
);
1073 ASSERT(pkt
!= NULL
);
1074 ASSERT(tcode
!= NULL
);
1075 ASSERT(hcicmd
!= NULL
);
1076 ASSERT(size
!= NULL
);
1078 /* read in the arresp tcode */
1079 quadlet
= hci1394_q_ar_get32(async_handle
->as_arresp_q
, &pkt
->q1
);
1080 *tcode
= HCI1394_DESC_TCODE_GET(quadlet
);
1082 /* Get the size of the arresp */
1083 status
= hci1394_async_arresp_size_get(*tcode
,
1084 async_handle
->as_arresp_q
, &pkt
->q1
, size
);
1085 if (status
!= DDI_SUCCESS
) {
1086 return (DDI_FAILURE
);
1089 /* Read in the tlabel, destination, and rcode (response code) */
1090 quadlet
= hci1394_q_ar_get32(async_handle
->as_arresp_q
, &pkt
->q1
);
1091 ac_tlabel
.tbi_tlabel
= HCI1394_DESC_TLABEL_GET(quadlet
);
1092 quadlet
= hci1394_q_ar_get32(async_handle
->as_arresp_q
, &pkt
->q2
);
1093 ac_tlabel
.tbi_destination
= HCI1394_DESC_DESTID_GET(quadlet
);
1094 rcode
= HCI1394_DESC_RCODE_GET(quadlet
);
1096 /* Lookup the ATREQ framework command this response goes with */
1097 hci1394_tlabel_lookup(async_handle
->as_tlabel
, &ac_tlabel
, &command
);
1100 * If there is not a cooresponding ATREQ command, this is an error. We
1101 * will ignore this response but still return success so we cleanup
1102 * after it and go on with other arresp's. This could happend if a
1103 * response was sent after the command has timed out or if the target
1104 * device is misbehaving. (we have seen both cases)
1106 *hcicmd
= (hci1394_async_cmd_t
*)command
;
1107 if ((*hcicmd
) == NULL
) {
1108 return (DDI_SUCCESS
);
1112 * copy the response code into the hal private command space. Setup
1113 * shortcuts to the 1394 framework command (cmd) and the HAL/SL private
1114 * area (cmd_priv). A command is made up of 4 parts. There is the public
1115 * part which is accessable to the target driver, there is the Services
1116 * Layer private part which is only accessible to the services layer,
1117 * there is the SL/HAL private area which is where the SL and HAL share
1118 * information about a particular command, and there is the HAL private
1119 * area where we keep track of our command specific state information.
1121 (*hcicmd
)->ac_status
= rcode
;
1122 cmd
= (*hcicmd
)->ac_cmd
;
1123 cmd_priv
= (*hcicmd
)->ac_priv
;
1126 * Calculate the address where the status of the ARRESP and timestamp is
1127 * kept at. It is the last quadlet in the response. Save away the
1130 status_addr
= (uint32_t *)((uintptr_t)pkt
+ (uintptr_t)*size
-
1131 (uintptr_t)IEEE1394_QUADLET
);
1132 quadlet
= hci1394_q_ar_get32(async_handle
->as_arresp_q
, status_addr
);
1133 cmd_priv
->recv_tstamp
= HCI1394_DESC_TIMESTAMP_GET(quadlet
);
1136 * if we did not get an ACK_COMPLETE, we will use the ack error instead
1137 * of the response in the packet for our status. We use special mask to
1138 * separate the reponses from the ACKs (ASYNC_ARRESP_ACK_ERROR). We will
1139 * return success with hcicmd set to the command so that this error gets
1140 * sent up to the Services Layer.
1142 ack
= HCI1394_DESC_EVT_GET(quadlet
);
1143 if (ack
!= OHCI_ACK_COMPLETE
) {
1144 /* use the ack error instead of rcode for the command status */
1145 (*hcicmd
)->ac_status
= ack
| ASYNC_ARRESP_ACK_ERROR
;
1146 return (DDI_SUCCESS
);
1150 * If we get to this point we have gotten a valid ACK on the response
1151 * and have matched up the response with an ATREQ. Now we check the
1152 * response code. If it is not resp_complete, we do not have anything
1153 * left to look at in the response. Return successfully.
1155 if (rcode
!= IEEE1394_RESP_COMPLETE
) {
1156 return (DDI_SUCCESS
);
1160 * Read the rest of the response (based on which kind of response it is)
1161 * into the 1394 framework command. In all of the different responses,
1162 * we check to make sure the response matches the original request. We
1163 * originally did not have this check but found a device or two which
1164 * did not behave very well and would cause us to corrupt our commands.
1165 * Now we check :-) We will return success when we get this error since
1166 * we can recover from it.
1169 case IEEE1394_TCODE_WRITE_RESP
:
1171 * make sure the ATREQ was a quadlet/block write. The same
1172 * response is sent back for those two type of ATREQs.
1174 if ((cmd
->cmd_type
!= CMD1394_ASYNCH_WR_QUAD
) &&
1175 (cmd
->cmd_type
!= CMD1394_ASYNCH_WR_BLOCK
)) {
1176 (*hcicmd
)->ac_status
= H1394_CMD_EDEVICE_ERROR
;
1177 return (DDI_SUCCESS
);
1181 case IEEE1394_TCODE_READ_QUADLET_RESP
:
1182 /* make sure the ATREQ was a quadlet read */
1183 if (cmd
->cmd_type
!= CMD1394_ASYNCH_RD_QUAD
) {
1184 (*hcicmd
)->ac_status
= H1394_CMD_EDEVICE_ERROR
;
1185 return (DDI_SUCCESS
);
1189 * read the quadlet read response in. Data is treated as a byte
1192 hci1394_q_ar_rep_get8(async_handle
->as_arresp_q
,
1193 (uint8_t *)&cmd
->cmd_u
.q
.quadlet_data
,
1194 (uint8_t *)&pkt
->q4
, IEEE1394_QUADLET
);
1197 case IEEE1394_TCODE_READ_BLOCK_RESP
:
1198 /* make sure the ATREQ was a block read */
1199 if (cmd
->cmd_type
!= CMD1394_ASYNCH_RD_BLOCK
) {
1200 (*hcicmd
)->ac_status
= H1394_CMD_EDEVICE_ERROR
;
1201 return (DDI_SUCCESS
);
1205 * read in the data length. Make sure the data length is the
1206 * same size as the read block request size that went out.
1208 quadlet
= hci1394_q_ar_get32(async_handle
->as_arresp_q
,
1210 data_length
= HCI1394_DESC_DATALEN_GET(quadlet
);
1211 if (data_length
!= cmd_priv
->mblk
.length
) {
1212 (*hcicmd
)->ac_status
= H1394_CMD_EDEVICE_ERROR
;
1213 return (DDI_SUCCESS
);
1216 /* Copy the read block data into the command mblk */
1217 hci1394_q_ar_copy_to_mblk(async_handle
->as_arresp_q
,
1218 (uint8_t *)&pkt
->q5
, &cmd_priv
->mblk
);
1221 case IEEE1394_TCODE_LOCK_RESP
:
1222 /* read in the data length */
1223 quadlet
= hci1394_q_ar_get32(async_handle
->as_arresp_q
,
1225 data_length
= HCI1394_DESC_DATALEN_GET(quadlet
);
1227 if (cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_32
) {
1229 * read in the data length. Make sure the data length
1230 * is the valid for a lock32 response (1 quadlet)
1232 if (data_length
!= IEEE1394_QUADLET
) {
1233 (*hcicmd
)->ac_status
= H1394_CMD_EDEVICE_ERROR
;
1234 return (DDI_SUCCESS
);
1238 * read the lock32 response in. Data is treated as a
1239 * byte stream unless it is an arithmetic lock
1240 * operation. In that case we treat data like a 32-bit
1243 hci1394_q_ar_rep_get8(async_handle
->as_arresp_q
,
1244 (uint8_t *)&cmd
->cmd_u
.l32
.old_value
,
1245 (uint8_t *)&pkt
->q5
, IEEE1394_QUADLET
);
1246 cmd
->cmd_u
.l32
.old_value
= HCI1394_ARITH_LOCK_SWAP32(
1247 cmd
->cmd_u
.l32
.lock_type
, cmd
->cmd_u
.l32
.old_value
);
1249 } else if (cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_64
) {
1251 * read in the data length. Make sure the data length
1252 * is the valid for a lock64 response (1 octlet)
1254 if (data_length
!= IEEE1394_OCTLET
) {
1255 (*hcicmd
)->ac_status
= H1394_CMD_EDEVICE_ERROR
;
1256 return (DDI_SUCCESS
);
1260 * read the lock64 response in. Data is treated as a
1261 * byte stream unless it is an arithmetic lock
1262 * operation. In that case we treat data like a 64-bit
1265 hci1394_q_ar_rep_get8(async_handle
->as_arresp_q
,
1266 (uint8_t *)&cmd
->cmd_u
.l64
.old_value
,
1267 (uint8_t *)&pkt
->q5
, IEEE1394_OCTLET
);
1268 cmd
->cmd_u
.l64
.old_value
= HCI1394_ARITH_LOCK_SWAP64(
1269 cmd
->cmd_u
.l64
.lock_type
, cmd
->cmd_u
.l64
.old_value
);
1272 * we sent out a request that was NOT a lock request and got
1273 * back a lock response.
1276 (*hcicmd
)->ac_status
= H1394_CMD_EDEVICE_ERROR
;
1277 return (DDI_SUCCESS
);
1282 /* we got a tcode that we don't know about. Return error */
1283 return (DDI_FAILURE
);
1286 return (DDI_SUCCESS
);
1291 * hci1394_async_arreq_read()
1292 * Read ARREQ in from memory into a 1394 Framework command. Allocate a 1394
1293 * framework command, read in the ARREQ, and before passing it up to the
1294 * services layer, see if it was a valid broadcast request.
1296 * The only time this routine should return DDI_FAILURE is if it was unable
1297 * to maintain a good state in the ARREQ Q (i.e. an unknown request was
1298 * received and we can not cleanup after it.) If we detect a recoverable
1299 * error we should return DDI_SUCCESS with hcicmd = NULL.
1302 hci1394_async_arreq_read(hci1394_async_handle_t async_handle
,
1303 hci1394_basic_pkt_t
*pkt
, uint_t
*tcode
, hci1394_async_cmd_t
**hcicmd
,
1306 h1394_cmd_priv_t
*cmd_priv
;
1307 boolean_t is_reset_token
;
1313 ASSERT(async_handle
!= NULL
);
1314 ASSERT(pkt
!= NULL
);
1315 ASSERT(tcode
!= NULL
);
1316 ASSERT(hcicmd
!= NULL
);
1317 ASSERT(size
!= NULL
);
1319 /* read in the arresp tcode */
1320 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q1
);
1321 *tcode
= HCI1394_DESC_TCODE_GET(quadlet
);
1324 * Allocated 1394 framework command. The Services layer takes care of
1325 * cacheing commands. This is called during interrupt processing so we
1326 * do not want to sleep.
1328 status
= h1394_alloc_cmd(async_handle
->as_drvinfo
->di_sl_private
,
1329 H1394_ALLOC_CMD_NOSLEEP
, &cmd
, &cmd_priv
);
1330 if (status
!= DDI_SUCCESS
) {
1331 return (DDI_FAILURE
);
1334 /* Initialize the HAL private command info */
1335 hci1394_async_hcicmd_init(async_handle
, cmd
, cmd_priv
, hcicmd
);
1338 * There are two generations in the command structure, one in the public
1339 * space and one in the HAL/SL private shared space. We need to fill in
1340 * both. We only use the private one internally.
1342 cmd_priv
->bus_generation
= async_handle
->as_drvinfo
->di_gencnt
;
1343 cmd
->bus_generation
= async_handle
->as_drvinfo
->di_gencnt
;
1346 * Read the request (based on which kind of request it is) into the 1394
1347 * framework command.
1350 case IEEE1394_TCODE_READ_QUADLET
:
1352 * We got a ARREQ quadlet read request. Read in the packet.
1353 * If there is a problem with the packet (i.e. we don't get
1354 * DDI_SUCCESS), we will free up the command and return NULL in
1355 * hcicmd to indicate that we did not get a valid ARREQ to
1358 status
= hci1394_async_arreq_read_qrd(async_handle
, pkt
,
1360 if (status
!= DDI_SUCCESS
) {
1361 hci1394_async_response_complete(async_handle
, cmd
,
1364 return (DDI_SUCCESS
);
1368 case IEEE1394_TCODE_WRITE_QUADLET
:
1370 * We got a ARREQ quadlet write request. Read in the packet.
1371 * If there is a problem with the packet (i.e. we don't get
1372 * DDI_SUCCESS), we will free up the command and return NULL in
1373 * hcicmd to indicate that we did not get a valid ARREQ to
1376 status
= hci1394_async_arreq_read_qwr(async_handle
, pkt
,
1378 if (status
!= DDI_SUCCESS
) {
1379 hci1394_async_response_complete(async_handle
, cmd
,
1382 return (DDI_SUCCESS
);
1386 case IEEE1394_TCODE_READ_BLOCK
:
1388 * We got a ARREQ block read request. Read in the packet.
1389 * If there is a problem with the packet (i.e. we don't get
1390 * DDI_SUCCESS), we will free up the command and return NULL in
1391 * hcicmd to indicate that we did not get a valid ARREQ to
1394 status
= hci1394_async_arreq_read_brd(async_handle
, pkt
,
1396 if (status
!= DDI_SUCCESS
) {
1397 hci1394_async_response_complete(async_handle
, cmd
,
1400 return (DDI_SUCCESS
);
1404 case IEEE1394_TCODE_WRITE_BLOCK
:
1406 * We got a ARREQ block write request. Read in the packet.
1407 * If there is a problem with the packet (i.e. we don't get
1408 * DDI_SUCCESS), we will free up the command and return NULL in
1409 * hcicmd to indicate that we did not get a valid ARREQ to
1412 status
= hci1394_async_arreq_read_bwr(async_handle
, pkt
,
1414 if (status
!= DDI_SUCCESS
) {
1415 hci1394_async_response_complete(async_handle
, cmd
,
1418 return (DDI_SUCCESS
);
1422 case IEEE1394_TCODE_LOCK
:
1424 * We got a ARREQ lock request. Read in the packet.
1425 * If there is a problem with the packet (i.e. we don't get
1426 * DDI_SUCCESS), we will free up the command and return NULL in
1427 * hcicmd to indicate that we did not get a valid ARREQ to
1430 status
= hci1394_async_arreq_read_lck(async_handle
, pkt
,
1432 if (status
!= DDI_SUCCESS
) {
1433 hci1394_async_response_complete(async_handle
, cmd
,
1436 return (DDI_SUCCESS
);
1440 case IEEE1394_TCODE_PHY
:
1442 * We got a PHY packet in the ARREQ buffer. Read in the packet.
1443 * If there is a problem with the packet (i.e. we don't get
1444 * DDI_SUCCESS), we will free up the command and return NULL in
1445 * hcicmd to indicate that we did not get a valid ARREQ to
1448 status
= hci1394_async_arreq_read_phy(async_handle
, pkt
,
1449 *hcicmd
, size
, &is_reset_token
);
1450 if (status
!= DDI_SUCCESS
) {
1451 hci1394_async_response_complete(async_handle
, cmd
,
1454 return (DDI_SUCCESS
);
1458 * If we got a bus reset token, free up the command and return
1459 * NULL in hcicmd to indicate that we did not get a valid ARREQ
1462 if (is_reset_token
== B_TRUE
) {
1463 hci1394_async_response_complete(async_handle
, cmd
,
1466 return (DDI_SUCCESS
);
1471 /* we got a tcode that we don't know about. Return error */
1472 return (DDI_FAILURE
);
1476 * If this command was broadcast and it was not a write, drop the
1477 * command since it's an invalid request. We will free up the command
1478 * and return NULL in hcicmd to indicate that we did not get a valid
1481 if ((((*hcicmd
)->ac_dest
& IEEE1394_NODE_NUM_MASK
) ==
1482 IEEE1394_BROADCAST_NODEID
) && ((*tcode
!=
1483 IEEE1394_TCODE_WRITE_QUADLET
) && (*tcode
!=
1484 IEEE1394_TCODE_WRITE_BLOCK
))) {
1485 hci1394_async_response_complete(async_handle
, cmd
, cmd_priv
);
1487 return (DDI_SUCCESS
);
1490 * It is a valid broadcast command, set that field in the public
1491 * command structure.
1493 } else if ((((*hcicmd
)->ac_dest
& IEEE1394_NODE_NUM_MASK
) ==
1494 IEEE1394_BROADCAST_NODEID
)) {
1498 return (DDI_SUCCESS
);
1503 * hci1394_async_arreq_read_qrd()
1504 * Read ARREQ quadlet read into the 1394 Framework command. This routine will
1505 * return DDI_FAILURE if it was not able to read the request succesfully.
1508 hci1394_async_arreq_read_qrd(hci1394_async_handle_t async_handle
,
1509 hci1394_basic_pkt_t
*pkt
, hci1394_async_cmd_t
*hcicmd
, uint_t
*size
)
1511 h1394_cmd_priv_t
*cmd_priv
;
1516 ASSERT(async_handle
!= NULL
);
1517 ASSERT(pkt
!= NULL
);
1518 ASSERT(hcicmd
!= NULL
);
1519 ASSERT(size
!= NULL
);
1521 /* Setup shortcuts, command type, and size of request */
1522 cmd
= hcicmd
->ac_cmd
;
1523 cmd_priv
= hcicmd
->ac_priv
;
1524 cmd
->cmd_type
= CMD1394_ASYNCH_RD_QUAD
;
1525 *size
= DESC_SZ_AR_READQUAD_REQ
;
1528 * read in the ARREQ ACK/EVT, the speed, the time we received it, and
1529 * calculate the ATRESP timeout for when we send it.
1531 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q4
);
1532 hcicmd
->ac_status
= HCI1394_DESC_EVT_GET(quadlet
);
1533 cmd_priv
->speed
= HCI1394_DESC_AR_SPD_GET(quadlet
);
1534 cmd_priv
->recv_tstamp
= HCI1394_DESC_TIMESTAMP_GET(quadlet
);
1535 hcicmd
->ac_qcmd
.qc_timestamp
= hci1394_async_timeout_calc(async_handle
,
1536 cmd_priv
->recv_tstamp
);
1539 * if the ARREQ ACK was bad, we were unable to successfully read in this
1540 * request. Return failure.
1542 if ((hcicmd
->ac_status
!= OHCI_ACK_COMPLETE
) &&
1543 (hcicmd
->ac_status
!= OHCI_ACK_PENDING
)) {
1544 return (DDI_FAILURE
);
1548 * Read in the tlabel and destination. We don't use an mblk for this
1551 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q1
);
1552 hcicmd
->ac_dest
= HCI1394_DESC_DESTID_GET(quadlet
);
1553 hcicmd
->ac_tlabel
.tbi_tlabel
= HCI1394_DESC_TLABEL_GET(quadlet
);
1554 hcicmd
->ac_mblk_alloc
= B_FALSE
;
1557 * Read in the sender so we know who to send the ATRESP to and read in
1558 * the 1394 48-bit address for this request.
1560 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q2
);
1561 cmd
->nodeID
= HCI1394_DESC_SRCID_GET(quadlet
);
1562 cmd
->cmd_addr
= HCI1394_TO_ADDR_HI(quadlet
);
1563 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q3
);
1564 cmd
->cmd_addr
|= HCI1394_TO_ADDR_LO(quadlet
);
1566 return (DDI_SUCCESS
);
1571 * hci1394_async_arreq_read_qwr()
1572 * Read ARREQ quadlet write into the 1394 Framework command. This routine
1573 * will return DDI_FAILURE if it was not able to read the request
1577 hci1394_async_arreq_read_qwr(hci1394_async_handle_t async_handle
,
1578 hci1394_basic_pkt_t
*pkt
, hci1394_async_cmd_t
*hcicmd
, uint_t
*size
)
1580 h1394_cmd_priv_t
*cmd_priv
;
1585 ASSERT(async_handle
!= NULL
);
1586 ASSERT(pkt
!= NULL
);
1587 ASSERT(hcicmd
!= NULL
);
1588 ASSERT(size
!= NULL
);
1590 /* Setup shortcuts, command type, and size of request */
1591 cmd
= hcicmd
->ac_cmd
;
1592 cmd_priv
= hcicmd
->ac_priv
;
1593 cmd
->cmd_type
= CMD1394_ASYNCH_WR_QUAD
;
1594 *size
= DESC_SZ_AR_WRITEQUAD_REQ
;
1597 * read in the ARREQ ACK/EVT, the speed, the time we received it, and
1598 * calculate the ATRESP timeout for when we send it.
1600 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q5
);
1601 hcicmd
->ac_status
= HCI1394_DESC_EVT_GET(quadlet
);
1602 cmd_priv
->speed
= HCI1394_DESC_AR_SPD_GET(quadlet
);
1603 cmd_priv
->recv_tstamp
= HCI1394_DESC_TIMESTAMP_GET(quadlet
);
1604 hcicmd
->ac_qcmd
.qc_timestamp
= hci1394_async_timeout_calc(async_handle
,
1605 cmd_priv
->recv_tstamp
);
1608 * if the ARREQ ACK was bad, we were unable to successfully read in this
1609 * request. Return failure.
1611 if ((hcicmd
->ac_status
!= OHCI_ACK_COMPLETE
) &&
1612 (hcicmd
->ac_status
!= OHCI_ACK_PENDING
)) {
1613 return (DDI_FAILURE
);
1617 * Read in the tlabel and destination. We don't use an mblk for this
1620 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q1
);
1621 hcicmd
->ac_dest
= HCI1394_DESC_DESTID_GET(quadlet
);
1622 hcicmd
->ac_tlabel
.tbi_tlabel
= HCI1394_DESC_TLABEL_GET(quadlet
);
1623 hcicmd
->ac_mblk_alloc
= B_FALSE
;
1626 * Read in the sender so we know who to send the ATRESP to. Read in
1627 * the 1394 48-bit address for this request. Copy the data quadlet into
1628 * the command. The data quadlet is treated like a byte stream.
1630 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q2
);
1631 cmd
->nodeID
= HCI1394_DESC_SRCID_GET(quadlet
);
1632 cmd
->cmd_addr
= HCI1394_TO_ADDR_HI(quadlet
);
1633 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q3
);
1634 cmd
->cmd_addr
|= HCI1394_TO_ADDR_LO(quadlet
);
1635 hci1394_q_ar_rep_get8(async_handle
->as_arreq_q
,
1636 (uint8_t *)&cmd
->cmd_u
.q
.quadlet_data
, (uint8_t *)&pkt
->q4
,
1639 return (DDI_SUCCESS
);
1644 * hci1394_async_arreq_read_brd()
1645 * Read ARREQ block read into the 1394 Framework command. This routine will
1646 * return DDI_FAILURE if it was not able to read the request succesfully.
1649 hci1394_async_arreq_read_brd(hci1394_async_handle_t async_handle
,
1650 hci1394_basic_pkt_t
*pkt
, hci1394_async_cmd_t
*hcicmd
, uint_t
*size
)
1652 h1394_cmd_priv_t
*cmd_priv
;
1657 ASSERT(async_handle
!= NULL
);
1658 ASSERT(pkt
!= NULL
);
1659 ASSERT(hcicmd
!= NULL
);
1660 ASSERT(size
!= NULL
);
1662 /* Setup shortcuts, command type, and size of request */
1663 cmd
= hcicmd
->ac_cmd
;
1664 cmd_priv
= hcicmd
->ac_priv
;
1665 cmd
->cmd_type
= CMD1394_ASYNCH_RD_BLOCK
;
1666 *size
= DESC_SZ_AR_READBLOCK_REQ
;
1669 * read in the ARREQ ACK/EVT, the speed, the time we received it, and
1670 * calculate the ATRESP timeout for when we send it.
1672 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q5
);
1673 hcicmd
->ac_status
= HCI1394_DESC_EVT_GET(quadlet
);
1674 cmd_priv
->speed
= HCI1394_DESC_AR_SPD_GET(quadlet
);
1675 cmd_priv
->recv_tstamp
= HCI1394_DESC_TIMESTAMP_GET(quadlet
);
1676 hcicmd
->ac_qcmd
.qc_timestamp
= hci1394_async_timeout_calc(async_handle
,
1677 cmd_priv
->recv_tstamp
);
1680 * if the ARREQ ACK was bad, we were unable to successfully read in this
1681 * request. Return failure.
1683 if ((hcicmd
->ac_status
!= OHCI_ACK_COMPLETE
) &&
1684 (hcicmd
->ac_status
!= OHCI_ACK_PENDING
)) {
1685 return (DDI_FAILURE
);
1688 /* Read in the tlabel and destination */
1689 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q1
);
1690 hcicmd
->ac_dest
= HCI1394_DESC_DESTID_GET(quadlet
);
1691 hcicmd
->ac_tlabel
.tbi_tlabel
= HCI1394_DESC_TLABEL_GET(quadlet
);
1694 * Read in the sender so we know who to send the ATRESP to. Read in
1695 * the 1394 48-bit address for this request. Read in the block data size
1696 * and allocate an mblk of that size.
1698 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q2
);
1699 cmd
->nodeID
= HCI1394_DESC_SRCID_GET(quadlet
);
1700 cmd
->cmd_addr
= HCI1394_TO_ADDR_HI(quadlet
);
1701 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q3
);
1702 cmd
->cmd_addr
|= HCI1394_TO_ADDR_LO(quadlet
);
1703 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q4
);
1704 cmd
->cmd_u
.b
.blk_length
= HCI1394_DESC_DATALEN_GET(quadlet
);
1705 cmd
->cmd_u
.b
.data_block
= allocb(cmd
->cmd_u
.b
.blk_length
, 0);
1706 if (cmd
->cmd_u
.b
.data_block
== NULL
) {
1707 return (DDI_FAILURE
);
1709 hcicmd
->ac_mblk_alloc
= B_TRUE
;
1711 return (DDI_SUCCESS
);
1716 * hci1394_async_arreq_read_bwr()
1717 * Read ARREQ block write into the 1394 Framework command. This routine will
1718 * return DDI_FAILURE if it was not able to read the request succesfully.
1721 hci1394_async_arreq_read_bwr(hci1394_async_handle_t async_handle
,
1722 hci1394_basic_pkt_t
*pkt
, hci1394_async_cmd_t
*hcicmd
, uint_t
*size
)
1724 h1394_cmd_priv_t
*cmd_priv
;
1725 uint32_t *local_addr
;
1730 ASSERT(async_handle
!= NULL
);
1731 ASSERT(pkt
!= NULL
);
1732 ASSERT(hcicmd
!= NULL
);
1733 ASSERT(size
!= NULL
);
1736 * Setup shortcuts, command type, and size of request. The size of the
1737 * request is in quadlets, therefore we need to make sure we count in
1738 * the padding when figureing out the size (i.e. data may be in bytes
1739 * but the HW always pads to quadlets)
1741 cmd
= hcicmd
->ac_cmd
;
1742 cmd_priv
= hcicmd
->ac_priv
;
1743 cmd
->cmd_type
= CMD1394_ASYNCH_WR_BLOCK
;
1744 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q4
);
1745 cmd
->cmd_u
.b
.blk_length
= HCI1394_DESC_DATALEN_GET(quadlet
);
1746 *size
= DESC_SZ_AR_WRITEBLOCK_REQ
+
1747 HCI1394_ALIGN_QUAD(cmd
->cmd_u
.b
.blk_length
);
1750 * read in the ARREQ ACK/EVT, the speed, the time we received it, and
1751 * calculate the ATRESP timeout for when we send it. The status word is
1752 * the last quadlet in the packet.
1754 local_addr
= (uint32_t *)(((uintptr_t)(&pkt
->q5
)) +
1755 ((uintptr_t)HCI1394_ALIGN_QUAD(cmd
->cmd_u
.b
.blk_length
)));
1756 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, local_addr
);
1757 hcicmd
->ac_status
= HCI1394_DESC_EVT_GET(quadlet
);
1758 cmd_priv
->speed
= HCI1394_DESC_AR_SPD_GET(quadlet
);
1759 cmd_priv
->recv_tstamp
= HCI1394_DESC_TIMESTAMP_GET(quadlet
);
1760 hcicmd
->ac_qcmd
.qc_timestamp
= hci1394_async_timeout_calc(async_handle
,
1761 cmd_priv
->recv_tstamp
);
1764 * if the ARREQ ACK was bad, we were unable to successfully read in this
1765 * request. Return failure.
1767 if ((hcicmd
->ac_status
!= OHCI_ACK_COMPLETE
) &&
1768 (hcicmd
->ac_status
!= OHCI_ACK_PENDING
)) {
1769 return (DDI_FAILURE
);
1772 /* Read in the tlabel and destination */
1773 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q1
);
1774 hcicmd
->ac_dest
= HCI1394_DESC_DESTID_GET(quadlet
);
1775 hcicmd
->ac_tlabel
.tbi_tlabel
= HCI1394_DESC_TLABEL_GET(quadlet
);
1778 * Read in the sender so we know who to send the ATRESP to. Read in
1779 * the 1394 48-bit address for this request. Read in the block data size
1780 * and allocate an mblk of that size.
1782 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q2
);
1783 cmd
->nodeID
= HCI1394_DESC_SRCID_GET(quadlet
);
1784 cmd
->cmd_addr
= HCI1394_TO_ADDR_HI(quadlet
);
1785 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q3
);
1786 cmd
->cmd_addr
|= HCI1394_TO_ADDR_LO(quadlet
);
1787 cmd
->cmd_u
.b
.data_block
= allocb(cmd
->cmd_u
.b
.blk_length
, 0);
1788 if (cmd
->cmd_u
.b
.data_block
== NULL
) {
1789 return (DDI_FAILURE
);
1791 hcicmd
->ac_mblk_alloc
= B_TRUE
;
1793 /* Copy ARREQ write data into mblk_t */
1794 hci1394_q_ar_rep_get8(async_handle
->as_arreq_q
,
1795 (uint8_t *)cmd
->cmd_u
.b
.data_block
->b_wptr
,
1796 (uint8_t *)&pkt
->q5
, cmd
->cmd_u
.b
.blk_length
);
1798 /* Update mblk_t wptr */
1799 cmd
->cmd_u
.b
.data_block
->b_wptr
+= cmd
->cmd_u
.b
.blk_length
;
1801 return (DDI_SUCCESS
);
1806 * hci1394_async_arreq_read_lck()
1807 * Read ARREQ lock request into the 1394 Framework command. This routine will
1808 * return DDI_FAILURE if it was not able to read the request succesfully.
1811 hci1394_async_arreq_read_lck(hci1394_async_handle_t async_handle
,
1812 hci1394_basic_pkt_t
*pkt
, hci1394_async_cmd_t
*hcicmd
, uint_t
*size
)
1814 h1394_cmd_priv_t
*cmd_priv
;
1815 uint32_t *local_addr
;
1822 ASSERT(async_handle
!= NULL
);
1823 ASSERT(pkt
!= NULL
);
1824 ASSERT(hcicmd
!= NULL
);
1825 ASSERT(size
!= NULL
);
1828 * Setup shortcuts, command type, and size of request. The size of the
1829 * request is in quadlets, therefore we need to make sure we count in
1830 * the padding when figuring out the size (i.e. data may be in bytes
1831 * but the HW always pads to quadlets)
1833 cmd
= hcicmd
->ac_cmd
;
1834 cmd_priv
= hcicmd
->ac_priv
;
1835 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q4
);
1836 length
= HCI1394_DESC_DATALEN_GET(quadlet
);
1837 *size
= DESC_SZ_AR_LOCK_REQ
+ HCI1394_ALIGN_QUAD(length
);
1839 /* make sure the length is a valid lock request length */
1840 if (length
== DESC_TWO_QUADS
) {
1841 cmd
->cmd_type
= CMD1394_ASYNCH_LOCK_32
;
1842 cmd
->cmd_u
.l32
.lock_type
= HCI1394_DESC_EXTTCODE_GET(quadlet
);
1843 } else if (length
== DESC_TWO_OCTLETS
) {
1844 cmd
->cmd_type
= CMD1394_ASYNCH_LOCK_64
;
1845 cmd
->cmd_u
.l64
.lock_type
= HCI1394_DESC_EXTTCODE_GET(quadlet
);
1847 return (DDI_FAILURE
);
1851 * read in the ARREQ ACK/EVT, the speed, the time we received it, and
1852 * calculate the ATRESP timeout for when we send it. The status word is
1853 * the last quadlet in the packet.
1855 local_addr
= (uint32_t *)(((uintptr_t)(&pkt
->q5
)) +
1856 ((uintptr_t)HCI1394_ALIGN_QUAD(length
)));
1857 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, local_addr
);
1858 hcicmd
->ac_status
= HCI1394_DESC_EVT_GET(quadlet
);
1859 cmd_priv
->speed
= HCI1394_DESC_AR_SPD_GET(quadlet
);
1860 cmd_priv
->recv_tstamp
= HCI1394_DESC_TIMESTAMP_GET(quadlet
);
1861 hcicmd
->ac_qcmd
.qc_timestamp
= hci1394_async_timeout_calc(async_handle
,
1862 cmd_priv
->recv_tstamp
);
1865 * if the ARREQ ACK was bad, we were unable to successfully read in this
1866 * request. Return failure.
1868 if ((hcicmd
->ac_status
!= OHCI_ACK_COMPLETE
) &&
1869 (hcicmd
->ac_status
!= OHCI_ACK_PENDING
)) {
1870 return (DDI_FAILURE
);
1873 /* Read in the tlabel and destination */
1874 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q1
);
1875 hcicmd
->ac_dest
= HCI1394_DESC_DESTID_GET(quadlet
);
1876 hcicmd
->ac_tlabel
.tbi_tlabel
= HCI1394_DESC_TLABEL_GET(quadlet
);
1877 hcicmd
->ac_mblk_alloc
= B_FALSE
;
1880 * Read in the sender so we know who to send the ATRESP to. Read in
1881 * the 1394 48-bit address for this request.
1883 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q2
);
1884 cmd
->nodeID
= HCI1394_DESC_SRCID_GET(quadlet
);
1885 cmd
->cmd_addr
= HCI1394_TO_ADDR_HI(quadlet
);
1886 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q3
);
1887 cmd
->cmd_addr
|= HCI1394_TO_ADDR_LO(quadlet
);
1889 /* Copy ARREQ lock data into 1394 framework command */
1890 if (cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_32
) {
1891 data_addr
= (uint8_t *)&pkt
->q5
;
1892 hci1394_q_ar_rep_get8(async_handle
->as_arreq_q
,
1893 (uint8_t *)&cmd
->cmd_u
.l32
.arg_value
, data_addr
,
1895 data_addr
= (uint8_t *)((uintptr_t)data_addr
+
1896 (uintptr_t)IEEE1394_QUADLET
);
1897 hci1394_q_ar_rep_get8(async_handle
->as_arreq_q
,
1898 (uint8_t *)&cmd
->cmd_u
.l32
.data_value
, data_addr
,
1901 * swap these for our correct architecture if we are doing
1902 * arithmetic lock operations
1904 cmd
->cmd_u
.l32
.arg_value
= HCI1394_ARITH_LOCK_SWAP32(
1905 cmd
->cmd_u
.l32
.lock_type
, cmd
->cmd_u
.l32
.arg_value
);
1906 cmd
->cmd_u
.l32
.data_value
= HCI1394_ARITH_LOCK_SWAP32(
1907 cmd
->cmd_u
.l32
.lock_type
, cmd
->cmd_u
.l32
.data_value
);
1908 } else if (cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_64
) {
1909 data_addr
= (uint8_t *)&pkt
->q5
;
1910 hci1394_q_ar_rep_get8(async_handle
->as_arreq_q
,
1911 (uint8_t *)&cmd
->cmd_u
.l64
.arg_value
, data_addr
,
1913 data_addr
= (uint8_t *)((uintptr_t)data_addr
+
1914 (uintptr_t)IEEE1394_OCTLET
);
1915 hci1394_q_ar_rep_get8(async_handle
->as_arreq_q
,
1916 (uint8_t *)&cmd
->cmd_u
.l64
.data_value
, data_addr
,
1920 * swap these for our correct architecture if we are doing
1921 * arithmetic lock operations
1923 cmd
->cmd_u
.l64
.arg_value
= HCI1394_ARITH_LOCK_SWAP64(
1924 cmd
->cmd_u
.l64
.lock_type
, cmd
->cmd_u
.l64
.arg_value
);
1925 cmd
->cmd_u
.l64
.data_value
= HCI1394_ARITH_LOCK_SWAP64(
1926 cmd
->cmd_u
.l64
.lock_type
, cmd
->cmd_u
.l64
.data_value
);
1929 return (DDI_SUCCESS
);
1934 * hci1394_async_arreq_read_phy()
1935 * Read ARREQ PHY quadlet into the 1394 Framework command. This routine will
1936 * return DDI_FAILURE if it was not able to read the request succesfully.
1939 hci1394_async_arreq_read_phy(hci1394_async_handle_t async_handle
,
1940 hci1394_basic_pkt_t
*pkt
, hci1394_async_cmd_t
*hcicmd
, uint_t
*size
,
1941 boolean_t
*bus_reset_token
)
1949 ASSERT(async_handle
!= NULL
);
1950 ASSERT(pkt
!= NULL
);
1951 ASSERT(hcicmd
!= NULL
);
1952 ASSERT(size
!= NULL
);
1954 /* Setup shortcuts, command type, and size of request */
1955 cmd
= hcicmd
->ac_cmd
;
1956 cmd
->cmd_type
= CMD1394_ASYNCH_WR_QUAD
;
1957 *size
= DESC_SZ_AR_PHY
;
1960 * read in the ARREQ ACK/EVT, the speed, the time we received it, and
1961 * set state that we do not use an mblk for this request.
1963 quadlet
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q4
);
1964 hcicmd
->ac_status
= HCI1394_DESC_EVT_GET(quadlet
);
1965 hcicmd
->ac_priv
->speed
= HCI1394_DESC_AR_SPD_GET(quadlet
);
1966 hcicmd
->ac_priv
->recv_tstamp
= HCI1394_DESC_TIMESTAMP_GET(quadlet
);
1967 hcicmd
->ac_mblk_alloc
= B_FALSE
;
1969 /* Read in the PHY packet quadlet and its check quadlet */
1970 data1
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q2
);
1971 data2
= hci1394_q_ar_get32(async_handle
->as_arreq_q
, &pkt
->q3
);
1974 * if this is a bus reset token, save away the generation. If the bus
1975 * reset token is for the current generation, we do not need to flush
1976 * the ARREQ Q anymore.
1978 if (hcicmd
->ac_status
== OHCI_EVT_BUS_RESET
) {
1979 *bus_reset_token
= B_TRUE
;
1980 async_handle
->as_phy_reset
= HCI1394_DESC_PHYGEN_GET(data2
);
1981 if (async_handle
->as_phy_reset
== hci1394_ohci_current_busgen(
1982 async_handle
->as_ohci
)) {
1983 async_handle
->as_flushing_arreq
= B_FALSE
;
1985 return (DDI_SUCCESS
);
1988 *bus_reset_token
= B_FALSE
;
1990 /* if there is a data error in the PHY packet, return failure */
1991 if (data1
!= ~data2
) {
1992 return (DDI_FAILURE
);
1995 /* Copy the PHY quadlet to the command */
1996 cmd
->cmd_u
.q
.quadlet_data
= data1
;
1998 return (DDI_SUCCESS
);
2003 * hci1394_async_phy()
2004 * Queue up ATREQ phy packet.
2007 hci1394_async_phy(hci1394_async_handle_t async_handle
, cmd1394_cmd_t
*cmd
,
2008 h1394_cmd_priv_t
*cmd_priv
, int *result
)
2010 hci1394_basic_pkt_t header
;
2011 hci1394_async_cmd_t
*hcicmd
;
2015 ASSERT(async_handle
!= NULL
);
2016 ASSERT(cmd
!= NULL
);
2017 ASSERT(cmd_priv
!= NULL
);
2018 ASSERT(result
!= NULL
);
2021 * make sure this call is during the current bus generation (i.e. no
2022 * bus resets have occured since this request was made.
2024 if (cmd_priv
->bus_generation
!= hci1394_ohci_current_busgen(
2025 async_handle
->as_ohci
)) {
2026 *result
= H1394_STATUS_INVALID_BUSGEN
;
2027 return (DDI_FAILURE
);
2030 /* Initialize the private HAL command structure */
2031 hci1394_async_hcicmd_init(async_handle
, cmd
, cmd_priv
, &hcicmd
);
2033 /* We do not allocate a tlabel for a PHY packet */
2034 hcicmd
->ac_tlabel_alloc
= B_FALSE
;
2037 * Setup the packet header information for a ATREQ PHY packet Add in
2038 * the tcode, phy quadlet, and it's 1's complement.
2040 header
.q1
= DESC_ATREQ_Q1_PHY
;
2041 header
.q2
= cmd
->cmd_u
.q
.quadlet_data
;
2042 header
.q3
= ~header
.q2
;
2044 /* Write request into the ATREQ Q. If we fail, we're out of space */
2045 status
= hci1394_q_at(async_handle
->as_atreq_q
, &hcicmd
->ac_qcmd
,
2046 &header
, DESC_PKT_HDRLEN_AT_PHY
, result
);
2047 if (status
!= DDI_SUCCESS
) {
2048 return (DDI_FAILURE
);
2051 return (DDI_SUCCESS
);
2056 * hci1394_async_write()
2057 * Queue up ATREQ write. This could be either a block write or a quadlet
2061 hci1394_async_write(hci1394_async_handle_t async_handle
, cmd1394_cmd_t
*cmd
,
2062 h1394_cmd_priv_t
*cmd_priv
, int *result
)
2064 hci1394_async_cmd_t
*hcicmd
;
2065 hci1394_basic_pkt_t header
;
2069 ASSERT(async_handle
!= NULL
);
2070 ASSERT(cmd
!= NULL
);
2071 ASSERT(cmd_priv
!= NULL
);
2072 ASSERT(result
!= NULL
);
2075 * make sure this call is during the current bus generation (i.e. no
2076 * bus resets have occured since this request was made.
2078 if (cmd_priv
->bus_generation
!= hci1394_ohci_current_busgen(
2079 async_handle
->as_ohci
)) {
2080 *result
= H1394_STATUS_INVALID_BUSGEN
;
2081 return (DDI_FAILURE
);
2084 /* Initialize the private HAL command structure */
2085 hci1394_async_hcicmd_init(async_handle
, cmd
, cmd_priv
, &hcicmd
);
2086 hcicmd
->ac_dest
= (uint_t
)(cmd
->cmd_addr
>> IEEE1394_ADDR_PHY_ID_SHIFT
);
2088 /* allocate a tlabel for this request */
2089 status
= hci1394_tlabel_alloc(async_handle
->as_tlabel
, hcicmd
->ac_dest
,
2090 &hcicmd
->ac_tlabel
);
2091 if (status
!= DDI_SUCCESS
) {
2092 *result
= H1394_STATUS_EMPTY_TLABEL
;
2093 return (DDI_FAILURE
);
2097 * Setup the packet header information for a ATREQ write packet. We
2098 * will set the tcode later on since this could be a block write or
2099 * a quadlet write. Set SRCBusId if this write is not a local bus
2100 * access. Copy in the speed, tlabel, and destination address.
2103 if ((hcicmd
->ac_dest
& IEEE1394_BUS_NUM_MASK
) !=
2104 IEEE1394_BUS_NUM_MASK
) {
2105 header
.q1
|= DESC_AT_SRCBUSID
;
2107 header
.q1
|= HCI1394_DESC_AT_SPD_SET(cmd_priv
->speed
) |
2108 HCI1394_DESC_TLABEL_SET(hcicmd
->ac_tlabel
.tbi_tlabel
);
2109 header
.q2
= (uint32_t)(cmd
->cmd_addr
>> 32);
2110 header
.q3
= (uint32_t)(cmd
->cmd_addr
& DESC_PKT_DESTOFFLO_MASK
);
2112 /* Register this command w/ its tlabel */
2113 hci1394_tlabel_register(async_handle
->as_tlabel
, &hcicmd
->ac_tlabel
,
2116 /* If this is a quadlet write ATREQ */
2117 if (cmd
->cmd_type
== CMD1394_ASYNCH_WR_QUAD
) {
2119 * setup the tcode for a quadlet write request and copy in
2120 * the quadlet data. Endian issues will be taken care of in
2123 header
.q1
|= DESC_ATREQ_Q1_QWR
;
2124 header
.q4
= cmd
->cmd_u
.q
.quadlet_data
;
2127 * Write the request into the ATREQ Q. If we fail, we are out
2130 status
= hci1394_q_at(async_handle
->as_atreq_q
,
2131 &hcicmd
->ac_qcmd
, &header
, DESC_PKT_HDRLEN_AT_WRITEQUAD
,
2133 if (status
!= DDI_SUCCESS
) {
2134 return (DDI_FAILURE
);
2137 /* This is a block write ATREQ */
2139 /* setup the tcode and the length of the block write */
2140 header
.q1
|= DESC_ATREQ_Q1_BWR
;
2141 header
.q4
= HCI1394_DESC_DATALEN_SET(cmd_priv
->mblk
.length
);
2144 * Write the request into the ATREQ Q. If we fail, we are out
2145 * of space. The data is in a mblk(s). We use a special
2146 * interface in the HAL/SL private command block to handle
2147 * partial transfers out of the mblk due to packet size
2150 status
= hci1394_q_at_with_mblk(async_handle
->as_atreq_q
,
2151 &hcicmd
->ac_qcmd
, &header
, DESC_PKT_HDRLEN_AT_WRITEBLOCK
,
2152 &cmd_priv
->mblk
, result
);
2153 if (status
!= DDI_SUCCESS
) {
2154 return (DDI_FAILURE
);
2158 return (DDI_SUCCESS
);
2163 * hci1394_async_read()
2164 * Queue up ATREQ read. This could be either a block read or a quadlet
2168 hci1394_async_read(hci1394_async_handle_t async_handle
, cmd1394_cmd_t
*cmd
,
2169 h1394_cmd_priv_t
*cmd_priv
, int *result
)
2171 hci1394_basic_pkt_t header
;
2173 hci1394_async_cmd_t
*hcicmd
;
2176 ASSERT(async_handle
!= NULL
);
2177 ASSERT(cmd
!= NULL
);
2178 ASSERT(cmd_priv
!= NULL
);
2179 ASSERT(result
!= NULL
);
2182 * make sure this call is during the current bus generation (i.e. no
2183 * bus resets have occured since this request was made.
2185 if (cmd_priv
->bus_generation
!= hci1394_ohci_current_busgen(
2186 async_handle
->as_ohci
)) {
2187 *result
= H1394_STATUS_INVALID_BUSGEN
;
2188 return (DDI_FAILURE
);
2191 /* Initialize the private HAL command structure */
2192 hci1394_async_hcicmd_init(async_handle
, cmd
, cmd_priv
, &hcicmd
);
2193 hcicmd
->ac_dest
= (uint_t
)(cmd
->cmd_addr
>> IEEE1394_ADDR_PHY_ID_SHIFT
);
2195 /* allocate a tlabel for this request */
2196 status
= hci1394_tlabel_alloc(async_handle
->as_tlabel
, hcicmd
->ac_dest
,
2197 &hcicmd
->ac_tlabel
);
2198 if (status
!= DDI_SUCCESS
) {
2199 *result
= H1394_STATUS_EMPTY_TLABEL
;
2200 return (DDI_FAILURE
);
2204 * Setup the packet header information for a ATREQ read packet. We
2205 * will set the tcode later on since this could be a block read or
2206 * a quadlet read. Set SRCBusId if this read is not a local bus
2207 * access. Copy in the speed, tlabel, and destination address.
2210 if ((hcicmd
->ac_dest
& IEEE1394_BUS_NUM_MASK
) !=
2211 IEEE1394_BUS_NUM_MASK
) {
2212 header
.q1
|= DESC_AT_SRCBUSID
;
2214 header
.q1
|= HCI1394_DESC_AT_SPD_SET(cmd_priv
->speed
) |
2215 HCI1394_DESC_TLABEL_SET(hcicmd
->ac_tlabel
.tbi_tlabel
);
2216 header
.q2
= (uint32_t)(cmd
->cmd_addr
>> 32);
2217 header
.q3
= (uint32_t)(cmd
->cmd_addr
& DESC_PKT_DESTOFFLO_MASK
);
2219 /* Register this command w/ its tlabel */
2220 hci1394_tlabel_register(async_handle
->as_tlabel
, &hcicmd
->ac_tlabel
,
2223 /* If this is a quadlet read ATREQ */
2224 if (cmd
->cmd_type
== CMD1394_ASYNCH_RD_QUAD
) {
2225 /* setup the tcode for a quadlet read request */
2226 header
.q1
|= DESC_ATREQ_Q1_QRD
;
2230 * Write the request into the ATREQ Q. If we fail, we are out
2233 status
= hci1394_q_at(async_handle
->as_atreq_q
,
2234 &hcicmd
->ac_qcmd
, &header
, DESC_PKT_HDRLEN_AT_READQUAD
,
2236 if (status
!= DDI_SUCCESS
) {
2237 return (DDI_FAILURE
);
2241 /* setup the tcode and the length of the block read */
2242 header
.q1
|= DESC_ATREQ_Q1_BRD
;
2243 header
.q4
= HCI1394_DESC_DATALEN_SET(cmd_priv
->mblk
.length
);
2246 * Write the request into the ATREQ Q. If we fail, we are out
2249 status
= hci1394_q_at(async_handle
->as_atreq_q
,
2250 &hcicmd
->ac_qcmd
, &header
, DESC_PKT_HDRLEN_AT_READBLOCK
,
2252 if (status
!= DDI_SUCCESS
) {
2253 return (DDI_FAILURE
);
2257 return (DDI_SUCCESS
);
2262 * hci1394_async_lock()
2263 * Queue up ATREQ lock. This could be either a 32-bit or 64-bit lock
2267 hci1394_async_lock(hci1394_async_handle_t async_handle
, cmd1394_cmd_t
*cmd
,
2268 h1394_cmd_priv_t
*cmd_priv
, int *result
)
2270 hci1394_basic_pkt_t header
;
2271 hci1394_async_cmd_t
*hcicmd
;
2279 ASSERT(async_handle
!= NULL
);
2280 ASSERT(cmd
!= NULL
);
2281 ASSERT(cmd_priv
!= NULL
);
2282 ASSERT(result
!= NULL
);
2285 * make sure this call is during the current bus generation (i.e. no
2286 * bus resets have occured since this request was made.
2288 if (cmd_priv
->bus_generation
!= hci1394_ohci_current_busgen(
2289 async_handle
->as_ohci
)) {
2290 *result
= H1394_STATUS_INVALID_BUSGEN
;
2291 return (DDI_FAILURE
);
2294 /* Initialize the private HAL command structure */
2295 hci1394_async_hcicmd_init(async_handle
, cmd
, cmd_priv
, &hcicmd
);
2296 hcicmd
->ac_dest
= (uint_t
)(cmd
->cmd_addr
>> IEEE1394_ADDR_PHY_ID_SHIFT
);
2298 /* allocate a tlabel for this request */
2299 status
= hci1394_tlabel_alloc(async_handle
->as_tlabel
, hcicmd
->ac_dest
,
2300 &hcicmd
->ac_tlabel
);
2301 if (status
!= DDI_SUCCESS
) {
2302 *result
= H1394_STATUS_EMPTY_TLABEL
;
2303 return (DDI_FAILURE
);
2306 /* Register this command w/ its tlabel */
2307 hci1394_tlabel_register(async_handle
->as_tlabel
, &hcicmd
->ac_tlabel
,
2311 * Setup the packet header information for a ATREQ lock packet. Set
2312 * the tcode up as a lock request. Set SRCBusId if this lock is not a
2313 * local bus access. Copy in the speed, tlabel, and destination
2316 header
.q1
= DESC_ATREQ_Q1_LCK
;
2317 if ((hcicmd
->ac_dest
& IEEE1394_BUS_NUM_MASK
) !=
2318 IEEE1394_BUS_NUM_MASK
) {
2319 header
.q1
|= DESC_AT_SRCBUSID
;
2321 header
.q1
|= HCI1394_DESC_AT_SPD_SET(cmd_priv
->speed
) |
2322 HCI1394_DESC_TLABEL_SET(hcicmd
->ac_tlabel
.tbi_tlabel
);
2323 header
.q2
= (uint32_t)(cmd
->cmd_addr
>> 32);
2324 header
.q3
= (uint32_t)(cmd
->cmd_addr
& DESC_PKT_DESTOFFLO_MASK
);
2327 * Setup the lock length based on what size lock operation we are
2328 * performing. If it isn't a lock32 or lock64, we have encountered an
2329 * internal error. Copy the lock data into a local data buffer. Perform
2330 * a byte swap if it is an arithmetic lock operation and we are on a
2331 * little endian machine.
2333 if (cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_32
) {
2334 size
= DESC_TWO_QUADS
;
2335 header
.q4
= HCI1394_DESC_DATALEN_SET(size
) |
2336 HCI1394_DESC_EXTTCODE_SET(cmd
->cmd_u
.l32
.lock_type
);
2337 data32
[0] = HCI1394_ARITH_LOCK_SWAP32(
2338 cmd
->cmd_u
.l32
.lock_type
, cmd
->cmd_u
.l32
.arg_value
);
2339 data32
[1] = HCI1394_ARITH_LOCK_SWAP32(
2340 cmd
->cmd_u
.l32
.lock_type
, cmd
->cmd_u
.l32
.data_value
);
2341 datap
= (uint8_t *)data32
;
2342 } else if (cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_64
) {
2343 size
= DESC_TWO_OCTLETS
;
2344 header
.q4
= HCI1394_DESC_DATALEN_SET(size
) |
2345 HCI1394_DESC_EXTTCODE_SET(cmd
->cmd_u
.l64
.lock_type
);
2346 data64
[0] = HCI1394_ARITH_LOCK_SWAP64(
2347 cmd
->cmd_u
.l64
.lock_type
, cmd
->cmd_u
.l64
.arg_value
);
2348 data64
[1] = HCI1394_ARITH_LOCK_SWAP64(
2349 cmd
->cmd_u
.l64
.lock_type
, cmd
->cmd_u
.l64
.data_value
);
2350 datap
= (uint8_t *)data64
;
2352 *result
= H1394_STATUS_INTERNAL_ERROR
;
2353 return (DDI_FAILURE
);
2356 /* Write request into the ATREQ Q. If we fail, we're out of space */
2357 status
= hci1394_q_at_with_data(async_handle
->as_atreq_q
,
2358 &hcicmd
->ac_qcmd
, &header
, DESC_PKT_HDRLEN_AT_LOCK
, datap
, size
,
2360 if (status
!= DDI_SUCCESS
) {
2361 return (DDI_FAILURE
);
2364 return (DDI_SUCCESS
);
2369 * hci1394_async_write_response()
2370 * Send a write ATRESP. This routine should be called from the Services
2371 * layer to send a response to a received write request (ARREQ). The same
2372 * response is sent to a quadlet and block write request.
2375 hci1394_async_write_response(hci1394_async_handle_t async_handle
,
2376 cmd1394_cmd_t
*cmd
, h1394_cmd_priv_t
*cmd_priv
, int *result
)
2378 hci1394_basic_pkt_t header
;
2380 hci1394_async_cmd_t
*hcicmd
;
2383 ASSERT(async_handle
!= NULL
);
2384 ASSERT(cmd
!= NULL
);
2385 ASSERT(cmd_priv
!= NULL
);
2386 ASSERT(result
!= NULL
);
2389 * make sure this call is during the current bus generation (i.e. no
2390 * bus resets have occured since this request was made.
2392 if (cmd_priv
->bus_generation
!= hci1394_ohci_current_busgen(
2393 async_handle
->as_ohci
)) {
2394 *result
= H1394_STATUS_INVALID_BUSGEN
;
2395 return (DDI_FAILURE
);
2399 * setup a shortcut to the hal private command area. Copy the generation
2400 * to the Q area so that we can check the generation when the AT Q is
2401 * locked. This prevents us from loosing commands due to race
2404 hcicmd
= (hci1394_async_cmd_t
*)cmd_priv
->hal_overhead
;
2405 hcicmd
->ac_qcmd
.qc_generation
= cmd_priv
->bus_generation
;
2408 * Setup the packet header information for a ATRESP write packet. Set
2409 * the tcode for a write response. Set SRCBusId if the addr is not a
2410 * local bus address. Copy in the speed, tlabel, and response code.
2412 header
.q1
= DESC_ATRESP_Q1_WR
;
2413 if ((cmd
->nodeID
& IEEE1394_BUS_NUM_MASK
) != IEEE1394_BUS_NUM_MASK
) {
2414 header
.q1
|= DESC_AT_SRCBUSID
;
2416 header
.q1
|= HCI1394_DESC_AT_SPD_SET(cmd_priv
->speed
) |
2417 HCI1394_DESC_TLABEL_SET(hcicmd
->ac_tlabel
.tbi_tlabel
);
2418 header
.q2
= (HCI1394_DESC_DESTID_SET(cmd
->nodeID
) |
2419 HCI1394_DESC_RCODE_SET(cmd
->cmd_result
));
2422 /* Write response into the ATRESP Q. If we fail, we're out of space */
2423 status
= hci1394_q_at(async_handle
->as_atresp_q
, &hcicmd
->ac_qcmd
,
2424 &header
, DESC_PKT_HDRLEN_AT_WRITE_RESP
, result
);
2425 if (status
!= DDI_SUCCESS
) {
2426 return (DDI_FAILURE
);
2429 return (DDI_SUCCESS
);
2434 * hci1394_async_read_response()
2435 * Send a read ATRESP. This routine should be called from the Services
2436 * layer to send a response to a received read request (ARREQ). The
2437 * response will differ between quadlet/block read requests.
2440 hci1394_async_read_response(hci1394_async_handle_t async_handle
,
2441 cmd1394_cmd_t
*cmd
, h1394_cmd_priv_t
*cmd_priv
, int *result
)
2443 hci1394_basic_pkt_t header
;
2445 hci1394_async_cmd_t
*hcicmd
;
2448 ASSERT(async_handle
!= NULL
);
2449 ASSERT(cmd
!= NULL
);
2450 ASSERT(cmd_priv
!= NULL
);
2451 ASSERT(result
!= NULL
);
2454 * make sure this call is during the current bus generation (i.e. no
2455 * bus resets have occured since this request was made.
2457 if (cmd_priv
->bus_generation
!= hci1394_ohci_current_busgen(
2458 async_handle
->as_ohci
)) {
2459 *result
= H1394_STATUS_INVALID_BUSGEN
;
2460 return (DDI_FAILURE
);
2464 * setup a shortcut to the hal private command area. Copy the generation
2465 * to the Q area so that we can check the generation when the AT Q is
2466 * locked. This prevents us from loosing commands due to race
2469 hcicmd
= (hci1394_async_cmd_t
*)cmd_priv
->hal_overhead
;
2470 hcicmd
->ac_qcmd
.qc_generation
= cmd_priv
->bus_generation
;
2473 * Setup the packet header information for a ATRESP read packet. we
2474 * will set the tcode later based on type of read response. Set
2475 * SRCBusId if the addr is not a local bus address. Copy in the
2476 * speed, tlabel, and response code.
2479 if ((cmd
->nodeID
& IEEE1394_BUS_NUM_MASK
) != IEEE1394_BUS_NUM_MASK
) {
2480 header
.q1
|= DESC_AT_SRCBUSID
;
2482 header
.q1
|= HCI1394_DESC_AT_SPD_SET(cmd_priv
->speed
) |
2483 HCI1394_DESC_TLABEL_SET(hcicmd
->ac_tlabel
.tbi_tlabel
);
2484 header
.q2
= (uint32_t)(HCI1394_DESC_DESTID_SET(cmd
->nodeID
) |
2485 HCI1394_DESC_RCODE_SET(cmd
->cmd_result
));
2488 /* if the response is a read quadlet response */
2489 if (cmd
->cmd_type
== CMD1394_ASYNCH_RD_QUAD
) {
2491 * setup the tcode for a quadlet read response, If the
2492 * response code is not resp complete.
2494 header
.q1
|= DESC_ATRESP_Q1_QRD
;
2495 if (cmd
->cmd_result
== IEEE1394_RESP_COMPLETE
) {
2496 header
.q4
= cmd
->cmd_u
.q
.quadlet_data
;
2502 * Write response into the ATRESP Q. If we fail, we're out of
2505 status
= hci1394_q_at(async_handle
->as_atresp_q
,
2506 &hcicmd
->ac_qcmd
, &header
, DESC_PKT_HDRLEN_AT_READQUAD_RESP
,
2508 if (status
!= DDI_SUCCESS
) {
2509 return (DDI_FAILURE
);
2513 * the response is a block read response. If the result is not a
2514 * resp complete, we are not going to send any data back.
2516 } else if ((cmd
->cmd_type
== CMD1394_ASYNCH_RD_BLOCK
) &&
2517 (cmd
->cmd_result
!= IEEE1394_RESP_COMPLETE
)) {
2519 * Setup the tcode for a block read response, set the data
2520 * length to zero since we had an error.
2522 header
.q1
|= DESC_ATRESP_Q1_BRD
;
2526 * Write response into the ATRESP Q. If we fail, we're out of
2529 status
= hci1394_q_at(async_handle
->as_atresp_q
,
2530 &hcicmd
->ac_qcmd
, &header
,
2531 DESC_PKT_HDRLEN_AT_READBLOCK_RESP
, result
);
2532 if (status
!= DDI_SUCCESS
) {
2533 return (DDI_FAILURE
);
2537 * the response is a block read response with a resp complete for the
2538 * response code. Send back the read data.
2542 * Setup the tcode for a block read response, setup the data
2545 header
.q1
|= DESC_ATRESP_Q1_BRD
;
2546 header
.q4
= HCI1394_DESC_DATALEN_SET(cmd
->cmd_u
.b
.blk_length
);
2549 * Write response into the ATRESP Q. If we fail, we're out of
2550 * space. Use the data in the mblk.
2552 status
= hci1394_q_at_with_mblk(async_handle
->as_atresp_q
,
2553 &hcicmd
->ac_qcmd
, &header
,
2554 DESC_PKT_HDRLEN_AT_READBLOCK_RESP
, &cmd_priv
->mblk
, result
);
2555 if (status
!= DDI_SUCCESS
) {
2556 return (DDI_FAILURE
);
2560 return (DDI_SUCCESS
);
2565 * hci1394_async_lock_response()
2566 * Send a lock ATRESP. This routine should be called from the Services
2567 * layer to send a response to a received lock request (ARREQ). The
2568 * response will differ between 32-bit/64-bit lock requests.
2571 hci1394_async_lock_response(hci1394_async_handle_t async_handle
,
2572 cmd1394_cmd_t
*cmd
, h1394_cmd_priv_t
*cmd_priv
, int *result
)
2574 hci1394_basic_pkt_t header
;
2575 hci1394_async_cmd_t
*hcicmd
;
2583 ASSERT(async_handle
!= NULL
);
2584 ASSERT(cmd
!= NULL
);
2585 ASSERT(cmd_priv
!= NULL
);
2586 ASSERT(result
!= NULL
);
2589 * make sure this call is during the current bus generation (i.e. no
2590 * bus resets have occured since this request was made.
2592 if (cmd_priv
->bus_generation
!= hci1394_ohci_current_busgen(
2593 async_handle
->as_ohci
)) {
2594 *result
= H1394_STATUS_INVALID_BUSGEN
;
2595 return (DDI_FAILURE
);
2599 * setup a shortcut to the hal private command area. Copy the generation
2600 * to the Q area so that we can check the generation when the AT Q is
2601 * locked. This prevents us from loosing commands due to race
2604 hcicmd
= (hci1394_async_cmd_t
*)cmd_priv
->hal_overhead
;
2605 hcicmd
->ac_qcmd
.qc_generation
= cmd_priv
->bus_generation
;
2608 * Setup the packet header information for a ATRESP lock packet. Set
2609 * the tcode for a lock response. Set SRCBusId if the addr is not a
2610 * local bus address. Copy in the speed, tlabel, and response code.
2612 header
.q1
= DESC_ATRESP_Q1_LCK
;
2613 if ((cmd
->nodeID
& IEEE1394_BUS_NUM_MASK
) != IEEE1394_BUS_NUM_MASK
) {
2614 header
.q1
|= DESC_AT_SRCBUSID
;
2616 header
.q1
|= HCI1394_DESC_AT_SPD_SET(cmd_priv
->speed
) |
2617 HCI1394_DESC_TLABEL_SET(hcicmd
->ac_tlabel
.tbi_tlabel
);
2618 header
.q2
= (uint32_t)(HCI1394_DESC_DESTID_SET(cmd
->nodeID
) |
2619 HCI1394_DESC_RCODE_SET(cmd
->cmd_result
));
2623 * If the lock result is not a resp complete, we are not going to send
2624 * any data back.with the response.
2626 if (cmd
->cmd_result
!= IEEE1394_RESP_COMPLETE
) {
2627 /* set response size to 0 for error. Set the extended tcode */
2629 if (cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_32
) {
2630 header
.q4
= HCI1394_DESC_DATALEN_SET(size
) |
2631 HCI1394_DESC_EXTTCODE_SET(cmd
->cmd_u
.l32
.lock_type
);
2633 header
.q4
= HCI1394_DESC_DATALEN_SET(size
) |
2634 HCI1394_DESC_EXTTCODE_SET(cmd
->cmd_u
.l64
.lock_type
);
2638 * Write response into the ATRESP Q. If we fail, we're out of
2641 status
= hci1394_q_at(async_handle
->as_atresp_q
,
2642 &hcicmd
->ac_qcmd
, &header
, DESC_PKT_HDRLEN_AT_LOCK_RESP
,
2644 if (status
!= DDI_SUCCESS
) {
2645 return (DDI_FAILURE
);
2647 return (DDI_SUCCESS
);
2651 * if the lock result is resp complete, setup the size of the response
2652 * depending on the lock size and copy the lock response data into a
2653 * local buffer. If the lock response is an arithmetic operation, swap
2654 * the data on little endian machines. If we don't know what type of
2655 * lock operation it is, someone has corrupted the command since we
2656 * had received the ARREQ.
2658 if (cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_32
) {
2659 size
= IEEE1394_QUADLET
;
2660 header
.q4
= HCI1394_DESC_DATALEN_SET(size
) |
2661 HCI1394_DESC_EXTTCODE_SET(cmd
->cmd_u
.l32
.lock_type
);
2662 data32
= HCI1394_ARITH_LOCK_SWAP32(
2663 cmd
->cmd_u
.l32
.lock_type
, cmd
->cmd_u
.l32
.old_value
);
2664 datap
= (uint8_t *)&data32
;
2665 } else if (cmd
->cmd_type
== CMD1394_ASYNCH_LOCK_64
) {
2666 size
= IEEE1394_OCTLET
;
2667 header
.q4
= HCI1394_DESC_DATALEN_SET(size
) |
2668 HCI1394_DESC_EXTTCODE_SET(cmd
->cmd_u
.l64
.lock_type
);
2669 data64
= HCI1394_ARITH_LOCK_SWAP64(
2670 cmd
->cmd_u
.l64
.lock_type
, cmd
->cmd_u
.l64
.old_value
);
2671 datap
= (uint8_t *)&data64
;
2673 *result
= H1394_STATUS_INTERNAL_ERROR
;
2674 return (DDI_FAILURE
);
2678 * Write response into the ATRESP Q. If we fail, we're out of space.
2679 * Use the local data buffer that we copied the data to above.
2681 status
= hci1394_q_at_with_data(async_handle
->as_atresp_q
,
2682 &hcicmd
->ac_qcmd
, &header
, DESC_PKT_HDRLEN_AT_LOCK_RESP
, datap
,
2684 if (status
!= DDI_SUCCESS
) {
2685 return (DDI_FAILURE
);
2688 return (DDI_SUCCESS
);
2693 * hci1394_async_response_complete()
2694 * Free up space allocted during an ARREQ. This is called when the target
2695 * driver and Services Layer are done with a command which was by the HAL
2696 * during ARREQ processing. This routine will also free up any allocated
2699 * NOTE: a target driver can hold on to a block write ARREQ mblk by setting
2700 * the mblk pointer to NULL. This ONLY applies to block write ARREQs. The
2701 * HAL will no longer track the mblk for this case.
2704 hci1394_async_response_complete(hci1394_async_handle_t async_handle
,
2705 cmd1394_cmd_t
*cmd
, h1394_cmd_priv_t
*cmd_priv
)
2707 hci1394_async_cmd_t
*hcicmd
;
2710 ASSERT(async_handle
!= NULL
);
2711 ASSERT(cmd
!= NULL
);
2712 ASSERT(cmd_priv
!= NULL
);
2714 hcicmd
= (hci1394_async_cmd_t
*)cmd_priv
->hal_overhead
;
2716 /* If we allocated an mblk for this command */
2717 if (hcicmd
->ac_mblk_alloc
== B_TRUE
) {
2719 * Don't free mblk if it is set to NULL. This allows a target
2720 * driver to hold on to it in the case of a block write ARREQ.
2722 if (cmd
->cmd_u
.b
.data_block
!= NULL
) {
2723 freeb(cmd
->cmd_u
.b
.data_block
);
2727 /* free up the 1394 framework command */
2728 (void) h1394_free_cmd((void *)async_handle
->as_drvinfo
->di_sl_private
,
2734 * hci1394_async_pending_timeout()
2735 * This is the ARREQ Pending timeout callback routine. It is called from
2736 * the tlist code. There is a race condition with the ARRESP interrupt
2737 * handler (hci1394_async_arresp_process) which requires a mutex to
2738 * lock around the mark of the bad tlabel.
2740 * Once we enter this routine, the command has timed out. If the command is
2741 * in both the ARRESP handler and here, we will consider it to have timed
2742 * out. That code path handles the race condition more easily.
2745 hci1394_async_pending_timeout(hci1394_tlist_node_t
*node
, void *arg
)
2747 hci1394_async_handle_t async_handle
;
2748 hci1394_async_cmd_t
*hcicmd
;
2751 async_handle
= (hci1394_async_handle_t
)arg
;
2752 ASSERT(async_handle
!= NULL
);
2753 ASSERT(node
!= NULL
);
2755 hcicmd
= (hci1394_async_cmd_t
*)node
->tln_addr
;
2758 * We do NOT want to set the command state here. That should only be
2759 * done in the ISR. The state does nothing for us here.
2763 * We want a lock around tlabel_lookup/reading data into the cmd in the
2764 * ARRESP ISR processing and a lock around the tlabel_bad in this
2765 * routine. This ensures that we will not be touching the command
2766 * structure after we pass it up to the Services Layer. If we mark it as
2767 * bad first, the lookup will fail. If we get to the lookup first, the
2768 * pending list delete will fail in arresp_process() which will tell
2769 * that guy that we are in the middle of doing the timeout processing
2770 * for this command. The ARRESP logic will just drop the response and
2773 mutex_enter(&hcicmd
->ac_async
->as_atomic_lookup
);
2774 hci1394_tlabel_bad(async_handle
->as_tlabel
, &hcicmd
->ac_tlabel
);
2775 mutex_exit(&hcicmd
->ac_async
->as_atomic_lookup
);
2777 /* Tell the Services Layer that the command has timed out */
2778 h1394_cmd_is_complete(async_handle
->as_drvinfo
->di_sl_private
,
2779 hcicmd
->ac_cmd
, H1394_AT_REQ
, H1394_CMD_ETIMEOUT
);
2784 * hci1394_async_timeout_calc()
2785 * Calculate the timeout for an ATRESP. When an ARREQ is received, this
2786 * routine is called with the time the ARREQ was received. It returns the
2787 * time when the ATRESP is considered to have timed out. We timeout after
2788 * split_timeout has gone by. Split timeout and the returned value are in bus
2792 hci1394_async_timeout_calc(hci1394_async_handle_t async_handle
,
2793 uint_t current_time
)
2795 uint_t split_timeout
;
2800 /* Get the current split timeout */
2801 split_timeout
= hci1394_csr_split_timeout_get(async_handle
->as_csr
);
2804 * The cycle count is broken up into two sections, the 3-bit seconds
2805 * field and the 13-bit cycle count. The cycle count is in 125uS
2806 * increments. The maximum value of cycle count is 7999 (8000 is one
2807 * second). With 13-bits, we could store up to 8191. Therefore, we don't
2808 * have a simple 16-bit addition. Hence, the code we see below.
2812 * calculate the new cycle count based on the cycle count from current
2813 * time and the split timeout. If this new value is not greater than the
2814 * maximum cycle count, we don't have a carry. Go to the next step.
2816 temp
= (current_time
& OHCI_CYCLE_CNT_MASK
) + (split_timeout
&
2817 OHCI_CYCLE_CNT_MASK
);
2818 if (temp
< OHCI_MAX_CYCLE_CNT
) {
2822 * the new cycle count adds up to more than the maximum cycle count,
2823 * set the carry state and adjust the total accordingly.
2826 temp
= temp
- OHCI_MAX_CYCLE_CNT
;
2831 * The timeout time equals the seconds added with the carry (1 or 0
2832 * seconds), added with the adjusted (if necessary) cycle count.
2833 * Mask the final value to get rid of any second rollovers.
2835 z
= (current_time
& OHCI_CYCLE_SEC_MASK
) + (split_timeout
&
2836 OHCI_CYCLE_SEC_MASK
) + (carry
<< OHCI_CYCLE_SEC_SHIFT
) + temp
;
2837 z
= z
& OHCI_TIMESTAMP_MASK
;
2844 * hci1394_async_arresp_size_get()
2845 * Return the size of the arresp that was received in q_handle at addr.
2848 hci1394_async_arresp_size_get(uint_t tcode
, hci1394_q_handle_t q_handle
,
2849 uint32_t *addr
, uint_t
*size
)
2855 ASSERT(q_handle
!= NULL
);
2856 ASSERT(addr
!= NULL
);
2857 ASSERT(size
!= NULL
);
2859 if (tcode
== IEEE1394_TCODE_WRITE_RESP
) {
2860 *size
= DESC_PKT_HDRLEN_AT_WRITE_RESP
+ IEEE1394_QUADLET
;
2861 } else if (tcode
== IEEE1394_TCODE_READ_QUADLET_RESP
) {
2862 *size
= DESC_PKT_HDRLEN_AT_READQUAD_RESP
+ IEEE1394_QUADLET
;
2863 } else if (tcode
== IEEE1394_TCODE_READ_BLOCK_RESP
) {
2864 quadlet
= hci1394_q_ar_get32(q_handle
, &addr
[3]);
2865 data_length
= HCI1394_DESC_DATALEN_GET(quadlet
);
2867 * response size is in quadlets, therefore we need to
2868 * make sure we count in the padding when figuring out
2869 * the size used up for this response
2871 *size
= DESC_PKT_HDRLEN_AT_READBLOCK_RESP
+
2872 HCI1394_ALIGN_QUAD(data_length
) + IEEE1394_QUADLET
;
2873 } else if (tcode
== IEEE1394_TCODE_LOCK_RESP
) {
2874 quadlet
= hci1394_q_ar_get32(q_handle
, &addr
[3]);
2875 data_length
= HCI1394_DESC_DATALEN_GET(quadlet
);
2877 * response size is in quadlets, therefore we need to
2878 * make sure we count in the padding when figuring out
2879 * the size used up for this response
2881 *size
= DESC_PKT_HDRLEN_AT_LOCK_RESP
+
2882 HCI1394_ALIGN_QUAD(data_length
) + IEEE1394_QUADLET
;
2884 return (DDI_FAILURE
);
2887 return (DDI_SUCCESS
);
2892 * hci1394_async_pending_list_flush()
2893 * Flush out the ATREQ pending list. All commands still on the ATREQ pending
2894 * list are considered to be completed due to a bus reset. The ATREQ and
2895 * ARRESP Q's should be flushed before the pending Q is flushed. The ATREQ
2896 * could have more ACK pendings and the ARRESP could have valid responses to
2900 hci1394_async_pending_list_flush(hci1394_async_handle_t async_handle
)
2902 hci1394_tlist_node_t
*node
;
2903 hci1394_async_cmd_t
*hcicmd
;
2906 ASSERT(async_handle
!= NULL
);
2910 * get the first node on the pending list. This routine also
2911 * removes the node from the list.
2913 hci1394_tlist_get(async_handle
->as_pending_list
, &node
);
2915 /* set the command state to completed */
2916 hcicmd
= (hci1394_async_cmd_t
*)node
->tln_addr
;
2917 hcicmd
->ac_state
= HCI1394_CMD_STATE_COMPLETED
;
2920 * Send the command up to the Services Layer with
2921 * completed due to the bus reset for status.
2923 h1394_cmd_is_complete(
2924 async_handle
->as_drvinfo
->di_sl_private
,
2925 hcicmd
->ac_cmd
, H1394_AT_REQ
,
2926 H1394_CMD_EBUSRESET
);
2928 } while (node
!= NULL
);
2933 * hci1394_async_atreq_start()
2934 * Setup the command pointer for the first descriptor to be fetched and
2935 * then set the run bit. This routine will be called the first time
2936 * a descriptor is added to the Q.
2939 hci1394_async_atreq_start(void *async
, uint32_t command_ptr
)
2941 hci1394_async_handle_t async_handle
;
2942 ASSERT(async
!= NULL
);
2943 async_handle
= (hci1394_async_handle_t
)async
;
2944 hci1394_ohci_atreq_start(async_handle
->as_ohci
, command_ptr
);
2949 * hci1394_async_atreq_wake()
2950 * Set the wake bit for the ATREQ DMA engine. This routine will be called
2951 * from the Q logic after placing a descriptor on the Q.
2954 hci1394_async_atreq_wake(void *async
)
2956 hci1394_async_handle_t async_handle
;
2957 ASSERT(async
!= NULL
);
2958 async_handle
= (hci1394_async_handle_t
)async
;
2959 hci1394_ohci_atreq_wake(async_handle
->as_ohci
);
2964 * hci1394_async_atreq_reset()
2965 * Reset the atreq Q. The AT DMA engines must be stopped every bus reset.
2966 * They will restart when the next descriptor is added to the Q. We will stop
2967 * the DMA engine and then notify the Q logic that it has been stopped so it
2968 * knows to do a start next time it puts a descriptor on the Q.
2971 hci1394_async_atreq_reset(hci1394_async_handle_t async_handle
)
2973 ASSERT(async_handle
!= NULL
);
2974 hci1394_ohci_atreq_stop(async_handle
->as_ohci
);
2975 hci1394_q_stop(async_handle
->as_atreq_q
);
2980 * hci1394_async_atreq_flush()
2981 * Flush out the atreq Q. This routine is called during bus reset processing.
2982 * it should be called before arresp_flush() and pending_list_flush().
2985 hci1394_async_atreq_flush(hci1394_async_handle_t async_handle
)
2987 boolean_t request_available
;
2990 ASSERT(async_handle
!= NULL
);
2992 /* Clear reqTxComplete interrupt */
2993 hci1394_ohci_intr_clear(async_handle
->as_ohci
, OHCI_INTR_REQ_TX_CMPLT
);
2996 * Processes all Q'd AT requests. If the request is pended, it is
2997 * considered complete relative the the atreq engine.
2998 * flush_pending_list() will finish up the required processing for
3002 /* Flush the atreq Q. Process all Q'd commands */
3003 status
= hci1394_async_atreq_process(async_handle
,
3004 B_TRUE
, &request_available
);
3005 if (status
!= DDI_SUCCESS
) {
3007 } while (request_available
== B_TRUE
);
3012 * hci1394_async_arresp_start()
3013 * Setup the command pointer for the first descriptor to be fetched and
3014 * then set the run bit. This routine will be called the first time
3015 * a descriptor is added to the Q.
3018 hci1394_async_arresp_start(void *async
, uint32_t command_ptr
)
3020 hci1394_async_handle_t async_handle
;
3021 ASSERT(async
!= NULL
);
3022 async_handle
= (hci1394_async_handle_t
)async
;
3023 hci1394_ohci_arresp_start(async_handle
->as_ohci
, command_ptr
);
3028 * hci1394_async_arresp_wake()
3029 * Set the wake bit for the ARRESP DMA engine. This routine will be called
3030 * from the Q logic after placing a descriptor on the Q.
3033 hci1394_async_arresp_wake(void *async
)
3035 hci1394_async_handle_t async_handle
;
3036 ASSERT(async
!= NULL
);
3037 async_handle
= (hci1394_async_handle_t
)async
;
3038 hci1394_ohci_arresp_wake(async_handle
->as_ohci
);
3043 * hci1394_async_arresp_flush()
3044 * Flush out the arresp Q. This routine is called during bus reset
3045 * processing. This should be called before pending_list_flush(). All
3046 * receive responses will be processed normally. The tlabels should
3047 * not be reset until after the ARRESP Q has been flushed. Otherwise
3048 * we would reject valid responses.
3051 hci1394_async_arresp_flush(hci1394_async_handle_t async_handle
)
3053 boolean_t response_available
;
3057 ASSERT(async_handle
!= NULL
);
3059 /* Clear reqTxComplete interrupt */
3060 hci1394_ohci_intr_clear(async_handle
->as_ohci
, OHCI_INTR_RSPKT
);
3063 /* Flush the arresp Q. Process all received commands */
3064 status
= hci1394_async_arresp_process(async_handle
,
3065 &response_available
);
3066 if (status
!= DDI_SUCCESS
) {
3068 } while (response_available
== B_TRUE
);
3073 * hci1394_async_arreq_start()
3074 * Setup the command pointer for the first descriptor to be fetched and
3075 * then set the run bit. This routine will be called the first time
3076 * a descriptor is added to the Q.
3079 hci1394_async_arreq_start(void *async
, uint32_t command_ptr
)
3081 hci1394_async_handle_t async_handle
;
3082 ASSERT(async
!= NULL
);
3083 async_handle
= (hci1394_async_handle_t
)async
;
3084 hci1394_ohci_arreq_start(async_handle
->as_ohci
, command_ptr
);
3089 * hci1394_async_arreq_wake()
3090 * Set the wake bit for the ARREQ DMA engine. This routine will be called
3091 * from the Q logic after placing a descriptor on the Q.
3094 hci1394_async_arreq_wake(void *async
)
3096 hci1394_async_handle_t async_handle
;
3097 ASSERT(async
!= NULL
);
3098 async_handle
= (hci1394_async_handle_t
)async
;
3099 hci1394_ohci_arreq_wake(async_handle
->as_ohci
);
3104 * hci1394_async_arreq_flush()
3105 * Flush the ARREQ Q. This will flush up to the bus reset token in the
3106 * ARREQ. There is no order dependency for when routine should get called
3107 * (relative to the other Q flushing routines)
3110 hci1394_async_arreq_flush(hci1394_async_handle_t async_handle
)
3112 boolean_t request_available
;
3116 ASSERT(async_handle
!= NULL
);
3119 * If the last bus reset token we have seen in
3120 * hci1394_async_arreq_read_phy() matches the current generation, the
3121 * ARREQ is already flushed. We have nothing further to do here so
3122 * return. This can happen if we are processing ARREQ's and a bus reset
3123 * occurs. Since we are already in the ISR, we will see the token before
3124 * the bus reset handler gets to run.
3126 if (async_handle
->as_phy_reset
== hci1394_ohci_current_busgen(
3127 async_handle
->as_ohci
)) {
3132 * set flag to tell hci1394_async_arreq_process() that we should not
3133 * pass ARREQ's up to the Services Layer. This will be set to B_FALSE
3134 * in hci1394_async_arreq_read_phy() when a bus reset token matching
3135 * the current generation is found.
3137 async_handle
->as_flushing_arreq
= B_TRUE
;
3140 * Process all requests that have been received or until we find the
3141 * correct bus reset token.
3144 status
= hci1394_async_arreq_process(async_handle
,
3145 &request_available
);
3146 if (status
!= DDI_SUCCESS
) {
3148 } while ((request_available
== B_TRUE
) &&
3149 (async_handle
->as_flushing_arreq
== B_TRUE
));
3152 * Clear the asserted interrupt if there are no more ARREQ's to process.
3153 * We could have ARREQ's in the Q after the bus reset token since we
3154 * will set as_flushing_arreq to FALSE when we see the correct bus reset
3155 * token in hci1394_async_arreq_read_phy(). If there are more ARREQ's,
3156 * we will process them later after finishing the reset of bus reset
3157 * processing. That is why we will leave the interrupt asserted.
3159 if (request_available
== B_FALSE
) {
3160 hci1394_ohci_intr_clear(async_handle
->as_ohci
, OHCI_INTR_RQPKT
);
3166 * hci1394_async_atresp_start()
3167 * Setup the command pointer for the first descriptor to be fetched and
3168 * then set the run bit. This routine will be called the first time
3169 * a descriptor is added to the Q.
3172 hci1394_async_atresp_start(void *async
, uint32_t command_ptr
)
3174 hci1394_async_handle_t async_handle
;
3175 ASSERT(async
!= NULL
);
3176 async_handle
= (hci1394_async_handle_t
)async
;
3177 hci1394_ohci_atresp_start(async_handle
->as_ohci
, command_ptr
);
3182 * hci1394_async_atresp_wake()
3183 * Set the wake bit for the ATRESP DMA engine. This routine will be called
3184 * from the Q logic after placing a descriptor on the Q.
3187 hci1394_async_atresp_wake(void *async
)
3189 hci1394_async_handle_t async_handle
;
3190 ASSERT(async
!= NULL
);
3191 async_handle
= (hci1394_async_handle_t
)async
;
3192 hci1394_ohci_atresp_wake(async_handle
->as_ohci
);
3197 * hci1394_async_atresp_reset()
3198 * Reset the atresp Q. The AT DMA engines must be stopped every bus reset.
3199 * They will restart when the next descriptor is added to the Q. We will stop
3200 * the DMA engine and then notify the Q logic that it has been stopped so it
3201 * knows to do a start next time it puts a descriptor on the Q.
3204 hci1394_async_atresp_reset(hci1394_async_handle_t async_handle
)
3206 ASSERT(async_handle
!= NULL
);
3207 hci1394_ohci_atresp_stop(async_handle
->as_ohci
);
3208 hci1394_q_stop(async_handle
->as_atresp_q
);
3213 * hci1394_async_atresp_flush()
3214 * Flush all commands out of the atresp Q. This routine will be called
3215 * during bus reset processing. There is no order dependency for when
3216 * routine should get called (relative to the other Q flushing routines)
3219 hci1394_async_atresp_flush(hci1394_async_handle_t async_handle
)
3221 boolean_t response_available
;
3224 ASSERT(async_handle
!= NULL
);
3226 /* Clear respTxComplete interrupt */
3227 hci1394_ohci_intr_clear(async_handle
->as_ohci
, OHCI_INTR_RESP_TX_CMPLT
);
3229 /* Processes all AT responses */
3231 /* Flush the atresp Q. Process all Q'd commands */
3232 status
= hci1394_async_atresp_process(async_handle
,
3233 B_TRUE
, &response_available
);
3234 } while (response_available
== B_TRUE
);
3238 * hci1394_async_hcicmd_init()
3239 * Initialize the private HAL command structure. This should be called from
3240 * ATREQ and ARREQ routines.
3243 hci1394_async_hcicmd_init(hci1394_async_handle_t async_handle
,
3244 cmd1394_cmd_t
*cmd
, h1394_cmd_priv_t
*cmd_priv
,
3245 hci1394_async_cmd_t
**hcicmd
)
3247 *hcicmd
= (hci1394_async_cmd_t
*)cmd_priv
->hal_overhead
;
3248 (*hcicmd
)->ac_cmd
= cmd
;
3249 (*hcicmd
)->ac_priv
= cmd_priv
;
3250 (*hcicmd
)->ac_async
= async_handle
;
3251 (*hcicmd
)->ac_state
= HCI1394_CMD_STATE_IN_PROGRESS
;
3252 (*hcicmd
)->ac_dest
= 0;
3253 (*hcicmd
)->ac_tlabel_alloc
= B_TRUE
;
3254 (*hcicmd
)->ac_tlabel
.tbi_tlabel
= 0;
3255 (*hcicmd
)->ac_tlabel
.tbi_destination
= 0;
3256 (*hcicmd
)->ac_status
= 0;
3257 (*hcicmd
)->ac_qcmd
.qc_timestamp
= 0;
3258 (*hcicmd
)->ac_qcmd
.qc_arg
= *hcicmd
;
3259 (*hcicmd
)->ac_qcmd
.qc_generation
= cmd_priv
->bus_generation
;
3260 (*hcicmd
)->ac_mblk_alloc
= B_FALSE
;