aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging/ced1401/usb1401.h
blob: f031e3a2c7cf209fbf82188cade39567502d846e (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
/* usb1401.h
 Header file for the CED 1401 USB device driver for Linux
 Copyright (C) 2010 Cambridge Electronic Design Ltd
 Author Greg P Smith (greg@ced.co.uk)

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
#ifndef __USB1401_H__
#define __USB1401_H__
#include "use1401.h"
#include "ced_ioctl.h"

#ifndef UINT
#define UINT unsigned int
#endif

/** Device type codes, but these don't need to be extended - a succession is assumed
** These are set for usb from the bcdDevice field (suitably mangled). Future devices
** will be added in order of device creation to the list, so the names here are just
** to help use remember which device is which. The U14ERR_... values follow the same
** pattern for modern devices.a
**/
#define TYPEUNKNOWN        -1             /*  dont know */
#define TYPE1401           0              /*  standard 1401 */
#define TYPEPLUS           1              /*  1401 plus */
#define TYPEU1401          2              /*  u1401 */
#define TYPEPOWER          3              /*  Power1401 */
#define TYPEU14012         4              /*  u1401 mkII */
#define TYPEPOWER2         5              /*  Power1401 mk II */
#define TYPEMICRO3         6              /*  Micro1401-3 */
#define TYPEPOWER3         7              /*  Power1401-3 */

/*  Some useful defines of constants. DONT FORGET to change the version in the */
/*  resources whenever you change it here!. */
#define DRIVERMAJREV      2             /*  driver revision level major (match windows) */
#define DRIVERMINREV      0             /*  driver revision level minor */

/*  Definitions of the various block transfer command codes */
#define TM_EXTTOHOST    8               /*  extended tohost */
#define TM_EXTTO1401    9               /*  extended to1401 */

/*  Definitions of values in usbReqtype. Used in sorting out setup actions */
#define H_TO_D 0x00
#define D_TO_H 0x80
#define VENDOR 0x40
#define DEVREQ 0x00
#define INTREQ 0x01
#define ENDREQ 0x02

/*  Definition of values in usbRequest, again used to sort out setup */
#define GET_STATUS      0x00
#define CLEAR_FEATURE   0x01
#define SET_FEATURE     0x03
#define SET_ADDRESS     0x05
#define GET_DESC        0x06
#define SET_DESC        0x07
#define GET_CONF        0x08
#define SET_CONF        0x09
#define GET_INTERFACE   0x0a
#define SET_INTERFACE   0x0b
#define SYNCH_FRAME     0x0c

/*  Definitions of the various debug command codes understood by the 1401. These */
/*  are used in various vendor-specific commands to achieve the desired effect */
#define DB_GRAB         0x50            /* Grab is a NOP for USB */
#define DB_FREE         0x51            /* Free is a NOP for the USB */
#define DB_SETADD       0x52            /* Set debug address (double) */
#define DB_SELFTEST     0x53            /* Start self test */
#define DB_SETMASK      0x54            /* Set enable mask (double) */
#define DB_SETDEF       0x55            /* Set default mask (double) */
#define DB_PEEK         0x56            /* Peek address, save result */
#define DB_POKE         0x57            /* Poke address with data (double) */
#define DB_RAMPD        0x58            /* Ramp data at debug address */
#define DB_RAMPA        0x59            /* Ramp address bus */
#define DB_REPEATS      0x5A            /* Set repeats for operations (double) */
#define DB_WIDTH        0x5B            /* Set width for operations (byte) */
#define DB_DATA         0x5C            /* Get 4-byte data read by PEEK */
#define DB_CHARS        0x5D            /* Send chars via EP0 control write */

#define CR_CHAR          0x0D           /* The carriage return character */
#define CR_CHAR_80       0x8d           /*  and with bit 7 set */

/*  A structure holding information about a block of memory for use in circular transfers */
typedef struct circBlk {
	volatile UINT dwOffset;             /* Offset within area of block start */
	volatile UINT dwSize;               /* Size of the block, in bytes (0 = unused) */
} CIRCBLK;

/*  A structure holding all of the information about a transfer area - an area of */
/*   memory set up for use either as a source or destination in DMA transfers. */
typedef struct transarea {
	void	*lpvBuff;                /*  User address of xfer area saved for completeness */
	UINT        dwBaseOffset;           /*  offset to start of xfer area in first page */
	UINT        dwLength;               /*  Length of xfer area, in bytes */
	struct page **pPages;               /*  Points at array of locked down pages */
	int         nPages;                 /*  number of pages that are locked down */
	bool        bUsed;                  /*  Is this structure in use? */
	bool        bCircular;              /*  Is this area for circular transfers? */
	bool        bCircToHost;            /*  Flag for direction of circular transfer */
	bool        bEventToHost;           /*  Set event on transfer to host? */
	int         iWakeUp;                /*  Set 1 on event, cleared by TestEvent() */
	UINT        dwEventSt;              /*  Defines section within xfer area for... */
	UINT        dwEventSz;              /*  ...notification by the event SZ is 0 if unset */
	CIRCBLK     aBlocks[2];             /*  Info on a pair of circular blocks */
	wait_queue_head_t wqEvent;          /*  The wait queue for events in this area MUST BE LAST */
} TRANSAREA;

/*  The DMADESC structure is used to hold information on the transfer in progress. It */
/*  is set up by ReadDMAInfo, using information sent by the 1401 in an escape sequence. */
typedef struct dmadesc {
	unsigned short wTransType;          /* transfer type as TM_xxx above        */
	unsigned short wIdent;              /* identifier word                      */
	unsigned int   dwSize;              /* bytes to transfer                    */
	unsigned int   dwOffset;            /* offset into transfer area for trans  */
	bool           bOutWard;            /* true when data is going TO 1401      */
} DMADESC;

#define INBUF_SZ         256            /* input buffer size */
#define OUTBUF_SZ        256            /* output buffer size */
#define STAGED_SZ 0x10000               /*  size of coherent buffer for staged transfers */

/*  Structure to hold all of our device specific stuff. We are making this as similar as we */
/*  can to the Windows driver to help in our understanding of what is going on. */
typedef struct _DEVICE_EXTENSION {
	char inputBuffer[INBUF_SZ];         /* The two buffers */
	char outputBuffer[OUTBUF_SZ];       /* accessed by the host functions */
	volatile unsigned int dwNumInput;   /* num of chars in input buffer   */
	volatile unsigned int dwInBuffGet;  /* where to get from input buffer */
	volatile unsigned int dwInBuffPut;  /* where to put into input buffer */
	volatile unsigned int dwNumOutput;  /* num of chars in output buffer  */
	volatile unsigned int dwOutBuffGet; /* where to get from output buffer*/
	volatile unsigned int dwOutBuffPut; /* where to put into output buffer*/

	volatile bool bSendCharsPending;    /* Flag to indicate sendchar active */
	volatile bool bReadCharsPending;    /* Flag to indicate a read is primed */
	char *pCoherCharOut;                /* special aligned buffer for chars to 1401 */
	struct urb *pUrbCharOut;            /* urb used for chars to 1401 */
	char *pCoherCharIn;                 /* special aligned buffer for chars to host */
	struct urb *pUrbCharIn;             /* urb used for chars to host */

	spinlock_t charOutLock;             /* to protect the outputBuffer and outputting */
	spinlock_t charInLock;              /* to protect the inputBuffer and char reads */
	__u8 bInterval;                     /* Interrupt end point interval */

	volatile unsigned int dwDMAFlag;    /* state of DMA */
	TRANSAREA rTransDef[MAX_TRANSAREAS];/* transfer area info */
	volatile DMADESC rDMAInfo;          /*  info on current DMA transfer */
	volatile bool bXFerWaiting;         /*  Flag set if DMA transfer stalled */
	volatile bool bInDrawDown;          /*  Flag that we want to halt transfers */

	/*  Parameters relating to a block read\write that is in progress. Some of these values */
	/*   are equivalent to values in rDMAInfo. The values here are those in use, while those */
	/*   in rDMAInfo are those received from the 1401 via an escape sequence. If another */
	/*   escape sequence arrives before the previous xfer ends, rDMAInfo values are updated while these */
	/*   are used to finish off the current transfer. */
	volatile short StagedId;            /*  The transfer area id for this transfer */
	volatile bool StagedRead;           /*  Flag TRUE for read from 1401, FALSE for write */
	volatile unsigned int StagedLength; /*  Total length of this transfer */
	volatile unsigned int StagedOffset; /*  Offset within memory area for transfer start */
	volatile unsigned int StagedDone;   /*  Bytes transferred so far */
	volatile bool bStagedUrbPending;    /*  Flag to indicate active */
	char *pCoherStagedIO;               /*  buffer used for block transfers */
	struct urb *pStagedUrb;             /*  The URB to use */
	spinlock_t stagedLock;              /*  protects ReadWriteMem() and circular buffer stuff */

	short s1401Type;                    /*  type of 1401 attached */
	short sCurrentState;                /*  current error state */
	bool bIsUSB2;                       /*  type of the interface we connect to */
	bool bForceReset;                   /*  Flag to make sure we get a real reset */
	__u32 statBuf[2];                   /*  buffer for 1401 state info */

	unsigned long ulSelfTestTime;       /*  used to timeout self test */

	int nPipes;                         /*  Should be 3 or 4 depending on 1401 usb chip */
	int bPipeError[4];                  /*  set non-zero if an error on one of the pipe */
	__u8 epAddr[4];                     /*  addresses of the 3/4 end points */

	struct usb_device *udev;            /*  the usb device for this device */
	struct usb_interface *interface;    /*  the interface for this device, NULL if removed */
	struct usb_anchor submitted;        /*  in case we need to retract our submissions */
	struct mutex io_mutex;              /*  synchronize I/O with disconnect, one user-mode caller at a time */

	int    errors;                      /*  the last request tanked */
	int    open_count;                  /*  count the number of openers */
	spinlock_t err_lock;                /*  lock for errors */
	struct kref kref;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
#define to_DEVICE_EXTENSION(d) container_of(d, DEVICE_EXTENSION, kref)

/*  Definitions of routimes used between compilation object files */
/*  in usb1401.c */
extern int Allowi(DEVICE_EXTENSION *pdx);
extern int SendChars(DEVICE_EXTENSION *pdx);
extern void ced_draw_down(DEVICE_EXTENSION *pdx);
extern int ReadWriteMem(DEVICE_EXTENSION *pdx, bool Read, unsigned short wIdent,
				unsigned int dwOffs, unsigned int dwLen);

/*  in ced_ioc.c */
extern int ClearArea(DEVICE_EXTENSION *pdx, int nArea);
extern int SendString(DEVICE_EXTENSION *pdx, const char __user *pData, unsigned int n);
extern int SendChar(DEVICE_EXTENSION *pdx, char c);
extern int Get1401State(DEVICE_EXTENSION *pdx, __u32 *state, __u32 *error);
extern int ReadWrite_Cancel(DEVICE_EXTENSION *pdx);
extern bool Is1401(DEVICE_EXTENSION *pdx);
extern bool QuickCheck(DEVICE_EXTENSION *pdx, bool bTestBuff, bool bCanReset);
extern int Reset1401(DEVICE_EXTENSION *pdx);
extern int GetChar(DEVICE_EXTENSION *pdx);
extern int GetString(DEVICE_EXTENSION *pdx, char __user *pUser, int n);
extern int SetTransfer(DEVICE_EXTENSION *pdx, TRANSFERDESC __user *pTD);
extern int UnsetTransfer(DEVICE_EXTENSION *pdx, int nArea);
extern int SetEvent(DEVICE_EXTENSION *pdx, TRANSFEREVENT __user *pTE);
extern int Stat1401(DEVICE_EXTENSION *pdx);
extern int LineCount(DEVICE_EXTENSION *pdx);
extern int GetOutBufSpace(DEVICE_EXTENSION *pdx);
extern int GetTransfer(DEVICE_EXTENSION *pdx, TGET_TX_BLOCK __user *pGTB);
extern int KillIO1401(DEVICE_EXTENSION *pdx);
extern int BlkTransState(DEVICE_EXTENSION *pdx);
extern int StateOf1401(DEVICE_EXTENSION *pdx);
extern int StartSelfTest(DEVICE_EXTENSION *pdx);
extern int CheckSelfTest(DEVICE_EXTENSION *pdx, TGET_SELFTEST __user *pGST);
extern int TypeOf1401(DEVICE_EXTENSION *pdx);
extern int TransferFlags(DEVICE_EXTENSION *pdx);
extern int DbgPeek(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB);
extern int DbgPoke(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB);
extern int DbgRampData(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB);
extern int DbgRampAddr(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB);
extern int DbgGetData(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB);
extern int DbgStopLoop(DEVICE_EXTENSION *pdx);
extern int SetCircular(DEVICE_EXTENSION *pdx, TRANSFERDESC __user *pTD);
extern int GetCircBlock(DEVICE_EXTENSION *pdx, TCIRCBLOCK __user *pCB);
extern int FreeCircBlock(DEVICE_EXTENSION *pdx, TCIRCBLOCK __user *pCB);
extern int WaitEvent(DEVICE_EXTENSION *pdx, int nArea, int msTimeOut);
extern int TestEvent(DEVICE_EXTENSION *pdx, int nArea);
#endif