#include <linux/init.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
-#include <linux/bitops.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
+#include <asm/bitops.h>
#define CY_LOCK(info,flags) \
do { \
static long maddr[NR_CARDS] = { 0, };
static int irq[NR_CARDS] = { 0, };
-module_param_array(maddr, long, NULL, 0);
-module_param_array(irq, int, NULL, 0);
+MODULE_PARM(maddr, "1-" __MODULE_STRING(NR_CARDS) "l");
+MODULE_PARM(irq, "1-" __MODULE_STRING(NR_CARDS) "i");
#endif
#endif /* CONFIG_ISA */
#ifdef CY_DEBUG_WAIT_UNTIL_SENT
printk("Not clean (jiff=%lu)...", jiffies);
#endif
- if (msleep_interruptible(jiffies_to_msecs(char_time)))
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(char_time);
+ if (signal_pending(current))
break;
if (timeout && time_after(jiffies, orig_jiffies + timeout))
break;
}
+ current->state = TASK_RUNNING;
} else {
// Nothing to do!
}
/* Run one more char cycle */
- msleep_interruptible(jiffies_to_msecs(char_time * 5));
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(char_time * 5);
#ifdef CY_DEBUG_WAIT_UNTIL_SENT
printk("Clean (jiff=%lu)...done\n", jiffies);
#endif
if (info->blocked_open) {
CY_UNLOCK(info, flags);
if (info->close_delay) {
- msleep_interruptible(jiffies_to_msecs(info->close_delay));
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(info->close_delay);
}
wake_up_interruptible(&info->open_wait);
CY_LOCK(info, flags);
*
*/
static int
-cy_write(struct tty_struct * tty, const unsigned char *buf, int count)
+cy_write(struct tty_struct * tty, int from_user,
+ const unsigned char *buf, int count)
{
struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
unsigned long flags;
return 0;
}
- CY_LOCK(info, flags);
- while (1) {
- c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1),
+ if (from_user) {
+ down(&tmp_buf_sem);
+ while (1) {
+ int c1;
+
+ c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1),
+ (int)(SERIAL_XMIT_SIZE - info->xmit_head)));
+ if (c <= 0)
+ break;
+
+ c -= copy_from_user(tmp_buf, buf, c);
+ if (!c) {
+ if (!ret) {
+ ret = -EFAULT;
+ }
+ break;
+ }
+ CY_LOCK(info, flags);
+ c1 = min(c, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1),
+ (int)(SERIAL_XMIT_SIZE - info->xmit_head)));
+
+ if (c1 < c)
+ c = c1;
+ memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
+ info->xmit_head = ((info->xmit_head + c) & (SERIAL_XMIT_SIZE-1));
+ info->xmit_cnt += c;
+ CY_UNLOCK(info, flags);
+ buf += c;
+ count -= c;
+ ret += c;
+ }
+ up(&tmp_buf_sem);
+ } else {
+ CY_LOCK(info, flags);
+ while (1) {
+ c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1),
(int)(SERIAL_XMIT_SIZE - info->xmit_head)));
- if (c <= 0)
- break;
+ if (c <= 0)
+ break;
- memcpy(info->xmit_buf + info->xmit_head, buf, c);
- info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
- info->xmit_cnt += c;
- buf += c;
- count -= c;
- ret += c;
+ memcpy(info->xmit_buf + info->xmit_head, buf, c);
+ info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+ info->xmit_cnt += c;
+ buf += c;
+ count -= c;
+ ret += c;
+ }
+ CY_UNLOCK(info, flags);
}
- CY_UNLOCK(info, flags);
info->idle_stats.xmit_bytes += ret;
info->idle_stats.xmit_idle = jiffies;
for (i = 0; i < NR_CARDS; i++) {
/* look for a Cyclades card by vendor and device id */
while((device_id = cy_pci_dev_id[dev_index]) != 0) {
- if((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES,
+ if((pdev = pci_find_device(PCI_VENDOR_ID_CYCLADES,
device_id, pdev)) == NULL) {
dev_index++; /* try next device id */
} else {
}
for (j = 1; j <= ints[0]; j++){
if ( i < NR_ISA_ADDRS ){
- cy_isa_addresses[i++] = ints[j];
+ cy_isa_addresses[i++] = (unsigned char *)(ints[j]);
}
}
#endif /* CONFIG_ISA */