1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1999-2000 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #ifndef _SYS_1394_ADAPTERS_HCI1394_ASYNC_H 28 #define _SYS_1394_ADAPTERS_HCI1394_ASYNC_H 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 /* 33 * hci1394_async.h 34 * These routines the 1394 asynchronous dma engines. These include incoming 35 * and outgoing reads, writes, and lock and their associated responses. 36 */ 37 38 #ifdef __cplusplus 39 extern "C" { 40 #endif 41 42 #include <sys/ddi.h> 43 #include <sys/modctl.h> 44 #include <sys/sunddi.h> 45 #include <sys/types.h> 46 47 #include <sys/1394/h1394.h> 48 49 #include <sys/1394/adapters/hci1394_def.h> 50 #include <sys/1394/adapters/hci1394_tlist.h> 51 #include <sys/1394/adapters/hci1394_q.h> 52 53 54 /* 55 * Async descriptor and data buffer sizes. The AR descriptor buffers do not need 56 * to be very big. There will be 1 16 byte IM for every AR data buffer. If we 57 * alloc a 16KByte ARRESP data buffer on X86, we could get 4 4KByte cookies. 58 * This would use up 64 bytes in the descriptor buffer. We will never need more 59 * space than that. A 256 byte descriptor should handle a 64K buffer on x86 60 * if it is broken into 16 cookies. 61 */ 62 #define ASYNC_ATREQ_DESC_SIZE 16384 63 #define ASYNC_ATREQ_DATA_SIZE 16384 64 #define ASYNC_ARRESP_DESC_SIZE 256 65 #define ASYNC_ARRESP_DATA_SIZE 16384 66 #define ASYNC_ARREQ_DESC_SIZE 256 67 #define ASYNC_ARREQ_DATA_SIZE 16384 68 #define ASYNC_ATRESP_DESC_SIZE 16384 69 #define ASYNC_ATRESP_DATA_SIZE 16384 70 71 72 /* handle passed back from init() and used for rest of functions */ 73 typedef struct hci1394_async_s *hci1394_async_handle_t; 74 75 /* 76 * Async Command State. This state is used to catch a race condition between 77 * the ATREQ complete interrupt handler and the ARRESP interrupt handler. The 78 * ATREQ will always complete before the ARRESP arrives, but SW may not see it 79 * that way. See hci1394_async_atreq_process() for more information on this. 80 */ 81 typedef enum { 82 HCI1394_CMD_STATE_IN_PROGRESS, 83 HCI1394_CMD_STATE_PENDING, 84 HCI1394_CMD_STATE_COMPLETED 85 } hci1394_async_cstate_t; 86 87 88 typedef struct hci1394_async_cmd_s { 89 /* Pointer to framework command allocted by services layer */ 90 cmd1394_cmd_t *ac_cmd; 91 92 /* 93 * Pointer to HAL/SL private area in the command. This is private info 94 * shared between the HAL and Services Layer on a per command basis. 95 */ 96 h1394_cmd_priv_t *ac_priv; 97 98 /* 99 * Status on if we allocated a tlabel for an ATREQ. Normally we will 100 * allocate a tlabel with every ATREQ. But, we will not allocate a 101 * tlabel for a PHY packet. When we initialize the command, we will 102 * assume that we are going to allocate a tlabel. The async phy command 103 * will "override" this setting and set ac_tlabel_alloc to b_false. 104 */ 105 boolean_t ac_tlabel_alloc; 106 107 /* handle for tlabel logic */ 108 hci1394_tlabel_info_t ac_tlabel; 109 110 /* 111 * This is used for ARREQs. When we get a block read or write request, 112 * we allocate a mblk to put the data into. After the ATRESP has been 113 * sent out and has completed, hci1394_async_response_complete() is 114 * called to free up the ARREQ resources which were allocated. This 115 * routine will free the mblk if we allocated it in ARREQ. If an ARREQ 116 * block write is received and the target driver wishes to keep the 117 * mblk w/ the data (to pass it up a stream), but releases the command, 118 * it can set the mblk pointer in the command to null. We will check 119 * for mblk being == to NULL even if ac_mblk_alloc is set to true. 120 */ 121 boolean_t ac_mblk_alloc; 122 123 /* 124 * ac_status contains the 1394 RESP for an ARRESP or the ACK for ARREQ. 125 * This status is set in either hci1394_async_arresp_read() or 126 * hci1394_arreq_read() 127 */ 128 int ac_status; 129 130 /* 131 * Destination packet was sent to. This is used to determine if the 132 * packet was broadcast or not in hci1394_async_arreq_read(). 133 */ 134 uint_t ac_dest; 135 136 /* 137 * Async command state. See comments above for more information. Other 138 * than initialization, this field is only accessed in the ISR. State 139 * is only used in ATREQ/ARRESP processing. 140 */ 141 hci1394_async_cstate_t ac_state; 142 143 /* 144 * Pointer back to the Async private state. This allows us to access 145 * the async state structures if all we have is a pointer to the async 146 * command. 147 */ 148 struct hci1394_async_s *ac_async; 149 150 /* 151 * pending list node structure. If a command is pended, this node is 152 * what's passed to the tlist code to add the node to the pending list. 153 * It contains all the pointers the linked list needs so that we do not 154 * need to allocate any space every time we add something to the list. 155 */ 156 hci1394_tlist_node_t ac_plist_node; 157 158 /* 159 * hci1394_q information about this command. This is used for AT 160 * commands. It contains information passed down to the hci1394_q_at*() 161 * routines like qc_timestamp which is used to tell the HW when an 162 * ATRESP has timed out out. The status of the AT command is returned 163 * in qc_status after calling hci1394_q_at_next(). The rest of the 164 * structure members are private members used to track the descriptor 165 * and data buffer usage. 166 */ 167 hci1394_q_cmd_t ac_qcmd; 168 } hci1394_async_cmd_t; 169 170 _NOTE(SCHEME_PROTECTS_DATA("Used only by one thread", hci1394_async_cmd_s \ 171 hci1394_async_cmd_s::ac_qcmd.qc_arg \ 172 hci1394_async_cmd_s::ac_qcmd.qc_generation \ 173 hci1394_async_cmd_s::ac_qcmd.qc_timestamp \ 174 hci1394_async_cmd_s::ac_tlabel_alloc \ 175 hci1394_async_cmd_s::ac_tlabel.tbi_destination \ 176 hci1394_async_cmd_s::ac_tlabel.tbi_tlabel)) 177 178 /* 179 * async private state information. It contains handles for the various modules 180 * that async uses. 181 */ 182 typedef struct hci1394_async_s { 183 hci1394_tlist_handle_t as_pending_list; 184 hci1394_ohci_handle_t as_ohci; 185 hci1394_tlabel_handle_t as_tlabel; 186 hci1394_csr_handle_t as_csr; 187 hci1394_q_handle_t as_atreq_q; 188 hci1394_q_handle_t as_arresp_q; 189 hci1394_q_handle_t as_arreq_q; 190 hci1394_q_handle_t as_atresp_q; 191 hci1394_drvinfo_t *as_drvinfo; 192 193 /* 194 * as_flushing_arreq is used in bus reset processing. It is set by 195 * hci1394_async_arreq_flush() and tells hci1394_async_arreq_process() 196 * not to send the ARREQ up to the Services Layer. It will be set to 197 * FALSE by hci1394_async_arreq_read_phy() when a bus reset token with 198 * the current bus generation is found. as_phy_reset is used to store 199 * the last PHY packet generation seen in the ARREQ Q. The HW puts a 200 * token in the ARREQ Q so that the SW can flush the Q up to and 201 * including the token. 202 */ 203 boolean_t as_flushing_arreq; 204 uint_t as_phy_reset; 205 206 /* 207 * as_atomic_lookup is used to protect the cmd from a race condition 208 * between the ARRESP and the Pending Timeout callback. This is 209 * explained in more detail in hci1394_async_atreq_process(). 210 */ 211 kmutex_t as_atomic_lookup; 212 } hci1394_async_t; 213 214 _NOTE(SCHEME_PROTECTS_DATA("Used only by one thread", \ 215 hci1394_async_s::as_flushing_arreq hci1394_async_s::as_phy_reset)) 216 217 int hci1394_async_init(hci1394_drvinfo_t *drvinfo, 218 hci1394_ohci_handle_t ohci_handle, hci1394_csr_handle_t csr_handle, 219 hci1394_async_handle_t *async_handle); 220 void hci1394_async_fini(hci1394_async_handle_t *async_handle); 221 void hci1394_async_suspend(hci1394_async_handle_t async_handle); 222 int hci1394_async_resume(hci1394_async_handle_t async_handle); 223 uint_t hci1394_async_cmd_overhead(); 224 225 void hci1394_async_flush(hci1394_async_handle_t async_handle); 226 void hci1394_async_atreq_reset(hci1394_async_handle_t async_handle); 227 void hci1394_async_atresp_reset(hci1394_async_handle_t async_handle); 228 void hci1394_async_pending_timeout_update(hci1394_async_handle_t async_handle, 229 hrtime_t timeout); 230 231 int hci1394_async_atreq_process(hci1394_async_handle_t async_handle, 232 boolean_t flush_q, boolean_t *request_available); 233 int hci1394_async_arresp_process(hci1394_async_handle_t async_handle, 234 boolean_t *response_available); 235 int hci1394_async_arreq_process(hci1394_async_handle_t async_handle, 236 boolean_t *request_available); 237 int hci1394_async_atresp_process(hci1394_async_handle_t async_handle, 238 boolean_t flush_q, boolean_t *response_available); 239 240 int hci1394_async_phy(hci1394_async_handle_t async_handle, 241 cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result); 242 int hci1394_async_write(hci1394_async_handle_t async_handle, 243 cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result); 244 int hci1394_async_read(hci1394_async_handle_t async_handle, 245 cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result); 246 int hci1394_async_lock(hci1394_async_handle_t async_handle, 247 cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result); 248 int hci1394_async_write_response(hci1394_async_handle_t async_handle, 249 cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result); 250 int hci1394_async_read_response(hci1394_async_handle_t async_handle, 251 cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result); 252 int hci1394_async_lock_response(hci1394_async_handle_t async_handle, 253 cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result); 254 void hci1394_async_response_complete(hci1394_async_handle_t async_handle, 255 cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv); 256 257 258 #ifdef __cplusplus 259 } 260 #endif 261 262 #endif /* _SYS_1394_ADAPTERS_HCI1394_ASYNC_H */ 263