The state of the driver hasn't improved much since it was added to staging, and no one with the hardware is currently working on it, so remove it. This commit can be reverted if someone wants to clean the driver up and move it to its proper place in the kernel. Signed-off-by: Kristina Martšenko <kristina.martsenko@xxxxxxxxx> Cc: Greg Smith <greg@xxxxxxxxx> Cc: Alois Schlögl <alois.schloegl@xxxxxxxxx> --- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/ced1401/Kconfig | 6 - drivers/staging/ced1401/Makefile | 3 - drivers/staging/ced1401/TODO | 10 - drivers/staging/ced1401/ced_ioc.c | 1613 -------------- drivers/staging/ced1401/ced_ioctl.h | 336 --- drivers/staging/ced1401/machine.h | 119 -- drivers/staging/ced1401/usb1401.c | 1767 ---------------- drivers/staging/ced1401/usb1401.h | 260 --- drivers/staging/ced1401/use1401.h | 288 --- drivers/staging/ced1401/use14_ioc.h | 299 --- drivers/staging/ced1401/userspace/use1401.c | 3030 --------------------------- 13 files changed, 7734 deletions(-) delete mode 100644 drivers/staging/ced1401/Kconfig delete mode 100644 drivers/staging/ced1401/Makefile delete mode 100644 drivers/staging/ced1401/TODO delete mode 100644 drivers/staging/ced1401/ced_ioc.c delete mode 100644 drivers/staging/ced1401/ced_ioctl.h delete mode 100644 drivers/staging/ced1401/machine.h delete mode 100644 drivers/staging/ced1401/usb1401.c delete mode 100644 drivers/staging/ced1401/usb1401.h delete mode 100644 drivers/staging/ced1401/use1401.h delete mode 100644 drivers/staging/ced1401/use14_ioc.h delete mode 100644 drivers/staging/ced1401/userspace/use1401.c diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 12b092c..0a92dc6 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -106,8 +106,6 @@ source "drivers/staging/gdm724x/Kconfig" source "drivers/staging/silicom/Kconfig" -source "drivers/staging/ced1401/Kconfig" - source "drivers/staging/imx-drm/Kconfig" source "drivers/staging/fwserial/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 29fa5df..fe5e76c 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -46,7 +46,6 @@ obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/ 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/ diff --git a/drivers/staging/ced1401/Kconfig b/drivers/staging/ced1401/Kconfig deleted file mode 100644 index ae36d1b..0000000 --- a/drivers/staging/ced1401/Kconfig +++ /dev/null @@ -1,6 +0,0 @@ -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.) diff --git a/drivers/staging/ced1401/Makefile b/drivers/staging/ced1401/Makefile deleted file mode 100644 index f0c114b..0000000 --- a/drivers/staging/ced1401/Makefile +++ /dev/null @@ -1,3 +0,0 @@ - -obj-$(CONFIG_CED1401) := cedusb.o -cedusb-objs := usb1401.o ced_ioc.o diff --git a/drivers/staging/ced1401/TODO b/drivers/staging/ced1401/TODO deleted file mode 100644 index 9fd5630..0000000 --- a/drivers/staging/ced1401/TODO +++ /dev/null @@ -1,10 +0,0 @@ -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@xxxxxxxxxxxxxxxxxxx> and Cc: -Alois Schlögl <alois.schloegl@xxxxxxxxx> - diff --git a/drivers/staging/ced1401/ced_ioc.c b/drivers/staging/ced1401/ced_ioc.c deleted file mode 100644 index 8cb6ea9..0000000 --- a/drivers/staging/ced1401/ced_ioc.c +++ /dev/null @@ -1,1613 +0,0 @@ -/* 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@xxxxxxxxx) - - 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; -} diff --git a/drivers/staging/ced1401/ced_ioctl.h b/drivers/staging/ced1401/ced_ioctl.h deleted file mode 100644 index 4b6c9de..0000000 --- a/drivers/staging/ced1401/ced_ioctl.h +++ /dev/null @@ -1,336 +0,0 @@ -/* - * IOCTL calls for the CED1401 driver - * Copyright (C) 2010 Cambridge Electronic Design Ltd - * Author Greg P Smith (greg@xxxxxxxxx) - * - * 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 diff --git a/drivers/staging/ced1401/machine.h b/drivers/staging/ced1401/machine.h deleted file mode 100644 index dbd4036d..0000000 --- a/drivers/staging/ced1401/machine.h +++ /dev/null @@ -1,119 +0,0 @@ -/***************************************************************************** -** -** 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@xxxxxxxxx -** -** 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 diff --git a/drivers/staging/ced1401/usb1401.c b/drivers/staging/ced1401/usb1401.c deleted file mode 100644 index 9988677..0000000 --- a/drivers/staging/ced1401/usb1401.c +++ /dev/null @@ -1,1767 +0,0 @@ -/******************************************************************************* - CED1401 usb driver. This basic loading is based on the usb-skeleton.c code that - is: - Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@xxxxxxxxx) - Copyright (C) 2012 Alois Schloegl <alois.schloegl@xxxxxxxxx> - 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@xxxxxxxxx) - - 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"); diff --git a/drivers/staging/ced1401/usb1401.h b/drivers/staging/ced1401/usb1401.h deleted file mode 100644 index da4d90c..0000000 --- a/drivers/staging/ced1401/usb1401.h +++ /dev/null @@ -1,260 +0,0 @@ -/* 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@xxxxxxxxx) - - 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 diff --git a/drivers/staging/ced1401/use1401.h b/drivers/staging/ced1401/use1401.h deleted file mode 100644 index b7997c9..0000000 --- a/drivers/staging/ced1401/use1401.h +++ /dev/null @@ -1,288 +0,0 @@ -/**************************************************************************** -** 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__ */ - diff --git a/drivers/staging/ced1401/use14_ioc.h b/drivers/staging/ced1401/use14_ioc.h deleted file mode 100644 index 42d2e4e..0000000 --- a/drivers/staging/ced1401/use14_ioc.h +++ /dev/null @@ -1,299 +0,0 @@ -/* 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 diff --git a/drivers/staging/ced1401/userspace/use1401.c b/drivers/staging/ced1401/userspace/use1401.c deleted file mode 100644 index d589311..0000000 --- a/drivers/staging/ced1401/userspace/use1401.c +++ /dev/null @@ -1,3030 +0,0 @@ -/**************************************************************************** -** 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@xxxxxxxxx -** -** 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 -- 1.8.5.5 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel