247 lines
13 KiB
C
247 lines
13 KiB
C
/* 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
|