1 /*        $NetBSD: umassvar.h,v 1.40 2021/12/31 14:24:16 riastradh Exp $        */
2 
3 /*-
4  * Copyright (c) 1999 MAEKAWA Masahide <bishop@rr.iij4u.or.jp>,
5  *                        Nick Hibma <n_hibma@freebsd.org>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  *     $FreeBSD: src/sys/dev/usb/umass.c,v 1.13 2000/03/26 01:39:12 n_hibma Exp $
30  */
31 
32 #ifdef UMASS_DEBUG
33 #define DIF(m, x)   if (umassdebug & (m)) do { x ; } while (0)
34 extern int umassdebug;
35 #else
36 #define umassdebug  0
37 #define DIF(m, x)   /* nop */
38 #endif
39 
40 #define   DPRINTFM(M,FMT,A,B,C,D)       USBHIST_LOGM(umassdebug,M,FMT,A,B,C,D)
41 #define   UMASSHIST_FUNC()    USBHIST_FUNC()
42 #define   UMASSHIST_CALLED(name)        USBHIST_CALLED(umassdebug)
43 
44 #define UDMASS_UPPER          0x00008000          /* upper layer */
45 #define UDMASS_GEN  0x00010000          /* general */
46 #define UDMASS_SCSI 0x00020000          /* scsi */
47 #define UDMASS_UFI  0x00040000          /* ufi command set */
48 #define UDMASS_8070 0x00080000          /* 8070i command set */
49 #define UDMASS_USB  0x00100000          /* USB general */
50 #define UDMASS_BBB  0x00200000          /* Bulk-Only transfers */
51 #define UDMASS_CBI  0x00400000          /* CBI transfers */
52 #define UDMASS_ALL  0xffff0000          /* all of the above */
53 
54 #define UDMASS_XFER 0x40000000          /* all transfers */
55 #define UDMASS_CMD  0x80000000
56 
57 /* Generic definitions */
58 
59 #define UFI_COMMAND_LENGTH 12
60 
61 /* Direction for umass_*_transfer */
62 #define DIR_NONE    0
63 #define DIR_IN                1
64 #define DIR_OUT               2
65 
66 /* Endpoints for umass */
67 #define   UMASS_BULKIN        0
68 #define   UMASS_BULKOUT       1
69 #define   UMASS_INTRIN        2
70 #define   UMASS_NEP 3
71 
72 /* Bulk-Only features */
73 
74 #define UR_BBB_RESET          0xff                /* Bulk-Only reset */
75 #define   UR_BBB_GET_MAX_LUN  0xfe
76 
77 /* Command Block Wrapper */
78 typedef struct {
79           uDWord              dCBWSignature;
80 #define CBWSIGNATURE          0x43425355
81           uDWord              dCBWTag;
82           uDWord              dCBWDataTransferLength;
83           uByte               bCBWFlags;
84 #define CBWFLAGS_OUT          0x00
85 #define CBWFLAGS_IN 0x80
86           uByte               bCBWLUN;
87           uByte               bCDBLength;
88 #define CBWCDBLENGTH          16
89           uByte               CBWCDB[CBWCDBLENGTH];
90 } umass_bbb_cbw_t;
91 #define UMASS_BBB_CBW_SIZE    31
92 
93 /* Command Status Wrapper */
94 typedef struct {
95           uDWord              dCSWSignature;
96 #define CSWSIGNATURE                    0x53425355
97 #define CSWSIGNATURE_OLYMPUS_C1         0x55425355
98           uDWord              dCSWTag;
99           uDWord              dCSWDataResidue;
100           uByte               bCSWStatus;
101 #define CSWSTATUS_GOOD        0x0
102 #define CSWSTATUS_FAILED 0x1
103 #define CSWSTATUS_PHASE       0x2
104 } umass_bbb_csw_t;
105 #define UMASS_BBB_CSW_SIZE    13
106 
107 /* CBI features */
108 
109 #define UR_CBI_ADSC 0x00
110 
111 typedef unsigned char umass_cbi_cbl_t[16];        /* Command block */
112 
113 typedef union {
114           struct {
115                     uByte     type;
116 #define IDB_TYPE_CCI                    0x00
117                     uByte     value;
118 #define IDB_VALUE_PASS                  0x00
119 #define IDB_VALUE_FAIL                  0x01
120 #define IDB_VALUE_PHASE                 0x02
121 #define IDB_VALUE_PERSISTENT  0x03
122 #define IDB_VALUE_STATUS_MASK 0x03
123           } common;
124 
125           struct {
126                     uByte     asc;
127                     uByte     ascq;
128           } ufi;
129 } umass_cbi_sbl_t;
130 
131 struct umass_softc;           /* see below */
132 
133 typedef void (*umass_callback)(struct umass_softc *, void *, int, int);
134 #define STATUS_CMD_OK                   0         /* everything ok */
135 #define STATUS_CMD_UNKNOWN    1         /* will have to fetch sense */
136 #define STATUS_CMD_FAILED     2         /* transfer was ok, command failed */
137 #define STATUS_WIRE_FAILED    3         /* couldn't even get command across */
138 #define STATUS_TIMEOUT                  4         /* transfer aborted */
139 
140 typedef void (*umass_wire_xfer)(struct umass_softc *, int, void *, int, void *,
141                                         int, int, u_int, int, umass_callback, void *);
142 typedef void (*umass_wire_reset)(struct umass_softc *, int);
143 typedef void (*umass_wire_state)(struct usbd_xfer *, void *,
144                                          usbd_status);
145 
146 struct umass_wire_methods {
147           umass_wire_xfer               wire_xfer;
148           umass_wire_reset    wire_reset;
149           umass_wire_state    wire_state;
150 };
151 
152 struct umassbus_softc {
153           device_t            sc_child; /* child device, for detach */
154 };
155 
156 /* the per device structure */
157 struct umass_softc {
158           device_t            sc_dev;             /* base device */
159           struct usbd_device *          sc_udev;  /* device */
160           struct usbd_interface *       sc_iface; /* interface */
161           int                           sc_ifaceno;         /* interface number */
162 
163           uint8_t                       sc_epaddr[UMASS_NEP];
164           struct usbd_pipe *  sc_pipe[UMASS_NEP];
165           usb_device_request_t          sc_req;
166 
167           const struct umass_wire_methods *sc_methods;
168 
169           kmutex_t            sc_lock;
170 
171           uint8_t                       sc_wire;  /* wire protocol */
172 #define   UMASS_WPROTO_UNSPEC 0
173 #define   UMASS_WPROTO_BBB    1
174 #define   UMASS_WPROTO_CBI    2
175 #define   UMASS_WPROTO_CBI_I  3
176 
177           uint8_t                       sc_cmd;             /* command protocol */
178 #define   UMASS_CPROTO_UNSPEC 0
179 #define   UMASS_CPROTO_SCSI   1
180 #define   UMASS_CPROTO_ATAPI  2
181 #define   UMASS_CPROTO_UFI    3
182 #define   UMASS_CPROTO_RBC    4
183 #define UMASS_CPROTO_ISD_ATA  5
184 
185           uint32_t            sc_quirks;
186 #define   UMASS_QUIRK_WRONG_CSWSIG      0x00000001
187 #define   UMASS_QUIRK_WRONG_CSWTAG      0x00000002
188 #define   UMASS_QUIRK_RBC_PAD_TO_12     0x00000004
189 #define   UMASS_QUIRK_NOGETMAXLUN                 0x00000008
190 
191 #define UMASS_QUIRK_USE_DEFAULTMATCH    -1
192 
193           uint32_t            sc_busquirks;
194 
195           /* Bulk specific variables for transfers in progress */
196           umass_bbb_cbw_t               cbw;      /* command block wrapper */
197           umass_bbb_csw_t               csw;      /* command status wrapper*/
198           /* CBI specific variables for transfers in progress */
199           umass_cbi_cbl_t               cbl;      /* command block */
200           umass_cbi_sbl_t               sbl;      /* status block */
201 
202           /* xfer handles
203            * Most of our operations are initiated from interrupt context, so
204            * we need to avoid using the one that is in use. We have to avoid
205            * allocating them in the interrupt context as well.
206            */
207           /* indices into array below */
208 #define XFER_BBB_CBW                    0         /* Bulk-Only */
209 #define XFER_BBB_DATAIN                 1
210 #define XFER_BBB_DATAOUT      2
211 #define XFER_BBB_DCLEAR                 3
212 #define XFER_BBB_CSW1                   4
213 #define XFER_BBB_CSW2                   5
214 #define XFER_BBB_SCLEAR                 6
215 #define XFER_BBB_RESET1                 7
216 #define XFER_BBB_RESET2                 8
217 #define XFER_BBB_RESET3                 9
218 
219 #define XFER_CBI_CB           0         /* CBI */
220 #define XFER_CBI_DATAIN                 1
221 #define XFER_CBI_DATAOUT      2
222 #define XFER_CBI_STATUS                 3
223 #define XFER_CBI_DCLEAR                 4
224 #define XFER_CBI_SCLEAR                 5
225 #define XFER_CBI_RESET1                 6
226 #define XFER_CBI_RESET2                 7
227 #define XFER_CBI_RESET3                 8
228 
229 #define XFER_NR                         10        /* maximum number */
230 
231           struct usbd_xfer    *transfer_xfer[XFER_NR]; /* for ctrl xfers */
232 
233           void                          *datain_buffer;
234           void                          *dataout_buffer;
235           void                          *cmd_buffer;
236           void                          *s1_buffer;
237           void                          *s2_buffer;
238 
239           int                           transfer_dir;                 /* data direction */
240           void                          *transfer_data;               /* data buffer */
241           int                           transfer_datalen;   /* (maximum) length */
242           int                           transfer_actlen;    /* actual length */
243           umass_callback                transfer_cb;                  /* callback */
244           void                          *transfer_priv;               /* for callback */
245           int                           transfer_status;
246 
247           int                           transfer_state;
248 #define TSTATE_IDLE                     0
249 #define TSTATE_BBB_COMMAND              1         /* CBW transfer */
250 #define TSTATE_BBB_DATA                           2         /* Data transfer */
251 #define TSTATE_BBB_DCLEAR               3         /* clear endpt stall */
252 #define TSTATE_BBB_STATUS1              4         /* clear endpt stall */
253 #define TSTATE_BBB_SCLEAR               5         /* clear endpt stall */
254 #define TSTATE_BBB_STATUS2              6         /* CSW transfer */
255 #define TSTATE_BBB_RESET1               7         /* reset command */
256 #define TSTATE_BBB_RESET2               8         /* in clear stall */
257 #define TSTATE_BBB_RESET3               9         /* out clear stall */
258 #define TSTATE_CBI_COMMAND              10        /* command transfer */
259 #define TSTATE_CBI_DATA                           11        /* data transfer */
260 #define TSTATE_CBI_STATUS               12        /* status transfer */
261 #define TSTATE_CBI_DCLEAR               13        /* clear ep stall */
262 #define TSTATE_CBI_SCLEAR               14        /* clear ep stall */
263 #define TSTATE_CBI_RESET1               15        /* reset command */
264 #define TSTATE_CBI_RESET2               16        /* in clear stall */
265 #define TSTATE_CBI_RESET3               17        /* out clear stall */
266 #define TSTATE_STATES                             18        /* # of states above */
267 
268 
269           int                           timeout;            /* in msecs */
270 
271           uint8_t                       maxlun;                       /* max lun supported */
272 
273 #ifdef UMASS_DEBUG
274           struct timeval tv;
275 #endif
276 
277           char                          sc_dying;
278           int                           sc_sense;
279 
280           struct umassbus_softc         *bus;                /* bus dependent data */
281 };
282 
283 #define UMASS_MAX_TRANSFER_SIZE         MAXPHYS
284