diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 12b092ce0d0f..0a92dc6ab77c 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 29fa5df5b969..fe5e76cd4cde 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 ae36d1b2ba99..000000000000 --- 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 f0c114b2b4b9..000000000000 --- 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 9fd5630bdf4d..000000000000 --- 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 and Cc: -Alois Schlögl - diff --git a/drivers/staging/ced1401/ced_ioc.c b/drivers/staging/ced1401/ced_ioc.c deleted file mode 100644 index 8cb6ea951adf..000000000000 --- 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@ced.co.uk) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 4b6c9dedb21e..000000000000 --- 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@ced.co.uk) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#ifndef __CED_IOCTL_H__ -#define __CED_IOCTL_H__ - -#include - -/* 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 dbd4036d9bdd..000000000000 --- 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@ced.co.uk -** -** This file is included at the start of 'C' or 'C++' source file to define -** things for cross-platform/compiler interoperability. This used to deal with -** MSDOS/16-bit stuff, but this was all removed in Decemeber 2010. There are -** three things to consider: Windows, LINUX, mac OSX (BSD Unix) and 32 vs 64 -** bit. At the time of writing (DEC 2010) there is a consensus on the following -** and their unsigned equivalents: -** -** type bits -** char 8 -** short 16 -** int 32 -** long long 64 -** -** long is a problem as it is always 64 bits on linux/unix and is always 32 bits -** on windows. -** On windows, we define _IS_WINDOWS_ and one of WIN32 or WIN64. -** On linux we define LINUX -** On Max OSX we define MACOSX -** -*/ - -#ifndef __MACHINE_H__ -#define __MACHINE_H__ -#ifndef __KERNEL__ -#include -#include -#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 -#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 99886778966b..000000000000 --- 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@kroah.com) - Copyright (C) 2012 Alois Schloegl - There is not a great deal of the skeleton left. - - All the remainder dealing specifically with the CED1401 is based on drivers - written by CED for other systems (mainly Windows) and is: - Copyright (C) 2010 Cambridge Electronic Design Ltd - Author Greg P Smith (greg@ced.co.uk) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -Endpoints -********* -There are 4 endpoints plus the control endpoint in the standard interface -provided by most 1401s. The control endpoint is used for standard USB requests, -plus various CED-specific transactions such as start self test, debug and get -the 1401 status. The other endpoints are: - - 1 Characters to the 1401 - 2 Characters from the 1401 - 3 Block data to the 1401 - 4 Block data to the host. - -inside the driver these are indexed as an array from 0 to 3, transactions -over the control endpoint are carried out using a separate mechanism. The -use of the endpoints is mostly straightforward, with the driver issuing -IO request packets (IRPs) as required to transfer data to and from the 1401. -The handling of endpoint 2 is different because it is used for characters -from the 1401, which can appear spontaneously and without any other driver -activity - for example to repeatedly request DMA transfers in Spike2. The -desired effect is achieved by using an interrupt endpoint which can be -polled to see if it has data available, and writing the driver so that it -always maintains a pending read IRP from that endpoint which will read the -character data and terminate as soon as the 1401 makes data available. This -works very well, some care is taken with when you kick off this character -read IRP to avoid it being active when it is not wanted but generally it -is running all the time. - -In the 2270, there are only three endpoints plus the control endpoint. In -addition to the transactions mentioned above, the control endpoint is used -to transfer character data to the 1401. The other endpoints are used as: - - 1 Characters from the 1401 - 2 Block data to the 1401 - 3 Block data to the host. - -The type of interface available is specified by the interface subclass field -in the interface descriptor provided by the 1401. See the USB_INT_ constants -for the values that this field can hold. - -**************************************************************************** -Linux implementation - -Although Linux Device Drivers (3rd Edition) was a major source of information, -it is very out of date. A lot of information was gleaned from the latest -usb_skeleton.c code (you need to download the kernel sources to get this). - -To match the Windows version, everything is done using ioctl calls. All the -device state is held in the struct ced_data. -Block transfers are done by using get_user_pages() to pin down a list of -pages that we hold a pointer to in the device driver. We also allocate a -coherent transfer buffer of size STAGED_SZ (this must be a multiple of the -bulk endpoint size so that the 1401 does not realise that we break large -transfers down into smaller pieces). We use kmap_atomic() to get a kernel -va for each page, as it is required, for copying; see ced_copy_user_space(). - -All character and data transfers are done using asynchronous IO. All Urbs are -tracked by anchoring them. Status and debug ioctls are implemented with the -synchronous non-Urb based transfers. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 da4d90cd49a0..000000000000 --- 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@ced.co.uk) - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -#ifndef __USB1401_H__ -#define __USB1401_H__ -#include "use1401.h" -#include "ced_ioctl.h" - -#ifndef UINT -#define UINT unsigned int -#endif - -/** Device type codes, but these don't need to be extended - a succession is assumed -** These are set for usb from the bcdDevice field (suitably mangled). Future devices -** will be added in order of device creation to the list, so the names here are just -** to help use remember which device is which. The U14ERR_... values follow the same -** pattern for modern devices.a -**/ -#define TYPEUNKNOWN -1 /* dont know */ -#define TYPE1401 0 /* standard 1401 */ -#define TYPEPLUS 1 /* 1401 plus */ -#define TYPEU1401 2 /* u1401 */ -#define TYPEPOWER 3 /* Power1401 */ -#define TYPEU14012 4 /* u1401 mkII */ -#define TYPEPOWER2 5 /* Power1401 mk II */ -#define TYPEMICRO3 6 /* Micro1401-3 */ -#define TYPEPOWER3 7 /* Power1401-3 */ - -/* Some useful defines of constants. DONT FORGET to change the version in the */ -/* resources whenever you change it here!. */ -#define DRIVERMAJREV 2 /* driver revision level major (match windows) */ -#define DRIVERMINREV 0 /* driver revision level minor */ - -/* Definitions of the various block transfer command codes */ -#define TM_EXTTOHOST 8 /* extended tohost */ -#define TM_EXTTO1401 9 /* extended to1401 */ - -/* Definitions of values in usbReqtype. Used in sorting out setup actions */ -#define H_TO_D 0x00 -#define D_TO_H 0x80 -#define VENDOR 0x40 -#define DEVREQ 0x00 -#define INTREQ 0x01 -#define ENDREQ 0x02 - -/* Definition of values in usbRequest, again used to sort out setup */ -#define GET_STATUS 0x00 -#define CLEAR_FEATURE 0x01 -#define SET_FEATURE 0x03 -#define SET_ADDRESS 0x05 -#define GET_DESC 0x06 -#define SET_DESC 0x07 -#define GET_CONF 0x08 -#define SET_CONF 0x09 -#define GET_INTERFACE 0x0a -#define SET_INTERFACE 0x0b -#define SYNCH_FRAME 0x0c - -/* Definitions of the various debug command codes understood by the 1401. These */ -/* are used in various vendor-specific commands to achieve the desired effect */ -#define DB_GRAB 0x50 /* Grab is a NOP for USB */ -#define DB_FREE 0x51 /* Free is a NOP for the USB */ -#define DB_SETADD 0x52 /* Set debug address (double) */ -#define DB_SELFTEST 0x53 /* Start self test */ -#define DB_SETMASK 0x54 /* Set enable mask (double) */ -#define DB_SETDEF 0x55 /* Set default mask (double) */ -#define DB_PEEK 0x56 /* Peek address, save result */ -#define DB_POKE 0x57 /* Poke address with data (double) */ -#define DB_RAMPD 0x58 /* Ramp data at debug address */ -#define DB_RAMPA 0x59 /* Ramp address bus */ -#define DB_REPEATS 0x5A /* Set repeats for operations (double) */ -#define DB_WIDTH 0x5B /* Set width for operations (byte) */ -#define DB_DATA 0x5C /* Get 4-byte data read by PEEK */ -#define DB_CHARS 0x5D /* Send chars via EP0 control write */ - -#define CR_CHAR 0x0D /* The carriage return character */ -#define CR_CHAR_80 0x8d /* and with bit 7 set */ - -/* A structure holding information about a block */ -/* of memory for use in circular transfers */ -struct circ_blk { - volatile UINT offset; /* Offset within area of block start */ - volatile UINT size; /* Size of the block, in bytes (0 = unused) */ -}; - -/* A structure holding all of the information about a transfer area - an area */ -/* of memory set up for use either as a source or destination in DMA */ -/* transfers. */ -struct transarea { - /* User address of xfer area saved for completeness */ - void __user *buff; - - /* offset to start of xfer area in first page */ - UINT base_offset; - - UINT length; /* Length of xfer area, in bytes */ - struct page **pages; /* Points at array of locked down pages */ - int n_pages; /* number of pages that are locked down */ - bool used; /* Is this structure in use? */ - bool circular; /* Is this area for circular transfers? */ - bool circ_to_host; /* Flag for direction of circular transfer */ - bool event_to_host; /* Set event on transfer to host? */ - int wake_up; /* Set 1 on event, cleared by TestEvent() */ - UINT event_st; /* Defines section within xfer area for... */ - UINT event_sz; /* notification by the event SZ is 0 if unset */ - struct circ_blk blocks[2]; /* Info on a pair of circular blocks */ - - wait_queue_head_t event; /* The wait queue for events in this */ - /* area MUST BE LAST */ -}; - -/* The dmadesc structure is used to hold information on the transfer in */ -/* progress. It is set up by ReadDMAInfo, using information sent by the 1401 */ -/* in an escape sequence. */ -struct dmadesc { - unsigned short trans_type; /* transfer type as TM_xxx above */ - unsigned short ident; /* identifier word */ - unsigned int size; /* bytes to transfer */ - unsigned int offset; /* offset into transfer area for trans */ - bool outward; /* true when data is going TO 1401 */ -}; - -#define INBUF_SZ 256 /* input buffer size */ -#define OUTBUF_SZ 256 /* output buffer size */ -#define STAGED_SZ 0x10000 /* size of coherent buffer for staged transfers */ - -/* Structure to hold all of our device specific stuff. We are making this as */ -/* similar as we can to the Windows driver to help in our understanding of */ -/* what is going on. */ -struct ced_data { - char input_buffer[INBUF_SZ]; /* The two buffers */ - char output_buffer[OUTBUF_SZ]; /* accessed by the host functions */ - volatile unsigned int num_input; /* num of chars in input buffer */ - volatile unsigned int in_buff_get; /* where to get from input buffer */ - volatile unsigned int in_buff_put; /* where to put into input buffer */ - volatile unsigned int num_output; /* num of chars in output buffer */ - volatile unsigned int out_buff_get; /* where to get from output buffer*/ - volatile unsigned int out_buff_put; /* where to put into output buffer*/ - - volatile bool send_chars_pending; /* Flag to indicate sendchar active */ - volatile bool read_chars_pending; /* Flag to indicate a read is primed*/ - char *coher_char_out; /* special aligned buffer for chars to 1401 */ - struct urb *urb_char_out; /* urb used for chars to 1401 */ - char *coher_char_in; /* special aligned buffer for chars to host */ - struct urb *urb_char_in; /* urb used for chars to host */ - - spinlock_t char_out_lock; /* protect the output_buffer and outputting */ - spinlock_t char_in_lock; /* protect the input_buffer and char reads */ - __u8 interval; /* Interrupt end point interval */ - - volatile unsigned int dma_flag; /* state of DMA */ - struct transarea trans_def[MAX_TRANSAREAS]; /* transfer area info */ - volatile struct dmadesc dma_info; /* info on current DMA transfer */ - volatile bool xfer_waiting; /* Flag set if DMA transfer stalled */ - volatile bool in_draw_down; /* Flag that we want to halt transfers */ - - /* Parameters relating to a block read\write that is in progress. Some of these values */ - /* are equivalent to values in dma_info. The values here are those in use, while those */ - /* in dma_info are those received from the 1401 via an escape sequence. If another */ - /* escape sequence arrives before the previous xfer ends, dma_info values are updated while these */ - /* are used to finish off the current transfer. */ - volatile short staged_id; /* The transfer area id for this transfer */ - volatile bool staged_read; /* Flag TRUE for read from 1401, FALSE for write */ - volatile unsigned int staged_length; /* Total length of this transfer */ - volatile unsigned int staged_offset; /* Offset within memory area for transfer start */ - volatile unsigned int staged_done; /* Bytes transferred so far */ - volatile bool staged_urb_pending; /* Flag to indicate active */ - char *coher_staged_io; /* buffer used for block transfers */ - struct urb *staged_urb; /* The URB to use */ - spinlock_t staged_lock; /* protects ReadWriteMem() and */ - /* circular buffer stuff */ - - short type; /* type of 1401 attached */ - short current_state; /* current error state */ - bool is_usb2; /* type of the interface we connect to */ - bool force_reset; /* Flag to make sure we get a real reset */ - __u32 stat_buf[2]; /* buffer for 1401 state info */ - - unsigned long self_test_time; /* used to timeout self test */ - - int n_pipes; /* Should be 3 or 4 depending on 1401 usb chip */ - int pipe_error[4]; /* set non-zero if an error on one of the pipe */ - __u8 ep_addr[4]; /* addresses of the 3/4 end points */ - - struct usb_device *udev; /* the usb device for this device */ - struct usb_interface *interface; /* the interface for this device, NULL if removed */ - struct usb_anchor submitted; /* in case we need to retract our submissions */ - struct mutex io_mutex; /* synchronize I/O with disconnect, one user-mode caller at a time */ - - int errors; /* the last request tanked */ - int open_count; /* count the number of openers */ - spinlock_t err_lock; /* lock for errors */ - struct kref kref; -}; - -#define to_ced_data(d) container_of(d, struct ced_data, kref) - -/* Definitions of routimes used between compilation object files */ -/* in usb1401.c */ -extern int ced_allowi(struct ced_data *ced); -extern int ced_send_chars(struct ced_data *ced); -extern void ced_draw_down(struct ced_data *ced); -extern int ced_read_write_mem(struct ced_data *ced, bool read, - unsigned short ident, unsigned int offs, - unsigned int len); - -/* in ced_ioc.c */ -extern int ced_clear_area(struct ced_data *ced, int area); -extern int ced_send_string(struct ced_data *ced, const char __user *data, unsigned int n); -extern int ced_send_char(struct ced_data *ced, char c); -extern int ced_get_state(struct ced_data *ced, __u32 *state, __u32 *error); -extern int ced_read_write_cancel(struct ced_data *ced); -extern int ced_reset(struct ced_data *ced); -extern int ced_get_char(struct ced_data *ced); -extern int ced_get_string(struct ced_data *ced, char __user *user, int n); -extern int ced_set_transfer(struct ced_data *ced, - struct transfer_area_desc __user *utd); -extern int ced_unset_transfer(struct ced_data *ced, int area); -extern int ced_set_event(struct ced_data *ced, - struct transfer_event __user *ute); -extern int ced_stat_1401(struct ced_data *ced); -extern int ced_line_count(struct ced_data *ced); -extern int ced_get_out_buf_space(struct ced_data *ced); -extern int ced_get_transfer(struct ced_data *ced, TGET_TX_BLOCK __user *utx); -extern int ced_kill_io(struct ced_data *ced); -extern int ced_state_of_1401(struct ced_data *ced); -extern int ced_start_self_test(struct ced_data *ced); -extern int ced_check_self_test(struct ced_data *ced, - TGET_SELFTEST __user *ugst); -extern int ced_type_of_1401(struct ced_data *ced); -extern int ced_transfer_flags(struct ced_data *ced); -extern int ced_dbg_peek(struct ced_data *ced, TDBGBLOCK __user *udb); -extern int ced_dbg_poke(struct ced_data *ced, TDBGBLOCK __user *udb); -extern int ced_dbg_ramp_data(struct ced_data *ced, TDBGBLOCK __user *udb); -extern int ced_dbg_ramp_addr(struct ced_data *ced, TDBGBLOCK __user *udb); -extern int ced_dbg_get_data(struct ced_data *ced, TDBGBLOCK __user *udb); -extern int ced_dbg_stop_loop(struct ced_data *ced); -extern int ced_set_circular(struct ced_data *ced, - struct transfer_area_desc __user *utd); -extern int ced_get_circ_block(struct ced_data *ced, TCIRCBLOCK __user *ucb); -extern int ced_free_circ_block(struct ced_data *ced, TCIRCBLOCK __user *ucb); -extern int ced_wait_event(struct ced_data *ced, int area, int time_out); -extern int ced_test_event(struct ced_data *ced, int area); -#endif diff --git a/drivers/staging/ced1401/use1401.h b/drivers/staging/ced1401/use1401.h deleted file mode 100644 index b7997c9835c2..000000000000 --- 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 42d2e4e6e9a9..000000000000 --- 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 d589311f1528..000000000000 --- 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@ced.co.uk -** -** Title: USE1401.C -** Version: 4.00 -** Author: Paul Cox, Tim Bergel, Greg Smith -** -** The code was vigorously pruned in DEC 2010 to remove the macintosh options -** and to get rid of the 16-bit support. It has also been aligned with the -** Linux version. See CVS for revisions. This will work for Win 9x onwards. -**************************************************************************** -** -** Notes on Windows interface to driver -** ************************************ -** -** Under Windows 9x and NT, Use1401 uses DeviceIoControl to get access to -** the 1401 driver. This has parameters for the device handle, the function -** code, an input pointer and byte count, an output pointer and byte count -** and a pointer to a unsigned int to hold the output byte count. Note that input -** and output are from the point-of-view of the driver, so the output stuff -** is used to read values from the 1401, not send to the 1401. The use of -** these parameters varies with the function in use and the operating -** system; there are five separate DIOC calls SendString, GetString and -** SetTransferArea all have their own specialised calls, the rest use the -** Status1401 or Control1401 functions. -** -** There are two basic styles of DIOC call used, one for Win9x VxD drivers -** and one for NT Kernel-mode and WDM drivers (see below for tables showing -** the different parameters used. The array bUseNTDIOC[] selects between -** these two calling styles. -** -** Function codes -** In Win3.x, simple function codes from 0 to 40 were used, shifted left 8 -** bits with a sub-function code in the lower 8 bits. These were also used -** in the Windows 95 driver, though we had to add 1 to the code value to -** avoid problems (Open from CreateFile is zero), and the sub-function code -** is now unused. We found that this gave some problems with Windows 98 -** as the function code values are reserved by microsoft, so we switched to -** using the NT function codes instead. The NT codes are generated using the -** CTL_CODE macro, essentially this gives 0x80012000 | (func << 2), where -** func is the original 0 to 34 value. The driver will handle both types of -** code and Use1432 only uses the NT codes if it knows the driver is new -** enough. The array bUseNTCodes[] holds flags on the type of codes required. -** GPS/TDB Dec 2010: we removed the bUseNTCodes array as this is always true -** as we no longer support ancient versions. -** -** The CreateFile and CloseFile function calls are also handled -** by DIOC, using the special function codes 0 and -1 respectively. -** -** Input pointer and buffer size -** These are intended for data sent to the device driver. In nearly all cases -** they are unused in calls to the Win95 driver, the NT driver uses them -** for all information sent to the driver. The table below shows the pointer -** and byte count used for the various calls: -** -** Win 95 Win NT -** SendString NULL, 0 pStr, nStr -** GetString NULL, 0 NULL, 0 -** SetTransferArea pBuf, nBuf (unused?) pDesc, nDesc -** GetTransfer NULL, 0 NULL, 0 -** Status1401 NULL, 0 NULL, 0 -** Control1401 NULL, 0 pBlk, nBlk -** -** pStr and nStr are pointers to a char buffer and the buffer length for -** string I/O, note that these are temporary buffers owned by the DLL, not -** application memory, pBuf and nBuf are the transfer area buffer (I think -** these are unused), pDesc and nDesc are the TRANSFERDESC structure, pBlk -** and nBlk are the TCSBLOCK structure. -** -** -** Output pointer and buffer size -** These are intended for data read from the device driver. These are used -** for almost all information sent to the Win95 driver, the NT driver uses -** them for information read from the driver, chiefly the error code. The -** table below shows the pointer and byte count used for the various calls: -** -** Win 95 Win NT -** SendString pStr, nStr pPar, nPar -** GetString pStr, nStr+2 pStr, nStr+2 -** SetTransferArea pDesc, nDesc pPar, nPar -** GetTransfer pGet, nGet pGet, nGet -** Status1401 pBlk, nBlk pPar, nPar -** Control1401 pBlk, nBlk pPar, nPar -** -** pStr and nStr are pointers to a char buffer and the buffer length for -** string I/O, the +2 for GetString refers to two spare bytes at the start -** used to hold the string length and returning an error code for NT. Note -** again that these are (and must be) DLL-owned temporary buffers. pPar -** and nPar are a PARAM structure used in NT (it holds an error code and a -** TCSBLOCK structure). pDesc and nDesc are the VXTRANSFERDESC structure, -** pBlk and nBlk are the TCSBLOCK structure. pGet and nGet indicate the -** TGET_TX_BLOCK structure used for GetTransfer. -** -** -** The output byte count -** Both drivers return the output buffer size here, regardless of the actual -** bytes output. This is used to check that we did get through to the driver. -** -** Multiple 1401s -** ************** -** -** We have code that tries to support the use of multiple 1401s, but there -** are problems: The lDriverVersion and lDriverType variables are global, not -** per-1401 (a particular problem as the U14 functions that use them don't -** have a hand parameter). In addition, the mechansim for finding a free -** 1401 depends upon the 1401 device driver open operation failing if it's -** already in use, which doesn't always happen, particularly with the VxDs. -** The code in TryToOpen tries to fix this by relying on TYPEOF1401 to detect -** the 1401-in-use state - the VxDs contain special code to help this. This is -** working OK but multiple 1401 support works better with the Win2000 drivers. -** -** USB driver -** ********** -** -** The USB driver, which runs on both Win98 and NT2000, uses the NT-style -** calling convention, both for the DIOC codes and the DIOC parameters. The -** TryToOpen function has been altered to look for an NT driver first in -** the appropriate circumstances, and to set the driver DIOC flags up in -** the correct state. -** -** Adding a new 1401 type - now almost nothing to do -** ************************************************* -** -** The 1401 types are defined by a set of U14TYPExxxx codes in USE1401.H. -** You should add a new one of these to keep things tidy for applications. -** -** DRIVERET_MAX (below) specifies the maximum allowed type code from the -** 1401 driver; I have set this high to accommodate as yet undesigned 1401 -** types. Similarly, as long as the command file names follow the ARM, -** ARN, ARO sequence, these are calculated by the ExtForType function, so -** you don't need to do anything here either. -** -** Version number -** ************** -** The new U14InitLib() function returns 0 if the OS is incapable of use, -** otherwise is returns the version of the USE1401 library. This is done -** in three parts: Major(31-24).Minor(23-16).Revision.(15-0) (brackets are -** the bits used). The Major number starts at 2 for the first revision with -** the U14InitLib() function. Changes to the Major version means that we -** have broken backwards compatibility. Minor number changes mean that we -** have added new functionality that does not break backwards compatibility. -** we starts at 0. Revision changes mean we have fixed something. Each index -** returns to 0 when a higher one changes. -*/ -#define U14LIB_MAJOR 4 -#define U14LIB_MINOR 0 -#define U14LIB_REVISION 0 -#define U14LIB_VERSION ((U14LIB_MAJOR<<24) | (U14LIB_MINOR<<16) | U14LIB_REVISION) - -#include -#include -#include - -#include "USE1401.H" - -#ifdef _IS_WINDOWS_ -#include -#include -#pragma warning(disable: 4100) /* Disable "Unused formal parameter" warning */ -#include -#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 -#include -#include -#include -#include -#include -#include -#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 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