3 * Copyright (c) 1997-2007 by Matthew Jacob
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
29 * Host Adapter Public Target Interface Structures && Routines
32 #ifndef _ISP_TPUBLIC_H
33 #define _ISP_TPUBLIC_H 1
36 * Action codes set by the MD target driver for
37 * the external layer to figure out what to do with.
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 */
50 * Action codes set by the external layer for the
51 * MD driver to figure out what to do with.
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 */
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.
78 /* NB: tags from here to r_version must never change */
80 void (*r_action)(qact_e, void *);
86 enum { R_FC, R_SPI } r_type;
91 * An information structure that is used to get or set per-channel transport layer parameters.
95 enum { I_FC, I_SPI } i_type;
112 * An information structure to return a list of logged in WWPNs. FC specific.
125 NT_ABORT_TASK=0x1000,
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 */
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 */
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) \
159 (iid == INI_ANY || iid == tmd->cd_iid) && \
160 (lun == LUN_ANY || lun == tmd->cd_lun) && \
161 (tag == TAG_ANY || tag == tmd->cd_tagval) \
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.
168 * If an error occurs in either enabling or disabling the described lun
169 * cd_error is set with an appropriate non-zero value.
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 */
182 * Suggested Software Target Mode Command Handling structure.
184 * A note about terminology:
186 * MD stands for "Machine Dependent".
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).
193 * "Outer Layer" means "Other Module"
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.
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.
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
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.
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).
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.
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
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.
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.
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.
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
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.
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.
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.
273 * The reason that total length and total residual have to be tracked
274 * is to keep track of relative offset.
276 * The tags cd_sense and cd_scsi_status are pretty obvious.
278 * The tag cd_error is to communicate between the MD layer and outer software
279 * the current error conditions.
281 * The tag cd_lreserved, cd_hreserved are scratch areas for use for the MD
282 * and outer layers respectively.
287 #define TMD_CDBLEN 16
290 #define TMD_SENSELEN 18
293 #define QCDS (sizeof (void *))
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];
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)];
321 } cd_lreserved[4], cd_hreserved[4];
325 #define CD_UNTAGGED 0
326 #define CD_SIMPLE_TAG 1
327 #define CD_ORDERED_TAG 2
328 #define CD_HEAD_TAG 3
332 #define TMD_SIZE (sizeof (tmd_cmd_t))
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) { \
342 if (nl == LUN_ANY) { \
343 (lptr)[0] = (nl >> 8) & 0xff; \
344 } else if (nl < 256) { \
347 (lptr)[0] = 0x40 | ((nl >> 8) & 0x3f); \
350 memset(&(lptr)[2], 0, 6)
353 * Note that NODISC (obviously) doesn't apply to non-SPI transport.
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.
358 * The CDFL_BIDIR is in anticipation of the adoption of some newer
359 * features required by OSD.
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.
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 */
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 */
385 * A word about the START/CONT/DONE/FIN dance:
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
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.
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.
406 * The graph looks like:
408 * QOUT_TMD_START -> [ QIN_TMD_CONT -> QOUT_TMD_DONE ] * -> QIN_TMD_FIN.
413 * Target handler functions.
415 * The MD target handler function (the outer layer calls this)
416 * should be be prototyped like:
418 * void target_action(qact_e, void *arg)
420 * The outer layer target handler function (the MD layer calls this)
421 * should be be prototyped like:
423 * void scsi_target_handler(tact_e, void *arg)
425 #endif /* _ISP_TPUBLIC_H */
427 * vim:ts=4:sw=4:expandtab