A basic Lindent run on the .c files, clean up the .h file by hand.
Cc: Alois Schlögl <alois.schloegl@ist.ac.at>
Cc: Greg P. Smith <greg@ced.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
**
** Empties the Output buffer and sets int lines. Used from user level only
****************************************************************************/
-void FlushOutBuff(DEVICE_EXTENSION *pdx)
+void FlushOutBuff(DEVICE_EXTENSION * pdx)
{
- dev_dbg(&pdx->interface->dev, "%s currentState=%d", __func__, pdx->sCurrentState);
- if (pdx->sCurrentState == U14ERR_TIME) /* Do nothing if hardware in trouble */
- return;
+ dev_dbg(&pdx->interface->dev, "%s currentState=%d", __func__,
+ pdx->sCurrentState);
+ if (pdx->sCurrentState == U14ERR_TIME) /* Do nothing if hardware in trouble */
+ return;
// CharSend_Cancel(pdx); /* Kill off any pending I/O */
- spin_lock_irq(&pdx->charOutLock);
- pdx->dwNumOutput = 0;
- pdx->dwOutBuffGet = 0;
- pdx->dwOutBuffPut = 0;
- spin_unlock_irq(&pdx->charOutLock);
+ spin_lock_irq(&pdx->charOutLock);
+ pdx->dwNumOutput = 0;
+ pdx->dwOutBuffGet = 0;
+ pdx->dwOutBuffPut = 0;
+ spin_unlock_irq(&pdx->charOutLock);
}
/****************************************************************************
**
** Empties the input buffer and sets int lines
****************************************************************************/
-void FlushInBuff(DEVICE_EXTENSION *pdx)
+void FlushInBuff(DEVICE_EXTENSION * pdx)
{
- dev_dbg(&pdx->interface->dev, "%s currentState=%d", __func__, pdx->sCurrentState);
- if (pdx->sCurrentState == U14ERR_TIME) /* Do nothing if hardware in trouble */
- return;
+ dev_dbg(&pdx->interface->dev, "%s currentState=%d", __func__,
+ pdx->sCurrentState);
+ if (pdx->sCurrentState == U14ERR_TIME) /* Do nothing if hardware in trouble */
+ return;
// CharRead_Cancel(pDevObject); /* Kill off any pending I/O */
- spin_lock_irq(&pdx->charInLock);
- pdx->dwNumInput = 0;
- pdx->dwInBuffGet = 0;
- pdx->dwInBuffPut = 0;
- spin_unlock_irq(&pdx->charInLock);
+ spin_lock_irq(&pdx->charInLock);
+ pdx->dwNumInput = 0;
+ pdx->dwInBuffGet = 0;
+ pdx->dwInBuffPut = 0;
+ spin_unlock_irq(&pdx->charInLock);
}
/****************************************************************************
** Utility routine to copy chars into the output buffer and fire them off.
** called from user mode, holds charOutLock.
****************************************************************************/
-static int PutChars(DEVICE_EXTENSION* pdx, const char* pCh, unsigned int uCount)
+static int PutChars(DEVICE_EXTENSION * pdx, const char *pCh,
+ unsigned int uCount)
{
- int iReturn;
- spin_lock_irq(&pdx->charOutLock); // get the output spin lock
- if ((OUTBUF_SZ - pdx->dwNumOutput) >= uCount)
- {
- unsigned int u;
- for (u=0; u<uCount; u++)
- {
- pdx->outputBuffer[pdx->dwOutBuffPut++] = pCh[u];
- if (pdx->dwOutBuffPut >= OUTBUF_SZ)
- pdx->dwOutBuffPut = 0;
- }
- pdx->dwNumOutput += uCount;
- spin_unlock_irq(&pdx->charOutLock);
- iReturn = SendChars(pdx); // ...give a chance to transmit data
- }
- else
- {
- iReturn = U14ERR_NOOUT; // no room at the out (ha-ha)
- spin_unlock_irq(&pdx->charOutLock);
- }
- return iReturn;
+ int iReturn;
+ spin_lock_irq(&pdx->charOutLock); // get the output spin lock
+ if ((OUTBUF_SZ - pdx->dwNumOutput) >= uCount) {
+ unsigned int u;
+ for (u = 0; u < uCount; u++) {
+ pdx->outputBuffer[pdx->dwOutBuffPut++] = pCh[u];
+ if (pdx->dwOutBuffPut >= OUTBUF_SZ)
+ pdx->dwOutBuffPut = 0;
+ }
+ pdx->dwNumOutput += uCount;
+ spin_unlock_irq(&pdx->charOutLock);
+ iReturn = SendChars(pdx); // ...give a chance to transmit data
+ } else {
+ iReturn = U14ERR_NOOUT; // no room at the out (ha-ha)
+ spin_unlock_irq(&pdx->charOutLock);
+ }
+ return iReturn;
}
/*****************************************************************************
** trigger an output transfer if this is appropriate. User mode.
** Holds the io_mutex
*****************************************************************************/
-int SendString(DEVICE_EXTENSION* pdx, const char __user* pData, unsigned int n)
+int SendString(DEVICE_EXTENSION * pdx, const char __user * pData,
+ unsigned int n)
{
- int iReturn = U14ERR_NOERROR; // assume all will be well
- char buffer[OUTBUF_SZ+1]; // space in our address space for characters
- if (n > OUTBUF_SZ) // check space in local buffer...
- return U14ERR_NOOUT; // ...too many characters
- if (copy_from_user(buffer, pData, n))
- return -ENOMEM; // could not copy
- buffer[n] = 0; // terminate for debug purposes
-
- mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o
- if (n > 0) // do nothing if nowt to do!
- {
- dev_dbg(&pdx->interface->dev, "%s n=%d>%s<", __func__, n, buffer);
- iReturn = PutChars(pdx, buffer, n);
- }
-
- Allowi(pdx, false); // make sure we have input int
- mutex_unlock(&pdx->io_mutex);
-
- return iReturn;
+ int iReturn = U14ERR_NOERROR; // assume all will be well
+ char buffer[OUTBUF_SZ + 1]; // space in our address space for characters
+ if (n > OUTBUF_SZ) // check space in local buffer...
+ return U14ERR_NOOUT; // ...too many characters
+ if (copy_from_user(buffer, pData, n))
+ return -ENOMEM; // could not copy
+ buffer[n] = 0; // terminate for debug purposes
+
+ mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o
+ if (n > 0) // do nothing if nowt to do!
+ {
+ dev_dbg(&pdx->interface->dev, "%s n=%d>%s<", __func__, n,
+ buffer);
+ iReturn = PutChars(pdx, buffer, n);
+ }
+
+ Allowi(pdx, false); // make sure we have input int
+ mutex_unlock(&pdx->io_mutex);
+
+ return iReturn;
}
/****************************************************************************
**
** Sends a single character to the 1401. User mode, holds io_mutex.
****************************************************************************/
-int SendChar(DEVICE_EXTENSION *pdx, char c)
+int SendChar(DEVICE_EXTENSION * pdx, char c)
{
- int iReturn;
- mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o
- iReturn = PutChars(pdx, &c, 1);
- dev_dbg(&pdx->interface->dev,"SendChar >%c< (0x%02x)", c, c);
- Allowi(pdx, false); // Make sure char reads are running
- mutex_unlock(&pdx->io_mutex);
- return iReturn;
+ int iReturn;
+ mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o
+ iReturn = PutChars(pdx, &c, 1);
+ dev_dbg(&pdx->interface->dev, "SendChar >%c< (0x%02x)", c, c);
+ Allowi(pdx, false); // Make sure char reads are running
+ mutex_unlock(&pdx->io_mutex);
+ return iReturn;
}
/***************************************************************************
**
** return error code (U14ERR_NOERROR for OK)
*/
-int Get1401State(DEVICE_EXTENSION* pdx, __u32* state, __u32* error)
+int Get1401State(DEVICE_EXTENSION * pdx, __u32 * state, __u32 * error)
{
- int nGot;
- dev_dbg(&pdx->interface->dev, "Get1401State() entry");
-
- *state = 0xFFFFFFFF; // Start off with invalid state
- nGot = usb_control_msg(pdx->udev, usb_rcvctrlpipe(pdx->udev, 0),
- GET_STATUS, (D_TO_H|VENDOR|DEVREQ), 0,0,
- pdx->statBuf, sizeof(pdx->statBuf), HZ);
- if (nGot != sizeof(pdx->statBuf))
- {
- dev_err(&pdx->interface->dev, "Get1401State() FAILED, return code %d", nGot);
- pdx->sCurrentState = U14ERR_TIME; // Indicate that things are very wrong indeed
- *state = 0; // Force status values to a known state
- *error = 0;
- }
- else
- {
- int nDevice;
- dev_dbg(&pdx->interface->dev, "Get1401State() Success, state: 0x%x, 0x%x",
- pdx->statBuf[0], pdx->statBuf[1]);
-
- *state = pdx->statBuf[0]; // Return the state values to the calling code
- *error = pdx->statBuf[1];
-
- nDevice = pdx->udev->descriptor.bcdDevice >> 8; // 1401 type code value
- switch (nDevice) // so we can clean up current state
- {
- case 0:
- pdx->sCurrentState = U14ERR_U1401;
- break;
-
- default: // allow lots of device codes for future 1401s
- if ((nDevice >= 1) && (nDevice <= 23))
- pdx->sCurrentState = (short)(nDevice + 6);
- else
- pdx->sCurrentState = U14ERR_ILL;
- break;
- }
- }
-
- return pdx->sCurrentState >= 0 ? U14ERR_NOERROR : pdx->sCurrentState;
+ int nGot;
+ dev_dbg(&pdx->interface->dev, "Get1401State() entry");
+
+ *state = 0xFFFFFFFF; // Start off with invalid state
+ nGot = usb_control_msg(pdx->udev, usb_rcvctrlpipe(pdx->udev, 0),
+ GET_STATUS, (D_TO_H | VENDOR | DEVREQ), 0, 0,
+ pdx->statBuf, sizeof(pdx->statBuf), HZ);
+ if (nGot != sizeof(pdx->statBuf)) {
+ dev_err(&pdx->interface->dev,
+ "Get1401State() FAILED, return code %d", nGot);
+ pdx->sCurrentState = U14ERR_TIME; // Indicate that things are very wrong indeed
+ *state = 0; // Force status values to a known state
+ *error = 0;
+ } else {
+ int nDevice;
+ dev_dbg(&pdx->interface->dev,
+ "Get1401State() Success, state: 0x%x, 0x%x",
+ pdx->statBuf[0], pdx->statBuf[1]);
+
+ *state = pdx->statBuf[0]; // Return the state values to the calling code
+ *error = pdx->statBuf[1];
+
+ nDevice = pdx->udev->descriptor.bcdDevice >> 8; // 1401 type code value
+ switch (nDevice) // so we can clean up current state
+ {
+ case 0:
+ pdx->sCurrentState = U14ERR_U1401;
+ break;
+
+ default: // allow lots of device codes for future 1401s
+ if ((nDevice >= 1) && (nDevice <= 23))
+ pdx->sCurrentState = (short)(nDevice + 6);
+ else
+ pdx->sCurrentState = U14ERR_ILL;
+ break;
+ }
+ }
+
+ return pdx->sCurrentState >= 0 ? U14ERR_NOERROR : pdx->sCurrentState;
}
/****************************************************************************
**
** Kills off staged read\write request from the USB if one is pending.
****************************************************************************/
-int ReadWrite_Cancel(DEVICE_EXTENSION *pdx)
+int ReadWrite_Cancel(DEVICE_EXTENSION * pdx)
{
- dev_dbg(&pdx->interface->dev, "ReadWrite_Cancel entry %d", pdx->bStagedUrbPending);
+ dev_dbg(&pdx->interface->dev, "ReadWrite_Cancel entry %d",
+ pdx->bStagedUrbPending);
#ifdef NOT_WRITTEN_YET
- int ntStatus = STATUS_SUCCESS;
- bool bResult = false;
- unsigned int i;
- // We can fill this in when we know how we will implement the staged transfer stuff
- spin_lock_irq(&pdx->stagedLock);
-
- if (pdx->bStagedUrbPending) // anything to be cancelled? May need more...
- {
- dev_info(&pdx->interface-dev, "ReadWrite_Cancel about to cancel Urb");
-
- // KeClearEvent(&pdx->StagingDoneEvent); // Clear the staging done flag
- USB_ASSERT(pdx->pStagedIrp != NULL);
-
- // Release the spinlock first otherwise the completion routine may hang
- // on the spinlock while this function hands waiting for the event.
- spin_unlock_irq(&pdx->stagedLock);
- bResult = IoCancelIrp(pdx->pStagedIrp); // Actually do the cancel
- if (bResult)
- {
- LARGE_INTEGER timeout;
- timeout.QuadPart = -10000000; // Use a timeout of 1 second
- dev_info(&pdx->interface-dev, "ReadWrite_Cancel about to wait till done");
- ntStatus = KeWaitForSingleObject(&pdx->StagingDoneEvent, Executive,
- KernelMode, FALSE, &timeout);
- }
- else
- {
- dev_info(&pdx->interface-dev, "ReadWrite_Cancel, cancellation failed");
- ntStatus = U14ERR_FAIL;
- }
- USB_KdPrint(DBGLVL_DEFAULT, ("ReadWrite_Cancel ntStatus = 0x%x decimal %d\n", ntStatus, ntStatus));
- }
- else
- spin_unlock_irq(&pdx->stagedLock);
-
- dev_info(&pdx->interface-dev, "ReadWrite_Cancel done");
- return ntStatus;
+ int ntStatus = STATUS_SUCCESS;
+ bool bResult = false;
+ unsigned int i;
+ // We can fill this in when we know how we will implement the staged transfer stuff
+ spin_lock_irq(&pdx->stagedLock);
+
+ if (pdx->bStagedUrbPending) // anything to be cancelled? May need more...
+ {
+ dev_info(&pdx->interface - dev,
+ "ReadWrite_Cancel about to cancel Urb");
+
+ // KeClearEvent(&pdx->StagingDoneEvent); // Clear the staging done flag
+ USB_ASSERT(pdx->pStagedIrp != NULL);
+
+ // Release the spinlock first otherwise the completion routine may hang
+ // on the spinlock while this function hands waiting for the event.
+ spin_unlock_irq(&pdx->stagedLock);
+ bResult = IoCancelIrp(pdx->pStagedIrp); // Actually do the cancel
+ if (bResult) {
+ LARGE_INTEGER timeout;
+ timeout.QuadPart = -10000000; // Use a timeout of 1 second
+ dev_info(&pdx->interface - dev,
+ "ReadWrite_Cancel about to wait till done");
+ ntStatus =
+ KeWaitForSingleObject(&pdx->StagingDoneEvent,
+ Executive, KernelMode, FALSE,
+ &timeout);
+ } else {
+ dev_info(&pdx->interface - dev,
+ "ReadWrite_Cancel, cancellation failed");
+ ntStatus = U14ERR_FAIL;
+ }
+ USB_KdPrint(DBGLVL_DEFAULT,
+ ("ReadWrite_Cancel ntStatus = 0x%x decimal %d\n",
+ ntStatus, ntStatus));
+ } else
+ spin_unlock_irq(&pdx->stagedLock);
+
+ dev_info(&pdx->interface - dev, "ReadWrite_Cancel done");
+ return ntStatus;
#else
- return U14ERR_NOERROR;
+ return U14ERR_NOERROR;
#endif
}
** InSelfTest - utility to check in self test. Return 1 for ST, 0 for not or
** a -ve error code if we failed for some reason.
***************************************************************************/
-static int InSelfTest(DEVICE_EXTENSION* pdx, unsigned int* pState)
+static int InSelfTest(DEVICE_EXTENSION * pdx, unsigned int *pState)
{
- unsigned int state, error;
- int iReturn = Get1401State(pdx, &state, &error); // see if in self-test
- if (iReturn == U14ERR_NOERROR) // if all still OK
- iReturn = (state == (unsigned int)-1) || // TX problem or...
- ((state & 0xff) == 0x80); // ...self test
- *pState = state; // return actual state
- return iReturn;
+ unsigned int state, error;
+ int iReturn = Get1401State(pdx, &state, &error); // see if in self-test
+ if (iReturn == U14ERR_NOERROR) // if all still OK
+ iReturn = (state == (unsigned int)-1) || // TX problem or...
+ ((state & 0xff) == 0x80); // ...self test
+ *pState = state; // return actual state
+ return iReturn;
}
/***************************************************************************
**
** Returns TRUE if a 1401 detected and OK, else FALSE
****************************************************************************/
-bool Is1401(DEVICE_EXTENSION* pdx)
+bool Is1401(DEVICE_EXTENSION * pdx)
{
- int iReturn;
- dev_dbg(&pdx->interface->dev, "%s", __func__);
-
- ced_draw_down(pdx); // wait for, then kill outstanding Urbs
- FlushInBuff(pdx); // Clear out input buffer & pipe
- FlushOutBuff(pdx); // Clear output buffer & pipe
-
- // The next call returns 0 if OK, but has returned 1 in the past, meaning that
- // usb_unlock_device() is needed... now it always is
- iReturn = usb_lock_device_for_reset(pdx->udev, pdx->interface);
-
- // release the io_mutex because if we don't, we will deadlock due to system
- // calls back into the driver.
- mutex_unlock(&pdx->io_mutex); // locked, so we will not get system calls
- if (iReturn >= 0) // if we failed
- {
- iReturn = usb_reset_device(pdx->udev); // try to do the reset
- usb_unlock_device(pdx->udev); // undo the lock
- }
-
- mutex_lock(&pdx->io_mutex); // hold stuff off while we wait
- pdx->dwDMAFlag = MODE_CHAR; // Clear DMA mode flag regardless!
- if (iReturn == 0) // if all is OK still
- {
- unsigned int state;
- iReturn = InSelfTest(pdx, &state); // see if likely in self test
- if (iReturn > 0) // do we need to wait for self-test?
- {
- unsigned long ulTimeOut = jiffies + 30*HZ; // when to give up
- while((iReturn > 0) && time_before(jiffies, ulTimeOut))
- {
- schedule(); // let other stuff run
- iReturn = InSelfTest(pdx, &state); // see if done yet
- }
- }
-
- if (iReturn == 0) // if all is OK...
- iReturn = state == 0; // then sucess is that the state is 0
- }
- else
- iReturn = 0; // we failed
- pdx->bForceReset = false; // Clear forced reset flag now
-
- return iReturn > 0;
+ int iReturn;
+ dev_dbg(&pdx->interface->dev, "%s", __func__);
+
+ ced_draw_down(pdx); // wait for, then kill outstanding Urbs
+ FlushInBuff(pdx); // Clear out input buffer & pipe
+ FlushOutBuff(pdx); // Clear output buffer & pipe
+
+ // The next call returns 0 if OK, but has returned 1 in the past, meaning that
+ // usb_unlock_device() is needed... now it always is
+ iReturn = usb_lock_device_for_reset(pdx->udev, pdx->interface);
+
+ // release the io_mutex because if we don't, we will deadlock due to system
+ // calls back into the driver.
+ mutex_unlock(&pdx->io_mutex); // locked, so we will not get system calls
+ if (iReturn >= 0) // if we failed
+ {
+ iReturn = usb_reset_device(pdx->udev); // try to do the reset
+ usb_unlock_device(pdx->udev); // undo the lock
+ }
+
+ mutex_lock(&pdx->io_mutex); // hold stuff off while we wait
+ pdx->dwDMAFlag = MODE_CHAR; // Clear DMA mode flag regardless!
+ if (iReturn == 0) // if all is OK still
+ {
+ unsigned int state;
+ iReturn = InSelfTest(pdx, &state); // see if likely in self test
+ if (iReturn > 0) // do we need to wait for self-test?
+ {
+ unsigned long ulTimeOut = jiffies + 30 * HZ; // when to give up
+ while ((iReturn > 0) && time_before(jiffies, ulTimeOut)) {
+ schedule(); // let other stuff run
+ iReturn = InSelfTest(pdx, &state); // see if done yet
+ }
+ }
+
+ if (iReturn == 0) // if all is OK...
+ iReturn = state == 0; // then sucess is that the state is 0
+ } else
+ iReturn = 0; // we failed
+ pdx->bForceReset = false; // Clear forced reset flag now
+
+ return iReturn > 0;
}
/****************************************************************************
**
** The return value is TRUE if a useable 1401 is found, FALSE if not
*/
-bool QuickCheck(DEVICE_EXTENSION* pdx, bool bTestBuff, bool bCanReset)
+bool QuickCheck(DEVICE_EXTENSION * pdx, bool bTestBuff, bool bCanReset)
{
- bool bRet = false; // assume it will fail and we will reset
- bool bShortTest;
-
- bShortTest = ((pdx->dwDMAFlag == MODE_CHAR) && // no DMA running
- (!pdx->bForceReset) && // Not had a real reset forced
- (pdx->sCurrentState >= U14ERR_STD)); // No 1401 errors stored
-
- dev_dbg(&pdx->interface->dev, "%s DMAFlag:%d, state:%d, force:%d, testBuff:%d, short:%d",
- __func__, pdx->dwDMAFlag, pdx->sCurrentState, pdx->bForceReset, bTestBuff, bShortTest);
-
- if ((bTestBuff) && // Buffer check requested, and...
- (pdx->dwNumInput || pdx->dwNumOutput)) // ...characters were in the buffer?
- {
- bShortTest = false; // Then do the full test
- dev_dbg(&pdx->interface->dev, "%s will reset as buffers not empty", __func__);
- }
-
- if (bShortTest || !bCanReset) // Still OK to try the short test?
- { // Always test if no reset - we want state update
- unsigned int state, error;
- dev_dbg(&pdx->interface->dev, "%s->Get1401State", __func__);
- if (Get1401State(pdx, &state, &error) == U14ERR_NOERROR) // Check on the 1401 state
- {
- if ((state & 0xFF) == 0) // If call worked, check the status value
- bRet = true; // If that was zero, all is OK, no reset needed
- }
- }
-
- if (!bRet && bCanReset) // If all not OK, then
- {
- dev_info(&pdx->interface->dev, "%s->Is1401 %d %d %d %d",
- __func__, bShortTest, pdx->sCurrentState, bTestBuff, pdx->bForceReset);
- bRet = Is1401(pdx); // do full test
- }
-
- return bRet;
+ bool bRet = false; // assume it will fail and we will reset
+ bool bShortTest;
+
+ bShortTest = ((pdx->dwDMAFlag == MODE_CHAR) && // no DMA running
+ (!pdx->bForceReset) && // Not had a real reset forced
+ (pdx->sCurrentState >= U14ERR_STD)); // No 1401 errors stored
+
+ dev_dbg(&pdx->interface->dev,
+ "%s DMAFlag:%d, state:%d, force:%d, testBuff:%d, short:%d",
+ __func__, pdx->dwDMAFlag, pdx->sCurrentState, pdx->bForceReset,
+ bTestBuff, bShortTest);
+
+ if ((bTestBuff) && // Buffer check requested, and...
+ (pdx->dwNumInput || pdx->dwNumOutput)) // ...characters were in the buffer?
+ {
+ bShortTest = false; // Then do the full test
+ dev_dbg(&pdx->interface->dev,
+ "%s will reset as buffers not empty", __func__);
+ }
+
+ if (bShortTest || !bCanReset) // Still OK to try the short test?
+ { // Always test if no reset - we want state update
+ unsigned int state, error;
+ dev_dbg(&pdx->interface->dev, "%s->Get1401State", __func__);
+ if (Get1401State(pdx, &state, &error) == U14ERR_NOERROR) // Check on the 1401 state
+ {
+ if ((state & 0xFF) == 0) // If call worked, check the status value
+ bRet = true; // If that was zero, all is OK, no reset needed
+ }
+ }
+
+ if (!bRet && bCanReset) // If all not OK, then
+ {
+ dev_info(&pdx->interface->dev, "%s->Is1401 %d %d %d %d",
+ __func__, bShortTest, pdx->sCurrentState, bTestBuff,
+ pdx->bForceReset);
+ bRet = Is1401(pdx); // do full test
+ }
+
+ return bRet;
}
/****************************************************************************
**
** Resets the 1401 and empties the i/o buffers
*****************************************************************************/
-int Reset1401(DEVICE_EXTENSION *pdx)
+int Reset1401(DEVICE_EXTENSION * pdx)
{
- mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o
- dev_dbg(&pdx->interface->dev,"ABout to call QuickCheck");
- QuickCheck(pdx, true, true); // Check 1401, reset if not OK
- mutex_unlock(&pdx->io_mutex);
- return U14ERR_NOERROR;
+ mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o
+ dev_dbg(&pdx->interface->dev, "ABout to call QuickCheck");
+ QuickCheck(pdx, true, true); // Check 1401, reset if not OK
+ mutex_unlock(&pdx->io_mutex);
+ return U14ERR_NOERROR;
}
/****************************************************************************
**
** Gets a single character from the 1401
****************************************************************************/
-int GetChar(DEVICE_EXTENSION *pdx)
+int GetChar(DEVICE_EXTENSION * pdx)
{
- int iReturn = U14ERR_NOIN; // assume we will get nothing
- mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o
-
- dev_dbg(&pdx->interface->dev, "GetChar");
-
- Allowi(pdx, false); // Make sure char reads are running
- SendChars(pdx); // and send any buffered chars
-
- spin_lock_irq(&pdx->charInLock);
- if (pdx->dwNumInput > 0) // worth looking
- {
- iReturn = pdx->inputBuffer[pdx->dwInBuffGet++];
- if (pdx->dwInBuffGet >= INBUF_SZ)
- pdx->dwInBuffGet = 0;
- pdx->dwNumInput--;
- }
- else
- iReturn = U14ERR_NOIN; // no input data to read
- spin_unlock_irq(&pdx->charInLock);
-
- Allowi(pdx, false); // Make sure char reads are running
-
- mutex_unlock(&pdx->io_mutex); // Protect disconnect from new i/o
- return iReturn;
+ int iReturn = U14ERR_NOIN; // assume we will get nothing
+ mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o
+
+ dev_dbg(&pdx->interface->dev, "GetChar");
+
+ Allowi(pdx, false); // Make sure char reads are running
+ SendChars(pdx); // and send any buffered chars
+
+ spin_lock_irq(&pdx->charInLock);
+ if (pdx->dwNumInput > 0) // worth looking
+ {
+ iReturn = pdx->inputBuffer[pdx->dwInBuffGet++];
+ if (pdx->dwInBuffGet >= INBUF_SZ)
+ pdx->dwInBuffGet = 0;
+ pdx->dwNumInput--;
+ } else
+ iReturn = U14ERR_NOIN; // no input data to read
+ spin_unlock_irq(&pdx->charInLock);
+
+ Allowi(pdx, false); // Make sure char reads are running
+
+ mutex_unlock(&pdx->io_mutex); // Protect disconnect from new i/o
+ return iReturn;
}
/****************************************************************************
** returns the count of characters (including the terminator, or 0 if none
** or a negative error code.
****************************************************************************/
-int GetString(DEVICE_EXTENSION *pdx, char __user* pUser, int n)
+int GetString(DEVICE_EXTENSION * pdx, char __user * pUser, int n)
{
- int nAvailable; // character in the buffer
- int iReturn = U14ERR_NOIN;
- if (n <= 0)
- return -ENOMEM;
-
- mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o
- Allowi(pdx, false); // Make sure char reads are running
- SendChars(pdx); // and send any buffered chars
-
- spin_lock_irq(&pdx->charInLock);
- nAvailable = pdx->dwNumInput; // characters available now
- if (nAvailable > n) // read max of space in pUser...
- nAvailable = n; // ...or input characters
-
- if (nAvailable > 0) // worth looking?
- {
- char buffer[INBUF_SZ+1]; // space for a linear copy of data
- int nGot = 0;
- int nCopyToUser; // number to copy to user
- char cData;
- do
- {
- cData = pdx->inputBuffer[pdx->dwInBuffGet++];
- if (cData == CR_CHAR) // replace CR with zero
- cData = (char)0;
-
- if (pdx->dwInBuffGet >= INBUF_SZ)
- pdx->dwInBuffGet = 0; // wrap buffer pointer
-
- buffer[nGot++] = cData; // save the output
- }
- while((nGot < nAvailable) && cData);
-
- nCopyToUser = nGot; // what to copy...
- if (cData) // do we need null
- {
- buffer[nGot] = (char)0; // make it tidy
- if (nGot < n) // if space in user buffer...
- ++nCopyToUser; // ...copy the 0 as well.
- }
-
- pdx->dwNumInput -= nGot;
- spin_unlock_irq(&pdx->charInLock);
-
- dev_dbg(&pdx->interface->dev,"GetString read %d characters >%s<", nGot, buffer);
- copy_to_user(pUser, buffer, nCopyToUser);
-
- iReturn = nGot; // report characters read
- }
- else
- spin_unlock_irq(&pdx->charInLock);
-
- Allowi(pdx, false); // Make sure char reads are running
- mutex_unlock(&pdx->io_mutex); // Protect disconnect from new i/o
-
- return iReturn;
+ int nAvailable; // character in the buffer
+ int iReturn = U14ERR_NOIN;
+ if (n <= 0)
+ return -ENOMEM;
+
+ mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o
+ Allowi(pdx, false); // Make sure char reads are running
+ SendChars(pdx); // and send any buffered chars
+
+ spin_lock_irq(&pdx->charInLock);
+ nAvailable = pdx->dwNumInput; // characters available now
+ if (nAvailable > n) // read max of space in pUser...
+ nAvailable = n; // ...or input characters
+
+ if (nAvailable > 0) // worth looking?
+ {
+ char buffer[INBUF_SZ + 1]; // space for a linear copy of data
+ int nGot = 0;
+ int nCopyToUser; // number to copy to user
+ char cData;
+ do {
+ cData = pdx->inputBuffer[pdx->dwInBuffGet++];
+ if (cData == CR_CHAR) // replace CR with zero
+ cData = (char)0;
+
+ if (pdx->dwInBuffGet >= INBUF_SZ)
+ pdx->dwInBuffGet = 0; // wrap buffer pointer
+
+ buffer[nGot++] = cData; // save the output
+ }
+ while ((nGot < nAvailable) && cData);
+
+ nCopyToUser = nGot; // what to copy...
+ if (cData) // do we need null
+ {
+ buffer[nGot] = (char)0; // make it tidy
+ if (nGot < n) // if space in user buffer...
+ ++nCopyToUser; // ...copy the 0 as well.
+ }
+
+ pdx->dwNumInput -= nGot;
+ spin_unlock_irq(&pdx->charInLock);
+
+ dev_dbg(&pdx->interface->dev,
+ "GetString read %d characters >%s<", nGot, buffer);
+ copy_to_user(pUser, buffer, nCopyToUser);
+
+ iReturn = nGot; // report characters read
+ } else
+ spin_unlock_irq(&pdx->charInLock);
+
+ Allowi(pdx, false); // Make sure char reads are running
+ mutex_unlock(&pdx->io_mutex); // Protect disconnect from new i/o
+
+ return iReturn;
}
/*******************************************************************************
** Get count of characters in the inout buffer.
*******************************************************************************/
-int Stat1401(DEVICE_EXTENSION *pdx)
+int Stat1401(DEVICE_EXTENSION * pdx)
{
- int iReturn;
- mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o
- Allowi(pdx, false); // make sure we allow pending chars
- SendChars(pdx); // in both directions
- iReturn = pdx->dwNumInput; // no lock as single read
- mutex_unlock(&pdx->io_mutex); // Protect disconnect from new i/o
- return iReturn;
+ int iReturn;
+ mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o
+ Allowi(pdx, false); // make sure we allow pending chars
+ SendChars(pdx); // in both directions
+ iReturn = pdx->dwNumInput; // no lock as single read
+ mutex_unlock(&pdx->io_mutex); // Protect disconnect from new i/o
+ return iReturn;
}
/****************************************************************************
** any fancy interlocks as we only read the interrupt routine data, and the
** system is arranged so nothing can be destroyed.
****************************************************************************/
-int LineCount(DEVICE_EXTENSION *pdx)
+int LineCount(DEVICE_EXTENSION * pdx)
{
- int iReturn = 0; // will be count of line ends
-
- mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o
- Allowi(pdx, false); // Make sure char reads are running
- SendChars(pdx); // and send any buffered chars
- spin_lock_irq(&pdx->charInLock); // Get protection
-
- if (pdx->dwNumInput > 0) // worth looking?
- {
- unsigned int dwIndex = pdx->dwInBuffGet;// start at first available
- unsigned int dwEnd = pdx->dwInBuffPut; // Position for search end
- do
- {
- if (pdx->inputBuffer[dwIndex++] == CR_CHAR)
- ++iReturn; // inc count if CR
-
- if (dwIndex >= INBUF_SZ) // see if we fall off buff
- dwIndex = 0;
- }
- while (dwIndex != dwEnd); // go to last avaliable
- }
-
- spin_unlock_irq(&pdx->charInLock);
- dev_dbg(&pdx->interface->dev,"LineCount returned %d", iReturn);
- mutex_unlock(&pdx->io_mutex); // Protect disconnect from new i/o
- return iReturn;
+ int iReturn = 0; // will be count of line ends
+
+ mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o
+ Allowi(pdx, false); // Make sure char reads are running
+ SendChars(pdx); // and send any buffered chars
+ spin_lock_irq(&pdx->charInLock); // Get protection
+
+ if (pdx->dwNumInput > 0) // worth looking?
+ {
+ unsigned int dwIndex = pdx->dwInBuffGet; // start at first available
+ unsigned int dwEnd = pdx->dwInBuffPut; // Position for search end
+ do {
+ if (pdx->inputBuffer[dwIndex++] == CR_CHAR)
+ ++iReturn; // inc count if CR
+
+ if (dwIndex >= INBUF_SZ) // see if we fall off buff
+ dwIndex = 0;
+ }
+ while (dwIndex != dwEnd); // go to last avaliable
+ }
+
+ spin_unlock_irq(&pdx->charInLock);
+ dev_dbg(&pdx->interface->dev, "LineCount returned %d", iReturn);
+ mutex_unlock(&pdx->io_mutex); // Protect disconnect from new i/o
+ return iReturn;
}
/****************************************************************************
**
** Gets the space in the output buffer. Called from user code.
*****************************************************************************/
-int GetOutBufSpace(DEVICE_EXTENSION *pdx)
+int GetOutBufSpace(DEVICE_EXTENSION * pdx)
{
- int iReturn;
- mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o
- SendChars(pdx); // send any buffered chars
- iReturn = (int)(OUTBUF_SZ - pdx->dwNumOutput); // no lock needed for single read
- dev_dbg(&pdx->interface->dev,"OutBufSpace %d", iReturn);
- mutex_unlock(&pdx->io_mutex); // Protect disconnect from new i/o
- return iReturn;
+ int iReturn;
+ mutex_lock(&pdx->io_mutex); // Protect disconnect from new i/o
+ SendChars(pdx); // send any buffered chars
+ iReturn = (int)(OUTBUF_SZ - pdx->dwNumOutput); // no lock needed for single read
+ dev_dbg(&pdx->interface->dev, "OutBufSpace %d", iReturn);
+ mutex_unlock(&pdx->io_mutex); // Protect disconnect from new i/o
+ return iReturn;
}
/****************************************************************************
** Clears up a transfer area. This is always called in the context of a user
** request, never from a call-back.
****************************************************************************/
-int ClearArea(DEVICE_EXTENSION *pdx, int nArea)
+int ClearArea(DEVICE_EXTENSION * pdx, int nArea)
{
- int iReturn = U14ERR_NOERROR;
-
- if ((nArea < 0) || (nArea >= MAX_TRANSAREAS))
- {
- iReturn = U14ERR_BADAREA;
- dev_err(&pdx->interface->dev, "%s Attempt to clear area %d", __func__, nArea);
- }
- else
- {
- TRANSAREA *pTA = &pdx->rTransDef[nArea]; // to save typing
- if (!pTA->bUsed) // if not used...
- iReturn = U14ERR_NOTSET; // ...nothing to be done
- else
- {
- // We must save the memory we return as we shouldn't mess with memory while
- // holding a spin lock.
- struct page **pPages = 0; // save page address list
- int nPages = 0; // and number of pages
- int np;
-
- dev_dbg(&pdx->interface->dev, "%s area %d", __func__, nArea);
- spin_lock_irq(&pdx->stagedLock);
- if ((pdx->StagedId == nArea) && (pdx->dwDMAFlag > MODE_CHAR))
- {
- iReturn = U14ERR_UNLOCKFAIL; // cannot delete as in use
- dev_err(&pdx->interface->dev, "%s call on area %d while active", __func__, nArea);
- }
- else
- {
- pPages = pTA->pPages; // save page address list
- nPages = pTA->nPages; // and page count
- if (pTA->dwEventSz) // if events flagging in use
- wake_up_interruptible(&pTA->wqEvent); // release anything that was waiting
-
- if (pdx->bXFerWaiting && (pdx->rDMAInfo.wIdent == nArea))
- pdx->bXFerWaiting = false; // Cannot have pending xfer if area cleared
-
- // Clean out the TRANSAREA except for the wait queue, which is at the end
- // This sets bUsed to false and dwEventSz to 0 to say area not used and no events.
- memset(pTA, 0, sizeof(TRANSAREA)-sizeof(wait_queue_head_t));
- }
- spin_unlock_irq(&pdx->stagedLock);
-
- if (pPages) // if we decided to release the memory
- {
- // Now we must undo the pinning down of the pages. We will assume the worst and mark
- // all the pages as dirty. Don't be tempted to move this up above as you must not be
- // holding a spin lock to do this stuff as it is not atomic.
- dev_dbg(&pdx->interface->dev, "%s nPages=%d", __func__, nPages);
-
- for (np = 0; np < nPages; ++np)
- {
- if (pPages[np])
- {
- SetPageDirty(pPages[np]);
- page_cache_release(pPages[np]);
- }
- }
-
- kfree(pPages);
- dev_dbg(&pdx->interface->dev, "%s kfree(pPages) done", __func__);
- }
- }
- }
-
- return iReturn;
+ int iReturn = U14ERR_NOERROR;
+
+ if ((nArea < 0) || (nArea >= MAX_TRANSAREAS)) {
+ iReturn = U14ERR_BADAREA;
+ dev_err(&pdx->interface->dev, "%s Attempt to clear area %d",
+ __func__, nArea);
+ } else {
+ TRANSAREA *pTA = &pdx->rTransDef[nArea]; // to save typing
+ if (!pTA->bUsed) // if not used...
+ iReturn = U14ERR_NOTSET; // ...nothing to be done
+ else {
+ // We must save the memory we return as we shouldn't mess with memory while
+ // holding a spin lock.
+ struct page **pPages = 0; // save page address list
+ int nPages = 0; // and number of pages
+ int np;
+
+ dev_dbg(&pdx->interface->dev, "%s area %d", __func__,
+ nArea);
+ spin_lock_irq(&pdx->stagedLock);
+ if ((pdx->StagedId == nArea)
+ && (pdx->dwDMAFlag > MODE_CHAR)) {
+ iReturn = U14ERR_UNLOCKFAIL; // cannot delete as in use
+ dev_err(&pdx->interface->dev,
+ "%s call on area %d while active",
+ __func__, nArea);
+ } else {
+ pPages = pTA->pPages; // save page address list
+ nPages = pTA->nPages; // and page count
+ if (pTA->dwEventSz) // if events flagging in use
+ wake_up_interruptible(&pTA->wqEvent); // release anything that was waiting
+
+ if (pdx->bXFerWaiting
+ && (pdx->rDMAInfo.wIdent == nArea))
+ pdx->bXFerWaiting = false; // Cannot have pending xfer if area cleared
+
+ // Clean out the TRANSAREA except for the wait queue, which is at the end
+ // This sets bUsed to false and dwEventSz to 0 to say area not used and no events.
+ memset(pTA, 0,
+ sizeof(TRANSAREA) -
+ sizeof(wait_queue_head_t));
+ }
+ spin_unlock_irq(&pdx->stagedLock);
+
+ if (pPages) // if we decided to release the memory
+ {
+ // Now we must undo the pinning down of the pages. We will assume the worst and mark
+ // all the pages as dirty. Don't be tempted to move this up above as you must not be
+ // holding a spin lock to do this stuff as it is not atomic.
+ dev_dbg(&pdx->interface->dev, "%s nPages=%d",
+ __func__, nPages);
+
+ for (np = 0; np < nPages; ++np) {
+ if (pPages[np]) {
+ SetPageDirty(pPages[np]);
+ page_cache_release(pPages[np]);
+ }
+ }
+
+ kfree(pPages);
+ dev_dbg(&pdx->interface->dev,
+ "%s kfree(pPages) done", __func__);
+ }
+ }
+ }
+
+ return iReturn;
}
/****************************************************************************
** Sets up a transfer area - the functional part. Called by both
** SetTransfer and SetCircular.
****************************************************************************/
-static int SetArea(DEVICE_EXTENSION *pdx, int nArea, char __user* puBuf,
- unsigned int dwLength, bool bCircular, bool bCircToHost)
+static int SetArea(DEVICE_EXTENSION * pdx, int nArea, char __user * puBuf,
+ unsigned int dwLength, bool bCircular, bool bCircToHost)
{
- // Start by working out the page aligned start of the area and the size
- // of the area in pages, allowing for the start not being aligned and the
- // end needing to be rounded up to a page boundary.
- unsigned long ulStart = ((unsigned long)puBuf) & PAGE_MASK;
- unsigned int ulOffset = ((unsigned long)puBuf) & (PAGE_SIZE-1);
- int len = (dwLength + ulOffset+PAGE_SIZE - 1) >> PAGE_SHIFT;
-
- TRANSAREA *pTA = &pdx->rTransDef[nArea]; // to save typing
- struct page **pPages = 0; // space for page tables
- int nPages = 0; // and number of pages
-
- int iReturn = ClearArea(pdx, nArea); // see if OK to use this area
- if ((iReturn != U14ERR_NOTSET) && // if not area unused and...
- (iReturn != U14ERR_NOERROR)) // ...not all OK, then...
- return iReturn; // ...we cannot use this area
-
- if (!access_ok(VERIFY_WRITE, puBuf, dwLength)) // if we cannot access the memory...
- return -EFAULT; // ...then we are done
-
- // Now allocate space to hold the page pointer and virtual address pointer tables
- pPages = (struct page **)kmalloc(len*sizeof(struct page *), GFP_KERNEL);
- if (!pPages)
- {
- iReturn = U14ERR_NOMEMORY;
- goto error;
- }
- dev_dbg(&pdx->interface->dev, "%s %p, length=%06x, circular %d", __func__, puBuf, dwLength, bCircular);
-
- // To pin down user pages we must first acquire the mapping semaphore.
- down_read(¤t->mm->mmap_sem); // get memory map semaphore
- nPages = get_user_pages(current, current->mm, ulStart, len, 1, 0, pPages, 0);
- up_read(¤t->mm->mmap_sem); // release the semaphore
- dev_dbg(&pdx->interface->dev, "%s nPages = %d", __func__, nPages);
-
- if (nPages > 0) // if we succeeded
- {
- // If you are tempted to use page_address (form LDD3), forget it. You MUST use
- // kmap() or kmap_atomic() to get a virtual address. page_address will give you
- // (null) or at least it does in this context with an x86 machine.
- spin_lock_irq(&pdx->stagedLock);
- pTA->lpvBuff = puBuf; // keep start of region (user address)
- pTA->dwBaseOffset = ulOffset; // save offset in first page to start of xfer
- pTA->dwLength = dwLength; // Size if the region in bytes
- pTA->pPages = pPages; // list of pages that are used by buffer
- pTA->nPages = nPages; // number of pages
-
- pTA->bCircular = bCircular;
- pTA->bCircToHost = bCircToHost;
-
- pTA->aBlocks[0].dwOffset = 0;
- pTA->aBlocks[0].dwSize = 0;
- pTA->aBlocks[1].dwOffset = 0;
- pTA->aBlocks[1].dwSize = 0;
- pTA->bUsed = true; // This is now a used block
-
- spin_unlock_irq(&pdx->stagedLock);
- iReturn = U14ERR_NOERROR; // say all was well
- }
- else
- {
- iReturn = U14ERR_LOCKFAIL;
- goto error;
- }
-
- return iReturn;
+ // Start by working out the page aligned start of the area and the size
+ // of the area in pages, allowing for the start not being aligned and the
+ // end needing to be rounded up to a page boundary.
+ unsigned long ulStart = ((unsigned long)puBuf) & PAGE_MASK;
+ unsigned int ulOffset = ((unsigned long)puBuf) & (PAGE_SIZE - 1);
+ int len = (dwLength + ulOffset + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ TRANSAREA *pTA = &pdx->rTransDef[nArea]; // to save typing
+ struct page **pPages = 0; // space for page tables
+ int nPages = 0; // and number of pages
+
+ int iReturn = ClearArea(pdx, nArea); // see if OK to use this area
+ if ((iReturn != U14ERR_NOTSET) && // if not area unused and...
+ (iReturn != U14ERR_NOERROR)) // ...not all OK, then...
+ return iReturn; // ...we cannot use this area
+
+ if (!access_ok(VERIFY_WRITE, puBuf, dwLength)) // if we cannot access the memory...
+ return -EFAULT; // ...then we are done
+
+ // Now allocate space to hold the page pointer and virtual address pointer tables
+ pPages =
+ (struct page **)kmalloc(len * sizeof(struct page *), GFP_KERNEL);
+ if (!pPages) {
+ iReturn = U14ERR_NOMEMORY;
+ goto error;
+ }
+ dev_dbg(&pdx->interface->dev, "%s %p, length=%06x, circular %d",
+ __func__, puBuf, dwLength, bCircular);
+
+ // To pin down user pages we must first acquire the mapping semaphore.
+ down_read(¤t->mm->mmap_sem); // get memory map semaphore
+ nPages =
+ get_user_pages(current, current->mm, ulStart, len, 1, 0, pPages, 0);
+ up_read(¤t->mm->mmap_sem); // release the semaphore
+ dev_dbg(&pdx->interface->dev, "%s nPages = %d", __func__, nPages);
+
+ if (nPages > 0) // if we succeeded
+ {
+ // If you are tempted to use page_address (form LDD3), forget it. You MUST use
+ // kmap() or kmap_atomic() to get a virtual address. page_address will give you
+ // (null) or at least it does in this context with an x86 machine.
+ spin_lock_irq(&pdx->stagedLock);
+ pTA->lpvBuff = puBuf; // keep start of region (user address)
+ pTA->dwBaseOffset = ulOffset; // save offset in first page to start of xfer
+ pTA->dwLength = dwLength; // Size if the region in bytes
+ pTA->pPages = pPages; // list of pages that are used by buffer
+ pTA->nPages = nPages; // number of pages
+
+ pTA->bCircular = bCircular;
+ pTA->bCircToHost = bCircToHost;
+
+ pTA->aBlocks[0].dwOffset = 0;
+ pTA->aBlocks[0].dwSize = 0;
+ pTA->aBlocks[1].dwOffset = 0;
+ pTA->aBlocks[1].dwSize = 0;
+ pTA->bUsed = true; // This is now a used block
+
+ spin_unlock_irq(&pdx->stagedLock);
+ iReturn = U14ERR_NOERROR; // say all was well
+ } else {
+ iReturn = U14ERR_LOCKFAIL;
+ goto error;
+ }
+
+ return iReturn;
error:
- kfree(pPages);
- return iReturn;
+ kfree(pPages);
+ return iReturn;
}
/****************************************************************************
** unset it. Unsetting will fail if the area is booked, and a transfer to that
** area is in progress. Otherwise, we will release the area and re-assign it.
****************************************************************************/
-int SetTransfer(DEVICE_EXTENSION *pdx, TRANSFERDESC __user *pTD)
+int SetTransfer(DEVICE_EXTENSION * pdx, TRANSFERDESC __user * pTD)
{
- int iReturn;
- TRANSFERDESC td;
- copy_from_user(&td, pTD, sizeof(td));
- mutex_lock(&pdx->io_mutex);
- dev_dbg(&pdx->interface->dev,"%s area:%d, size:%08x", __func__, td.wAreaNum, td.dwLength);
- // The strange cast is done so that we don't get warnings in 32-bit linux about the size of the
- // pointer. The pointer is always passed as a 64-bit object so that we don't have problems using
- // a 32-bit program on a 64-bit system. unsigned long is 64-bits on a 64-bit system.
- iReturn = SetArea(pdx, td.wAreaNum, (char __user *)((unsigned long)td.lpvBuff), td.dwLength, false, false);
- mutex_unlock(&pdx->io_mutex);
- return iReturn;
+ int iReturn;
+ TRANSFERDESC td;
+ copy_from_user(&td, pTD, sizeof(td));
+ mutex_lock(&pdx->io_mutex);
+ dev_dbg(&pdx->interface->dev, "%s area:%d, size:%08x", __func__,
+ td.wAreaNum, td.dwLength);
+ // The strange cast is done so that we don't get warnings in 32-bit linux about the size of the
+ // pointer. The pointer is always passed as a 64-bit object so that we don't have problems using
+ // a 32-bit program on a 64-bit system. unsigned long is 64-bits on a 64-bit system.
+ iReturn =
+ SetArea(pdx, td.wAreaNum,
+ (char __user *)((unsigned long)td.lpvBuff), td.dwLength,
+ false, false);
+ mutex_unlock(&pdx->io_mutex);
+ return iReturn;
}
/****************************************************************************
** UnSetTransfer
** Erases a transfer area record
****************************************************************************/
-int UnsetTransfer(DEVICE_EXTENSION *pdx, int nArea)
+int UnsetTransfer(DEVICE_EXTENSION * pdx, int nArea)
{
- int iReturn;
- mutex_lock(&pdx->io_mutex);
- iReturn = ClearArea(pdx, nArea);
- mutex_unlock(&pdx->io_mutex);
- return iReturn;
+ int iReturn;
+ mutex_lock(&pdx->io_mutex);
+ iReturn = ClearArea(pdx, nArea);
+ mutex_unlock(&pdx->io_mutex);
+ return iReturn;
}
/****************************************************************************
** pretend that whatever the user asked for was achieved, so we return 1 if
** try to create one, and 0 if they ask to remove (assuming all else was OK).
****************************************************************************/
-int SetEvent(DEVICE_EXTENSION *pdx, TRANSFEREVENT __user*pTE)
+int SetEvent(DEVICE_EXTENSION * pdx, TRANSFEREVENT __user * pTE)
{
- int iReturn = U14ERR_NOERROR;
- TRANSFEREVENT te;
- copy_from_user(&te, pTE, sizeof(te)); // get a local copy of the data
- if (te.wAreaNum >= MAX_TRANSAREAS) // the area must exist
- return U14ERR_BADAREA;
- else
- {
- TRANSAREA *pTA = &pdx->rTransDef[te.wAreaNum];
- mutex_lock(&pdx->io_mutex); // make sure we have no competitor
- spin_lock_irq(&pdx->stagedLock);
- if (pTA->bUsed) // area must be in use
- {
- pTA->dwEventSt = te.dwStart; // set area regions
- pTA->dwEventSz = te.dwLength; // set size (0 cancels it)
- pTA->bEventToHost = te.wFlags & 1; // set the direction
- pTA->iWakeUp = 0; // zero the wake up count
- }
- else
- iReturn = U14ERR_NOTSET;
- spin_unlock_irq(&pdx->stagedLock);
- mutex_unlock(&pdx->io_mutex);
- }
- return iReturn == U14ERR_NOERROR ? (te.iSetEvent ? 1 : U14ERR_NOERROR) : iReturn;
+ int iReturn = U14ERR_NOERROR;
+ TRANSFEREVENT te;
+ copy_from_user(&te, pTE, sizeof(te)); // get a local copy of the data
+ if (te.wAreaNum >= MAX_TRANSAREAS) // the area must exist
+ return U14ERR_BADAREA;
+ else {
+ TRANSAREA *pTA = &pdx->rTransDef[te.wAreaNum];
+ mutex_lock(&pdx->io_mutex); // make sure we have no competitor
+ spin_lock_irq(&pdx->stagedLock);
+ if (pTA->bUsed) // area must be in use
+ {
+ pTA->dwEventSt = te.dwStart; // set area regions
+ pTA->dwEventSz = te.dwLength; // set size (0 cancels it)
+ pTA->bEventToHost = te.wFlags & 1; // set the direction
+ pTA->iWakeUp = 0; // zero the wake up count
+ } else
+ iReturn = U14ERR_NOTSET;
+ spin_unlock_irq(&pdx->stagedLock);
+ mutex_unlock(&pdx->io_mutex);
+ }
+ return iReturn ==
+ U14ERR_NOERROR ? (te.iSetEvent ? 1 : U14ERR_NOERROR) : iReturn;
}
/****************************************************************************
** of times that a block met the event condition since we last cleared it or
** 0 if timed out, or -ve error (bad area or not set, or signal).
****************************************************************************/
-int WaitEvent(DEVICE_EXTENSION *pdx, int nArea, int msTimeOut)
+int WaitEvent(DEVICE_EXTENSION * pdx, int nArea, int msTimeOut)
{
- int iReturn;
- if ((unsigned)nArea > MAX_TRANSAREAS)
- return U14ERR_BADAREA;
- else
- {
- int iWait;
- TRANSAREA *pTA = &pdx->rTransDef[nArea];
- msTimeOut = (msTimeOut * HZ + 999)/1000; // convert timeout to jiffies
-
- // We cannot wait holding the mutex, but we check the flags while holding
- // it. This may well be pointless as another thread could get in between
- // releasing it and the wait call. However, this would have to clear the
- // iWakeUp flag. However, the !pTA-bUsed may help us in this case.
- mutex_lock(&pdx->io_mutex); // make sure we have no competitor
- if (!pTA->bUsed || !pTA->dwEventSz) // check something to wait for...
- return U14ERR_NOTSET; // ...else we do nothing
- mutex_unlock(&pdx->io_mutex);
-
- if (msTimeOut)
- iWait = wait_event_interruptible_timeout(pTA->wqEvent, pTA->iWakeUp || !pTA->bUsed, msTimeOut);
- else
- iWait = wait_event_interruptible(pTA->wqEvent, pTA->iWakeUp || !pTA->bUsed);
- if (iWait)
- iReturn = -ERESTARTSYS; // oops - we have had a SIGNAL
- else
- iReturn = pTA->iWakeUp; // else the wakeup count
-
- spin_lock_irq(&pdx->stagedLock);
- pTA->iWakeUp = 0; // clear the flag
- spin_unlock_irq(&pdx->stagedLock);
- }
- return iReturn;
+ int iReturn;
+ if ((unsigned)nArea > MAX_TRANSAREAS)
+ return U14ERR_BADAREA;
+ else {
+ int iWait;
+ TRANSAREA *pTA = &pdx->rTransDef[nArea];
+ msTimeOut = (msTimeOut * HZ + 999) / 1000; // convert timeout to jiffies
+
+ // We cannot wait holding the mutex, but we check the flags while holding
+ // it. This may well be pointless as another thread could get in between
+ // releasing it and the wait call. However, this would have to clear the
+ // iWakeUp flag. However, the !pTA-bUsed may help us in this case.
+ mutex_lock(&pdx->io_mutex); // make sure we have no competitor
+ if (!pTA->bUsed || !pTA->dwEventSz) // check something to wait for...
+ return U14ERR_NOTSET; // ...else we do nothing
+ mutex_unlock(&pdx->io_mutex);
+
+ if (msTimeOut)
+ iWait =
+ wait_event_interruptible_timeout(pTA->wqEvent,
+ pTA->iWakeUp
+ || !pTA->bUsed,
+ msTimeOut);
+ else
+ iWait =
+ wait_event_interruptible(pTA->wqEvent, pTA->iWakeUp
+ || !pTA->bUsed);
+ if (iWait)
+ iReturn = -ERESTARTSYS; // oops - we have had a SIGNAL
+ else
+ iReturn = pTA->iWakeUp; // else the wakeup count
+
+ spin_lock_irq(&pdx->stagedLock);
+ pTA->iWakeUp = 0; // clear the flag
+ spin_unlock_irq(&pdx->stagedLock);
+ }
+ return iReturn;
}
/****************************************************************************
** number of times a block completed since the last call, or 0 if none or a
** negative error.
****************************************************************************/
-int TestEvent(DEVICE_EXTENSION *pdx, int nArea)
+int TestEvent(DEVICE_EXTENSION * pdx, int nArea)
{
- int iReturn;
- if ((unsigned)nArea > MAX_TRANSAREAS)
- iReturn = U14ERR_BADAREA;
- else
- {
- TRANSAREA *pTA = &pdx->rTransDef[nArea];
- mutex_lock(&pdx->io_mutex); // make sure we have no competitor
- spin_lock_irq(&pdx->stagedLock);
- iReturn = pTA->iWakeUp; // get wakeup count since last call
- pTA->iWakeUp = 0; // clear the count
- spin_unlock_irq(&pdx->stagedLock);
- mutex_unlock(&pdx->io_mutex);
- }
- return iReturn;
+ int iReturn;
+ if ((unsigned)nArea > MAX_TRANSAREAS)
+ iReturn = U14ERR_BADAREA;
+ else {
+ TRANSAREA *pTA = &pdx->rTransDef[nArea];
+ mutex_lock(&pdx->io_mutex); // make sure we have no competitor
+ spin_lock_irq(&pdx->stagedLock);
+ iReturn = pTA->iWakeUp; // get wakeup count since last call
+ pTA->iWakeUp = 0; // clear the count
+ spin_unlock_irq(&pdx->stagedLock);
+ mutex_unlock(&pdx->io_mutex);
+ }
+ return iReturn;
}
/****************************************************************************
** GetTransferInfo
** Puts the current state of the 1401 in a TGET_TX_BLOCK.
*****************************************************************************/
-int GetTransfer(DEVICE_EXTENSION *pdx, TGET_TX_BLOCK __user *pTX)
+int GetTransfer(DEVICE_EXTENSION * pdx, TGET_TX_BLOCK __user * pTX)
{
- int iReturn = U14ERR_NOERROR;
- unsigned int dwIdent;
-
- mutex_lock(&pdx->io_mutex);
- dwIdent = pdx->StagedId; // area ident for last xfer
- if (dwIdent >= MAX_TRANSAREAS)
- iReturn = U14ERR_BADAREA;
- else
- {
- // Return the best information we have - we don't have physical addresses
- TGET_TX_BLOCK tx;
- memset(&tx, 0, sizeof(tx)); // clean out local work structure
- tx.size = pdx->rTransDef[dwIdent].dwLength;
- tx.linear = (long long)((long)pdx->rTransDef[dwIdent].lpvBuff);
- tx.avail = GET_TX_MAXENTRIES; // how many blocks we could return
- tx.used = 1; // number we actually return
- tx.entries[0].physical = (long long)(tx.linear+pdx->StagedOffset);
- tx.entries[0].size = tx.size;
- copy_to_user(pTX, &tx, sizeof(tx));
- }
- mutex_unlock(&pdx->io_mutex);
- return iReturn;
+ int iReturn = U14ERR_NOERROR;
+ unsigned int dwIdent;
+
+ mutex_lock(&pdx->io_mutex);
+ dwIdent = pdx->StagedId; // area ident for last xfer
+ if (dwIdent >= MAX_TRANSAREAS)
+ iReturn = U14ERR_BADAREA;
+ else {
+ // Return the best information we have - we don't have physical addresses
+ TGET_TX_BLOCK tx;
+ memset(&tx, 0, sizeof(tx)); // clean out local work structure
+ tx.size = pdx->rTransDef[dwIdent].dwLength;
+ tx.linear = (long long)((long)pdx->rTransDef[dwIdent].lpvBuff);
+ tx.avail = GET_TX_MAXENTRIES; // how many blocks we could return
+ tx.used = 1; // number we actually return
+ tx.entries[0].physical =
+ (long long)(tx.linear + pdx->StagedOffset);
+ tx.entries[0].size = tx.size;
+ copy_to_user(pTX, &tx, sizeof(tx));
+ }
+ mutex_unlock(&pdx->io_mutex);
+ return iReturn;
}
/****************************************************************************
**
** Empties the host i/o buffers
****************************************************************************/
-int KillIO1401(DEVICE_EXTENSION *pdx)
+int KillIO1401(DEVICE_EXTENSION * pdx)
{
- dev_dbg(&pdx->interface->dev, "%s", __func__);
- mutex_lock(&pdx->io_mutex);
- FlushOutBuff(pdx);
- FlushInBuff(pdx);
- mutex_unlock(&pdx->io_mutex);
- return U14ERR_NOERROR;
+ dev_dbg(&pdx->interface->dev, "%s", __func__);
+ mutex_lock(&pdx->io_mutex);
+ FlushOutBuff(pdx);
+ FlushInBuff(pdx);
+ mutex_unlock(&pdx->io_mutex);
+ return U14ERR_NOERROR;
}
/****************************************************************************
** Returns a 0 or a 1 for whether DMA is happening. No point holding a mutex
** for this as it only does one read.
*****************************************************************************/
-int BlkTransState(DEVICE_EXTENSION *pdx)
+int BlkTransState(DEVICE_EXTENSION * pdx)
{
- int iReturn = pdx->dwDMAFlag != MODE_CHAR;
- dev_dbg(&pdx->interface->dev, "%s = %d", __func__, iReturn);
- return iReturn;
+ int iReturn = pdx->dwDMAFlag != MODE_CHAR;
+ dev_dbg(&pdx->interface->dev, "%s = %d", __func__, iReturn);
+ return iReturn;
}
/****************************************************************************
**
** Puts the current state of the 1401 in the Irp return buffer.
*****************************************************************************/
-int StateOf1401(DEVICE_EXTENSION *pdx)
+int StateOf1401(DEVICE_EXTENSION * pdx)
{
- int iReturn;
- mutex_lock(&pdx->io_mutex);
+ int iReturn;
+ mutex_lock(&pdx->io_mutex);
- QuickCheck(pdx, false, false); // get state up to date, no reset
- iReturn = pdx->sCurrentState;
+ QuickCheck(pdx, false, false); // get state up to date, no reset
+ iReturn = pdx->sCurrentState;
- mutex_unlock(&pdx->io_mutex);
- dev_dbg(&pdx->interface->dev, "%s = %d", __func__, iReturn);
+ mutex_unlock(&pdx->io_mutex);
+ dev_dbg(&pdx->interface->dev, "%s = %d", __func__, iReturn);
- return iReturn;
+ return iReturn;
}
+
/****************************************************************************
** StartSelfTest
**
** Initiates a self-test cycle. The assumption is that we have no interrupts
** active, so we should make sure that this is the case.
*****************************************************************************/
-int StartSelfTest(DEVICE_EXTENSION *pdx)
+int StartSelfTest(DEVICE_EXTENSION * pdx)
{
- int nGot;
- mutex_lock(&pdx->io_mutex);
- dev_dbg(&pdx->interface->dev, "%s", __func__);
+ int nGot;
+ mutex_lock(&pdx->io_mutex);
+ dev_dbg(&pdx->interface->dev, "%s", __func__);
- ced_draw_down(pdx); // wait for, then kill outstanding Urbs
- FlushInBuff(pdx); // Clear out input buffer & pipe
- FlushOutBuff(pdx); // Clear output buffer & pipe
+ ced_draw_down(pdx); // wait for, then kill outstanding Urbs
+ FlushInBuff(pdx); // Clear out input buffer & pipe
+ FlushOutBuff(pdx); // Clear output buffer & pipe
// ReadWrite_Cancel(pDeviceObject); /* so things stay tidy */
- pdx->dwDMAFlag = MODE_CHAR; /* Clear DMA mode flags here */
+ pdx->dwDMAFlag = MODE_CHAR; /* Clear DMA mode flags here */
- nGot = usb_control_msg(pdx->udev, usb_rcvctrlpipe(pdx->udev, 0),
- DB_SELFTEST, (H_TO_D|VENDOR|DEVREQ), 0, 0,
- 0, 0, HZ); // allow 1 second timeout
- pdx->ulSelfTestTime = jiffies + HZ*30; // 30 seconds into the future
+ nGot = usb_control_msg(pdx->udev, usb_rcvctrlpipe(pdx->udev, 0), DB_SELFTEST, (H_TO_D | VENDOR | DEVREQ), 0, 0, 0, 0, HZ); // allow 1 second timeout
+ pdx->ulSelfTestTime = jiffies + HZ * 30; // 30 seconds into the future
- mutex_unlock(&pdx->io_mutex);
- if (nGot < 0)
- dev_err(&pdx->interface->dev, "%s err=%d", __func__, nGot);
- return nGot < 0 ? U14ERR_FAIL : U14ERR_NOERROR;
+ mutex_unlock(&pdx->io_mutex);
+ if (nGot < 0)
+ dev_err(&pdx->interface->dev, "%s err=%d", __func__, nGot);
+ return nGot < 0 ? U14ERR_FAIL : U14ERR_NOERROR;
}
-
/****************************************************************************
** CheckSelfTest
**
** Check progress of a self-test cycle
****************************************************************************/
-int CheckSelfTest(DEVICE_EXTENSION *pdx, TGET_SELFTEST __user *pGST)
+int CheckSelfTest(DEVICE_EXTENSION * pdx, TGET_SELFTEST __user * pGST)
{
- unsigned int state, error;
- int iReturn;
- TGET_SELFTEST gst; // local work space
- memset(&gst, 0, sizeof(gst)); // clear out the space (sets code 0)
-
- mutex_lock(&pdx->io_mutex);
-
- dev_dbg(&pdx->interface->dev, "%s", __func__);
- iReturn = Get1401State(pdx, &state, &error);
- if (iReturn == U14ERR_NOERROR) // Only accept zero if it happens twice
- iReturn = Get1401State(pdx, &state, &error);
-
- if (iReturn != U14ERR_NOERROR) // Self-test can cause comms errors
- { // so we assume still testing
- dev_err(&pdx->interface->dev, "%s Get1401State=%d, assuming still testing", __func__, iReturn);
- state = 0x80; // Force still-testing, no error
- error = 0;
- iReturn = U14ERR_NOERROR;
- }
-
- if ((state == -1) && (error == -1)) // If Get1401State had problems
- {
- dev_err(&pdx->interface->dev, "%s Get1401State failed, assuming still testing", __func__);
- state = 0x80; // Force still-testing, no error
- error = 0;
- }
-
- if ((state & 0xFF) == 0x80) // If we are still in self-test
- {
- if (state & 0x00FF0000) // Have we got an error?
- {
- gst.code = (state & 0x00FF0000) >> 16; // read the error code
- gst.x = error & 0x0000FFFF; // Error data X
- gst.y = (error & 0xFFFF0000) >> 16; // and data Y
- dev_dbg(&pdx->interface->dev,"Self-test error code %d", gst.code);
- }
- else // No error, check for timeout
- {
- unsigned long ulNow = jiffies; // get current time
- if (time_after(ulNow, pdx->ulSelfTestTime))
- {
- gst.code = -2; // Flag the timeout
- dev_dbg(&pdx->interface->dev, "Self-test timed-out");
- }
- else
- dev_dbg(&pdx->interface->dev, "Self-test on-going");
- }
- }
- else
- {
- gst.code = -1; // Flag the test is done
- dev_dbg(&pdx->interface->dev, "Self-test done");
- }
-
- if (gst.code < 0) // If we have a problem or finished
- { // If using the 2890 we should reset properly
- if ((pdx->nPipes == 4) && (pdx->s1401Type <= TYPEPOWER))
- Is1401(pdx); // Get 1401 reset and OK
- else
- QuickCheck(pdx, true, true); // Otherwise check without reset unless problems
- }
- mutex_unlock(&pdx->io_mutex);
-
- copy_to_user(pGST, &gst, sizeof(gst)); // copy result to user space
- return iReturn;
+ unsigned int state, error;
+ int iReturn;
+ TGET_SELFTEST gst; // local work space
+ memset(&gst, 0, sizeof(gst)); // clear out the space (sets code 0)
+
+ mutex_lock(&pdx->io_mutex);
+
+ dev_dbg(&pdx->interface->dev, "%s", __func__);
+ iReturn = Get1401State(pdx, &state, &error);
+ if (iReturn == U14ERR_NOERROR) // Only accept zero if it happens twice
+ iReturn = Get1401State(pdx, &state, &error);
+
+ if (iReturn != U14ERR_NOERROR) // Self-test can cause comms errors
+ { // so we assume still testing
+ dev_err(&pdx->interface->dev,
+ "%s Get1401State=%d, assuming still testing", __func__,
+ iReturn);
+ state = 0x80; // Force still-testing, no error
+ error = 0;
+ iReturn = U14ERR_NOERROR;
+ }
+
+ if ((state == -1) && (error == -1)) // If Get1401State had problems
+ {
+ dev_err(&pdx->interface->dev,
+ "%s Get1401State failed, assuming still testing",
+ __func__);
+ state = 0x80; // Force still-testing, no error
+ error = 0;
+ }
+
+ if ((state & 0xFF) == 0x80) // If we are still in self-test
+ {
+ if (state & 0x00FF0000) // Have we got an error?
+ {
+ gst.code = (state & 0x00FF0000) >> 16; // read the error code
+ gst.x = error & 0x0000FFFF; // Error data X
+ gst.y = (error & 0xFFFF0000) >> 16; // and data Y
+ dev_dbg(&pdx->interface->dev, "Self-test error code %d",
+ gst.code);
+ } else // No error, check for timeout
+ {
+ unsigned long ulNow = jiffies; // get current time
+ if (time_after(ulNow, pdx->ulSelfTestTime)) {
+ gst.code = -2; // Flag the timeout
+ dev_dbg(&pdx->interface->dev,
+ "Self-test timed-out");
+ } else
+ dev_dbg(&pdx->interface->dev,
+ "Self-test on-going");
+ }
+ } else {
+ gst.code = -1; // Flag the test is done
+ dev_dbg(&pdx->interface->dev, "Self-test done");
+ }
+
+ if (gst.code < 0) // If we have a problem or finished
+ { // If using the 2890 we should reset properly
+ if ((pdx->nPipes == 4) && (pdx->s1401Type <= TYPEPOWER))
+ Is1401(pdx); // Get 1401 reset and OK
+ else
+ QuickCheck(pdx, true, true); // Otherwise check without reset unless problems
+ }
+ mutex_unlock(&pdx->io_mutex);
+
+ copy_to_user(pGST, &gst, sizeof(gst)); // copy result to user space
+ return iReturn;
}
/****************************************************************************
**
** Returns code for standard, plus, micro1401, power1401 or none
****************************************************************************/
-int TypeOf1401(DEVICE_EXTENSION *pdx)
+int TypeOf1401(DEVICE_EXTENSION * pdx)
{
- int iReturn = TYPEUNKNOWN;
- mutex_lock(&pdx->io_mutex);
- dev_dbg(&pdx->interface->dev, "%s", __func__);
-
- switch (pdx->s1401Type)
- {
- case TYPE1401: iReturn = U14ERR_STD; break; // Handle these types directly
- case TYPEPLUS: iReturn = U14ERR_PLUS; break;
- case TYPEU1401:iReturn = U14ERR_U1401;break;
- default:
- if ((pdx->s1401Type >= TYPEPOWER) &&
- (pdx->s1401Type <= 25))
- iReturn = pdx->s1401Type + 4; // We can calculate types
- else // for up-coming 1401 designs
- iReturn = TYPEUNKNOWN; // Don't know or not there
- }
- dev_dbg(&pdx->interface->dev, "%s %d", __func__, iReturn);
- mutex_unlock(&pdx->io_mutex);
-
- return iReturn;
+ int iReturn = TYPEUNKNOWN;
+ mutex_lock(&pdx->io_mutex);
+ dev_dbg(&pdx->interface->dev, "%s", __func__);
+
+ switch (pdx->s1401Type) {
+ case TYPE1401:
+ iReturn = U14ERR_STD;
+ break; // Handle these types directly
+ case TYPEPLUS:
+ iReturn = U14ERR_PLUS;
+ break;
+ case TYPEU1401:
+ iReturn = U14ERR_U1401;
+ break;
+ default:
+ if ((pdx->s1401Type >= TYPEPOWER) && (pdx->s1401Type <= 25))
+ iReturn = pdx->s1401Type + 4; // We can calculate types
+ else // for up-coming 1401 designs
+ iReturn = TYPEUNKNOWN; // Don't know or not there
+ }
+ dev_dbg(&pdx->interface->dev, "%s %d", __func__, iReturn);
+ mutex_unlock(&pdx->io_mutex);
+
+ return iReturn;
}
/****************************************************************************
**
** Returns flags on block transfer abilities
****************************************************************************/
-int TransferFlags(DEVICE_EXTENSION *pdx)
+int TransferFlags(DEVICE_EXTENSION * pdx)
{
- int iReturn = U14TF_MULTIA | U14TF_DIAG | // we always have multiple DMA area
- U14TF_NOTIFY | U14TF_CIRCTH; // diagnostics, notify and circular
- dev_dbg(&pdx->interface->dev, "%s", __func__);
- mutex_lock(&pdx->io_mutex);
- if (pdx->bIsUSB2) // Set flag for USB2 if appropriate
- iReturn |= U14TF_USB2;
- mutex_unlock(&pdx->io_mutex);
-
- return iReturn;
+ int iReturn = U14TF_MULTIA | U14TF_DIAG | // we always have multiple DMA area
+ U14TF_NOTIFY | U14TF_CIRCTH; // diagnostics, notify and circular
+ dev_dbg(&pdx->interface->dev, "%s", __func__);
+ mutex_lock(&pdx->io_mutex);
+ if (pdx->bIsUSB2) // Set flag for USB2 if appropriate
+ iReturn |= U14TF_USB2;
+ mutex_unlock(&pdx->io_mutex);
+
+ return iReturn;
}
/***************************************************************************
** Issues a debug\diagnostic command to the 1401 along with a 32-bit datum
** This is a utility command used for dbg operations.
*/
-static int DbgCmd1401(DEVICE_EXTENSION *pdx, unsigned char cmd, unsigned int data)
+static int DbgCmd1401(DEVICE_EXTENSION * pdx, unsigned char cmd,
+ unsigned int data)
{
- int iReturn;
- dev_dbg(&pdx->interface->dev, "%s entry", __func__);
- iReturn = usb_control_msg(pdx->udev, usb_sndctrlpipe(pdx->udev, 0),
- cmd, (H_TO_D|VENDOR|DEVREQ),
- (unsigned short)data, (unsigned short)(data >> 16),
- 0, 0, HZ); // allow 1 second timeout
- if (iReturn < 0)
- dev_err(&pdx->interface->dev, "%s fail code=%d", __func__, iReturn);
-
- return iReturn;
+ int iReturn;
+ dev_dbg(&pdx->interface->dev, "%s entry", __func__);
+ iReturn = usb_control_msg(pdx->udev, usb_sndctrlpipe(pdx->udev, 0), cmd, (H_TO_D | VENDOR | DEVREQ), (unsigned short)data, (unsigned short)(data >> 16), 0, 0, HZ); // allow 1 second timeout
+ if (iReturn < 0)
+ dev_err(&pdx->interface->dev, "%s fail code=%d", __func__,
+ iReturn);
+
+ return iReturn;
}
/****************************************************************************
**
** Execute the diagnostic peek operation. Uses address, width and repeats.
****************************************************************************/
-int DbgPeek(DEVICE_EXTENSION *pdx, TDBGBLOCK __user* pDB)
+int DbgPeek(DEVICE_EXTENSION * pdx, TDBGBLOCK __user * pDB)
{
- int iReturn;
- TDBGBLOCK db;
- copy_from_user(&db, pDB, sizeof(db)); // get the data
-
- mutex_lock(&pdx->io_mutex);
- dev_dbg(&pdx->interface->dev, "%s @ %08x", __func__, db.iAddr);
-
- iReturn = DbgCmd1401(pdx, DB_SETADD, db.iAddr);
- if (iReturn == U14ERR_NOERROR)
- iReturn = DbgCmd1401(pdx, DB_WIDTH, db.iWidth);
- if (iReturn == U14ERR_NOERROR)
- iReturn = DbgCmd1401(pdx, DB_REPEATS, db.iRepeats);
- if (iReturn == U14ERR_NOERROR)
- iReturn = DbgCmd1401(pdx, DB_PEEK, 0);
- mutex_unlock(&pdx->io_mutex);
-
- return iReturn;
+ int iReturn;
+ TDBGBLOCK db;
+ copy_from_user(&db, pDB, sizeof(db)); // get the data
+
+ mutex_lock(&pdx->io_mutex);
+ dev_dbg(&pdx->interface->dev, "%s @ %08x", __func__, db.iAddr);
+
+ iReturn = DbgCmd1401(pdx, DB_SETADD, db.iAddr);
+ if (iReturn == U14ERR_NOERROR)
+ iReturn = DbgCmd1401(pdx, DB_WIDTH, db.iWidth);
+ if (iReturn == U14ERR_NOERROR)
+ iReturn = DbgCmd1401(pdx, DB_REPEATS, db.iRepeats);
+ if (iReturn == U14ERR_NOERROR)
+ iReturn = DbgCmd1401(pdx, DB_PEEK, 0);
+ mutex_unlock(&pdx->io_mutex);
+
+ return iReturn;
}
-
/****************************************************************************
** DbgPoke
**
** Execute the diagnostic poke operation. Parameters are in the CSBLOCK struct
** in order address, size, repeats and value to poke.
****************************************************************************/
-int DbgPoke(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB)
+int DbgPoke(DEVICE_EXTENSION * pdx, TDBGBLOCK __user * pDB)
{
- int iReturn;
- TDBGBLOCK db;
- copy_from_user(&db, pDB, sizeof(db)); // get the data
-
- mutex_lock(&pdx->io_mutex);
- dev_dbg(&pdx->interface->dev, "%s @ %08x", __func__, db.iAddr);
-
- iReturn = DbgCmd1401(pdx, DB_SETADD, db.iAddr);
- if (iReturn == U14ERR_NOERROR)
- iReturn = DbgCmd1401(pdx, DB_WIDTH, db.iWidth);
- if (iReturn == U14ERR_NOERROR)
- iReturn = DbgCmd1401(pdx, DB_REPEATS, db.iRepeats);
- if (iReturn == U14ERR_NOERROR)
- iReturn = DbgCmd1401(pdx, DB_POKE, db.iData);
- mutex_unlock(&pdx->io_mutex);
-
- return iReturn;
+ int iReturn;
+ TDBGBLOCK db;
+ copy_from_user(&db, pDB, sizeof(db)); // get the data
+
+ mutex_lock(&pdx->io_mutex);
+ dev_dbg(&pdx->interface->dev, "%s @ %08x", __func__, db.iAddr);
+
+ iReturn = DbgCmd1401(pdx, DB_SETADD, db.iAddr);
+ if (iReturn == U14ERR_NOERROR)
+ iReturn = DbgCmd1401(pdx, DB_WIDTH, db.iWidth);
+ if (iReturn == U14ERR_NOERROR)
+ iReturn = DbgCmd1401(pdx, DB_REPEATS, db.iRepeats);
+ if (iReturn == U14ERR_NOERROR)
+ iReturn = DbgCmd1401(pdx, DB_POKE, db.iData);
+ mutex_unlock(&pdx->io_mutex);
+
+ return iReturn;
}
-
/****************************************************************************
** DbgRampData
**
** Execute the diagnostic ramp data operation. Parameters are in the CSBLOCK struct
** in order address, default, enable mask, size and repeats.
****************************************************************************/
-int DbgRampData(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB)
+int DbgRampData(DEVICE_EXTENSION * pdx, TDBGBLOCK __user * pDB)
{
- int iReturn;
- TDBGBLOCK db;
- copy_from_user(&db, pDB, sizeof(db)); // get the data
-
- mutex_lock(&pdx->io_mutex);
- dev_dbg(&pdx->interface->dev, "%s @ %08x", __func__, db.iAddr);
-
- iReturn = DbgCmd1401(pdx, DB_SETADD, db.iAddr);
- if (iReturn == U14ERR_NOERROR)
- iReturn = DbgCmd1401(pdx, DB_SETDEF, db.iDefault);
- if (iReturn == U14ERR_NOERROR)
- iReturn = DbgCmd1401(pdx, DB_SETMASK, db.iMask);
- if (iReturn == U14ERR_NOERROR)
- iReturn = DbgCmd1401(pdx, DB_WIDTH, db.iWidth);
- if (iReturn == U14ERR_NOERROR)
- iReturn = DbgCmd1401(pdx, DB_REPEATS, db.iRepeats);
- if (iReturn == U14ERR_NOERROR)
- iReturn = DbgCmd1401(pdx, DB_RAMPD, 0);
- mutex_unlock(&pdx->io_mutex);
-
- return iReturn;
+ int iReturn;
+ TDBGBLOCK db;
+ copy_from_user(&db, pDB, sizeof(db)); // get the data
+
+ mutex_lock(&pdx->io_mutex);
+ dev_dbg(&pdx->interface->dev, "%s @ %08x", __func__, db.iAddr);
+
+ iReturn = DbgCmd1401(pdx, DB_SETADD, db.iAddr);
+ if (iReturn == U14ERR_NOERROR)
+ iReturn = DbgCmd1401(pdx, DB_SETDEF, db.iDefault);
+ if (iReturn == U14ERR_NOERROR)
+ iReturn = DbgCmd1401(pdx, DB_SETMASK, db.iMask);
+ if (iReturn == U14ERR_NOERROR)
+ iReturn = DbgCmd1401(pdx, DB_WIDTH, db.iWidth);
+ if (iReturn == U14ERR_NOERROR)
+ iReturn = DbgCmd1401(pdx, DB_REPEATS, db.iRepeats);
+ if (iReturn == U14ERR_NOERROR)
+ iReturn = DbgCmd1401(pdx, DB_RAMPD, 0);
+ mutex_unlock(&pdx->io_mutex);
+
+ return iReturn;
}
-
/****************************************************************************
** DbgRampAddr
**
** Execute the diagnostic ramp address operation
****************************************************************************/
-int DbgRampAddr(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB)
+int DbgRampAddr(DEVICE_EXTENSION * pdx, TDBGBLOCK __user * pDB)
{
- int iReturn;
- TDBGBLOCK db;
- copy_from_user(&db, pDB, sizeof(db)); // get the data
-
- mutex_lock(&pdx->io_mutex);
- dev_dbg(&pdx->interface->dev, "%s", __func__);
-
- iReturn = DbgCmd1401(pdx, DB_SETDEF, db.iDefault);
- if (iReturn == U14ERR_NOERROR)
- iReturn = DbgCmd1401(pdx, DB_SETMASK, db.iMask);
- if (iReturn == U14ERR_NOERROR)
- iReturn = DbgCmd1401(pdx, DB_WIDTH, db.iWidth);
- if (iReturn == U14ERR_NOERROR)
- iReturn = DbgCmd1401(pdx, DB_REPEATS, db.iRepeats);
- if (iReturn == U14ERR_NOERROR)
- iReturn = DbgCmd1401(pdx, DB_RAMPA, 0);
- mutex_unlock(&pdx->io_mutex);
-
- return iReturn;
+ int iReturn;
+ TDBGBLOCK db;
+ copy_from_user(&db, pDB, sizeof(db)); // get the data
+
+ mutex_lock(&pdx->io_mutex);
+ dev_dbg(&pdx->interface->dev, "%s", __func__);
+
+ iReturn = DbgCmd1401(pdx, DB_SETDEF, db.iDefault);
+ if (iReturn == U14ERR_NOERROR)
+ iReturn = DbgCmd1401(pdx, DB_SETMASK, db.iMask);
+ if (iReturn == U14ERR_NOERROR)
+ iReturn = DbgCmd1401(pdx, DB_WIDTH, db.iWidth);
+ if (iReturn == U14ERR_NOERROR)
+ iReturn = DbgCmd1401(pdx, DB_REPEATS, db.iRepeats);
+ if (iReturn == U14ERR_NOERROR)
+ iReturn = DbgCmd1401(pdx, DB_RAMPA, 0);
+ mutex_unlock(&pdx->io_mutex);
+
+ return iReturn;
}
-
/****************************************************************************
** DbgGetData
**
** Retrieve the data resulting from the last debug Peek operation
****************************************************************************/
-int DbgGetData(DEVICE_EXTENSION *pdx, TDBGBLOCK __user *pDB)
+int DbgGetData(DEVICE_EXTENSION * pdx, TDBGBLOCK __user * pDB)
{
- int iReturn;
- TDBGBLOCK db;
- memset(&db, 0, sizeof(db)); // fill returned block with 0s
-
- mutex_lock(&pdx->io_mutex);
- dev_dbg(&pdx->interface->dev, "%s", __func__);
-
- // Read back the last peeked value from the 1401.
- iReturn = usb_control_msg(pdx->udev, usb_rcvctrlpipe(pdx->udev, 0),
- DB_DATA, (D_TO_H|VENDOR|DEVREQ), 0,0,
- &db.iData, sizeof(db.iData), HZ);
- if (iReturn == sizeof(db.iData))
- {
- copy_to_user(pDB, &db, sizeof(db));
- iReturn = U14ERR_NOERROR;
- }
- else
- dev_err(&pdx->interface->dev, "%s failed, code %d", __func__, iReturn);
-
- mutex_unlock(&pdx->io_mutex);
-
- return iReturn;
+ int iReturn;
+ TDBGBLOCK db;
+ memset(&db, 0, sizeof(db)); // fill returned block with 0s
+
+ mutex_lock(&pdx->io_mutex);
+ dev_dbg(&pdx->interface->dev, "%s", __func__);
+
+ // Read back the last peeked value from the 1401.
+ iReturn = usb_control_msg(pdx->udev, usb_rcvctrlpipe(pdx->udev, 0),
+ DB_DATA, (D_TO_H | VENDOR | DEVREQ), 0, 0,
+ &db.iData, sizeof(db.iData), HZ);
+ if (iReturn == sizeof(db.iData)) {
+ copy_to_user(pDB, &db, sizeof(db));
+ iReturn = U14ERR_NOERROR;
+ } else
+ dev_err(&pdx->interface->dev, "%s failed, code %d", __func__,
+ iReturn);
+
+ mutex_unlock(&pdx->io_mutex);
+
+ return iReturn;
}
/****************************************************************************
** Stop any never-ending debug loop, we just call Get1401State for USB
**
****************************************************************************/
-int DbgStopLoop(DEVICE_EXTENSION *pdx)
+int DbgStopLoop(DEVICE_EXTENSION * pdx)
{
- int iReturn;
- unsigned int uState, uErr;
+ int iReturn;
+ unsigned int uState, uErr;
- mutex_lock(&pdx->io_mutex);
- dev_dbg(&pdx->interface->dev, "%s", __func__);
- iReturn = Get1401State(pdx, &uState, &uErr);
- mutex_unlock(&pdx->io_mutex);
+ mutex_lock(&pdx->io_mutex);
+ dev_dbg(&pdx->interface->dev, "%s", __func__);
+ iReturn = Get1401State(pdx, &uState, &uErr);
+ mutex_unlock(&pdx->io_mutex);
- return iReturn;
+ return iReturn;
}
-
/****************************************************************************
** SetCircular
**
** booked and a transfer to that area is in progress. Otherwise, we will
** release the area and re-assign it.
****************************************************************************/
-int SetCircular(DEVICE_EXTENSION *pdx, TRANSFERDESC __user *pTD)
+int SetCircular(DEVICE_EXTENSION * pdx, TRANSFERDESC __user * pTD)
{
- int iReturn;
- bool bToHost;
- TRANSFERDESC td;
- copy_from_user(&td, pTD, sizeof(td));
- mutex_lock(&pdx->io_mutex);
- dev_dbg(&pdx->interface->dev,"%s area:%d, size:%08x", __func__, td.wAreaNum, td.dwLength);
- bToHost = td.eSize != 0; // this is used as the tohost flag
-
- // The strange cast is done so that we don't get warnings in 32-bit linux about the size of the
- // pointer. The pointer is always passed as a 64-bit object so that we don't have problems using
- // a 32-bit program on a 64-bit system. unsigned long is 64-bits on a 64-bit system.
- iReturn = SetArea(pdx, td.wAreaNum, (char __user *)((unsigned long)td.lpvBuff), td.dwLength, true, bToHost);
- mutex_unlock(&pdx->io_mutex);
- return iReturn;
+ int iReturn;
+ bool bToHost;
+ TRANSFERDESC td;
+ copy_from_user(&td, pTD, sizeof(td));
+ mutex_lock(&pdx->io_mutex);
+ dev_dbg(&pdx->interface->dev, "%s area:%d, size:%08x", __func__,
+ td.wAreaNum, td.dwLength);
+ bToHost = td.eSize != 0; // this is used as the tohost flag
+
+ // The strange cast is done so that we don't get warnings in 32-bit linux about the size of the
+ // pointer. The pointer is always passed as a 64-bit object so that we don't have problems using
+ // a 32-bit program on a 64-bit system. unsigned long is 64-bits on a 64-bit system.
+ iReturn =
+ SetArea(pdx, td.wAreaNum,
+ (char __user *)((unsigned long)td.lpvBuff), td.dwLength,
+ true, bToHost);
+ mutex_unlock(&pdx->io_mutex);
+ return iReturn;
}
/****************************************************************************
**
** Return the next available block of circularly-transferred data.
****************************************************************************/
-int GetCircBlock(DEVICE_EXTENSION *pdx, TCIRCBLOCK __user* pCB)
+int GetCircBlock(DEVICE_EXTENSION * pdx, TCIRCBLOCK __user * pCB)
{
- int iReturn = U14ERR_NOERROR;
- unsigned int nArea;
- TCIRCBLOCK cb;
- dev_dbg(&pdx->interface->dev, "%s", __func__);
- copy_from_user(&cb, pCB, sizeof(cb));
- mutex_lock(&pdx->io_mutex);
-
- nArea = cb.nArea; // Retrieve parameters first
- cb.dwOffset = 0; // set default result (nothing)
- cb.dwSize = 0;
-
- if (nArea < MAX_TRANSAREAS) // The area number must be OK
- {
- TRANSAREA* pArea = &pdx->rTransDef[nArea]; // Pointer to relevant info
- spin_lock_irq(&pdx->stagedLock); // Lock others out
-
- if ((pArea->bUsed) && (pArea->bCircular) && // Must be circular area
- (pArea->bCircToHost)) // For now at least must be to host
- {
- if (pArea->aBlocks[0].dwSize > 0) // Got anything?
- {
- cb.dwOffset = pArea->aBlocks[0].dwOffset;
- cb.dwSize = pArea->aBlocks[0].dwSize;
- dev_dbg(&pdx->interface->dev, "%s return block 0: %d bytes at %d", __func__, cb.dwSize, cb.dwOffset);
- }
- }
- else
- iReturn = U14ERR_NOTSET;
-
- spin_unlock_irq(&pdx->stagedLock);
- }
- else
- iReturn = U14ERR_BADAREA;
-
- copy_to_user(pCB, &cb, sizeof(cb));
- mutex_unlock(&pdx->io_mutex);
- return iReturn;
+ int iReturn = U14ERR_NOERROR;
+ unsigned int nArea;
+ TCIRCBLOCK cb;
+ dev_dbg(&pdx->interface->dev, "%s", __func__);
+ copy_from_user(&cb, pCB, sizeof(cb));
+ mutex_lock(&pdx->io_mutex);
+
+ nArea = cb.nArea; // Retrieve parameters first
+ cb.dwOffset = 0; // set default result (nothing)
+ cb.dwSize = 0;
+
+ if (nArea < MAX_TRANSAREAS) // The area number must be OK
+ {
+ TRANSAREA *pArea = &pdx->rTransDef[nArea]; // Pointer to relevant info
+ spin_lock_irq(&pdx->stagedLock); // Lock others out
+
+ if ((pArea->bUsed) && (pArea->bCircular) && // Must be circular area
+ (pArea->bCircToHost)) // For now at least must be to host
+ {
+ if (pArea->aBlocks[0].dwSize > 0) // Got anything?
+ {
+ cb.dwOffset = pArea->aBlocks[0].dwOffset;
+ cb.dwSize = pArea->aBlocks[0].dwSize;
+ dev_dbg(&pdx->interface->dev,
+ "%s return block 0: %d bytes at %d",
+ __func__, cb.dwSize, cb.dwOffset);
+ }
+ } else
+ iReturn = U14ERR_NOTSET;
+
+ spin_unlock_irq(&pdx->stagedLock);
+ } else
+ iReturn = U14ERR_BADAREA;
+
+ copy_to_user(pCB, &cb, sizeof(cb));
+ mutex_unlock(&pdx->io_mutex);
+ return iReturn;
}
-
/****************************************************************************
** FreeCircBlock
**
** Frees a block of circularly-transferred data and returns the next one.
****************************************************************************/
-int FreeCircBlock(DEVICE_EXTENSION *pdx, TCIRCBLOCK __user* pCB)
+int FreeCircBlock(DEVICE_EXTENSION * pdx, TCIRCBLOCK __user * pCB)
{
- int iReturn = U14ERR_NOERROR;
- unsigned int nArea, uStart, uSize;
- TCIRCBLOCK cb;
- dev_dbg(&pdx->interface->dev, "%s", __func__);
- copy_from_user(&cb, pCB, sizeof(cb));
- mutex_lock(&pdx->io_mutex);
-
- nArea = cb.nArea; // Retrieve parameters first
- uStart = cb.dwOffset;
- uSize = cb.dwSize;
- cb.dwOffset = 0; // then set default result (nothing)
- cb.dwSize = 0;
-
- if (nArea < MAX_TRANSAREAS) // The area number must be OK
- {
- TRANSAREA* pArea = &pdx->rTransDef[nArea]; // Pointer to relevant info
- spin_lock_irq(&pdx->stagedLock); // Lock others out
-
- if ((pArea->bUsed) && (pArea->bCircular) && // Must be circular area
- (pArea->bCircToHost)) // For now at least must be to host
- {
- bool bWaiting = false;
-
- if ((pArea->aBlocks[0].dwSize >= uSize) && // Got anything?
- (pArea->aBlocks[0].dwOffset == uStart)) // Must be legal data
- {
- pArea->aBlocks[0].dwSize -= uSize;
- pArea->aBlocks[0].dwOffset += uSize;
- if (pArea->aBlocks[0].dwSize == 0) // Have we emptied this block?
- {
- if (pArea->aBlocks[1].dwSize) // Is there a second block?
- {
- pArea->aBlocks[0] = pArea->aBlocks[1]; // Copy down block 2 data
- pArea->aBlocks[1].dwSize = 0; // and mark the second block as unused
- pArea->aBlocks[1].dwOffset = 0;
- }
- else
- pArea->aBlocks[0].dwOffset = 0;
- }
-
- dev_dbg(&pdx->interface->dev, "%s free %d bytes at %d, return %d bytes at %d, wait=%d",
- __func__, uSize, uStart, pArea->aBlocks[0].dwSize, pArea->aBlocks[0].dwOffset, pdx->bXFerWaiting);
-
- // Return the next available block of memory as well
- if (pArea->aBlocks[0].dwSize > 0) // Got anything?
- {
- cb.dwOffset = pArea->aBlocks[0].dwOffset;
- cb.dwSize = pArea->aBlocks[0].dwSize;
- }
-
- bWaiting = pdx->bXFerWaiting;
- if (bWaiting && pdx->bStagedUrbPending)
- {
- dev_err(&pdx->interface->dev, "%s ERROR: waiting xfer and staged Urb pending!", __func__);
- bWaiting = false;
- }
- }
- else
- {
- dev_err(&pdx->interface->dev, "%s ERROR: freeing %d bytes at %d, block 0 is %d bytes at %d",
- __func__, uSize, uStart, pArea->aBlocks[0].dwSize, pArea->aBlocks[0].dwOffset);
- iReturn = U14ERR_NOMEMORY;
- }
-
- // If we have one, kick off pending transfer
- if (bWaiting) // Got a block xfer waiting?
- {
- int RWMStat = ReadWriteMem(pdx, !pdx->rDMAInfo.bOutWard,
- pdx->rDMAInfo.wIdent, pdx->rDMAInfo.dwOffset, pdx->rDMAInfo.dwSize);
- if (RWMStat != U14ERR_NOERROR)
- dev_err(&pdx->interface->dev, "%s rw setup failed %d", __func__, RWMStat);
- }
- }
- else
- iReturn = U14ERR_NOTSET;
-
- spin_unlock_irq(&pdx->stagedLock);
- }
- else
- iReturn = U14ERR_BADAREA;
-
- copy_to_user(pCB, &cb, sizeof(cb));
- mutex_unlock(&pdx->io_mutex);
- return iReturn;
+ int iReturn = U14ERR_NOERROR;
+ unsigned int nArea, uStart, uSize;
+ TCIRCBLOCK cb;
+ dev_dbg(&pdx->interface->dev, "%s", __func__);
+ copy_from_user(&cb, pCB, sizeof(cb));
+ mutex_lock(&pdx->io_mutex);
+
+ nArea = cb.nArea; // Retrieve parameters first
+ uStart = cb.dwOffset;
+ uSize = cb.dwSize;
+ cb.dwOffset = 0; // then set default result (nothing)
+ cb.dwSize = 0;
+
+ if (nArea < MAX_TRANSAREAS) // The area number must be OK
+ {
+ TRANSAREA *pArea = &pdx->rTransDef[nArea]; // Pointer to relevant info
+ spin_lock_irq(&pdx->stagedLock); // Lock others out
+
+ if ((pArea->bUsed) && (pArea->bCircular) && // Must be circular area
+ (pArea->bCircToHost)) // For now at least must be to host
+ {
+ bool bWaiting = false;
+
+ if ((pArea->aBlocks[0].dwSize >= uSize) && // Got anything?
+ (pArea->aBlocks[0].dwOffset == uStart)) // Must be legal data
+ {
+ pArea->aBlocks[0].dwSize -= uSize;
+ pArea->aBlocks[0].dwOffset += uSize;
+ if (pArea->aBlocks[0].dwSize == 0) // Have we emptied this block?
+ {
+ if (pArea->aBlocks[1].dwSize) // Is there a second block?
+ {
+ pArea->aBlocks[0] = pArea->aBlocks[1]; // Copy down block 2 data
+ pArea->aBlocks[1].dwSize = 0; // and mark the second block as unused
+ pArea->aBlocks[1].dwOffset = 0;
+ } else
+ pArea->aBlocks[0].dwOffset = 0;
+ }
+
+ dev_dbg(&pdx->interface->dev,
+ "%s free %d bytes at %d, return %d bytes at %d, wait=%d",
+ __func__, uSize, uStart,
+ pArea->aBlocks[0].dwSize,
+ pArea->aBlocks[0].dwOffset,
+ pdx->bXFerWaiting);
+
+ // Return the next available block of memory as well
+ if (pArea->aBlocks[0].dwSize > 0) // Got anything?
+ {
+ cb.dwOffset =
+ pArea->aBlocks[0].dwOffset;
+ cb.dwSize = pArea->aBlocks[0].dwSize;
+ }
+
+ bWaiting = pdx->bXFerWaiting;
+ if (bWaiting && pdx->bStagedUrbPending) {
+ dev_err(&pdx->interface->dev,
+ "%s ERROR: waiting xfer and staged Urb pending!",
+ __func__);
+ bWaiting = false;
+ }
+ } else {
+ dev_err(&pdx->interface->dev,
+ "%s ERROR: freeing %d bytes at %d, block 0 is %d bytes at %d",
+ __func__, uSize, uStart,
+ pArea->aBlocks[0].dwSize,
+ pArea->aBlocks[0].dwOffset);
+ iReturn = U14ERR_NOMEMORY;
+ }
+
+ // If we have one, kick off pending transfer
+ if (bWaiting) // Got a block xfer waiting?
+ {
+ int RWMStat =
+ ReadWriteMem(pdx, !pdx->rDMAInfo.bOutWard,
+ pdx->rDMAInfo.wIdent,
+ pdx->rDMAInfo.dwOffset,
+ pdx->rDMAInfo.dwSize);
+ if (RWMStat != U14ERR_NOERROR)
+ dev_err(&pdx->interface->dev,
+ "%s rw setup failed %d",
+ __func__, RWMStat);
+ }
+ } else
+ iReturn = U14ERR_NOTSET;
+
+ spin_unlock_irq(&pdx->stagedLock);
+ } else
+ iReturn = U14ERR_BADAREA;
+
+ copy_to_user(pCB, &cb, sizeof(cb));
+ mutex_unlock(&pdx->io_mutex);
+ return iReturn;
}
-
-
-
-/* ced_ioctl.h
- IOCTL calls for the CED1401 driver
- 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.
-*/
+/*
+ * IOCTL calls for the CED1401 driver
+ * 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.
+ */
#ifndef __CED_IOCTL_H__
#define __CED_IOCTL_H__
-#include <asm/ioctl.h>
-/// dma modes, only MODE_CHAR and MODE_LINEAR are used in this driver
-#define MODE_CHAR 0
-#define MODE_LINEAR 1
+#include <linux/ioctl.h>
+
+/* dma modes, only MODE_CHAR and MODE_LINEAR are used in this driver */
+#define MODE_CHAR 0
+#define MODE_LINEAR 1
/****************************************************************************
** TypeDefs
*****************************************************************************/
-typedef unsigned short TBLOCKENTRY; // index the blk transfer table 0-7
+typedef unsigned short TBLOCKENTRY; /* index the blk transfer table 0-7 */
-typedef struct TransferDesc
-{
- long long lpvBuff; // address of transfer area (for 64 or 32 bit)
- unsigned int dwLength; // length of the area
- TBLOCKENTRY wAreaNum; // number of transfer area to set up
- short eSize; // element size - is tohost flag for circular
+typedef struct TransferDesc {
+ long long lpvBuff; /* address of transfer area (for 64 or 32 bit) */
+ unsigned int dwLength; /* length of the area */
+ TBLOCKENTRY wAreaNum; /* number of transfer area to set up */
+ short eSize; /* element size - is tohost flag for circular */
} TRANSFERDESC;
-typedef TRANSFERDESC* LPTRANSFERDESC;
+typedef TRANSFERDESC * LPTRANSFERDESC;
-typedef struct TransferEvent
-{
- unsigned int dwStart; // offset into the area
- unsigned int dwLength; // length of the region
- unsigned short wAreaNum; // the area number
- unsigned short wFlags; // bit 0 set for toHost
- int iSetEvent; // could be dummy in LINUX
+typedef struct TransferEvent {
+ unsigned int dwStart; /* offset into the area */
+ unsigned int dwLength; /* length of the region */
+ unsigned short wAreaNum; /* the area number */
+ unsigned short wFlags; /* bit 0 set for toHost */
+ int iSetEvent; /* could be dummy in LINUX */
} TRANSFEREVENT;
-#define MAX_TRANSFER_SIZE 0x4000 /* Maximum data bytes per IRP */
-#define MAX_AREA_LENGTH 0x100000 /* Maximum size of transfer area */
-#define MAX_TRANSAREAS 8 /* definitions for dma set up */
+#define MAX_TRANSFER_SIZE 0x4000 /* Maximum data bytes per IRP */
+#define MAX_AREA_LENGTH 0x100000 /* Maximum size of transfer area */
+#define MAX_TRANSAREAS 8 /* definitions for dma set up */
-typedef struct TGetSelfTest
-{
- int code; // self-test error code
- int x,y; // additional information
+typedef struct TGetSelfTest {
+ int code; /* self-test error code */
+ int x, y; /* additional information */
} TGET_SELFTEST;
-/// Debug block used for several commands. Not all fields are used for all commands.
-typedef struct TDbgBlock
-{
- int iAddr; // the address in the 1401
- int iRepeats; // number of repeats
- int iWidth; // width in bytes 1, 2, 4
- int iDefault; // default value
- int iMask; // mask to apply
- int iData; // data for poke, result for peek
+/* Debug block used for several commands. Not all fields are used for all commands. */
+typedef struct TDbgBlock {
+ int iAddr; /* the address in the 1401 */
+ int iRepeats; /* number of repeats */
+ int iWidth; /* width in bytes 1, 2, 4 */
+ int iDefault; /* default value */
+ int iMask; /* mask to apply */
+ int iData; /* data for poke, result for peek */
} TDBGBLOCK;
-/// Used to collect information about a circular block from the device driver
-typedef struct TCircBlock
-{
- unsigned int nArea; // the area to collect information from
- unsigned int dwOffset; // offset into the area to the available block
- unsigned int dwSize; // size of the area
+/* Used to collect information about a circular block from the device driver */
+typedef struct TCircBlock {
+ unsigned int nArea; /* the area to collect information from */
+ unsigned int dwOffset; /* offset into the area to the available block */
+ unsigned int dwSize; /* size of the area */
} TCIRCBLOCK;
-/// Used to clollect the 1401 status
-typedef struct TCSBlock
-{
- unsigned int uiState;
- unsigned int uiError;
+/* Used to clollect the 1401 status */
+typedef struct TCSBlock {
+ unsigned int uiState;
+ unsigned int uiError;
} TCSBLOCK;
-// As seen by the user, an ioctl call looks like:
-// int ioctl(int fd, unsigned long cmd, char* argp);
-// We will then have all sorts of variants on this that can be used
-// to pass stuff to our driver. We will generate macros for each type
-// of call so as to provide some sort of type safety in the calling:
+/*
+ * As seen by the user, an ioctl call looks like: int ioctl(int fd, unsigned
+ * long cmd, char* argp); We will then have all sorts of variants on this that
+ * can be used to pass stuff to our driver. We will generate macros for each
+ * type of call so as to provide some sort of type safety in the calling:
+ */
#define CED_MAGIC_IOC 0xce
-// NBNB: READ and WRITE are from the point of view of the device, not user.
-typedef struct ced_ioc_string
-{
- int nChars;
- char buffer[256];
+/* NBNB: READ and WRITE are from the point of view of the device, not user. */
+typedef struct ced_ioc_string {
+ int nChars;
+ char buffer[256];
} CED_IOC_STRING;
-#define IOCTL_CED_SENDSTRING(n) _IOC(_IOC_WRITE, CED_MAGIC_IOC, 2, n)
-
-#define IOCTL_CED_RESET1401 _IO(CED_MAGIC_IOC, 3)
-#define IOCTL_CED_GETCHAR _IO(CED_MAGIC_IOC, 4)
-#define IOCTL_CED_SENDCHAR _IO(CED_MAGIC_IOC, 5)
-#define IOCTL_CED_STAT1401 _IO(CED_MAGIC_IOC, 6)
-#define IOCTL_CED_LINECOUNT _IO(CED_MAGIC_IOC, 7)
-#define IOCTL_CED_GETSTRING(nMax) _IOC(_IOC_READ, CED_MAGIC_IOC, 8, nMax)
-
-#define IOCTL_CED_SETTRANSFER _IOW(CED_MAGIC_IOC, 11, TRANSFERDESC)
-#define IOCTL_CED_UNSETTRANSFER _IO(CED_MAGIC_IOC, 12)
-#define IOCTL_CED_SETEVENT _IOW(CED_MAGIC_IOC,13, TRANSFEREVENT)
-#define IOCTL_CED_GETOUTBUFSPACE _IO(CED_MAGIC_IOC, 14)
-#define IOCTL_CED_GETBASEADDRESS _IO(CED_MAGIC_IOC, 15)
-#define IOCTL_CED_GETDRIVERREVISION _IO(CED_MAGIC_IOC, 16)
-
-#define IOCTL_CED_GETTRANSFER _IOR(CED_MAGIC_IOC,17, TGET_TX_BLOCK)
-#define IOCTL_CED_KILLIO1401 _IO(CED_MAGIC_IOC,18)
-#define IOCTL_CED_BLKTRANSSTATE _IO(CED_MAGIC_IOC,19)
-
-#define IOCTL_CED_STATEOF1401 _IO(CED_MAGIC_IOC,23)
-#define IOCTL_CED_GRAB1401 _IO(CED_MAGIC_IOC,25)
-#define IOCTL_CED_FREE1401 _IO(CED_MAGIC_IOC,26)
-#define IOCTL_CED_STARTSELFTEST _IO(CED_MAGIC_IOC,31)
-#define IOCTL_CED_CHECKSELFTEST _IOR(CED_MAGIC_IOC,32, TGET_SELFTEST)
-#define IOCTL_CED_TYPEOF1401 _IO(CED_MAGIC_IOC,33)
-#define IOCTL_CED_TRANSFERFLAGS _IO(CED_MAGIC_IOC,34)
-
-#define IOCTL_CED_DBGPEEK _IOW(CED_MAGIC_IOC,35, TDBGBLOCK)
-#define IOCTL_CED_DBGPOKE _IOW(CED_MAGIC_IOC,36, TDBGBLOCK)
-#define IOCTL_CED_DBGRAMPDATA _IOW(CED_MAGIC_IOC,37, TDBGBLOCK)
-#define IOCTL_CED_DBGRAMPADDR _IOW(CED_MAGIC_IOC,38, TDBGBLOCK)
-#define IOCTL_CED_DBGGETDATA _IOR(CED_MAGIC_IOC,39, TDBGBLOCK)
-#define IOCTL_CED_DBGSTOPLOOP _IO(CED_MAGIC_IOC,40)
-#define IOCTL_CED_FULLRESET _IO(CED_MAGIC_IOC,41)
-#define IOCTL_CED_SETCIRCULAR _IOW(CED_MAGIC_IOC,42, TRANSFERDESC)
-#define IOCTL_CED_GETCIRCBLOCK _IOWR(CED_MAGIC_IOC,43, TCIRCBLOCK)
-#define IOCTL_CED_FREECIRCBLOCK _IOWR(CED_MAGIC_IOC,44, TCIRCBLOCK)
-#define IOCTL_CED_WAITEVENT _IO(CED_MAGIC_IOC, 45)
-#define IOCTL_CED_TESTEVENT _IO(CED_MAGIC_IOC, 46)
+#define IOCTL_CED_SENDSTRING(n) _IOC(_IOC_WRITE, CED_MAGIC_IOC, 2, n)
+
+#define IOCTL_CED_RESET1401 _IO(CED_MAGIC_IOC, 3)
+#define IOCTL_CED_GETCHAR _IO(CED_MAGIC_IOC, 4)
+#define IOCTL_CED_SENDCHAR _IO(CED_MAGIC_IOC, 5)
+#define IOCTL_CED_STAT1401 _IO(CED_MAGIC_IOC, 6)
+#define IOCTL_CED_LINECOUNT _IO(CED_MAGIC_IOC, 7)
+#define IOCTL_CED_GETSTRING(nMax) _IOC(_IOC_READ, CED_MAGIC_IOC, 8, nMax)
+
+#define IOCTL_CED_SETTRANSFER _IOW(CED_MAGIC_IOC, 11, TRANSFERDESC)
+#define IOCTL_CED_UNSETTRANSFER _IO(CED_MAGIC_IOC, 12)
+#define IOCTL_CED_SETEVENT _IOW(CED_MAGIC_IOC, 13, TRANSFEREVENT)
+#define IOCTL_CED_GETOUTBUFSPACE _IO(CED_MAGIC_IOC, 14)
+#define IOCTL_CED_GETBASEADDRESS _IO(CED_MAGIC_IOC, 15)
+#define IOCTL_CED_GETDRIVERREVISION _IO(CED_MAGIC_IOC, 16)
+
+#define IOCTL_CED_GETTRANSFER _IOR(CED_MAGIC_IOC, 17, TGET_TX_BLOCK)
+#define IOCTL_CED_KILLIO1401 _IO(CED_MAGIC_IOC, 18)
+#define IOCTL_CED_BLKTRANSSTATE _IO(CED_MAGIC_IOC, 19)
+
+#define IOCTL_CED_STATEOF1401 _IO(CED_MAGIC_IOC, 23)
+#define IOCTL_CED_GRAB1401 _IO(CED_MAGIC_IOC, 25)
+#define IOCTL_CED_FREE1401 _IO(CED_MAGIC_IOC, 26)
+#define IOCTL_CED_STARTSELFTEST _IO(CED_MAGIC_IOC, 31)
+#define IOCTL_CED_CHECKSELFTEST _IOR(CED_MAGIC_IOC, 32, TGET_SELFTEST)
+#define IOCTL_CED_TYPEOF1401 _IO(CED_MAGIC_IOC, 33)
+#define IOCTL_CED_TRANSFERFLAGS _IO(CED_MAGIC_IOC, 34)
+
+#define IOCTL_CED_DBGPEEK _IOW(CED_MAGIC_IOC, 35, TDBGBLOCK)
+#define IOCTL_CED_DBGPOKE _IOW(CED_MAGIC_IOC, 36, TDBGBLOCK)
+#define IOCTL_CED_DBGRAMPDATA _IOW(CED_MAGIC_IOC, 37, TDBGBLOCK)
+#define IOCTL_CED_DBGRAMPADDR _IOW(CED_MAGIC_IOC, 38, TDBGBLOCK)
+#define IOCTL_CED_DBGGETDATA _IOR(CED_MAGIC_IOC, 39, TDBGBLOCK)
+#define IOCTL_CED_DBGSTOPLOOP _IO(CED_MAGIC_IOC, 40)
+#define IOCTL_CED_FULLRESET _IO(CED_MAGIC_IOC, 41)
+#define IOCTL_CED_SETCIRCULAR _IOW(CED_MAGIC_IOC, 42, TRANSFERDESC)
+#define IOCTL_CED_GETCIRCBLOCK _IOWR(CED_MAGIC_IOC, 43, TCIRCBLOCK)
+#define IOCTL_CED_FREECIRCBLOCK _IOWR(CED_MAGIC_IOC, 44, TCIRCBLOCK)
+#define IOCTL_CED_WAITEVENT _IO(CED_MAGIC_IOC, 45)
+#define IOCTL_CED_TESTEVENT _IO(CED_MAGIC_IOC, 46)
#ifndef __KERNEL__
-// If nothing said about return value, it is a U14ERR_... error code (U14ERR_NOERROR for none)
-inline int CED_SendString(int fh, const char* szText, int n){return ioctl(fh, IOCTL_CED_SENDSTRING(n), szText);}
+/*
+ * If nothing said about return value, it is a U14ERR_... error code
+ * (U14ERR_NOERROR for none)
+ */
+inline int CED_SendString(int fh, const char *szText, int n)
+{
+ return ioctl(fh, IOCTL_CED_SENDSTRING(n), szText);
+}
-inline int CED_Reset1401(int fh){return ioctl(fh, IOCTL_CED_RESET1401);}
+inline int CED_Reset1401(int fh)
+{
+ return ioctl(fh, IOCTL_CED_RESET1401);
+}
-inline int CED_GetChar(int fh){return ioctl(fh, IOCTL_CED_GETCHAR);}
-// Return the singe character or a -ve error code.
+/* Return the singe character or a -ve error code. */
+inline int CED_GetChar(int fh)
+{
+ return ioctl(fh, IOCTL_CED_GETCHAR);
+}
-inline int CED_Stat1401(int fh){return ioctl(fh, IOCTL_CED_STAT1401);}
-// Return character count in input buffer
+/* Return character count in input buffer */
+inline int CED_Stat1401(int fh)
+{
+ return ioctl(fh, IOCTL_CED_STAT1401);
+}
-inline int CED_SendChar(int fh, char c){return ioctl(fh, IOCTL_CED_SENDCHAR, c);}
+inline int CED_SendChar(int fh, char c)
+{
+ return ioctl(fh, IOCTL_CED_SENDCHAR, c);
+}
-inline int CED_LineCount(int fh){return ioctl(fh, IOCTL_CED_LINECOUNT);}
+inline int CED_LineCount(int fh)
+{
+ return ioctl(fh, IOCTL_CED_LINECOUNT);
+}
+
+/*
+ * return the count of characters returned. If the string was terminated by CR
+ * or 0, then the 0 is part of the count. Otherwise, we will add a zero if
+ * there is room, but it is not included in the count. The return value is 0
+ * if there was nothing to read.
+ */
+inline int CED_GetString(int fh, char *szText, int nMax)
+{
+ return ioctl(fh, IOCTL_CED_GETSTRING(nMax), szText);
+}
-inline int CED_GetString(int fh, char* szText, int nMax){return ioctl(fh, IOCTL_CED_GETSTRING(nMax), szText);}
-// return the count of characters returned. If the string was terminated by CR or 0, then the 0 is part
-// of the count. Otherwise, we will add a zero if there is room, but it is not included in the count.
-// The return value is 0 if there was nothing to read.
+/* returns space in the output buffer. */
+inline int CED_GetOutBufSpace(int fh)
+{
+ return ioctl(fh, IOCTL_CED_GETOUTBUFSPACE);
+}
-inline int CED_GetOutBufSpace(int fh){return ioctl(fh, IOCTL_CED_GETOUTBUFSPACE);}
-// returns space in the output buffer.
+/* This always returns -1 as not implemented. */
+inline int CED_GetBaseAddress(int fh)
+{
+ return ioctl(fh, IOCTL_CED_GETBASEADDRESS);
+}
-inline int CED_GetBaseAddress(int fh){return ioctl(fh, IOCTL_CED_GETBASEADDRESS);}
-// This always returns -1 as not implemented.
+/* returns the major revision <<16 | minor revision. */
+inline int CED_GetDriverRevision(int fh)
+{
+ return ioctl(fh, IOCTL_CED_GETDRIVERREVISION);
+}
-inline int CED_GetDriverRevision(int fh){return ioctl(fh, IOCTL_CED_GETDRIVERREVISION);}
-// returns the major revision <<16 | minor revision.
+inline int CED_SetTransfer(int fh, TRANSFERDESC *pTD)
+{
+ return ioctl(fh, IOCTL_CED_SETTRANSFER, pTD);
+}
-inline int CED_SetTransfer(int fh, TRANSFERDESC* pTD){return ioctl(fh, IOCTL_CED_SETTRANSFER, pTD);}
+inline int CED_UnsetTransfer(int fh, int nArea)
+{
+ return ioctl(fh, IOCTL_CED_UNSETTRANSFER, nArea);
+}
-inline int CED_UnsetTransfer(int fh, int nArea){return ioctl(fh, IOCTL_CED_UNSETTRANSFER, nArea);}
+inline int CED_SetEvent(int fh, TRANSFEREVENT *pTE)
+{
+ return ioctl(fh, IOCTL_CED_SETEVENT, pTE);
+}
-inline int CED_SetEvent(int fh, TRANSFEREVENT* pTE){return ioctl(fh, IOCTL_CED_SETEVENT, pTE);}
+inline int CED_GetTransfer(int fh, TGET_TX_BLOCK *pTX)
+{
+ return ioctl(fh, IOCTL_CED_GETTRANSFER, pTX);
+}
-inline int CED_GetTransfer(int fh, TGET_TX_BLOCK* pTX){return ioctl(fh, IOCTL_CED_GETTRANSFER, pTX);}
+inline int CED_KillIO1401(int fh)
+{
+ return ioctl(fh, IOCTL_CED_KILLIO1401);
+}
-inline int CED_KillIO1401(int fh){return ioctl(fh, IOCTL_CED_KILLIO1401);}
+/* returns 0 if no active DMA, 1 if active */
+inline int CED_BlkTransState(int fh)
+{
+ return ioctl(fh, IOCTL_CED_BLKTRANSSTATE);
+}
-inline int CED_BlkTransState(int fh){return ioctl(fh, IOCTL_CED_BLKTRANSSTATE);}
-// returns 0 if no active DMA, 1 if active
+inline int CED_StateOf1401(int fh)
+{
+ return ioctl(fh, IOCTL_CED_STATEOF1401);
+}
-inline int CED_StateOf1401(int fh){return ioctl(fh, IOCTL_CED_STATEOF1401);}
+inline int CED_Grab1401(int fh)
+{
+ return ioctl(fh, IOCTL_CED_GRAB1401);
+}
-inline int CED_Grab1401(int fh){return ioctl(fh, IOCTL_CED_GRAB1401);}
-inline int CED_Free1401(int fh){return ioctl(fh, IOCTL_CED_FREE1401);}
+inline int CED_Free1401(int fh)
+{
+ return ioctl(fh, IOCTL_CED_FREE1401);
+}
-inline int CED_StartSelfTest(int fh){return ioctl(fh, IOCTL_CED_STARTSELFTEST);}
-inline int CED_CheckSelfTest(int fh, TGET_SELFTEST* pGST){return ioctl(fh, IOCTL_CED_CHECKSELFTEST, pGST);}
+inline int CED_StartSelfTest(int fh)
+{
+ return ioctl(fh, IOCTL_CED_STARTSELFTEST);
+}
+
+inline int CED_CheckSelfTest(int fh, TGET_SELFTEST *pGST)
+{
+ return ioctl(fh, IOCTL_CED_CHECKSELFTEST, pGST);
+}
+
+inline int CED_TypeOf1401(int fh)
+{
+ return ioctl(fh, IOCTL_CED_TYPEOF1401);
+}
+
+inline int CED_TransferFlags(int fh)
+{
+ return ioctl(fh, IOCTL_CED_TRANSFERFLAGS);
+}
+
+inline int CED_DbgPeek(int fh, TDBGBLOCK *pDB)
+{
+ return ioctl(fh, IOCTL_CED_DBGPEEK, pDB);
+}
+
+inline int CED_DbgPoke(int fh, TDBGBLOCK *pDB)
+{
+ return ioctl(fh, IOCTL_CED_DBGPOKE, pDB);
+}
+
+inline int CED_DbgRampData(int fh, TDBGBLOCK *pDB)
+{
+ return ioctl(fh, IOCTL_CED_DBGRAMPDATA, pDB);
+}
-inline int CED_TypeOf1401(int fh){return ioctl(fh, IOCTL_CED_TYPEOF1401);}
-inline int CED_TransferFlags(int fh){return ioctl(fh, IOCTL_CED_TRANSFERFLAGS);}
+inline int CED_DbgRampAddr(int fh, TDBGBLOCK *pDB)
+{
+ return ioctl(fh, IOCTL_CED_DBGRAMPADDR, pDB);
+}
-inline int CED_DbgPeek(int fh, TDBGBLOCK* pDB){return ioctl(fh, IOCTL_CED_DBGPEEK, pDB);}
-inline int CED_DbgPoke(int fh, TDBGBLOCK* pDB){return ioctl(fh, IOCTL_CED_DBGPOKE, pDB);}
-inline int CED_DbgRampData(int fh, TDBGBLOCK* pDB){return ioctl(fh, IOCTL_CED_DBGRAMPDATA, pDB);}
-inline int CED_DbgRampAddr(int fh, TDBGBLOCK* pDB){return ioctl(fh, IOCTL_CED_DBGRAMPADDR, pDB);}
-inline int CED_DbgGetData(int fh, TDBGBLOCK* pDB){return ioctl(fh, IOCTL_CED_DBGGETDATA, pDB);}
-inline int CED_DbgStopLoop(int fh){return ioctl(fh, IOCTL_CED_DBGSTOPLOOP);}
+inline int CED_DbgGetData(int fh, TDBGBLOCK *pDB)
+{
+ return ioctl(fh, IOCTL_CED_DBGGETDATA, pDB);
+}
-inline int CED_FullReset(int fh){return ioctl(fh, IOCTL_CED_FULLRESET);}
+inline int CED_DbgStopLoop(int fh)
+{
+ return ioctl(fh, IOCTL_CED_DBGSTOPLOOP);
+}
-inline int CED_SetCircular(int fh, TRANSFERDESC* pTD){return ioctl(fh, IOCTL_CED_SETCIRCULAR, pTD);}
-inline int CED_GetCircBlock(int fh, TCIRCBLOCK* pCB){return ioctl(fh, IOCTL_CED_GETCIRCBLOCK, pCB);}
-inline int CED_FreeCircBlock(int fh, TCIRCBLOCK* pCB){return ioctl(fh, IOCTL_CED_FREECIRCBLOCK, pCB);}
+inline int CED_FullReset(int fh)
+{
+ return ioctl(fh, IOCTL_CED_FULLRESET);
+}
-inline int CED_WaitEvent(int fh, int nArea, int msTimeOut){return ioctl(fh, IOCTL_CED_WAITEVENT, (nArea & 0xff)|(msTimeOut << 8));}
-inline int CED_TestEvent(int fh, int nArea){return ioctl(fh, IOCTL_CED_TESTEVENT, nArea);}
+inline int CED_SetCircular(int fh, TRANSFERDESC *pTD)
+{
+ return ioctl(fh, IOCTL_CED_SETCIRCULAR, pTD);
+}
+
+inline int CED_GetCircBlock(int fh, TCIRCBLOCK *pCB)
+{
+ return ioctl(fh, IOCTL_CED_GETCIRCBLOCK, pCB);
+}
+
+inline int CED_FreeCircBlock(int fh, TCIRCBLOCK *pCB)
+{
+ return ioctl(fh, IOCTL_CED_FREECIRCBLOCK, pCB);
+}
+
+inline int CED_WaitEvent(int fh, int nArea, int msTimeOut)
+{
+ return ioctl(fh, IOCTL_CED_WAITEVENT, (nArea & 0xff)|(msTimeOut << 8));
+}
+
+inline int CED_TestEvent(int fh, int nArea)
+{
+ return ioctl(fh, IOCTL_CED_TESTEVENT, nArea);
+}
#endif
#ifdef NOTWANTEDYET
-#define IOCTL_CED_REGCALLBACK _IO(CED_MAGIC_IOC,9) // Not used
-#define IOCTL_CED_GETMONITORBUF _IO(CED_MAGIC_IOC,10) // Not used
+#define IOCTL_CED_REGCALLBACK _IO(CED_MAGIC_IOC, 9) /* Not used */
+#define IOCTL_CED_GETMONITORBUF _IO(CED_MAGIC_IOC, 10) /* Not used */
-#define IOCTL_CED_BYTECOUNT _IO(CED_MAGIC_IOC,20) // Not used
-#define IOCTL_CED_ZEROBLOCKCOUNT _IO(CED_MAGIC_IOC,21) // Not used
-#define IOCTL_CED_STOPCIRCULAR _IO(CED_MAGIC_IOC,22) // Not used
+#define IOCTL_CED_BYTECOUNT _IO(CED_MAGIC_IOC, 20) /* Not used */
+#define IOCTL_CED_ZEROBLOCKCOUNT _IO(CED_MAGIC_IOC, 21) /* Not used */
+#define IOCTL_CED_STOPCIRCULAR _IO(CED_MAGIC_IOC, 22) /* Not used */
-#define IOCTL_CED_REGISTERS1401 _IO(CED_MAGIC_IOC,24) // Not used
-#define IOCTL_CED_STEP1401 _IO(CED_MAGIC_IOC,27) // Not used
-#define IOCTL_CED_SET1401REGISTERS _IO(CED_MAGIC_IOC,28) // Not used
-#define IOCTL_CED_STEPTILL1401 _IO(CED_MAGIC_IOC,29) // Not used
-#define IOCTL_CED_SETORIN _IO(CED_MAGIC_IOC,30) // Not used
+#define IOCTL_CED_REGISTERS1401 _IO(CED_MAGIC_IOC, 24) /* Not used */
+#define IOCTL_CED_STEP1401 _IO(CED_MAGIC_IOC, 27) /* Not used */
+#define IOCTL_CED_SET1401REGISTERS _IO(CED_MAGIC_IOC, 28) /* Not used */
+#define IOCTL_CED_STEPTILL1401 _IO(CED_MAGIC_IOC, 29) /* Not used */
+#define IOCTL_CED_SETORIN _IO(CED_MAGIC_IOC, 30) /* Not used */
#endif
-// __CED_IOCTL_H__
+/* __CED_IOCTL_H__ */
#endif
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
Endpoints
*********
There are 4 endpoints plus the control endpoint in the standard interface
#include <linux/highmem.h>
#include <linux/version.h>
#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) )
- #include <linux/init.h>
- #include <linux/slab.h>
- #include <linux/module.h>
- #include <linux/kref.h>
- #include <linux/uaccess.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/uaccess.h>
#endif
-
#include "usb1401.h"
/* Define these values to match your devices */
#define USB_CED_PRODUCT_ID 0xa0f0
/* table of devices that work with this driver */
-static const struct usb_device_id ced_table[] =
-{
- { USB_DEVICE(USB_CED_VENDOR_ID, USB_CED_PRODUCT_ID) },
- { } /* Terminating entry */
+static const struct usb_device_id ced_table[] = {
+ {USB_DEVICE(USB_CED_VENDOR_ID, USB_CED_PRODUCT_ID)},
+ {} /* Terminating entry */
};
-MODULE_DEVICE_TABLE(usb, ced_table);
+MODULE_DEVICE_TABLE(usb, ced_table);
/* Get a minor range for your devices from the usb maintainer */
#define USB_CED_MINOR_BASE 192
This is needed on Debian 2.6.32-5-amd64
*/
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) )
- #define usb_alloc_coherent usb_buffer_alloc
- #define usb_free_coherent usb_buffer_free
- #define noop_llseek NULL
+#define usb_alloc_coherent usb_buffer_alloc
+#define usb_free_coherent usb_buffer_free
+#define noop_llseek NULL
#endif
static struct usb_driver ced_driver;
static void ced_delete(struct kref *kref)
{
- DEVICE_EXTENSION *pdx = to_DEVICE_EXTENSION(kref);
-
- // Free up the output buffer, then free the output urb. Note that the interface member
- // of pdx will probably be NULL, so cannot be used to get to dev.
- usb_free_coherent(pdx->udev, OUTBUF_SZ, pdx->pCoherCharOut, pdx->pUrbCharOut->transfer_dma);
- usb_free_urb(pdx->pUrbCharOut);
-
- // Do the same for chan input
- usb_free_coherent(pdx->udev, INBUF_SZ, pdx->pCoherCharIn, pdx->pUrbCharIn->transfer_dma);
- usb_free_urb(pdx->pUrbCharIn);
-
- // Do the same for the block transfers
- usb_free_coherent(pdx->udev, STAGED_SZ, pdx->pCoherStagedIO, pdx->pStagedUrb->transfer_dma);
- usb_free_urb(pdx->pStagedUrb);
-
- usb_put_dev(pdx->udev);
- kfree(pdx);
+ DEVICE_EXTENSION *pdx = to_DEVICE_EXTENSION(kref);
+
+ // Free up the output buffer, then free the output urb. Note that the interface member
+ // of pdx will probably be NULL, so cannot be used to get to dev.
+ usb_free_coherent(pdx->udev, OUTBUF_SZ, pdx->pCoherCharOut,
+ pdx->pUrbCharOut->transfer_dma);
+ usb_free_urb(pdx->pUrbCharOut);
+
+ // Do the same for chan input
+ usb_free_coherent(pdx->udev, INBUF_SZ, pdx->pCoherCharIn,
+ pdx->pUrbCharIn->transfer_dma);
+ usb_free_urb(pdx->pUrbCharIn);
+
+ // Do the same for the block transfers
+ usb_free_coherent(pdx->udev, STAGED_SZ, pdx->pCoherStagedIO,
+ pdx->pStagedUrb->transfer_dma);
+ usb_free_urb(pdx->pStagedUrb);
+
+ usb_put_dev(pdx->udev);
+ kfree(pdx);
}
// This is the driver end of the open() call from user space.
static int ced_open(struct inode *inode, struct file *file)
{
- DEVICE_EXTENSION *pdx;
- int retval = 0;
- int subminor = iminor(inode);
- struct usb_interface* interface = usb_find_interface(&ced_driver, subminor);
- if (!interface)
- {
- pr_err("%s - error, can't find device for minor %d", __func__, subminor);
- retval = -ENODEV;
- goto exit;
- }
-
- pdx = usb_get_intfdata(interface);
- if (!pdx)
- {
- retval = -ENODEV;
- goto exit;
- }
-
- dev_dbg(&interface->dev, "%s got pdx", __func__);
-
- /* increment our usage count for the device */
- kref_get(&pdx->kref);
-
- /* lock the device to allow correctly handling errors
- * in resumption */
- mutex_lock(&pdx->io_mutex);
-
- if (!pdx->open_count++)
- {
- retval = usb_autopm_get_interface(interface);
- if (retval)
- {
- pdx->open_count--;
- mutex_unlock(&pdx->io_mutex);
- kref_put(&pdx->kref, ced_delete);
- goto exit;
- }
- }
- else
- { //uncomment this block if you want exclusive open
- dev_err(&interface->dev, "%s fail: already open", __func__);
+ DEVICE_EXTENSION *pdx;
+ int retval = 0;
+ int subminor = iminor(inode);
+ struct usb_interface *interface =
+ usb_find_interface(&ced_driver, subminor);
+ if (!interface) {
+ pr_err("%s - error, can't find device for minor %d", __func__,
+ subminor);
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ pdx = usb_get_intfdata(interface);
+ if (!pdx) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ dev_dbg(&interface->dev, "%s got pdx", __func__);
+
+ /* increment our usage count for the device */
+ kref_get(&pdx->kref);
+
+ /* lock the device to allow correctly handling errors
+ * in resumption */
+ mutex_lock(&pdx->io_mutex);
+
+ if (!pdx->open_count++) {
+ retval = usb_autopm_get_interface(interface);
+ if (retval) {
+ pdx->open_count--;
+ mutex_unlock(&pdx->io_mutex);
+ kref_put(&pdx->kref, ced_delete);
+ goto exit;
+ }
+ } else { //uncomment this block if you want exclusive open
+ dev_err(&interface->dev, "%s fail: already open", __func__);
retval = -EBUSY;
pdx->open_count--;
mutex_unlock(&pdx->io_mutex);
kref_put(&pdx->kref, ced_delete);
goto exit;
}
- /* prevent the device from being autosuspended */
+ /* prevent the device from being autosuspended */
- /* save our object in the file's private structure */
- file->private_data = pdx;
- mutex_unlock(&pdx->io_mutex);
+ /* save our object in the file's private structure */
+ file->private_data = pdx;
+ mutex_unlock(&pdx->io_mutex);
exit:
- return retval;
+ return retval;
}
static int ced_release(struct inode *inode, struct file *file)
{
- DEVICE_EXTENSION *pdx = file->private_data;
- if (pdx == NULL)
- return -ENODEV;
-
- dev_dbg(&pdx->interface->dev,"%s called", __func__);
- mutex_lock(&pdx->io_mutex);
- if (!--pdx->open_count && pdx->interface) // Allow autosuspend
- usb_autopm_put_interface(pdx->interface);
- mutex_unlock(&pdx->io_mutex);
-
- kref_put(&pdx->kref, ced_delete); // decrement the count on our device
- return 0;
+ DEVICE_EXTENSION *pdx = file->private_data;
+ if (pdx == NULL)
+ return -ENODEV;
+
+ dev_dbg(&pdx->interface->dev, "%s called", __func__);
+ mutex_lock(&pdx->io_mutex);
+ if (!--pdx->open_count && pdx->interface) // Allow autosuspend
+ usb_autopm_put_interface(pdx->interface);
+ mutex_unlock(&pdx->io_mutex);
+
+ kref_put(&pdx->kref, ced_delete); // decrement the count on our device
+ return 0;
}
static int ced_flush(struct file *file, fl_owner_t id)
{
- int res;
- DEVICE_EXTENSION *pdx = file->private_data;
- if (pdx == NULL)
- return -ENODEV;
+ int res;
+ DEVICE_EXTENSION *pdx = file->private_data;
+ if (pdx == NULL)
+ return -ENODEV;
- dev_dbg(&pdx->interface->dev,"%s char in pend=%d", __func__, pdx->bReadCharsPending);
+ dev_dbg(&pdx->interface->dev, "%s char in pend=%d", __func__,
+ pdx->bReadCharsPending);
- /* wait for io to stop */
- mutex_lock(&pdx->io_mutex);
- dev_dbg(&pdx->interface->dev,"%s got io_mutex", __func__);
- ced_draw_down(pdx);
+ /* wait for io to stop */
+ mutex_lock(&pdx->io_mutex);
+ dev_dbg(&pdx->interface->dev, "%s got io_mutex", __func__);
+ ced_draw_down(pdx);
- /* read out errors, leave subsequent opens a clean slate */
- spin_lock_irq(&pdx->err_lock);
- res = pdx->errors ? (pdx->errors == -EPIPE ? -EPIPE : -EIO) : 0;
- pdx->errors = 0;
- spin_unlock_irq(&pdx->err_lock);
+ /* read out errors, leave subsequent opens a clean slate */
+ spin_lock_irq(&pdx->err_lock);
+ res = pdx->errors ? (pdx->errors == -EPIPE ? -EPIPE : -EIO) : 0;
+ pdx->errors = 0;
+ spin_unlock_irq(&pdx->err_lock);
- mutex_unlock(&pdx->io_mutex);
- dev_dbg(&pdx->interface->dev,"%s exit reached", __func__);
+ mutex_unlock(&pdx->io_mutex);
+ dev_dbg(&pdx->interface->dev, "%s exit reached", __func__);
- return res;
+ return res;
}
-
static ssize_t ced_read(struct file *file, char *buffer, size_t count,
- loff_t *ppos)
+ loff_t * ppos)
{
- DEVICE_EXTENSION *pdx = file->private_data;
- dev_err(&pdx->interface->dev, "%s called: use ioctl for cedusb", __func__);
- return 0; // as we do not do reads this way
+ DEVICE_EXTENSION *pdx = file->private_data;
+ dev_err(&pdx->interface->dev, "%s called: use ioctl for cedusb",
+ __func__);
+ return 0; // as we do not do reads this way
}
static ssize_t ced_write(struct file *file, const char *user_buffer,
- size_t count, loff_t *ppos)
+ size_t count, loff_t * ppos)
{
- DEVICE_EXTENSION *pdx = file->private_data;
- dev_err(&pdx->interface->dev, "%s called: use ioctl for cedusb", __func__);
- return 0;
+ DEVICE_EXTENSION *pdx = file->private_data;
+ dev_err(&pdx->interface->dev, "%s called: use ioctl for cedusb",
+ __func__);
+ return 0;
}
/***************************************************************************
** not help with a device extension held by a file.
** return true if can accept new io requests, else false
*/
-static bool CanAcceptIoRequests(DEVICE_EXTENSION* pdx)
+static bool CanAcceptIoRequests(DEVICE_EXTENSION * pdx)
{
- return pdx && pdx->interface; // Can we accept IO requests
+ return pdx && pdx->interface; // Can we accept IO requests
}
/****************************************************************************
** Callback routine to complete writes. This may need to fire off another
** urb to complete the transfer.
****************************************************************************/
-static void ced_writechar_callback(struct urb* pUrb)
+static void ced_writechar_callback(struct urb *pUrb)
{
- DEVICE_EXTENSION *pdx = pUrb->context;
- int nGot = pUrb->actual_length; // what we transferred
-
- if (pUrb->status)
- { // sync/async unlink faults aren't errors
- if (!(pUrb->status == -ENOENT || pUrb->status == -ECONNRESET || pUrb->status == -ESHUTDOWN))
- {
- dev_err(&pdx->interface->dev, "%s - nonzero write bulk status received: %d", __func__, pUrb->status);
- }
-
- spin_lock(&pdx->err_lock);
- pdx->errors = pUrb->status;
- spin_unlock(&pdx->err_lock);
- nGot = 0; // and tidy up again if so
-
- spin_lock(&pdx->charOutLock); // already at irq level
- pdx->dwOutBuffGet = 0; // Reset the output buffer
- pdx->dwOutBuffPut = 0;
- pdx->dwNumOutput = 0; // Clear the char count
- pdx->bPipeError[0] = 1; // Flag an error for later
- pdx->bSendCharsPending = false; // Allow other threads again
- spin_unlock(&pdx->charOutLock); // already at irq level
- dev_dbg(&pdx->interface->dev, "%s - char out done, 0 chars sent", __func__);
- }
- else
- {
- dev_dbg(&pdx->interface->dev, "%s - char out done, %d chars sent", __func__, nGot);
- spin_lock(&pdx->charOutLock); // already at irq level
- pdx->dwNumOutput -= nGot; // Now adjust the char send buffer
- pdx->dwOutBuffGet += nGot; // to match what we did
- if (pdx->dwOutBuffGet >= OUTBUF_SZ) // Can't do this any earlier as data could be overwritten
- pdx->dwOutBuffGet = 0;
-
- if (pdx->dwNumOutput > 0) // if more to be done...
- {
- int nPipe = 0; // The pipe number to use
- int iReturn;
- char* pDat = &pdx->outputBuffer[pdx->dwOutBuffGet];
- unsigned int dwCount = pdx->dwNumOutput; // maximum to send
- if ((pdx->dwOutBuffGet+dwCount) > OUTBUF_SZ) // does it cross buffer end?
- dwCount = OUTBUF_SZ - pdx->dwOutBuffGet;
- spin_unlock(&pdx->charOutLock); // we are done with stuff that changes
- memcpy(pdx->pCoherCharOut, pDat, dwCount); // copy output data to the buffer
- usb_fill_bulk_urb(pdx->pUrbCharOut, pdx->udev,
- usb_sndbulkpipe(pdx->udev, pdx->epAddr[0]),
- pdx->pCoherCharOut, dwCount, ced_writechar_callback, pdx);
- pdx->pUrbCharOut->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- usb_anchor_urb(pdx->pUrbCharOut, &pdx->submitted); // in case we need to kill it
- iReturn = usb_submit_urb(pdx->pUrbCharOut, GFP_ATOMIC);
- dev_dbg(&pdx->interface->dev, "%s n=%d>%s<", __func__, dwCount, pDat);
- spin_lock(&pdx->charOutLock); // grab lock for errors
- if (iReturn)
- {
- pdx->bPipeError[nPipe] = 1; // Flag an error to be handled later
- pdx->bSendCharsPending = false; // Allow other threads again
- usb_unanchor_urb(pdx->pUrbCharOut);
- dev_err(&pdx->interface->dev, "%s usb_submit_urb() returned %d", __func__, iReturn);
- }
- }
- else
- pdx->bSendCharsPending = false; // Allow other threads again
- spin_unlock(&pdx->charOutLock); // already at irq level
- }
+ DEVICE_EXTENSION *pdx = pUrb->context;
+ int nGot = pUrb->actual_length; // what we transferred
+
+ if (pUrb->status) { // sync/async unlink faults aren't errors
+ if (!
+ (pUrb->status == -ENOENT || pUrb->status == -ECONNRESET
+ || pUrb->status == -ESHUTDOWN)) {
+ dev_err(&pdx->interface->dev,
+ "%s - nonzero write bulk status received: %d",
+ __func__, pUrb->status);
+ }
+
+ spin_lock(&pdx->err_lock);
+ pdx->errors = pUrb->status;
+ spin_unlock(&pdx->err_lock);
+ nGot = 0; // and tidy up again if so
+
+ spin_lock(&pdx->charOutLock); // already at irq level
+ pdx->dwOutBuffGet = 0; // Reset the output buffer
+ pdx->dwOutBuffPut = 0;
+ pdx->dwNumOutput = 0; // Clear the char count
+ pdx->bPipeError[0] = 1; // Flag an error for later
+ pdx->bSendCharsPending = false; // Allow other threads again
+ spin_unlock(&pdx->charOutLock); // already at irq level
+ dev_dbg(&pdx->interface->dev,
+ "%s - char out done, 0 chars sent", __func__);
+ } else {
+ dev_dbg(&pdx->interface->dev,
+ "%s - char out done, %d chars sent", __func__, nGot);
+ spin_lock(&pdx->charOutLock); // already at irq level
+ pdx->dwNumOutput -= nGot; // Now adjust the char send buffer
+ pdx->dwOutBuffGet += nGot; // to match what we did
+ if (pdx->dwOutBuffGet >= OUTBUF_SZ) // Can't do this any earlier as data could be overwritten
+ pdx->dwOutBuffGet = 0;
+
+ if (pdx->dwNumOutput > 0) // if more to be done...
+ {
+ int nPipe = 0; // The pipe number to use
+ int iReturn;
+ char *pDat = &pdx->outputBuffer[pdx->dwOutBuffGet];
+ unsigned int dwCount = pdx->dwNumOutput; // maximum to send
+ if ((pdx->dwOutBuffGet + dwCount) > OUTBUF_SZ) // does it cross buffer end?
+ dwCount = OUTBUF_SZ - pdx->dwOutBuffGet;
+ spin_unlock(&pdx->charOutLock); // we are done with stuff that changes
+ memcpy(pdx->pCoherCharOut, pDat, dwCount); // copy output data to the buffer
+ usb_fill_bulk_urb(pdx->pUrbCharOut, pdx->udev,
+ usb_sndbulkpipe(pdx->udev,
+ pdx->epAddr[0]),
+ pdx->pCoherCharOut, dwCount,
+ ced_writechar_callback, pdx);
+ pdx->pUrbCharOut->transfer_flags |=
+ URB_NO_TRANSFER_DMA_MAP;
+ usb_anchor_urb(pdx->pUrbCharOut, &pdx->submitted); // in case we need to kill it
+ iReturn = usb_submit_urb(pdx->pUrbCharOut, GFP_ATOMIC);
+ dev_dbg(&pdx->interface->dev, "%s n=%d>%s<", __func__,
+ dwCount, pDat);
+ spin_lock(&pdx->charOutLock); // grab lock for errors
+ if (iReturn) {
+ pdx->bPipeError[nPipe] = 1; // Flag an error to be handled later
+ pdx->bSendCharsPending = false; // Allow other threads again
+ usb_unanchor_urb(pdx->pUrbCharOut);
+ dev_err(&pdx->interface->dev,
+ "%s usb_submit_urb() returned %d",
+ __func__, iReturn);
+ }
+ } else
+ pdx->bSendCharsPending = false; // Allow other threads again
+ spin_unlock(&pdx->charOutLock); // already at irq level
+ }
}
/****************************************************************************
** Transmit the characters in the output buffer to the 1401. This may need
** breaking down into multiple transfers.
****************************************************************************/
-int SendChars(DEVICE_EXTENSION* pdx)
+int SendChars(DEVICE_EXTENSION * pdx)
{
- int iReturn = U14ERR_NOERROR;
-
- spin_lock_irq(&pdx->charOutLock); // Protect ourselves
-
- if ((!pdx->bSendCharsPending) && // Not currently sending
- (pdx->dwNumOutput > 0) && // has characters to output
- (CanAcceptIoRequests(pdx))) // and current activity is OK
- {
- unsigned int dwCount = pdx->dwNumOutput; // Get a copy of the character count
- pdx->bSendCharsPending = true; // Set flag to lock out other threads
-
- dev_dbg(&pdx->interface->dev, "Send %d chars to 1401, EP0 flag %d\n", dwCount, pdx->nPipes == 3);
- // If we have only 3 end points we must send the characters to the 1401 using EP0.
- if (pdx->nPipes == 3)
- {
- // For EP0 character transmissions to the 1401, we have to hang about until they
- // are gone, as otherwise without more character IO activity they will never go.
- unsigned int count = dwCount; // Local char counter
- unsigned int index = 0; // The index into the char buffer
-
- spin_unlock_irq(&pdx->charOutLock); // Free spinlock as we call USBD
-
- while ((count > 0) && (iReturn == U14ERR_NOERROR))
- {
- // We have to break the transfer up into 64-byte chunks because of a 2270 problem
- int n = count > 64 ? 64 : count; // Chars for this xfer, max of 64
- int nSent = usb_control_msg(pdx->udev,
- usb_sndctrlpipe(pdx->udev,0), // use end point 0
- DB_CHARS, // bRequest
- (H_TO_D|VENDOR|DEVREQ), // to the device, vendor request to the device
- 0,0, // value and index are both 0
- &pdx->outputBuffer[index], // where to send from
- n, // how much to send
- 1000); // timeout in jiffies
- if (nSent <= 0)
- {
- iReturn = nSent ? nSent : -ETIMEDOUT; // if 0 chars says we timed out
- dev_err(&pdx->interface->dev, "Send %d chars by EP0 failed: %d", n, iReturn);
- }
- else
- {
- dev_dbg(&pdx->interface->dev, "Sent %d chars by EP0", n);
- count -= nSent;
- index += nSent;
- }
- }
-
- spin_lock_irq(&pdx->charOutLock); // Protect pdx changes, released by general code
- pdx->dwOutBuffGet = 0; // so reset the output buffer
- pdx->dwOutBuffPut = 0;
- pdx->dwNumOutput = 0; // and clear the buffer count
- pdx->bSendCharsPending = false; // Allow other threads again
- }
- else
- { // Here for sending chars normally - we hold the spin lock
- int nPipe = 0; // The pipe number to use
- char* pDat = &pdx->outputBuffer[pdx->dwOutBuffGet];
-
- if ((pdx->dwOutBuffGet+dwCount) > OUTBUF_SZ) // does it cross buffer end?
- dwCount = OUTBUF_SZ - pdx->dwOutBuffGet;
- spin_unlock_irq(&pdx->charOutLock); // we are done with stuff that changes
- memcpy(pdx->pCoherCharOut, pDat, dwCount); // copy output data to the buffer
- usb_fill_bulk_urb(pdx->pUrbCharOut, pdx->udev,
- usb_sndbulkpipe(pdx->udev, pdx->epAddr[0]),
- pdx->pCoherCharOut, dwCount, ced_writechar_callback, pdx);
- pdx->pUrbCharOut->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- usb_anchor_urb(pdx->pUrbCharOut, &pdx->submitted);
- iReturn = usb_submit_urb(pdx->pUrbCharOut, GFP_KERNEL);
- spin_lock_irq(&pdx->charOutLock); // grab lock for errors
- if (iReturn)
- {
- pdx->bPipeError[nPipe] = 1; // Flag an error to be handled later
- pdx->bSendCharsPending = false; // Allow other threads again
- usb_unanchor_urb(pdx->pUrbCharOut); // remove from list of active urbs
- }
- }
- }
- else
- if (pdx->bSendCharsPending && (pdx->dwNumOutput > 0))
- dev_dbg(&pdx->interface->dev, "SendChars bSendCharsPending:true");
-
-
- dev_dbg(&pdx->interface->dev, "SendChars exit code: %d", iReturn);
- spin_unlock_irq(&pdx->charOutLock); // Now let go of the spinlock
- return iReturn;
+ int iReturn = U14ERR_NOERROR;
+
+ spin_lock_irq(&pdx->charOutLock); // Protect ourselves
+
+ if ((!pdx->bSendCharsPending) && // Not currently sending
+ (pdx->dwNumOutput > 0) && // has characters to output
+ (CanAcceptIoRequests(pdx))) // and current activity is OK
+ {
+ unsigned int dwCount = pdx->dwNumOutput; // Get a copy of the character count
+ pdx->bSendCharsPending = true; // Set flag to lock out other threads
+
+ dev_dbg(&pdx->interface->dev,
+ "Send %d chars to 1401, EP0 flag %d\n", dwCount,
+ pdx->nPipes == 3);
+ // If we have only 3 end points we must send the characters to the 1401 using EP0.
+ if (pdx->nPipes == 3) {
+ // For EP0 character transmissions to the 1401, we have to hang about until they
+ // are gone, as otherwise without more character IO activity they will never go.
+ unsigned int count = dwCount; // Local char counter
+ unsigned int index = 0; // The index into the char buffer
+
+ spin_unlock_irq(&pdx->charOutLock); // Free spinlock as we call USBD
+
+ while ((count > 0) && (iReturn == U14ERR_NOERROR)) {
+ // We have to break the transfer up into 64-byte chunks because of a 2270 problem
+ int n = count > 64 ? 64 : count; // Chars for this xfer, max of 64
+ int nSent = usb_control_msg(pdx->udev,
+ usb_sndctrlpipe(pdx->udev, 0), // use end point 0
+ DB_CHARS, // bRequest
+ (H_TO_D | VENDOR | DEVREQ), // to the device, vendor request to the device
+ 0, 0, // value and index are both 0
+ &pdx->outputBuffer[index], // where to send from
+ n, // how much to send
+ 1000); // timeout in jiffies
+ if (nSent <= 0) {
+ iReturn = nSent ? nSent : -ETIMEDOUT; // if 0 chars says we timed out
+ dev_err(&pdx->interface->dev,
+ "Send %d chars by EP0 failed: %d",
+ n, iReturn);
+ } else {
+ dev_dbg(&pdx->interface->dev,
+ "Sent %d chars by EP0", n);
+ count -= nSent;
+ index += nSent;
+ }
+ }
+
+ spin_lock_irq(&pdx->charOutLock); // Protect pdx changes, released by general code
+ pdx->dwOutBuffGet = 0; // so reset the output buffer
+ pdx->dwOutBuffPut = 0;
+ pdx->dwNumOutput = 0; // and clear the buffer count
+ pdx->bSendCharsPending = false; // Allow other threads again
+ } else { // Here for sending chars normally - we hold the spin lock
+ int nPipe = 0; // The pipe number to use
+ char *pDat = &pdx->outputBuffer[pdx->dwOutBuffGet];
+
+ if ((pdx->dwOutBuffGet + dwCount) > OUTBUF_SZ) // does it cross buffer end?
+ dwCount = OUTBUF_SZ - pdx->dwOutBuffGet;
+ spin_unlock_irq(&pdx->charOutLock); // we are done with stuff that changes
+ memcpy(pdx->pCoherCharOut, pDat, dwCount); // copy output data to the buffer
+ usb_fill_bulk_urb(pdx->pUrbCharOut, pdx->udev,
+ usb_sndbulkpipe(pdx->udev,
+ pdx->epAddr[0]),
+ pdx->pCoherCharOut, dwCount,
+ ced_writechar_callback, pdx);
+ pdx->pUrbCharOut->transfer_flags |=
+ URB_NO_TRANSFER_DMA_MAP;
+ usb_anchor_urb(pdx->pUrbCharOut, &pdx->submitted);
+ iReturn = usb_submit_urb(pdx->pUrbCharOut, GFP_KERNEL);
+ spin_lock_irq(&pdx->charOutLock); // grab lock for errors
+ if (iReturn) {
+ pdx->bPipeError[nPipe] = 1; // Flag an error to be handled later
+ pdx->bSendCharsPending = false; // Allow other threads again
+ usb_unanchor_urb(pdx->pUrbCharOut); // remove from list of active urbs
+ }
+ }
+ } else if (pdx->bSendCharsPending && (pdx->dwNumOutput > 0))
+ dev_dbg(&pdx->interface->dev,
+ "SendChars bSendCharsPending:true");
+
+ dev_dbg(&pdx->interface->dev, "SendChars exit code: %d", iReturn);
+ spin_unlock_irq(&pdx->charOutLock); // Now let go of the spinlock
+ return iReturn;
}
/***************************************************************************
** pdx Is our device extension which holds all we know about the transfer.
** n The number of bytes to move one way or the other.
***************************************************************************/
-static void CopyUserSpace(DEVICE_EXTENSION *pdx, int n)
+static void CopyUserSpace(DEVICE_EXTENSION * pdx, int n)
{
- unsigned int nArea = pdx->StagedId;
- if (nArea < MAX_TRANSAREAS)
- {
- TRANSAREA *pArea = &pdx->rTransDef[nArea]; // area to be used
- unsigned int dwOffset = pdx->StagedDone + pdx->StagedOffset + pArea->dwBaseOffset;
- char* pCoherBuf = pdx->pCoherStagedIO; // coherent buffer
- if (!pArea->bUsed)
- {
- dev_err(&pdx->interface->dev, "%s area %d unused", __func__, nArea);
- return;
- }
-
- while (n)
- {
- int nPage = dwOffset >> PAGE_SHIFT; // page number in table
- if (nPage < pArea->nPages)
- {
- char *pvAddress = (char*)kmap_atomic(pArea->pPages[nPage]);
- if (pvAddress)
- {
- unsigned int uiPageOff = dwOffset & (PAGE_SIZE-1); // offset into the page
- size_t uiXfer = PAGE_SIZE - uiPageOff; // max to transfer on this page
- if (uiXfer > n) // limit byte count if too much
- uiXfer = n; // for the page
- if (pdx->StagedRead)
- memcpy(pvAddress+uiPageOff, pCoherBuf, uiXfer);
- else
- memcpy(pCoherBuf, pvAddress+uiPageOff, uiXfer);
- kunmap_atomic(pvAddress);
- dwOffset += uiXfer;
- pCoherBuf += uiXfer;
- n -= uiXfer;
- }
- else
- {
- dev_err(&pdx->interface->dev, "%s did not map page %d", __func__, nPage);
- return;
- }
-
- }
- else
- {
- dev_err(&pdx->interface->dev, "%s exceeded pages %d", __func__, nPage);
- return;
- }
- }
- }
- else
- dev_err(&pdx->interface->dev, "%s bad area %d", __func__, nArea);
+ unsigned int nArea = pdx->StagedId;
+ if (nArea < MAX_TRANSAREAS) {
+ TRANSAREA *pArea = &pdx->rTransDef[nArea]; // area to be used
+ unsigned int dwOffset =
+ pdx->StagedDone + pdx->StagedOffset + pArea->dwBaseOffset;
+ char *pCoherBuf = pdx->pCoherStagedIO; // coherent buffer
+ if (!pArea->bUsed) {
+ dev_err(&pdx->interface->dev, "%s area %d unused",
+ __func__, nArea);
+ return;
+ }
+
+ while (n) {
+ int nPage = dwOffset >> PAGE_SHIFT; // page number in table
+ if (nPage < pArea->nPages) {
+ char *pvAddress =
+ (char *)kmap_atomic(pArea->pPages[nPage]);
+ if (pvAddress) {
+ unsigned int uiPageOff = dwOffset & (PAGE_SIZE - 1); // offset into the page
+ size_t uiXfer = PAGE_SIZE - uiPageOff; // max to transfer on this page
+ if (uiXfer > n) // limit byte count if too much
+ uiXfer = n; // for the page
+ if (pdx->StagedRead)
+ memcpy(pvAddress + uiPageOff,
+ pCoherBuf, uiXfer);
+ else
+ memcpy(pCoherBuf,
+ pvAddress + uiPageOff,
+ uiXfer);
+ kunmap_atomic(pvAddress);
+ dwOffset += uiXfer;
+ pCoherBuf += uiXfer;
+ n -= uiXfer;
+ } else {
+ dev_err(&pdx->interface->dev,
+ "%s did not map page %d",
+ __func__, nPage);
+ return;
+ }
+
+ } else {
+ dev_err(&pdx->interface->dev,
+ "%s exceeded pages %d", __func__,
+ nPage);
+ return;
+ }
+ }
+ } else
+ dev_err(&pdx->interface->dev, "%s bad area %d", __func__,
+ nArea);
}
// Forward declarations for stuff used circularly
-static int StageChunk(DEVICE_EXTENSION *pdx);
+static int StageChunk(DEVICE_EXTENSION * pdx);
/***************************************************************************
** ReadWrite_Complete
**
** Completion routine for our staged read/write Irps
*/
-static void staged_callback(struct urb* pUrb)
+static void staged_callback(struct urb *pUrb)
{
- DEVICE_EXTENSION *pdx = pUrb->context;
- unsigned int nGot = pUrb->actual_length; // what we transferred
- bool bCancel = false;
- bool bRestartCharInput; // used at the end
-
- spin_lock(&pdx->stagedLock); // stop ReadWriteMem() action while this routine is running
- pdx->bStagedUrbPending = false; // clear the flag for staged IRP pending
-
- if (pUrb->status)
- { // sync/async unlink faults aren't errors
- if (!(pUrb->status == -ENOENT || pUrb->status == -ECONNRESET || pUrb->status == -ESHUTDOWN))
- {
- dev_err(&pdx->interface->dev, "%s - nonzero write bulk status received: %d", __func__, pUrb->status);
- }
- else
- dev_info(&pdx->interface->dev, "%s - staged xfer cancelled", __func__);
-
- spin_lock(&pdx->err_lock);
- pdx->errors = pUrb->status;
- spin_unlock(&pdx->err_lock);
- nGot = 0; // and tidy up again if so
- bCancel = true;
- }
- else
- {
- dev_dbg(&pdx->interface->dev, "%s %d chars xferred", __func__, nGot);
- if (pdx->StagedRead) // if reading, save to user space
- CopyUserSpace(pdx, nGot); // copy from buffer to user
- if (nGot == 0)
- dev_dbg(&pdx->interface->dev, "%s ZLP", __func__);
- }
-
- // Update the transfer length based on the TransferBufferLength value in the URB
- pdx->StagedDone += nGot;
-
- dev_dbg(&pdx->interface->dev, "%s, done %d bytes of %d", __func__, pdx->StagedDone, pdx->StagedLength);
-
- if ((pdx->StagedDone == pdx->StagedLength) || // If no more to do
- (bCancel)) // or this IRP was cancelled
- {
- TRANSAREA* pArea = &pdx->rTransDef[pdx->StagedId]; // Transfer area info
- dev_dbg(&pdx->interface->dev, "%s transfer done, bytes %d, cancel %d", __func__, pdx->StagedDone, bCancel);
-
- // Here is where we sort out what to do with this transfer if using a circular buffer. We have
- // a completed transfer that can be assumed to fit into the transfer area. We should be able to
- // add this to the end of a growing block or to use it to start a new block unless the code
- // that calculates the offset to use (in ReadWriteMem) is totally duff.
- if ((pArea->bCircular) && (pArea->bCircToHost) && (!bCancel) && // Time to sort out circular buffer info?
- (pdx->StagedRead)) // Only for tohost transfers for now
- {
- if (pArea->aBlocks[1].dwSize > 0) // If block 1 is in use we must append to it
- {
- if (pdx->StagedOffset == (pArea->aBlocks[1].dwOffset + pArea->aBlocks[1].dwSize))
- {
- pArea->aBlocks[1].dwSize += pdx->StagedLength;
- dev_dbg(&pdx->interface->dev, "RWM_Complete, circ block 1 now %d bytes at %d",
- pArea->aBlocks[1].dwSize, pArea->aBlocks[1].dwOffset);
- }
- else
- {
- // Here things have gone very, very, wrong, but I cannot see how this can actually be achieved
- pArea->aBlocks[1].dwOffset = pdx->StagedOffset;
- pArea->aBlocks[1].dwSize = pdx->StagedLength;
- dev_err(&pdx->interface->dev, "%s ERROR, circ block 1 re-started %d bytes at %d",
- __func__, pArea->aBlocks[1].dwSize, pArea->aBlocks[1].dwOffset);
- }
- }
- else // If block 1 is not used, we try to add to block 0
- {
- if (pArea->aBlocks[0].dwSize > 0) // Got stored block 0 information?
- { // Must append onto the existing block 0
- if (pdx->StagedOffset == (pArea->aBlocks[0].dwOffset + pArea->aBlocks[0].dwSize))
- {
- pArea->aBlocks[0].dwSize += pdx->StagedLength; // Just add this transfer in
- dev_dbg(&pdx->interface->dev, "RWM_Complete, circ block 0 now %d bytes at %d",
- pArea->aBlocks[0].dwSize, pArea->aBlocks[0].dwOffset);
- }
- else // If it doesn't append, put into new block 1
- {
- pArea->aBlocks[1].dwOffset = pdx->StagedOffset;
- pArea->aBlocks[1].dwSize = pdx->StagedLength;
- dev_dbg(&pdx->interface->dev, "RWM_Complete, circ block 1 started %d bytes at %d",
- pArea->aBlocks[1].dwSize, pArea->aBlocks[1].dwOffset);
- }
- }
- else // No info stored yet, just save in block 0
- {
- pArea->aBlocks[0].dwOffset = pdx->StagedOffset;
- pArea->aBlocks[0].dwSize = pdx->StagedLength;
- dev_dbg(&pdx->interface->dev, "RWM_Complete, circ block 0 started %d bytes at %d",
- pArea->aBlocks[0].dwSize, pArea->aBlocks[0].dwOffset);
- }
- }
- }
-
- if (!bCancel) // Don't generate an event if cancelled
- {
- dev_dbg(&pdx->interface->dev, "RWM_Complete, bCircular %d, bToHost %d, eStart %d, eSize %d",
- pArea->bCircular, pArea->bEventToHost, pArea->dwEventSt, pArea->dwEventSz);
- if ((pArea->dwEventSz) && // Set a user-mode event...
- (pdx->StagedRead == pArea->bEventToHost)) // ...on transfers in this direction?
- {
- int iWakeUp = 0; // assume
- // If we have completed the right sort of DMA transfer then set the event to notify
- // the user code to wake up anyone that is waiting.
- if ((pArea->bCircular) && // Circular areas use a simpler test
- (pArea->bCircToHost)) // only in supported direction
- { // Is total data waiting up to size limit?
- unsigned int dwTotal = pArea->aBlocks[0].dwSize + pArea->aBlocks[1].dwSize;
- iWakeUp = (dwTotal >= pArea->dwEventSz);
- }
- else
- {
- unsigned int transEnd = pdx->StagedOffset + pdx->StagedLength;
- unsigned int eventEnd = pArea->dwEventSt + pArea->dwEventSz;
- iWakeUp = (pdx->StagedOffset < eventEnd) && (transEnd > pArea->dwEventSt);
- }
-
- if (iWakeUp)
- {
- dev_dbg(&pdx->interface->dev, "About to set event to notify app");
- wake_up_interruptible(&pArea->wqEvent); // wake up waiting processes
- ++pArea->iWakeUp; // increment wakeup count
- }
- }
- }
-
- pdx->dwDMAFlag = MODE_CHAR; // Switch back to char mode before ReadWriteMem call
-
- if (!bCancel) // Don't look for waiting transfer if cancelled
- {
- // If we have a transfer waiting, kick it off
- if (pdx->bXFerWaiting) // Got a block xfer waiting?
- {
- int iReturn;
- dev_info(&pdx->interface->dev, "*** RWM_Complete *** pending transfer will now be set up!!!");
- iReturn = ReadWriteMem(pdx, !pdx->rDMAInfo.bOutWard, pdx->rDMAInfo.wIdent, pdx->rDMAInfo.dwOffset, pdx->rDMAInfo.dwSize);
-
- if (iReturn)
- dev_err(&pdx->interface->dev, "RWM_Complete rw setup failed %d", iReturn);
- }
- }
-
- }
- else // Here for more to do
- StageChunk(pdx); // fire off the next bit
-
- // While we hold the stagedLock, see if we should reallow character input ints
- // Don't allow if cancelled, or if a new block has started or if there is a waiting block.
- // This feels wrong as we should ask which spin lock protects dwDMAFlag.
- bRestartCharInput = !bCancel && (pdx->dwDMAFlag == MODE_CHAR) && !pdx->bXFerWaiting;
-
- spin_unlock(&pdx->stagedLock); // Finally release the lock again
-
- // This is not correct as dwDMAFlag is protected by the staged lock, but it is treated
- // in Allowi as if it were protected by the char lock. In any case, most systems will
- // not be upset by char input during DMA... sigh. Needs sorting out.
- if (bRestartCharInput) // may be out of date, but...
- Allowi(pdx, true); // ...Allowi tests a lock too.
- dev_dbg(&pdx->interface->dev, "%s done", __func__);
+ DEVICE_EXTENSION *pdx = pUrb->context;
+ unsigned int nGot = pUrb->actual_length; // what we transferred
+ bool bCancel = false;
+ bool bRestartCharInput; // used at the end
+
+ spin_lock(&pdx->stagedLock); // stop ReadWriteMem() action while this routine is running
+ pdx->bStagedUrbPending = false; // clear the flag for staged IRP pending
+
+ if (pUrb->status) { // sync/async unlink faults aren't errors
+ if (!
+ (pUrb->status == -ENOENT || pUrb->status == -ECONNRESET
+ || pUrb->status == -ESHUTDOWN)) {
+ dev_err(&pdx->interface->dev,
+ "%s - nonzero write bulk status received: %d",
+ __func__, pUrb->status);
+ } else
+ dev_info(&pdx->interface->dev,
+ "%s - staged xfer cancelled", __func__);
+
+ spin_lock(&pdx->err_lock);
+ pdx->errors = pUrb->status;
+ spin_unlock(&pdx->err_lock);
+ nGot = 0; // and tidy up again if so
+ bCancel = true;
+ } else {
+ dev_dbg(&pdx->interface->dev, "%s %d chars xferred", __func__,
+ nGot);
+ if (pdx->StagedRead) // if reading, save to user space
+ CopyUserSpace(pdx, nGot); // copy from buffer to user
+ if (nGot == 0)
+ dev_dbg(&pdx->interface->dev, "%s ZLP", __func__);
+ }
+
+ // Update the transfer length based on the TransferBufferLength value in the URB
+ pdx->StagedDone += nGot;
+
+ dev_dbg(&pdx->interface->dev, "%s, done %d bytes of %d", __func__,
+ pdx->StagedDone, pdx->StagedLength);
+
+ if ((pdx->StagedDone == pdx->StagedLength) || // If no more to do
+ (bCancel)) // or this IRP was cancelled
+ {
+ TRANSAREA *pArea = &pdx->rTransDef[pdx->StagedId]; // Transfer area info
+ dev_dbg(&pdx->interface->dev,
+ "%s transfer done, bytes %d, cancel %d", __func__,
+ pdx->StagedDone, bCancel);
+
+ // Here is where we sort out what to do with this transfer if using a circular buffer. We have
+ // a completed transfer that can be assumed to fit into the transfer area. We should be able to
+ // add this to the end of a growing block or to use it to start a new block unless the code
+ // that calculates the offset to use (in ReadWriteMem) is totally duff.
+ if ((pArea->bCircular) && (pArea->bCircToHost) && (!bCancel) && // Time to sort out circular buffer info?
+ (pdx->StagedRead)) // Only for tohost transfers for now
+ {
+ if (pArea->aBlocks[1].dwSize > 0) // If block 1 is in use we must append to it
+ {
+ if (pdx->StagedOffset ==
+ (pArea->aBlocks[1].dwOffset +
+ pArea->aBlocks[1].dwSize)) {
+ pArea->aBlocks[1].dwSize +=
+ pdx->StagedLength;
+ dev_dbg(&pdx->interface->dev,
+ "RWM_Complete, circ block 1 now %d bytes at %d",
+ pArea->aBlocks[1].dwSize,
+ pArea->aBlocks[1].dwOffset);
+ } else {
+ // Here things have gone very, very, wrong, but I cannot see how this can actually be achieved
+ pArea->aBlocks[1].dwOffset =
+ pdx->StagedOffset;
+ pArea->aBlocks[1].dwSize =
+ pdx->StagedLength;
+ dev_err(&pdx->interface->dev,
+ "%s ERROR, circ block 1 re-started %d bytes at %d",
+ __func__,
+ pArea->aBlocks[1].dwSize,
+ pArea->aBlocks[1].dwOffset);
+ }
+ } else // If block 1 is not used, we try to add to block 0
+ {
+ if (pArea->aBlocks[0].dwSize > 0) // Got stored block 0 information?
+ { // Must append onto the existing block 0
+ if (pdx->StagedOffset ==
+ (pArea->aBlocks[0].dwOffset +
+ pArea->aBlocks[0].dwSize)) {
+ pArea->aBlocks[0].dwSize += pdx->StagedLength; // Just add this transfer in
+ dev_dbg(&pdx->interface->dev,
+ "RWM_Complete, circ block 0 now %d bytes at %d",
+ pArea->aBlocks[0].
+ dwSize,
+ pArea->aBlocks[0].
+ dwOffset);
+ } else // If it doesn't append, put into new block 1
+ {
+ pArea->aBlocks[1].dwOffset =
+ pdx->StagedOffset;
+ pArea->aBlocks[1].dwSize =
+ pdx->StagedLength;
+ dev_dbg(&pdx->interface->dev,
+ "RWM_Complete, circ block 1 started %d bytes at %d",
+ pArea->aBlocks[1].
+ dwSize,
+ pArea->aBlocks[1].
+ dwOffset);
+ }
+ } else // No info stored yet, just save in block 0
+ {
+ pArea->aBlocks[0].dwOffset =
+ pdx->StagedOffset;
+ pArea->aBlocks[0].dwSize =
+ pdx->StagedLength;
+ dev_dbg(&pdx->interface->dev,
+ "RWM_Complete, circ block 0 started %d bytes at %d",
+ pArea->aBlocks[0].dwSize,
+ pArea->aBlocks[0].dwOffset);
+ }
+ }
+ }
+
+ if (!bCancel) // Don't generate an event if cancelled
+ {
+ dev_dbg(&pdx->interface->dev,
+ "RWM_Complete, bCircular %d, bToHost %d, eStart %d, eSize %d",
+ pArea->bCircular, pArea->bEventToHost,
+ pArea->dwEventSt, pArea->dwEventSz);
+ if ((pArea->dwEventSz) && // Set a user-mode event...
+ (pdx->StagedRead == pArea->bEventToHost)) // ...on transfers in this direction?
+ {
+ int iWakeUp = 0; // assume
+ // If we have completed the right sort of DMA transfer then set the event to notify
+ // the user code to wake up anyone that is waiting.
+ if ((pArea->bCircular) && // Circular areas use a simpler test
+ (pArea->bCircToHost)) // only in supported direction
+ { // Is total data waiting up to size limit?
+ unsigned int dwTotal =
+ pArea->aBlocks[0].dwSize +
+ pArea->aBlocks[1].dwSize;
+ iWakeUp = (dwTotal >= pArea->dwEventSz);
+ } else {
+ unsigned int transEnd =
+ pdx->StagedOffset +
+ pdx->StagedLength;
+ unsigned int eventEnd =
+ pArea->dwEventSt + pArea->dwEventSz;
+ iWakeUp = (pdx->StagedOffset < eventEnd)
+ && (transEnd > pArea->dwEventSt);
+ }
+
+ if (iWakeUp) {
+ dev_dbg(&pdx->interface->dev,
+ "About to set event to notify app");
+ wake_up_interruptible(&pArea->wqEvent); // wake up waiting processes
+ ++pArea->iWakeUp; // increment wakeup count
+ }
+ }
+ }
+
+ pdx->dwDMAFlag = MODE_CHAR; // Switch back to char mode before ReadWriteMem call
+
+ if (!bCancel) // Don't look for waiting transfer if cancelled
+ {
+ // If we have a transfer waiting, kick it off
+ if (pdx->bXFerWaiting) // Got a block xfer waiting?
+ {
+ int iReturn;
+ dev_info(&pdx->interface->dev,
+ "*** RWM_Complete *** pending transfer will now be set up!!!");
+ iReturn =
+ ReadWriteMem(pdx, !pdx->rDMAInfo.bOutWard,
+ pdx->rDMAInfo.wIdent,
+ pdx->rDMAInfo.dwOffset,
+ pdx->rDMAInfo.dwSize);
+
+ if (iReturn)
+ dev_err(&pdx->interface->dev,
+ "RWM_Complete rw setup failed %d",
+ iReturn);
+ }
+ }
+
+ } else // Here for more to do
+ StageChunk(pdx); // fire off the next bit
+
+ // While we hold the stagedLock, see if we should reallow character input ints
+ // Don't allow if cancelled, or if a new block has started or if there is a waiting block.
+ // This feels wrong as we should ask which spin lock protects dwDMAFlag.
+ bRestartCharInput = !bCancel && (pdx->dwDMAFlag == MODE_CHAR)
+ && !pdx->bXFerWaiting;
+
+ spin_unlock(&pdx->stagedLock); // Finally release the lock again
+
+ // This is not correct as dwDMAFlag is protected by the staged lock, but it is treated
+ // in Allowi as if it were protected by the char lock. In any case, most systems will
+ // not be upset by char input during DMA... sigh. Needs sorting out.
+ if (bRestartCharInput) // may be out of date, but...
+ Allowi(pdx, true); // ...Allowi tests a lock too.
+ dev_dbg(&pdx->interface->dev, "%s done", __func__);
}
/****************************************************************************
** The calling code must have acquired the staging spinlock before calling
** this function, and is responsible for releasing it. We are at callback level.
****************************************************************************/
-static int StageChunk(DEVICE_EXTENSION *pdx)
+static int StageChunk(DEVICE_EXTENSION * pdx)
{
- int iReturn = U14ERR_NOERROR;
+ int iReturn = U14ERR_NOERROR;
unsigned int ChunkSize;
- int nPipe = pdx->StagedRead ? 3 : 2; // The pipe number to use for reads or writes
- if (pdx->nPipes == 3) nPipe--; // Adjust for the 3-pipe case
- if (nPipe < 0) // and trap case that should never happen
- return U14ERR_FAIL;
-
- if (!CanAcceptIoRequests(pdx)) // got sudden remove?
- {
- dev_info(&pdx->interface->dev, "%s sudden remove, giving up", __func__);
- return U14ERR_FAIL; // could do with a better error
- }
-
- ChunkSize = (pdx->StagedLength - pdx->StagedDone); // transfer length remaining
- if (ChunkSize > STAGED_SZ) // make sure to keep legal
- ChunkSize = STAGED_SZ; // limit to max allowed
-
- if (!pdx->StagedRead) // if writing...
- CopyUserSpace(pdx, ChunkSize); // ...copy data into the buffer
-
- usb_fill_bulk_urb(pdx->pStagedUrb, pdx->udev,
- pdx->StagedRead ? usb_rcvbulkpipe(pdx->udev, pdx->epAddr[nPipe]):
- usb_sndbulkpipe(pdx->udev, pdx->epAddr[nPipe]),
- pdx->pCoherStagedIO, ChunkSize, staged_callback, pdx);
- pdx->pStagedUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- usb_anchor_urb(pdx->pStagedUrb, &pdx->submitted); // in case we need to kill it
- iReturn = usb_submit_urb(pdx->pStagedUrb, GFP_ATOMIC);
- if (iReturn)
- {
- usb_unanchor_urb(pdx->pStagedUrb); // kill it
- pdx->bPipeError[nPipe] = 1; // Flag an error to be handled later
- dev_err(&pdx->interface->dev, "%s submit urb failed, code %d", __func__, iReturn);
- }
- else
- pdx->bStagedUrbPending = true; // Set the flag for staged URB pending
- dev_dbg(&pdx->interface->dev, "%s done so far:%d, this size:%d", __func__, pdx->StagedDone, ChunkSize);
-
- return iReturn;
+ int nPipe = pdx->StagedRead ? 3 : 2; // The pipe number to use for reads or writes
+ if (pdx->nPipes == 3)
+ nPipe--; // Adjust for the 3-pipe case
+ if (nPipe < 0) // and trap case that should never happen
+ return U14ERR_FAIL;
+
+ if (!CanAcceptIoRequests(pdx)) // got sudden remove?
+ {
+ dev_info(&pdx->interface->dev, "%s sudden remove, giving up",
+ __func__);
+ return U14ERR_FAIL; // could do with a better error
+ }
+
+ ChunkSize = (pdx->StagedLength - pdx->StagedDone); // transfer length remaining
+ if (ChunkSize > STAGED_SZ) // make sure to keep legal
+ ChunkSize = STAGED_SZ; // limit to max allowed
+
+ if (!pdx->StagedRead) // if writing...
+ CopyUserSpace(pdx, ChunkSize); // ...copy data into the buffer
+
+ usb_fill_bulk_urb(pdx->pStagedUrb, pdx->udev,
+ pdx->StagedRead ? usb_rcvbulkpipe(pdx->udev,
+ pdx->
+ epAddr[nPipe]) :
+ usb_sndbulkpipe(pdx->udev, pdx->epAddr[nPipe]),
+ pdx->pCoherStagedIO, ChunkSize, staged_callback, pdx);
+ pdx->pStagedUrb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ usb_anchor_urb(pdx->pStagedUrb, &pdx->submitted); // in case we need to kill it
+ iReturn = usb_submit_urb(pdx->pStagedUrb, GFP_ATOMIC);
+ if (iReturn) {
+ usb_unanchor_urb(pdx->pStagedUrb); // kill it
+ pdx->bPipeError[nPipe] = 1; // Flag an error to be handled later
+ dev_err(&pdx->interface->dev, "%s submit urb failed, code %d",
+ __func__, iReturn);
+ } else
+ pdx->bStagedUrbPending = true; // Set the flag for staged URB pending
+ dev_dbg(&pdx->interface->dev, "%s done so far:%d, this size:%d",
+ __func__, pdx->StagedDone, ChunkSize);
+
+ return iReturn;
}
/***************************************************************************
** transfer.
** dwLen - the number of bytes to transfer.
*/
-int ReadWriteMem(DEVICE_EXTENSION *pdx, bool Read, unsigned short wIdent,
- unsigned int dwOffs, unsigned int dwLen)
+int ReadWriteMem(DEVICE_EXTENSION * pdx, bool Read, unsigned short wIdent,
+ unsigned int dwOffs, unsigned int dwLen)
{
- TRANSAREA* pArea = &pdx->rTransDef[wIdent]; // Transfer area info
-
- if (!CanAcceptIoRequests(pdx)) // Are we in a state to accept new requests?
- {
- dev_err(&pdx->interface->dev, "%s can't accept requests", __func__);
- return U14ERR_FAIL;
- }
-
- dev_dbg(&pdx->interface->dev, "%s xfer %d bytes to %s, offset %d, area %d",
- __func__, dwLen, Read ? "host" : "1401", dwOffs, wIdent);
-
- // Amazingly, we can get an escape sequence back before the current staged Urb is done, so we
- // have to check for this situation and, if so, wait until all is OK.
- if (pdx->bStagedUrbPending)
- {
- pdx->bXFerWaiting = true; // Flag we are waiting
- dev_info(&pdx->interface->dev, "%s xfer is waiting, as previous staged pending", __func__);
- return U14ERR_NOERROR;
- }
-
- if (dwLen == 0) // allow 0-len read or write; just return success
- {
- dev_dbg(&pdx->interface->dev, "%s OK; zero-len read/write request", __func__);
- return U14ERR_NOERROR;
- }
-
- if ((pArea->bCircular) && // Circular transfer?
- (pArea->bCircToHost) && (Read)) // In a supported direction
- { // If so, we sort out offset ourself
- bool bWait = false; // Flag for transfer having to wait
-
- dev_dbg(&pdx->interface->dev, "Circular buffers are %d at %d and %d at %d",
- pArea->aBlocks[0].dwSize, pArea->aBlocks[0].dwOffset, pArea->aBlocks[1].dwSize, pArea->aBlocks[1].dwOffset);
- if (pArea->aBlocks[1].dwSize > 0) // Using the second block already?
- {
- dwOffs = pArea->aBlocks[1].dwOffset + pArea->aBlocks[1].dwSize; // take offset from that
- bWait = (dwOffs + dwLen) > pArea->aBlocks[0].dwOffset; // Wait if will overwrite block 0?
- bWait |= (dwOffs + dwLen) > pArea->dwLength; // or if it overflows the buffer
- }
- else // Area 1 not in use, try to use area 0
- {
- if (pArea->aBlocks[0].dwSize == 0) // Reset block 0 if not in use
- pArea->aBlocks[0].dwOffset = 0;
- dwOffs = pArea->aBlocks[0].dwOffset + pArea->aBlocks[0].dwSize;
- if ((dwOffs+dwLen) > pArea->dwLength) // Off the end of the buffer?
- {
- pArea->aBlocks[1].dwOffset = 0; // Set up to use second block
- dwOffs = 0;
- bWait = (dwOffs + dwLen) > pArea->aBlocks[0].dwOffset; // Wait if will overwrite block 0?
- bWait |= (dwOffs + dwLen) > pArea->dwLength; // or if it overflows the buffer
- }
- }
-
- if (bWait) // This transfer will have to wait?
- {
- pdx->bXFerWaiting = true; // Flag we are waiting
- dev_dbg(&pdx->interface->dev, "%s xfer waiting for circular buffer space", __func__);
- return U14ERR_NOERROR;
- }
-
- dev_dbg(&pdx->interface->dev, "%s circular xfer, %d bytes starting at %d", __func__, dwLen, dwOffs);
- }
-
- // Save the parameters for the read\write transfer
- pdx->StagedRead = Read; // Save the parameters for this read
- pdx->StagedId = wIdent; // ID allows us to get transfer area info
- pdx->StagedOffset = dwOffs; // The area within the transfer area
- pdx->StagedLength = dwLen;
- pdx->StagedDone = 0; // Initialise the byte count
- pdx->dwDMAFlag = MODE_LINEAR; // Set DMA mode flag at this point
- pdx->bXFerWaiting = false; // Clearly not a transfer waiting now
+ TRANSAREA *pArea = &pdx->rTransDef[wIdent]; // Transfer area info
+
+ if (!CanAcceptIoRequests(pdx)) // Are we in a state to accept new requests?
+ {
+ dev_err(&pdx->interface->dev, "%s can't accept requests",
+ __func__);
+ return U14ERR_FAIL;
+ }
+
+ dev_dbg(&pdx->interface->dev,
+ "%s xfer %d bytes to %s, offset %d, area %d", __func__, dwLen,
+ Read ? "host" : "1401", dwOffs, wIdent);
+
+ // Amazingly, we can get an escape sequence back before the current staged Urb is done, so we
+ // have to check for this situation and, if so, wait until all is OK.
+ if (pdx->bStagedUrbPending) {
+ pdx->bXFerWaiting = true; // Flag we are waiting
+ dev_info(&pdx->interface->dev,
+ "%s xfer is waiting, as previous staged pending",
+ __func__);
+ return U14ERR_NOERROR;
+ }
+
+ if (dwLen == 0) // allow 0-len read or write; just return success
+ {
+ dev_dbg(&pdx->interface->dev,
+ "%s OK; zero-len read/write request", __func__);
+ return U14ERR_NOERROR;
+ }
+
+ if ((pArea->bCircular) && // Circular transfer?
+ (pArea->bCircToHost) && (Read)) // In a supported direction
+ { // If so, we sort out offset ourself
+ bool bWait = false; // Flag for transfer having to wait
+
+ dev_dbg(&pdx->interface->dev,
+ "Circular buffers are %d at %d and %d at %d",
+ pArea->aBlocks[0].dwSize, pArea->aBlocks[0].dwOffset,
+ pArea->aBlocks[1].dwSize, pArea->aBlocks[1].dwOffset);
+ if (pArea->aBlocks[1].dwSize > 0) // Using the second block already?
+ {
+ dwOffs = pArea->aBlocks[1].dwOffset + pArea->aBlocks[1].dwSize; // take offset from that
+ bWait = (dwOffs + dwLen) > pArea->aBlocks[0].dwOffset; // Wait if will overwrite block 0?
+ bWait |= (dwOffs + dwLen) > pArea->dwLength; // or if it overflows the buffer
+ } else // Area 1 not in use, try to use area 0
+ {
+ if (pArea->aBlocks[0].dwSize == 0) // Reset block 0 if not in use
+ pArea->aBlocks[0].dwOffset = 0;
+ dwOffs =
+ pArea->aBlocks[0].dwOffset +
+ pArea->aBlocks[0].dwSize;
+ if ((dwOffs + dwLen) > pArea->dwLength) // Off the end of the buffer?
+ {
+ pArea->aBlocks[1].dwOffset = 0; // Set up to use second block
+ dwOffs = 0;
+ bWait = (dwOffs + dwLen) > pArea->aBlocks[0].dwOffset; // Wait if will overwrite block 0?
+ bWait |= (dwOffs + dwLen) > pArea->dwLength; // or if it overflows the buffer
+ }
+ }
+
+ if (bWait) // This transfer will have to wait?
+ {
+ pdx->bXFerWaiting = true; // Flag we are waiting
+ dev_dbg(&pdx->interface->dev,
+ "%s xfer waiting for circular buffer space",
+ __func__);
+ return U14ERR_NOERROR;
+ }
+
+ dev_dbg(&pdx->interface->dev,
+ "%s circular xfer, %d bytes starting at %d", __func__,
+ dwLen, dwOffs);
+ }
+ // Save the parameters for the read\write transfer
+ pdx->StagedRead = Read; // Save the parameters for this read
+ pdx->StagedId = wIdent; // ID allows us to get transfer area info
+ pdx->StagedOffset = dwOffs; // The area within the transfer area
+ pdx->StagedLength = dwLen;
+ pdx->StagedDone = 0; // Initialise the byte count
+ pdx->dwDMAFlag = MODE_LINEAR; // Set DMA mode flag at this point
+ pdx->bXFerWaiting = false; // Clearly not a transfer waiting now
// KeClearEvent(&pdx->StagingDoneEvent); // Clear the transfer done event
- StageChunk(pdx); // fire off the first chunk
+ StageChunk(pdx); // fire off the first chunk
- return U14ERR_NOERROR;
+ return U14ERR_NOERROR;
}
/****************************************************************************
** data we return FALSE. Used as part of decoding a DMA request.
**
****************************************************************************/
-static bool ReadChar(unsigned char* pChar, char* pBuf, unsigned int* pdDone, unsigned int dGot)
+static bool ReadChar(unsigned char *pChar, char *pBuf, unsigned int *pdDone,
+ unsigned int dGot)
{
- bool bRead = false;
- unsigned int dDone = *pdDone;
-
- if (dDone < dGot) // If there is more data
- {
- *pChar = (unsigned char)pBuf[dDone];// Extract the next char
- dDone++; // Increment the done count
- *pdDone = dDone;
- bRead = true; // and flag success
- }
-
- return bRead;
+ bool bRead = false;
+ unsigned int dDone = *pdDone;
+
+ if (dDone < dGot) // If there is more data
+ {
+ *pChar = (unsigned char)pBuf[dDone]; // Extract the next char
+ dDone++; // Increment the done count
+ *pdDone = dDone;
+ bRead = true; // and flag success
+ }
+
+ return bRead;
}
#ifdef NOTUSED
** Reads a word from the 1401, just uses ReadChar twice; passes on any error
**
*****************************************************************************/
-static bool ReadWord(unsigned short* pWord, char* pBuf, unsigned int* pdDone, unsigned int dGot)
+static bool ReadWord(unsigned short *pWord, char *pBuf, unsigned int *pdDone,
+ unsigned int dGot)
{
- if (ReadChar((unsigned char*)pWord, pBuf, pdDone, dGot))
- return ReadChar(((unsigned char*)pWord)+1, pBuf, pdDone, dGot);
- else
- return false;
+ if (ReadChar((unsigned char *)pWord, pBuf, pdDone, dGot))
+ return ReadChar(((unsigned char *)pWord) + 1, pBuf, pdDone,
+ dGot);
+ else
+ return false;
}
#endif
** to indicate three byte total.
**
*****************************************************************************/
-static bool ReadHuff(volatile unsigned int* pDWord, char* pBuf, unsigned int* pdDone, unsigned int dGot)
+static bool ReadHuff(volatile unsigned int *pDWord, char *pBuf,
+ unsigned int *pdDone, unsigned int dGot)
{
- unsigned char ucData; /* for each read to ReadChar */
- bool bReturn = true; /* assume we will succeed */
- unsigned int dwData = 0; /* Accumulator for the data */
-
- if (ReadChar(&ucData, pBuf, pdDone, dGot))
- {
- dwData = ucData; /* copy the data */
- if ((dwData & 0x00000080) != 0) /* Bit set for more data ? */
- {
- dwData &= 0x0000007F; /* Clear the relevant bit */
- if (ReadChar(&ucData, pBuf, pdDone, dGot))
- {
- dwData = (dwData << 8) | ucData;
- if ((dwData & 0x00004000) != 0) /* three byte sequence ? */
- {
- dwData &= 0x00003FFF; /* Clear the relevant bit */
- if (ReadChar(&ucData, pBuf, pdDone, dGot))
- dwData = (dwData << 8) | ucData;
- else
- bReturn = false;
- }
- }
- else
- bReturn = false; /* couldn't read data */
- }
- }
- else
- bReturn = false;
-
- *pDWord = dwData; /* return the data */
- return bReturn;
+ unsigned char ucData; /* for each read to ReadChar */
+ bool bReturn = true; /* assume we will succeed */
+ unsigned int dwData = 0; /* Accumulator for the data */
+
+ if (ReadChar(&ucData, pBuf, pdDone, dGot)) {
+ dwData = ucData; /* copy the data */
+ if ((dwData & 0x00000080) != 0) { /* Bit set for more data ? */
+ dwData &= 0x0000007F; /* Clear the relevant bit */
+ if (ReadChar(&ucData, pBuf, pdDone, dGot)) {
+ dwData = (dwData << 8) | ucData;
+ if ((dwData & 0x00004000) != 0) { /* three byte sequence ? */
+ dwData &= 0x00003FFF; /* Clear the relevant bit */
+ if (ReadChar
+ (&ucData, pBuf, pdDone, dGot))
+ dwData = (dwData << 8) | ucData;
+ else
+ bReturn = false;
+ }
+ } else
+ bReturn = false; /* couldn't read data */
+ }
+ } else
+ bReturn = false;
+
+ *pDWord = dwData; /* return the data */
+ return bReturn;
}
/***************************************************************************
** we start handling the data at offset zero.
**
*****************************************************************************/
-static bool ReadDMAInfo(volatile DMADESC* pDmaDesc, DEVICE_EXTENSION *pdx,
- char* pBuf, unsigned int dwCount)
+static bool ReadDMAInfo(volatile DMADESC * pDmaDesc, DEVICE_EXTENSION * pdx,
+ char *pBuf, unsigned int dwCount)
{
- bool bResult = false; // assume we won't succeed
- unsigned char ucData;
- unsigned int dDone = 0; // We haven't parsed anything so far
-
- dev_dbg(&pdx->interface->dev, "%s", __func__);
-
- if (ReadChar(&ucData, pBuf, &dDone, dwCount))
- {
- unsigned char ucTransCode = (ucData & 0x0F); // get code for transfer type
- unsigned short wIdent = ((ucData >> 4) & 0x07); // and area identifier
-
- // fill in the structure we were given
- pDmaDesc->wTransType = ucTransCode; // type of transfer
- pDmaDesc->wIdent = wIdent; // area to use
- pDmaDesc->dwSize = 0; // initialise other bits
- pDmaDesc->dwOffset = 0;
-
- dev_dbg(&pdx->interface->dev, "%s type: %d ident: %d", __func__, pDmaDesc->wTransType, pDmaDesc->wIdent);
-
- pDmaDesc->bOutWard = (ucTransCode != TM_EXTTOHOST); // set transfer direction
-
- switch (ucTransCode)
- {
- case TM_EXTTOHOST: // Extended linear transfer modes (the only ones!)
- case TM_EXTTO1401:
- {
- bResult = ReadHuff(&(pDmaDesc->dwOffset), pBuf, &dDone, dwCount) &&
- ReadHuff(&(pDmaDesc->dwSize), pBuf, &dDone, dwCount);
- if (bResult)
- {
- dev_dbg(&pdx->interface->dev, "%s xfer offset & size %d %d",
- __func__, pDmaDesc->dwOffset, pDmaDesc->dwSize);
-
- if ((wIdent >= MAX_TRANSAREAS) || // Illegal area number, or...
- (!pdx->rTransDef[wIdent].bUsed) || // area not set up, or...
- (pDmaDesc->dwOffset > pdx->rTransDef[wIdent].dwLength) || // range/size
- ((pDmaDesc->dwOffset + pDmaDesc->dwSize) > (pdx->rTransDef[wIdent].dwLength)))
- {
- bResult = false; // bad parameter(s)
- dev_dbg(&pdx->interface->dev, "%s bad param - id %d, bUsed %d, offset %d, size %d, area length %d",
- __func__, wIdent, pdx->rTransDef[wIdent].bUsed, pDmaDesc->dwOffset, pDmaDesc->dwSize,
- pdx->rTransDef[wIdent].dwLength);
- }
- }
- break;
- }
- default:
- break;
- }
- }
- else
- bResult = false;
-
- if (!bResult) // now check parameters for validity
- dev_err(&pdx->interface->dev, "%s error reading Esc sequence", __func__);
-
- return bResult;
+ bool bResult = false; // assume we won't succeed
+ unsigned char ucData;
+ unsigned int dDone = 0; // We haven't parsed anything so far
+
+ dev_dbg(&pdx->interface->dev, "%s", __func__);
+
+ if (ReadChar(&ucData, pBuf, &dDone, dwCount)) {
+ unsigned char ucTransCode = (ucData & 0x0F); // get code for transfer type
+ unsigned short wIdent = ((ucData >> 4) & 0x07); // and area identifier
+
+ // fill in the structure we were given
+ pDmaDesc->wTransType = ucTransCode; // type of transfer
+ pDmaDesc->wIdent = wIdent; // area to use
+ pDmaDesc->dwSize = 0; // initialise other bits
+ pDmaDesc->dwOffset = 0;
+
+ dev_dbg(&pdx->interface->dev, "%s type: %d ident: %d", __func__,
+ pDmaDesc->wTransType, pDmaDesc->wIdent);
+
+ pDmaDesc->bOutWard = (ucTransCode != TM_EXTTOHOST); // set transfer direction
+
+ switch (ucTransCode) {
+ case TM_EXTTOHOST: // Extended linear transfer modes (the only ones!)
+ case TM_EXTTO1401:
+ {
+ bResult =
+ ReadHuff(&(pDmaDesc->dwOffset), pBuf,
+ &dDone, dwCount)
+ && ReadHuff(&(pDmaDesc->dwSize), pBuf,
+ &dDone, dwCount);
+ if (bResult) {
+ dev_dbg(&pdx->interface->dev,
+ "%s xfer offset & size %d %d",
+ __func__, pDmaDesc->dwOffset,
+ pDmaDesc->dwSize);
+
+ if ((wIdent >= MAX_TRANSAREAS) || // Illegal area number, or...
+ (!pdx->rTransDef[wIdent].bUsed) || // area not set up, or...
+ (pDmaDesc->dwOffset > pdx->rTransDef[wIdent].dwLength) || // range/size
+ ((pDmaDesc->dwOffset +
+ pDmaDesc->dwSize) >
+ (pdx->rTransDef[wIdent].
+ dwLength))) {
+ bResult = false; // bad parameter(s)
+ dev_dbg(&pdx->interface->dev,
+ "%s bad param - id %d, bUsed %d, offset %d, size %d, area length %d",
+ __func__, wIdent,
+ pdx->rTransDef[wIdent].
+ bUsed,
+ pDmaDesc->dwOffset,
+ pDmaDesc->dwSize,
+ pdx->rTransDef[wIdent].
+ dwLength);
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ } else
+ bResult = false;
+
+ if (!bResult) // now check parameters for validity
+ dev_err(&pdx->interface->dev, "%s error reading Esc sequence",
+ __func__);
+
+ return bResult;
}
/****************************************************************************
** this is known to be at least 2 or we will not be called.
**
****************************************************************************/
-static int Handle1401Esc(DEVICE_EXTENSION* pdx, char* pCh, unsigned int dwCount)
+static int Handle1401Esc(DEVICE_EXTENSION * pdx, char *pCh,
+ unsigned int dwCount)
{
- int iReturn = U14ERR_FAIL;
-
- // I have no idea what this next test is about. '?' is 0x3f, which is area 3, code
- // 15. At the moment, this is not used, so it does no harm, but unless someone can
- // tell me what this is for, it should be removed from this and the Windows driver.
- if (pCh[0] == '?') // Is this an information response
- { // Parse and save the information
- }
- else
- {
- spin_lock(&pdx->stagedLock); // Lock others out
-
- if (ReadDMAInfo(&pdx->rDMAInfo, pdx, pCh, dwCount)) // Get DMA parameters
- {
- unsigned short wTransType = pdx->rDMAInfo.wTransType; // check transfer type
-
- dev_dbg(&pdx->interface->dev, "%s xfer to %s, offset %d, length %d", __func__,
- pdx->rDMAInfo.bOutWard ? "1401" : "host",
- pdx->rDMAInfo.dwOffset, pdx->rDMAInfo.dwSize);
-
- if (pdx->bXFerWaiting) // Check here for badly out of kilter...
- { // This can never happen, really
- dev_err(&pdx->interface->dev, "ERROR: DMA setup while transfer still waiting");
- spin_unlock(&pdx->stagedLock);
- }
- else
- {
- if ((wTransType == TM_EXTTOHOST) || (wTransType == TM_EXTTO1401))
- {
- iReturn = ReadWriteMem(pdx, !pdx->rDMAInfo.bOutWard, pdx->rDMAInfo.wIdent, pdx->rDMAInfo.dwOffset, pdx->rDMAInfo.dwSize);
- if (iReturn != U14ERR_NOERROR)
- dev_err(&pdx->interface->dev, "%s ReadWriteMem() failed %d", __func__, iReturn);
- }
- else // This covers non-linear transfer setup
- dev_err(&pdx->interface->dev, "%s Unknown block xfer type %d", __func__, wTransType);
- }
- }
- else // Failed to read parameters
- dev_err(&pdx->interface->dev, "%s ReadDMAInfo() fail", __func__);
-
- spin_unlock(&pdx->stagedLock); // OK here
- }
-
- dev_dbg(&pdx->interface->dev, "%s returns %d", __func__, iReturn);
-
- return iReturn;
+ int iReturn = U14ERR_FAIL;
+
+ // I have no idea what this next test is about. '?' is 0x3f, which is area 3, code
+ // 15. At the moment, this is not used, so it does no harm, but unless someone can
+ // tell me what this is for, it should be removed from this and the Windows driver.
+ if (pCh[0] == '?') // Is this an information response
+ { // Parse and save the information
+ } else {
+ spin_lock(&pdx->stagedLock); // Lock others out
+
+ if (ReadDMAInfo(&pdx->rDMAInfo, pdx, pCh, dwCount)) // Get DMA parameters
+ {
+ unsigned short wTransType = pdx->rDMAInfo.wTransType; // check transfer type
+
+ dev_dbg(&pdx->interface->dev,
+ "%s xfer to %s, offset %d, length %d", __func__,
+ pdx->rDMAInfo.bOutWard ? "1401" : "host",
+ pdx->rDMAInfo.dwOffset, pdx->rDMAInfo.dwSize);
+
+ if (pdx->bXFerWaiting) // Check here for badly out of kilter...
+ { // This can never happen, really
+ dev_err(&pdx->interface->dev,
+ "ERROR: DMA setup while transfer still waiting");
+ spin_unlock(&pdx->stagedLock);
+ } else {
+ if ((wTransType == TM_EXTTOHOST)
+ || (wTransType == TM_EXTTO1401)) {
+ iReturn =
+ ReadWriteMem(pdx,
+ !pdx->rDMAInfo.
+ bOutWard,
+ pdx->rDMAInfo.wIdent,
+ pdx->rDMAInfo.dwOffset,
+ pdx->rDMAInfo.dwSize);
+ if (iReturn != U14ERR_NOERROR)
+ dev_err(&pdx->interface->dev,
+ "%s ReadWriteMem() failed %d",
+ __func__, iReturn);
+ } else // This covers non-linear transfer setup
+ dev_err(&pdx->interface->dev,
+ "%s Unknown block xfer type %d",
+ __func__, wTransType);
+ }
+ } else // Failed to read parameters
+ dev_err(&pdx->interface->dev, "%s ReadDMAInfo() fail",
+ __func__);
+
+ spin_unlock(&pdx->stagedLock); // OK here
+ }
+
+ dev_dbg(&pdx->interface->dev, "%s returns %d", __func__, iReturn);
+
+ return iReturn;
}
/****************************************************************************
** Callback for the character read complete or error
****************************************************************************/
-static void ced_readchar_callback(struct urb* pUrb)
+static void ced_readchar_callback(struct urb *pUrb)
{
- DEVICE_EXTENSION *pdx = pUrb->context;
- int nGot = pUrb->actual_length; // what we transferred
-
- if (pUrb->status) // Do we have a problem to handle?
- {
- int nPipe = pdx->nPipes == 4 ? 1 : 0; // The pipe number to use for error
- // sync/async unlink faults aren't errors... just saying device removed or stopped
- if (!(pUrb->status == -ENOENT || pUrb->status == -ECONNRESET || pUrb->status == -ESHUTDOWN))
- {
- dev_err(&pdx->interface->dev, "%s - nonzero write bulk status received: %d", __func__, pUrb->status);
- }
- else
- dev_dbg(&pdx->interface->dev, "%s - 0 chars pUrb->status=%d (shutdown?)", __func__, pUrb->status);
-
- spin_lock(&pdx->err_lock);
- pdx->errors = pUrb->status;
- spin_unlock(&pdx->err_lock);
- nGot = 0; // and tidy up again if so
-
- spin_lock(&pdx->charInLock); // already at irq level
- pdx->bPipeError[nPipe] = 1; // Flag an error for later
- }
- else
- {
- if ((nGot > 1) && ((pdx->pCoherCharIn[0] & 0x7f) == 0x1b)) // Esc sequence?
- {
- Handle1401Esc(pdx, &pdx->pCoherCharIn[1], nGot-1); // handle it
- spin_lock(&pdx->charInLock); // already at irq level
- }
- else
- {
- spin_lock(&pdx->charInLock); // already at irq level
- if (nGot > 0)
- {
- unsigned int i;
- if (nGot < INBUF_SZ)
- {
- pdx->pCoherCharIn[nGot] = 0; // tidy the string
- dev_dbg(&pdx->interface->dev, "%s got %d chars >%s<", __func__, nGot, pdx->pCoherCharIn);
- }
-
- // We know that whatever we read must fit in the input buffer
- for (i = 0; i < nGot; i++)
- {
- pdx->inputBuffer[pdx->dwInBuffPut++] = pdx->pCoherCharIn[i] & 0x7F;
- if (pdx->dwInBuffPut >= INBUF_SZ)
- pdx->dwInBuffPut = 0;
- }
-
- if ((pdx->dwNumInput + nGot) <= INBUF_SZ)
- pdx->dwNumInput += nGot; // Adjust the buffer count accordingly
- }
- else
- dev_dbg(&pdx->interface->dev, "%s read ZLP", __func__);
- }
- }
-
- pdx->bReadCharsPending = false; // No longer have a pending read
- spin_unlock(&pdx->charInLock); // already at irq level
-
- Allowi(pdx, true); // see if we can do the next one
+ DEVICE_EXTENSION *pdx = pUrb->context;
+ int nGot = pUrb->actual_length; // what we transferred
+
+ if (pUrb->status) // Do we have a problem to handle?
+ {
+ int nPipe = pdx->nPipes == 4 ? 1 : 0; // The pipe number to use for error
+ // sync/async unlink faults aren't errors... just saying device removed or stopped
+ if (!
+ (pUrb->status == -ENOENT || pUrb->status == -ECONNRESET
+ || pUrb->status == -ESHUTDOWN)) {
+ dev_err(&pdx->interface->dev,
+ "%s - nonzero write bulk status received: %d",
+ __func__, pUrb->status);
+ } else
+ dev_dbg(&pdx->interface->dev,
+ "%s - 0 chars pUrb->status=%d (shutdown?)",
+ __func__, pUrb->status);
+
+ spin_lock(&pdx->err_lock);
+ pdx->errors = pUrb->status;
+ spin_unlock(&pdx->err_lock);
+ nGot = 0; // and tidy up again if so
+
+ spin_lock(&pdx->charInLock); // already at irq level
+ pdx->bPipeError[nPipe] = 1; // Flag an error for later
+ } else {
+ if ((nGot > 1) && ((pdx->pCoherCharIn[0] & 0x7f) == 0x1b)) // Esc sequence?
+ {
+ Handle1401Esc(pdx, &pdx->pCoherCharIn[1], nGot - 1); // handle it
+ spin_lock(&pdx->charInLock); // already at irq level
+ } else {
+ spin_lock(&pdx->charInLock); // already at irq level
+ if (nGot > 0) {
+ unsigned int i;
+ if (nGot < INBUF_SZ) {
+ pdx->pCoherCharIn[nGot] = 0; // tidy the string
+ dev_dbg(&pdx->interface->dev,
+ "%s got %d chars >%s<",
+ __func__, nGot,
+ pdx->pCoherCharIn);
+ }
+ // We know that whatever we read must fit in the input buffer
+ for (i = 0; i < nGot; i++) {
+ pdx->inputBuffer[pdx->dwInBuffPut++] =
+ pdx->pCoherCharIn[i] & 0x7F;
+ if (pdx->dwInBuffPut >= INBUF_SZ)
+ pdx->dwInBuffPut = 0;
+ }
+
+ if ((pdx->dwNumInput + nGot) <= INBUF_SZ)
+ pdx->dwNumInput += nGot; // Adjust the buffer count accordingly
+ } else
+ dev_dbg(&pdx->interface->dev, "%s read ZLP",
+ __func__);
+ }
+ }
+
+ pdx->bReadCharsPending = false; // No longer have a pending read
+ spin_unlock(&pdx->charInLock); // already at irq level
+
+ Allowi(pdx, true); // see if we can do the next one
}
/****************************************************************************
** we can pick up any inward transfers. This can be called in multiple contexts
** so we use the irqsave version of the spinlock.
****************************************************************************/
-int Allowi(DEVICE_EXTENSION* pdx, bool bInCallback)
+int Allowi(DEVICE_EXTENSION * pdx, bool bInCallback)
{
- int iReturn = U14ERR_NOERROR;
- unsigned long flags;
- spin_lock_irqsave(&pdx->charInLock, flags); // can be called in multiple contexts
-
- // We don't want char input running while DMA is in progress as we know that this
- // can cause sequencing problems for the 2270. So don't. It will also allow the
- // ERR response to get back to the host code too early on some PCs, even if there
- // is no actual driver failure, so we don't allow this at all.
- if (!pdx->bInDrawDown && // stop input if
- !pdx->bReadCharsPending && // If no read request outstanding
- (pdx->dwNumInput < (INBUF_SZ/2)) && // and there is some space
- (pdx->dwDMAFlag == MODE_CHAR) && // not doing any DMA
- (!pdx->bXFerWaiting) && // no xfer waiting to start
- (CanAcceptIoRequests(pdx))) // and activity is generally OK
- { // then off we go
- unsigned int nMax = INBUF_SZ-pdx->dwNumInput; // max we could read
- int nPipe = pdx->nPipes == 4 ? 1 : 0; // The pipe number to use
-
- dev_dbg(&pdx->interface->dev, "%s %d chars in input buffer", __func__, pdx->dwNumInput);
-
- usb_fill_int_urb(pdx->pUrbCharIn, pdx->udev,
- usb_rcvintpipe(pdx->udev, pdx->epAddr[nPipe]),
- pdx->pCoherCharIn, nMax, ced_readchar_callback,
- pdx, pdx->bInterval);
- pdx->pUrbCharIn->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; // short xfers are OK by default
- usb_anchor_urb(pdx->pUrbCharIn, &pdx->submitted); // in case we need to kill it
- iReturn = usb_submit_urb(pdx->pUrbCharIn, bInCallback ? GFP_ATOMIC : GFP_KERNEL);
- if (iReturn)
- {
- usb_unanchor_urb(pdx->pUrbCharIn); // remove from list of active Urbs
- pdx->bPipeError[nPipe] = 1; // Flag an error to be handled later
- dev_err(&pdx->interface->dev,"%s submit urb failed: %d", __func__, iReturn);
- }
- else
- pdx->bReadCharsPending = true; // Flag that we are active here
- }
-
- spin_unlock_irqrestore(&pdx->charInLock, flags);
-
- return iReturn;
+ int iReturn = U14ERR_NOERROR;
+ unsigned long flags;
+ spin_lock_irqsave(&pdx->charInLock, flags); // can be called in multiple contexts
+
+ // We don't want char input running while DMA is in progress as we know that this
+ // can cause sequencing problems for the 2270. So don't. It will also allow the
+ // ERR response to get back to the host code too early on some PCs, even if there
+ // is no actual driver failure, so we don't allow this at all.
+ if (!pdx->bInDrawDown && // stop input if
+ !pdx->bReadCharsPending && // If no read request outstanding
+ (pdx->dwNumInput < (INBUF_SZ / 2)) && // and there is some space
+ (pdx->dwDMAFlag == MODE_CHAR) && // not doing any DMA
+ (!pdx->bXFerWaiting) && // no xfer waiting to start
+ (CanAcceptIoRequests(pdx))) // and activity is generally OK
+ { // then off we go
+ unsigned int nMax = INBUF_SZ - pdx->dwNumInput; // max we could read
+ int nPipe = pdx->nPipes == 4 ? 1 : 0; // The pipe number to use
+
+ dev_dbg(&pdx->interface->dev, "%s %d chars in input buffer",
+ __func__, pdx->dwNumInput);
+
+ usb_fill_int_urb(pdx->pUrbCharIn, pdx->udev,
+ usb_rcvintpipe(pdx->udev, pdx->epAddr[nPipe]),
+ pdx->pCoherCharIn, nMax, ced_readchar_callback,
+ pdx, pdx->bInterval);
+ pdx->pUrbCharIn->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; // short xfers are OK by default
+ usb_anchor_urb(pdx->pUrbCharIn, &pdx->submitted); // in case we need to kill it
+ iReturn =
+ usb_submit_urb(pdx->pUrbCharIn,
+ bInCallback ? GFP_ATOMIC : GFP_KERNEL);
+ if (iReturn) {
+ usb_unanchor_urb(pdx->pUrbCharIn); // remove from list of active Urbs
+ pdx->bPipeError[nPipe] = 1; // Flag an error to be handled later
+ dev_err(&pdx->interface->dev,
+ "%s submit urb failed: %d", __func__, iReturn);
+ } else
+ pdx->bReadCharsPending = true; // Flag that we are active here
+ }
+
+ spin_unlock_irqrestore(&pdx->charInLock, flags);
+
+ return iReturn;
}
** enough for a 64-bit pointer.
*****************************************************************************/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
-static long ced_ioctl(struct file * file, unsigned int cmd, unsigned long ulArg)
+static long ced_ioctl(struct file *file, unsigned int cmd, unsigned long ulArg)
#else
-static int ced_ioctl(struct inode * node, struct file * file, unsigned int cmd, unsigned long ulArg)
+static int ced_ioctl(struct inode *node, struct file *file, unsigned int cmd,
+ unsigned long ulArg)
#endif
{
- int err = 0;
- DEVICE_EXTENSION *pdx = file->private_data;
- if (!CanAcceptIoRequests(pdx)) // check we still exist
- return -ENODEV;
+ int err = 0;
+ DEVICE_EXTENSION *pdx = file->private_data;
+ if (!CanAcceptIoRequests(pdx)) // check we still exist
+ return -ENODEV;
- // Check that access is allowed, where is is needed. Anything that would have an indeterminate
- // size will be checked by the specific command.
- if (_IOC_DIR(cmd) & _IOC_READ) // read from point of view of user...
- err = !access_ok(VERIFY_WRITE, (void __user *)ulArg, _IOC_SIZE(cmd)); // is kernel write
- else if (_IOC_DIR(cmd) & _IOC_WRITE) // and write from point of view of user...
- err = !access_ok(VERIFY_READ, (void __user *)ulArg, _IOC_SIZE(cmd)); // is kernel read
- if (err)
- return -EFAULT;
+ // Check that access is allowed, where is is needed. Anything that would have an indeterminate
+ // size will be checked by the specific command.
+ if (_IOC_DIR(cmd) & _IOC_READ) // read from point of view of user...
+ err = !access_ok(VERIFY_WRITE, (void __user *)ulArg, _IOC_SIZE(cmd)); // is kernel write
+ else if (_IOC_DIR(cmd) & _IOC_WRITE) // and write from point of view of user...
+ err = !access_ok(VERIFY_READ, (void __user *)ulArg, _IOC_SIZE(cmd)); // is kernel read
+ if (err)
+ return -EFAULT;
- switch (_IOC_NR(cmd))
- {
- case _IOC_NR(IOCTL_CED_SENDSTRING(0)):
- return SendString(pdx, (const char __user*)ulArg, _IOC_SIZE(cmd));
+ switch (_IOC_NR(cmd)) {
+ case _IOC_NR(IOCTL_CED_SENDSTRING(0)):
+ return SendString(pdx, (const char __user *)ulArg,
+ _IOC_SIZE(cmd));
- case _IOC_NR(IOCTL_CED_RESET1401):
- return Reset1401(pdx);
+ case _IOC_NR(IOCTL_CED_RESET1401):
+ return Reset1401(pdx);
- case _IOC_NR(IOCTL_CED_GETCHAR):
- return GetChar(pdx);
+ case _IOC_NR(IOCTL_CED_GETCHAR):
+ return GetChar(pdx);
- case _IOC_NR(IOCTL_CED_SENDCHAR):
- return SendChar(pdx, (char)ulArg);
+ case _IOC_NR(IOCTL_CED_SENDCHAR):
+ return SendChar(pdx, (char)ulArg);
- case _IOC_NR(IOCTL_CED_STAT1401):
- return Stat1401(pdx);
+ case _IOC_NR(IOCTL_CED_STAT1401):
+ return Stat1401(pdx);
- case _IOC_NR(IOCTL_CED_LINECOUNT):
- return LineCount(pdx);
+ case _IOC_NR(IOCTL_CED_LINECOUNT):
+ return LineCount(pdx);
- case _IOC_NR(IOCTL_CED_GETSTRING(0)):
- return GetString(pdx, (char __user*)ulArg, _IOC_SIZE(cmd));
+ case _IOC_NR(IOCTL_CED_GETSTRING(0)):
+ return GetString(pdx, (char __user *)ulArg, _IOC_SIZE(cmd));
- case _IOC_NR(IOCTL_CED_SETTRANSFER):
- return SetTransfer(pdx, (TRANSFERDESC __user*)ulArg);
+ case _IOC_NR(IOCTL_CED_SETTRANSFER):
+ return SetTransfer(pdx, (TRANSFERDESC __user *) ulArg);
- case _IOC_NR(IOCTL_CED_UNSETTRANSFER):
- return UnsetTransfer(pdx, (int)ulArg);
+ case _IOC_NR(IOCTL_CED_UNSETTRANSFER):
+ return UnsetTransfer(pdx, (int)ulArg);
- case _IOC_NR(IOCTL_CED_SETEVENT):
- return SetEvent(pdx, (TRANSFEREVENT __user*)ulArg);
+ case _IOC_NR(IOCTL_CED_SETEVENT):
+ return SetEvent(pdx, (TRANSFEREVENT __user *) ulArg);
- case _IOC_NR(IOCTL_CED_GETOUTBUFSPACE):
- return GetOutBufSpace(pdx);
+ case _IOC_NR(IOCTL_CED_GETOUTBUFSPACE):
+ return GetOutBufSpace(pdx);
- case _IOC_NR(IOCTL_CED_GETBASEADDRESS):
- return -1;
+ case _IOC_NR(IOCTL_CED_GETBASEADDRESS):
+ return -1;
- case _IOC_NR(IOCTL_CED_GETDRIVERREVISION):
- return (2<<24)|(DRIVERMAJREV<<16) | DRIVERMINREV; // USB | MAJOR | MINOR
+ case _IOC_NR(IOCTL_CED_GETDRIVERREVISION):
+ return (2 << 24) | (DRIVERMAJREV << 16) | DRIVERMINREV; // USB | MAJOR | MINOR
- case _IOC_NR(IOCTL_CED_GETTRANSFER):
- return GetTransfer(pdx, (TGET_TX_BLOCK __user*)ulArg);
+ case _IOC_NR(IOCTL_CED_GETTRANSFER):
+ return GetTransfer(pdx, (TGET_TX_BLOCK __user *) ulArg);
- case _IOC_NR(IOCTL_CED_KILLIO1401):
- return KillIO1401(pdx);
+ case _IOC_NR(IOCTL_CED_KILLIO1401):
+ return KillIO1401(pdx);
- case _IOC_NR(IOCTL_CED_STATEOF1401):
- return StateOf1401(pdx);
+ case _IOC_NR(IOCTL_CED_STATEOF1401):
+ return StateOf1401(pdx);
- case _IOC_NR(IOCTL_CED_GRAB1401):
- case _IOC_NR(IOCTL_CED_FREE1401):
- return U14ERR_NOERROR;
+ case _IOC_NR(IOCTL_CED_GRAB1401):
+ case _IOC_NR(IOCTL_CED_FREE1401):
+ return U14ERR_NOERROR;
- case _IOC_NR(IOCTL_CED_STARTSELFTEST):
- return StartSelfTest(pdx);
+ case _IOC_NR(IOCTL_CED_STARTSELFTEST):
+ return StartSelfTest(pdx);
- case _IOC_NR(IOCTL_CED_CHECKSELFTEST):
- return CheckSelfTest(pdx, (TGET_SELFTEST __user*)ulArg);
+ case _IOC_NR(IOCTL_CED_CHECKSELFTEST):
+ return CheckSelfTest(pdx, (TGET_SELFTEST __user *) ulArg);
- case _IOC_NR(IOCTL_CED_TYPEOF1401):
- return TypeOf1401(pdx);
+ case _IOC_NR(IOCTL_CED_TYPEOF1401):
+ return TypeOf1401(pdx);
- case _IOC_NR(IOCTL_CED_TRANSFERFLAGS):
- return TransferFlags(pdx);
+ case _IOC_NR(IOCTL_CED_TRANSFERFLAGS):
+ return TransferFlags(pdx);
- case _IOC_NR(IOCTL_CED_DBGPEEK):
- return DbgPeek(pdx, (TDBGBLOCK __user*)ulArg);
+ case _IOC_NR(IOCTL_CED_DBGPEEK):
+ return DbgPeek(pdx, (TDBGBLOCK __user *) ulArg);
- case _IOC_NR(IOCTL_CED_DBGPOKE):
- return DbgPoke(pdx, (TDBGBLOCK __user*)ulArg);
+ case _IOC_NR(IOCTL_CED_DBGPOKE):
+ return DbgPoke(pdx, (TDBGBLOCK __user *) ulArg);
- case _IOC_NR(IOCTL_CED_DBGRAMPDATA):
- return DbgRampData(pdx, (TDBGBLOCK __user*)ulArg);
+ case _IOC_NR(IOCTL_CED_DBGRAMPDATA):
+ return DbgRampData(pdx, (TDBGBLOCK __user *) ulArg);
- case _IOC_NR(IOCTL_CED_DBGRAMPADDR):
- return DbgRampAddr(pdx, (TDBGBLOCK __user*)ulArg);
+ case _IOC_NR(IOCTL_CED_DBGRAMPADDR):
+ return DbgRampAddr(pdx, (TDBGBLOCK __user *) ulArg);
- case _IOC_NR(IOCTL_CED_DBGGETDATA):
- return DbgGetData(pdx, (TDBGBLOCK __user*)ulArg);
+ case _IOC_NR(IOCTL_CED_DBGGETDATA):
+ return DbgGetData(pdx, (TDBGBLOCK __user *) ulArg);
- case _IOC_NR(IOCTL_CED_DBGSTOPLOOP):
- return DbgStopLoop(pdx);
+ case _IOC_NR(IOCTL_CED_DBGSTOPLOOP):
+ return DbgStopLoop(pdx);
- case _IOC_NR(IOCTL_CED_FULLRESET):
- pdx->bForceReset = true; // Set a flag for a full reset
- break;
+ case _IOC_NR(IOCTL_CED_FULLRESET):
+ pdx->bForceReset = true; // Set a flag for a full reset
+ break;
- case _IOC_NR(IOCTL_CED_SETCIRCULAR):
- return SetCircular(pdx, (TRANSFERDESC __user*)ulArg);
+ case _IOC_NR(IOCTL_CED_SETCIRCULAR):
+ return SetCircular(pdx, (TRANSFERDESC __user *) ulArg);
- case _IOC_NR(IOCTL_CED_GETCIRCBLOCK):
- return GetCircBlock(pdx, (TCIRCBLOCK __user*)ulArg);
+ case _IOC_NR(IOCTL_CED_GETCIRCBLOCK):
+ return GetCircBlock(pdx, (TCIRCBLOCK __user *) ulArg);
- case _IOC_NR(IOCTL_CED_FREECIRCBLOCK):
- return FreeCircBlock(pdx, (TCIRCBLOCK __user*)ulArg);
+ case _IOC_NR(IOCTL_CED_FREECIRCBLOCK):
+ return FreeCircBlock(pdx, (TCIRCBLOCK __user *) ulArg);
- case _IOC_NR(IOCTL_CED_WAITEVENT):
- return WaitEvent(pdx, (int)(ulArg & 0xff), (int)(ulArg >> 8));
+ case _IOC_NR(IOCTL_CED_WAITEVENT):
+ return WaitEvent(pdx, (int)(ulArg & 0xff), (int)(ulArg >> 8));
- case _IOC_NR(IOCTL_CED_TESTEVENT):
- return TestEvent(pdx, (int)ulArg);
+ case _IOC_NR(IOCTL_CED_TESTEVENT):
+ return TestEvent(pdx, (int)ulArg);
- default:
- return U14ERR_NO_SUCH_FN;
- }
- return U14ERR_NOERROR;
+ default:
+ return U14ERR_NO_SUCH_FN;
+ }
+ return U14ERR_NOERROR;
}
-static const struct file_operations ced_fops =
-{
- .owner = THIS_MODULE,
- .read = ced_read,
- .write = ced_write,
- .open = ced_open,
- .release = ced_release,
- .flush = ced_flush,
- .llseek = noop_llseek,
+static const struct file_operations ced_fops = {
+ .owner = THIS_MODULE,
+ .read = ced_read,
+ .write = ced_write,
+ .open = ced_open,
+ .release = ced_release,
+ .flush = ced_flush,
+ .llseek = noop_llseek,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
- .unlocked_ioctl = ced_ioctl,
+ .unlocked_ioctl = ced_ioctl,
#else
- .ioctl = ced_ioctl,
+ .ioctl = ced_ioctl,
#endif
};
* usb class driver info in order to get a minor number from the usb core,
* and to have the device registered with the driver core
*/
-static struct usb_class_driver ced_class =
-{
- .name = "cedusb%d",
- .fops = &ced_fops,
- .minor_base = USB_CED_MINOR_BASE,
+static struct usb_class_driver ced_class = {
+ .name = "cedusb%d",
+ .fops = &ced_fops,
+ .minor_base = USB_CED_MINOR_BASE,
};
// Check that the device that matches a 1401 vendor and product ID is OK to use and
// initialise our DEVICE_EXTENSION.
-static int ced_probe(struct usb_interface *interface, const struct usb_device_id *id)
+static int ced_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
{
- DEVICE_EXTENSION *pdx;
- struct usb_host_interface *iface_desc;
- struct usb_endpoint_descriptor *endpoint;
- int i, bcdDevice;
- int retval = -ENOMEM;
-
- // allocate memory for our device extension and initialize it
- pdx = kzalloc(sizeof(*pdx), GFP_KERNEL);
- if (!pdx)
- {
- dev_err(&interface->dev, "Out of memory\n");
- goto error;
- }
-
- for (i=0; i<MAX_TRANSAREAS; ++i) // Initialise the wait queues
- {
- init_waitqueue_head(&pdx->rTransDef[i].wqEvent);
- }
-
- // Put initialises for our stuff here. Note that all of *pdx is zero, so
- // no need to explicitly zero it.
- spin_lock_init(&pdx->charOutLock);
- spin_lock_init(&pdx->charInLock);
- spin_lock_init(&pdx->stagedLock);
-
- // Initialises from the skeleton stuff
- kref_init(&pdx->kref);
- mutex_init(&pdx->io_mutex);
- spin_lock_init(&pdx->err_lock);
- init_usb_anchor(&pdx->submitted);
-
- pdx->udev = usb_get_dev(interface_to_usbdev(interface));
- pdx->interface = interface;
-
- // Attempt to identify the device
- bcdDevice = pdx->udev->descriptor.bcdDevice;
- i = (bcdDevice >> 8);
- if (i == 0)
- pdx->s1401Type = TYPEU1401;
- else if ((i>=1) && (i<=23))
- pdx->s1401Type = i+2;
- else
- {
- dev_err(&interface->dev, "%s Unknown device. bcdDevice = %d", __func__, bcdDevice);
- goto error;
- }
- // set up the endpoint information. We only care about the number of EP as
- // we know that we are dealing with a 1401 device.
- iface_desc = interface->cur_altsetting;
- pdx->nPipes = iface_desc->desc.bNumEndpoints;
- dev_info(&interface->dev, "1401Type=%d with %d End Points", pdx->s1401Type, pdx->nPipes);
- if ((pdx->nPipes < 3) || (pdx->nPipes > 4))
- goto error;
-
- // Allocate the URBs we hold for performing transfers
- pdx->pUrbCharOut = usb_alloc_urb(0, GFP_KERNEL); // character output URB
- pdx->pUrbCharIn = usb_alloc_urb(0, GFP_KERNEL); // character input URB
- pdx->pStagedUrb = usb_alloc_urb(0, GFP_KERNEL); // block transfer URB
- if (!pdx->pUrbCharOut || !pdx->pUrbCharIn || !pdx->pStagedUrb)
- {
- dev_err(&interface->dev, "%s URB alloc failed", __func__);
- goto error;
- }
-
- pdx->pCoherStagedIO = usb_alloc_coherent(pdx->udev, STAGED_SZ, GFP_KERNEL, &pdx->pStagedUrb->transfer_dma);
- pdx->pCoherCharOut = usb_alloc_coherent(pdx->udev, OUTBUF_SZ, GFP_KERNEL, &pdx->pUrbCharOut->transfer_dma);
- pdx->pCoherCharIn = usb_alloc_coherent(pdx->udev, INBUF_SZ, GFP_KERNEL, &pdx->pUrbCharIn->transfer_dma);
- if (!pdx->pCoherCharOut || !pdx->pCoherCharIn || !pdx->pCoherStagedIO)
- {
- dev_err(&interface->dev, "%s Coherent buffer alloc failed", __func__);
- goto error;
- }
-
- for (i = 0; i < pdx->nPipes; ++i)
- {
- endpoint = &iface_desc->endpoint[i].desc;
- pdx->epAddr[i] = endpoint->bEndpointAddress;
- dev_info(&interface->dev, "Pipe %d, ep address %02x", i, pdx->epAddr[i]);
- if (((pdx->nPipes==3) && (i==0)) || // if char input end point
- ((pdx->nPipes==4) && (i==1)))
- {
- pdx->bInterval = endpoint->bInterval; // save the endpoint interrupt interval
- dev_info(&interface->dev, "Pipe %d, bInterval = %d", i, pdx->bInterval);
- }
-
- // Detect USB2 by checking last ep size (64 if USB1)
- if (i == pdx->nPipes-1) // if this is the last ep (bulk)
- {
- pdx->bIsUSB2 = le16_to_cpu(endpoint->wMaxPacketSize) > 64;
- dev_info(&pdx->interface->dev, "USB%d", pdx->bIsUSB2 + 1);
- }
- }
-
- /* save our data pointer in this interface device */
- usb_set_intfdata(interface, pdx);
-
- /* we can register the device now, as it is ready */
- retval = usb_register_dev(interface, &ced_class);
- if (retval)
- {
- /* something prevented us from registering this driver */
- dev_err(&interface->dev, "Not able to get a minor for this device.\n");
- usb_set_intfdata(interface, NULL);
- goto error;
- }
-
- /* let the user know what node this device is now attached to */
- dev_info(&interface->dev,
- "USB CEDUSB device now attached to cedusb #%d",
- interface->minor);
- return 0;
+ DEVICE_EXTENSION *pdx;
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ int i, bcdDevice;
+ int retval = -ENOMEM;
+
+ // allocate memory for our device extension and initialize it
+ pdx = kzalloc(sizeof(*pdx), GFP_KERNEL);
+ if (!pdx) {
+ dev_err(&interface->dev, "Out of memory\n");
+ goto error;
+ }
+
+ for (i = 0; i < MAX_TRANSAREAS; ++i) // Initialise the wait queues
+ {
+ init_waitqueue_head(&pdx->rTransDef[i].wqEvent);
+ }
+
+ // Put initialises for our stuff here. Note that all of *pdx is zero, so
+ // no need to explicitly zero it.
+ spin_lock_init(&pdx->charOutLock);
+ spin_lock_init(&pdx->charInLock);
+ spin_lock_init(&pdx->stagedLock);
+
+ // Initialises from the skeleton stuff
+ kref_init(&pdx->kref);
+ mutex_init(&pdx->io_mutex);
+ spin_lock_init(&pdx->err_lock);
+ init_usb_anchor(&pdx->submitted);
+
+ pdx->udev = usb_get_dev(interface_to_usbdev(interface));
+ pdx->interface = interface;
+
+ // Attempt to identify the device
+ bcdDevice = pdx->udev->descriptor.bcdDevice;
+ i = (bcdDevice >> 8);
+ if (i == 0)
+ pdx->s1401Type = TYPEU1401;
+ else if ((i >= 1) && (i <= 23))
+ pdx->s1401Type = i + 2;
+ else {
+ dev_err(&interface->dev, "%s Unknown device. bcdDevice = %d",
+ __func__, bcdDevice);
+ goto error;
+ }
+ // set up the endpoint information. We only care about the number of EP as
+ // we know that we are dealing with a 1401 device.
+ iface_desc = interface->cur_altsetting;
+ pdx->nPipes = iface_desc->desc.bNumEndpoints;
+ dev_info(&interface->dev, "1401Type=%d with %d End Points",
+ pdx->s1401Type, pdx->nPipes);
+ if ((pdx->nPipes < 3) || (pdx->nPipes > 4))
+ goto error;
+
+ // Allocate the URBs we hold for performing transfers
+ pdx->pUrbCharOut = usb_alloc_urb(0, GFP_KERNEL); // character output URB
+ pdx->pUrbCharIn = usb_alloc_urb(0, GFP_KERNEL); // character input URB
+ pdx->pStagedUrb = usb_alloc_urb(0, GFP_KERNEL); // block transfer URB
+ if (!pdx->pUrbCharOut || !pdx->pUrbCharIn || !pdx->pStagedUrb) {
+ dev_err(&interface->dev, "%s URB alloc failed", __func__);
+ goto error;
+ }
+
+ pdx->pCoherStagedIO =
+ usb_alloc_coherent(pdx->udev, STAGED_SZ, GFP_KERNEL,
+ &pdx->pStagedUrb->transfer_dma);
+ pdx->pCoherCharOut =
+ usb_alloc_coherent(pdx->udev, OUTBUF_SZ, GFP_KERNEL,
+ &pdx->pUrbCharOut->transfer_dma);
+ pdx->pCoherCharIn =
+ usb_alloc_coherent(pdx->udev, INBUF_SZ, GFP_KERNEL,
+ &pdx->pUrbCharIn->transfer_dma);
+ if (!pdx->pCoherCharOut || !pdx->pCoherCharIn || !pdx->pCoherStagedIO) {
+ dev_err(&interface->dev, "%s Coherent buffer alloc failed",
+ __func__);
+ goto error;
+ }
+
+ for (i = 0; i < pdx->nPipes; ++i) {
+ endpoint = &iface_desc->endpoint[i].desc;
+ pdx->epAddr[i] = endpoint->bEndpointAddress;
+ dev_info(&interface->dev, "Pipe %d, ep address %02x", i,
+ pdx->epAddr[i]);
+ if (((pdx->nPipes == 3) && (i == 0)) || // if char input end point
+ ((pdx->nPipes == 4) && (i == 1))) {
+ pdx->bInterval = endpoint->bInterval; // save the endpoint interrupt interval
+ dev_info(&interface->dev, "Pipe %d, bInterval = %d", i,
+ pdx->bInterval);
+ }
+ // Detect USB2 by checking last ep size (64 if USB1)
+ if (i == pdx->nPipes - 1) // if this is the last ep (bulk)
+ {
+ pdx->bIsUSB2 =
+ le16_to_cpu(endpoint->wMaxPacketSize) > 64;
+ dev_info(&pdx->interface->dev, "USB%d",
+ pdx->bIsUSB2 + 1);
+ }
+ }
+
+ /* save our data pointer in this interface device */
+ usb_set_intfdata(interface, pdx);
+
+ /* we can register the device now, as it is ready */
+ retval = usb_register_dev(interface, &ced_class);
+ if (retval) {
+ /* something prevented us from registering this driver */
+ dev_err(&interface->dev,
+ "Not able to get a minor for this device.\n");
+ usb_set_intfdata(interface, NULL);
+ goto error;
+ }
+
+ /* let the user know what node this device is now attached to */
+ dev_info(&interface->dev,
+ "USB CEDUSB device now attached to cedusb #%d",
+ interface->minor);
+ return 0;
error:
- if (pdx)
- kref_put(&pdx->kref, ced_delete); // frees allocated memory
- return retval;
+ if (pdx)
+ kref_put(&pdx->kref, ced_delete); // frees allocated memory
+ return retval;
}
static void ced_disconnect(struct usb_interface *interface)
{
- DEVICE_EXTENSION *pdx = usb_get_intfdata(interface);
- int minor = interface->minor; // save for message at the end
- int i;
-
- usb_set_intfdata(interface, NULL); // remove the pdx from the interface
- usb_deregister_dev(interface, &ced_class); // give back our minor device number
-
- mutex_lock(&pdx->io_mutex); // stop more I/O starting while...
- ced_draw_down(pdx); // ...wait for then kill any io
- for (i=0; i<MAX_TRANSAREAS; ++i)
- {
- int iErr = ClearArea(pdx, i); // ...release any used memory
- if (iErr == U14ERR_UNLOCKFAIL)
- dev_err(&pdx->interface->dev, "%s Area %d was in used", __func__, i);
- }
- pdx->interface = NULL; // ...we kill off link to interface
- mutex_unlock(&pdx->io_mutex);
+ DEVICE_EXTENSION *pdx = usb_get_intfdata(interface);
+ int minor = interface->minor; // save for message at the end
+ int i;
+
+ usb_set_intfdata(interface, NULL); // remove the pdx from the interface
+ usb_deregister_dev(interface, &ced_class); // give back our minor device number
+
+ mutex_lock(&pdx->io_mutex); // stop more I/O starting while...
+ ced_draw_down(pdx); // ...wait for then kill any io
+ for (i = 0; i < MAX_TRANSAREAS; ++i) {
+ int iErr = ClearArea(pdx, i); // ...release any used memory
+ if (iErr == U14ERR_UNLOCKFAIL)
+ dev_err(&pdx->interface->dev, "%s Area %d was in used",
+ __func__, i);
+ }
+ pdx->interface = NULL; // ...we kill off link to interface
+ mutex_unlock(&pdx->io_mutex);
- usb_kill_anchored_urbs(&pdx->submitted);
+ usb_kill_anchored_urbs(&pdx->submitted);
- kref_put(&pdx->kref, ced_delete); // decrement our usage count
+ kref_put(&pdx->kref, ced_delete); // decrement our usage count
- dev_info(&interface->dev, "USB cedusb #%d now disconnected", minor);
+ dev_info(&interface->dev, "USB cedusb #%d now disconnected", minor);
}
// Wait for all the urbs we know of to be done with, then kill off any that
// are left. NBNB we will need to have a mechanism to stop circular xfers
// from trying to fire off more urbs. We will wait up to 3 seconds for Urbs
// to be done.
-void ced_draw_down(DEVICE_EXTENSION *pdx)
+void ced_draw_down(DEVICE_EXTENSION * pdx)
{
- int time;
- dev_dbg(&pdx->interface->dev,"%s called", __func__);
-
- pdx->bInDrawDown = true;
- time = usb_wait_anchor_empty_timeout(&pdx->submitted, 3000);
- if (!time) // if we timed out we kill the urbs
- {
- usb_kill_anchored_urbs(&pdx->submitted);
- dev_err(&pdx->interface->dev,"%s timed out", __func__);
- }
- pdx->bInDrawDown = false;
- }
+ int time;
+ dev_dbg(&pdx->interface->dev, "%s called", __func__);
+
+ pdx->bInDrawDown = true;
+ time = usb_wait_anchor_empty_timeout(&pdx->submitted, 3000);
+ if (!time) // if we timed out we kill the urbs
+ {
+ usb_kill_anchored_urbs(&pdx->submitted);
+ dev_err(&pdx->interface->dev, "%s timed out", __func__);
+ }
+ pdx->bInDrawDown = false;
+}
static int ced_suspend(struct usb_interface *intf, pm_message_t message)
{
- DEVICE_EXTENSION *pdx = usb_get_intfdata(intf);
- if (!pdx)
- return 0;
- ced_draw_down(pdx);
+ DEVICE_EXTENSION *pdx = usb_get_intfdata(intf);
+ if (!pdx)
+ return 0;
+ ced_draw_down(pdx);
- dev_dbg(&pdx->interface->dev,"%s called", __func__);
- return 0;
+ dev_dbg(&pdx->interface->dev, "%s called", __func__);
+ return 0;
}
static int ced_resume(struct usb_interface *intf)
{
- DEVICE_EXTENSION *pdx = usb_get_intfdata(intf);
- if (!pdx)
- return 0;
- dev_dbg(&pdx->interface->dev,"%s called", __func__);
- return 0;
+ DEVICE_EXTENSION *pdx = usb_get_intfdata(intf);
+ if (!pdx)
+ return 0;
+ dev_dbg(&pdx->interface->dev, "%s called", __func__);
+ return 0;
}
static int ced_pre_reset(struct usb_interface *intf)
{
- DEVICE_EXTENSION *pdx = usb_get_intfdata(intf);
- dev_dbg(&pdx->interface->dev, "%s", __func__);
- mutex_lock(&pdx->io_mutex);
- ced_draw_down(pdx);
- return 0;
+ DEVICE_EXTENSION *pdx = usb_get_intfdata(intf);
+ dev_dbg(&pdx->interface->dev, "%s", __func__);
+ mutex_lock(&pdx->io_mutex);
+ ced_draw_down(pdx);
+ return 0;
}
static int ced_post_reset(struct usb_interface *intf)
{
- DEVICE_EXTENSION *pdx = usb_get_intfdata(intf);
- dev_dbg(&pdx->interface->dev, "%s", __func__);
+ DEVICE_EXTENSION *pdx = usb_get_intfdata(intf);
+ dev_dbg(&pdx->interface->dev, "%s", __func__);
- /* we are sure no URBs are active - no locking needed */
- pdx->errors = -EPIPE;
- mutex_unlock(&pdx->io_mutex);
+ /* we are sure no URBs are active - no locking needed */
+ pdx->errors = -EPIPE;
+ mutex_unlock(&pdx->io_mutex);
- return 0;
+ return 0;
}
-static struct usb_driver ced_driver =
-{
- .name = "cedusb",
- .probe = ced_probe,
- .disconnect = ced_disconnect,
- .suspend = ced_suspend,
- .resume = ced_resume,
- .pre_reset = ced_pre_reset,
- .post_reset = ced_post_reset,
- .id_table = ced_table,
- .supports_autosuspend = 1,
+static struct usb_driver ced_driver = {
+ .name = "cedusb",
+ .probe = ced_probe,
+ .disconnect = ced_disconnect,
+ .suspend = ced_suspend,
+ .resume = ced_resume,
+ .pre_reset = ced_pre_reset,
+ .post_reset = ced_post_reset,
+ .id_table = ced_table,
+ .supports_autosuspend = 1,
};
static int __init usb_skel_init(void)
{
- /* register this driver with the USB subsystem */
- return usb_register(&ced_driver);
+ /* register this driver with the USB subsystem */
+ return usb_register(&ced_driver);
}
static void __exit usb_skel_exit(void)
{
- /* deregister this driver with the USB subsystem */
- usb_deregister(&ced_driver);
+ /* deregister this driver with the USB subsystem */
+ usb_deregister(&ced_driver);
}
module_init(usb_skel_init);