source "drivers/staging/silicom/Kconfig"
-source "drivers/staging/ced1401/Kconfig"
-
source "drivers/staging/imx-drm/Kconfig"
source "drivers/staging/fwserial/Kconfig"
obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/
obj-$(CONFIG_LTE_GDM724X) += gdm724x/
obj-$(CONFIG_NET_VENDOR_SILICOM) += silicom/
-obj-$(CONFIG_CED1401) += ced1401/
obj-$(CONFIG_DRM_IMX) += imx-drm/
obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/
obj-$(CONFIG_GOLDFISH) += goldfish/
+++ /dev/null
-config CED1401
- tristate "Cambridge Electronic Design 1401 USB support"
- depends on USB
- help
- This driver supports the Cambridge Electronic Design 1401 USB device
- (whatever that is.)
+++ /dev/null
-
-obj-$(CONFIG_CED1401) := cedusb.o
-cedusb-objs := usb1401.o ced_ioc.o
+++ /dev/null
-TODO:
- - coding syle fixes
- - build warning fixups
- - ioctl auditing
- - usb api auditing
- - proper USB minor number (it's stomping on an existing one right now.)
-
-Please send patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org> and Cc:
-Alois Schlögl <alois.schloegl@ist.ac.at>
-
+++ /dev/null
-/* ced_ioc.c
- ioctl part of the 1401 usb device driver for linux.
- Copyright (C) 2010 Cambridge Electronic Design Ltd
- Author Greg P Smith (greg@ced.co.uk)
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/kref.h>
-#include <linux/uaccess.h>
-#include <linux/usb.h>
-#include <linux/mutex.h>
-#include <linux/page-flags.h>
-#include <linux/pagemap.h>
-#include <linux/jiffies.h>
-
-#include "usb1401.h"
-
-/****************************************************************************
-** ced_flush_out_buff
-**
-** Empties the Output buffer and sets int lines. Used from user level only
-****************************************************************************/
-static void ced_flush_out_buff(struct ced_data *ced)
-{
- dev_dbg(&ced->interface->dev, "%s: current_state=%d\n",
- __func__, ced->current_state);
-
- /* Do nothing if hardware in trouble */
- if (ced->current_state == U14ERR_TIME)
- return;
- /* Kill off any pending I/O */
- /* CharSend_Cancel(ced); */
- spin_lock_irq(&ced->char_out_lock);
- ced->num_output = 0;
- ced->out_buff_get = 0;
- ced->out_buff_put = 0;
- spin_unlock_irq(&ced->char_out_lock);
-}
-
-/****************************************************************************
-**
-** ced_flush_in_buff
-**
-** Empties the input buffer and sets int lines
-****************************************************************************/
-static void ced_flush_in_buff(struct ced_data *ced)
-{
- dev_dbg(&ced->interface->dev, "%s: current_state=%d\n",
- __func__, ced->current_state);
-
- if (ced->current_state == U14ERR_TIME)
- return; /* Do nothing if hardware in trouble */
-
- /* Kill off any pending I/O */
- /* CharRead_Cancel(pDevObject); */
- spin_lock_irq(&ced->char_in_lock);
- ced->num_input = 0;
- ced->in_buff_get = 0;
- ced->in_buff_put = 0;
- spin_unlock_irq(&ced->char_in_lock);
-}
-
-/****************************************************************************
-** ced_put_chars
-**
-** Utility routine to copy chars into the output buffer and fire them off.
-** called from user mode, holds char_out_lock.
-****************************************************************************/
-static int ced_put_chars(struct ced_data *ced, const char *ch,
- unsigned int count)
-{
- int ret;
-
- spin_lock_irq(&ced->char_out_lock); /* get the output spin lock */
- if ((OUTBUF_SZ - ced->num_output) >= count) {
- unsigned int u;
-
- for (u = 0; u < count; u++) {
- ced->output_buffer[ced->out_buff_put++] = ch[u];
- if (ced->out_buff_put >= OUTBUF_SZ)
- ced->out_buff_put = 0;
- }
- ced->num_output += count;
- spin_unlock_irq(&ced->char_out_lock);
-
- /* ...give a chance to transmit data */
- ret = ced_send_chars(ced);
- } else {
- ret = U14ERR_NOOUT; /* no room at the out (ha-ha) */
- spin_unlock_irq(&ced->char_out_lock);
- }
- return ret;
-}
-
-/*****************************************************************************
-** Add the data in "data" local pointer of length n to the output buffer, and
-** trigger an output transfer if this is appropriate. User mode.
-** Holds the io_mutex
-*****************************************************************************/
-int ced_send_string(struct ced_data *ced, const char __user *data,
- unsigned int n)
-{
- int ret = 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, data, n))
- return -EFAULT;
- buffer[n] = 0; /* terminate for debug purposes */
-
- mutex_lock(&ced->io_mutex); /* Protect disconnect from new i/o */
- if (n > 0) { /* do nothing if nowt to do! */
- dev_dbg(&ced->interface->dev, "%s: n=%d>%s<\n",
- __func__, n, buffer);
- ret = ced_put_chars(ced, buffer, n);
- }
-
- ced_allowi(ced); /* make sure we have input int */
- mutex_unlock(&ced->io_mutex);
-
- return ret;
-}
-
-/****************************************************************************
-** ced_send_char
-**
-** Sends a single character to the 1401. User mode, holds io_mutex.
-****************************************************************************/
-int ced_send_char(struct ced_data *ced, char c)
-{
- int ret;
-
- mutex_lock(&ced->io_mutex); /* Protect disconnect from new i/o */
- ret = ced_put_chars(ced, &c, 1);
- dev_dbg(&ced->interface->dev, "ced_send_char >%c< (0x%02x)\n", c, c);
- ced_allowi(ced); /* Make sure char reads are running */
- mutex_unlock(&ced->io_mutex);
- return ret;
-}
-
-/***************************************************************************
-**
-** ced_get_state
-**
-** Retrieves state information from the 1401, adjusts the 1401 state held
-** in the device extension to indicate the current 1401 type.
-**
-** *state is updated with information about the 1401 state as returned by the
-** 1401. The low byte is a code for what 1401 is doing:
-**
-** 0 normal 1401 operation
-** 1 sending chars to host
-** 2 sending block data to host
-** 3 reading block data from host
-** 4 sending an escape sequence to the host
-** 0x80 1401 is executing self-test, in which case the upper word
-** is the last error code seen (or zero for no new error).
-**
-** *error is updated with error information if a self-test error code
-** is returned in the upper word of state.
-**
-** both state and error are set to -1 if there are comms problems, and
-** to zero if there is a simple failure.
-**
-** return error code (U14ERR_NOERROR for OK)
-*/
-int ced_get_state(struct ced_data *ced, __u32 *state, __u32 *error)
-{
- int got;
-
- dev_dbg(&ced->interface->dev, "%s: entry\n", __func__);
-
- *state = 0xFFFFFFFF; /* Start off with invalid state */
- got = usb_control_msg(ced->udev, usb_rcvctrlpipe(ced->udev, 0),
- GET_STATUS, (D_TO_H | VENDOR | DEVREQ), 0, 0,
- ced->stat_buf, sizeof(ced->stat_buf), HZ);
- if (got != sizeof(ced->stat_buf)) {
- dev_err(&ced->interface->dev,
- "%s: FAILED, return code %d\n", __func__, got);
- /* Indicate that things are very wrong indeed */
- ced->current_state = U14ERR_TIME;
- *state = 0; /* Force status values to a known state */
- *error = 0;
- } else {
- int device;
-
- dev_dbg(&ced->interface->dev,
- "%s: Success, state: 0x%x, 0x%x\n",
- __func__, ced->stat_buf[0], ced->stat_buf[1]);
-
- /* Return the state values to the calling code */
- *state = ced->stat_buf[0];
-
- *error = ced->stat_buf[1];
-
- /* 1401 type code value */
- device = ced->udev->descriptor.bcdDevice >> 8;
- switch (device) { /* so we can clean up current state */
- case 0:
- ced->current_state = U14ERR_U1401;
- break;
-
- default: /* allow lots of device codes for future 1401s */
- if ((device >= 1) && (device <= 23))
- ced->current_state = (short)(device + 6);
- else
- ced->current_state = U14ERR_ILL;
- break;
- }
- }
-
- return ced->current_state >= 0 ? U14ERR_NOERROR : ced->current_state;
-}
-
-/****************************************************************************
-** ced_read_write_cancel
-**
-** Kills off staged read\write request from the USB if one is pending.
-****************************************************************************/
-int ced_read_write_cancel(struct ced_data *ced)
-{
- dev_dbg(&ced->interface->dev, "%s: entry %d\n",
- __func__, ced->staged_urb_pending);
-#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(&ced->staged_lock);
-
- if (ced->staged_urb_pending) {/* anything to be cancelled? */
- /* May need more... */
- dev_info(&ced->interface - dev,
- "ced_read_write_cancel about to cancel Urb\n");
- /* Clear the staging done flag */
- /* KeClearEvent(&ced->StagingDoneEvent); */
- USB_ASSERT(ced->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(&ced->staged_lock);
-
- /* Actually do the cancel */
- bResult = IoCancelIrp(ced->pStagedIrp);
- if (bResult) {
- LARGE_INTEGER timeout;
-
- /* Use a timeout of 1 second */
- timeout.QuadPart = -10000000;
- dev_info(&ced->interface - dev,
- "%s: about to wait till done\n", __func__);
- ntStatus =
- KeWaitForSingleObject(&ced->StagingDoneEvent,
- Executive, KernelMode, FALSE,
- &timeout);
- } else {
- dev_info(&ced->interface - dev,
- "%s: cancellation failed\n", __func__);
- ntStatus = U14ERR_FAIL;
- }
- USB_KdPrint(DBGLVL_DEFAULT,
- ("ced_read_write_cancel ntStatus = 0x%x decimal %d\n",
- ntStatus, ntStatus));
- } else
- spin_unlock_irq(&ced->staged_lock);
-
- dev_info(&ced->interface - dev, "%s: done\n", __func__);
- return ntStatus;
-#else
- return U14ERR_NOERROR;
-#endif
-
-}
-
-/***************************************************************************
-** ced_in_self_test - 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 ced_in_self_test(struct ced_data *ced, unsigned int *stat)
-{
- unsigned int state, error;
- int ret = ced_get_state(ced, &state, &error); /* see if in self-test */
-
- if (ret == U14ERR_NOERROR) /* if all still OK */
- ret = (state == (unsigned int)-1) || /* TX problem or... */
- ((state & 0xff) == 0x80); /* ...self test */
- *stat = state; /* return actual state */
- return ret;
-}
-
-/***************************************************************************
-** ced_is_1401 - ALWAYS CALLED HOLDING THE io_mutex
-**
-** Tests for the current state of the 1401. Sets current_state:
-**
-** U14ERR_NOIF 1401 i/f card not installed (not done here)
-** U14ERR_OFF 1401 apparently not switched on
-** U14ERR_NC 1401 appears to be not connected
-** U14ERR_ILL 1401 if it is there its not very well at all
-** U14ERR_TIME 1401 appears OK, but doesn't communicate - very bad
-** U14ERR_STD 1401 OK and ready for use
-** U14ERR_PLUS 1401+ OK and ready for use
-** U14ERR_U1401 Micro1401 OK and ready for use
-** U14ERR_POWER Power1401 OK and ready for use
-** U14ERR_U14012 Micro1401 mkII OK and ready for use
-**
-** Returns TRUE if a 1401 detected and OK, else FALSE
-****************************************************************************/
-static bool ced_is_1401(struct ced_data *ced)
-{
- int ret;
-
- dev_dbg(&ced->interface->dev, "%s\n", __func__);
-
- ced_draw_down(ced); /* wait for, then kill outstanding Urbs */
- ced_flush_in_buff(ced); /* Clear out input buffer & pipe */
- ced_flush_out_buff(ced); /* 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 */
- ret = usb_lock_device_for_reset(ced->udev, ced->interface);
-
- /* release the io_mutex because if we don't, we will deadlock due to */
- /* system calls back into the driver. */
- mutex_unlock(&ced->io_mutex); /* locked, so we will not get */
- /* system calls */
- if (ret >= 0) { /* if we failed */
- ret = usb_reset_device(ced->udev); /* try to do the reset */
- usb_unlock_device(ced->udev); /* undo the lock */
- }
-
- mutex_lock(&ced->io_mutex); /* hold stuff off while we wait */
- ced->dma_flag = MODE_CHAR; /* Clear DMA mode flag regardless! */
- if (ret == 0) { /* if all is OK still */
- unsigned int state;
-
- ret = ced_in_self_test(ced, &state); /* see if likely in */
- /* self test */
- if (ret > 0) { /* do we need to wait for self-test? */
- /* when to give up */
- unsigned long timeout = jiffies + 30 * HZ;
-
- while ((ret > 0) && time_before(jiffies, timeout)) {
- schedule(); /* let other stuff run */
-
- /* see if done yet */
- ret = ced_in_self_test(ced, &state);
- }
- }
-
- if (ret == 0) /* if all is OK... */
- /* then success is that the state is 0 */
- ret = state == 0;
- } else
- ret = 0; /* we failed */
- ced->force_reset = false; /* Clear forced reset flag now */
-
- return ret > 0;
-}
-
-/****************************************************************************
-** ced_quick_check - ALWAYS CALLED HOLDING THE io_mutex
-** This is used to test for a 1401. It will try to do a quick check if all is
-** OK, that is the 1401 was OK the last time it was asked, and there is no DMA
-** in progress, and if the bTestBuff flag is set, the character buffers must be
-** empty too. If the quick check shows that the state is still the same, then
-** all is OK.
-**
-** If any of the above conditions are not met, or if the state or type of the
-** 1401 has changed since the previous test, the full ced_is_1401 test is done,
-** but only if can_reset is also TRUE.
-**
-** The return value is TRUE if a useable 1401 is found, FALSE if not
-*/
-static bool ced_quick_check(struct ced_data *ced, bool test_buff,
- bool can_reset)
-{
- bool ret = false; /* assume it will fail and we will reset */
- bool short_test;
-
- short_test = ((ced->dma_flag == MODE_CHAR) && /* no DMA running */
- (!ced->force_reset) && /* Not had a real reset forced */
- /* No 1401 errors stored */
- (ced->current_state >= U14ERR_STD));
-
- dev_dbg(&ced->interface->dev,
- "%s: DMAFlag:%d, state:%d, force:%d, testBuff:%d, short:%d\n",
- __func__, ced->dma_flag, ced->current_state, ced->force_reset,
- test_buff, short_test);
-
- if ((test_buff) && /* Buffer check requested, and... */
- (ced->num_input || ced->num_output)) {/* ...characters were in */
- /* the buffer? */
- short_test = false; /* Then do the full test */
- dev_dbg(&ced->interface->dev,
- "%s: will reset as buffers not empty\n", __func__);
- }
-
- if (short_test || !can_reset) { /* Still OK to try the short test? */
- /* Always test if no reset - we */
- /* want state update */
- unsigned int state, error;
-
- dev_dbg(&ced->interface->dev, "%s: ced_get_state\n", __func__);
-
- /* Check on the 1401 state */
- if (ced_get_state(ced, &state, &error) == U14ERR_NOERROR) {
- /* If call worked, check the status value */
- if ((state & 0xFF) == 0)
- ret = true; /* If that was zero, all is OK, */
- /* no reset needed */
- }
- }
-
- if (!ret && can_reset) { /* If all not OK, then */
- dev_info(&ced->interface->dev, "%s: ced_is_1401 %d %d %d %d\n",
- __func__, short_test, ced->current_state, test_buff,
- ced->force_reset);
- ret = ced_is_1401(ced); /* do full test */
- }
-
- return ret;
-}
-
-/****************************************************************************
-** ced_reset
-**
-** Resets the 1401 and empties the i/o buffers
-*****************************************************************************/
-int ced_reset(struct ced_data *ced)
-{
- mutex_lock(&ced->io_mutex); /* Protect disconnect from new i/o */
- dev_dbg(&ced->interface->dev, "%s: About to call ced_quick_check\n",
- __func__);
- ced_quick_check(ced, true, true); /* Check 1401, reset if not OK */
- mutex_unlock(&ced->io_mutex);
- return U14ERR_NOERROR;
-}
-
-/****************************************************************************
-** ced_get_char
-**
-** Gets a single character from the 1401
-****************************************************************************/
-int ced_get_char(struct ced_data *ced)
-{
- int ret = U14ERR_NOIN; /* assume we will get nothing */
-
- mutex_lock(&ced->io_mutex); /* Protect disconnect from new i/o */
-
- dev_dbg(&ced->interface->dev, "%s\n", __func__);
-
- ced_allowi(ced); /* Make sure char reads are running */
- ced_send_chars(ced); /* and send any buffered chars */
-
- spin_lock_irq(&ced->char_in_lock);
- if (ced->num_input > 0) { /* worth looking */
- ret = ced->input_buffer[ced->in_buff_get++];
- if (ced->in_buff_get >= INBUF_SZ)
- ced->in_buff_get = 0;
- ced->num_input--;
- } else
- ret = U14ERR_NOIN; /* no input data to read */
- spin_unlock_irq(&ced->char_in_lock);
-
- ced_allowi(ced); /* Make sure char reads are running */
-
- mutex_unlock(&ced->io_mutex); /* Protect disconnect from new i/o */
- return ret;
-}
-
-/****************************************************************************
-** ced_get_string
-**
-** Gets a string from the 1401. Returns chars up to the next CR or when
-** there are no more to read or nowhere to put them. CR is translated to
-** 0 and counted as a character. If the string does not end in a 0, we will
-** add one, if there is room, but it is not counted as a character.
-**
-** returns the count of characters (including the terminator, or 0 if none
-** or a negative error code.
-****************************************************************************/
-int ced_get_string(struct ced_data *ced, char __user *user, int n)
-{
- int available; /* character in the buffer */
- int ret = U14ERR_NOIN;
-
- if (n <= 0)
- return -ENOMEM;
-
- mutex_lock(&ced->io_mutex); /* Protect disconnect from new i/o */
- ced_allowi(ced); /* Make sure char reads are running */
- ced_send_chars(ced); /* and send any buffered chars */
-
- spin_lock_irq(&ced->char_in_lock);
- available = ced->num_input; /* characters available now */
- if (available > n) /* read max of space in user... */
- available = n; /* ...or input characters */
-
- if (available > 0) { /* worth looking? */
- char buffer[INBUF_SZ + 1]; /* space for a linear copy of data */
- int got = 0;
- int n_copy_to_user; /* number to copy to user */
- char data;
-
- do {
- data = ced->input_buffer[ced->in_buff_get++];
- if (data == CR_CHAR) /* replace CR with zero */
- data = (char)0;
-
- if (ced->in_buff_get >= INBUF_SZ)
- ced->in_buff_get = 0; /* wrap buffer pointer */
-
- buffer[got++] = data; /* save the output */
- } while ((got < available) && data);
-
- n_copy_to_user = got; /* what to copy... */
- if (data) { /* do we need null */
- buffer[got] = (char)0; /* make it tidy */
- if (got < n) /* if space in user buffer... */
- ++n_copy_to_user; /* ...copy the 0 as well. */
- }
-
- ced->num_input -= got;
- spin_unlock_irq(&ced->char_in_lock);
-
- dev_dbg(&ced->interface->dev, "%s: read %d characters >%s<\n",
- __func__, got, buffer);
- if (copy_to_user(user, buffer, n_copy_to_user))
- ret = -EFAULT;
- else
- ret = got; /* report characters read */
- } else
- spin_unlock_irq(&ced->char_in_lock);
-
- ced_allowi(ced); /* Make sure char reads are running */
- mutex_unlock(&ced->io_mutex); /* Protect disconnect from new i/o */
-
- return ret;
-}
-
-/*******************************************************************************
-** Get count of characters in the inout buffer.
-*******************************************************************************/
-int ced_stat_1401(struct ced_data *ced)
-{
- int ret;
-
- mutex_lock(&ced->io_mutex); /* Protect disconnect from new i/o */
- ced_allowi(ced); /* make sure we allow pending chars */
- ced_send_chars(ced); /* in both directions */
- ret = ced->num_input; /* no lock as single read */
- mutex_unlock(&ced->io_mutex); /* Protect disconnect from new i/o */
- return ret;
-}
-
-/****************************************************************************
-** ced_line_count
-**
-** Returns the number of newline chars in the buffer. There is no need for
-** any fancy interlocks as we only read the interrupt routine data, and the
-** system is arranged so nothing can be destroyed.
-****************************************************************************/
-int ced_line_count(struct ced_data *ced)
-{
- int ret = 0; /* will be count of line ends */
-
- mutex_lock(&ced->io_mutex); /* Protect disconnect from new i/o */
- ced_allowi(ced); /* Make sure char reads are running */
- ced_send_chars(ced); /* and send any buffered chars */
- spin_lock_irq(&ced->char_in_lock); /* Get protection */
-
- if (ced->num_input > 0) { /* worth looking? */
- /* start at first available */
- unsigned int index = ced->in_buff_get;
- /* Position for search end */
- unsigned int end = ced->in_buff_put;
-
- do {
- if (ced->input_buffer[index++] == CR_CHAR)
- ++ret; /* inc count if CR */
-
- if (index >= INBUF_SZ) /* see if we fall off buff */
- index = 0;
- } while (index != end); /* go to last available */
- }
-
- spin_unlock_irq(&ced->char_in_lock);
- dev_dbg(&ced->interface->dev, "%s: returned %d\n", __func__, ret);
- mutex_unlock(&ced->io_mutex); /* Protect disconnect from new i/o */
- return ret;
-}
-
-/****************************************************************************
-** ced_get_out_buf_space
-**
-** Gets the space in the output buffer. Called from user code.
-*****************************************************************************/
-int ced_get_out_buf_space(struct ced_data *ced)
-{
- int ret;
-
- mutex_lock(&ced->io_mutex); /* Protect disconnect from new i/o */
-
- ced_send_chars(ced); /* send any buffered chars */
-
- /* no lock needed for single read */
- ret = (int)(OUTBUF_SZ - ced->num_output);
-
- dev_dbg(&ced->interface->dev, "%s: %d\n", __func__, ret);
-
- mutex_unlock(&ced->io_mutex); /* Protect disconnect from new i/o */
- return ret;
-}
-
-/****************************************************************************
-**
-** ced_clear_area
-**
-** Clears up a transfer area. This is always called in the context of a user
-** request, never from a call-back.
-****************************************************************************/
-int ced_clear_area(struct ced_data *ced, int area)
-{
- int ret = U14ERR_NOERROR;
-
- if ((area < 0) || (area >= MAX_TRANSAREAS)) {
- ret = U14ERR_BADAREA;
- dev_err(&ced->interface->dev, "%s: Attempt to clear area %d\n",
- __func__, area);
- } else {
- /* to save typing */
- struct transarea *ta = &ced->trans_def[area];
-
- if (!ta->used) /* if not used... */
- ret = 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 **pages = NULL; /*save page address list*/
- int n_pages = 0; /* and number of pages */
- int np;
-
- dev_dbg(&ced->interface->dev, "%s: area %d\n",
- __func__, area);
- spin_lock_irq(&ced->staged_lock);
- if ((ced->staged_id == area)
- && (ced->dma_flag > MODE_CHAR)) {
- /* cannot delete as in use */
- ret = U14ERR_UNLOCKFAIL;
- dev_err(&ced->interface->dev,
- "%s: call on area %d while active\n",
- __func__, area);
- } else {
- pages = ta->pages; /* save page address list */
- n_pages = ta->n_pages; /* and page count */
- if (ta->event_sz)/* if events flagging in use */
- /* release anything that was waiting */
- wake_up_interruptible(&ta->event);
-
- if (ced->xfer_waiting
- && (ced->dma_info.ident == area))
- /* Cannot have pending xfer if */
- /* area cleared */
- ced->xfer_waiting = false;
-
- /* Clean out the struct transarea except for */
- /* the wait queue, which is at the end. This */
- /* sets used to false and event_sz to 0 to */
- /* say area not used and no events. */
- memset(ta, 0,
- sizeof(struct transarea) -
- sizeof(wait_queue_head_t));
- }
- spin_unlock_irq(&ced->staged_lock);
-
- if (pages) { /* 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(&ced->interface->dev,
- "%s: n_pages=%d\n",
- __func__, n_pages);
-
- for (np = 0; np < n_pages; ++np) {
- if (pages[np]) {
- SetPageDirty(pages[np]);
- page_cache_release(pages[np]);
- }
- }
-
- kfree(pages);
- dev_dbg(&ced->interface->dev,
- "%s: kfree(pages) done\n", __func__);
- }
- }
- }
-
- return ret;
-}
-
-/****************************************************************************
-** ced_set_area
-**
-** Sets up a transfer area - the functional part. Called by both
-** ced_set_transfer and ced_set_circular.
-****************************************************************************/
-static int ced_set_area(struct ced_data *ced, int area, char __user *buf,
- unsigned int length, bool circular, bool circ_to_host)
-{
- /* 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 start = ((unsigned long)buf) & PAGE_MASK;
- unsigned int offset = ((unsigned long)buf) & (PAGE_SIZE - 1);
- int len = (length + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
-
- struct transarea *ta = &ced->trans_def[area]; /* to save typing */
- struct page **pages = NULL; /* space for page tables */
- int n_pages = 0; /* and number of pages */
-
- int ret = ced_clear_area(ced, area); /* see if OK to use this area */
-
- if ((ret != U14ERR_NOTSET) && /* if not area unused and... */
- (ret != U14ERR_NOERROR)) /* ...not all OK, then... */
- return ret; /* ...we cannot use this area */
-
- /* if we cannot access the memory... */
- if (!access_ok(VERIFY_WRITE, buf, length))
- return -EFAULT; /* ...then we are done */
-
- /* Now allocate space to hold the page pointer and */
- /* virtual address pointer tables */
- pages = kmalloc(len * sizeof(struct page *), GFP_KERNEL);
- if (!pages) {
- ret = U14ERR_NOMEMORY;
- goto error;
- }
- dev_dbg(&ced->interface->dev, "%s: %p, length=%06x, circular %d\n",
- __func__, buf, length, circular);
-
- /* To pin down user pages we must first */
- /* acquire the mapping semaphore. */
- n_pages = get_user_pages_fast(start, len, 1, pages);
- dev_dbg(&ced->interface->dev, "%s: n_pages = %d\n", __func__, n_pages);
-
- if (n_pages > 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(&ced->staged_lock);
- ta->buff = buf; /* keep start of region (user address) */
- ta->base_offset = offset; /* save offset in first page */
- /* to start of xfer */
- ta->length = length; /* Size if the region in bytes */
- ta->pages = pages; /* list of pages that are used by buffer */
- ta->n_pages = n_pages; /* number of pages */
-
- ta->circular = circular;
- ta->circ_to_host = circ_to_host;
-
- ta->blocks[0].offset = 0;
- ta->blocks[0].size = 0;
- ta->blocks[1].offset = 0;
- ta->blocks[1].size = 0;
- ta->used = true; /* This is now a used block */
-
- spin_unlock_irq(&ced->staged_lock);
- ret = U14ERR_NOERROR; /* say all was well */
- } else {
- ret = U14ERR_LOCKFAIL;
- goto error;
- }
-
- return ret;
-
-error:
- kfree(pages);
- return ret;
-}
-
-/****************************************************************************
-** ced_set_transfer
-**
-** Sets up a transfer area record. If the area is already set, we attempt to
-** 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 ced_set_transfer(struct ced_data *ced,
- struct transfer_area_desc __user *utd)
-{
- int ret;
- struct transfer_area_desc td;
-
- if (copy_from_user(&td, utd, sizeof(td)))
- return -EFAULT;
-
- mutex_lock(&ced->io_mutex);
- dev_dbg(&ced->interface->dev, "%s: area:%d, size:%08x\n",
- __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. */
- ret =
- ced_set_area(ced, td.wAreaNum,
- (char __user *)((unsigned long)td.lpvBuff), td.dwLength,
- false, false);
- mutex_unlock(&ced->io_mutex);
- return ret;
-}
-
-/****************************************************************************
-** ced_unset_transfer
-** Erases a transfer area record
-****************************************************************************/
-int ced_unset_transfer(struct ced_data *ced, int area)
-{
- int ret;
-
- mutex_lock(&ced->io_mutex);
- ret = ced_clear_area(ced, area);
- mutex_unlock(&ced->io_mutex);
- return ret;
-}
-
-/****************************************************************************
-** ced_set_event
-** Creates an event that we can test for based on a transfer to/from an area.
-** The area must be setup for a transfer. We attempt to simulate the Windows
-** driver behavior for events (as we don't actually use them), which is to
-** 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 ced_set_event(struct ced_data *ced, struct transfer_event __user *ute)
-{
- int ret = U14ERR_NOERROR;
- struct transfer_event te;
- struct transarea *ta;
-
- /* get a local copy of the data */
- if (copy_from_user(&te, ute, sizeof(te)))
- return -EFAULT;
-
- if (te.wAreaNum >= MAX_TRANSAREAS) /* the area must exist */
- return U14ERR_BADAREA;
-
- ta = &ced->trans_def[te.wAreaNum];
-
- /* make sure we have no competitor */
- mutex_lock(&ced->io_mutex);
- spin_lock_irq(&ced->staged_lock);
-
- if (ta->used) { /* area must be in use */
- ta->event_st = te.dwStart; /* set area regions */
-
- /* set size (0 cancels it) */
- ta->event_sz = te.dwLength;
-
- /* set the direction */
- ta->event_to_host = te.wFlags & 1;
- ta->wake_up = 0; /* zero the wake up count */
- } else
- ret = U14ERR_NOTSET;
-
- spin_unlock_irq(&ced->staged_lock);
- mutex_unlock(&ced->io_mutex);
-
- return ret ==
- U14ERR_NOERROR ? (te.iSetEvent ? 1 : U14ERR_NOERROR) : ret;
-}
-
-/****************************************************************************
-** ced_wait_event
-** Sleep the process with a timeout waiting for an event. Returns the number
-** 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 ced_wait_event(struct ced_data *ced, int area, int time_out)
-{
- int ret;
- int wait;
- struct transarea *ta;
-
- if ((unsigned)area >= MAX_TRANSAREAS)
- return U14ERR_BADAREA;
-
- ta = &ced->trans_def[area];
-
- /* convert timeout to jiffies */
- time_out = (time_out * HZ + 999) / 1000;
-
- /* 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 wake_up flag. */
- /* However, the !ta->used may help us in this case. */
-
- /* make sure we have no competitor */
- mutex_lock(&ced->io_mutex);
- if (!ta->used || !ta->event_sz) /* check something to */
- /* wait for... */
- return U14ERR_NOTSET; /* ...else we do nothing */
- mutex_unlock(&ced->io_mutex);
-
- if (time_out)
- wait = wait_event_interruptible_timeout(ta->event,
- ta->wake_up ||
- !ta->used,
- time_out);
- else
- wait = wait_event_interruptible(ta->event,
- ta->wake_up ||
- !ta->used);
-
- if (wait)
- ret = -ERESTARTSYS; /* oops - we have had a SIGNAL */
- else
- ret = ta->wake_up; /* else the wakeup count */
-
- spin_lock_irq(&ced->staged_lock);
- ta->wake_up = 0; /* clear the flag */
- spin_unlock_irq(&ced->staged_lock);
-
- return ret;
-}
-
-/****************************************************************************
-** ced_test_event
-** Test the event to see if a ced_wait_event would return immediately. Returns
-** the number of times a block completed since the last call, or 0 if none or a
-** negative error.
-****************************************************************************/
-int ced_test_event(struct ced_data *ced, int area)
-{
- int ret;
-
- if ((unsigned)area >= MAX_TRANSAREAS)
- ret = U14ERR_BADAREA;
- else {
- struct transarea *ta = &ced->trans_def[area];
-
- /* make sure we have no competitor */
- mutex_lock(&ced->io_mutex);
- spin_lock_irq(&ced->staged_lock);
- ret = ta->wake_up; /* get wakeup count since last call */
- ta->wake_up = 0; /* clear the count */
- spin_unlock_irq(&ced->staged_lock);
- mutex_unlock(&ced->io_mutex);
- }
- return ret;
-}
-
-/****************************************************************************
-** ced_get_transferInfo
-** Puts the current state of the 1401 in a TGET_TX_BLOCK.
-*****************************************************************************/
-int ced_get_transfer(struct ced_data *ced, TGET_TX_BLOCK __user *utx)
-{
- int ret = U14ERR_NOERROR;
- unsigned int dwIdent;
-
- mutex_lock(&ced->io_mutex);
- dwIdent = ced->staged_id; /* area ident for last xfer */
- if (dwIdent >= MAX_TRANSAREAS)
- ret = U14ERR_BADAREA;
- else {
- /* Return the best information we have - we */
- /* don't have physical addresses */
- TGET_TX_BLOCK *tx;
-
- tx = kzalloc(sizeof(*tx), GFP_KERNEL);
- if (!tx) {
- mutex_unlock(&ced->io_mutex);
- return -ENOMEM;
- }
- tx->size = ced->trans_def[dwIdent].length;
- tx->linear = (long long)((long)ced->trans_def[dwIdent].buff);
- /* how many blocks we could return */
- tx->avail = GET_TX_MAXENTRIES;
- tx->used = 1; /* number we actually return */
- tx->entries[0].physical =
- (long long)(tx->linear + ced->staged_offset);
- tx->entries[0].size = tx->size;
-
- if (copy_to_user(utx, tx, sizeof(*tx)))
- ret = -EFAULT;
- kfree(tx);
- }
- mutex_unlock(&ced->io_mutex);
- return ret;
-}
-
-/****************************************************************************
-** ced_kill_io
-**
-** Empties the host i/o buffers
-****************************************************************************/
-int ced_kill_io(struct ced_data *ced)
-{
- dev_dbg(&ced->interface->dev, "%s\n", __func__);
- mutex_lock(&ced->io_mutex);
- ced_flush_out_buff(ced);
- ced_flush_in_buff(ced);
- mutex_unlock(&ced->io_mutex);
- return U14ERR_NOERROR;
-}
-
-/****************************************************************************
-** ced_state_of_1401
-**
-** Puts the current state of the 1401 in the Irp return buffer.
-*****************************************************************************/
-int ced_state_of_1401(struct ced_data *ced)
-{
- int ret;
-
- mutex_lock(&ced->io_mutex);
-
- ced_quick_check(ced, false, false); /* get state up to date, no reset */
- ret = ced->current_state;
-
- mutex_unlock(&ced->io_mutex);
- dev_dbg(&ced->interface->dev, "%s: %d\n", __func__, ret);
-
- return ret;
-}
-
-/****************************************************************************
-** ced_start_self_test
-**
-** 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 ced_start_self_test(struct ced_data *ced)
-{
- int got;
-
- mutex_lock(&ced->io_mutex);
- dev_dbg(&ced->interface->dev, "%s\n", __func__);
-
- ced_draw_down(ced); /* wait for, then kill outstanding Urbs */
- ced_flush_in_buff(ced); /* Clear out input buffer & pipe */
- ced_flush_out_buff(ced); /* Clear output buffer & pipe */
- /* so things stay tidy */
- /* ced_read_write_cancel(pDeviceObject); */
- ced->dma_flag = MODE_CHAR; /* Clear DMA mode flags here */
-
- got = usb_control_msg(ced->udev, usb_rcvctrlpipe(ced->udev, 0),
- DB_SELFTEST, (H_TO_D | VENDOR | DEVREQ),
- 0, 0, NULL, 0, HZ); /* allow 1 second timeout */
- ced->self_test_time = jiffies + HZ * 30; /* 30 seconds into the */
- /* future */
-
- mutex_unlock(&ced->io_mutex);
- if (got < 0)
- dev_err(&ced->interface->dev, "%s: err=%d\n", __func__, got);
- return got < 0 ? U14ERR_FAIL : U14ERR_NOERROR;
-}
-
-/****************************************************************************
-** ced_check_self_test
-**
-** Check progress of a self-test cycle
-****************************************************************************/
-int ced_check_self_test(struct ced_data *ced, TGET_SELFTEST __user *ugst)
-{
- unsigned int state, error;
- int ret;
- TGET_SELFTEST gst; /* local work space */
-
- memset(&gst, 0, sizeof(gst)); /* clear out the space (sets code 0) */
-
- mutex_lock(&ced->io_mutex);
-
- dev_dbg(&ced->interface->dev, "%s\n", __func__);
- ret = ced_get_state(ced, &state, &error);
- if (ret == U14ERR_NOERROR) /* Only accept zero if it happens twice */
- ret = ced_get_state(ced, &state, &error);
-
- if (ret != U14ERR_NOERROR) { /* Self-test can cause comms errors */
- /* so we assume still testing */
- dev_err(&ced->interface->dev,
- "%s: ced_get_state=%d, assuming still testing\n",
- __func__, ret);
- state = 0x80; /* Force still-testing, no error */
- error = 0;
- ret = U14ERR_NOERROR;
- }
-
- if ((state == -1) && (error == -1)) {/* If ced_get_state had problems */
- dev_err(&ced->interface->dev,
- "%s: ced_get_state failed, assuming still testing\n",
- __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? */
- /* read the error code */
- gst.code = (state & 0x00FF0000) >> 16;
- gst.x = error & 0x0000FFFF; /* Error data X */
- gst.y = (error & 0xFFFF0000) >> 16; /* and data Y */
- dev_dbg(&ced->interface->dev,
- "Self-test error code %d\n", gst.code);
- } else { /* No error, check for timeout */
- unsigned long now = jiffies; /* get current time */
-
- if (time_after(now, ced->self_test_time)) {
- gst.code = -2; /* Flag the timeout */
- dev_dbg(&ced->interface->dev,
- "Self-test timed-out\n");
- } else
- dev_dbg(&ced->interface->dev,
- "Self-test on-going\n");
- }
- } else {
- gst.code = -1; /* Flag the test is done */
- dev_dbg(&ced->interface->dev, "Self-test done\n");
- }
-
- if (gst.code < 0) { /* If we have a problem or finished */
- /* If using the 2890 we should reset properly */
- if ((ced->n_pipes == 4) && (ced->type <= TYPEPOWER))
- ced_is_1401(ced); /* Get 1401 reset and OK */
- else
- /* Otherwise check without reset unless problems */
- ced_quick_check(ced, true, true);
- }
- mutex_unlock(&ced->io_mutex);
-
- if (copy_to_user(ugst, &gst, sizeof(gst)))
- return -EFAULT;
-
- return ret;
-}
-
-/****************************************************************************
-** ced_type_of_1401
-**
-** Returns code for standard, plus, micro1401, power1401 or none
-****************************************************************************/
-int ced_type_of_1401(struct ced_data *ced)
-{
- int ret = TYPEUNKNOWN;
-
- mutex_lock(&ced->io_mutex);
- dev_dbg(&ced->interface->dev, "%s\n", __func__);
-
- switch (ced->type) {
- case TYPE1401:
- ret = U14ERR_STD;
- break; /* Handle these types directly */
- case TYPEPLUS:
- ret = U14ERR_PLUS;
- break;
- case TYPEU1401:
- ret = U14ERR_U1401;
- break;
- default:
- if ((ced->type >= TYPEPOWER) && (ced->type <= 25))
- ret = ced->type + 4; /* We can calculate types */
- else /* for up-coming 1401 designs */
- ret = TYPEUNKNOWN; /* Don't know or not there */
- }
- dev_dbg(&ced->interface->dev, "%s %d\n", __func__, ret);
- mutex_unlock(&ced->io_mutex);
-
- return ret;
-}
-
-/****************************************************************************
-** ced_transfer_flags
-**
-** Returns flags on block transfer abilities
-****************************************************************************/
-int ced_transfer_flags(struct ced_data *ced)
-{
- /* we always have multiple DMA area diagnostics, notify and circular */
- int ret = U14TF_MULTIA | U14TF_DIAG |
- U14TF_NOTIFY | U14TF_CIRCTH;
-
- dev_dbg(&ced->interface->dev, "%s\n", __func__);
- mutex_lock(&ced->io_mutex);
- if (ced->is_usb2) /* Set flag for USB2 if appropriate */
- ret |= U14TF_USB2;
- mutex_unlock(&ced->io_mutex);
-
- return ret;
-}
-
-/***************************************************************************
-** ced_dbg_cmd
-** 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 ced_dbg_cmd(struct ced_data *ced, unsigned char cmd,
- unsigned int data)
-{
- int ret;
-
- dev_dbg(&ced->interface->dev, "%s: entry\n", __func__);
- ret = usb_control_msg(ced->udev, usb_sndctrlpipe(ced->udev, 0), cmd,
- (H_TO_D | VENDOR | DEVREQ),
- (unsigned short)data,
- (unsigned short)(data >> 16), NULL, 0, HZ);
- /* allow 1 second timeout */
- if (ret < 0)
- dev_err(&ced->interface->dev, "%s: fail code=%d\n",
- __func__, ret);
-
- return ret;
-}
-
-/****************************************************************************
-** ced_dbg_peek
-**
-** Execute the diagnostic peek operation. Uses address, width and repeats.
-****************************************************************************/
-int ced_dbg_peek(struct ced_data *ced, TDBGBLOCK __user *udb)
-{
- int ret;
- TDBGBLOCK db;
-
- if (copy_from_user(&db, udb, sizeof(db)))
- return -EFAULT;
-
- mutex_lock(&ced->io_mutex);
- dev_dbg(&ced->interface->dev, "%s: @ %08x\n", __func__, db.iAddr);
-
- ret = ced_dbg_cmd(ced, DB_SETADD, db.iAddr);
- if (ret == U14ERR_NOERROR)
- ret = ced_dbg_cmd(ced, DB_WIDTH, db.iWidth);
- if (ret == U14ERR_NOERROR)
- ret = ced_dbg_cmd(ced, DB_REPEATS, db.iRepeats);
- if (ret == U14ERR_NOERROR)
- ret = ced_dbg_cmd(ced, DB_PEEK, 0);
- mutex_unlock(&ced->io_mutex);
-
- return ret;
-}
-
-/****************************************************************************
-** ced_dbg_poke
-**
-** Execute the diagnostic poke operation. Parameters are in the CSBLOCK struct
-** in order address, size, repeats and value to poke.
-****************************************************************************/
-int ced_dbg_poke(struct ced_data *ced, TDBGBLOCK __user *udb)
-{
- int ret;
- TDBGBLOCK db;
-
- if (copy_from_user(&db, udb, sizeof(db)))
- return -EFAULT;
-
- mutex_lock(&ced->io_mutex);
- dev_dbg(&ced->interface->dev, "%s: @ %08x\n", __func__, db.iAddr);
-
- ret = ced_dbg_cmd(ced, DB_SETADD, db.iAddr);
- if (ret == U14ERR_NOERROR)
- ret = ced_dbg_cmd(ced, DB_WIDTH, db.iWidth);
- if (ret == U14ERR_NOERROR)
- ret = ced_dbg_cmd(ced, DB_REPEATS, db.iRepeats);
- if (ret == U14ERR_NOERROR)
- ret = ced_dbg_cmd(ced, DB_POKE, db.iData);
- mutex_unlock(&ced->io_mutex);
-
- return ret;
-}
-
-/****************************************************************************
-** ced_dbg_ramp_data
-**
-** Execute the diagnostic ramp data operation. Parameters are in the CSBLOCK
-** struct in order address, default, enable mask, size and repeats.
-****************************************************************************/
-int ced_dbg_ramp_data(struct ced_data *ced, TDBGBLOCK __user *udb)
-{
- int ret;
- TDBGBLOCK db;
-
- if (copy_from_user(&db, udb, sizeof(db)))
- return -EFAULT;
-
- mutex_lock(&ced->io_mutex);
- dev_dbg(&ced->interface->dev, "%s: @ %08x\n", __func__, db.iAddr);
-
- ret = ced_dbg_cmd(ced, DB_SETADD, db.iAddr);
- if (ret == U14ERR_NOERROR)
- ret = ced_dbg_cmd(ced, DB_SETDEF, db.iDefault);
- if (ret == U14ERR_NOERROR)
- ret = ced_dbg_cmd(ced, DB_SETMASK, db.iMask);
- if (ret == U14ERR_NOERROR)
- ret = ced_dbg_cmd(ced, DB_WIDTH, db.iWidth);
- if (ret == U14ERR_NOERROR)
- ret = ced_dbg_cmd(ced, DB_REPEATS, db.iRepeats);
- if (ret == U14ERR_NOERROR)
- ret = ced_dbg_cmd(ced, DB_RAMPD, 0);
- mutex_unlock(&ced->io_mutex);
-
- return ret;
-}
-
-/****************************************************************************
-** ced_dbg_ramp_addr
-**
-** Execute the diagnostic ramp address operation
-****************************************************************************/
-int ced_dbg_ramp_addr(struct ced_data *ced, TDBGBLOCK __user *udb)
-{
- int ret;
- TDBGBLOCK db;
-
- if (copy_from_user(&db, udb, sizeof(db)))
- return -EFAULT;
-
- mutex_lock(&ced->io_mutex);
- dev_dbg(&ced->interface->dev, "%s\n", __func__);
-
- ret = ced_dbg_cmd(ced, DB_SETDEF, db.iDefault);
- if (ret == U14ERR_NOERROR)
- ret = ced_dbg_cmd(ced, DB_SETMASK, db.iMask);
- if (ret == U14ERR_NOERROR)
- ret = ced_dbg_cmd(ced, DB_WIDTH, db.iWidth);
- if (ret == U14ERR_NOERROR)
- ret = ced_dbg_cmd(ced, DB_REPEATS, db.iRepeats);
- if (ret == U14ERR_NOERROR)
- ret = ced_dbg_cmd(ced, DB_RAMPA, 0);
- mutex_unlock(&ced->io_mutex);
-
- return ret;
-}
-
-/****************************************************************************
-** ced_dbg_get_data
-**
-** Retrieve the data resulting from the last debug Peek operation
-****************************************************************************/
-int ced_dbg_get_data(struct ced_data *ced, TDBGBLOCK __user *udb)
-{
- int ret;
- TDBGBLOCK db;
-
- memset(&db, 0, sizeof(db)); /* fill returned block with 0s */
-
- mutex_lock(&ced->io_mutex);
- dev_dbg(&ced->interface->dev, "%s\n", __func__);
-
- /* Read back the last peeked value from the 1401. */
- ret = usb_control_msg(ced->udev, usb_rcvctrlpipe(ced->udev, 0),
- DB_DATA, (D_TO_H | VENDOR | DEVREQ), 0, 0,
- &db.iData, sizeof(db.iData), HZ);
- if (ret == sizeof(db.iData)) {
- if (copy_to_user(udb, &db, sizeof(db)))
- ret = -EFAULT;
- else
- ret = U14ERR_NOERROR;
- } else
- dev_err(&ced->interface->dev, "%s: failed, code %d\n",
- __func__, ret);
-
- mutex_unlock(&ced->io_mutex);
-
- return ret;
-}
-
-/****************************************************************************
-** ced_dbg_stop_loop
-**
-** Stop any never-ending debug loop, we just call ced_get_state for USB
-**
-****************************************************************************/
-int ced_dbg_stop_loop(struct ced_data *ced)
-{
- int ret;
- unsigned int uState, uErr;
-
- mutex_lock(&ced->io_mutex);
- dev_dbg(&ced->interface->dev, "%s\n", __func__);
- ret = ced_get_state(ced, &uState, &uErr);
- mutex_unlock(&ced->io_mutex);
-
- return ret;
-}
-
-/****************************************************************************
-** ced_set_circular
-**
-** Sets up a transfer area record for circular transfers. If the area is
-** already set, we attempt to 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 ced_set_circular(struct ced_data *ced,
- struct transfer_area_desc __user *utd)
-{
- int ret;
- bool to_host;
- struct transfer_area_desc td;
-
- if (copy_from_user(&td, utd, sizeof(td)))
- return -EFAULT;
-
- mutex_lock(&ced->io_mutex);
- dev_dbg(&ced->interface->dev, "%s: area:%d, size:%08x\n",
- __func__, td.wAreaNum, td.dwLength);
- to_host = 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. */
- ret =
- ced_set_area(ced, td.wAreaNum,
- (char __user *)((unsigned long)td.lpvBuff), td.dwLength,
- true, to_host);
- mutex_unlock(&ced->io_mutex);
- return ret;
-}
-
-/****************************************************************************
-** ced_get_circ_block
-**
-** Return the next available block of circularly-transferred data.
-****************************************************************************/
-int ced_get_circ_block(struct ced_data *ced, TCIRCBLOCK __user *ucb)
-{
- int ret = U14ERR_NOERROR;
- unsigned int area;
- TCIRCBLOCK cb;
-
- dev_dbg(&ced->interface->dev, "%s\n", __func__);
-
- if (copy_from_user(&cb, ucb, sizeof(cb)))
- return -EFAULT;
-
- mutex_lock(&ced->io_mutex);
-
- area = cb.nArea; /* Retrieve parameters first */
- cb.dwOffset = 0; /* set default result (nothing) */
- cb.dwSize = 0;
-
- if (area < MAX_TRANSAREAS) { /* The area number must be OK */
- /* Pointer to relevant info */
- struct transarea *ta = &ced->trans_def[area];
-
- spin_lock_irq(&ced->staged_lock); /* Lock others out */
-
- if ((ta->used) && (ta->circular) && /* Must be circular area */
- (ta->circ_to_host)) { /* For now at least must be to host */
- if (ta->blocks[0].size > 0) { /* Got anything? */
- cb.dwOffset = ta->blocks[0].offset;
- cb.dwSize = ta->blocks[0].size;
- dev_dbg(&ced->interface->dev,
- "%s: return block 0: %d bytes at %d\n",
- __func__, cb.dwSize, cb.dwOffset);
- }
- } else
- ret = U14ERR_NOTSET;
-
- spin_unlock_irq(&ced->staged_lock);
- } else
- ret = U14ERR_BADAREA;
-
- if (copy_to_user(ucb, &cb, sizeof(cb)))
- ret = -EFAULT;
-
- mutex_unlock(&ced->io_mutex);
- return ret;
-}
-
-/****************************************************************************
-** ced_free_circ_block
-**
-** Frees a block of circularly-transferred data and returns the next one.
-****************************************************************************/
-int ced_free_circ_block(struct ced_data *ced, TCIRCBLOCK __user *ucb)
-{
- int ret = U14ERR_NOERROR;
- unsigned int area, start, size;
- TCIRCBLOCK cb;
-
- dev_dbg(&ced->interface->dev, "%s\n", __func__);
-
- if (copy_from_user(&cb, ucb, sizeof(cb)))
- return -EFAULT;
-
- mutex_lock(&ced->io_mutex);
-
- area = cb.nArea; /* Retrieve parameters first */
- start = cb.dwOffset;
- size = cb.dwSize;
- cb.dwOffset = 0; /* then set default result (nothing) */
- cb.dwSize = 0;
-
- if (area < MAX_TRANSAREAS) { /* The area number must be OK */
- /* Pointer to relevant info */
- struct transarea *ta = &ced->trans_def[area];
-
- spin_lock_irq(&ced->staged_lock); /* Lock others out */
-
- if ((ta->used) && (ta->circular) && /* Must be circular area */
- (ta->circ_to_host)) { /* For now at least must be to host */
- bool waiting = false;
-
- if ((ta->blocks[0].size >= size) && /* Got anything? */
- /* Must be legal data */
- (ta->blocks[0].offset == start)) {
- ta->blocks[0].size -= size;
- ta->blocks[0].offset += size;
-
- /* Have we emptied this block? */
- if (ta->blocks[0].size == 0) {
- /* Is there a second block? */
- if (ta->blocks[1].size) {
- /* Copy down block 2 data */
- ta->blocks[0] = ta->blocks[1];
- /* and mark the second */
- /* block as unused */
- ta->blocks[1].size = 0;
- ta->blocks[1].offset = 0;
- } else
- ta->blocks[0].offset = 0;
- }
-
- dev_dbg(&ced->interface->dev,
- "%s: free %d bytes at %d, "
- "return %d bytes at %d, wait=%d\n",
- __func__, size, start,
- ta->blocks[0].size,
- ta->blocks[0].offset,
- ced->xfer_waiting);
-
- /* Return the next available block of */
- /* memory as well */
- if (ta->blocks[0].size > 0) {/* Got anything? */
- cb.dwOffset =
- ta->blocks[0].offset;
- cb.dwSize = ta->blocks[0].size;
- }
-
- waiting = ced->xfer_waiting;
- if (waiting && ced->staged_urb_pending) {
- dev_err(&ced->interface->dev,
- "%s: ERROR: waiting xfer and "
- "staged Urb pending!\n",
- __func__);
- waiting = false;
- }
- } else {
- dev_err(&ced->interface->dev,
- "%s: ERROR: freeing %d bytes at %d, "
- "block 0 is %d bytes at %d\n",
- __func__, size, start,
- ta->blocks[0].size,
- ta->blocks[0].offset);
- ret = U14ERR_NOMEMORY;
- }
-
- /* If we have one, kick off pending transfer */
- if (waiting) { /* Got a block xfer waiting? */
- int RWMStat =
- ced_read_write_mem(ced,
- !ced->dma_info.outward,
- ced->dma_info.ident,
- ced->dma_info.offset,
- ced->dma_info.size);
- if (RWMStat != U14ERR_NOERROR)
- dev_err(&ced->interface->dev,
- "%s: rw setup failed %d\n",
- __func__, RWMStat);
- }
- } else
- ret = U14ERR_NOTSET;
-
- spin_unlock_irq(&ced->staged_lock);
- } else
- ret = U14ERR_BADAREA;
-
- if (copy_to_user(ucb, &cb, sizeof(cb)))
- ret = -EFAULT;
-
- mutex_unlock(&ced->io_mutex);
- return ret;
-}
+++ /dev/null
-/*
- * 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 <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
-*****************************************************************************/
-
-struct transfer_area_desc {
- long long lpvBuff; /* address of transfer area (for 64 or 32 bit) */
- unsigned int dwLength; /* length of the area */
- unsigned short wAreaNum; /* number of transfer area to set up */
- short eSize; /* element size - is tohost flag for circular */
-};
-
-
-struct transfer_event {
- 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 */
-};
-
-#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 */
-} 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 */
-} 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 */
-} TCIRCBLOCK;
-
-/* 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:
- */
-#define CED_MAGIC_IOC 0xce
-
-#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, struct transfer_area_desc)
-#define IOCTL_CED_UNSETTRANSFER _IO(CED_MAGIC_IOC, 12)
-#define IOCTL_CED_SETEVENT _IOW(CED_MAGIC_IOC, 13, struct transfer_event)
-#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, struct transfer_area_desc)
-#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);
-}
-
-inline int CED_Reset1401(int fh)
-{
- return ioctl(fh, IOCTL_CED_RESET1401);
-}
-
-/* Return the singe character or a -ve error code. */
-inline int CED_GetChar(int fh)
-{
- return ioctl(fh, IOCTL_CED_GETCHAR);
-}
-
-/* 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_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);
-}
-
-/* returns space in the output buffer. */
-inline int CED_GetOutBufSpace(int fh)
-{
- return ioctl(fh, IOCTL_CED_GETOUTBUFSPACE);
-}
-
-/* This always returns -1 as not implemented. */
-inline int CED_GetBaseAddress(int fh)
-{
- return ioctl(fh, IOCTL_CED_GETBASEADDRESS);
-}
-
-/* returns the major revision <<16 | minor revision. */
-inline int CED_GetDriverRevision(int fh)
-{
- return ioctl(fh, IOCTL_CED_GETDRIVERREVISION);
-}
-
-inline int CED_SetTransfer(int fh, struct transfer_area_desc *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_SetEvent(int fh, struct transfer_event *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_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_StateOf1401(int fh)
-{
- return ioctl(fh, IOCTL_CED_STATEOF1401);
-}
-
-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_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_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_FullReset(int fh)
-{
- return ioctl(fh, IOCTL_CED_FULLRESET);
-}
-
-inline int CED_SetCircular(int fh, struct transfer_area_desc *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_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 */
-
-#endif
-
-/* __CED_IOCTL_H__ */
-#endif
+++ /dev/null
-/*****************************************************************************
-**
-** machine.h
-**
-** Copyright (c) Cambridge Electronic Design Limited 1991,1992,2010
-**
-** 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.
-**
-** Contact CED: Cambridge Electronic Design Limited, Science Park, Milton Road
-** Cambridge, CB6 0FE.
-** www.ced.co.uk
-** greg@ced.co.uk
-**
-** This file is included at the start of 'C' or 'C++' source file to define
-** things for cross-platform/compiler interoperability. This used to deal with
-** MSDOS/16-bit stuff, but this was all removed in Decemeber 2010. There are
-** three things to consider: Windows, LINUX, mac OSX (BSD Unix) and 32 vs 64
-** bit. At the time of writing (DEC 2010) there is a consensus on the following
-** and their unsigned equivalents:
-**
-** type bits
-** char 8
-** short 16
-** int 32
-** long long 64
-**
-** long is a problem as it is always 64 bits on linux/unix and is always 32 bits
-** on windows.
-** On windows, we define _IS_WINDOWS_ and one of WIN32 or WIN64.
-** On linux we define LINUX
-** On Max OSX we define MACOSX
-**
-*/
-
-#ifndef __MACHINE_H__
-#define __MACHINE_H__
-#ifndef __KERNEL__
-#include <float.h>
-#include <limits.h>
-#endif
-
-/*
-** The initial section is to identify the operating system
-*/
-#if (defined(__linux__) || defined(_linux) || defined(__linux)) && !defined(LINUX)
-#define LINUX 1
-#endif
-
-#if (defined(__WIN32__) || defined(_WIN32)) && !defined(WIN32)
-#define WIN32 1
-#endif
-
-#if defined(__APPLE__)
-#define MACOSX
-#endif
-
-#if defined(_WIN64)
-#undef WIN32
-#undef WIN64
-#define WIN64 1
-#endif
-
-#if defined(WIN32) || defined(WIN64)
-#define _IS_WINDOWS_ 1
-#endif
-
-#if defined(LINUX) || defined(MAXOSX)
- #define FAR
-
- typedef int BOOL; /* To match Windows */
- typedef unsigned char BYTE;
- #define __packed __attribute__((packed))
- #define HIWORD(x) (unsigned short)(((x)>>16) & 0xffff)
- #define LOWORD(x) (unsigned short)((x) & 0xffff)
-#endif
-
-#ifdef _IS_WINDOWS_
-#include <windows.h>
-#define __packed
-#endif
-
-/*
-** Sort out the DllExport and DllImport macros. The GCC compiler has its own
-** syntax for this, though it also supports the MS specific __declspec() as
-** a synonym.
-*/
-#ifdef GNUC
- #define DllExport __attribute__((dllexport))
- #define DllImport __attribute__((dllimport))
-#endif
-
-#ifndef DllExport
-#ifdef _IS_WINDOWS_
- #define DllExport __declspec(dllexport)
- #define DllImport __declspec(dllimport)
-#else
- #define DllExport
- #define DllImport
-#endif
-#endif /* _IS_WINDOWS_ */
-
-#ifndef TRUE
- #define TRUE 1
- #define FALSE 0
-#endif
-
-#endif
+++ /dev/null
-/*******************************************************************************
- CED1401 usb driver. This basic loading is based on the usb-skeleton.c code that
- is:
- Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
- Copyright (C) 2012 Alois Schloegl <alois.schloegl@ist.ac.at>
- There is not a great deal of the skeleton left.
-
- All the remainder dealing specifically with the CED1401 is based on drivers
- written by CED for other systems (mainly Windows) and is:
- 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.
-
-Endpoints
-*********
-There are 4 endpoints plus the control endpoint in the standard interface
-provided by most 1401s. The control endpoint is used for standard USB requests,
-plus various CED-specific transactions such as start self test, debug and get
-the 1401 status. The other endpoints are:
-
- 1 Characters to the 1401
- 2 Characters from the 1401
- 3 Block data to the 1401
- 4 Block data to the host.
-
-inside the driver these are indexed as an array from 0 to 3, transactions
-over the control endpoint are carried out using a separate mechanism. The
-use of the endpoints is mostly straightforward, with the driver issuing
-IO request packets (IRPs) as required to transfer data to and from the 1401.
-The handling of endpoint 2 is different because it is used for characters
-from the 1401, which can appear spontaneously and without any other driver
-activity - for example to repeatedly request DMA transfers in Spike2. The
-desired effect is achieved by using an interrupt endpoint which can be
-polled to see if it has data available, and writing the driver so that it
-always maintains a pending read IRP from that endpoint which will read the
-character data and terminate as soon as the 1401 makes data available. This
-works very well, some care is taken with when you kick off this character
-read IRP to avoid it being active when it is not wanted but generally it
-is running all the time.
-
-In the 2270, there are only three endpoints plus the control endpoint. In
-addition to the transactions mentioned above, the control endpoint is used
-to transfer character data to the 1401. The other endpoints are used as:
-
- 1 Characters from the 1401
- 2 Block data to the 1401
- 3 Block data to the host.
-
-The type of interface available is specified by the interface subclass field
-in the interface descriptor provided by the 1401. See the USB_INT_ constants
-for the values that this field can hold.
-
-****************************************************************************
-Linux implementation
-
-Although Linux Device Drivers (3rd Edition) was a major source of information,
-it is very out of date. A lot of information was gleaned from the latest
-usb_skeleton.c code (you need to download the kernel sources to get this).
-
-To match the Windows version, everything is done using ioctl calls. All the
-device state is held in the struct ced_data.
-Block transfers are done by using get_user_pages() to pin down a list of
-pages that we hold a pointer to in the device driver. We also allocate a
-coherent transfer buffer of size STAGED_SZ (this must be a multiple of the
-bulk endpoint size so that the 1401 does not realise that we break large
-transfers down into smaller pieces). We use kmap_atomic() to get a kernel
-va for each page, as it is required, for copying; see ced_copy_user_space().
-
-All character and data transfers are done using asynchronous IO. All Urbs are
-tracked by anchoring them. Status and debug ioctls are implemented with the
-synchronous non-Urb based transfers.
-*/
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/usb.h>
-#include <linux/mutex.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/kref.h>
-#include <linux/uaccess.h>
-
-#include "usb1401.h"
-
-/* Define these values to match your devices */
-#define USB_CED_VENDOR_ID 0x0525
-#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 */
-};
-
-MODULE_DEVICE_TABLE(usb, ced_table);
-
-/* Get a minor range for your devices from the usb maintainer */
-#define USB_CED_MINOR_BASE 192
-
-/* our private defines. if this grows any larger, use your own .h file */
-#define MAX_TRANSFER (PAGE_SIZE - 512)
-/* MAX_TRANSFER is chosen so that the VM is not stressed by
- allocations > PAGE_SIZE and the number of packets in a page
- is an integer 512 is the largest possible packet on EHCI */
-#define WRITES_IN_FLIGHT 8
-/* arbitrarily chosen */
-
-static struct usb_driver ced_driver;
-
-static void ced_delete(struct kref *kref)
-{
- struct ced_data *ced = to_ced_data(kref);
-
- /* Free up the output buffer, then free the output urb. Note that the */
- /* interface member of ced will probably be NULL, so cannot be used */
- /* to get to dev. */
- usb_free_coherent(ced->udev, OUTBUF_SZ, ced->coher_char_out,
- ced->urb_char_out->transfer_dma);
- usb_free_urb(ced->urb_char_out);
-
- /* Do the same for chan input */
- usb_free_coherent(ced->udev, INBUF_SZ, ced->coher_char_in,
- ced->urb_char_in->transfer_dma);
- usb_free_urb(ced->urb_char_in);
-
- /* Do the same for the block transfers */
- usb_free_coherent(ced->udev, STAGED_SZ, ced->coher_staged_io,
- ced->staged_urb->transfer_dma);
- usb_free_urb(ced->staged_urb);
-
- usb_put_dev(ced->udev);
- kfree(ced);
-}
-
-/* This is the driver end of the open() call from user space. */
-static int ced_open(struct inode *inode, struct file *file)
-{
- struct ced_data *ced;
- 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;
- }
-
- ced = usb_get_intfdata(interface);
- if (!ced) {
- retval = -ENODEV;
- goto exit;
- }
-
- dev_dbg(&interface->dev, "%s: got ced\n", __func__);
-
- /* increment our usage count for the device */
- kref_get(&ced->kref);
-
- /* lock the device to allow correctly handling errors
- * in resumption */
- mutex_lock(&ced->io_mutex);
-
- if (!ced->open_count++) {
- retval = usb_autopm_get_interface(interface);
- if (retval) {
- ced->open_count--;
- mutex_unlock(&ced->io_mutex);
- kref_put(&ced->kref, ced_delete);
- goto exit;
- }
- } else { /* uncomment this block if you want exclusive open */
- dev_err(&interface->dev, "%s: fail: already open\n", __func__);
- retval = -EBUSY;
- ced->open_count--;
- mutex_unlock(&ced->io_mutex);
- kref_put(&ced->kref, ced_delete);
- goto exit;
- }
- /* prevent the device from being autosuspended */
-
- /* save our object in the file's private structure */
- file->private_data = ced;
- mutex_unlock(&ced->io_mutex);
-
-exit:
- return retval;
-}
-
-static int ced_release(struct inode *inode, struct file *file)
-{
- struct ced_data *ced = file->private_data;
-
- if (ced == NULL)
- return -ENODEV;
-
- dev_dbg(&ced->interface->dev, "%s: called\n", __func__);
- mutex_lock(&ced->io_mutex);
- if (!--ced->open_count && ced->interface) /* Allow autosuspend */
- usb_autopm_put_interface(ced->interface);
- mutex_unlock(&ced->io_mutex);
-
- /* decrement the count on our device */
- kref_put(&ced->kref, ced_delete);
- return 0;
-}
-
-static int ced_flush(struct file *file, fl_owner_t id)
-{
- int res;
- struct ced_data *ced = file->private_data;
-
- if (ced == NULL)
- return -ENODEV;
-
- dev_dbg(&ced->interface->dev, "%s: char in pend=%d\n",
- __func__, ced->read_chars_pending);
-
- /* wait for io to stop */
- mutex_lock(&ced->io_mutex);
- dev_dbg(&ced->interface->dev, "%s: got io_mutex\n", __func__);
- ced_draw_down(ced);
-
- /* read out errors, leave subsequent opens a clean slate */
- spin_lock_irq(&ced->err_lock);
- res = ced->errors ? (ced->errors == -EPIPE ? -EPIPE : -EIO) : 0;
- ced->errors = 0;
- spin_unlock_irq(&ced->err_lock);
-
- mutex_unlock(&ced->io_mutex);
- dev_dbg(&ced->interface->dev, "%s: exit reached\n", __func__);
-
- return res;
-}
-
-/***************************************************************************
-** can_accept_io_requests
-** If the device is removed, interface is set NULL. We also clear our pointer
-** from the interface, so we should make sure that ced is not NULL. This will
-** not help with a device extension held by a file.
-** return true if can accept new io requests, else false
-*/
-static bool can_accept_io_requests(struct ced_data *ced)
-{
- return ced && ced->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 *urb)
-{
- struct ced_data *ced = urb->context;
- int got = urb->actual_length; /* what we transferred */
-
- if (urb->status) { /* sync/async unlink faults aren't errors */
- if (!
- (urb->status == -ENOENT || urb->status == -ECONNRESET
- || urb->status == -ESHUTDOWN)) {
- dev_err(&ced->interface->dev,
- "%s: nonzero write bulk status received: %d\n",
- __func__, urb->status);
- }
-
- spin_lock(&ced->err_lock);
- ced->errors = urb->status;
- spin_unlock(&ced->err_lock);
- got = 0; /* and tidy up again if so */
-
- spin_lock(&ced->char_out_lock); /* already at irq level */
- ced->out_buff_get = 0; /* Reset the output buffer */
- ced->out_buff_put = 0;
- ced->num_output = 0; /* Clear the char count */
- ced->pipe_error[0] = 1; /* Flag an error for later */
- ced->send_chars_pending = false; /* Allow other threads again */
- spin_unlock(&ced->char_out_lock); /* already at irq level */
- dev_dbg(&ced->interface->dev,
- "%s: char out done, 0 chars sent\n", __func__);
- } else {
- dev_dbg(&ced->interface->dev,
- "%s: char out done, %d chars sent\n", __func__, got);
- spin_lock(&ced->char_out_lock); /* already at irq level */
- ced->num_output -= got; /* Now adjust the char send buffer */
- ced->out_buff_get += got; /* to match what we did */
-
- /* Can't do this any earlier as data could be overwritten */
- if (ced->out_buff_get >= OUTBUF_SZ)
- ced->out_buff_get = 0;
-
- if (ced->num_output > 0) { /* if more to be done... */
- int pipe = 0; /* The pipe number to use */
- int ret;
- char *pDat = &ced->output_buffer[ced->out_buff_get];
- /* maximum to send */
- unsigned int count = ced->num_output;
-
- /* does it cross buffer end? */
- if ((ced->out_buff_get + count) > OUTBUF_SZ)
- count = OUTBUF_SZ - ced->out_buff_get;
-
- /* we are done with stuff that changes */
- spin_unlock(&ced->char_out_lock);
-
- /* copy output data to the buffer */
- memcpy(ced->coher_char_out, pDat, count);
- usb_fill_bulk_urb(ced->urb_char_out, ced->udev,
- usb_sndbulkpipe(ced->udev,
- ced->ep_addr[0]),
- ced->coher_char_out, count,
- ced_writechar_callback, ced);
- ced->urb_char_out->transfer_flags |=
- URB_NO_TRANSFER_DMA_MAP;
-
- /* in case we need to kill it */
- usb_anchor_urb(ced->urb_char_out, &ced->submitted);
- ret = usb_submit_urb(ced->urb_char_out, GFP_ATOMIC);
- dev_dbg(&ced->interface->dev, "%s: n=%d>%s<\n",
- __func__, count, pDat);
-
- /* grab lock for errors */
- spin_lock(&ced->char_out_lock);
-
- if (ret) {
- /* Flag an error to be handled later */
- ced->pipe_error[pipe] = 1;
- /* Allow other threads again */
- ced->send_chars_pending = false;
- usb_unanchor_urb(ced->urb_char_out);
- dev_err(&ced->interface->dev,
- "%s: usb_submit_urb() returned %d\n",
- __func__, ret);
- }
- } else
- /* Allow other threads again */
- ced->send_chars_pending = false;
-
- spin_unlock(&ced->char_out_lock); /* already at irq level */
- }
-}
-
-/****************************************************************************
-** ced_send_chars
-** Transmit the characters in the output buffer to the 1401. This may need
-** breaking down into multiple transfers.
-****************************************************************************/
-int ced_send_chars(struct ced_data *ced)
-{
- int retval = U14ERR_NOERROR;
-
- spin_lock_irq(&ced->char_out_lock); /* Protect ourselves */
-
- if ((!ced->send_chars_pending) && /* Not currently sending */
- (ced->num_output > 0) && /* has characters to output */
- (can_accept_io_requests(ced))) { /* and current activity is OK */
- unsigned int count = ced->num_output; /* Get a copy of the */
- /* character count */
-
- /* Set flag to lock out other threads */
- ced->send_chars_pending = true;
-
- dev_dbg(&ced->interface->dev,
- "Send %d chars to 1401, EP0 flag %d\n",
- count, ced->n_pipes == 3);
- /* If we have only 3 end points we must send the characters */
- /* to the 1401 using EP0. */
- if (ced->n_pipes == 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 i = count; /* Local char counter */
- unsigned int index = 0; /* The index into the */
- /* char buffer */
-
- /* Free spinlock as we call USBD */
- spin_unlock_irq(&ced->char_out_lock);
-
- while ((i > 0) && (retval == U14ERR_NOERROR)) {
- /* We have to break the transfer up into 64-byte chunks because of a 2270 problem */
- int n = i > 64 ? 64 : i; /* Chars for this xfer, max of 64 */
- int sent = usb_control_msg(ced->udev,
- usb_sndctrlpipe(ced->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 */
- &ced->output_buffer[index], /* where to send from */
- n, /* how much to send */
- 1000); /* timeout in jiffies */
- if (sent <= 0) {
- /* if 0 chars says we timed out */
- retval = sent ? sent : -ETIMEDOUT;
- dev_err(&ced->interface->dev,
- "Send %d chars by EP0 failed: %d\n",
- n, retval);
- } else {
- dev_dbg(&ced->interface->dev,
- "Sent %d chars by EP0\n", n);
- i -= sent;
- index += sent;
- }
- }
-
- /* Protect ced changes, released by general code */
- spin_lock_irq(&ced->char_out_lock);
- ced->out_buff_get = 0; /* so reset the output buffer */
- ced->out_buff_put = 0;
- ced->num_output = 0; /* and clear the buffer count */
- /* Allow other threads again */
- ced->send_chars_pending = false;
- } else { /* Here for sending chars normally - we hold the */
- /* spin lock */
- int pipe = 0; /* The pipe number to use */
- char *pDat = &ced->output_buffer[ced->out_buff_get];
-
- /* does it cross buffer end? */
- if ((ced->out_buff_get + count) > OUTBUF_SZ)
- count = OUTBUF_SZ - ced->out_buff_get;
- /* we are done with stuff that changes */
- spin_unlock_irq(&ced->char_out_lock);
- /* copy output data to the buffer */
- memcpy(ced->coher_char_out, pDat, count);
- usb_fill_bulk_urb(ced->urb_char_out, ced->udev,
- usb_sndbulkpipe(ced->udev,
- ced->ep_addr[0]),
- ced->coher_char_out, count,
- ced_writechar_callback, ced);
- ced->urb_char_out->transfer_flags |=
- URB_NO_TRANSFER_DMA_MAP;
- usb_anchor_urb(ced->urb_char_out, &ced->submitted);
- retval = usb_submit_urb(ced->urb_char_out, GFP_KERNEL);
-
- /* grab lock for errors */
- spin_lock_irq(&ced->char_out_lock);
-
- if (retval) {
- /* Flag an error to be handled later */
- ced->pipe_error[pipe] = 1;
- /* Allow other threads again */
- ced->send_chars_pending = false;
- /* remove from list of active urbs */
- usb_unanchor_urb(ced->urb_char_out);
- }
- }
- } else if (ced->send_chars_pending && (ced->num_output > 0))
- dev_dbg(&ced->interface->dev,
- "%s: send_chars_pending:true\n", __func__);
-
- dev_dbg(&ced->interface->dev, "%s: exit code: %d\n", __func__, retval);
- spin_unlock_irq(&ced->char_out_lock); /* Now let go of the spinlock */
- return retval;
-}
-
-/***************************************************************************
-** ced_copy_user_space
-** This moves memory between pinned down user space and the coher_staged_io
-** memory buffer we use for transfers. Copy n bytes in the directions that
-** is defined by ced->staged_read. The user space is determined by the area
-** in ced->staged_id and the offset in ced->staged_done. The user
-** area may well not start on a page boundary, so allow for that.
-**
-** We have a table of physical pages that describe the area, so we can use
-** this to get a virtual address that the kernel can use.
-**
-** ced 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 ced_copy_user_space(struct ced_data *ced, int n)
-{
- unsigned int area = ced->staged_id;
-
- if (area < MAX_TRANSAREAS) {
- /* area to be used */
- struct transarea *ta = &ced->trans_def[area];
- unsigned int offset =
- ced->staged_done + ced->staged_offset + ta->base_offset;
- char *coher_buf = ced->coher_staged_io; /* coherent buffer */
-
- if (!ta->used) {
- dev_err(&ced->interface->dev, "%s: area %d unused\n",
- __func__, area);
- return;
- }
-
- while (n) {
- /* page number in table */
- int page = offset >> PAGE_SHIFT;
-
- if (page < ta->n_pages) {
- char *address =
- (char *)kmap_atomic(ta->pages[page]);
- if (address) {
- /* offset into the page */
- unsigned int page_off =
- offset & (PAGE_SIZE - 1);
- /* max to transfer on this page */
- size_t xfer = PAGE_SIZE - page_off;
-
- /* limit byte count if too much */
- /* for the page */
- if (xfer > n)
- xfer = n;
- if (ced->staged_read)
- memcpy(address + page_off,
- coher_buf, xfer);
- else
- memcpy(coher_buf,
- address + page_off,
- xfer);
- kunmap_atomic(address);
- offset += xfer;
- coher_buf += xfer;
- n -= xfer;
- } else {
- dev_err(&ced->interface->dev,
- "%s: did not map page %d\n",
- __func__, page);
- return;
- }
-
- } else {
- dev_err(&ced->interface->dev,
- "%s: exceeded pages %d\n",
- __func__, page);
- return;
- }
- }
- } else
- dev_err(&ced->interface->dev, "%s: bad area %d\n",
- __func__, area);
-}
-
-/* Forward declarations for stuff used circularly */
-static int ced_stage_chunk(struct ced_data *ced);
-
-/***************************************************************************
-** ReadWrite_Complete
-**
-** Completion routine for our staged read/write Irps
-*/
-static void staged_callback(struct urb *urb)
-{
- struct ced_data *ced = urb->context;
- unsigned int got = urb->actual_length; /* what we transferred */
- bool cancel = false;
- bool restart_char_input; /* used at the end */
-
- spin_lock(&ced->staged_lock); /* stop ced_read_write_mem() action */
- /* while this routine is running */
-
- /* clear the flag for staged IRP pending */
- ced->staged_urb_pending = false;
-
- if (urb->status) { /* sync/async unlink faults aren't errors */
- if (!
- (urb->status == -ENOENT || urb->status == -ECONNRESET
- || urb->status == -ESHUTDOWN)) {
- dev_err(&ced->interface->dev,
- "%s: nonzero write bulk status received: %d\n",
- __func__, urb->status);
- } else
- dev_info(&ced->interface->dev,
- "%s: staged xfer cancelled\n", __func__);
-
- spin_lock(&ced->err_lock);
- ced->errors = urb->status;
- spin_unlock(&ced->err_lock);
- got = 0; /* and tidy up again if so */
- cancel = true;
- } else {
- dev_dbg(&ced->interface->dev, "%s: %d chars xferred\n",
- __func__, got);
- if (ced->staged_read) /* if reading, save to user space */
- /* copy from buffer to user */
- ced_copy_user_space(ced, got);
- if (got == 0)
- dev_dbg(&ced->interface->dev, "%s: ZLP\n", __func__);
- }
-
- /* Update the transfer length based on the TransferBufferLength value */
- /* in the URB */
- ced->staged_done += got;
-
- dev_dbg(&ced->interface->dev, "%s: done %d bytes of %d\n",
- __func__, ced->staged_done, ced->staged_length);
-
- if ((ced->staged_done == ced->staged_length) || /* If no more to do */
- (cancel)) { /* or this IRP was cancelled */
- /* Transfer area info */
- struct transarea *ta = &ced->trans_def[ced->staged_id];
-
- dev_dbg(&ced->interface->dev,
- "%s: transfer done, bytes %d, cancel %d\n",
- __func__, ced->staged_done, cancel);
-
- /* 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 ced_read_write_mem) is totally duff. */
- if ((ta->circular) &&
- (ta->circ_to_host) &&
- (!cancel) && /* Time to sort out circular buffer info? */
- (ced->staged_read)) {/* Only for tohost transfers for now */
- /* If block 1 is in use we must append to it */
- if (ta->blocks[1].size > 0) {
- if (ced->staged_offset ==
- (ta->blocks[1].offset +
- ta->blocks[1].size)) {
- ta->blocks[1].size +=
- ced->staged_length;
- dev_dbg(&ced->interface->dev,
- "RWM_Complete, circ block 1 now %d bytes at %d\n",
- ta->blocks[1].size,
- ta->blocks[1].offset);
- } else {
- /* Here things have gone very, very */
- /* wrong, but I cannot see how this */
- /* can actually be achieved */
- ta->blocks[1].offset =
- ced->staged_offset;
- ta->blocks[1].size =
- ced->staged_length;
- dev_err(&ced->interface->dev,
- "%s: ERROR, circ block 1 re-started %d bytes at %d\n",
- __func__,
- ta->blocks[1].size,
- ta->blocks[1].offset);
- }
- } else { /* If block 1 is not used, we try to add */
- /*to block 0 */
-
- /* Got stored block 0 information? */
- if (ta->blocks[0].size > 0) {
- /* Must append onto the */
- /*existing block 0 */
- if (ced->staged_offset ==
- (ta->blocks[0].offset +
- ta->blocks[0].size)) {
- /* Just add this transfer in */
- ta->blocks[0].size +=
- ced->staged_length;
- dev_dbg(&ced->interface->dev,
- "RWM_Complete, circ block 0 now %d bytes at %d\n",
- ta->blocks[0].size,
- ta->blocks[0].offset);
-
- } else { /* If it doesn't append, put */
- /* into new block 1 */
- ta->blocks[1].offset =
- ced->staged_offset;
- ta->blocks[1].size =
- ced->staged_length;
- dev_dbg(&ced->interface->dev,
- "RWM_Complete, circ block 1 started %d bytes at %d\n",
- ta->blocks[1].size,
- ta->blocks[1].offset);
- }
- } else { /* No info stored yet, just save */
- /* in block 0 */
- ta->blocks[0].offset =
- ced->staged_offset;
- ta->blocks[0].size =
- ced->staged_length;
- dev_dbg(&ced->interface->dev,
- "RWM_Complete, circ block 0 started %d bytes at %d\n",
- ta->blocks[0].size,
- ta->blocks[0].offset);
- }
- }
- }
-
- if (!cancel) { /* Don't generate an event if cancelled */
- dev_dbg(&ced->interface->dev,
- "RWM_Complete, bCircular %d, bToHost %d, eStart %d, eSize %d\n",
- ta->circular, ta->event_to_host,
- ta->event_st, ta->event_sz);
- /* Set a user-mode event... */
- /* ...on transfers in this direction? */
- if ((ta->event_sz) &&
- (ced->staged_read == ta->event_to_host)) {
- int wakeup = 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 ((ta->circular) && /* Circular areas use a
- simpler test */
- (ta->circ_to_host)) { /* only in supported
- direction */
- /* Is total data waiting up */
- /* to size limit? */
- unsigned int dwTotal =
- ta->blocks[0].size +
- ta->blocks[1].size;
- wakeup = (dwTotal >= ta->event_sz);
- } else {
- unsigned int transEnd =
- ced->staged_offset +
- ced->staged_length;
- unsigned int eventEnd =
- ta->event_st + ta->event_sz;
- wakeup = (ced->staged_offset < eventEnd)
- && (transEnd > ta->event_st);
- }
-
- if (wakeup) {
- dev_dbg(&ced->interface->dev,
- "About to set event to notify app\n");
-
- /* wake up waiting processes */
- wake_up_interruptible(&ta->event);
- /* increment wakeup count */
- ++ta->wake_up;
- }
- }
- }
-
- /* Switch back to char mode before ced_read_write_mem call */
- ced->dma_flag = MODE_CHAR;
-
- /* Don't look for waiting transfer if cancelled */
- if (!cancel) {
- /* If we have a transfer waiting, kick it off */
- if (ced->xfer_waiting) {/* Got a block xfer waiting? */
- int retval;
-
- dev_info(&ced->interface->dev,
- "*** RWM_Complete *** pending transfer will now be set up!!!\n");
- retval =
- ced_read_write_mem(ced,
- !ced->dma_info.outward,
- ced->dma_info.ident,
- ced->dma_info.offset,
- ced->dma_info.size);
-
- if (retval)
- dev_err(&ced->interface->dev,
- "RWM_Complete rw setup failed %d\n",
- retval);
- }
- }
-
- } else /* Here for more to do */
- ced_stage_chunk(ced); /* fire off the next bit */
-
- /* While we hold the staged_lock, 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 */
- /* dma_flag. */
- restart_char_input = !cancel && (ced->dma_flag == MODE_CHAR) &&
- !ced->xfer_waiting;
-
- spin_unlock(&ced->staged_lock); /* Finally release the lock again */
-
- /* This is not correct as dma_flag is protected by the staged lock, */
- /* but it is treated in ced_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 (restart_char_input) /* may be out of date, but... */
- ced_allowi(ced); /* ...ced_allowi tests a lock too. */
- dev_dbg(&ced->interface->dev, "%s: done\n", __func__);
-}
-
-/****************************************************************************
-** ced_stage_chunk
-**
-** Generates the next chunk of data making up a staged transfer.
-**
-** 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 ced_stage_chunk(struct ced_data *ced)
-{
- int retval = U14ERR_NOERROR;
- unsigned int chunk_size;
- int pipe = ced->staged_read ? 3 : 2; /* The pipe number to use for */
- /* reads or writes */
-
- if (ced->n_pipes == 3)
- pipe--; /* Adjust for the 3-pipe case */
-
- if (pipe < 0) /* and trap case that should never happen */
- return U14ERR_FAIL;
-
- if (!can_accept_io_requests(ced)) { /* got sudden remove? */
- dev_info(&ced->interface->dev, "%s: sudden remove, giving up\n",
- __func__);
- return U14ERR_FAIL; /* could do with a better error */
- }
-
- /* transfer length remaining */
- chunk_size = (ced->staged_length - ced->staged_done);
- if (chunk_size > STAGED_SZ) /* make sure to keep legal */
- chunk_size = STAGED_SZ; /* limit to max allowed */
-
- if (!ced->staged_read) /* if writing... */
- /* ...copy data into the buffer */
- ced_copy_user_space(ced, chunk_size);
-
- usb_fill_bulk_urb(ced->staged_urb, ced->udev,
- ced->staged_read ? usb_rcvbulkpipe(ced->udev,
- ced->
- ep_addr[pipe]) :
- usb_sndbulkpipe(ced->udev, ced->ep_addr[pipe]),
- ced->coher_staged_io, chunk_size,
- staged_callback, ced);
- ced->staged_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- /* in case we need to kill it */
- usb_anchor_urb(ced->staged_urb, &ced->submitted);
- retval = usb_submit_urb(ced->staged_urb, GFP_ATOMIC);
- if (retval) {
- usb_unanchor_urb(ced->staged_urb); /* kill it */
- ced->pipe_error[pipe] = 1; /* Flag an error to be */
- /* handled later */
- dev_err(&ced->interface->dev,
- "%s: submit urb failed, code %d\n",
- __func__, retval);
- } else
- /* Set the flag for staged URB pending */
- ced->staged_urb_pending = true;
- dev_dbg(&ced->interface->dev, "%s: done so far:%d, this size:%d\n",
- __func__, ced->staged_done, chunk_size);
-
- return retval;
-}
-
-/***************************************************************************
-** ced_read_write_mem
-**
-** This routine is used generally for block read and write operations.
-** Breaks up a read or write in to specified sized chunks, as specified by pipe
-** information on maximum transfer size.
-**
-** Any code that calls this must be holding the staged_lock
-**
-** Arguments:
-** DeviceObject - pointer to our FDO (Functional Device Object)
-** read - TRUE for read, FALSE for write. This is from POV of the driver
-** ident - the transfer area number - defines memory area and more.
-** offs - the start offset within the transfer area of the start of this
-** transfer.
-** len - the number of bytes to transfer.
-*/
-int ced_read_write_mem(struct ced_data *ced, bool read, unsigned short ident,
- unsigned int offs, unsigned int len)
-{
- /* Transfer area info */
- struct transarea *ta = &ced->trans_def[ident];
-
- /* Are we in a state to accept new requests? */
- if (!can_accept_io_requests(ced)) {
- dev_err(&ced->interface->dev, "%s: can't accept requests\n",
- __func__);
- return U14ERR_FAIL;
- }
-
- dev_dbg(&ced->interface->dev,
- "%s: xfer %d bytes to %s, offset %d, area %d\n",
- __func__, len, read ? "host" : "1401", offs, ident);
-
- /* 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 (ced->staged_urb_pending) {
- ced->xfer_waiting = true; /* Flag we are waiting */
- dev_info(&ced->interface->dev,
- "%s: xfer is waiting, as previous staged pending\n",
- __func__);
- return U14ERR_NOERROR;
- }
-
- if (len == 0) { /* allow 0-len read or write; just return success */
- dev_dbg(&ced->interface->dev,
- "%s: OK; zero-len read/write request\n", __func__);
- return U14ERR_NOERROR;
- }
-
- if ((ta->circular) && /* Circular transfer? */
- (ta->circ_to_host) && (read)) { /* In a supported direction */
- /* If so, we sort out offset ourself */
- bool bWait = false; /* Flag for transfer having to wait */
-
- dev_dbg(&ced->interface->dev,
- "Circular buffers are %d at %d and %d at %d\n",
- ta->blocks[0].size, ta->blocks[0].offset,
- ta->blocks[1].size, ta->blocks[1].offset);
-
- /* Using the second block already? */
- if (ta->blocks[1].size > 0) {
- /* take offset from that */
- offs = ta->blocks[1].offset + ta->blocks[1].size;
- /* Wait if will overwrite block 0? */
- bWait = (offs + len) > ta->blocks[0].offset;
- /* or if it overflows the buffer */
- bWait |= (offs + len) > ta->length;
- } else { /* Area 1 not in use, try to use area 0 */
- /* Reset block 0 if not in use */
- if (ta->blocks[0].size == 0)
- ta->blocks[0].offset = 0;
- offs =
- ta->blocks[0].offset +
- ta->blocks[0].size;
- /* Off the end of the buffer? */
- if ((offs + len) > ta->length) {
- /* Set up to use second block */
- ta->blocks[1].offset = 0;
- offs = 0;
- /* Wait if will overwrite block 0? */
- bWait = (offs + len) > ta->blocks[0].offset;
- /* or if it overflows the buffer */
- bWait |= (offs + len) > ta->length;
- }
- }
-
- if (bWait) { /* This transfer will have to wait? */
- ced->xfer_waiting = true; /* Flag we are waiting */
- dev_dbg(&ced->interface->dev,
- "%s: xfer waiting for circular buffer space\n",
- __func__);
- return U14ERR_NOERROR;
- }
-
- dev_dbg(&ced->interface->dev,
- "%s: circular xfer, %d bytes starting at %d\n",
- __func__, len, offs);
- }
- /* Save the parameters for the read\write transfer */
- ced->staged_read = read; /* Save the parameters for this read */
- ced->staged_id = ident; /* ID allows us to get transfer area info */
- ced->staged_offset = offs; /* The area within the transfer area */
- ced->staged_length = len;
- ced->staged_done = 0; /* Initialise the byte count */
- ced->dma_flag = MODE_LINEAR; /* Set DMA mode flag at this point */
- ced->xfer_waiting = false; /* Clearly not a transfer waiting now */
-
-/* KeClearEvent(&ced->StagingDoneEvent); // Clear the transfer done event */
- ced_stage_chunk(ced); /* fire off the first chunk */
-
- return U14ERR_NOERROR;
-}
-
-/****************************************************************************
-**
-** ced_read_char
-**
-** Reads a character a buffer. If there is no more
-** data we return FALSE. Used as part of decoding a DMA request.
-**
-****************************************************************************/
-static bool ced_read_char(unsigned char *character, char *buf,
- unsigned int *n_done, unsigned int got)
-{
- bool read = false;
- unsigned int done = *n_done;
-
- if (done < got) { /* If there is more data */
- /* Extract the next char */
- *character = (unsigned char)buf[done];
- done++; /* Increment the done count */
- *n_done = done;
- read = true; /* and flag success */
- }
-
- return read;
-}
-
-#ifdef NOTUSED
-/****************************************************************************
-**
-** ced_read_word
-**
-** Reads a word from the 1401, just uses ced_read_char twice;
-** passes on any error
-**
-*****************************************************************************/
-static bool ced_read_word(unsigned short *word, char *buf, unsigned int *n_done,
- unsigned int got)
-{
- if (ced_read_char((unsigned char *)word, buf, n_done, got))
- return ced_read_char(((unsigned char *)word) + 1, buf, n_done,
- got);
- else
- return false;
-}
-#endif
-
-/****************************************************************************
-** ced_read_huff
-**
-** Reads a coded number in and returns it, Code is:
-** If data is in range 0..127 we receive 1 byte. If data in range 128-16383
-** we receive two bytes, top bit of first indicates another on its way. If
-** data in range 16384-4194303 we get three bytes, top two bits of first set
-** to indicate three byte total.
-**
-*****************************************************************************/
-static bool ced_read_huff(volatile unsigned int *word, char *buf,
- unsigned int *n_done, unsigned int got)
-{
- unsigned char c; /* for each read to ced_read_char */
- bool retval = true; /* assume we will succeed */
- unsigned int data = 0; /* Accumulator for the data */
-
- if (ced_read_char(&c, buf, n_done, got)) {
- data = c; /* copy the data */
- if ((data & 0x00000080) != 0) { /* Bit set for more data ? */
- data &= 0x0000007F; /* Clear the relevant bit */
- if (ced_read_char(&c, buf, n_done, got)) {
- data = (data << 8) | c;
-
- /* three byte sequence ? */
- if ((data & 0x00004000) != 0) {
- /* Clear the relevant bit */
- data &= 0x00003FFF;
- if (ced_read_char
- (&c, buf, n_done, got))
- data = (data << 8) | c;
- else
- retval = false;
- }
- } else
- retval = false; /* couldn't read data */
- }
- } else
- retval = false;
-
- *word = data; /* return the data */
- return retval;
-}
-
-/***************************************************************************
-**
-** ced_read_dma_info
-**
-** Tries to read info about the dma request from the 1401 and decode it into
-** the dma descriptor block. We have at this point had the escape character
-** from the 1401 and now we must read in the rest of the information about
-** the transfer request. Returns FALSE if 1401 fails to respond or obselete
-** code from 1401 or bad parameters.
-**
-** The buf char pointer does not include the initial escape character, so
-** we start handling the data at offset zero.
-**
-*****************************************************************************/
-static bool ced_read_dma_info(volatile struct dmadesc *dma_desc,
- struct ced_data *ced,
- char *buf, unsigned int count)
-{
- bool retval = false; /* assume we won't succeed */
- unsigned char c;
- unsigned int n_done = 0; /* We haven't parsed anything so far */
-
- dev_dbg(&ced->interface->dev, "%s\n", __func__);
-
- if (ced_read_char(&c, buf, &n_done, count)) {
- /* get code for transfer type */
- unsigned char trans_code = (c & 0x0F);
- /* and area identifier */
- unsigned short ident = ((c >> 4) & 0x07);
-
- /* fill in the structure we were given */
- dma_desc->trans_type = trans_code; /* type of transfer */
- dma_desc->ident = ident; /* area to use */
- dma_desc->size = 0; /* initialise other bits */
- dma_desc->offset = 0;
-
- dev_dbg(&ced->interface->dev, "%s: type: %d ident: %d\n",
- __func__, dma_desc->trans_type, dma_desc->ident);
-
- /* set transfer direction */
- dma_desc->outward = (trans_code != TM_EXTTOHOST);
-
- switch (trans_code) {
-
- /* Extended linear transfer modes (the only ones!) */
- case TM_EXTTOHOST:
- case TM_EXTTO1401:
- {
- retval =
- ced_read_huff(&(dma_desc->offset), buf,
- &n_done, count)
- && ced_read_huff(&(dma_desc->size), buf,
- &n_done, count);
- if (retval) {
- dev_dbg(&ced->interface->dev,
- "%s: xfer offset & size %d %d\n",
- __func__, dma_desc->offset,
- dma_desc->size);
-
- if ((ident >= MAX_TRANSAREAS) || /* Illegal area number, or... */
- (!ced->trans_def[ident].used) || /* area not set up, or... */
- (dma_desc->offset > ced->trans_def[ident].length) || /* range/size */
- ((dma_desc->offset +
- dma_desc->size) >
- (ced->trans_def[ident].length))) {
- /* bad parameter(s) */
- retval = false;
- dev_dbg(&ced->interface->dev,
- "%s: bad param - id %d, bUsed %d, offset %d, size %d, area length %d\n",
- __func__, ident,
- ced->trans_def[ident].
- used,
- dma_desc->offset,
- dma_desc->size,
- ced->trans_def[ident].
- length);
- }
- }
- break;
- }
- default:
- break;
- }
- } else
- retval = false;
-
- if (!retval) /* now check parameters for validity */
- dev_err(&ced->interface->dev,
- "%s: error reading Esc sequence\n",
- __func__);
-
- return retval;
-}
-
-/****************************************************************************
-**
-** ced_handle_esc
-**
-** Deals with an escape sequence coming from the 1401. This can either be
-** a DMA transfer request of various types or a response to an escape sequence
-** sent to the 1401. This is called from a callback.
-**
-** Parameters are
-**
-** count - the number of characters in the device extension char in buffer,
-** this is known to be at least 2 or we will not be called.
-**
-****************************************************************************/
-static int ced_handle_esc(struct ced_data *ced, char *ch,
- unsigned int count)
-{
- int retval = 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 (ch[0] == '?') { /* Is this an information response */
- /* Parse and save the information */
- } else {
- spin_lock(&ced->staged_lock); /* Lock others out */
-
- /* Get DMA parameters */
- if (ced_read_dma_info(&ced->dma_info, ced, ch, count)) {
- /* check transfer type */
- unsigned short trans_type = ced->dma_info.trans_type;
-
- dev_dbg(&ced->interface->dev,
- "%s: xfer to %s, offset %d, length %d\n",
- __func__,
- ced->dma_info.outward ? "1401" : "host",
- ced->dma_info.offset, ced->dma_info.size);
-
- /* Check here for badly out of kilter... */
- if (ced->xfer_waiting) {
- /* This can never happen, really */
- dev_err(&ced->interface->dev,
- "ERROR: DMA setup while transfer still waiting\n");
- } else {
- if ((trans_type == TM_EXTTOHOST)
- || (trans_type == TM_EXTTO1401)) {
- retval =
- ced_read_write_mem(ced,
- !ced->dma_info.outward,
- ced->dma_info.ident,
- ced->dma_info.offset,
- ced->dma_info.size);
- if (retval != U14ERR_NOERROR)
- dev_err(&ced->interface->dev,
- "%s: ced_read_write_mem() failed %d\n",
- __func__, retval);
- } else /* This covers non-linear
- transfer setup */
- dev_err(&ced->interface->dev,
- "%s: Unknown block xfer type %d\n",
- __func__, trans_type);
- }
- } else /* Failed to read parameters */
- dev_err(&ced->interface->dev, "%s: ced_read_dma_info() fail\n",
- __func__);
-
- spin_unlock(&ced->staged_lock); /* OK here */
- }
-
- dev_dbg(&ced->interface->dev, "%s: returns %d\n", __func__, retval);
-
- return retval;
-}
-
-/****************************************************************************
-** Callback for the character read complete or error
-****************************************************************************/
-static void ced_readchar_callback(struct urb *urb)
-{
- struct ced_data *ced = urb->context;
- int got = urb->actual_length; /* what we transferred */
-
- if (urb->status) { /* Do we have a problem to handle? */
- /* The pipe number to use for error */
- int pipe = ced->n_pipes == 4 ? 1 : 0;
- /* sync/async unlink faults aren't errors... */
- /* just saying device removed or stopped */
- if (!
- (urb->status == -ENOENT || urb->status == -ECONNRESET
- || urb->status == -ESHUTDOWN)) {
- dev_err(&ced->interface->dev,
- "%s: nonzero write bulk status received: %d\n",
- __func__, urb->status);
- } else
- dev_dbg(&ced->interface->dev,
- "%s: 0 chars urb->status=%d (shutdown?)\n",
- __func__, urb->status);
-
- spin_lock(&ced->err_lock);
- ced->errors = urb->status;
- spin_unlock(&ced->err_lock);
- got = 0; /* and tidy up again if so */
-
- spin_lock(&ced->char_in_lock); /* already at irq level */
- ced->pipe_error[pipe] = 1; /* Flag an error for later */
- } else {
- /* Esc sequence? */
- if ((got > 1) && ((ced->coher_char_in[0] & 0x7f) == 0x1b)) {
- /* handle it */
- ced_handle_esc(ced, &ced->coher_char_in[1], got - 1);
-
- /* already at irq level */
- spin_lock(&ced->char_in_lock);
- } else {
- /* already at irq level */
- spin_lock(&ced->char_in_lock);
-
- if (got > 0) {
- unsigned int i;
-
- if (got < INBUF_SZ) {
- /* tidy the string */
- ced->coher_char_in[got] = 0;
- dev_dbg(&ced->interface->dev,
- "%s: got %d chars >%s<\n",
- __func__, got,
- ced->coher_char_in);
- }
- /* We know that whatever we read must fit */
- /* in the input buffer */
- for (i = 0; i < got; i++) {
- ced->input_buffer[ced->in_buff_put++] =
- ced->coher_char_in[i] & 0x7F;
- if (ced->in_buff_put >= INBUF_SZ)
- ced->in_buff_put = 0;
- }
-
- if ((ced->num_input + got) <= INBUF_SZ)
- /* Adjust the buffer count */
- /* accordingly */
- ced->num_input += got;
- } else
- dev_dbg(&ced->interface->dev, "%s: read ZLP\n",
- __func__);
- }
- }
-
- ced->read_chars_pending = false; /* No longer have a pending read */
- spin_unlock(&ced->char_in_lock); /* already at irq level */
-
- ced_allowi(ced); /* see if we can do the next one */
-}
-
-/****************************************************************************
-** ced_allowi
-**
-** This is used to make sure that there is always a pending input transfer so
-** we can pick up any inward transfers. This can be called in multiple contexts
-** so we use the irqsave version of the spinlock.
-****************************************************************************/
-int ced_allowi(struct ced_data *ced)
-{
- int retval = U14ERR_NOERROR;
- unsigned long flags;
-
- /* can be called in multiple contexts */
- spin_lock_irqsave(&ced->char_in_lock, flags);
-
- /* 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 (!ced->in_draw_down && /* stop input if */
- !ced->read_chars_pending && /* If no read request outstanding */
- (ced->num_input < (INBUF_SZ / 2)) && /* and there is some space */
- (ced->dma_flag == MODE_CHAR) && /* not doing any DMA */
- (!ced->xfer_waiting) && /* no xfer waiting to start */
- (can_accept_io_requests(ced))) { /* and activity is generally OK */
- /* then off we go */
- /* max we could read */
- unsigned int max = INBUF_SZ - ced->num_input;
- /* The pipe number to use */
- int pipe = ced->n_pipes == 4 ? 1 : 0;
-
- dev_dbg(&ced->interface->dev, "%s: %d chars in input buffer\n",
- __func__, ced->num_input);
-
- usb_fill_int_urb(ced->urb_char_in, ced->udev,
- usb_rcvintpipe(ced->udev, ced->ep_addr[pipe]),
- ced->coher_char_in, max, ced_readchar_callback,
- ced, ced->interval);
-
- /* short xfers are OK by default */
- ced->urb_char_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
- /* in case we need to kill it */
- usb_anchor_urb(ced->urb_char_in, &ced->submitted);
-
- retval = usb_submit_urb(ced->urb_char_in, GFP_ATOMIC);
- if (retval) {
- /* remove from list of active Urbs */
- usb_unanchor_urb(ced->urb_char_in);
- /* Flag an error to be handled later */
- ced->pipe_error[pipe] = 1;
- dev_err(&ced->interface->dev,
- "%s: submit urb failed: %d\n",
- __func__, retval);
- } else
- /* Flag that we are active here */
- ced->read_chars_pending = true;
- }
-
- spin_unlock_irqrestore(&ced->char_in_lock, flags);
-
- return retval;
-}
-
-/*****************************************************************************
-** The ioctl entry point to the driver that is used by us to talk to it.
-** inode The device node (no longer in 3.0.0 kernels)
-** file The file that is open, which holds our ced pointer
-** arg The argument passed in. Note that long is 64-bits in 64-bit system,
-** i.e. it is big enough for a 64-bit pointer.
-*****************************************************************************/
-static long ced_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- int err = 0;
- struct ced_data *ced = file->private_data;
-
- if (!can_accept_io_requests(ced)) /* 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... */
- /* is kernel write */
- err = !access_ok(VERIFY_WRITE,
- (void __user *)arg, _IOC_SIZE(cmd));
- else if (_IOC_DIR(cmd) & _IOC_WRITE) /* and write from point of */
- /* view of user... */
- /* is kernel read */
- err = !access_ok(VERIFY_READ,
- (void __user *)arg, _IOC_SIZE(cmd));
- if (err)
- return -EFAULT;
-
- switch (_IOC_NR(cmd)) {
- case _IOC_NR(IOCTL_CED_SENDSTRING(0)):
- return ced_send_string(ced, (const char __user *)arg,
- _IOC_SIZE(cmd));
-
- case _IOC_NR(IOCTL_CED_RESET1401):
- return ced_reset(ced);
-
- case _IOC_NR(IOCTL_CED_GETCHAR):
- return ced_get_char(ced);
-
- case _IOC_NR(IOCTL_CED_SENDCHAR):
- return ced_send_char(ced, (char)arg);
-
- case _IOC_NR(IOCTL_CED_STAT1401):
- return ced_stat_1401(ced);
-
- case _IOC_NR(IOCTL_CED_LINECOUNT):
- return ced_line_count(ced);
-
- case _IOC_NR(IOCTL_CED_GETSTRING(0)):
- return ced_get_string(ced, (char __user *)arg, _IOC_SIZE(cmd));
-
- case _IOC_NR(IOCTL_CED_SETTRANSFER):
- return ced_set_transfer(ced,
- (struct transfer_area_desc __user *) arg);
-
- case _IOC_NR(IOCTL_CED_UNSETTRANSFER):
- return ced_unset_transfer(ced, (int)arg);
-
- case _IOC_NR(IOCTL_CED_SETEVENT):
- return ced_set_event(ced,
- (struct transfer_event __user *) arg);
-
- case _IOC_NR(IOCTL_CED_GETOUTBUFSPACE):
- return ced_get_out_buf_space(ced);
-
- case _IOC_NR(IOCTL_CED_GETBASEADDRESS):
- return -1;
-
- case _IOC_NR(IOCTL_CED_GETDRIVERREVISION):
- /* USB | MAJOR | MINOR */
- return (2 << 24) | (DRIVERMAJREV << 16) | DRIVERMINREV;
-
- case _IOC_NR(IOCTL_CED_GETTRANSFER):
- return ced_get_transfer(ced, (TGET_TX_BLOCK __user *) arg);
-
- case _IOC_NR(IOCTL_CED_KILLIO1401):
- return ced_kill_io(ced);
-
- case _IOC_NR(IOCTL_CED_STATEOF1401):
- return ced_state_of_1401(ced);
-
- case _IOC_NR(IOCTL_CED_GRAB1401):
- case _IOC_NR(IOCTL_CED_FREE1401):
- return U14ERR_NOERROR;
-
- case _IOC_NR(IOCTL_CED_STARTSELFTEST):
- return ced_start_self_test(ced);
-
- case _IOC_NR(IOCTL_CED_CHECKSELFTEST):
- return ced_check_self_test(ced, (TGET_SELFTEST __user *) arg);
-
- case _IOC_NR(IOCTL_CED_TYPEOF1401):
- return ced_type_of_1401(ced);
-
- case _IOC_NR(IOCTL_CED_TRANSFERFLAGS):
- return ced_transfer_flags(ced);
-
- case _IOC_NR(IOCTL_CED_DBGPEEK):
- return ced_dbg_peek(ced, (TDBGBLOCK __user *) arg);
-
- case _IOC_NR(IOCTL_CED_DBGPOKE):
- return ced_dbg_poke(ced, (TDBGBLOCK __user *) arg);
-
- case _IOC_NR(IOCTL_CED_DBGRAMPDATA):
- return ced_dbg_ramp_data(ced, (TDBGBLOCK __user *) arg);
-
- case _IOC_NR(IOCTL_CED_DBGRAMPADDR):
- return ced_dbg_ramp_addr(ced, (TDBGBLOCK __user *) arg);
-
- case _IOC_NR(IOCTL_CED_DBGGETDATA):
- return ced_dbg_get_data(ced, (TDBGBLOCK __user *) arg);
-
- case _IOC_NR(IOCTL_CED_DBGSTOPLOOP):
- return ced_dbg_stop_loop(ced);
-
- case _IOC_NR(IOCTL_CED_FULLRESET):
- ced->force_reset = true; /* Set a flag for a full reset */
- break;
-
- case _IOC_NR(IOCTL_CED_SETCIRCULAR):
- return ced_set_circular(ced,
- (struct transfer_area_desc __user *) arg);
-
- case _IOC_NR(IOCTL_CED_GETCIRCBLOCK):
- return ced_get_circ_block(ced, (TCIRCBLOCK __user *) arg);
-
- case _IOC_NR(IOCTL_CED_FREECIRCBLOCK):
- return ced_free_circ_block(ced, (TCIRCBLOCK __user *) arg);
-
- case _IOC_NR(IOCTL_CED_WAITEVENT):
- return ced_wait_event(ced, (int)(arg & 0xff), (int)(arg >> 8));
-
- case _IOC_NR(IOCTL_CED_TESTEVENT):
- return ced_test_event(ced, (int)arg);
-
- default:
- return U14ERR_NO_SUCH_FN;
- }
- return U14ERR_NOERROR;
-}
-
-static const struct file_operations ced_fops = {
- .owner = THIS_MODULE,
- .open = ced_open,
- .release = ced_release,
- .flush = ced_flush,
- .llseek = noop_llseek,
- .unlocked_ioctl = ced_ioctl,
-};
-
-/*
- * 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,
-};
-
-/* Check that the device that matches a 1401 vendor and product ID is OK to */
-/* use and initialise our struct ced_data. */
-static int ced_probe(struct usb_interface *interface,
- const struct usb_device_id *id)
-{
- struct ced_data *ced;
- 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 */
- ced = kzalloc(sizeof(*ced), GFP_KERNEL);
- if (!ced)
- goto error;
-
- for (i = 0; i < MAX_TRANSAREAS; ++i) { /* Initialise the wait queues */
- init_waitqueue_head(&ced->trans_def[i].event);
- }
-
- /* Put initialises for our stuff here. Note that all of *ced is
- * zero, so no need to explicitly zero it. */
- spin_lock_init(&ced->char_out_lock);
- spin_lock_init(&ced->char_in_lock);
- spin_lock_init(&ced->staged_lock);
-
- /* Initialises from the skeleton stuff */
- kref_init(&ced->kref);
- mutex_init(&ced->io_mutex);
- spin_lock_init(&ced->err_lock);
- init_usb_anchor(&ced->submitted);
-
- ced->udev = usb_get_dev(interface_to_usbdev(interface));
- ced->interface = interface;
-
- /* Attempt to identify the device */
- bcdDevice = ced->udev->descriptor.bcdDevice;
- i = (bcdDevice >> 8);
- if (i == 0)
- ced->type = TYPEU1401;
- else if ((i >= 1) && (i <= 23))
- ced->type = i + 2;
- else {
- dev_err(&interface->dev, "%s: Unknown device. bcdDevice = %d\n",
- __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;
- ced->n_pipes = iface_desc->desc.bNumEndpoints;
- dev_info(&interface->dev, "1401Type=%d with %d End Points\n",
- ced->type, ced->n_pipes);
- if ((ced->n_pipes < 3) || (ced->n_pipes > 4))
- goto error;
-
- /* Allocate the URBs we hold for performing transfers */
- ced->urb_char_out = usb_alloc_urb(0, GFP_KERNEL);/* character output
- URB */
- ced->urb_char_in = usb_alloc_urb(0, GFP_KERNEL); /* character input
- URB */
- ced->staged_urb = usb_alloc_urb(0, GFP_KERNEL); /* block transfer URB */
- if (!ced->urb_char_out || !ced->urb_char_in || !ced->staged_urb) {
- dev_err(&interface->dev, "%s: URB alloc failed\n", __func__);
- goto error;
- }
-
- ced->coher_staged_io =
- usb_alloc_coherent(ced->udev, STAGED_SZ, GFP_KERNEL,
- &ced->staged_urb->transfer_dma);
- ced->coher_char_out =
- usb_alloc_coherent(ced->udev, OUTBUF_SZ, GFP_KERNEL,
- &ced->urb_char_out->transfer_dma);
- ced->coher_char_in =
- usb_alloc_coherent(ced->udev, INBUF_SZ, GFP_KERNEL,
- &ced->urb_char_in->transfer_dma);
- if (!ced->coher_char_out || !ced->coher_char_in ||
- !ced->coher_staged_io) {
- dev_err(&interface->dev, "%s: Coherent buffer alloc failed\n",
- __func__);
- goto error;
- }
-
- for (i = 0; i < ced->n_pipes; ++i) {
- endpoint = &iface_desc->endpoint[i].desc;
- ced->ep_addr[i] = endpoint->bEndpointAddress;
- dev_info(&interface->dev, "Pipe %d, ep address %02x\n",
- i, ced->ep_addr[i]);
-
- /* if char input end point */
- if (((ced->n_pipes == 3) && (i == 0)) ||
- ((ced->n_pipes == 4) && (i == 1))) {
- /* save the endpoint interrupt interval */
- ced->interval = endpoint->bInterval;
- dev_info(&interface->dev, "Pipe %d, interval = %d\n",
- i, ced->interval);
- }
- /* Detect USB2 by checking last ep size (64 if USB1) */
- if (i == ced->n_pipes - 1) { /* if this is the last ep (bulk) */
- ced->is_usb2 =
- le16_to_cpu(endpoint->wMaxPacketSize) > 64;
- dev_info(&ced->interface->dev, "USB%d\n",
- ced->is_usb2 + 1);
- }
- }
-
- /* save our data pointer in this interface device */
- usb_set_intfdata(interface, ced);
-
- /* 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\n",
- interface->minor);
- return 0;
-
-error:
- if (ced)
- kref_put(&ced->kref, ced_delete); /* frees allocated memory */
- return retval;
-}
-
-static void ced_disconnect(struct usb_interface *interface)
-{
- struct ced_data *ced = usb_get_intfdata(interface);
- int minor = interface->minor;
- int i;
-
- /* remove the ced from the interface */
- usb_set_intfdata(interface, NULL);
- /* give back our minor device number */
- usb_deregister_dev(interface, &ced_class);
-
- mutex_lock(&ced->io_mutex); /* stop more I/O starting while... */
- ced_draw_down(ced); /* ...wait for then kill any io */
- for (i = 0; i < MAX_TRANSAREAS; ++i) {
- /* ...release any used memory */
- int err = ced_clear_area(ced, i);
-
- if (err == U14ERR_UNLOCKFAIL)
- dev_err(&ced->interface->dev,
- "%s: Area %d was in used\n",
- __func__, i);
- }
- ced->interface = NULL; /* ...we kill off link to interface */
- mutex_unlock(&ced->io_mutex);
-
- usb_kill_anchored_urbs(&ced->submitted);
-
- kref_put(&ced->kref, ced_delete); /* decrement our usage count */
-
- dev_info(&interface->dev, "USB cedusb #%d now disconnected\n", 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(struct ced_data *ced)
-{
- int time;
-
- dev_dbg(&ced->interface->dev, "%s: called\n", __func__);
-
- ced->in_draw_down = true;
- time = usb_wait_anchor_empty_timeout(&ced->submitted, 3000);
- if (!time) { /* if we timed out we kill the urbs */
- usb_kill_anchored_urbs(&ced->submitted);
- dev_err(&ced->interface->dev, "%s: timed out\n", __func__);
- }
- ced->in_draw_down = false;
-}
-
-static int ced_suspend(struct usb_interface *intf, pm_message_t message)
-{
- struct ced_data *ced = usb_get_intfdata(intf);
-
- if (!ced)
- return 0;
- ced_draw_down(ced);
-
- dev_dbg(&ced->interface->dev, "%s: called\n", __func__);
- return 0;
-}
-
-static int ced_resume(struct usb_interface *intf)
-{
- struct ced_data *ced = usb_get_intfdata(intf);
-
- if (!ced)
- return 0;
- dev_dbg(&ced->interface->dev, "%s: called\n", __func__);
- return 0;
-}
-
-static int ced_pre_reset(struct usb_interface *intf)
-{
- struct ced_data *ced = usb_get_intfdata(intf);
-
- dev_dbg(&ced->interface->dev, "%s\n", __func__);
- mutex_lock(&ced->io_mutex);
- ced_draw_down(ced);
- return 0;
-}
-
-static int ced_post_reset(struct usb_interface *intf)
-{
- struct ced_data *ced = usb_get_intfdata(intf);
-
- dev_dbg(&ced->interface->dev, "%s\n", __func__);
-
- /* we are sure no URBs are active - no locking needed */
- ced->errors = -EPIPE;
- mutex_unlock(&ced->io_mutex);
-
- 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,
-};
-
-module_usb_driver(ced_driver);
-MODULE_LICENSE("GPL");
+++ /dev/null
-/* usb1401.h
- Header file for the CED 1401 USB device driver for Linux
- Copyright (C) 2010 Cambridge Electronic Design Ltd
- Author Greg P Smith (greg@ced.co.uk)
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-#ifndef __USB1401_H__
-#define __USB1401_H__
-#include "use1401.h"
-#include "ced_ioctl.h"
-
-#ifndef UINT
-#define UINT unsigned int
-#endif
-
-/** Device type codes, but these don't need to be extended - a succession is assumed
-** These are set for usb from the bcdDevice field (suitably mangled). Future devices
-** will be added in order of device creation to the list, so the names here are just
-** to help use remember which device is which. The U14ERR_... values follow the same
-** pattern for modern devices.a
-**/
-#define TYPEUNKNOWN -1 /* dont know */
-#define TYPE1401 0 /* standard 1401 */
-#define TYPEPLUS 1 /* 1401 plus */
-#define TYPEU1401 2 /* u1401 */
-#define TYPEPOWER 3 /* Power1401 */
-#define TYPEU14012 4 /* u1401 mkII */
-#define TYPEPOWER2 5 /* Power1401 mk II */
-#define TYPEMICRO3 6 /* Micro1401-3 */
-#define TYPEPOWER3 7 /* Power1401-3 */
-
-/* Some useful defines of constants. DONT FORGET to change the version in the */
-/* resources whenever you change it here!. */
-#define DRIVERMAJREV 2 /* driver revision level major (match windows) */
-#define DRIVERMINREV 0 /* driver revision level minor */
-
-/* Definitions of the various block transfer command codes */
-#define TM_EXTTOHOST 8 /* extended tohost */
-#define TM_EXTTO1401 9 /* extended to1401 */
-
-/* Definitions of values in usbReqtype. Used in sorting out setup actions */
-#define H_TO_D 0x00
-#define D_TO_H 0x80
-#define VENDOR 0x40
-#define DEVREQ 0x00
-#define INTREQ 0x01
-#define ENDREQ 0x02
-
-/* Definition of values in usbRequest, again used to sort out setup */
-#define GET_STATUS 0x00
-#define CLEAR_FEATURE 0x01
-#define SET_FEATURE 0x03
-#define SET_ADDRESS 0x05
-#define GET_DESC 0x06
-#define SET_DESC 0x07
-#define GET_CONF 0x08
-#define SET_CONF 0x09
-#define GET_INTERFACE 0x0a
-#define SET_INTERFACE 0x0b
-#define SYNCH_FRAME 0x0c
-
-/* Definitions of the various debug command codes understood by the 1401. These */
-/* are used in various vendor-specific commands to achieve the desired effect */
-#define DB_GRAB 0x50 /* Grab is a NOP for USB */
-#define DB_FREE 0x51 /* Free is a NOP for the USB */
-#define DB_SETADD 0x52 /* Set debug address (double) */
-#define DB_SELFTEST 0x53 /* Start self test */
-#define DB_SETMASK 0x54 /* Set enable mask (double) */
-#define DB_SETDEF 0x55 /* Set default mask (double) */
-#define DB_PEEK 0x56 /* Peek address, save result */
-#define DB_POKE 0x57 /* Poke address with data (double) */
-#define DB_RAMPD 0x58 /* Ramp data at debug address */
-#define DB_RAMPA 0x59 /* Ramp address bus */
-#define DB_REPEATS 0x5A /* Set repeats for operations (double) */
-#define DB_WIDTH 0x5B /* Set width for operations (byte) */
-#define DB_DATA 0x5C /* Get 4-byte data read by PEEK */
-#define DB_CHARS 0x5D /* Send chars via EP0 control write */
-
-#define CR_CHAR 0x0D /* The carriage return character */
-#define CR_CHAR_80 0x8d /* and with bit 7 set */
-
-/* A structure holding information about a block */
-/* of memory for use in circular transfers */
-struct circ_blk {
- volatile UINT offset; /* Offset within area of block start */
- volatile UINT size; /* Size of the block, in bytes (0 = unused) */
-};
-
-/* A structure holding all of the information about a transfer area - an area */
-/* of memory set up for use either as a source or destination in DMA */
-/* transfers. */
-struct transarea {
- /* User address of xfer area saved for completeness */
- void __user *buff;
-
- /* offset to start of xfer area in first page */
- UINT base_offset;
-
- UINT length; /* Length of xfer area, in bytes */
- struct page **pages; /* Points at array of locked down pages */
- int n_pages; /* number of pages that are locked down */
- bool used; /* Is this structure in use? */
- bool circular; /* Is this area for circular transfers? */
- bool circ_to_host; /* Flag for direction of circular transfer */
- bool event_to_host; /* Set event on transfer to host? */
- int wake_up; /* Set 1 on event, cleared by TestEvent() */
- UINT event_st; /* Defines section within xfer area for... */
- UINT event_sz; /* notification by the event SZ is 0 if unset */
- struct circ_blk blocks[2]; /* Info on a pair of circular blocks */
-
- wait_queue_head_t event; /* The wait queue for events in this */
- /* area MUST BE LAST */
-};
-
-/* The dmadesc structure is used to hold information on the transfer in */
-/* progress. It is set up by ReadDMAInfo, using information sent by the 1401 */
-/* in an escape sequence. */
-struct dmadesc {
- unsigned short trans_type; /* transfer type as TM_xxx above */
- unsigned short ident; /* identifier word */
- unsigned int size; /* bytes to transfer */
- unsigned int offset; /* offset into transfer area for trans */
- bool outward; /* true when data is going TO 1401 */
-};
-
-#define INBUF_SZ 256 /* input buffer size */
-#define OUTBUF_SZ 256 /* output buffer size */
-#define STAGED_SZ 0x10000 /* size of coherent buffer for staged transfers */
-
-/* Structure to hold all of our device specific stuff. We are making this as */
-/* similar as we can to the Windows driver to help in our understanding of */
-/* what is going on. */
-struct ced_data {
- char input_buffer[INBUF_SZ]; /* The two buffers */
- char output_buffer[OUTBUF_SZ]; /* accessed by the host functions */
- volatile unsigned int num_input; /* num of chars in input buffer */
- volatile unsigned int in_buff_get; /* where to get from input buffer */
- volatile unsigned int in_buff_put; /* where to put into input buffer */
- volatile unsigned int num_output; /* num of chars in output buffer */
- volatile unsigned int out_buff_get; /* where to get from output buffer*/
- volatile unsigned int out_buff_put; /* where to put into output buffer*/
-
- volatile bool send_chars_pending; /* Flag to indicate sendchar active */
- volatile bool read_chars_pending; /* Flag to indicate a read is primed*/
- char *coher_char_out; /* special aligned buffer for chars to 1401 */
- struct urb *urb_char_out; /* urb used for chars to 1401 */
- char *coher_char_in; /* special aligned buffer for chars to host */
- struct urb *urb_char_in; /* urb used for chars to host */
-
- spinlock_t char_out_lock; /* protect the output_buffer and outputting */
- spinlock_t char_in_lock; /* protect the input_buffer and char reads */
- __u8 interval; /* Interrupt end point interval */
-
- volatile unsigned int dma_flag; /* state of DMA */
- struct transarea trans_def[MAX_TRANSAREAS]; /* transfer area info */
- volatile struct dmadesc dma_info; /* info on current DMA transfer */
- volatile bool xfer_waiting; /* Flag set if DMA transfer stalled */
- volatile bool in_draw_down; /* Flag that we want to halt transfers */
-
- /* Parameters relating to a block read\write that is in progress. Some of these values */
- /* are equivalent to values in dma_info. The values here are those in use, while those */
- /* in dma_info are those received from the 1401 via an escape sequence. If another */
- /* escape sequence arrives before the previous xfer ends, dma_info values are updated while these */
- /* are used to finish off the current transfer. */
- volatile short staged_id; /* The transfer area id for this transfer */
- volatile bool staged_read; /* Flag TRUE for read from 1401, FALSE for write */
- volatile unsigned int staged_length; /* Total length of this transfer */
- volatile unsigned int staged_offset; /* Offset within memory area for transfer start */
- volatile unsigned int staged_done; /* Bytes transferred so far */
- volatile bool staged_urb_pending; /* Flag to indicate active */
- char *coher_staged_io; /* buffer used for block transfers */
- struct urb *staged_urb; /* The URB to use */
- spinlock_t staged_lock; /* protects ReadWriteMem() and */
- /* circular buffer stuff */
-
- short type; /* type of 1401 attached */
- short current_state; /* current error state */
- bool is_usb2; /* type of the interface we connect to */
- bool force_reset; /* Flag to make sure we get a real reset */
- __u32 stat_buf[2]; /* buffer for 1401 state info */
-
- unsigned long self_test_time; /* used to timeout self test */
-
- int n_pipes; /* Should be 3 or 4 depending on 1401 usb chip */
- int pipe_error[4]; /* set non-zero if an error on one of the pipe */
- __u8 ep_addr[4]; /* addresses of the 3/4 end points */
-
- struct usb_device *udev; /* the usb device for this device */
- struct usb_interface *interface; /* the interface for this device, NULL if removed */
- struct usb_anchor submitted; /* in case we need to retract our submissions */
- struct mutex io_mutex; /* synchronize I/O with disconnect, one user-mode caller at a time */
-
- int errors; /* the last request tanked */
- int open_count; /* count the number of openers */
- spinlock_t err_lock; /* lock for errors */
- struct kref kref;
-};
-
-#define to_ced_data(d) container_of(d, struct ced_data, kref)
-
-/* Definitions of routimes used between compilation object files */
-/* in usb1401.c */
-extern int ced_allowi(struct ced_data *ced);
-extern int ced_send_chars(struct ced_data *ced);
-extern void ced_draw_down(struct ced_data *ced);
-extern int ced_read_write_mem(struct ced_data *ced, bool read,
- unsigned short ident, unsigned int offs,
- unsigned int len);
-
-/* in ced_ioc.c */
-extern int ced_clear_area(struct ced_data *ced, int area);
-extern int ced_send_string(struct ced_data *ced, const char __user *data, unsigned int n);
-extern int ced_send_char(struct ced_data *ced, char c);
-extern int ced_get_state(struct ced_data *ced, __u32 *state, __u32 *error);
-extern int ced_read_write_cancel(struct ced_data *ced);
-extern int ced_reset(struct ced_data *ced);
-extern int ced_get_char(struct ced_data *ced);
-extern int ced_get_string(struct ced_data *ced, char __user *user, int n);
-extern int ced_set_transfer(struct ced_data *ced,
- struct transfer_area_desc __user *utd);
-extern int ced_unset_transfer(struct ced_data *ced, int area);
-extern int ced_set_event(struct ced_data *ced,
- struct transfer_event __user *ute);
-extern int ced_stat_1401(struct ced_data *ced);
-extern int ced_line_count(struct ced_data *ced);
-extern int ced_get_out_buf_space(struct ced_data *ced);
-extern int ced_get_transfer(struct ced_data *ced, TGET_TX_BLOCK __user *utx);
-extern int ced_kill_io(struct ced_data *ced);
-extern int ced_state_of_1401(struct ced_data *ced);
-extern int ced_start_self_test(struct ced_data *ced);
-extern int ced_check_self_test(struct ced_data *ced,
- TGET_SELFTEST __user *ugst);
-extern int ced_type_of_1401(struct ced_data *ced);
-extern int ced_transfer_flags(struct ced_data *ced);
-extern int ced_dbg_peek(struct ced_data *ced, TDBGBLOCK __user *udb);
-extern int ced_dbg_poke(struct ced_data *ced, TDBGBLOCK __user *udb);
-extern int ced_dbg_ramp_data(struct ced_data *ced, TDBGBLOCK __user *udb);
-extern int ced_dbg_ramp_addr(struct ced_data *ced, TDBGBLOCK __user *udb);
-extern int ced_dbg_get_data(struct ced_data *ced, TDBGBLOCK __user *udb);
-extern int ced_dbg_stop_loop(struct ced_data *ced);
-extern int ced_set_circular(struct ced_data *ced,
- struct transfer_area_desc __user *utd);
-extern int ced_get_circ_block(struct ced_data *ced, TCIRCBLOCK __user *ucb);
-extern int ced_free_circ_block(struct ced_data *ced, TCIRCBLOCK __user *ucb);
-extern int ced_wait_event(struct ced_data *ced, int area, int time_out);
-extern int ced_test_event(struct ced_data *ced, int area);
-#endif
+++ /dev/null
-/****************************************************************************
-** use1401.h
-** Copyright (C) Cambridge Electronic Design Ltd, 1992-2010
-** Authors: Paul Cox, Tim Bergel, Greg Smith
-** See CVS for revisions.
-**
-** Because the size of a long is different between 32-bit and 64-bit on some
-** systems, we avoid this in this interface.
-****************************************************************************/
-#ifndef __USE1401_H__
-#define __USE1401_H__
-#include "machine.h"
-
-/* Some definitions to make things compatible. If you want to use Use1401 directly */
-/* from a Windows program you should define U14_NOT_DLL, in which case you also */
-/* MUST make sure that your application startup code calls U14InitLib(). */
-/* DLL_USE1401 is defined when you are building the Use1401 dll, not otherwise. */
-#ifdef _IS_WINDOWS_
-#ifndef U14_NOT_DLL
-#ifdef DLL_USE1401
-#define U14API(retType) (retType DllExport __stdcall)
-#else
-#define U14API(retType) (retType DllImport __stdcall)
-#endif
-#endif
-
-#define U14ERRBASE -500
-#define U14LONG long
-#endif
-
-#ifdef LINUX
-#define U14ERRBASE -1000
-#define U14LONG int
-#endif
-
-#ifdef _QT
-#ifndef U14_NOT_DLL
-#undef U14API
-#define U14API(retType) (retType __declspec(dllimport) __stdcall)
-#endif
-#undef U14LONG
-#define U14LONG int
-#endif
-
-#ifndef U14API
-#define U14API(retType) retType
-#endif
-
-#ifndef U14LONG
-#define U14LONG long
-#endif
-
-/* Error codes: We need them here as user space can see them. */
-#define U14ERR_NOERROR 0 /* no problems */
-
-/* Device error codes, but these don't need to be extended - a succession is assumed */
-#define U14ERR_STD 4 /* standard 1401 connected */
-#define U14ERR_U1401 5 /* u1401 connected */
-#define U14ERR_PLUS 6 /* 1401 plus connected */
-#define U14ERR_POWER 7 /* Power1401 connected */
-#define U14ERR_U14012 8 /* u1401 mkII connected */
-#define U14ERR_POWER2 9
-#define U14ERR_U14013 10
-#define U14ERR_POWER3 11
-
-/* NBNB Error numbers need shifting as some linux error codes start at 512 */
-#define U14ERR(n) (n+U14ERRBASE)
-#define U14ERR_OFF U14ERR(0) /* 1401 there but switched off */
-#define U14ERR_NC U14ERR(-1) /* 1401 not connected */
-#define U14ERR_ILL U14ERR(-2) /* if present it is ill */
-#define U14ERR_NOIF U14ERR(-3) /* I/F card missing */
-#define U14ERR_TIME U14ERR(-4) /* 1401 failed to come ready */
-#define U14ERR_BADSW U14ERR(-5) /* I/F card bad switches */
-#define U14ERR_PTIME U14ERR(-6) /* 1401plus failed to come ready */
-#define U14ERR_NOINT U14ERR(-7) /* couldn't grab the int vector */
-#define U14ERR_INUSE U14ERR(-8) /* 1401 is already in use */
-#define U14ERR_NODMA U14ERR(-9) /* couldn't get DMA channel */
-#define U14ERR_BADHAND U14ERR(-10) /* handle provided was bad */
-#define U14ERR_BAD1401NUM U14ERR(-11) /* 1401 number provided was bad */
-
-#define U14ERR_NO_SUCH_FN U14ERR(-20) /* no such function */
-#define U14ERR_NO_SUCH_SUBFN U14ERR(-21) /* no such sub function */
-#define U14ERR_NOOUT U14ERR(-22) /* no room in output buffer */
-#define U14ERR_NOIN U14ERR(-23) /* no input in buffer */
-#define U14ERR_STRLEN U14ERR(-24) /* string longer than buffer */
-#define U14ERR_ERR_STRLEN U14ERR(-24) /* string longer than buffer */
-#define U14ERR_LOCKFAIL U14ERR(-25) /* failed to lock memory */
-#define U14ERR_UNLOCKFAIL U14ERR(-26) /* failed to unlock memory */
-#define U14ERR_ALREADYSET U14ERR(-27) /* area already set up */
-#define U14ERR_NOTSET U14ERR(-28) /* area not set up */
-#define U14ERR_BADAREA U14ERR(-29) /* illegal area number */
-#define U14ERR_FAIL U14ERR(-30) /* we failed for some other reason*/
-
-#define U14ERR_NOFILE U14ERR(-40) /* command file not found */
-#define U14ERR_READERR U14ERR(-41) /* error reading command file */
-#define U14ERR_UNKNOWN U14ERR(-42) /* unknown command */
-#define U14ERR_HOSTSPACE U14ERR(-43) /* not enough host space to load */
-#define U14ERR_LOCKERR U14ERR(-44) /* could not lock resource/command*/
-#define U14ERR_CLOADERR U14ERR(-45) /* CLOAD command failed */
-
-#define U14ERR_TOXXXERR U14ERR(-60) /* tohost/1401 failed */
-#define U14ERR_NO386ENH U14ERR(-80) /* not 386 enhanced mode */
-#define U14ERR_NO1401DRIV U14ERR(-81) /* no device driver */
-#define U14ERR_DRIVTOOOLD U14ERR(-82) /* device driver too old */
-
-#define U14ERR_TIMEOUT U14ERR(-90) /* timeout occurred */
-
-#define U14ERR_BUFF_SMALL U14ERR(-100) /* buffer for getstring too small */
-#define U14ERR_CBALREADY U14ERR(-101) /* there is already a callback */
-#define U14ERR_BADDEREG U14ERR(-102) /* bad parameter to deregcallback */
-#define U14ERR_NOMEMORY U14ERR(-103) /* no memory for allocation */
-
-#define U14ERR_DRIVCOMMS U14ERR(-110) /* failed talking to driver */
-#define U14ERR_OUTOFMEMORY U14ERR(-111) /* needed memory and couldnt get it*/
-
-/* / 1401 type codes. */
-#define U14TYPE1401 0 /* standard 1401 */
-#define U14TYPEPLUS 1 /* 1401 plus */
-#define U14TYPEU1401 2 /* u1401 */
-#define U14TYPEPOWER 3 /* power1401 */
-#define U14TYPEU14012 4 /* u1401 mk II */
-#define U14TYPEPOWER2 5 /* power1401 mk II */
-#define U14TYPEU14013 6 /* u1401-3 */
-#define U14TYPEPOWER3 7 /* power1401-3 */
-#define U14TYPEUNKNOWN -1 /* dont know */
-
-/* Transfer flags to allow driver capabilities to be interrogated */
-
-/* Constants for transfer flags */
-#define U14TF_USEDMA 1 /* Transfer flag for use DMA */
-#define U14TF_MULTIA 2 /* Transfer flag for multi areas */
-#define U14TF_FIFO 4 /* for FIFO interface card */
-#define U14TF_USB2 8 /* for USB2 interface and 1401 */
-#define U14TF_NOTIFY 16 /* for event notifications */
-#define U14TF_SHORT 32 /* for PCI can short cycle */
-#define U14TF_PCI2 64 /* for new PCI card 1401-70 */
-#define U14TF_CIRCTH 128 /* Circular-mode to host */
-#define U14TF_DIAG 256 /* Diagnostics/debug functions */
-#define U14TF_CIRC14 512 /* Circular-mode to 1401 */
-
-/* Definitions of element sizes for DMA transfers - to allow byte-swapping */
-#define ESZBYTES 0 /* BYTE element size value */
-#define ESZWORDS 1 /* unsigned short element size value */
-#define ESZLONGS 2 /* long element size value */
-#define ESZUNKNOWN 0 /* unknown element size value */
-
-/* These define required access types for the debug/diagnostics function */
-#define BYTE_SIZE 1 /* 8-bit access */
-#define WORD_SIZE 2 /* 16-bit access */
-#define LONG_SIZE 3 /* 32-bit access */
-
-/* Stuff used by U14_GetTransfer */
-#define GET_TX_MAXENTRIES 257 /* (max length / page size + 1) */
-
-#ifdef _IS_WINDOWS_
-#pragma pack(1)
-
-typedef struct /* used for U14_GetTransfer results */
-{ /* Info on a single mapped block */
- U14LONG physical;
- U14LONG size;
-} TXENTRY;
-
-typedef struct TGetTxBlock /* used for U14_GetTransfer results */
-{ /* matches structure in VXD */
- U14LONG size;
- U14LONG linear;
- short seg;
- short reserved;
- short avail; /* number of available entries */
- short used; /* number of used entries */
- TXENTRY entries[GET_TX_MAXENTRIES]; /* Array of mapped block info */
-} TGET_TX_BLOCK;
-
-typedef TGET_TX_BLOCK *LPGET_TX_BLOCK;
-
-#pragma pack()
-#endif
-
-#ifdef LINUX
-typedef struct /* used for U14_GetTransfer results */
-{ /* Info on a single mapped block */
- long long physical;
- long size;
-} TXENTRY;
-
-typedef struct TGetTxBlock /* used for U14_GetTransfer results */
-{ /* matches structure in VXD */
- long long linear; /* linear address */
- long size; /* total size of the mapped area, holds id when called */
- short seg; /* segment of the address for Win16 */
- short reserved;
- short avail; /* number of available entries */
- short used; /* number of used entries */
- TXENTRY entries[GET_TX_MAXENTRIES]; /* Array of mapped block info */
-} TGET_TX_BLOCK;
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-U14API(int) U14WhenToTimeOut(short hand); /* when to timeout in ms */
-U14API(short) U14PassedTime(int iTime); /* non-zero if iTime passed */
-
-U14API(short) U14LastErrCode(short hand);
-
-U14API(short) U14Open1401(short n1401);
-U14API(short) U14Close1401(short hand);
-U14API(short) U14Reset1401(short hand);
-U14API(short) U14ForceReset(short hand);
-U14API(short) U14TypeOf1401(short hand);
-U14API(short) U14NameOf1401(short hand, char *pBuf, unsigned short wMax);
-
-U14API(short) U14Stat1401(short hand);
-U14API(short) U14CharCount(short hand);
-U14API(short) U14LineCount(short hand);
-
-U14API(short) U14SendString(short hand, const char *pString);
-U14API(short) U14GetString(short hand, char *pBuffer, unsigned short wMaxLen);
-U14API(short) U14SendChar(short hand, char cChar);
-U14API(short) U14GetChar(short hand, char *pcChar);
-
-U14API(short) U14LdCmd(short hand, const char *command);
-U14API(unsigned int) U14Ld(short hand, const char *vl, const char *str);
-
-U14API(short) U14SetTransArea(short hand, unsigned short wArea, void *pvBuff,
- unsigned int dwLength, short eSz);
-U14API(short) U14UnSetTransfer(short hand, unsigned short wArea);
-U14API(short) U14SetTransferEvent(short hand, unsigned short wArea, BOOL bEvent,
- BOOL bToHost, unsigned int dwStart, unsigned int dwLength);
-U14API(int) U14TestTransferEvent(short hand, unsigned short wArea);
-U14API(int) U14WaitTransferEvent(short hand, unsigned short wArea, int msTimeOut);
-U14API(short) U14GetTransfer(short hand, TGET_TX_BLOCK *pTransBlock);
-
-U14API(short) U14ToHost(short hand, char *pAddrHost, unsigned int dwSize, unsigned int dw1401,
- short eSz);
-U14API(short) U14To1401(short hand, const char *pAddrHost, unsigned int dwSize, unsigned int dw1401,
- short eSz);
-
-U14API(short) U14SetCircular(short hand, unsigned short wArea, BOOL bToHost, void *pvBuff,
- unsigned int dwLength);
-
-U14API(int) U14GetCircBlk(short hand, unsigned short wArea, unsigned int *pdwOffs);
-U14API(int) U14FreeCircBlk(short hand, unsigned short wArea, unsigned int dwOffs, unsigned int dwSize,
- unsigned int *pdwOffs);
-
-U14API(short) U14StrToLongs(const char *pszBuff, U14LONG *palNums, short sMaxLongs);
-U14API(short) U14LongsFrom1401(short hand, U14LONG *palBuff, short sMaxLongs);
-
-U14API(void) U14SetTimeout(short hand, int lTimeout);
-U14API(int) U14GetTimeout(short hand);
-U14API(short) U14OutBufSpace(short hand);
-U14API(int) U14BaseAddr1401(short hand);
-U14API(int) U14DriverVersion(short hand);
-U14API(int) U14DriverType(short hand);
-U14API(short) U14DriverName(short hand, char *pBuf, unsigned short wMax);
-U14API(short) U14GetUserMemorySize(short hand, unsigned int *pMemorySize);
-U14API(short) U14KillIO1401(short hand);
-
-U14API(short) U14BlkTransState(short hand);
-U14API(short) U14StateOf1401(short hand);
-
-U14API(short) U14Grab1401(short hand);
-U14API(short) U14Free1401(short hand);
-U14API(short) U14Peek1401(short hand, unsigned int dwAddr, int nSize, int nRepeats);
-U14API(short) U14Poke1401(short hand, unsigned int dwAddr, unsigned int dwValue, int nSize, int nRepeats);
-U14API(short) U14Ramp1401(short hand, unsigned int dwAddr, unsigned int dwDef, unsigned int dwEnable, int nSize, int nRepeats);
-U14API(short) U14RampAddr(short hand, unsigned int dwDef, unsigned int dwEnable, int nSize, int nRepeats);
-U14API(short) U14StopDebugLoop(short hand);
-U14API(short) U14GetDebugData(short hand, U14LONG *plValue);
-
-U14API(short) U14StartSelfTest(short hand);
-U14API(short) U14CheckSelfTest(short hand, U14LONG *pData);
-U14API(short) U14TransferFlags(short hand);
-U14API(void) U14GetErrorString(short nErr, char *pStr, unsigned short wMax);
-U14API(int) U14MonitorRev(short hand);
-U14API(void) U14CloseAll(void);
-
-U14API(short) U14WorkingSet(unsigned int dwMinKb, unsigned int dwMaxKb);
-U14API(int) U14InitLib(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* End of ifndef __USE1401_H__ */
-
+++ /dev/null
-/* use14_ioc.h
-** definitions of use1401 module stuff that is shared between use1401 and the driver.
-** Copyright (C) Cambridge Electronic Design Limited 2010
-** Author Greg P Smith
-************************************************************************************/
-#ifndef __USE14_IOC_H__
-#define __USE14_IOC_H__
-
-#define MAX_TRANSAREAS 8 /* The number of transfer areas supported by driver */
-
-#define i386
-#include "winioctl.h" /* needed so we can access driver */
-
-/*
-** Defines for IOCTL functions to ask driver to perform. These must be matched
-** in both use1401 and in the driver. The IOCTL code contains a command
-** identifier, plus other information about the device, the type of access
-** with which the file must have been opened, and the type of buffering.
-** The IOCTL function codes from 0x80 to 0xFF are for developer use.
-*/
-#define FILE_DEVICE_CED1401 0x8001
- FNNUMBASE 0x800
-
-#define U14_OPEN1401 CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_CLOSE1401 CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+1, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_SENDSTRING CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+2, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_RESET1401 CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+3, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_GETCHAR CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+4, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_SENDCHAR CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+5, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_STAT1401 CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+6, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_LINECOUNT CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+7, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_GETSTRING CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+8, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_REGCALLBACK CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+9, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_GETMONITORBUF CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+10, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_SETTRANSFER CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+11, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_UNSETTRANSFER CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+12, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_SETTRANSEVENT CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+13, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_GETOUTBUFSPACE CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+14, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_GETBASEADDRESS CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+15, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_GETDRIVERREVISION CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+16, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_GETTRANSFER CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+17, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_KILLIO1401 CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+18, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_BLKTRANSSTATE CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+19, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_BYTECOUNT CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+20, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_ZEROBLOCKCOUNT CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+21, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_STOPCIRCULAR CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+22, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_STATEOF1401 CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+23, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_REGISTERS1401 CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+24, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_GRAB1401 CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+25, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_FREE1401 CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+26, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_STEP1401 CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+27, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_SET1401REGISTERS CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+28, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_STEPTILL1401 CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+29, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_SETORIN CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+30, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_STARTSELFTEST CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+31, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_CHECKSELFTEST CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+32, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_TYPEOF1401 CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+33, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_TRANSFERFLAGS CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+34, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_DBGPEEK CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+35, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_DBGPOKE CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+36, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_DBGRAMPDATA CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+37, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_DBGRAMPADDR CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+38, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_DBGGETDATA CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+39, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_DBGSTOPLOOP CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+40, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_FULLRESET CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+41, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_SETCIRCULAR CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+42, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_GETCIRCBLK CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+43, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-#define U14_FREECIRCBLK CTL_CODE(FILE_DEVICE_CED1401, \
- FNNUMBASE+44, \
- METHOD_BUFFERED, \
- FILE_ANY_ACCESS)
-
-/*--------------- Structures that are shared with the driver ------------- */
-#pragma pack(1)
-
-typedef struct /* used for get/set standard 1401 registers */
-{
- short sPC;
- char A;
- char X;
- char Y;
- char stat;
- char rubbish;
-} T1401REGISTERS;
-
-typedef union /* to communicate with 1401 driver status & control funcs */
-{
- char chrs[22];
- short ints[11];
- long longs[5];
- T1401REGISTERS registers;
-} TCSBLOCK;
-
-typedef TCSBLOCK* LPTCSBLOCK;
-
-typedef struct paramBlk {
- short sState;
- TCSBLOCK csBlock;
-} PARAMBLK;
-
-typedef PARAMBLK* PPARAMBLK;
-
-struct transfer_area_desc /* Structure and type for SetTransArea */
-{
- unsigned short wArea; /* number of transfer area to set up */
- void FAR *lpvBuff; /* address of transfer area */
- unsigned int dwLength; /* length of area to set up */
- short eSize; /* size to move (for swapping on MAC) */
-};
-
-
-/* This is the structure used to set up a transfer area */
-typedef struct VXTransferDesc /* use1401.c and use1432x.x use only */
-{
- unsigned short wArea; /* number of transfer area to set up */
- unsigned short wAddrSel; /* 16 bit selector for area */
- unsigned int dwAddrOfs; /* 32 bit offset for area start */
- unsigned int dwLength; /* length of area to set up */
-} VXTRANSFERDESC;
-
-#pragma pack()
-
-#endif
+++ /dev/null
-/****************************************************************************
-** use1401.c
-** Copyright (C) Cambridge Electronic Design Ltd, 1992-2010
-**
-** 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.
-**
-** Contact CED: Cambridge Electronic Design Limited, Science Park, Milton Road
-** Cambridge, CB6 0FE.
-** www.ced.co.uk
-** greg@ced.co.uk
-**
-** Title: USE1401.C
-** Version: 4.00
-** Author: Paul Cox, Tim Bergel, Greg Smith
-**
-** The code was vigorously pruned in DEC 2010 to remove the macintosh options
-** and to get rid of the 16-bit support. It has also been aligned with the
-** Linux version. See CVS for revisions. This will work for Win 9x onwards.
-****************************************************************************
-**
-** Notes on Windows interface to driver
-** ************************************
-**
-** Under Windows 9x and NT, Use1401 uses DeviceIoControl to get access to
-** the 1401 driver. This has parameters for the device handle, the function
-** code, an input pointer and byte count, an output pointer and byte count
-** and a pointer to a unsigned int to hold the output byte count. Note that input
-** and output are from the point-of-view of the driver, so the output stuff
-** is used to read values from the 1401, not send to the 1401. The use of
-** these parameters varies with the function in use and the operating
-** system; there are five separate DIOC calls SendString, GetString and
-** SetTransferArea all have their own specialised calls, the rest use the
-** Status1401 or Control1401 functions.
-**
-** There are two basic styles of DIOC call used, one for Win9x VxD drivers
-** and one for NT Kernel-mode and WDM drivers (see below for tables showing
-** the different parameters used. The array bUseNTDIOC[] selects between
-** these two calling styles.
-**
-** Function codes
-** In Win3.x, simple function codes from 0 to 40 were used, shifted left 8
-** bits with a sub-function code in the lower 8 bits. These were also used
-** in the Windows 95 driver, though we had to add 1 to the code value to
-** avoid problems (Open from CreateFile is zero), and the sub-function code
-** is now unused. We found that this gave some problems with Windows 98
-** as the function code values are reserved by microsoft, so we switched to
-** using the NT function codes instead. The NT codes are generated using the
-** CTL_CODE macro, essentially this gives 0x80012000 | (func << 2), where
-** func is the original 0 to 34 value. The driver will handle both types of
-** code and Use1432 only uses the NT codes if it knows the driver is new
-** enough. The array bUseNTCodes[] holds flags on the type of codes required.
-** GPS/TDB Dec 2010: we removed the bUseNTCodes array as this is always true
-** as we no longer support ancient versions.
-**
-** The CreateFile and CloseFile function calls are also handled
-** by DIOC, using the special function codes 0 and -1 respectively.
-**
-** Input pointer and buffer size
-** These are intended for data sent to the device driver. In nearly all cases
-** they are unused in calls to the Win95 driver, the NT driver uses them
-** for all information sent to the driver. The table below shows the pointer
-** and byte count used for the various calls:
-**
-** Win 95 Win NT
-** SendString NULL, 0 pStr, nStr
-** GetString NULL, 0 NULL, 0
-** SetTransferArea pBuf, nBuf (unused?) pDesc, nDesc
-** GetTransfer NULL, 0 NULL, 0
-** Status1401 NULL, 0 NULL, 0
-** Control1401 NULL, 0 pBlk, nBlk
-**
-** pStr and nStr are pointers to a char buffer and the buffer length for
-** string I/O, note that these are temporary buffers owned by the DLL, not
-** application memory, pBuf and nBuf are the transfer area buffer (I think
-** these are unused), pDesc and nDesc are the TRANSFERDESC structure, pBlk
-** and nBlk are the TCSBLOCK structure.
-**
-**
-** Output pointer and buffer size
-** These are intended for data read from the device driver. These are used
-** for almost all information sent to the Win95 driver, the NT driver uses
-** them for information read from the driver, chiefly the error code. The
-** table below shows the pointer and byte count used for the various calls:
-**
-** Win 95 Win NT
-** SendString pStr, nStr pPar, nPar
-** GetString pStr, nStr+2 pStr, nStr+2
-** SetTransferArea pDesc, nDesc pPar, nPar
-** GetTransfer pGet, nGet pGet, nGet
-** Status1401 pBlk, nBlk pPar, nPar
-** Control1401 pBlk, nBlk pPar, nPar
-**
-** pStr and nStr are pointers to a char buffer and the buffer length for
-** string I/O, the +2 for GetString refers to two spare bytes at the start
-** used to hold the string length and returning an error code for NT. Note
-** again that these are (and must be) DLL-owned temporary buffers. pPar
-** and nPar are a PARAM structure used in NT (it holds an error code and a
-** TCSBLOCK structure). pDesc and nDesc are the VXTRANSFERDESC structure,
-** pBlk and nBlk are the TCSBLOCK structure. pGet and nGet indicate the
-** TGET_TX_BLOCK structure used for GetTransfer.
-**
-**
-** The output byte count
-** Both drivers return the output buffer size here, regardless of the actual
-** bytes output. This is used to check that we did get through to the driver.
-**
-** Multiple 1401s
-** **************
-**
-** We have code that tries to support the use of multiple 1401s, but there
-** are problems: The lDriverVersion and lDriverType variables are global, not
-** per-1401 (a particular problem as the U14 functions that use them don't
-** have a hand parameter). In addition, the mechansim for finding a free
-** 1401 depends upon the 1401 device driver open operation failing if it's
-** already in use, which doesn't always happen, particularly with the VxDs.
-** The code in TryToOpen tries to fix this by relying on TYPEOF1401 to detect
-** the 1401-in-use state - the VxDs contain special code to help this. This is
-** working OK but multiple 1401 support works better with the Win2000 drivers.
-**
-** USB driver
-** **********
-**
-** The USB driver, which runs on both Win98 and NT2000, uses the NT-style
-** calling convention, both for the DIOC codes and the DIOC parameters. The
-** TryToOpen function has been altered to look for an NT driver first in
-** the appropriate circumstances, and to set the driver DIOC flags up in
-** the correct state.
-**
-** Adding a new 1401 type - now almost nothing to do
-** *************************************************
-**
-** The 1401 types are defined by a set of U14TYPExxxx codes in USE1401.H.
-** You should add a new one of these to keep things tidy for applications.
-**
-** DRIVERET_MAX (below) specifies the maximum allowed type code from the
-** 1401 driver; I have set this high to accommodate as yet undesigned 1401
-** types. Similarly, as long as the command file names follow the ARM,
-** ARN, ARO sequence, these are calculated by the ExtForType function, so
-** you don't need to do anything here either.
-**
-** Version number
-** **************
-** The new U14InitLib() function returns 0 if the OS is incapable of use,
-** otherwise is returns the version of the USE1401 library. This is done
-** in three parts: Major(31-24).Minor(23-16).Revision.(15-0) (brackets are
-** the bits used). The Major number starts at 2 for the first revision with
-** the U14InitLib() function. Changes to the Major version means that we
-** have broken backwards compatibility. Minor number changes mean that we
-** have added new functionality that does not break backwards compatibility.
-** we starts at 0. Revision changes mean we have fixed something. Each index
-** returns to 0 when a higher one changes.
-*/
-#define U14LIB_MAJOR 4
-#define U14LIB_MINOR 0
-#define U14LIB_REVISION 0
-#define U14LIB_VERSION ((U14LIB_MAJOR<<24) | (U14LIB_MINOR<<16) | U14LIB_REVISION)
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "USE1401.H"
-
-#ifdef _IS_WINDOWS_
-#include <io.h>
-#include <windows.h>
-#pragma warning(disable: 4100) /* Disable "Unused formal parameter" warning */
-#include <assert.h>
-#include "process.h"
-
-
-#define sprintf wsprintf
-#define PATHSEP '\\'
-#define PATHSEPSTR "\\"
-#define DEFCMDPATH "\\1401\\" // default command path if all else fails
-#define MINDRIVERMAJREV 1 // minimum driver revision level we need
-#define __packed // does nothing in Windows
-
-#include "use14_ioc.h" // links to device driver stuff
-#endif
-
-#ifdef LINUX
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <sched.h>
-#include <libgen.h>
-#define PATHSEP '/'
-#define PATHSEPSTR "/"
-#define DEFCMDPATH "/var/1401/" // default command path if all else fails
-#define MINDRIVERMAJREV 2 // minimum driver revision level we need
-
-#include "ced_ioctl.h" // links to device driver stuff
-#endif
-
-#define MAX1401 8 // The number of 1401s that can be supported
-
-/*
-** These are the 1401 type codes returned by the driver, they are a slightly
-** odd sequence & start for reasons of compatibility with the DOS driver.
-** The maximum code value is the upper limit of 1401 device types.
-*/
-#define DRIVRET_STD 4 // Codes for 1401 types matching driver values
-#define DRIVRET_U1401 5 // This table does not need extending, as
-#define DRIVRET_PLUS 6 // we can calculate values now.
-#define DRIVRET_POWER 7 // but we need all of these values still
-#define DRIVRET_MAX 26 // Maximum tolerated code - future designs
-
-/*
-** These variables store data that will be used to generate the last
-** error string. For now, a string will hold the 1401 command file name.
-*/
-static char szLastName[20]; // additional text information
-
-/*
-** Information stored per handle. NBNB, driverType and DriverVersion used to be
-** only stored once for all handles... i.e. nonsensical. This change means that
-** three U14...() calls now include handles that were previously void. We have
-** set a constructor and a destructor call for the library (see the end) to
-** initialise important structures, or call use1401_load().
-*/
-static short asDriverType[MAX1401] = {0};
-static int lLastDriverVersion = U14ERR_NO1401DRIV;
-static int lLastDriverType = U14TYPEUNKNOWN;
-static int alDriverVersion[MAX1401]; // version/type of each driver
-static int alTimeOutPeriod[MAX1401]; // timeout time in milliseconds
-static short asLastRetCode[MAX1401]; // last code from a fn call
-static short asType1401[MAX1401] = {0}; // The type of the 1401
-static BOOL abGrabbed[MAX1401] = {0}; // Flag for grabbed, set true by grab1401
-static int iAttached = 0; // counts process attaches so can let go
-
-#ifdef _IS_WINDOWS_
-/****************************************************************************
-** Windows NT Specific Variables and internal types
-****************************************************************************/
-static HANDLE aHand1401[MAX1401] = {0}; // handles for 1401s
-static HANDLE aXferEvent[MAX1401] = {0}; // transfer events for the 1401s
-static LPVOID apAreas[MAX1401][MAX_TRANSAREAS]; // Locked areas
-static unsigned int auAreas[MAX1401][MAX_TRANSAREAS]; // Size of locked areas
-static BOOL bWindows9x = FALSE; // if we are Windows 95 or better
-#ifdef _WIN64
-#define USE_NT_DIOC(ind) TRUE
-#else
-static BOOL abUseNTDIOC[MAX1401]; // Use NT-style DIOC parameters */
-#define USE_NT_DIOC(ind) abUseNTDIOC[ind]
-#endif
-
-#endif
-
-#ifdef LINUX
-static int aHand1401[MAX1401] = {0}; // handles for 1401s
-#define INVALID_HANDLE_VALUE 0 // to avoid code differences
-#endif
-
-
-/*
-** The CmdHead relates to backwards compatibility with ancient Microsoft (and Sperry!)
-** versions of BASIC, where this header was needed so we could load a command into
-** memory.
-*/
-#pragma pack(1) // pack our structure
-typedef struct CmdHead // defines header block on command
-{ // for PC commands
- char acBasic[5]; // BASIC information - needed to align things
- unsigned short wBasicSz; // size as seen by BASIC
- unsigned short wCmdSize; // size of the following info
-} __packed CMDHEAD;
-#pragma pack() // back to normal
-
-/*
-** The rest of the header looks like this...
-** int iRelPnt; relocation pointer... actual start
-** char acName[8]; string holding the command name
-** BYTE bMonRev; monitor revision level
-** BYTE bCmdRev; command revision level
-*/
-
-typedef CMDHEAD *LPCMDHEAD; // pointer to a command header
-
-#define MAXSTRLEN 255 // maximum string length we use
-#define TOHOST FALSE
-#define TO1401 TRUE
-
-static short CheckHandle(short h)
-{
- if ((h < 0) || (h >= MAX1401)) // must be legal range...
- return U14ERR_BADHAND;
- if (aHand1401[h] <= 0) // must be open
- return U14ERR_BADHAND;
- return U14ERR_NOERROR;
-}
-
-#ifdef _IS_WINDOWS_
-/****************************************************************************
-** U14Status1401 Used for functions which do not pass any data in but
-** get data back
-****************************************************************************/
-static short U14Status1401(short sHand, LONG lCode, TCSBLOCK* pBlk)
-{
- unsigned int dwBytes = 0;
-
- if ((sHand < 0) || (sHand >= MAX1401)) /* Check parameters */
- return U14ERR_BADHAND;
-#ifndef _WIN64
- if (!USE_NT_DIOC(sHand))
- { /* Windows 9x DIOC methods? */
- if (DeviceIoControl(aHand1401[sHand], lCode, NULL, 0, pBlk,sizeof(TCSBLOCK),&dwBytes,NULL))
- return (short)((dwBytes>=sizeof(TCSBLOCK)) ? U14ERR_NOERROR : U14ERR_DRIVCOMMS);
- else
- return (short)GetLastError();
- }
- else
-#endif
- { /* Windows NT or USB driver */
- PARAMBLK rWork;
- rWork.sState = U14ERR_DRIVCOMMS;
- if (DeviceIoControl(aHand1401[sHand], lCode, NULL, 0, &rWork,sizeof(PARAMBLK),&dwBytes,NULL) &&
- (dwBytes >= sizeof(PARAMBLK)))
- {
- *pBlk = rWork.csBlock;
- return rWork.sState;
- }
- }
-
- return U14ERR_DRIVCOMMS;
-}
-
-/****************************************************************************
-** U14Control1401 Used for functions which pass data in and only expect
-** an error code back
-****************************************************************************/
-static short U14Control1401(short sHand, LONG lCode, TCSBLOCK* pBlk)
-{
- unsigned int dwBytes = 0;
-
- if ((sHand < 0) || (sHand >= MAX1401)) /* Check parameters */
- return U14ERR_BADHAND;
-
-#ifndef _WIN64
- if (!USE_NT_DIOC(sHand))
- { /* Windows 9x DIOC methods */
- if (DeviceIoControl(aHand1401[sHand], lCode, NULL, 0, pBlk, sizeof(TCSBLOCK), &dwBytes, NULL))
- return (short)(dwBytes >= sizeof(TCSBLOCK) ? U14ERR_NOERROR : U14ERR_DRIVCOMMS);
- else
- return (short)GetLastError();
- }
- else
-#endif
- { /* Windows NT or later */
- PARAMBLK rWork;
- rWork.sState = U14ERR_DRIVCOMMS;
- if (DeviceIoControl(aHand1401[sHand], lCode, pBlk, sizeof(TCSBLOCK), &rWork, sizeof(PARAMBLK), &dwBytes, NULL) &&
- (dwBytes >= sizeof(PARAMBLK)))
- return rWork.sState;
- }
-
- return U14ERR_DRIVCOMMS;
-}
-#endif
-
-/****************************************************************************
-** SafeTickCount
-** Gets time in approximately units of a millisecond.
-*****************************************************************************/
-static long SafeTickCount(void)
-{
-#ifdef _IS_WINDOWS_
- return GetTickCount();
-#endif
-#ifdef LINUX
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return (tv.tv_sec*1000 + tv.tv_usec/1000);
-#endif
-}
-
-/****************************************************************************
-** A utility routine to get the command file extension for a given type
-** of 1401. We assume the type code is vaguely legal.
-****************************************************************************/
-static int ExtForType(short sType, char* szExt)
-{
- szExt[0] = 0; /* Default return is a blank string */
- switch (sType)
- {
- case U14TYPE1401: strcpy(szExt, ".CMD"); break; // Standard 1401
- case U14TYPEPLUS: strcpy(szExt, ".GXC"); break; // 1401 plus
- default: // All others are in a predictable sequence
- strcpy(szExt, ".ARM");
- szExt[3] = (char)('M' + sType - U14TYPEU1401);
- if (szExt[3] > 'Z') // Wrap round to ARA after ARZ
- szExt[3] = (char)(szExt[3] - 26);
- }
- return 0;
-}
-
-/****************************************************************************
-** U14WhenToTimeOut
-** Returns the time to time out in time units suitable for the machine
-** we are running on ie millsecs for pc/linux, or Mac/
-****************************************************************************/
-U14API(int) U14WhenToTimeOut(short hand)
-{
- int iNow = SafeTickCount();
- if ((hand >= 0) && (hand < MAX1401))
- iNow += alTimeOutPeriod[hand];
- return iNow;
-}
-
-/****************************************************************************
-** U14PassedTime
-** Returns non zero if the timed passed in has been passed 0 if not
-****************************************************************************/
-U14API(short) U14PassedTime(int lCheckTime)
-{
- return (short)((SafeTickCount()-lCheckTime) > 0);
-}
-
-/****************************************************************************
-** TranslateString
-** Tidies up string that U14GetString returns. Converts all the commas in a
-** string to spaces. Removes terminating CR character. May do more in future.
-****************************************************************************/
-static void TranslateString(char* pStr)
-{
- int i = 0;
- while (pStr[i])
- {
- if (pStr[i] == ',')
- pStr[i] = ' '; /* convert comma to space */
- ++i;
- }
-
- if ((i > 0) && (pStr[i-1] == '\n')) /* kill terminating LF */
- pStr[i-1] = (char)0;
-}
-
-/****************************************************************************
-** U14StrToLongs
-** Converts a string to an array of longs and returns the number of values
-****************************************************************************/
-U14API(short) U14StrToLongs(const char* pszBuff, U14LONG *palNums, short sMaxLongs)
-{
- unsigned short wChInd = 0; // index into source
- short sLgInd = 0; // index into result longs
-
- while (pszBuff[wChInd] && // until we get to end of string...
- (sLgInd < sMaxLongs)) // ...or filled the buffer
- {
- // Why not use a C Library converter?
- switch (pszBuff[wChInd])
- {
- case '-':
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- {
- BOOL bDone = FALSE; // true at end of number
- int iSign = 1; // sign of number
- long lValue = 0;
-
- while ((!bDone) && pszBuff[wChInd])
- {
- switch (pszBuff[wChInd])
- {
- case '-':
- iSign = -1; // swap sign
- break;
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- lValue *= 10; // move to next digit base 10
- lValue += ((int)pszBuff[wChInd]-(int)'0');
- break;
-
- default: // end of number
- bDone = TRUE;
- break;
- }
- wChInd++; // move onto next character
- }
- palNums[sLgInd] = lValue * iSign;
- sLgInd++;
- }
- break;
-
- default:
- wChInd++; // look at next char
- break;
- }
- }
- return (sLgInd);
-}
-
-
-/****************************************************************************
-** U14LongsFrom1401
-** Gets the next waiting line from the 1401 and converts it longs
-** Returns the number of numbers read or an error.
-****************************************************************************/
-U14API(short) U14LongsFrom1401(short hand, U14LONG *palBuff, short sMaxLongs)
-{
- char szWork[MAXSTRLEN];
- short sResult = U14GetString(hand, szWork, MAXSTRLEN);/* get reply from 1401 */
- if (sResult == U14ERR_NOERROR) /* if no error convert */
- sResult = U14StrToLongs(szWork, palBuff, sMaxLongs);
- return sResult;
-}
-
-/****************************************************************************
-** U14CheckErr
-** Sends the ERR command to the 1401 and gets the result. Returns 0, a
-** negative error code, or the first error value.
-****************************************************************************/
-U14API(short) U14CheckErr(short hand)
-{
- short sResult = U14SendString(hand, ";ERR;");
- if (sResult == U14ERR_NOERROR)
- {
- U14LONG er[3];
- sResult = U14LongsFrom1401(hand, er, 3);
- if (sResult > 0)
- {
- sResult = (short)er[0]; /* Either zero or an error value */
-#ifdef _DEBUG
- if (er[0] != 0)
- {
- char szMsg[50];
- sprintf(szMsg, "U14CheckErr returned %d,%d\n", er[0], er[1]);
- OutputDebugString(szMsg);
- }
-#endif
- }
- else
- {
- if (sResult == 0)
- sResult = U14ERR_TIMEOUT; /* No numbers equals timeout */
- }
- }
-
- return sResult;
-}
-
-/****************************************************************************
-** U14LastErrCode
-** Returns the last code from the driver. This is for Windows where all calls
-** go through the Control and Status routines, so we can save any error.
-****************************************************************************/
-U14API(short) U14LastErrCode(short hand)
-{
- if ((hand < 0) || (hand >= MAX1401))
- return U14ERR_BADHAND;
- return asLastRetCode[hand];
-}
-
-/****************************************************************************
-** U14SetTimeout
-** Set the timeout period for 1401 comms in milliseconds
-****************************************************************************/
-U14API(void) U14SetTimeout(short hand, int lTimeOut)
-{
- if ((hand < 0) || (hand >= MAX1401))
- return;
- alTimeOutPeriod[hand] = lTimeOut;
-}
-
-/****************************************************************************
-** U14GetTimeout
-** Get the timeout period for 1401 comms in milliseconds
-****************************************************************************/
-U14API(int) U14GetTimeout(short hand)
-{
- if ((hand < 0) || (hand >= MAX1401))
- return U14ERR_BADHAND;
- return alTimeOutPeriod[hand];
-}
-
-/****************************************************************************
-** U14OutBufSpace
-** Return the space in the output buffer, or an error.
-****************************************************************************/
-U14API(short) U14OutBufSpace(short hand)
-{
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- short sErr = U14Status1401(hand, U14_GETOUTBUFSPACE,&csBlock);
- if (sErr == U14ERR_NOERROR)
- sErr = csBlock.ints[0];
- return sErr;
-#endif
-#ifdef LINUX
- short sErr = CheckHandle(hand);
- return (sErr == U14ERR_NOERROR) ? CED_GetOutBufSpace(aHand1401[hand]) : sErr;
-#endif
-}
-
-
-/****************************************************************************
-** U14BaseAddr1401
-** Returns the 1401 base address or an error code. Meaningless nowadays
-****************************************************************************/
-U14API(int) U14BaseAddr1401(short hand)
-{
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- int iError = U14Status1401(hand, U14_GETBASEADDRESS,&csBlock);
- if (iError == U14ERR_NOERROR)
- iError = csBlock.longs[0];
- return iError;
-#endif
-#ifdef LINUX
- short sErr = CheckHandle(hand);
- return (sErr == U14ERR_NOERROR) ? CED_GetBaseAddress(aHand1401[hand]) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14StateOf1401
-** Return error state, either NOERROR or a negative code.
-****************************************************************************/
-U14API(short) U14StateOf1401(short hand)
-{
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- short sErr = U14Status1401(hand, U14_STATEOF1401, &csBlock);
- if (sErr == U14ERR_NOERROR)
- {
- sErr = csBlock.ints[0]; // returned 1401 state
- if ((sErr >= DRIVRET_STD) && (sErr <= DRIVRET_MAX))
- sErr = U14ERR_NOERROR;
- }
-#endif
-#ifdef LINUX
- short sErr = CheckHandle(hand);
- if (sErr == U14ERR_NOERROR)
- {
- sErr = (short)CED_StateOf1401(aHand1401[hand]);
- if ((sErr >= DRIVRET_STD) && (sErr <= DRIVRET_MAX))
- sErr = U14ERR_NOERROR;
- }
-#endif
- return sErr;
-}
-
-/****************************************************************************
-** U14DriverVersion
-** Returns the driver version. Hi word is major revision, low word is minor.
-** If you pass in a silly handle (like -1), we return the version of the last
-** driver we know of (to cope with PCI and no 1401 attached).
-****************************************************************************/
-U14API(int) U14DriverVersion(short hand)
-{
- return CheckHandle(hand) != U14ERR_NOERROR ? lLastDriverVersion : alDriverVersion[hand];
-}
-
-/****************************************************************************
-** U14DriverType
-** Returns the driver type. The type, 0=ISA/NU-Bus, 1=PCI, 2=USB, 3=HSS
-** If you pass in a silly handle (like -1), we return the type of the last
-** driver we know of (to cope with PCI and no 1401 attached).
-****************************************************************************/
-U14API(int) U14DriverType(short hand)
-{
- return CheckHandle(hand) != U14ERR_NOERROR ? lLastDriverType : asDriverType[hand];
-}
-
-/****************************************************************************
-** U14DriverName
-** Returns the driver type as 3 character (ISA, PCI, USB or HSS))
-****************************************************************************/
-U14API(short) U14DriverName(short hand, char* pBuf, unsigned short wMax)
-{
- char* pName;
- *pBuf = 0; // Start off with a blank string
- switch (U14DriverType(hand)) // Results according to type
- {
- case 0: pName = "ISA"; break;
- case 1: pName = "PCI"; break;
- case 2: pName = "USB"; break;
- case 3: pName = "HSS"; break;
- default: pName = "???"; break;
- }
- strncpy(pBuf, pName, wMax); // Copy the correct name to return
-
- return U14ERR_NOERROR;
-}
-
-/****************************************************************************
-** U14BlkTransState
-** Returns 0 no transfer in progress, 1 transfer in progress or an error code
-****************************************************************************/
-U14API(short) U14BlkTransState(short hand)
-{
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- short sErr = U14Status1401(hand, U14_BLKTRANSSTATE, &csBlock);
- if (sErr == U14ERR_NOERROR)
- sErr = csBlock.ints[0];
- return sErr;
-#endif
-#ifdef LINUX
- short sErr = CheckHandle(hand);
- return (sErr == U14ERR_NOERROR) ? CED_BlkTransState(aHand1401[hand]) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14Grab1401
-** Take control of the 1401 for diagnostics purposes. USB does nothing.
-****************************************************************************/
-U14API(short) U14Grab1401(short hand)
-{
- short sErr = CheckHandle(hand);
- if (sErr == U14ERR_NOERROR)
- {
-#ifdef _IS_WINDOWS_
- if (abGrabbed[hand]) // 1401 should not have been grabbed
- sErr = U14ERR_ALREADYSET; // Error code defined for this
- else
- {
- TCSBLOCK csBlock;
- sErr = U14Control1401(hand, U14_GRAB1401, &csBlock);
- }
-#endif
-#ifdef LINUX
- // 1401 should not have been grabbed
- sErr = abGrabbed[hand] ? U14ERR_ALREADYSET : CED_Grab1401(aHand1401[hand]);
-#endif
- if (sErr == U14ERR_NOERROR)
- abGrabbed[hand] = TRUE;
- }
- return sErr;
-}
-
-/****************************************************************************
-** U14Free1401
-****************************************************************************/
-U14API(short) U14Free1401(short hand)
-{
- short sErr = CheckHandle(hand);
- if (sErr == U14ERR_NOERROR)
- {
-#ifdef _IS_WINDOWS_
- if (abGrabbed[hand]) // 1401 should have been grabbed
- {
- TCSBLOCK csBlock;
- sErr = U14Control1401(hand, U14_FREE1401, &csBlock);
- }
- else
- sErr = U14ERR_NOTSET;
-#endif
-#ifdef LINUX
- // 1401 should not have been grabbed
- sErr = abGrabbed[hand] ? CED_Free1401(aHand1401[hand]) : U14ERR_NOTSET;
-#endif
- if (sErr == U14ERR_NOERROR)
- abGrabbed[hand] = FALSE;
- }
- return sErr;
-}
-
-/****************************************************************************
-** U14Peek1401
-** DESCRIPTION Cause the 1401 to do one or more peek operations.
-** If lRepeats is zero, the loop will continue until U14StopDebugLoop
-** is called. After the peek is done, use U14GetDebugData to retrieve
-** the results of the peek.
-****************************************************************************/
-U14API(short) U14Peek1401(short hand, unsigned int dwAddr, int nSize, int nRepeats)
-{
- short sErr = CheckHandle(hand);
- if (sErr == U14ERR_NOERROR)
- {
- if (abGrabbed[hand]) // 1401 should have been grabbed
- {
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- csBlock.longs[0] = (long)dwAddr;
- csBlock.longs[1] = nSize;
- csBlock.longs[2] = nRepeats;
- sErr = U14Control1401(hand, U14_DBGPEEK, &csBlock);
-#endif
-#ifdef LINUX
- TDBGBLOCK dbb;
- dbb.iAddr = (int)dwAddr;
- dbb.iWidth = nSize;
- dbb.iRepeats = nRepeats;
- sErr = CED_DbgPeek(aHand1401[hand], &dbb);
-#endif
- }
- else
- sErr = U14ERR_NOTSET;
- }
- return sErr;
-}
-
-/****************************************************************************
-** U14Poke1401
-** DESCRIPTION Cause the 1401 to do one or more poke operations.
-** If lRepeats is zero, the loop will continue until U14StopDebugLoop
-** is called.
-****************************************************************************/
-U14API(short) U14Poke1401(short hand, unsigned int dwAddr, unsigned int dwValue,
- int nSize, int nRepeats)
-{
- short sErr = CheckHandle(hand);
- if (sErr == U14ERR_NOERROR)
- {
- if (abGrabbed[hand]) // 1401 should have been grabbed
- {
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- csBlock.longs[0] = (long)dwAddr;
- csBlock.longs[1] = nSize;
- csBlock.longs[2] = nRepeats;
- csBlock.longs[3] = (long)dwValue;
- sErr = U14Control1401(hand, U14_DBGPOKE, &csBlock);
-#endif
-#ifdef LINUX
- TDBGBLOCK dbb;
- dbb.iAddr = (int)dwAddr;
- dbb.iWidth = nSize;
- dbb.iRepeats= nRepeats;
- dbb.iData = (int)dwValue;
- sErr = CED_DbgPoke(aHand1401[hand], &dbb);
-#endif
- }
- else
- sErr = U14ERR_NOTSET;
- }
- return sErr;
-}
-
-/****************************************************************************
-** U14Ramp1401
-** DESCRIPTION Cause the 1401 to loop, writing a ramp to a location.
-** If lRepeats is zero, the loop will continue until U14StopDebugLoop.
-****************************************************************************/
-U14API(short) U14Ramp1401(short hand, unsigned int dwAddr, unsigned int dwDef, unsigned int dwEnable,
- int nSize, int nRepeats)
-{
- short sErr = CheckHandle(hand);
- if (sErr == U14ERR_NOERROR)
- {
- if (abGrabbed[hand]) // 1401 should have been grabbed
- {
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- csBlock.longs[0] = (long)dwAddr;
- csBlock.longs[1] = (long)dwDef;
- csBlock.longs[2] = (long)dwEnable;
- csBlock.longs[3] = nSize;
- csBlock.longs[4] = nRepeats;
- sErr = U14Control1401(hand, U14_DBGRAMPDATA, &csBlock);
-#endif
-#ifdef LINUX
- TDBGBLOCK dbb;
- dbb.iAddr = (int)dwAddr;
- dbb.iDefault = (int)dwDef;
- dbb.iMask = (int)dwEnable;
- dbb.iWidth = nSize;
- dbb.iRepeats = nRepeats;
- sErr = CED_DbgRampAddr(aHand1401[hand], &dbb);
-#endif
- }
- else
- sErr = U14ERR_NOTSET;
- }
- return sErr;
-}
-
-/****************************************************************************
-** U14RampAddr
-** DESCRIPTION Cause the 1401 to loop, reading from a ramping location.
-** If lRepeats is zero, the loop will continue until U14StopDebugLoop
-****************************************************************************/
-U14API(short) U14RampAddr(short hand, unsigned int dwDef, unsigned int dwEnable,
- int nSize, int nRepeats)
-{
- short sErr = CheckHandle(hand);
- if (sErr == U14ERR_NOERROR)
- {
- if (abGrabbed[hand]) // 1401 should have been grabbed
- {
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- csBlock.longs[0] = (long)dwDef;
- csBlock.longs[1] = (long)dwEnable;
- csBlock.longs[2] = nSize;
- csBlock.longs[3] = nRepeats;
- sErr = U14Control1401(hand, U14_DBGRAMPADDR, &csBlock);
-#endif
-#ifdef LINUX
- TDBGBLOCK dbb;
- dbb.iDefault = (int)dwDef;
- dbb.iMask = (int)dwEnable;
- dbb.iWidth = nSize;
- dbb.iRepeats = nRepeats;
- sErr = CED_DbgRampAddr(aHand1401[hand], &dbb);
-#endif
- }
- else
- sErr = U14ERR_NOTSET;
- }
- return sErr;
-}
-
-/****************************************************************************
-** U14StopDebugLoop
-** DESCRIPTION Stops a peek\poke\ramp that, with repeats set to zero,
-** will otherwise continue forever.
-****************************************************************************/
-U14API(short) U14StopDebugLoop(short hand)
-{
- short sErr = CheckHandle(hand);
- if (sErr == U14ERR_NOERROR)
-#ifdef _IS_WINDOWS_
- {
- if (abGrabbed[hand]) // 1401 should have been grabbed
- {
- TCSBLOCK csBlock;
- sErr = U14Control1401(hand, U14_DBGSTOPLOOP, &csBlock);
- }
- else
- sErr = U14ERR_NOTSET;
- }
-#endif
-#ifdef LINUX
- sErr = abGrabbed[hand] ? CED_DbgStopLoop(aHand1401[hand]) : U14ERR_NOTSET;
-#endif
- return sErr;
-}
-
-/****************************************************************************
-** U14GetDebugData
-** DESCRIPTION Returns the result from a previous peek operation.
-****************************************************************************/
-U14API(short) U14GetDebugData(short hand, U14LONG* plValue)
-{
- short sErr = CheckHandle(hand);
- if (sErr == U14ERR_NOERROR)
- {
- if (abGrabbed[hand]) // 1401 should have been grabbed
- {
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- sErr = U14Status1401(hand, U14_DBGGETDATA, &csBlock);
- if (sErr == U14ERR_NOERROR)
- *plValue = csBlock.longs[0]; // Return the data
-#endif
-#ifdef LINUX
- TDBGBLOCK dbb;
- sErr = CED_DbgGetData(aHand1401[hand], &dbb);
- if (sErr == U14ERR_NOERROR)
- *plValue = dbb.iData; /* Return the data */
-#endif
- }
- else
- sErr = U14ERR_NOTSET;
- }
- return sErr;
-}
-
-/****************************************************************************
-** U14StartSelfTest
-****************************************************************************/
-U14API(short) U14StartSelfTest(short hand)
-{
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- return U14Control1401(hand, U14_STARTSELFTEST, &csBlock);
-#endif
-#ifdef LINUX
- short sErr = CheckHandle(hand);
- return (sErr == U14ERR_NOERROR) ? CED_StartSelfTest(aHand1401[hand]) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14CheckSelfTest
-****************************************************************************/
-U14API(short) U14CheckSelfTest(short hand, U14LONG *pData)
-{
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- short sErr = U14Status1401(hand, U14_CHECKSELFTEST, &csBlock);
- if (sErr == U14ERR_NOERROR)
- {
- pData[0] = csBlock.longs[0]; /* Return the results to user */
- pData[1] = csBlock.longs[1];
- pData[2] = csBlock.longs[2];
- }
-#endif
-#ifdef LINUX
- short sErr = CheckHandle(hand);
- if (sErr == U14ERR_NOERROR) /* Check parameters */
- {
- TGET_SELFTEST gst;
- sErr = CED_CheckSelfTest(aHand1401[hand], &gst);
- if (sErr == U14ERR_NOERROR)
- {
- pData[0] = gst.code; /* Return the results to user */
- pData[1] = gst.x;
- pData[2] = gst.y;
- }
- }
-#endif
- return sErr;
-}
-
-/****************************************************************************
-** U14GetUserMemorySize
-****************************************************************************/
-U14API(short) U14GetUserMemorySize(short hand, unsigned int *pMemorySize)
-{
- // The original 1401 used a different command for getting the size
- short sErr = U14SendString(hand, (asType1401[hand] == U14TYPE1401) ? "MEMTOP;" : "MEMTOP,?;");
- *pMemorySize = 0; /* if we get error then leave size set at 0 */
- if (sErr == U14ERR_NOERROR)
- {
- U14LONG alLimits[4];
- sErr = U14LongsFrom1401(hand, alLimits, 4);
- if (sErr > 0) /* +ve sErr is the number of values read */
- {
- sErr = U14ERR_NOERROR; /* All OK, flag success */
- if (asType1401[hand] == U14TYPE1401) /* result for standard */
- *pMemorySize = alLimits[0] - alLimits[1]; /* memtop-membot */
- else
- *pMemorySize = alLimits[0]; /* result for plus or u1401 */
- }
- }
- return sErr;
-}
-
-/****************************************************************************
-** U14TypeOf1401
-** Returns the type of the 1401, maybe unknown
-****************************************************************************/
-U14API(short) U14TypeOf1401(short hand)
-{
- if ((hand < 0) || (hand >= MAX1401)) /* Check parameters */
- return U14ERR_BADHAND;
- else
- return asType1401[hand];
-}
-
-/****************************************************************************
-** U14NameOf1401
-** Returns the type of the 1401 as a string, blank if unknown
-****************************************************************************/
-U14API(short) U14NameOf1401(short hand, char* pBuf, unsigned short wMax)
-{
- short sErr = CheckHandle(hand);
- if (sErr == U14ERR_NOERROR)
- {
- char* pName;
- switch (asType1401[hand]) // Results according to type
- {
- case U14TYPE1401: pName = "Std 1401"; break;
- case U14TYPEPLUS: pName = "1401plus"; break;
- case U14TYPEU1401: pName = "micro1401"; break;
- case U14TYPEPOWER: pName = "Power1401"; break;
- case U14TYPEU14012:pName = "Micro1401 mk II"; break;
- case U14TYPEPOWER2:pName = "Power1401 mk II"; break;
- case U14TYPEU14013:pName = "Micro1401-3"; break;
- case U14TYPEPOWER3:pName = "Power1401-3"; break;
- default: pName = "Unknown";
- }
- strncpy(pBuf, pName, wMax);
- }
- return sErr;
-}
-
-/****************************************************************************
-** U14TransferFlags
-** Returns the driver block transfer flags.
-** Bits can be set - see U14TF_ constants in use1401.h
-*****************************************************************************/
-U14API(short) U14TransferFlags(short hand)
-{
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- short sErr = U14Status1401(hand, U14_TRANSFERFLAGS, &csBlock);
- return (sErr == U14ERR_NOERROR) ? (short)csBlock.ints[0] : sErr;
-#endif
-#ifdef LINUX
- short sErr = CheckHandle(hand);
- return (sErr == U14ERR_NOERROR) ? CED_TransferFlags(aHand1401[hand]) : sErr;
-#endif
-}
-
-/****************************************************************************
-** GetDriverVersion
-** Actually reads driver version from the device driver.
-** Hi word is major revision, low word is minor revision.
-** Assumes that hand has been checked. Also codes driver type in bits 24 up.
-*****************************************************************************/
-static int GetDriverVersion(short hand)
-{
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- int iErr = U14Status1401(hand, U14_GETDRIVERREVISION, &csBlock);
- if (iErr == U14ERR_NOERROR)
- iErr = csBlock.longs[0];
- return iErr;
-#endif
-#ifdef LINUX
- return CED_GetDriverRevision(aHand1401[hand]);
-#endif
-}
-
-/****************************************************************************
-** U14MonitorRev
-** Returns the 1401 monitor revision number.
-** The number returned is the minor revision - the part after the
-** decimal point - plus the major revision times 1000.
-*****************************************************************************/
-U14API(int) U14MonitorRev(short hand)
-{
- int iRev = 0;
- int iErr = CheckHandle(hand);
- if (iErr != U14ERR_NOERROR) // Check open and in use
- return iErr;
-
- if (asType1401[hand] >= U14TYPEPOWER2) // The Power2 onwards can give us the monitor
- { // revision directly for all versions
- iErr = U14SendString(hand, "INFO,S,28;");
- if (iErr == U14ERR_NOERROR)
- {
- U14LONG lVals[2]; // Read a single number being the revision
- iErr = U14LongsFrom1401(hand, lVals, 1);
- if (iErr > 0)
- {
- iErr = U14ERR_NOERROR;
- iRev = lVals[0]; // This is the minor part of the revision
- iRev += asType1401[hand] * 10000;
- }
- }
- }
- else
- { /* Do it the hard way for older hardware */
- iErr = U14SendString(hand, ";CLIST;"); /* ask for command levels */
- if (iErr == U14ERR_NOERROR)
- {
- while (iErr == U14ERR_NOERROR)
- {
- char wstr[50];
- iErr = U14GetString(hand, wstr, 45);
- if (iErr == U14ERR_NOERROR)
- {
- char *pstr = strstr(wstr,"RESET"); /* Is this the RESET command? */
- if ((pstr == wstr) && (wstr[5] == ' '))
- {
- char *pstr2;
- size_t l;
- pstr += 6; /* Move past RESET and followinmg char */
- l = strlen(pstr); /* The length of text remaining */
- while (((pstr[l-1] == ' ') || (pstr[l-1] == 13)) && (l > 0))
- {
- pstr[l-1] = 0; /* Tidy up string at the end */
- l--; /* by removing spaces and CRs */
- }
- pstr2 = strchr(pstr, '.'); /* Find the decimal point */
- if (pstr2 != NULL) /* If we found the DP */
- {
- *pstr2 = 0; /* End pstr string at DP */
- pstr2++; /* Now past the decimal point */
- iRev = atoi(pstr2); /* Get the number after point */
- }
- iRev += (atoi(pstr) * 1000); /* Add first bit * 1000 */
- }
- if ((strlen(wstr) < 3) && (wstr[0] == ' '))
- break; /* Spot the last line of results */
- }
- }
- }
- }
- if (iErr == U14ERR_NOERROR) /* Return revision if no error */
- iErr = iRev;
-
- return iErr;
-}
-
-/****************************************************************************
-** U14TryToOpen Tries to open the 1401 number passed
-** Note : This will succeed with NT driver even if no I/F card or
-** 1401 switched off, so we check state and close the driver
-** if the state is unsatisfactory in U14Open1401.
-****************************************************************************/
-#ifdef _IS_WINDOWS_
-#define U14NAMEOLD "\\\\.\\CED_140%d"
-#define U14NAMENEW "\\\\.\\CED%d"
-static short U14TryToOpen(int n1401, long* plRetVal, short* psHandle)
-{
- short sErr = U14ERR_NOERROR;
- HANDLE hDevice = INVALID_HANDLE_VALUE;
- unsigned int dwErr = 0;
- int nFirst, nLast, nDev = 0; /* Used for the search for a 1401 */
- BOOL bOldName = FALSE; /* start by looking for a modern driver */
-
- if (n1401 == 0) /* If we need to look for a 1401 */
- {
- nFirst = 1; /* Set the search range */
- nLast = MAX1401; /* through all the possible 1401s */
- }
- else
- nFirst = nLast = n1401; /* Otherwise just one 1401 */
-
- while (hDevice == INVALID_HANDLE_VALUE) /* Loop to try for a 1401 */
- {
- for (nDev = nFirst; nDev <= nLast; nDev++)
- {
- char szDevName[40]; /* name of the device to open */
- sprintf(szDevName, bOldName ? U14NAMEOLD : U14NAMENEW, nDev);
- hDevice = CreateFile(szDevName, GENERIC_WRITE | GENERIC_READ,
- 0, 0, /* Unshared mode does nothing as this is a device */
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-
- if (hDevice != INVALID_HANDLE_VALUE)/* Check 1401 if opened */
- {
- TCSBLOCK csBlock;
- assert(aHand1401[nDev-1] == INVALID_HANDLE_VALUE); // assert if already open
- aHand1401[nDev-1] = hDevice; /* Save handle for now */
-
-#ifndef _WIN64
- // Use DIOC method if not windows 9x or if using new device name
- abUseNTDIOC[nDev-1] = (BOOL)(!bWindows9x || !bOldName);
-#endif
- sErr = U14Status1401((short)(nDev-1), U14_TYPEOF1401, &csBlock);
- if (sErr == U14ERR_NOERROR)
- {
- *plRetVal = csBlock.ints[0];
- if (csBlock.ints[0] == U14ERR_INUSE)/* Prevent multi opens */
- {
- CloseHandle(hDevice); /* treat as open failure */
- hDevice = INVALID_HANDLE_VALUE;
- aHand1401[nDev-1] = INVALID_HANDLE_VALUE;
- sErr = U14ERR_INUSE;
- }
- else
- break; /* Exit from for loop on success */
- }
- else
- {
- CloseHandle(hDevice); /* Give up if func fails */
- hDevice = INVALID_HANDLE_VALUE;
- aHand1401[nDev-1] = INVALID_HANDLE_VALUE;
- }
- }
- else
- {
- unsigned int dwe = GetLastError(); /* Get error code otherwise */
- if ((dwe != ERROR_FILE_NOT_FOUND) || (dwErr == 0))
- dwErr = dwe; /* Ignore repeats of 'not found' */
- }
- }
-
- if ((hDevice == INVALID_HANDLE_VALUE) &&/* No device found, and... */
- (bWindows9x) && /* ...old names are allowed, and... */
- (bOldName == FALSE)) /* ...not tried old names yet */
- bOldName = TRUE; /* Set flag and go round again */
- else
- break; /* otherwise that's all folks */
- }
-
- if (hDevice != INVALID_HANDLE_VALUE) /* If we got our device open */
- *psHandle = (short)(nDev-1); /* return 1401 number opened */
- else
- {
- if (dwErr == ERROR_FILE_NOT_FOUND) /* Sort out the error codes */
- sErr = U14ERR_NO1401DRIV; /* if file not found */
- else if (dwErr == ERROR_NOT_SUPPORTED)
- sErr = U14ERR_DRIVTOOOLD; /* if DIOC not supported */
- else if (dwErr == ERROR_ACCESS_DENIED)
- sErr = U14ERR_INUSE;
- else
- sErr = U14ERR_DRIVCOMMS; /* otherwise assume comms problem */
- }
- return sErr;
-}
-#endif
-#ifdef LINUX
-static short U14TryToOpen(int n1401, long* plRetVal, short* psHandle)
-{
- short sErr = U14ERR_NOERROR;
- int fh = 0; // will be 1401 handle
- int iErr = 0;
- int nFirst, nLast, nDev = 0; // Used for the search for a 1401
-
- if (n1401 == 0) // If we need to look for a 1401
- {
- nFirst = 1; /* Set the search range */
- nLast = MAX1401; /* through all the possible 1401s */
- }
- else
- nFirst = nLast = n1401; /* Otherwise just one 1401 */
-
- for (nDev = nFirst; nDev <= nLast; nDev++)
- {
- char szDevName[40]; // name of the device to open
- sprintf(szDevName,"/dev/cedusb/%d", nDev-1);
- fh = open(szDevName, O_RDWR); // can only be opened once at a time
- if (fh > 0) // Check 1401 if opened
- {
- int iType1401 = CED_TypeOf1401(fh); // get 1401 type
- aHand1401[nDev-1] = fh; // Save handle for now
- if (iType1401 >= 0)
- {
- *plRetVal = iType1401;
- break; // Exit from for loop on success
- }
- else
- {
- close(fh); // Give up if func fails
- fh = 0;
- aHand1401[nDev-1] = 0;
- }
- }
- else
- {
- if (((errno != ENODEV) && (errno != ENOENT)) || (iErr == 0))
- iErr = errno; // Ignore repeats of 'not found'
- }
- }
-
-
- if (fh) // If we got our device open
- *psHandle = (short)(nDev-1); // return 1401 number opened
- else
- {
- if ((iErr == ENODEV) || (iErr == ENOENT)) // Sort out the error codes
- sErr = U14ERR_NO1401DRIV; // if file not found
- else if (iErr == EBUSY)
- sErr = U14ERR_INUSE;
- else
- sErr = U14ERR_DRIVCOMMS; // otherwise assume comms problem
- }
-
- return sErr;
-}
-#endif
-/****************************************************************************
-** U14Open1401
-** Tries to get the 1401 for use by this application
-*****************************************************************************/
-U14API(short) U14Open1401(short n1401)
-{
- long lRetVal = -1;
- short sErr;
- short hand = 0;
-
- if ((n1401 < 0) || (n1401 > MAX1401)) // must check the 1401 number
- return U14ERR_BAD1401NUM;
-
- szLastName[0] = 0; /* initialise the error info string */
-
- sErr = U14TryToOpen(n1401, &lRetVal, &hand);
- if (sErr == U14ERR_NOERROR)
- {
- long lDriverVersion = GetDriverVersion(hand); /* get driver revision */
- long lDriverRev = -1;
- if (lDriverVersion >= 0) /* can use it if all OK */
- {
- lLastDriverType = (lDriverVersion >> 24) & 0x000000FF;
- asDriverType[hand] = (short)lLastDriverType; /* Drv type */
- lLastDriverVersion = lDriverVersion & 0x00FFFFFF;
- alDriverVersion[hand] = lLastDriverVersion; /* Actual version */
- lDriverRev = ((lDriverVersion>>16) & 0x00FF); /* use hi word */
- }
- else
- {
- U14Close1401(hand); /* If there is a problem we should close */
- return (short)lDriverVersion; /* and return the error code */
- }
-
- if (lDriverRev < MINDRIVERMAJREV) /* late enough version? */
- {
- U14Close1401(hand); /* If there is a problem we should close */
- return U14ERR_DRIVTOOOLD; /* too old */
- }
-
- asLastRetCode[hand] = U14ERR_NOERROR; /* Initialise this 1401s info */
- abGrabbed[hand] = FALSE; /* we are not in single step mode */
- U14SetTimeout(hand, 3000); /* set 3 seconds as default timeout */
-
- switch (lRetVal)
- {
- case DRIVRET_STD: asType1401[hand] = U14TYPE1401; break; /* Some we do by hand */
- case DRIVRET_U1401:asType1401[hand] = U14TYPEU1401; break;
- case DRIVRET_PLUS: asType1401[hand] = U14TYPEPLUS; break;
- default: // For the power upwards, we can calculate the codes
- if ((lRetVal >= DRIVRET_POWER) && (lRetVal <= DRIVRET_MAX))
- asType1401[hand] = (short)(lRetVal - (DRIVRET_POWER - U14TYPEPOWER));
- else
- asType1401[hand] = U14TYPEUNKNOWN;
- break;
- }
- U14KillIO1401(hand); /* resets the 1401 buffers */
-
- if (asType1401[hand] != U14TYPEUNKNOWN) /* If all seems OK so far */
- {
- sErr = U14CheckErr(hand); /* we can check 1401 comms now */
- if (sErr != 0) /* If this failed to go OK */
- U14Reset1401(hand); /* Reset the 1401 to try to sort it out */
- }
-
- sErr = U14StateOf1401(hand);/* Get the state of the 1401 for return */
- if (sErr == U14ERR_NOERROR)
- sErr = hand; /* return the handle if no problem */
- else
- U14Close1401(hand); /* If there is a problem we should close */
- }
-
- return sErr;
-}
-
-
-/****************************************************************************
-** U14Close1401
-** Closes the 1401 so someone else can use it.
-****************************************************************************/
-U14API(short) U14Close1401(short hand)
-{
- int j;
- int iAreaMask = 0; // Mask for active areas
- short sErr = CheckHandle(hand);
- if (sErr != U14ERR_NOERROR) // Check open and in use
- return sErr;
-
- for (j = 0; j<MAX_TRANSAREAS; ++j)
- {
- TGET_TX_BLOCK gtb;
- int iReturn = U14GetTransfer(hand, >b); // get area information
- if (iReturn == U14ERR_NOERROR) // ignore if any problem
- if (gtb.used)
- iAreaMask |= (1 << j); // set a bit for each used area
- }
-
- if (iAreaMask) // if any areas are in use
- {
- U14Reset1401(hand); // in case an active transfer running
- for (j = 0; j < MAX_TRANSAREAS; ++j) // Locate locked areas
- if (iAreaMask & (1 << j)) // And kill off any transfers
- U14UnSetTransfer(hand, (unsigned short)j);
- }
-
-#ifdef _IS_WINDOWS_
- if (aXferEvent[hand]) // if this 1401 has an open event handle
- {
- CloseHandle(aXferEvent[hand]); // close down the handle
- aXferEvent[hand] = NULL; // and mark it as gone
- }
-
- if (CloseHandle(aHand1401[hand]))
-#endif
-#ifdef LINUX
- if (close(aHand1401[hand]) == 0) // make sure that close works
-#endif
- {
- aHand1401[hand] = INVALID_HANDLE_VALUE;
- asType1401[hand] = U14TYPEUNKNOWN;
- return U14ERR_NOERROR;
- }
- else
- return U14ERR_BADHAND; /* BUGBUG GetLastError() ? */
-}
-
-/**************************************************************************
-**
-** Look for open 1401s and attempt to close them down. 32-bit windows only.
-**************************************************************************/
-U14API(void) U14CloseAll(void)
-{
- int i;
- for (i = 0; i < MAX1401; i++) // Tidy up and make safe
- if (aHand1401[i] != INVALID_HANDLE_VALUE)
- U14Close1401((short)i); // Last ditch close 1401
-}
-
-/****************************************************************************
-** U14Reset1401
-** Resets the 1401
-****************************************************************************/
-U14API(short) U14Reset1401(short hand)
-{
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- return U14Control1401(hand, U14_RESET1401, &csBlock);
-#endif
-#ifdef LINUX
- short sErr = CheckHandle(hand);
- return (sErr == U14ERR_NOERROR) ? CED_Reset1401(aHand1401[hand]) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14ForceReset
-** Sets the 1401 full reset flag, so that next call to Reset1401 will
-** always cause a genuine reset.
-*****************************************************************************/
-U14API(short) U14ForceReset(short hand)
-{
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- return U14Control1401(hand, U14_FULLRESET, &csBlock);
-#endif
-#ifdef LINUX
- short sErr = CheckHandle(hand);
- return (sErr == U14ERR_NOERROR) ? CED_FullReset(aHand1401[hand]) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14KillIO1401
-** Removes any pending IO from the buffers.
-*****************************************************************************/
-U14API(short) U14KillIO1401(short hand)
-{
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- return U14Control1401(hand, U14_KILLIO1401, &csBlock);
-#endif
-#ifdef LINUX
- short sErr = CheckHandle(hand);
- return (sErr == U14ERR_NOERROR) ? CED_KillIO1401(aHand1401[hand]) : sErr;
-#endif
-}
-
-
-/****************************************************************************
-** U14SendString
-** Send characters to the 1401
-*****************************************************************************/
-U14API(short) U14SendString(short hand, const char* pString)
-{
- int nChars; // length we are sending
- long lTimeOutTicks; // when to time out
- BOOL bSpaceToSend; // space to send yet
- short sErr = CheckHandle(hand);
- if (sErr != U14ERR_NOERROR)
- return sErr;
-
- nChars = (int)strlen(pString); // get string length we want to send
- if (nChars > MAXSTRLEN)
- return U14ERR_STRLEN; // String too long
-
-#ifdef _IS_WINDOWS_
- // To get here we must wait for the buffer to have some space
- lTimeOutTicks = U14WhenToTimeOut(hand);
- do
- {
- bSpaceToSend = (BOOL)((long)U14OutBufSpace(hand) >= nChars);
- }
- while (!bSpaceToSend && !U14PassedTime(lTimeOutTicks));
-
- if (!bSpaceToSend) /* Last-ditch attempt to avoid timeout */
- { /* This can happen with anti-virus or network activity! */
- int i;
- for (i = 0; (i < 4) && (!bSpaceToSend); ++i)
- {
- Sleep(25); /* Give other threads a chance for a while */
- bSpaceToSend = (BOOL)((long)U14OutBufSpace(hand) >= nChars);
- }
- }
-
- if (asLastRetCode[hand] == U14ERR_NOERROR) /* no errors? */
- {
- if (bSpaceToSend)
- {
- PARAMBLK rData;
- unsigned int dwBytes;
- char tstr[MAXSTRLEN+5]; /* Buffer for chars */
-
- if ((hand < 0) || (hand >= MAX1401))
- sErr = U14ERR_BADHAND;
- else
- {
- strcpy(tstr, pString); /* Into local buf */
-#ifndef _WIN64
- if (!USE_NT_DIOC(hand)) /* Using WIN 95 driver access? */
- {
- int iOK = DeviceIoControl(aHand1401[hand], (unsigned int)U14_SENDSTRING,
- NULL, 0, tstr, nChars,
- &dwBytes, NULL);
- if (iOK)
- sErr = (dwBytes >= (unsigned int)nChars) ? U14ERR_NOERROR : U14ERR_DRIVCOMMS;
- else
- sErr = (short)GetLastError();
- }
- else
-#endif
- {
- int iOK = DeviceIoControl(aHand1401[hand],(unsigned int)U14_SENDSTRING,
- tstr, nChars,
- &rData,sizeof(PARAMBLK),&dwBytes,NULL);
- if (iOK && (dwBytes >= sizeof(PARAMBLK)))
- sErr = rData.sState;
- else
- sErr = U14ERR_DRIVCOMMS;
- }
-
- if (sErr != U14ERR_NOERROR) // If we have had a comms error
- U14ForceReset(hand); // make sure we get real reset
- }
-
- return sErr;
-
- }
- else
- {
- U14ForceReset(hand); // make sure we get real reset
- return U14ERR_TIMEOUT;
- }
- }
- else
- return asLastRetCode[hand];
-#endif
-#ifdef LINUX
- // Just try to send it and see what happens!
- sErr = CED_SendString(aHand1401[hand], pString, nChars);
- if (sErr != U14ERR_NOOUT) // if any result except "no room in output"...
- {
- if (sErr != U14ERR_NOERROR) // if a problem...
- U14ForceReset(hand); // ...make sure we get real reset next time
- return sErr; // ... we are done as nothing we can do
- }
-
- // To get here we must wait for the buffer to have some space
- lTimeOutTicks = U14WhenToTimeOut(hand);
- do
- {
- bSpaceToSend = (BOOL)((long)U14OutBufSpace(hand) >= nChars);
- if (!bSpaceToSend)
- sched_yield(); // let others have fun while we wait
- }
- while (!bSpaceToSend && !U14PassedTime(lTimeOutTicks));
-
- if (asLastRetCode[hand] == U14ERR_NOERROR) /* no errors? */
- {
- if (bSpaceToSend)
- {
- sErr = CED_SendString(aHand1401[hand], pString, nChars);
- if (sErr != U14ERR_NOERROR) // If we have had a comms error
- U14ForceReset(hand); // make sure we get real reset
- return sErr;
- }
- else
- {
- U14ForceReset(hand); // make sure we get real reset
- return U14ERR_TIMEOUT;
- }
- }
- else
- return asLastRetCode[hand];
-#endif
-}
-
-/****************************************************************************
-** U14SendChar
-** Send character to the 1401
-*****************************************************************************/
-U14API(short) U14SendChar(short hand, char cChar)
-{
-#ifdef _IS_WINDOWS_
- char sz[2]=" "; // convert to a string and send
- sz[0] = cChar;
- sz[1] = 0;
- return(U14SendString(hand, sz)); // String routines are better
-#endif
-#ifdef LINUX
- short sErr = CheckHandle(hand);
- return (sErr == U14ERR_NOERROR) ? CED_SendChar(aHand1401[hand], cChar) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14GetString
-** Get a string from the 1401. Returns a null terminated string.
-** The string is all the characters up to the next CR in the buffer
-** or the end of the buffer if that comes first. This only returns text
-** if there is a CR in the buffer. The terminating CR character is removed.
-** wMaxLen Is the size of the buffer and must be at least 2 or an error.
-** Returns U14ERR_NOERR if OK with the result in the string or a negative
-** error code. Any error from the device causes us to set up for
-** a full reset.
-****************************************************************************/
-U14API(short) U14GetString(short hand, char* pBuffer, unsigned short wMaxLen)
-{
- short sErr = CheckHandle(hand);
- if (sErr != U14ERR_NOERROR) // If an error...
- return sErr; // ...bail out!
-
-#ifdef _IS_WINDOWS_
- if (wMaxLen>1) // we need space for terminating 0
- {
- BOOL bLineToGet; // true when a line to get
- long lTimeOutTicks = U14WhenToTimeOut(hand);
- do
- bLineToGet = (BOOL)(U14LineCount(hand) != 0);
- while (!bLineToGet && !U14PassedTime(lTimeOutTicks));
-
- if (!bLineToGet) /* Last-ditch attempt to avoid timeout */
- { /* This can happen with anti-virus or network activity! */
- int i;
- for (i = 0; (i < 4) && (!bLineToGet); ++i)
- {
- Sleep(25); /* Give other threads a chance for a while */
- bLineToGet = (BOOL)(U14LineCount(hand) != 0);
- }
- }
-
- if (bLineToGet)
- {
- if (asLastRetCode[hand] == U14ERR_NOERROR) /* all ok so far */
- {
- unsigned int dwBytes = 0;
- *((unsigned short *)pBuffer) = wMaxLen; /* set up length */
-#ifndef _WIN64
- if (!USE_NT_DIOC(hand)) /* Win 95 DIOC here ? */
- {
- char tstr[MAXSTRLEN+5]; /* Buffer for Win95 chars */
- int iOK;
-
- if (wMaxLen > MAXSTRLEN) /* Truncate length */
- wMaxLen = MAXSTRLEN;
-
- *((unsigned short *)tstr) = wMaxLen; /* set len */
-
- iOK = DeviceIoControl(aHand1401[hand],(unsigned int)U14_GETSTRING,
- NULL, 0, tstr, wMaxLen+sizeof(short),
- &dwBytes, NULL);
- if (iOK) /* Device IO control OK ? */
- {
- strcpy(pBuffer, tstr);
- sErr = U14ERR_NOERROR;
- }
- else
- {
- sErr = (short)GetLastError();
- if (sErr > 0) /* Errors are -ve */
- sErr = (short)-sErr;
- }
- }
- else
-#endif
- { /* Here for NT, the DLL must own the buffer */
- HANDLE hMem = GlobalAlloc(GMEM_MOVEABLE,wMaxLen+sizeof(short));
- if (hMem)
- {
- char* pMem = (char*)GlobalLock(hMem);
- if (pMem)
- {
- int iOK = DeviceIoControl(aHand1401[hand],(unsigned int)U14_GETSTRING,
- NULL, 0, pMem, wMaxLen+sizeof(short),
- &dwBytes, NULL);
- if (iOK) /* Device IO control OK ? */
- {
- if (dwBytes >= wMaxLen)
- {
- strcpy(pBuffer, pMem+sizeof(short));
- sErr = *((SHORT*)pMem);
- }
- else
- sErr = U14ERR_DRIVCOMMS;
- }
- else
- sErr = U14ERR_DRIVCOMMS;
-
- GlobalUnlock(hMem);
- }
- else
- sErr = U14ERR_OUTOFMEMORY;
-
- GlobalFree(hMem);
- }
- else
- sErr = U14ERR_OUTOFMEMORY;
- }
-
- if (sErr == U14ERR_NOERROR) // If all OK...
- TranslateString(pBuffer); // ...convert any commas to spaces
- else // If we have had a comms error...
- U14ForceReset(hand); // ...make sure we get real reset
-
- }
- else
- sErr = asLastRetCode[hand];
- }
- else
- {
- sErr = U14ERR_TIMEOUT;
- U14ForceReset(hand); // make sure we get real reset
- }
- }
- else
- sErr = U14ERR_BUFF_SMALL;
- return sErr;
-#endif
-#ifdef LINUX
- if (wMaxLen>1) // we need space for terminating 0
- {
- BOOL bLineToGet; // true when a line to get
- long lTimeOutTicks = U14WhenToTimeOut(hand);
- do
- {
- bLineToGet = (BOOL)(U14LineCount(hand) != 0);
- if (!bLineToGet)
- sched_yield();
-
- }
- while (!bLineToGet && !U14PassedTime(lTimeOutTicks));
-
- if (bLineToGet)
- {
- sErr = CED_GetString(aHand1401[hand], pBuffer, wMaxLen-1); // space for terminator
- if (sErr >=0) // if we were OK...
- {
- if (sErr >= wMaxLen) // this should NOT happen unless
- sErr = U14ERR_DRIVCOMMS; // ...driver Comms are very bad
- else
- {
- pBuffer[sErr] = 0; // OK, so terminate the string...
- TranslateString(pBuffer); // ...and convert commas to spaces.
- }
- }
-
- if (sErr < U14ERR_NOERROR) // If we have had a comms error
- U14ForceReset(hand); // make sure we get real reset
- }
- else
- {
- sErr = U14ERR_TIMEOUT;
- U14ForceReset(hand); // make sure we get real reset
- }
- }
- else
- sErr = U14ERR_BUFF_SMALL;
-
- return sErr >= U14ERR_NOERROR ? U14ERR_NOERROR : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14GetChar
-** Get a character from the 1401. CR returned as CR.
-*****************************************************************************/
-U14API(short) U14GetChar(short hand, char* pcChar)
-{
-#ifdef _IS_WINDOWS_
- char sz[2]; // read a very short string
- short sErr = U14GetString(hand, sz, 2); // read one char and nul terminate it
- *pcChar = sz[0]; // copy to result, NB char translate done by GetString
- if (sErr == U14ERR_NOERROR)
- { // undo translate of CR to zero
- if (*pcChar == '\0') // by converting back
- *pcChar = '\n'; // What a nasty thing to have to do
- }
- return sErr;
-#endif
-#ifdef LINUX
- short sErr = CheckHandle(hand);
- if (sErr != U14ERR_NOERROR) // Check parameters
- return sErr;
- sErr = CED_GetChar(aHand1401[hand]); // get one char, if available
- if (sErr >= 0)
- {
- *pcChar = (char)sErr; // return if it we have one
- return U14ERR_NOERROR; // say all OK
- }
- else
- return sErr;
-#endif
-}
-
-/****************************************************************************
-** U14Stat1401
-** Returns 0 for no lines or error or non zero for something waiting
-****************************************************************************/
-U14API(short) U14Stat1401(short hand)
-{
- return ((short)(U14LineCount(hand) > 0));
-}
-
-/****************************************************************************
-** U14CharCount
-** Returns the number of characters in the input buffer
-*****************************************************************************/
-U14API(short) U14CharCount(short hand)
-{
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- short sErr = U14Status1401(hand, U14_STAT1401, &csBlock);
- if (sErr == U14ERR_NOERROR)
- sErr = csBlock.ints[0];
- return sErr;
-#endif
-#ifdef LINUX
- short sErr = CheckHandle(hand);
- return (sErr == U14ERR_NOERROR) ? CED_Stat1401(aHand1401[hand]) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14LineCount
-** Returns the number of CR characters in the input buffer
-*****************************************************************************/
-U14API(short) U14LineCount(short hand)
-{
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- short sErr = U14Status1401(hand, U14_LINECOUNT, &csBlock);
- if (sErr == U14ERR_NOERROR)
- sErr = csBlock.ints[0];
- return sErr;
-#endif
-#ifdef LINUX
- short sErr = CheckHandle(hand);
- return (sErr == U14ERR_NOERROR) ? CED_LineCount(aHand1401[hand]) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14GetErrorString
-** Converts error code supplied to a decent descriptive string.
-** NOTE: This function may use some extra information stored
-** internally in the DLL. This information is stored on a
-** per-process basis, but it might be altered if you call
-** other functions after getting an error and before using
-** this function.
-****************************************************************************/
-U14API(void) U14GetErrorString(short nErr, char* pStr, unsigned short wMax)
-{
- char wstr[150];
-
- switch (nErr) /* Basically, we do this with a switch block */
- {
- case U14ERR_OFF:
- sprintf(wstr, "The 1401 is apparently switched off (code %d)", nErr);
- break;
-
- case U14ERR_NC:
- sprintf(wstr, "The 1401 is not connected to the interface card (code %d)", nErr);
- break;
-
- case U14ERR_ILL:
- sprintf(wstr, "The 1401 is not working correctly (code %d)", nErr);
- break;
-
- case U14ERR_NOIF:
- sprintf(wstr, "The 1401 interface card was not detected (code %d)", nErr);
- break;
-
- case U14ERR_TIME:
- sprintf(wstr, "The 1401 fails to become ready for use (code %d)", nErr);
- break;
-
- case U14ERR_BADSW:
- sprintf(wstr, "The 1401 interface card jumpers are incorrect (code %d)", nErr);
- break;
-
- case U14ERR_NOINT:
- sprintf(wstr, "The 1401 interrupt is not available for use (code %d)", nErr);
- break;
-
- case U14ERR_INUSE:
- sprintf(wstr, "The 1401 is already in use by another program (code %d)", nErr);
- break;
-
- case U14ERR_NODMA:
- sprintf(wstr, "The 1401 DMA channel is not available for use (code %d)", nErr);
- break;
-
- case U14ERR_BADHAND:
- sprintf(wstr, "The application supplied an incorrect 1401 handle (code %d)", nErr);
- break;
-
- case U14ERR_BAD1401NUM:
- sprintf(wstr, "The application used an incorrect 1401 number (code %d)", nErr);
- break;
-
- case U14ERR_NO_SUCH_FN:
- sprintf(wstr, "The code passed to the 1401 driver is invalid (code %d)", nErr);
- break;
-
- case U14ERR_NO_SUCH_SUBFN:
- sprintf(wstr, "The sub-code passed to the 1401 driver is invalid (code %d)", nErr);
- break;
-
- case U14ERR_NOOUT:
- sprintf(wstr, "No room in buffer for characters for the 1401 (code %d)", nErr);
- break;
-
- case U14ERR_NOIN:
- sprintf(wstr, "No characters from the 1401 are available (code %d)", nErr);
- break;
-
- case U14ERR_STRLEN:
- sprintf(wstr, "A string sent to or read from the 1401 was too long (code %d)", nErr);
- break;
-
- case U14ERR_LOCKFAIL:
- sprintf(wstr, "Failed to lock host memory for data transfer (code %d)", nErr);
- break;
-
- case U14ERR_UNLOCKFAIL:
- sprintf(wstr, "Failed to unlock host memory after data transfer (code %d)", nErr);
- break;
-
- case U14ERR_ALREADYSET:
- sprintf(wstr, "The transfer area used is already set up (code %d)", nErr);
- break;
-
- case U14ERR_NOTSET:
- sprintf(wstr, "The transfer area used has not been set up (code %d)", nErr);
- break;
-
- case U14ERR_BADAREA:
- sprintf(wstr, "The transfer area number is incorrect (code %d)", nErr);
- break;
-
- case U14ERR_NOFILE:
- sprintf(wstr, "The command file %s could not be opened (code %d)", szLastName, nErr);
- break;
-
- case U14ERR_READERR:
- sprintf(wstr, "The command file %s could not be read (code %d)", szLastName, nErr);
- break;
-
- case U14ERR_UNKNOWN:
- sprintf(wstr, "The %s command resource could not be found (code %d)", szLastName, nErr);
- break;
-
- case U14ERR_HOSTSPACE:
- sprintf(wstr, "Unable to allocate memory for loading command %s (code %d)", szLastName, nErr);
- break;
-
- case U14ERR_LOCKERR:
- sprintf(wstr, "Unable to lock memory for loading command %s (code %d)", szLastName, nErr);
- break;
-
- case U14ERR_CLOADERR:
- sprintf(wstr, "Error in loading command %s, bad command format (code %d)", szLastName, nErr);
- break;
-
- case U14ERR_TOXXXERR:
- sprintf(wstr, "Error detected after data transfer to or from the 1401 (code %d)", nErr);
- break;
-
- case U14ERR_NO386ENH:
- sprintf(wstr, "Windows 3.1 is not running in 386 enhanced mode (code %d)", nErr);
- break;
-
- case U14ERR_NO1401DRIV:
- sprintf(wstr, "The 1401 device driver cannot be found (code %d)\nUSB: check plugged in and powered\nOther: not installed?", nErr);
- break;
-
- case U14ERR_DRIVTOOOLD:
- sprintf(wstr, "The 1401 device driver is too old for use (code %d)", nErr);
- break;
-
- case U14ERR_TIMEOUT:
- sprintf(wstr, "Character transmissions to the 1401 timed-out (code %d)", nErr);
- break;
-
- case U14ERR_BUFF_SMALL:
- sprintf(wstr, "Buffer for text from the 1401 was too small (code %d)", nErr);
- break;
-
- case U14ERR_CBALREADY:
- sprintf(wstr, "1401 monitor callback already set up (code %d)", nErr);
- break;
-
- case U14ERR_BADDEREG:
- sprintf(wstr, "1401 monitor callback deregister invalid (code %d)", nErr);
- break;
-
- case U14ERR_DRIVCOMMS:
- sprintf(wstr, "1401 device driver communications failed (code %d)", nErr);
- break;
-
- case U14ERR_OUTOFMEMORY:
- sprintf(wstr, "Failed to allocate or lock memory for text from the 1401 (code %d)", nErr);
- break;
-
- default:
- sprintf(wstr, "1401 error code %d returned; this code is unknown", nErr);
- break;
-
- }
- if ((unsigned short)strlen(wstr) >= wMax-1) /* Check for string being too long */
- wstr[wMax-1] = 0; /* and truncate it if so */
- strcpy(pStr, wstr); /* Return the error string */
-}
-
-/***************************************************************************
-** U14GetTransfer
-** Get a TGET_TX_BLOCK describing a transfer area (held in the block)
-***************************************************************************/
-U14API(short) U14GetTransfer(short hand, TGET_TX_BLOCK *pTransBlock)
-{
- short sErr = CheckHandle(hand);
-#ifdef _IS_WINDOWS_
- if (sErr == U14ERR_NOERROR)
- {
- unsigned int dwBytes = 0;
- BOOL bOK = DeviceIoControl(aHand1401[hand], (unsigned int)U14_GETTRANSFER, NULL, 0, pTransBlock,
- sizeof(TGET_TX_BLOCK), &dwBytes, NULL);
-
- if (bOK && (dwBytes >= sizeof(TGET_TX_BLOCK)))
- sErr = U14ERR_NOERROR;
- else
- sErr = U14ERR_DRIVCOMMS;
- }
- return sErr;
-#endif
-#ifdef LINUX
- return (sErr == U14ERR_NOERROR) ? CED_GetTransfer(aHand1401[hand], pTransBlock) : sErr;
-#endif
-}
-/////////////////////////////////////////////////////////////////////////////
-// U14WorkingSet
-// For Win32 only, adjusts process working set so that minimum is at least
-// dwMinKb and maximum is at least dwMaxKb.
-// Return value is zero if all went OK, or a code from 1 to 3 indicating the
-// cause of the failure:
-//
-// 1 unable to access process (insufficient rights?)
-// 2 unable to read process working set
-// 3 unable to set process working set - bad parameters?
-U14API(short) U14WorkingSet(unsigned int dwMinKb, unsigned int dwMaxKb)
-{
-#ifdef _IS_WINDOWS_
- short sRetVal = 0; // 0 means all is OK
- HANDLE hProcess;
- unsigned int dwVer = GetVersion();
- if (dwVer & 0x80000000) // is this not NT?
- return 0; // then give up right now
-
- // Now attempt to get information on working set size
- hProcess = OpenProcess(STANDARD_RIGHTS_REQUIRED |
- PROCESS_QUERY_INFORMATION |
- PROCESS_SET_QUOTA,
- FALSE, _getpid());
- if (hProcess)
- {
- SIZE_T dwMinSize,dwMaxSize;
- if (GetProcessWorkingSetSize(hProcess, &dwMinSize, &dwMaxSize))
- {
- unsigned int dwMin = dwMinKb << 10; // convert from kb to bytes
- unsigned int dwMax = dwMaxKb << 10;
-
- // if we get here, we have managed to read the current size
- if (dwMin > dwMinSize) // need to change sizes?
- dwMinSize = dwMin;
-
- if (dwMax > dwMaxSize)
- dwMaxSize = dwMax;
-
- if (!SetProcessWorkingSetSize(hProcess, dwMinSize, dwMaxSize))
- sRetVal = 3; // failed to change size
- }
- else
- sRetVal = 2; // failed to read original size
-
- CloseHandle(hProcess);
- }
- else
- sRetVal = 1; // failed to get handle
-
- return sRetVal;
-#endif
-#ifdef LINUX
- if (dwMinKb | dwMaxKb)
- {
- // to stop compiler moaning
- }
- return U14ERR_NOERROR;
-#endif
-}
-
-/****************************************************************************
-** U14UnSetTransfer Cancels a transfer area
-** wArea The index of a block previously used in by SetTransfer
-*****************************************************************************/
-U14API(short) U14UnSetTransfer(short hand, unsigned short wArea)
-{
- short sErr = CheckHandle(hand);
-#ifdef _IS_WINDOWS_
- if (sErr == U14ERR_NOERROR)
- {
- TCSBLOCK csBlock;
- csBlock.ints[0] = (short)wArea; /* Area number into control block */
- sErr = U14Control1401(hand, U14_UNSETTRANSFER, &csBlock); /* Free area */
-
- VirtualUnlock(apAreas[hand][wArea], auAreas[hand][wArea]);/* Unlock */
- apAreas[hand][wArea] = NULL; /* Clear locations */
- auAreas[hand][wArea] = 0;
- }
- return sErr;
-#endif
-#ifdef LINUX
- return (sErr == U14ERR_NOERROR) ? CED_UnsetTransfer(aHand1401[hand], wArea) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14SetTransArea Sets an area up to be used for transfers
-** unsigned short wArea The area number to set up
-** void *pvBuff The address of the buffer for the data.
-** unsigned int dwLength The length of the buffer for the data
-** short eSz The element size (used for byte swapping on the Mac)
-****************************************************************************/
-U14API(short) U14SetTransArea(short hand, unsigned short wArea, void *pvBuff,
- unsigned int dwLength, short eSz)
-{
- struct transfer_area_desc td;
- short sErr = CheckHandle(hand);
- if (sErr != U14ERR_NOERROR)
- return sErr;
- if (wArea >= MAX_TRANSAREAS) // Is this a valid area number
- return U14ERR_BADAREA;
-
-#ifdef _IS_WINDOWS_
- assert(apAreas[hand][wArea] == NULL);
- assert(auAreas[hand][wArea] == 0);
-
- apAreas[hand][wArea] = pvBuff; /* Save data for later */
- auAreas[hand][wArea] = dwLength;
-
- if (!VirtualLock(pvBuff, dwLength)) /* Lock using WIN32 calls */
- {
- apAreas[hand][wArea] = NULL; /* Clear locations */
- auAreas[hand][wArea] = 0;
- return U14ERR_LOCKERR; /* VirtualLock failed */
- }
-#ifndef _WIN64
- if (!USE_NT_DIOC(hand)) /* Use Win 9x DIOC? */
- {
- unsigned int dwBytes;
- VXTRANSFERDESC vxDesc; /* Structure to pass to VXD */
- vxDesc.wArea = wArea; /* Copy across simple params */
- vxDesc.dwLength = dwLength;
-
- // Check we are not asking an old driver for more than area 0
- if ((wArea != 0) && (U14DriverVersion(hand) < 0x00010002L))
- sErr = U14ERR_DRIVTOOOLD;
- else
- {
- vxDesc.dwAddrOfs = (unsigned int)pvBuff; /* 32 bit offset */
- vxDesc.wAddrSel = 0;
-
- if (DeviceIoControl(aHand1401[hand], (unsigned int)U14_SETTRANSFER,
- pvBuff,dwLength, /* Will translate pointer */
- &vxDesc,sizeof(VXTRANSFERDESC),
- &dwBytes,NULL))
- {
- if (dwBytes >= sizeof(VXTRANSFERDESC)) /* Driver OK ? */
- sErr = U14ERR_NOERROR;
- else
- sErr = U14ERR_DRIVCOMMS; /* Else never got there */
- }
- else
- sErr = (short)GetLastError();
- }
- }
- else
-#endif
- {
- PARAMBLK rWork;
- unsigned int dwBytes;
- td.wArea = wArea; /* Pure NT - put data into struct */
- td.lpvBuff = pvBuff;
- td.dwLength = dwLength;
- td.eSize = 0; // Dummy element size
-
- if (DeviceIoControl(aHand1401[hand],(unsigned int)U14_SETTRANSFER,
- &td,sizeof(struct transfer_area_desc),
- &rWork,sizeof(PARAMBLK),&dwBytes,NULL))
- {
- if (dwBytes >= sizeof(PARAMBLK)) // maybe error from driver?
- sErr = rWork.sState; // will report any error
- else
- sErr = U14ERR_DRIVCOMMS; // Else never got there
- }
- else
- sErr = U14ERR_DRIVCOMMS;
- }
-
- if (sErr != U14ERR_NOERROR)
- {
- if (sErr != U14ERR_LOCKERR) // unless lock failed...
- VirtualUnlock(pvBuff, dwLength); // ...release the lock
- apAreas[hand][wArea] = NULL; // Clear locations
- auAreas[hand][wArea] = 0;
- }
-
- return sErr;
-#endif
-#ifdef LINUX
- // The strange cast is so that it works in 64 and 32-bit linux as long is 64-bits
- // in the 64 bit version.
- td.lpvBuff = (long long)((unsigned long)pvBuff);
- td.wAreaNum = wArea;
- td.dwLength = dwLength;
- td.eSize = eSz; // Dummy element size
- return CED_SetTransfer(aHand1401[hand], &td);
-#endif
-}
-
-/****************************************************************************
-** U14SetTransferEvent Sets an event for notification of application
-** wArea The transfer area index, from 0 to MAXAREAS-1
-** bEvent True to create an event, false to remove it
-** bToHost Set 0 for notification on to1401 tranfers, 1 for
-** notification of transfers to the host PC
-** dwStart The offset of the sub-area of interest
-** dwLength The size of the sub-area of interest
-**
-** The device driver will set the event supplied to the signalled state
-** whenever a DMA transfer to/from the specified area is completed. The
-** transfer has to be in the direction specified by bToHost, and overlap
-** that part of the whole transfer area specified by dwStart and dwLength.
-** It is important that this function is called with bEvent false to release
-** the event once 1401 activity is finished.
-**
-** Returns 1 if an event handle exists, 0 if all OK and no event handle or
-** a negative code for an error.
-****************************************************************************/
-U14API(short) U14SetTransferEvent(short hand, unsigned short wArea, BOOL bEvent,
- BOOL bToHost, unsigned int dwStart, unsigned int dwLength)
-{
-#ifdef _IS_WINDOWS_
- TCSBLOCK csBlock;
- short sErr = U14TransferFlags(hand); // see if we can handle events
- if (sErr >= U14ERR_NOERROR) // check handle is OK
- {
- bEvent = bEvent && ((sErr & U14TF_NOTIFY) != 0); // remove request if we cannot do events
- if (wArea >= MAX_TRANSAREAS) // Check a valid area...
- return U14ERR_BADAREA; // ...and bail of not
-
- // We can hold an event for each area, so see if we need to change the
- // state of the event.
- if ((bEvent != 0) != (aXferEvent[hand] != 0)) // change of event state?
- {
- if (bEvent) // want one and none present
- aXferEvent[hand] = CreateEvent(NULL, FALSE, FALSE, NULL);
- else
- {
- CloseHandle(aXferEvent[hand]); // clear the existing event
- aXferEvent[hand] = NULL; // and clear handle
- }
- }
-
- // We have to store the parameters differently for 64-bit operations
- // because a handle is 64 bits long. The drivers know of this and
- // handle the information appropriately.
-#ifdef _WIN64
- csBlock.longs[0] = wArea; // Pass paramaters into the driver...
- if (bToHost != 0) // The direction flag is held in the
- csBlock.longs[0] |= 0x10000; // upper word of the transfer area value
- *((HANDLE*)&csBlock.longs[1]) = aXferEvent[hand]; // The event handle is 64-bits
- csBlock.longs[3] = dwStart; // Thankfully these two remain
- csBlock.longs[4] = dwLength; // as unsigned 32-bit values
-#else
- csBlock.longs[0] = wArea; // pass paramaters into the driver...
- csBlock.longs[1] = (long)aXferEvent[hand]; // ...especially the event handle
- csBlock.longs[2] = bToHost;
- csBlock.longs[3] = dwStart;
- csBlock.longs[4] = dwLength;
-#endif
- sErr = U14Control1401(hand, U14_SETTRANSEVENT, &csBlock);
- if (sErr == U14ERR_NOERROR)
- sErr = (short)(aXferEvent[hand] != NULL); // report if we have a flag
- }
-
- return sErr;
-#endif
-#ifdef LINUX
- TRANSFEREVENT te;
- short sErr = CheckHandle(hand);
- if (sErr != U14ERR_NOERROR)
- return sErr;
-
- if (wArea >= MAX_TRANSAREAS) // Is this a valid area number
- return U14ERR_BADAREA;
-
- te.wAreaNum = wArea; // copy parameters to the control block
- te.wFlags = bToHost ? 1 : 0; // bit 0 sets the direction
- te.dwStart = dwStart; // start offset of the event area
- te.dwLength = dwLength; // size of the event area
- te.iSetEvent = bEvent; // in Windows, this creates/destroys the event
- return CED_SetEvent(aHand1401[hand], &te);
-#endif
-}
-
-/****************************************************************************
-** U14TestTransferEvent
-** Would a U14WaitTransferEvent() call return immediately? return 1 if so,
-** 0 if not or a negative code if a problem.
-****************************************************************************/
-U14API(int) U14TestTransferEvent(short hand, unsigned short wArea)
-{
-#ifdef _IS_WINDOWS_
- int iErr = CheckHandle(hand);
- if (iErr == U14ERR_NOERROR)
- {
- if (aXferEvent[hand]) // if a handle is set...
- iErr = WaitForSingleObject(aXferEvent[hand], 0) == WAIT_OBJECT_0;
- }
- return iErr;
-#endif
-#ifdef LINUX
- short sErr = CheckHandle(hand);
- return (sErr == U14ERR_NOERROR) ? CED_TestEvent(aHand1401[hand], wArea) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14WaitTransferEvent
-** Wait for a transfer event with a timeout.
-** msTimeOut is 0 for an infinite wait, else it is the maximum time to wait
-** in milliseconds in range 0-0x00ffffff.
-** Returns If no event handle then return immediately. Else return 1 if
-** timed out or 0=event, and a negative code if a problem.
-****************************************************************************/
-U14API(int) U14WaitTransferEvent(short hand, unsigned short wArea, int msTimeOut)
-{
-#ifdef _IS_WINDOWS_
- int iErr = CheckHandle(hand);
- if (iErr == U14ERR_NOERROR)
- {
- if (aXferEvent[hand])
- {
- if (msTimeOut == 0)
- msTimeOut = INFINITE;
- iErr = WaitForSingleObject(aXferEvent[hand], msTimeOut) != WAIT_OBJECT_0;
- }
- else
- iErr = TRUE; // say we timed out if no event
- }
- return iErr;
-#endif
-#ifdef LINUX
- short sErr = CheckHandle(hand);
- return (sErr == U14ERR_NOERROR) ? CED_WaitEvent(aHand1401[hand], wArea, msTimeOut) : sErr;
-#endif
-}
-
-/****************************************************************************
-** U14SetCircular Sets an area up for circular DMA transfers
-** unsigned short wArea The area number to set up
-** BOOL bToHost Sets the direction of data transfer
-** void *pvBuff The address of the buffer for the data
-** unsigned int dwLength The length of the buffer for the data
-****************************************************************************/
-U14API(short) U14SetCircular(short hand, unsigned short wArea, BOOL bToHost,
- void *pvBuff, unsigned int dwLength)
-{
- short sErr = CheckHandle(hand);
- if (sErr != U14ERR_NOERROR)
- return sErr;
-
- if (wArea >= MAX_TRANSAREAS) /* Is this a valid area number */
- return U14ERR_BADAREA;
-
- if (!bToHost) /* For now, support tohost transfers only */
- return U14ERR_BADAREA; /* best error code I can find */
-#ifdef _IS_WINDOWS_
- assert(apAreas[hand][wArea] == NULL);
- assert(auAreas[hand][wArea] == 0);
-
- apAreas[hand][wArea] = pvBuff; /* Save data for later */
- auAreas[hand][wArea] = dwLength;
-
- if (!VirtualLock(pvBuff, dwLength)) /* Lock using WIN32 calls */
- sErr = U14ERR_LOCKERR; /* VirtualLock failed */
- else
- {
- PARAMBLK rWork;
- unsigned int dwBytes;
- struct transfer_area_desc txDesc;
- txDesc.wArea = wArea; /* Pure NT - put data into struct */
- txDesc.lpvBuff = pvBuff;
- txDesc.dwLength = dwLength;
- txDesc.eSize = (short)bToHost; /* Use this for direction flag */
-
- if (DeviceIoControl(aHand1401[hand],(unsigned int)U14_SETCIRCULAR,
- &txDesc, sizeof(struct transfer_area_desc),
- &rWork, sizeof(PARAMBLK),&dwBytes,NULL))
- {
- if (dwBytes >= sizeof(PARAMBLK)) /* error from driver? */
- sErr = rWork.sState; /* No, just return driver data */
- else
- sErr = U14ERR_DRIVCOMMS; /* Else never got there */
- }
- else
- sErr = U14ERR_DRIVCOMMS;
- }
-
- if (sErr != U14ERR_NOERROR)
- {
- if (sErr != U14ERR_LOCKERR)
- VirtualUnlock(pvBuff, dwLength); /* Release NT lock */
- apAreas[hand][wArea] = NULL; /* Clear locations */
- auAreas[hand][wArea] = 0;
- }
-
- return sErr;
-#endif
-#ifdef LINUX
- else
- {
- struct transfer_area_desc td;
- td.lpvBuff = (long long)((unsigned long)pvBuff);
- td.wAreaNum = wArea;
- td.dwLength = dwLength;
- td.eSize = (short)bToHost; /* Use this for direction flag */
- return CED_SetCircular(aHand1401[hand], &td);
- }
-#endif
-}
-
-/****************************************************************************
-** Function GetCircBlk returns the size (& start offset) of the next
-** available block of circular data.
-****************************************************************************/
-U14API(int) U14GetCircBlk(short hand, unsigned short wArea, unsigned int *pdwOffs)
-{
- int lErr = CheckHandle(hand);
- if (lErr != U14ERR_NOERROR)
- return lErr;
-
- if (wArea >= MAX_TRANSAREAS) // Is this a valid area number?
- return U14ERR_BADAREA;
- else
- {
-#ifdef _IS_WINDOWS_
- PARAMBLK rWork;
- TCSBLOCK csBlock;
- unsigned int dwBytes;
- csBlock.longs[0] = wArea; // Area number into control block
- rWork.sState = U14ERR_DRIVCOMMS;
- if (DeviceIoControl(aHand1401[hand], (unsigned int)U14_GETCIRCBLK, &csBlock, sizeof(TCSBLOCK), &rWork, sizeof(PARAMBLK), &dwBytes, NULL) &&
- (dwBytes >= sizeof(PARAMBLK)))
- lErr = rWork.sState;
- else
- lErr = U14ERR_DRIVCOMMS;
-
- if (lErr == U14ERR_NOERROR) // Did everything go OK?
- { // Yes, we can pass the results back
- lErr = rWork.csBlock.longs[1]; // Return the block information
- *pdwOffs = rWork.csBlock.longs[0]; // Offset is first in array
- }
-#endif
-#ifdef LINUX
- TCIRCBLOCK cb;
- cb.nArea = wArea; // Area number into control block
- cb.dwOffset = 0;
- cb.dwSize = 0;
- lErr = CED_GetCircBlock(aHand1401[hand], &cb);
- if (lErr == U14ERR_NOERROR) // Did everything go OK?
- { // Yes, we can pass the results back
- lErr = cb.dwSize; // return the size
- *pdwOffs = cb.dwOffset; // and the offset
- }
-#endif
- }
- return lErr;
-}
-
-/****************************************************************************
-** Function FreeCircBlk marks the specified area of memory as free for
-** resuse for circular transfers and returns the size (& start
-** offset) of the next available block of circular data.
-****************************************************************************/
-U14API(int) U14FreeCircBlk(short hand, unsigned short wArea, unsigned int dwOffs, unsigned int dwSize,
- unsigned int *pdwOffs)
-{
- int lErr = CheckHandle(hand);
- if (lErr != U14ERR_NOERROR)
- return lErr;
-
- if (wArea < MAX_TRANSAREAS) // Is this a valid area number
- {
-#ifdef _IS_WINDOWS_
- PARAMBLK rWork;
- TCSBLOCK csBlock;
- unsigned int dwBytes;
- csBlock.longs[0] = wArea; // Area number into control block
- csBlock.longs[1] = dwOffs;
- csBlock.longs[2] = dwSize;
- rWork.sState = U14ERR_DRIVCOMMS;
- if (DeviceIoControl(aHand1401[hand], (unsigned int)U14_FREECIRCBLK, &csBlock, sizeof(TCSBLOCK),
- &rWork, sizeof(PARAMBLK), &dwBytes, NULL) &&
- (dwBytes >= sizeof(PARAMBLK)))
- lErr = rWork.sState;
- else
- lErr = U14ERR_DRIVCOMMS;
- if (lErr == U14ERR_NOERROR) // Did everything work OK?
- { // Yes, we can pass the results back
- lErr = rWork.csBlock.longs[1]; // Return the block information
- *pdwOffs = rWork.csBlock.longs[0]; // Offset is first in array
- }
-#endif
-#ifdef LINUX
- TCIRCBLOCK cb;
- cb.nArea = wArea; // Area number into control block
- cb.dwOffset = dwOffs;
- cb.dwSize = dwSize;
-
- lErr = CED_FreeCircBlock(aHand1401[hand], &cb);
- if (lErr == U14ERR_NOERROR) // Did everything work OK?
- { // Yes, we can pass the results back
- lErr = cb.dwSize; // Return the block information
- *pdwOffs = cb.dwOffset; // Offset is first in array
- }
-#endif
- }
- else
- lErr = U14ERR_BADAREA;
-
- return lErr;
-}
-
-/****************************************************************************
-** Transfer
-** Transfer moves data to 1401 or to host
-** Assumes memory is allocated and locked,
-** which it should be to get a pointer
-*****************************************************************************/
-static short Transfer(short hand, BOOL bTo1401, char* pData,
- unsigned int dwSize, unsigned int dw1401, short eSz)
-{
- char strcopy[MAXSTRLEN+1]; // to hold copy of work string
- short sResult = U14SetTransArea(hand, 0, (void *)pData, dwSize, eSz);
- if (sResult == U14ERR_NOERROR) // no error
- {
- sprintf(strcopy, // data offset is always 0
- "TO%s,$%X,$%X,0;", bTo1401 ? "1401" : "HOST", dw1401, dwSize);
-
- U14SendString(hand, strcopy); // send transfer string
-
- sResult = U14CheckErr(hand); // Use ERR command to check for done
- if (sResult > 0)
- sResult = U14ERR_TOXXXERR; // If a 1401 error, use this code
-
- U14UnSetTransfer(hand, 0);
- }
- return sResult;
-}
-
-/****************************************************************************
-** Function ToHost transfers data into the host from the 1401
-****************************************************************************/
-U14API(short) U14ToHost(short hand, char* pAddrHost, unsigned int dwSize,
- unsigned int dw1401, short eSz)
-{
- short sErr = CheckHandle(hand);
- if ((sErr == U14ERR_NOERROR) && dwSize) // TOHOST is a constant
- sErr = Transfer(hand, TOHOST, pAddrHost, dwSize, dw1401, eSz);
- return sErr;
-}
-
-/****************************************************************************
-** Function To1401 transfers data into the 1401 from the host
-****************************************************************************/
-U14API(short) U14To1401(short hand, const char* pAddrHost,unsigned int dwSize,
- unsigned int dw1401, short eSz)
-{
- short sErr = CheckHandle(hand);
- if ((sErr == U14ERR_NOERROR) && dwSize) // TO1401 is a constant
- sErr = Transfer(hand, TO1401, (char*)pAddrHost, dwSize, dw1401, eSz);
- return sErr;
-}
-
-/****************************************************************************
-** Function LdCmd Loads a command from a full path or just a file
-*****************************************************************************/
-#ifdef _IS_WINDOWS_
-#define file_exist(name) (_access(name, 0) != -1)
-#define file_open(name) _lopen(name, OF_READ)
-#define file_close(h) _lclose(h)
-#define file_seek(h, pos) _llseek(h, pos, FILE_BEGIN)
-#define file_read(h, buffer, size) (_lread(h, buffer, size) == size)
-#endif
-#ifdef LINUX
-#define file_exist(name) (access(name, F_OK) != -1)
-#define file_open(name) open(name, O_RDONLY)
-#define file_close(h) close(h)
-#define file_seek(h, pos) lseek(h, pos, SEEK_SET)
-#define file_read(h, buffer, size) (read(h, buffer, size) == (ssize_t)size)
-static unsigned int GetModuleFileName(void* dummy, char* buffer, int max)
-{
- // The following works for Linux systems with a /proc file system.
- char szProcPath[32];
- sprintf(szProcPath, "/proc/%d/exe", getpid()); // attempt to read link
- if (readlink(szProcPath, buffer, max) != -1)
- {
- dirname (buffer);
- strcat (buffer, "/");
- return strlen(buffer);
- }
- return 0;
-}
-#endif
-
-U14API(short) U14LdCmd(short hand, const char* command)
-{
- char strcopy[MAXSTRLEN+1]; // to hold copy of work string
- BOOL bGotIt = FALSE; // have we found the command file?
- int iFHandle; // file handle of command
-#define FNSZ 260
- char filnam[FNSZ]; // space to build name in
- char szCmd[25]; // just the command name with extension
-
- short sErr = CheckHandle(hand);
- if (sErr != U14ERR_NOERROR)
- return sErr;
-
- if (strchr(command, '.') != NULL) // see if we have full name
- {
- if (file_exist(command)) // If the file exists
- {
- strcpy(filnam, command); // use name as is
- bGotIt = TRUE; // Flag no more searching
- }
- else // not found, get file name for search
- {
- char* pStr = strrchr(command, PATHSEP); // Point to last separator
- if (pStr != NULL) // Check we got it
- {
- pStr++; // move past the backslash
- strcpy(szCmd, pStr); // copy file name as is
- }
- else
- strcpy(szCmd, command); // use as is
- }
- }
- else // File extension not supplied, so build the command file name
- {
- char szExt[8];
- strcpy(szCmd, command); // Build command file name
- ExtForType(asType1401[hand], szExt);// File extension string
- strcat(szCmd, szExt); // add it to the end
- }
-
- // Next place to look is in the 1401 folder in the same place as the
- // application was run from.
- if (!bGotIt) // Still not got it?
- {
- unsigned int dwLen = GetModuleFileName(NULL, filnam, FNSZ); // Get app path
- if (dwLen > 0) // and use it as path if found
- {
- char* pStr = strrchr(filnam, PATHSEP); // Point to last separator
- if (pStr != NULL)
- {
- *(++pStr) = 0; // Terminate string there
- if (strlen(filnam) < FNSZ-6) // make sure we have space
- {
- strcat(filnam, "1401" PATHSEPSTR); // add in 1401 subdir
- strcat(filnam,szCmd);
- bGotIt = (BOOL)file_exist(filnam); // See if file exists
- }
- }
- }
- }
-
- // Next place to look is in whatever path is set by the 1401DIR environment
- // variable, if it exists.
- if (!bGotIt) // Need to do more searches?/
- {
- char* pStr = getenv("1401DIR"); // Try to find environment var
- if (pStr != NULL) // and use it as path if found
- {
- strcpy(filnam, pStr); // Use path in environment
- if (filnam[strlen(filnam)-1] != PATHSEP)// We need separator
- strcat(filnam, PATHSEPSTR);
- strcat(filnam, szCmd);
- bGotIt = (BOOL)file_exist(filnam); // Got this one?
- }
- }
-
- // Last place to look is the default location.
- if (!bGotIt) // Need to do more searches?
- {
- strcpy(filnam, DEFCMDPATH); // Use default path
- strcat(filnam, szCmd);
- bGotIt = file_exist(filnam); // Got this one?
- }
-
- iFHandle = file_open(filnam);
- if (iFHandle == -1)
- sErr = U14ERR_NOFILE;
- else
- { // first read in the header block
- CMDHEAD rCmdHead; // to hold the command header
- if (file_read(iFHandle, &rCmdHead, sizeof(CMDHEAD)))
- {
- size_t nComSize = rCmdHead.wCmdSize;
- char* pMem = malloc(nComSize);
- if (pMem != NULL)
- {
- file_seek(iFHandle, sizeof(CMDHEAD));
- if (file_read(iFHandle, pMem, (UINT)nComSize))
- {
- sErr = U14SetTransArea(hand, 0, (void *)pMem, (unsigned int)nComSize, ESZBYTES);
- if (sErr == U14ERR_NOERROR)
- {
- sprintf(strcopy, "CLOAD,0,$%X;", (int)nComSize);
- sErr = U14SendString(hand, strcopy);
- if (sErr == U14ERR_NOERROR)
- {
- sErr = U14CheckErr(hand); // Use ERR to check for done
- if (sErr > 0)
- sErr = U14ERR_CLOADERR; // If an error, this code
- }
- U14UnSetTransfer(hand, 0); // release transfer area
- }
- }
- else
- sErr = U14ERR_READERR;
- free(pMem);
- }
- else
- sErr = U14ERR_HOSTSPACE; // memory allocate failed
- }
- else
- sErr = U14ERR_READERR;
-
- file_close(iFHandle); // close the file
- }
-
- return sErr;
-}
-
-
-/****************************************************************************
-** Ld
-** Loads a command into the 1401
-** Returns NOERROR code or a long with error in lo word and index of
-** command that failed in high word
-****************************************************************************/
-U14API(unsigned int) U14Ld(short hand, const char* vl, const char* str)
-{
- unsigned int dwIndex = 0; // index to current command
- long lErr = U14ERR_NOERROR; // what the error was that went wrong
- char strcopy[MAXSTRLEN+1]; // stores unmodified str parameter
- char szFExt[8]; // The command file extension
- short sErr = CheckHandle(hand);
- if (sErr != U14ERR_NOERROR)
- return sErr;
-
- ExtForType(asType1401[hand], szFExt); // File extension string
- strcpy(strcopy, str); // to avoid changing original
-
- // now break out one command at a time and see if loaded
- if (*str) // if anything there
- {
- BOOL bDone = FALSE; // true when finished all commands
- int iLoop1 = 0; // Point at start of string for command name
- int iLoop2 = 0; // and at start of str parameter
- do // repeat until end of str
- {
- char filnam[MAXSTRLEN+1]; // filename to use
- char szFName[MAXSTRLEN+1]; // filename work string
-
- if (!strcopy[iLoop1]) // at the end of the string?
- bDone = TRUE; // set the finish flag
-
- if (bDone || (strcopy[iLoop1] == ',')) // end of cmd?
- {
- U14LONG er[5]; // Used to read back error results
- ++dwIndex; // Keep count of command number, first is 1
- szFName[iLoop2]=(char)0; // null terminate name of command
-
- strncpy(szLastName, szFName, sizeof(szLastName)); // Save for error info
- szLastName[sizeof(szLastName)-1] = 0;
- strncat(szLastName, szFExt, sizeof(szLastName)); // with extension included
- szLastName[sizeof(szLastName)-1] = 0;
-
- U14SendString(hand, szFName); // ask if loaded
- U14SendString(hand, ";ERR;"); // add err return
-
- lErr = U14LongsFrom1401(hand, er, 5);
- if (lErr > 0)
- {
- lErr = U14ERR_NOERROR;
- if (er[0] == 255) // if command not loaded at all
- {
- if (vl && *vl) // if we have a path name
- {
- strcpy(filnam, vl);
- if (strchr("\\/:", filnam[strlen(filnam)-1]) == NULL)
- strcat(filnam, PATHSEPSTR); // add separator if none found
- strcat(filnam, szFName); // add the file name
- strcat(filnam, szFExt); // and extension
- }
- else
- strcpy(filnam, szFName); // simple name
-
- lErr = U14LdCmd(hand, filnam); // load cmd
- if (lErr != U14ERR_NOERROR) // spot any errors
- bDone = TRUE; // give up if an error
- }
- }
- else
- bDone = TRUE; // give up if an error
-
- iLoop2 = 0; // Reset pointer to command name string
- ++iLoop1; // and move on through str parameter
- }
- else
- szFName[iLoop2++] = strcopy[iLoop1++]; // no command end, so copy 1 char
- }
- while (!bDone);
- }
-
- if (lErr == U14ERR_NOERROR)
- {
- szLastName[0] = 0; // No error, so clean out command name here
- return lErr;
- }
- else
- return ((dwIndex<<16) | ((unsigned int)lErr & 0x0000FFFF));
-}
-
-// Initialise the library (if not initialised) and return the library version
-U14API(int) U14InitLib(void)
-{
- int iRetVal = U14LIB_VERSION;
- if (iAttached == 0) // only do this the first time please
- {
- int i;
-#ifdef _IS_WINDOWS_
- int j;
- unsigned int dwVersion = GetVersion();
- bWindows9x = FALSE; // Assume not Win9x
-
- if (dwVersion & 0x80000000) // if not windows NT
- {
- if ((LOBYTE(LOWORD(dwVersion)) < 4) && // if Win32s or...
- (HIBYTE(LOWORD(dwVersion)) < 95)) // ...below Windows 95
- iRetVal = 0; // We do not support this
- else
- bWindows9x = TRUE; // Flag we have Win9x
- }
-#endif
-
- for (i = 0; i < MAX1401; i++) // initialise the device area
- {
- aHand1401[i] = INVALID_HANDLE_VALUE; // Clear handle values
- asType1401[i] = U14TYPEUNKNOWN; // and 1401 type codes
- alTimeOutPeriod[i] = 3000; // 3 second timeouts
-#ifdef _IS_WINDOWS_
-#ifndef _WIN64
- abUseNTDIOC[i] = (BOOL)!bWindows9x;
-#endif
- aXferEvent[i] = NULL; // there are no Xfer events
- for (j = 0; j < MAX_TRANSAREAS; j++) // Clear out locked area info
- {
- apAreas[i][j] = NULL;
- auAreas[i][j] = 0;
- }
-#endif
- }
- }
- return iRetVal;
-}
-
-///--------------------------------------------------------------------------------
-/// Functions called when the library is loaded and unloaded to give us a chance to
-/// setup the library.
-
-
-#ifdef _IS_WINDOWS_
-#ifndef U14_NOT_DLL
-/****************************************************************************
-** FUNCTION: DllMain(HANDLE, unsigned int, LPVOID)
-** LibMain is called by Windows when the DLL is initialized, Thread Attached,
-** and other times. Refer to SDK documentation, as to the different ways this
-** may be called.
-****************************************************************************/
-INT APIENTRY DllMain(HANDLE hInst, unsigned int ul_reason_being_called, LPVOID lpReserved)
-{
- int iRetVal = 1;
-
- switch (ul_reason_being_called)
- {
- case DLL_PROCESS_ATTACH:
- iRetVal = U14InitLib() > 0; // does nothing if iAttached != 0
- ++iAttached; // count times attached
- break;
-
- case DLL_PROCESS_DETACH:
- if (--iAttached == 0) // last man out?
- U14CloseAll(); // release all open handles
- break;
- }
- return iRetVal;
-
- UNREFERENCED_PARAMETER(lpReserved);
-}
-#endif
-#endif
-#ifdef LINUX
-void __attribute__((constructor)) use1401_load(void)
-{
- U14InitLib();
- ++iAttached;
-}
-
-void __attribute__((destructor)) use1401_unload(void)
-{
- if (--iAttached == 0) // last man out?
- U14CloseAll(); // release all open handles
-}
-#endif