1 /* $NetBSD: isp_tpublic.h,v 1.17 2008/05/11 02:08:11 mjacob Exp $ */
2 /*-
3 * Copyright (c) 1997-2008 by Matthew Jacob
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28 /*
29 * Host Adapter Public Target Interface Structures && Routines
30 */
31 /*
32 * A note about terminology:
33 *
34 * "Inner Layer" means this driver (isp and the isp_tpublic API).
35 *
36 * This module includes the both generic and platform specific pieces.
37 *
38 * "Outer Layer" means another (external) module.
39 *
40 * This is an additional module that actually implements SCSI target command
41 * decode and is the recipient of incoming commands and the source of the
42 * disposition for them.
43 */
44
45 #ifndef _ISP_TPUBLIC_H
46 #define _ISP_TPUBLIC_H 1
47
48 /*
49 * Action codes set by the Inner Layer for the outer layer to figure out what to do with.
50 */
51 typedef enum {
52 QOUT_HBA_REG=0, /* the argument is a pointer to a hba_register_t */
53 QOUT_ENABLE, /* the argument is a pointer to a enadis_t */
54 QOUT_DISABLE, /* the argument is a pointer to a enadis_t */
55 QOUT_TMD_START, /* the argument is a pointer to a tmd_cmd_t */
56 QOUT_TMD_DONE, /* the argument is a pointer to a tmd_xact_t */
57 QOUT_NOTIFY, /* the argument is a pointer to a tmd_notify_t */
58 QOUT_HBA_UNREG /* the argument is a pointer to a hba_register_t */
59 } tact_e;
60
61 /*
62 * Action codes set by the outer layer for the
63 * inner layer to figure out what to do with.
64 */
65 typedef enum {
66 QIN_HBA_REG=99, /* the argument is a pointer to a hba_register_t */
67 QIN_GETINFO, /* the argument is a pointer to a info_t */
68 QIN_SETINFO, /* the argument is a pointer to a info_t */
69 QIN_GETDLIST, /* the argument is a pointer to a fc_dlist_t */
70 QIN_ENABLE, /* the argument is a pointer to a enadis_t */
71 QIN_DISABLE, /* the argument is a pointer to a enadis_t */
72 QIN_TMD_CONT, /* the argument is a pointer to a tmd_xact_t */
73 QIN_TMD_FIN, /* the argument is a pointer to a tmd_cmd_t */
74 QIN_NOTIFY_ACK, /* the argument is a pointer to a tmd_notify_t */
75 QIN_HBA_UNREG, /* the argument is a pointer to a hba_register_t */
76 } qact_e;
77
78 /*
79 * This structure is used to register to the outer layer the
80 * binding of an HBA identifier, driver name and instance and the
81 * lun width capapbilities of this inner layer. It's up to each
82 * platform to figure out how it wants to actually implement this.
83 * A typical sequence would be for the MD layer to find some external
84 * module's entry point and start by sending a QOUT_HBA_REG with info
85 * filled in, and the external module to call back with a QIN_HBA_REG
86 * that passes back the corresponding information.
87 *
88 * The r_version tag defines the version of this API.
89 */
90 #define QR_VERSION 20
91 typedef struct {
92 /* NB: structure tags from here to r_version must never change */
93 void * r_identity;
94 void (*r_action)(qact_e, void *);
95 char r_name[8];
96 int r_inst;
97 int r_version;
98 uint32_t r_locator;
99 uint32_t r_nchannels;
100 enum { R_FC, R_SPI } r_type;
101 void * r_private;
102 } hba_register_t;
103
104 /*
105 * An information structure that is used to get or set per-channel transport layer parameters.
106 */
107 typedef struct {
108 void * i_identity;
109 enum { I_FC, I_SPI } i_type;
110 int i_channel;
111 int i_error;
112 union {
113 struct {
114 uint64_t wwnn_nvram;
115 uint64_t wwpn_nvram;
116 uint64_t wwnn;
117 uint64_t wwpn;
118 } fc;
119 struct {
120 int iid;
121 } spi;
122 } i_id;
123 } info_t;
124
125 /*
126 * An information structure to return a list of logged in WWPNs. FC specific.
127 */
128 typedef struct {
129 void * d_identity;
130 int d_channel;
131 int d_error;
132 int d_count;
133 uint64_t * d_wwpns;
134 } fc_dlist_t;
135
136 /*
137 * Notify structure- these are for asynchronous events that need to be sent
138 * as notifications to the outer layer. It should be pretty self-explanatory.
139 */
140 typedef enum {
141 NT_UNKNOWN=0x999,
142 NT_ABORT_TASK=0x1000,
143 NT_ABORT_TASK_SET,
144 NT_CLEAR_ACA,
145 NT_CLEAR_TASK_SET,
146 NT_LUN_RESET,
147 NT_TARGET_RESET,
148 NT_BUS_RESET,
149 NT_LIP_RESET,
150 NT_LINK_UP,
151 NT_LINK_DOWN,
152 NT_LOGOUT,
153 NT_HBA_RESET
154 } tmd_ncode_t;
155
156 typedef struct tmd_notify {
157 void * nt_hba; /* HBA tag */
158 uint64_t nt_iid; /* inititator id */
159 uint64_t nt_tgt; /* target id */
160 uint16_t nt_lun; /* logical unit */
161 uint16_t : 15,
162 nt_need_ack : 1; /* this notify needs an ACK */
163 uint64_t nt_tagval; /* tag value */
164 uint32_t nt_channel; /* channel id */
165 tmd_ncode_t nt_ncode; /* action */
166 void * nt_tmd; /* TMD for this notify */
167 void * nt_lreserved;
168 void * nt_hreserved;
169 } tmd_notify_t;
170 #define LUN_ANY 0xffff
171 #define TGT_ANY ((uint64_t) -1)
172 #ifdef INI_ANY
173 #define INI_ANY ((uint64_t) -1)
174 #endif
175 #ifndef INI_NONE
176 #define INI_NONE ((uint64_t) 0)
177 #endif
178 #define TAG_ANY ((uint64_t) 0)
179 #define MATCH_TMD(tmd, iid, lun, tag) \
180 ( \
181 (tmd) && \
182 (iid == INI_ANY || iid == tmd->cd_iid) && \
183 (lun == LUN_ANY || lun == tmd->cd_lun) && \
184 (tag == TAG_ANY || tag == tmd->cd_tagval) \
185 )
186
187 /*
188 * Lun ENABLE/DISABLE
189 *
190 * A word about ENABLE/DISABLE: the argument is a pointer to a enadis_t
191 * with en_hba, en_chan and en_lun filled out. We used to have an iid
192 * and target pair, but this just gets silly so we made initiator id
193 * and target id something you set, once, elsewhere.
194 *
195 * If an error occurs in either enabling or disabling the described lun
196 * en_error is set with an appropriate non-zero value.
197 */
198 typedef struct {
199 void * en_private; /* for outer layer usage */
200 void * en_hba; /* HBA tag */
201 uint16_t en_lun; /* logical unit */
202 uint16_t en_chan; /* channel on card */
203 int en_error;
204 } enadis_t;
205
206
207
208 /*
209 * Data Transaction
210 *
211 * A tmd_xact_t is a structure used to describe a transaction within
212 * an overall command. It used to be part of the overall command,
213 * but it became desirable to allow for multiple simultaneous
214 * transfers for a command to happen. Generally these structures
215 * define data to be moved (along with the relative offset within
216 * the overall command) with the last structure containing status
217 * and sense (if needed) as well.
218 *
219 * The td_cmd tag points back to the owning command.
220 *
221 * The td_data tag points to the (platform specific) data descriptor.
222 *
223 * The td_lprivate is for use by the Inner Layer for private usage.
224 *
225 * The td_xfrlen says whether this transaction is moving data- if nonzero.
226 *
227 * The td_offset states what the relative offset within the comamnd the
228 * data transfer will start at. It is undefined if td_xfrlen is zero.
229 *
230 * The td_error flag will note any errors that occurred during an attempt
231 * to start this transaction. The inner layer is responsible for setting
232 * this.
233 *
234 * The td_hflags tag is set by the outer layer to indicate how the inner
235 * layer is supposed to treat this transaction.
236 *
237 * The td_lflags tag is set by the inner layer to indicate whether this
238 * transaction sent status and/or sense. Note that (much as it hurts),
239 * this API allows the inner layer to *fail* to send sense even if asked
240 * to- that is, AUTOSENSE is not a requirement of this API and the outer
241 * layer has to be prepared for this (unlikely) eventuality.
242 */
243
244 typedef struct tmd_cmd tmd_cmd_t;
245 typedef struct tmd_xact {
246 tmd_cmd_t * td_cmd; /* cross-ref to tmd_cmd_t */
247 void * td_data; /* data descriptor */
248 void * td_lprivate; /* private for lower layer */
249 uint32_t td_xfrlen; /* size of this data load */
250 uint32_t td_offset; /* offset for this data load */
251 int td_error; /* error with this transfer */
252 uint8_t td_hflags; /* flags set by caller */
253 uint8_t td_lflags; /* flags set by callee */
254 } tmd_xact_t;
255
256 #define TDFH_STSVALID 0x01 /* status is valid - include it */
257 #define TDFH_SNSVALID 0x02 /* sense data (from outer layer) good - include it */
258 #define TDFH_DATA_IN 0x04 /* target (us) -> initiator (them) */
259 #define TDFH_DATA_OUT 0x08 /* initiator (them) -> target (us) */
260 #define TDFH_DATA_MASK 0x0C /* mask to cover data direction */
261 #define TDFH_PRIVATE 0xF0 /* private outer layer usage */
262
263 #define TDFL_SENTSTATUS 0x01 /* this transaction sent status */
264 #define TDFL_SENTSENSE 0x02 /* this transaction sent sense data */
265 #define TDFL_ERROR 0x04 /* this transaction had an error */
266 #define TDFL_PRIVATE 0xF0 /* private inner layer usage */
267
268 /*
269 * The command structure below the SCSI Command structure that is
270 * is the whole point of this API. After a LUN is (or LUNS are)
271 * enabled, initiators who send commands addressed to the port,
272 * channel and lun that have been enabled cause an interrupt which
273 * causes the chip to receive the command and present it to the
274 * inner layer. The inner layer allocates one of this command
275 * structures and copies relevant information to it and sends it
276 * to the outer layer with the action QOUT_TMD_START.
277 *
278 * The outer layer is then responsible for command decode and is responsible
279 * for sending any transactions back (via a QIN_TMD_CONT) to the inner layer
280 * that (optionally) moves data and then sends closing status.
281 *
282 * The outer layer, when informed of the status of the final transaction
283 * then releases this structure by sending it back to the inner layer
284 * with the action QOUT_TMD_FIN.
285 *
286 * The structure tag meanings are as described below.
287 *
288 * The cd_hba tag is a tag that uniquely identifies the HBA this target
289 * mode command is coming from. The outer layer has to pass this back
290 * unchanged to avoid chaos. It is identical to the r_identity tag used
291 * by the inner layer to register with the outer layer.
292 *
293 * The cd_iid, cd_channel, cd_tgt and cd_lun tags are used to identify the
294 * the initiator who sent us a command, the channel on the this particular
295 * hardware port we arrived on (for multiple channel devices), the target we
296 * claim to be, and the lun on that target.
297 *
298 * The cd_tagval field is a tag that uniquely describes this tag. It may
299 * or may not have any correspondence to an underying hardware tag. The
300 * outer layer must pass this back unchanged or chaos will result.
301 *
302 * The tag cd_totlen is the total data amount expected to be moved
303 * for this command. This will be set to non-zero for transports
304 * that know this value from the transport level (e.g., Fibre Channel).
305 * If it shows up in the outer layers set to zero, the total data length
306 * must be inferred from the CDB.
307 *
308 * The tag cd_moved is the total amount of data moved so far. It is the
309 * responsibilty of the inner layer to set this for every transaction and
310 * to keep track of it so that transport level residuals may be correctly
311 * set.
312 *
313 * The cd_cdb contains storage for the passed in SCSI command.
314 *
315 * The cd_tagtype field specifies what kind of command tag type, if
316 * any, has been sent with this command.
317 *
318 * The tag cd_flags has some junk flags set but mostly has flags reserved for outer layer use.
319 *
320 * The tags cd_sense and cd_scsi_status are self-explanatory.
321 *
322 * The cd_xact tag is the first or only transaction structure related to this command.
323 *
324 * The tag cd_lreserved, cd_hreserved are scratch areas for use for the outer and inner layers respectively.
325 *
326 */
327
328 #ifndef TMD_CDBLEN
329 #define TMD_CDBLEN 16
330 #endif
331 #ifndef TMD_SENSELEN
332 #define TMD_SENSELEN 18
333 #endif
334 #ifndef QCDS
335 #define QCDS (sizeof (uint64_t))
336 #endif
337 #ifndef TMD_PRIV_LO
338 #define TMD_PRIV_LO 4
339 #endif
340 #ifndef TMD_PRIV_HI
341 #define TMD_PRIV_HI 4
342 #endif
343
344 struct tmd_cmd {
345 void * cd_hba; /* HBA tag */
346 uint64_t cd_iid; /* initiator ID */
347 uint64_t cd_tgt; /* target id */
348 uint64_t cd_tagval; /* tag value */
349 uint8_t cd_lun[8]; /* logical unit */
350 uint32_t cd_totlen; /* total data load */
351 uint32_t cd_moved; /* total data moved so far */
352 uint16_t cd_channel; /* channel index */
353 uint16_t cd_flags; /* flags */
354 uint16_t cd_req_cnt; /* how many tmd_xact_t's are active */
355 uint8_t cd_cdb[TMD_CDBLEN];
356 uint8_t cd_tagtype; /* tag type */
357 uint8_t cd_scsi_status;
358 uint8_t cd_sense[TMD_SENSELEN];
359 tmd_xact_t cd_xact; /* first or only transaction */
360 union {
361 void * ptrs[QCDS / sizeof (void *)]; /* (assume) one pointer */
362 uint64_t llongs[QCDS / sizeof (uint64_t)]; /* one long long */
363 uint32_t longs[QCDS / sizeof (uint32_t)]; /* two longs */
364 uint16_t shorts[QCDS / sizeof (uint16_t)]; /* four shorts */
365 uint8_t bytes[QCDS]; /* eight bytes */
366 } cd_lreserved[TMD_PRIV_LO], cd_hreserved[TMD_PRIV_HI];
367 };
368
369 #define CDF_NODISC 0x0001 /* disconnects disabled */
370 #define CDF_DATA_IN 0x0002 /* target (us) -> initiator (them) */
371 #define CDF_DATA_OUT 0x0004 /* initiator (them) -> target (us) */
372 #define CDF_BIDIR 0x0006 /* bidirectional data */
373 #define CDF_SNSVALID 0x0008 /* sense is set on incoming command */
374 #define CDF_PRIVATE 0xff00 /* available for private use in outer layer */
375
376 /* defined tags */
377 #define CD_UNTAGGED 0
378 #define CD_SIMPLE_TAG 1
379 #define CD_ORDERED_TAG 2
380 #define CD_HEAD_TAG 3
381 #define CD_ACA_TAG 4
382
383 #ifndef TMD_SIZE
384 #define TMD_SIZE (sizeof (tmd_cmd_t))
385 #endif
386
387 #define L0LUN_TO_FLATLUN(lptr) ((((lptr)[0] & 0x3f) << 8) | ((lptr)[1]))
388 #define FLATLUN_TO_L0LUN(lptr, lun) \
389 (lptr)[1] = lun & 0xff; \
390 if (sizeof (lun) == 1) { \
391 (lptr)[0] = 0; \
392 } else { \
393 uint16_t nl = lun; \
394 if (nl == LUN_ANY) { \
395 (lptr)[0] = (nl >> 8) & 0xff; \
396 } else if (nl < 256) { \
397 (lptr)[0] = 0; \
398 } else { \
399 (lptr)[0] = 0x40 | ((nl >> 8) & 0x3f); \
400 } \
401 } \
402 memset(&(lptr)[2], 0, 6)
403
404 /*
405 * Inner Layer Handler Function.
406 *
407 * The inner layer target handler function (the outer layer calls this)
408 * should be be prototyped like so:
409 *
410 * void target_action(qact_e, void *arg)
411 *
412 * The outer layer target handler function (the inner layer calls this)
413 * should be be prototyped like:
414 *
415 * void scsi_target_handler(tact_e, void *arg)
416 */
417 #endif /* _ISP_TPUBLIC_H */
418 /*
419 * vim:ts=4:sw=4:expandtab
420 */
Cache object: 483e4403398533d276d65af978ed18ad
|