patch-2.2.15 linux/drivers/net/irda/toshoboe.c
Next file: linux/drivers/net/irda/uircc.c
Previous file: linux/drivers/net/irda/tekram.c
Back to the patch index
Back to the overall index
- Lines: 1034
- Date:
Fri Apr 21 12:46:17 2000
- Orig file:
v2.2.14/drivers/net/irda/toshoboe.c
- Orig date:
Sat Aug 14 02:27:29 1999
diff -u --new-file --recursive --exclude-from ../../exclude v2.2.14/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c
@@ -7,8 +7,10 @@
* Status: Experimental.
* Author: James McKenzie <james@fishsoup.dhs.org>
* Created at: Sat May 8 12:35:27 1999
+ * Modified: Paul Bristow <paul.bristow@technologist.com>
+ * Modified: Mon Nov 11 19:10:05 1999
*
- * Copyright (c) 1999 James McKenzie, All Rights Reserved.
+ * Copyright (c) 1999-2000 James McKenzie, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -28,32 +30,13 @@
/* an olivetti notebook which doesn't have FIR, a toshiba libretto, and */
/* an hp printer, this works fine at 4MBPS with my HP printer */
-static char *rcsid = "$Id: toshoboe.c,v 1.5 1999/05/12 12:24:39 root Exp root $";
-
-/*
- * $Log: toshoboe.c,v $
- * Revision 1.5 1999/05/12 12:24:39 root
- * *** empty log message ***
- *
- * Revision 1.4 1999/05/12 11:55:08 root
- * *** empty log message ***
- *
- * Revision 1.3 1999/05/09 01:33:12 root
- * *** empty log message ***
- *
- * Revision 1.2 1999/05/09 01:30:38 root
- * *** empty log message ***
- *
- * Revision 1.1 1999/05/09 01:25:04 root
- * Initial revision
- *
- */
+static char *rcsid = "$Id: toshoboe.c,v 1.91 1999/06/29 14:21:06 root Exp $";
/* Define this to have only one frame in the XMIT or RECV queue */
/* Toshiba's drivers do this, but it disables back to back tansfers */
/* I think that the chip may have some problems certainly, I have */
/* seen it jump over tasks in the taskfile->xmit with this turned on */
-#define ONETASK
+#define ONETASK
/* To adjust the number of tasks in use edit toshoboe.h */
@@ -83,6 +66,7 @@
#include <linux/malloc.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/rtnetlink.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -93,6 +77,10 @@
#include <net/irda/irlap_frame.h>
#include <net/irda/irda_device.h>
+#ifdef CONFIG_APM
+#include <linux/apm_bios.h>
+#endif
+
#include <net/irda/toshoboe.h>
static char *driver_name = "toshoboe";
@@ -100,11 +88,13 @@
static struct toshoboe_cb *dev_self[NSELFS + 1] =
{NULL, NULL, NULL, NULL, NULL};
+static int max_baud = 4000000;
+
/* Shutdown the chip and point the taskfile reg somewhere else */
-static void
+static void
toshoboe_stopchip (struct toshoboe_cb *self)
{
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
outb_p (0x0e, OBOE_REG_11);
@@ -117,16 +107,19 @@
outb_p (0x00, OBOE_ISR); /*FIXME: should i do this to disbale ints */
outb_p (0x80, OBOE_RST);
outb_p (0xe, OBOE_LOCK);
+
}
/*Set the baud rate */
-static void
+static void
toshoboe_setbaud (struct toshoboe_cb *self, int baud)
{
- DEBUG (4, __FUNCTION__ "()\n");
+ unsigned long flags;
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
- printk (KERN_WARNING "ToshOboe: seting baud to %d\n", baud);
+ printk (KERN_WARNING "ToshOboe: setting baud to %d\n", baud);
+ save_flags (flags);
cli ();
switch (baud)
{
@@ -177,21 +170,22 @@
break;
}
- sti ();
+ restore_flags (flags);
outb_p (0x00, OBOE_RST);
outb_p (0x80, OBOE_RST);
outb_p (0x01, OBOE_REG_9);
+ self->io.speed = baud;
}
/* Wake the chip up and get it looking at the taskfile */
-static void
+static void
toshoboe_startchip (struct toshoboe_cb *self)
{
__u32 physaddr;
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
outb_p (0, OBOE_LOCK);
@@ -217,19 +211,19 @@
}
/*Let the chip look at memory */
-static void
+static void
toshoboe_enablebm (struct toshoboe_cb *self)
{
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
pci_set_master (self->pdev);
}
/*Don't let the chip look at memory */
-static void
+static void
toshoboe_disablebm (struct toshoboe_cb *self)
{
__u8 command;
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
pci_read_config_byte (self->pdev, PCI_COMMAND, &command);
command &= ~PCI_COMMAND_MASTER;
@@ -238,13 +232,15 @@
}
/*setup the taskfile */
-static void
+static void
toshoboe_initbuffs (struct toshoboe_cb *self)
{
int i;
+ unsigned long flags;
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
+ save_flags (flags);
cli ();
for (i = 0; i < TX_SLOTS; ++i)
@@ -261,25 +257,30 @@
self->taskfile->recv[i].buffer = virt_to_bus (self->recv_bufs[i]);
}
- sti ();
+ restore_flags (flags);
}
-
/*Transmit something */
-static int
+static int
toshoboe_hard_xmit (struct sk_buff *skb, struct device *dev)
{
- struct irda_device *idev;
struct toshoboe_cb *self;
+ __u32 speed;
int mtt, len;
- idev = (struct irda_device *) dev->priv;
- ASSERT (idev != NULL, return 0;);
- ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+ self = (struct toshoboe_cb *) dev->priv;
+
+ ASSERT (self != NULL, return 0;
+ );
- self = idev->priv;
- ASSERT (self != NULL, return 0;);
+ /* Check if we need to change the speed */
+ if ((speed = irda_get_speed(skb)) != self->io.speed)
+ self->new_speed = speed;
+ if (self->stopped) {
+ dev_kfree_skb(skb);
+ return 0;
+ }
#ifdef ONETASK
if (self->txpending)
@@ -343,27 +344,21 @@
}
/*interrupt handler */
-static void
+static void
toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs)
{
- struct irda_device *idev = (struct irda_device *) dev_id;
- struct toshoboe_cb *self;
+ struct toshoboe_cb *self = (struct toshoboe_cb *) dev_id;
__u8 irqstat;
struct sk_buff *skb;
- if (idev == NULL)
+ if (self == NULL)
{
printk (KERN_WARNING "%s: irq %d for unknown device.\n",
driver_name, irq);
return;
}
- self = idev->priv;
-
- if (!self)
- return;
-
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
irqstat = inb_p (OBOE_ISR);
@@ -379,12 +374,17 @@
{
self->txpending--;
- idev->stats.tx_packets++;
+ self->stats.tx_packets++;
- idev->media_busy = FALSE;
- idev->netdev.tbusy = 0;
+ if (self->new_speed) {
+ toshoboe_setbaud(self, self->new_speed);
- mark_bh (NET_BH);
+ self->new_speed = 0;
+ }
+ self->netdev->tbusy = 0; /* Unlock */
+
+ /* Tell network layer that we want more frames */
+ mark_bh(NET_BH);
}
if (irqstat & OBOE_ISR_RXDONE)
@@ -399,8 +399,9 @@
#endif
{
int len = self->taskfile->recv[self->rxs].len;
-
- if (len>2) len-=2;
+
+ if (len > 2)
+ len -= 2;
skb = dev_alloc_skb (len + 1);
if (skb)
@@ -410,8 +411,8 @@
skb_put (skb, len);
memcpy (skb->data, self->recv_bufs[self->rxs], len);
- idev->stats.rx_packets++;
- skb->dev = &idev->netdev;
+ self->stats.rx_packets++;
+ skb->dev = self->netdev;
skb->mac.raw = skb->data;
skb->protocol = htons (ETH_P_IRDA);
}
@@ -421,8 +422,6 @@
"(), memory squeeze, dropping frame.\n");
}
-
-
self->taskfile->recv[self->rxs].control = 0x83;
self->taskfile->recv[self->rxs].len = 0x0;
@@ -448,76 +447,18 @@
{
/*FIXME: I think this is a TX or RX error of some sort */
- idev->stats.tx_errors++;
- idev->stats.rx_errors++;
+ self->stats.tx_errors++;
+ self->stats.rx_errors++;
}
}
-
-
-/* Change the baud rate */
-static void
-toshoboe_change_speed (struct irda_device *idev, int speed)
-{
- struct toshoboe_cb *self;
- DEBUG (4, __FUNCTION__ "()\n");
-
- ASSERT (idev != NULL, return;);
- ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return;);
-
- self = idev->priv;
- ASSERT (self != NULL, return;);
-
- idev->io.baudrate = speed;
-
- toshoboe_setbaud (self, speed);
-
-}
-
-
-/* Check all xmit_tasks finished */
-static void
-toshoboe_wait_until_sent (struct irda_device *idev)
-{
- struct toshoboe_cb *self;
- int i;
-
- DEBUG (4, __FUNCTION__ "()\n");
-
- ASSERT (idev != NULL, return;);
- ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return;);
-
- self = idev->priv;
- ASSERT (self != NULL, return;);
-
- for (i = 0; i < TX_SLOTS; ++i)
- {
- while (self->taskfile->xmit[i].control)
- {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout (6);
- }
- }
-
-}
-
-static int
-toshoboe_is_receiving (struct irda_device *idev)
-{
- DEBUG (4, __FUNCTION__ "()\n");
-
-/*FIXME Can't tell! */
- return (FALSE);
-}
-
-
-static int
+static int
toshoboe_net_init (struct device *dev)
{
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
/* Setup to be a normal IrDA network device driver */
irda_device_setup (dev);
@@ -527,37 +468,12 @@
}
-
-
-static int
-toshoboe_net_open (struct device *dev)
+static void
+toshoboe_initptrs (struct toshoboe_cb *self)
{
- struct irda_device *idev;
- struct toshoboe_cb *self;
-
- DEBUG (4, __FUNCTION__ "()\n");
-
- ASSERT (dev != NULL, return -1;);
- idev = (struct irda_device *) dev->priv;
-
- ASSERT (idev != NULL, return 0;);
- ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;);
-
- self = idev->priv;
- ASSERT (self != NULL, return 0;);
-
- if (request_irq (idev->io.irq, toshoboe_interrupt,
- SA_SHIRQ | SA_INTERRUPT, idev->name, (void *) idev))
- {
-
- return -EAGAIN;
- }
-
- toshoboe_initbuffs (self);
- toshoboe_enablebm (self);
- toshoboe_startchip (self);
-
+ unsigned long flags;
+ save_flags (flags);
cli ();
/*FIXME: need to test this carefully to check which one */
@@ -580,45 +496,88 @@
self->txpending = 0;
- sti ();
+ restore_flags (flags);
+
+}
+static int
+toshoboe_net_open (struct device *dev)
+{
+ struct toshoboe_cb *self;
+
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
+
+ ASSERT (dev != NULL, return -1;
+ );
+ self = (struct toshoboe_cb *) dev->priv;
+
+ ASSERT (self != NULL, return 0;
+ );
+
+ if (self->stopped)
+ return 0;
+
+ if (request_irq (self->io.irq, toshoboe_interrupt,
+ SA_SHIRQ | SA_INTERRUPT, dev->name, (void *) self))
+ {
+
+ return -EAGAIN;
+ }
+
+ toshoboe_initbuffs (self);
+ toshoboe_enablebm (self);
+ toshoboe_startchip (self);
+ toshoboe_initptrs (self);
+
+ /* Ready to play! */
dev->tbusy = 0;
dev->interrupt = 0;
dev->start = 1;
+
+ /*
+ * Open new IrLAP layer instance, now that everything should be
+ * initialized properly
+ */
+ self->irlap = irlap_open(dev, &self->qos);
+ self->open = 1;
+
MOD_INC_USE_COUNT;
return 0;
}
-static int
+static int
toshoboe_net_close (struct device *dev)
{
- struct irda_device *idev;
struct toshoboe_cb *self;
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
- ASSERT (dev != NULL, return -1;);
- idev = (struct irda_device *) dev->priv;
-
- ASSERT (idev != NULL, return 0;);
- ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+ ASSERT (dev != NULL, return -1;
+ );
+ self = (struct toshoboe_cb *) dev->priv;
+ /* Stop device */
dev->tbusy = 1;
dev->start = 0;
+
+ /* Stop and remove instance of IrLAP */
+ if (self->irlap)
+ irlap_close(self->irlap);
+ self->irlap = NULL;
+ self->open = 0;
- self = idev->priv;
-
- ASSERT (self != NULL, return 0;);
+ free_irq (self->io.irq, (void *) self);
- free_irq (idev->io.irq, (void *) idev);
-
- toshoboe_stopchip (self);
- toshoboe_disablebm (self);
+ if (!self->stopped)
+ {
+ toshoboe_stopchip (self);
+ toshoboe_disablebm (self);
+ }
MOD_DEC_USE_COUNT;
@@ -626,28 +585,77 @@
}
+/*
+ * Function toshoboe_net_ioctl (dev, rq, cmd)
+ *
+ * Process IOCTL commands for this device
+ *
+ */
+static int toshoboe_net_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+{
+ struct if_irda_req *irq = (struct if_irda_req *) rq;
+ struct toshoboe_cb *self;
+ unsigned long flags;
+ int ret = 0;
+
+ ASSERT(dev != NULL, return -1;);
+
+ self = dev->priv;
+ ASSERT(self != NULL, return -1;);
+
+ IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+
+ /* Disable interrupts & save flags */
+ save_flags(flags);
+ cli();
+
+ switch (cmd) {
+ case SIOCSBANDWIDTH: /* Set bandwidth */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ /* toshoboe_setbaud(self, irq->ifr_baudrate); */
+ /* Just change speed once - inserted by Paul Bristow */
+ self->new_speed = irq->ifr_baudrate;
+ break;
+ case SIOCSMEDIABUSY: /* Set media busy */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ irda_device_set_media_busy(self->netdev, TRUE);
+ break;
+ case SIOCGRECEIVING: /* Check if we are receiving right now */
+ irq->ifr_receiving = 0; /* Can't tell */
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ }
+
+ restore_flags(flags);
+
+ return ret;
+}
#ifdef MODULE
-static int
-toshoboe_close (struct irda_device *idev)
+MODULE_PARM (max_baud, "i");
+
+static int
+toshoboe_close (struct toshoboe_cb *self)
{
- struct toshoboe_cb *self;
int i;
- DEBUG (4, __FUNCTION__ "()\n");
-
- ASSERT (idev != NULL, return -1;);
- ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
- self = idev->priv;
+ ASSERT (self != NULL, return -1;
+ );
- ASSERT (self != NULL, return -1;);
-
- toshoboe_stopchip (self);
+ if (!self->stopped)
+ {
+ toshoboe_stopchip (self);
+ toshoboe_disablebm (self);
+ }
- release_region (idev->io.iobase, idev->io.io_ext);
+ release_region (self->io.sir_base, self->io.sir_ext);
for (i = 0; i < TX_SLOTS; ++i)
@@ -662,14 +670,19 @@
self->recv_bufs[i] = NULL;
}
+ if (self->netdev) {
+ /* Remove netdevice */
+ rtnl_lock();
+ unregister_netdevice(self->netdev);
+ rtnl_unlock();
+ /* Must free the old-style 2.2.x device */
+ kfree(self->netdev);
+ }
kfree (self->taskfilebuf);
self->taskfilebuf = NULL;
self->taskfile = NULL;
-
- irda_device_close (idev);
-
return (0);
}
@@ -678,16 +691,16 @@
-static int
+static int
toshoboe_open (struct pci_dev *pci_dev)
{
struct toshoboe_cb *self;
- struct irda_device *idev;
+ struct device *dev;
int i = 0;
- int ok=0;
+ int ok = 0;
+ int err;
-
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
while (dev_self[i])
i++;
@@ -709,26 +722,24 @@
memset (self, 0, sizeof (struct toshoboe_cb));
+ dev_self[i] = self; /*This needs moving if we ever get more than one chip */
- dev_self[i] = self;
-
+ self->open = 0;
+ self->stopped = 0;
self->pdev = pci_dev;
self->base = pci_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
- idev = &self->idev;
-
- /*Setup idev */
-
- idev->io.iobase = self->base;
- idev->io.irq = pci_dev->irq;
- idev->io.io_ext = CHIP_IO_EXTENT;
+ self->io.sir_base = self->base;
+ self->io.irq = pci_dev->irq;
+ self->io.sir_ext = CHIP_IO_EXTENT;
+ self->io.speed = 9600;
/* Lock the port that we need */
- i = check_region (idev->io.iobase, idev->io.io_ext);
+ i = check_region (self->io.sir_base, self->io.sir_ext);
if (i < 0)
{
- DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
- idev->io.iobase);
+ IRDA_DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+ self->io.sir_base);
dev_self[i] = NULL;
kfree (self);
@@ -736,55 +747,52 @@
return -ENODEV;
}
- request_region (idev->io.iobase, idev->io.io_ext, driver_name);
- irda_init_max_qos_capabilies (&idev->qos);
+ irda_init_max_qos_capabilies (&self->qos);
+ self->qos.baud_rate.bits = 0;
- idev->qos.baud_rate.bits = IR_2400 | /*IR_4800 | */ IR_9600 | IR_19200 |
- IR_115200;
+ if (max_baud >= 2400)
+ self->qos.baud_rate.bits |= IR_2400;
+ /*if (max_baud>=4800) idev->qos.baud_rate.bits|=IR_4800; */
+ if (max_baud >= 9600)
+ self->qos.baud_rate.bits |= IR_9600;
+ if (max_baud >= 19200)
+ self->qos.baud_rate.bits |= IR_19200;
+ if (max_baud >= 115200)
+ self->qos.baud_rate.bits |= IR_115200;
#ifdef ENABLE_FAST
- idev->qos.baud_rate.bits|= IR_576000 | IR_1152000 | (IR_4000000 << 8);
+ if (max_baud >= 576000)
+ self->qos.baud_rate.bits |= IR_576000;
+ if (max_baud >= 1152000)
+ self->qos.baud_rate.bits |= IR_1152000;
+ if (max_baud >= 4000000)
+ self->qos.baud_rate.bits |= (IR_4000000 << 8);
#endif
- idev->qos.min_turn_time.bits = 0xff; /*FIXME: what does this do? */
- irda_qos_bits_to_value (&idev->qos);
+ self->qos.min_turn_time.bits = 0xff; /*FIXME: what does this do? */
- idev->flags = IFF_SIR | IFF_DMA | IFF_PIO;
+ irda_qos_bits_to_value (&self->qos);
+
+ self->flags = IFF_SIR | IFF_DMA | IFF_PIO;
#ifdef ENABLE_FAST
- idev->flags |= IFF_FIR;
+ if (max_baud >= 576000)
+ self->flags |= IFF_FIR;
#endif
- /* These aren't much use as we need to have a whole panoply of
- * buffers running */
-
- idev->rx_buff.flags = 0;
- idev->tx_buff.flags = 0;
- idev->rx_buff.truesize = 0;
- idev->rx_buff.truesize = 0;
-
- idev->change_speed = toshoboe_change_speed;
- idev->wait_until_sent = toshoboe_wait_until_sent;
- idev->is_receiving = toshoboe_is_receiving;
-
- idev->netdev.init = toshoboe_net_init;
- idev->netdev.hard_start_xmit = toshoboe_hard_xmit;
- idev->netdev.open = toshoboe_net_open;
- idev->netdev.stop = toshoboe_net_close;
-
-
/* Now setup the endless buffers we need */
self->txs = 0;
self->rxs = 0;
- self->taskfilebuf = kmalloc (OBOE_TASK_BUF_LEN, GFP_KERNEL | GFP_DMA);
- if (!self->taskfilebuf) {
- printk(KERN_ERR "toshoboe: kmalloc for DMA failed()\n");
- kfree(self);
- return -ENOMEM;
- }
+ self->taskfilebuf = kmalloc (OBOE_TASK_BUF_LEN, GFP_KERNEL);
+ if (!self->taskfilebuf)
+ {
+ printk (KERN_ERR "toshoboe: kmalloc for DMA failed()\n");
+ kfree (self);
+ return -ENOMEM;
+ }
memset (self->taskfilebuf, 0, OBOE_TASK_BUF_LEN);
@@ -803,29 +811,61 @@
for (i = 0; i < TX_SLOTS; ++i)
{
self->xmit_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL | GFP_DMA);
- if (self->xmit_bufs[i]) ok++;
+ if (self->xmit_bufs[i])
+ ok++;
}
for (i = 0; i < RX_SLOTS; ++i)
{
self->recv_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL | GFP_DMA);
- if (self->recv_bufs[i]) ok++;
+ if (self->recv_bufs[i])
+ ok++;
}
- if (ok!=RX_SLOTS+TX_SLOTS) {
- printk(KERN_ERR "toshoboe: kmalloc for buffers failed()\n");
+ if (ok != RX_SLOTS + TX_SLOTS)
+ {
+ printk (KERN_ERR "toshoboe: kmalloc for buffers failed()\n");
+
+ for (i = 0; i < TX_SLOTS; ++i)
+ if (self->xmit_bufs[i])
+ kfree (self->xmit_bufs[i]);
+ for (i = 0; i < RX_SLOTS; ++i)
+ if (self->recv_bufs[i])
+ kfree (self->recv_bufs[i]);
- for (i = 0; i < TX_SLOTS; ++i) if (self->xmit_bufs[i]) kfree(self->xmit_bufs[i]);
- for (i = 0; i < RX_SLOTS; ++i) if (self->recv_bufs[i]) kfree(self->recv_bufs[i]);
+ kfree (self);
+ return -ENOMEM;
- kfree(self);
- return -ENOMEM;
+ }
- }
+ request_region (self->io.sir_base, self->io.sir_ext, driver_name);
+ if (!(dev = dev_alloc("irda%d", &err))) {
+ ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+ return -ENOMEM;
+ }
+ /* dev_alloc doesn't clear the struct, so lets do a little hack */
+ memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct device)-sizeof(char*));
- irda_device_open (idev, driver_name, self);
+ dev->priv = (void *) self;
+ self->netdev = dev;
+
+ MESSAGE("IrDA: Registered device %s\n", dev->name);
+
+ dev->init = toshoboe_net_init;
+ dev->hard_start_xmit = toshoboe_hard_xmit;
+ dev->open = toshoboe_net_open;
+ dev->stop = toshoboe_net_close;
+ dev->do_ioctl = toshoboe_net_ioctl;
+
+ rtnl_lock();
+ err = register_netdevice(dev);
+ rtnl_unlock();
+ if (err) {
+ ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+ return -1;
+ }
printk (KERN_WARNING "ToshOboe: Using ");
#ifdef ONETASK
@@ -838,7 +878,119 @@
return (0);
}
-__initfunc (int toshoboe_init (void))
+#ifdef CONFIG_APM
+static void
+toshoboe_gotosleep (struct toshoboe_cb *self)
+{
+ int i = 10;
+
+ printk (KERN_WARNING "ToshOboe: suspending\n");
+
+ if (self->stopped)
+ return;
+
+ self->stopped = 1;
+
+ if (!self->open)
+ return;
+
+/*FIXME: can't sleep here wait one second */
+
+ while ((i--) && (self->txpending))
+ udelay (100000);
+
+ toshoboe_stopchip (self);
+ toshoboe_disablebm (self);
+
+ self->txpending = 0;
+
+}
+
+
+static void
+toshoboe_wakeup (struct toshoboe_cb *self)
+{
+ struct device *dev = self->netdev;
+ unsigned long flags;
+
+ if (!self->stopped)
+ return;
+
+ if (!self->open)
+ {
+ self->stopped = 0;
+ return;
+ }
+
+ save_flags (flags);
+ cli ();
+
+ toshoboe_initbuffs (self);
+ toshoboe_enablebm (self);
+ toshoboe_startchip (self);
+
+ toshoboe_setbaud (self, self->io.speed);
+
+ toshoboe_initptrs (self);
+
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+ self->stopped = 0;
+
+ restore_flags (flags);
+ printk (KERN_WARNING "ToshOboe: waking up\n");
+
+}
+
+static int
+toshoboe_apmproc (apm_event_t event)
+{
+ static int down = 0; /*Filter out double events */
+ int i;
+
+ switch (event)
+ {
+ case APM_SYS_SUSPEND:
+ case APM_USER_SUSPEND:
+ if (!down)
+ {
+
+ for (i = 0; i < 4; i++)
+ {
+ if (dev_self[i])
+ toshoboe_gotosleep (dev_self[i]);
+ }
+
+ }
+ down = 1;
+ break;
+ case APM_NORMAL_RESUME:
+ case APM_CRITICAL_RESUME:
+ if (down)
+ {
+
+
+
+ for (i = 0; i < 4; i++)
+ {
+ if (dev_self[i])
+ toshoboe_wakeup (dev_self[i]);
+ }
+
+
+
+ }
+ down = 0;
+ break;
+ }
+ return 0;
+}
+
+
+#endif
+
+int __init toshoboe_init (void)
{
struct pci_dev *pci_dev = NULL;
int found = 0;
@@ -860,38 +1012,49 @@
}
while (pci_dev);
+
if (found)
- return 0;
+ {
+#ifdef CONFIG_APM
+ apm_register_callback (toshoboe_apmproc);
+#endif
+ return 0;
+ }
return -ENODEV;
}
#ifdef MODULE
-static void
+static void
toshoboe_cleanup (void)
{
int i;
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
for (i = 0; i < 4; i++)
{
if (dev_self[i])
- toshoboe_close (&(dev_self[i]->idev));
+ toshoboe_close (dev_self[i]);
}
+
+#ifdef CONFIG_APM
+ apm_unregister_callback (toshoboe_apmproc);
+#endif
+
}
-int
+int
init_module (void)
{
return toshoboe_init ();
}
-void
+void
cleanup_module (void)
{
toshoboe_cleanup ();
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)