summaryrefslogtreecommitdiff
path: root/sys/dev/ic/isp_tpublic.h
blob: 1b5694e602f30b7334fd8a9bd147d2d16424a40d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
/* $NetBSD: isp_tpublic.h,v 1.21 2021/12/12 13:05:14 andvar Exp $ */
/*-
 *  Copyright (c) 1997-2008 by Matthew Jacob
 *  All rights reserved.
 * 
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 * 
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 
 *  THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 *  SUCH DAMAGE.
 */
/*
 * Host Adapter Public Target Interface Structures && Routines
 */
/*
 * A note about terminology:
 *
 *  "Inner Layer" means this driver (isp and the isp_tpublic API).
 *
 *    This module includes the both generic and platform specific pieces.
 *
 *  "Outer Layer" means another (external) module.
 *
 *    This is an additional module that actually implements SCSI target command
 *    decode and is the recipient of incoming commands and the source of the
 *    disposition for them.
 */

#ifndef    _ISP_TPUBLIC_H
#define    _ISP_TPUBLIC_H    1
/*
 * Include general target definitions
 */
#include "isp_target.h"

/*
 * Action codes set by the Inner Layer for the outer layer to figure out what to do with.
 */
typedef enum {
    QOUT_HBA_REG=0,     /* the argument is a pointer to a hba_register_t */
    QOUT_ENABLE,        /* the argument is a pointer to a enadis_t */
    QOUT_DISABLE,       /* the argument is a pointer to a enadis_t */
    QOUT_TMD_START,     /* the argument is a pointer to a tmd_cmd_t */
    QOUT_TMD_DONE,      /* the argument is a pointer to a tmd_xact_t */
    QOUT_NOTIFY,        /* the argument is a pointer to a notify_t */
    QOUT_HBA_UNREG      /* the argument is a pointer to a hba_register_t */
} tact_e;

/*
 * Action codes set by the outer layer for the
 * inner layer to figure out what to do with.
 */
typedef enum {
    QIN_HBA_REG=99,     /* the argument is a pointer to a hba_register_t */
    QIN_GETINFO,        /* the argument is a pointer to a info_t */
    QIN_SETINFO,        /* the argument is a pointer to a info_t */
    QIN_GETDLIST,       /* the argument is a pointer to a fc_dlist_t */
    QIN_ENABLE,         /* the argument is a pointer to a enadis_t */
    QIN_DISABLE,        /* the argument is a pointer to a enadis_t */
    QIN_TMD_CONT,       /* the argument is a pointer to a tmd_xact_t */
    QIN_TMD_FIN,        /* the argument is a pointer to a tmd_cmd_t */
    QIN_NOTIFY_ACK,     /* the argument is a pointer to a notify_t */
    QIN_HBA_UNREG,      /* the argument is a pointer to a hba_register_t */
} qact_e;

/*
 * This structure is used to register to the outer layer the
 * binding of an HBA identifier, driver name and instance and the
 * lun width capabilities of this inner layer. It's up to each
 * platform to figure out how it wants to actually implement this.
 * A typical sequence would be for the MD layer to find some external
 * module's entry point and start by sending a QOUT_HBA_REG with info
 * filled in, and the external module to call back with a QIN_HBA_REG
 * that passes back the corresponding information.
 *
 * The r_version tag defines the version of this API.
 */
#define    QR_VERSION    20
typedef struct {
    /* NB: structure tags from here to r_version must never change */
    void *                  r_identity;
    void                    (*r_action)(qact_e, void *);
    char                    r_name[8];
    int                     r_inst;
    int                     r_version;
    uint32_t                r_locator;
    uint32_t                r_nchannels;
    enum { R_FC, R_SPI }    r_type;
    void *                  r_private;
} hba_register_t;

/*
 * An information structure that is used to get or set per-channel transport layer parameters.
 */
typedef struct {
    void *                  i_identity;
    enum { I_FC, I_SPI }    i_type;
    int                     i_channel;
    int                     i_error;
    union {
        struct {
            uint64_t    wwnn_nvram;
            uint64_t    wwpn_nvram;
            uint64_t    wwnn;
            uint64_t    wwpn;
        } fc;
        struct {
            int         iid;
        } spi;
    }                       i_id;
} info_t;

/*
 * An information structure to return a list of logged in WWPNs. FC specific.
 */
typedef struct {
    void *                  d_identity;
    int                     d_channel;
    int                     d_error;
    int                     d_count;
    uint64_t *              d_wwpns;
} fc_dlist_t;

/*
 * Lun ENABLE/DISABLE
 *
 * A word about ENABLE/DISABLE: the argument is a pointer to a enadis_t
 * with en_hba, en_chan and en_lun filled out. We used to have an iid
 * and target pair, but this just gets silly so we made initiator id
 * and target id something you set, once, elsewhere.
 *
 * If an error occurs in either enabling or disabling the described lun
 * en_error is set with an appropriate non-zero value.
 */
typedef struct {
    void *          en_private;     /* for outer layer usage */
    void *          en_hba;         /* HBA tag */
    uint16_t        en_lun;         /* logical unit */
    uint16_t        en_chan;        /* channel on card */
    int             en_error;
} enadis_t;



/*
 * Data Transaction
 *
 * A tmd_xact_t is a structure used to describe a transaction within
 * an overall command. It used to be part of the overall command,
 * but it became desirable to allow for multiple simultaneous
 * transfers for a command to happen. Generally these structures
 * define data to be moved (along with the relative offset within
 * the overall command) with the last structure containing status
 * and sense (if needed) as well.
 *
 * The td_cmd tag points back to the owning command.
 *
 * The td_data tag points to the (platform specific) data descriptor.
 *
 * The td_lprivate is for use by the Inner Layer for private usage.
 *
 * The td_xfrlen says whether this transaction is moving data- if nonzero.
 *
 * The td_offset states what the relative offset within the comamnd the
 * data transfer will start at. It is undefined if td_xfrlen is zero.
 *
 * The td_error flag will note any errors that occurred during an attempt
 * to start this transaction. The inner layer is responsible for setting
 * this.
 *
 * The td_hflags tag is set by the outer layer to indicate how the inner
 * layer is supposed to treat this transaction.
 *
 * The td_lflags tag is set by the inner layer to indicate whether this
 * transaction sent status and/or sense. Note that (much as it hurts),
 * this API allows the inner layer to *fail* to send sense even if asked
 * to- that is, AUTOSENSE is not a requirement of this API and the outer
 * layer has to be prepared for this (unlikely) eventuality.
 */

typedef struct tmd_cmd tmd_cmd_t;
typedef struct tmd_xact {
    tmd_cmd_t *         td_cmd;                 /* cross-ref to tmd_cmd_t */
    void *              td_data;                /* data descriptor */
    void *              td_lprivate;            /* private for lower layer */
    uint32_t            td_xfrlen;              /* size of this data load */
    uint32_t            td_offset;              /* offset for this data load */
    int                 td_error;               /* error with this transfer */
    uint8_t             td_hflags;              /* flags set by caller */
    uint8_t             td_lflags;              /* flags set by callee */
} tmd_xact_t;

#define TDFH_STSVALID   0x01    /* status is valid - include it */
#define TDFH_SNSVALID   0x02    /* sense data (from outer layer) good - include it */
#define TDFH_DATA_IN    0x04    /* target (us) -> initiator (them) */
#define TDFH_DATA_OUT   0x08    /* initiator (them) -> target (us) */
#define TDFH_DATA_MASK  0x0C    /* mask to cover data direction */
#define TDFH_PRIVATE    0xF0    /* private outer layer usage */

#define TDFL_SENTSTATUS 0x01    /* this transaction sent status */
#define TDFL_SENTSENSE  0x02    /* this transaction sent sense data */
#define TDFL_ERROR      0x04    /* this transaction had an error */
#define TDFL_SYNCERROR  0x08    /* ... and didn't even start because of it */
#define TDFL_PRIVATE    0xF0    /* private inner layer usage */

/*
 * The command structure below the SCSI Command structure that is
 * is the whole point of this API. After a LUN is (or LUNS are)
 * enabled, initiators who send commands addressed to the port,
 * channel and lun that have been enabled cause an interrupt which
 * causes the chip to receive the command and present it to the
 * inner layer. The inner layer allocates one of this command
 * structures and copies relevant information to it and sends it
 * to the outer layer with the action QOUT_TMD_START.
 *
 * The outer layer is then responsible for command decode and is responsible
 * for sending any transactions back (via a QIN_TMD_CONT) to the inner layer
 * that (optionally) moves data and then sends closing status.
 *
 * The outer layer, when informed of the status of the final transaction
 * then releases this structure by sending it back to the inner layer
 * with the action QOUT_TMD_FIN.
 *
 * The structure tag meanings are as described below.
 *
 * The cd_hba tag is a tag that uniquely identifies the HBA this target
 * mode command is coming from. The outer layer has to pass this back
 * unchanged to avoid chaos. It is identical to the r_identity tag used
 * by the inner layer to register with the outer layer.
 *
 * The cd_iid, cd_channel, cd_tgt and cd_lun tags are used to identify the
 * the initiator who sent us a command, the channel on the this particular
 * hardware port we arrived on (for multiple channel devices), the target we
 * claim to be, and the lun on that target.
 *
 * The cd_tagval field is a tag that uniquely describes this tag. It may
 * or may not have any correspondence to an underying hardware tag. The
 * outer layer must pass this back unchanged or chaos will result.
 *
 * The tag cd_totlen is the total data amount expected to be moved
 * for this command. This will be set to non-zero for transports
 * that know this value from the transport level (e.g., Fibre Channel).
 * If it shows up in the outer layers set to zero, the total data length
 * must be inferred from the CDB.
 *
 * The tag cd_moved is the total amount of data moved so far. It is the
 * responsibility of the inner layer to set this for every transaction and
 * to keep track of it so that transport level residuals may be correctly
 * set.
 *
 * The cd_cdb contains storage for the passed in SCSI command.
 *
 * The cd_tagtype field specifies what kind of command tag type, if
 * any, has been sent with this command.
 *
 * The tag cd_flags has some junk flags set but mostly has flags reserved for outer layer use.
 *
 * The tags cd_sense and cd_scsi_status are self-explanatory.
 *
 * The cd_xact tag is the first or only transaction structure related to this command.
 *
 * The tag cd_lreserved, cd_hreserved are scratch areas for use for the outer and inner layers respectively.
 * 
 */

#ifndef TMD_CDBLEN
#define TMD_CDBLEN       16
#endif
#ifndef TMD_SENSELEN
#define TMD_SENSELEN     18
#endif
#ifndef QCDS
#define QCDS             (sizeof (uint64_t))
#endif
#ifndef TMD_PRIV_LO
#define TMD_PRIV_LO 4
#endif
#ifndef TMD_PRIV_HI
#define TMD_PRIV_HI 4
#endif

struct tmd_cmd {
    void *              cd_hba;     /* HBA tag */
    uint64_t            cd_iid;     /* initiator ID */
    uint64_t            cd_tgt;     /* target id */
    uint64_t            cd_tagval;  /* tag value */
    uint8_t             cd_lun[8];  /* logical unit */
    uint32_t            cd_totlen;  /* total data load */
    uint32_t            cd_moved;   /* total data moved so far */
    uint16_t            cd_channel; /* channel index */
    uint16_t            cd_flags;   /* flags */
    uint16_t            cd_req_cnt; /* how many tmd_xact_t's are active */
    uint8_t             cd_cdb[TMD_CDBLEN];
    uint8_t             cd_tagtype; /* tag type */
    uint8_t             cd_scsi_status;
    uint8_t             cd_sense[TMD_SENSELEN];
    tmd_xact_t          cd_xact;    /* first or only transaction */
    union {
        void *          ptrs[QCDS / sizeof (void *)];       /* (assume) one pointer */
        uint64_t        llongs[QCDS / sizeof (uint64_t)];   /* one long long */
        uint32_t        longs[QCDS / sizeof (uint32_t)];    /* two longs */
        uint16_t        shorts[QCDS / sizeof (uint16_t)];   /* four shorts */
        uint8_t         bytes[QCDS];                        /* eight bytes */
    } cd_lreserved[TMD_PRIV_LO], cd_hreserved[TMD_PRIV_HI];
};

#define CDF_NODISC      0x0001  /* disconnects disabled */
#define CDF_DATA_IN     0x0002  /* target (us) -> initiator (them) */
#define CDF_DATA_OUT    0x0004  /* initiator (them) -> target (us) */
#define CDF_BIDIR       0x0006  /* bidirectional data */
#define CDF_SNSVALID    0x0008  /* sense is set on incoming command */
#define CDF_PRIVATE     0xff00  /* available for private use in outer layer */

/* defined tags */
#define CD_UNTAGGED     0
#define CD_SIMPLE_TAG   1
#define CD_ORDERED_TAG  2
#define CD_HEAD_TAG     3
#define CD_ACA_TAG      4

#ifndef    TMD_SIZE
#define    TMD_SIZE     (sizeof (tmd_cmd_t))
#endif

#define L0LUN_TO_FLATLUN(lptr)              ((((lptr)[0] & 0x3f) << 8) | ((lptr)[1]))
#define FLATLUN_TO_L0LUN(lptr, lun)                 \
    (lptr)[1] = lun & 0xff;                         \
    if (sizeof (lun) == 1) {                        \
        (lptr)[0] = 0;                              \
    } else {                                        \
        uint16_t nl = lun;                          \
        if (nl == LUN_ANY) {                        \
            (lptr)[0] = (nl >> 8) & 0xff;           \
        } else if (nl < 256) {                      \
            (lptr)[0] = 0;                          \
        } else {                                    \
            (lptr)[0] = 0x40 | ((nl >> 8) & 0x3f);  \
        }                                           \
    }                                               \
    memset(&(lptr)[2], 0, 6)

/*
 * Inner Layer Handler Function.
 *
 * The inner layer target handler function (the outer layer calls this)
 * should be prototyped like so:
 *
 *    void target_action(qact_e, void *arg)
 *
 * The outer layer target handler function (the inner layer calls this)
 * should be prototyped like:
 *
 *    void scsi_target_handler(tact_e, void *arg)
 */

#endif    /* _ISP_TPUBLIC_H */
/*
 * vim:ts=4:sw=4:expandtab
 */