isp_tpublic.h revision 1.13.4.1 1 /* $NetBSD: isp_tpublic.h,v 1.13.4.1 2007/09/03 14:34:49 yamt Exp $ */
2 /*
3 * Copyright (c) 1997-2006 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 #ifndef _ISP_TPUBLIC_H
33 #define _ISP_TPUBLIC_H 1
34
35 /*
36 * Action codes set by the MD target driver for
37 * the external layer to figure out what to do with.
38 */
39 typedef enum {
40 QOUT_HBA_REG=0, /* the argument is a pointer to a hba_register_t */
41 QOUT_ENABLE, /* the argument is a pointer to a enadis_t */
42 QOUT_DISABLE, /* the argument is a pointer to a enadis_t */
43 QOUT_TMD_START, /* the argument is a pointer to a tmd_cmd_t */
44 QOUT_TMD_DONE, /* the argument is a pointer to a tmd_cmd_t */
45 QOUT_NOTIFY, /* the argument is a pointer to a tmd_notify_t */
46 QOUT_HBA_UNREG /* the argument is a pointer to a hba_register_t */
47 } tact_e;
48
49 /*
50 * Action codes set by the external layer for the
51 * MD driver to figure out what to do with.
52 */
53 typedef enum {
54 QIN_HBA_REG=99, /* the argument is a pointer to a hba_register_t */
55 QIN_GETINFO, /* the argument is a pointer to a info_t */
56 QIN_SETINFO, /* the argument is a pointer to a info_t */
57 QIN_GETDLIST, /* the argument is a pointer to a fc_dlist_t */
58 QIN_ENABLE, /* the argument is a pointer to a enadis_t */
59 QIN_DISABLE, /* the argument is a pointer to a enadis_t */
60 QIN_TMD_CONT, /* the argument is a pointer to a tmd_cmd_t */
61 QIN_TMD_FIN, /* the argument is a pointer to a tmd_cmd_t */
62 QIN_NOTIFY_ACK, /* the argument is a pointer to a tmd_notify_t */
63 QIN_HBA_UNREG, /* the argument is a pointer to a hba_register_t */
64 } qact_e;
65
66 /*
67 * This structure is used to register to other software modules the
68 * binding of an HBA identifier, driver name and instance and the
69 * lun width capapbilities of this target driver. It's up to each
70 * platform to figure out how it wants to do this, but a typical
71 * sequence would be for the MD layer to find some external module's
72 * entry point and start by sending a QOUT_HBA_REG with info filled
73 * in, and the external module to call back with a QIN_HBA_REG that
74 * passes back the corresponding information.
75 */
76 #define QR_VERSION 16
77 typedef struct {
78 /* NB: tags from here to r_version must never change */
79 void * r_identity;
80 void (*r_action)(qact_e, void *);
81 char r_name[8];
82 int r_inst;
83 int r_version;
84 uint32_t r_locator;
85 uint32_t r_nchannels;
86 enum { R_FC, R_SPI } r_type;
87 void * r_private;
88 } hba_register_t;
89
90 /*
91 * An information structure that is used to get or set per-channel transport layer parameters.
92 */
93 typedef struct {
94 void * i_identity;
95 enum { I_FC, I_SPI } i_type;
96 int i_channel;
97 int i_error;
98 union {
99 struct {
100 uint64_t wwnn_nvram;
101 uint64_t wwpn_nvram;
102 uint64_t wwnn;
103 uint64_t wwpn;
104 } fc;
105 struct {
106 int iid;
107 } spi;
108 } i_id;
109 } info_t;
110
111 /*
112 * An information structure to return a list of logged in WWPNs. FC specific.
113 */
114 typedef struct {
115 void * d_identity;
116 int d_channel;
117 int d_error;
118 int d_count;
119 uint64_t * d_wwpns;
120 } fc_dlist_t;
121 /*
122 * Notify structure
123 */
124 typedef enum {
125 NT_ABORT_TASK=0x1000,
126 NT_ABORT_TASK_SET,
127 NT_CLEAR_ACA,
128 NT_CLEAR_TASK_SET,
129 NT_LUN_RESET,
130 NT_TARGET_RESET,
131 NT_BUS_RESET,
132 NT_LIP_RESET,
133 NT_LINK_UP,
134 NT_LINK_DOWN,
135 NT_LOGOUT,
136 NT_HBA_RESET
137 } tmd_ncode_t;
138
139 typedef struct tmd_notify {
140 void * nt_hba; /* HBA tag */
141 uint64_t nt_iid; /* inititator id */
142 uint64_t nt_tgt; /* target id */
143 uint16_t nt_lun; /* logical unit */
144 uint16_t : 15,
145 nt_need_ack : 1; /* this notify needs an ACK */
146 uint64_t nt_tagval; /* tag value */
147 uint32_t nt_channel; /* channel id */
148 tmd_ncode_t nt_ncode; /* action */
149 void * nt_lreserved;
150 void * nt_hreserved;
151 } tmd_notify_t;
152 #define LUN_ANY 0xffff
153 #define TGT_ANY ((uint64_t) -1)
154 #define INI_ANY ((uint64_t) -1)
155 #define TAG_ANY ((uint64_t) 0)
156 #define MATCH_TMD(tmd, iid, lun, tag) \
157 ( \
158 (tmd) && \
159 (iid == INI_ANY || iid == tmd->cd_iid) && \
160 (lun == LUN_ANY || lun == tmd->cd_lun) && \
161 (tag == TAG_ANY || tag == tmd->cd_tagval) \
162 )
163
164 /*
165 * A word about ENABLE/DISABLE: the argument is a pointer to a enadis_t
166 * with en_hba, en_iid, en_chan, en_tgt and en_lun filled out.
167 *
168 * If an error occurs in either enabling or disabling the described lun
169 * cd_error is set with an appropriate non-zero value.
170 */
171 typedef struct {
172 void * en_private; /* for outer layer usage */
173 void * en_hba; /* HBA tag */
174 uint64_t en_iid; /* initiator ID */
175 uint64_t en_tgt; /* target id */
176 uint16_t en_lun; /* logical unit */
177 uint16_t en_chan; /* channel on card */
178 int en_error;
179 } enadis_t;
180
181 /*
182 * Suggested Software Target Mode Command Handling structure.
183 *
184 * A note about terminology:
185 *
186 * MD stands for "Machine Dependent".
187 *
188 * This driver is structured in three layers: Outer MD, core, and inner MD.
189 * The latter also is bus dependent (i.e., is cognizant of PCI bus issues
190 * as well as platform issues).
191 *
192 *
193 * "Outer Layer" means "Other Module"
194 *
195 * Some additional module that actually implements SCSI target command
196 * policy is the recipient of incoming commands and the source of the
197 * disposition for them.
198 *
199 * The command structure below is one suggested possible MD command structure,
200 * but since the handling of thbis is entirely in the MD layer, there is
201 * no explicit or implicit requirement that it be used.
202 *
203 * The cd_private tag should be used by the MD layer to keep a free list
204 * of these structures. Code outside of this driver can then use this
205 * to identify it's own unit structures. That is, when not on the MD
206 * layer's freelist, the MD layer should shove into it the identifier
207 * that the outer layer has for it- passed in on an initial QIN_HBA_REG
208 * call (see below).
209 *
210 * The cd_hba tag is a tag that uniquely identifies the HBA this target
211 * mode command is coming from. The outer layer has to pass this back
212 * unchanged to avoid chaos.
213 *
214 * The cd_iid, cd_tgt, cd_lun and cd_port tags are used to identify the
215 * id of the initiator who sent us a command, the target claim to be, the
216 * lun on the target we claim to be, and the port instance (for multiple
217 * port host adapters) that this applies to (consider it an extra port
218 * parameter). The iid, tgt and lun values are deliberately chosen to be
219 * fat so that, for example, World Wide Names can be used instead of
220 * the units that the firmware uses (in the case where the MD
221 * layer maintains a port database, for example).
222 *
223 * The cd_tagtype field specifies what kind of command tag type, if
224 * any, has been sent with the command. Note that the Outer Layer
225 * still needs to pass the tag handle through unchanged even
226 * if the tag type is CD_UNTAGGED.
227 *
228 * The cd_cdb contains storage for the passed in command descriptor block.
229 * There is no need to define length as the callee should be able to
230 * figure this out.
231 *
232 * The tag cd_lflags are the flags set by the MD driver when it gets
233 * command incoming or when it needs to inform any outside entities
234 * that the last requested action failed.
235 *
236 * The tag cd_hflags should be set by any outside software to indicate
237 * the validity of sense and status fields (defined below) and to indicate
238 * the direction data is expected to move. It is an error to have both
239 * CDFH_DATA_IN and CDFH_DATA_OUT set.
240 *
241 * If the CDFH_STSVALID flag is set, the command should be completed (after
242 * sending any data and/or status). If CDFH_SNSVALID is set and the MD layer
243 * can also handle sending the associated sense data (either back with an
244 * FCP RESPONSE IU for Fibre Channel or otherwise automatically handling a
245 * REQUEST SENSE from the initator for this target/lun), the MD layer will
246 * set the CDFL_SENTSENSE flag on successful transmission of the sense data.
247 * It is an error for the CDFH_SNSVALID bit to be set and CDFH_STSVALID not
248 * to be set. It is an error for the CDFH_SNSVALID be set and the associated
249 * SCSI status (cd_scsi_status) not be set to CHECK CONDITON.
250 *
251 * The tag cd_data points to a data segment to either be filled or
252 * read from depending on the direction of data movement. The tag
253 * is undefined if no data direction is set. The MD layer and outer
254 * layers must agree on the meaning of cd_data and it is specifically
255 * not defined here.
256 *
257 * The tag cd_totlen is the total data amount expected to be moved
258 * over the life of the command. It may be set by the MD layer, possibly
259 * from the datalen field of an FCP CMND IU unit. If it shows up in the outer
260 * layers set to zero and the CDB indicates data should be moved, the outer
261 * layer should set it to the amount expected to be moved.
262 *
263 * The tag cd_resid should be the total residual of data not transferred.
264 * The outer layers need to set this at the begining of command processing
265 * to equal cd_totlen. As data is successfully moved, this value is decreased.
266 * At the end of a command, any nonzero residual indicates the number of bytes
267 * requested by the command but not moved.
268 *
269 * The tag cd_xfrlen is the length of the currently active data transfer.
270 * This allows several interations between any outside software and the
271 * MD layer to move data.
272 *
273 * The reason that total length and total residual have to be tracked
274 * is to keep track of relative offset.
275 *
276 * The tags cd_sense and cd_scsi_status are pretty obvious.
277 *
278 * The tag cd_error is to communicate between the MD layer and outer software
279 * the current error conditions.
280 *
281 * The tag cd_lreserved, cd_hreserved are scratch areas for use for the MD
282 * and outer layers respectively.
283 *
284 */
285
286 #ifndef TMD_CDBLEN
287 #define TMD_CDBLEN 16
288 #endif
289 #ifndef TMD_SENSELEN
290 #define TMD_SENSELEN 18
291 #endif
292 #ifndef QCDS
293 #define QCDS (sizeof (void *))
294 #endif
295
296 typedef struct tmd_cmd {
297 void * cd_private; /* private data pointer */
298 void * cd_hba; /* HBA tag */
299 void * cd_data; /* 'pointer' to data */
300 uint64_t cd_iid; /* initiator ID */
301 uint64_t cd_tgt; /* target id */
302 uint8_t cd_lun[8]; /* logical unit */
303 uint64_t cd_tagval; /* tag value */
304 uint32_t cd_channel; /* channel index */
305 uint32_t cd_lflags; /* flags lower level sets */
306 uint32_t cd_hflags; /* flags higher level sets */
307 uint32_t cd_totlen; /* total data load */
308 uint32_t cd_resid; /* total data residual */
309 uint32_t cd_xfrlen; /* current data load */
310 int32_t cd_error; /* current error */
311 uint8_t cd_tagtype; /* tag type */
312 uint8_t cd_scsi_status;
313 uint8_t cd_sense[TMD_SENSELEN];
314 uint8_t cd_cdb[TMD_CDBLEN];
315 union {
316 void * ptrs[QCDS / sizeof (void *)];
317 uint64_t llongs[QCDS / sizeof (uint64_t)];
318 uint32_t longs[QCDS / sizeof (uint32_t)];
319 uint16_t shorts[QCDS / sizeof (uint16_t)];
320 uint8_t bytes[QCDS];
321 } cd_lreserved[4], cd_hreserved[4];
322 } tmd_cmd_t;
323
324 /* defined tags */
325 #define CD_UNTAGGED 0
326 #define CD_SIMPLE_TAG 1
327 #define CD_ORDERED_TAG 2
328 #define CD_HEAD_TAG 3
329 #define CD_ACA_TAG 4
330
331 #ifndef TMD_SIZE
332 #define TMD_SIZE (sizeof (tmd_cmd_t))
333 #endif
334
335 #define L0LUN_TO_FLATLUN(lptr) ((((lptr)[0] & 0x3f) << 8) | ((lptr)[1]))
336 #define FLATLUN_TO_L0LUN(lptr, lun) \
337 (lptr)[1] = lun & 0xff; \
338 if (sizeof (lun) == 1) { \
339 (lptr)[0] = 0; \
340 } else { \
341 uint16_t nl = lun; \
342 if (nl == LUN_ANY) { \
343 (lptr)[0] = (nl >> 8) & 0xff; \
344 } else if (nl < 256) { \
345 (lptr)[0] = 0; \
346 } else { \
347 (lptr)[0] = 0x40 | ((nl >> 8) & 0x3f); \
348 } \
349 } \
350 memset(&(lptr)[2], 0, 6)
351
352 /*
353 * Note that NODISC (obviously) doesn't apply to non-SPI transport.
354 *
355 * Note that knowing the data direction and lengh at the time of receipt of
356 * a command from the initiator is a feature only of Fibre Channel.
357 *
358 * The CDFL_BIDIR is in anticipation of the adoption of some newer
359 * features required by OSD.
360 *
361 * The principle selector for MD layer to know whether data is to
362 * be transferred in any QOUT_TMD_CONT call is cd_xfrlen- the
363 * flags CDFH_DATA_IN and CDFH_DATA_OUT define which direction.
364 */
365 #define CDFL_SNSVALID 0x01 /* sense data (from f/w) good */
366 #define CDFL_SENTSTATUS 0x02 /* last action sent status */
367 #define CDFL_DATA_IN 0x04 /* target (us) -> initiator (them) */
368 #define CDFL_DATA_OUT 0x08 /* initiator (them) -> target (us) */
369 #define CDFL_BIDIR 0x0C /* bidirectional data */
370 #define CDFL_ERROR 0x10 /* last action ended in error */
371 #define CDFL_NODISC 0x20 /* disconnects disabled */
372 #define CDFL_SENTSENSE 0x40 /* last action sent sense data */
373 #define CDFL_BUSY 0x80 /* this command is not on a free list */
374 #define CDFL_PRIVATE 0xFF000000 /* private layer flags */
375
376 #define CDFH_SNSVALID 0x01 /* sense data (from outer layer) good */
377 #define CDFH_STSVALID 0x02 /* status valid */
378 #define CDFH_DATA_IN 0x04 /* target (us) -> initiator (them) */
379 #define CDFH_DATA_OUT 0x08 /* initiator (them) -> target (us) */
380 #define CDFH_DATA_MASK 0x0C /* mask to cover data direction */
381 #define CDFH_PRIVATE 0xFF000000 /* private layer flags */
382
383
384 /*
385 * A word about the START/CONT/DONE/FIN dance:
386 *
387 * When the HBA is enabled for receiving commands, one may show up
388 * without notice. When that happens, the MD target mode driver
389 * gets a tmd_cmd_t, fills it with the info that just arrived, and
390 * calls the outer layer with a QOUT_TMD_START code and pointer to
391 * the tmd_cmd_t.
392 *
393 * The outer layer decodes the command, fetches data, prepares stuff,
394 * whatever, and starts by passing back the pointer with a QIN_TMD_CONT
395 * code which causes the MD target mode driver to generate CTIOs to
396 * satisfy whatever action needs to be taken. When those CTIOs complete,
397 * the MD target driver sends the pointer to the cmd_tmd_t back with
398 * a QOUT_TMD_DONE code. This repeats for as long as necessary. These
399 * may not be done in parallel- they are sequential operations.
400 *
401 * The outer layer signals it wants to end the command by settings within
402 * the tmd_cmd_t itself. When the final QIN_TMD_CONT is reported completed,
403 * the outer layer frees the tmd_cmd_t by sending the pointer to it
404 * back with a QIN_TMD_FIN code.
405 *
406 * The graph looks like:
407 *
408 * QOUT_TMD_START -> [ QIN_TMD_CONT -> QOUT_TMD_DONE ] * -> QIN_TMD_FIN.
409 *
410 */
411
412 /*
413 * Target handler functions.
414 *
415 * The MD target handler function (the outer layer calls this)
416 * should be be prototyped like:
417 *
418 * void target_action(qact_e, void *arg)
419 *
420 * The outer layer target handler function (the MD layer calls this)
421 * should be be prototyped like:
422 *
423 * void scsi_target_handler(tact_e, void *arg)
424 */
425 #endif /* _ISP_TPUBLIC_H */
426 /*
427 * vim:ts=4:sw=4:expandtab
428 */
429