patch-2.3.4 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: 902
- Date:
Sun May 30 10:27:04 1999
- Orig file:
v2.3.3/linux/drivers/net/irda/toshoboe.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.3.3/linux/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c
@@ -0,0 +1,901 @@
+/*********************************************************************
+ *
+ * Filename: toshoboe.c
+ * Version: 0.1
+ * Description: Driver for the Toshiba OBOE (or type-O or 700 or 701)
+ * FIR Chipset.
+ * Status: Experimental.
+ * Author: James McKenzie <james@fishsoup.dhs.org>
+ * Created at: Sat May 8 12:35:27 1999
+ *
+ * Copyright (c) 1999 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
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither James McKenzie nor Cambridge University admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ * Applicable Models : Libretto 100CT. and many more
+ * Toshiba refers to this chip as the type-O IR port.
+ *
+ ********************************************************************/
+
+/* This driver is experimental, I have only three ir devices */
+/* 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
+ *
+ */
+
+/* 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
+
+/* To adjust the number of tasks in use edit toshoboe.h */
+
+/* Define this to enable FIR and MIR support */
+#define ENABLE_FAST
+
+/* Number of ports this driver can support, you also need to edit dev_self below */
+#define NSELFS 4
+
+/* Size of IO window */
+#define CHIP_IO_EXTENT 0x1f
+
+/* Transmit and receive buffer sizes, adjust at your peril */
+#define RX_BUF_SZ 4196
+#define TX_BUF_SZ 4196
+
+/* No user servicable parts below here */
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include <net/irda/wrapper.h>
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlap_frame.h>
+#include <net/irda/irda_device.h>
+
+#include <net/irda/toshoboe.h>
+
+static char *driver_name = "toshoboe";
+
+static struct toshoboe_cb *dev_self[NSELFS + 1] =
+{NULL, NULL, NULL, NULL, NULL};
+
+/* Shutdown the chip and point the taskfile reg somewhere else */
+static void
+toshoboe_stopchip (struct toshoboe_cb *self)
+{
+ DEBUG (4, __FUNCTION__ "()\n");
+
+ outb_p (0x0e, OBOE_REG_11);
+
+ outb_p (0x00, OBOE_RST);
+ outb_p (0x3f, OBOE_TFP2); /*Write the taskfile address */
+ outb_p (0xff, OBOE_TFP1);
+ outb_p (0xff, OBOE_TFP0);
+ outb_p (0x0f, OBOE_REG_1B);
+ outb_p (0xff, OBOE_REG_1A);
+ 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
+toshoboe_setbaud (struct toshoboe_cb *self, int baud)
+{
+ DEBUG (4, __FUNCTION__ "()\n");
+
+ printk (KERN_WARNING "ToshOboe: seting baud to %d\n", baud);
+
+ cli ();
+ switch (baud)
+ {
+ case 2400:
+ outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+ outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+ outb_p (0xbf, OBOE_UDIV);
+ break;
+ case 4800:
+ outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+ outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+ outb_p (0x5f, OBOE_UDIV);
+ break;
+ case 9600:
+ outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+ outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+ outb_p (0x2f, OBOE_UDIV);
+ break;
+ case 19200:
+ outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+ outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+ outb_p (0x17, OBOE_UDIV);
+ break;
+ case 38400:
+ outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+ outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+ outb_p (0xb, OBOE_UDIV);
+ break;
+ case 57600:
+ outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+ outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+ outb_p (0x7, OBOE_UDIV);
+ break;
+ case 115200:
+ outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
+ outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
+ outb_p (0x3, OBOE_UDIV);
+ break;
+ case 1152000:
+ outb_p (OBOE_PMDL_MIR, OBOE_PMDL);
+ outb_p (OBOE_SMDL_MIR, OBOE_SMDL);
+ outb_p (0x1, OBOE_UDIV);
+ break;
+ case 4000000:
+ outb_p (OBOE_PMDL_FIR, OBOE_PMDL);
+ outb_p (OBOE_SMDL_FIR, OBOE_SMDL);
+ outb_p (0x0, OBOE_UDIV);
+ break;
+ }
+
+ sti ();
+
+ outb_p (0x00, OBOE_RST);
+ outb_p (0x80, OBOE_RST);
+ outb_p (0x01, OBOE_REG_9);
+
+}
+
+/* Wake the chip up and get it looking at the taskfile */
+static void
+toshoboe_startchip (struct toshoboe_cb *self)
+{
+ __u32 physaddr;
+
+ DEBUG (4, __FUNCTION__ "()\n");
+
+
+ outb_p (0, OBOE_LOCK);
+ outb_p (0, OBOE_RST);
+ outb_p (OBOE_NTR_VAL, OBOE_NTR);
+ outb_p (0xf0, OBOE_REG_D);
+ outb_p (0xff, OBOE_ISR);
+ outb_p (0x0f, OBOE_REG_1A);
+ outb_p (0xff, OBOE_REG_1B);
+
+
+ physaddr = virt_to_bus (self->taskfile);
+
+ outb_p ((physaddr >> 0x0a) & 0xff, OBOE_TFP0);
+ outb_p ((physaddr >> 0x12) & 0xff, OBOE_TFP1);
+ outb_p ((physaddr >> 0x1a) & 0x3f, OBOE_TFP2);
+
+ outb_p (0x0e, OBOE_REG_11);
+ outb_p (0x80, OBOE_RST);
+
+ toshoboe_setbaud (self, 9600);
+
+}
+
+/*Let the chip look at memory */
+static void
+toshoboe_enablebm (struct toshoboe_cb *self)
+{
+ DEBUG (4, __FUNCTION__ "()\n");
+ pci_set_master (self->pdev);
+}
+
+/*Don't let the chip look at memory */
+static void
+toshoboe_disablebm (struct toshoboe_cb *self)
+{
+ __u8 command;
+ DEBUG (4, __FUNCTION__ "()\n");
+
+ pci_read_config_byte (self->pdev, PCI_COMMAND, &command);
+ command &= ~PCI_COMMAND_MASTER;
+ pci_write_config_byte (self->pdev, PCI_COMMAND, command);
+
+}
+
+/*setup the taskfile */
+static void
+toshoboe_initbuffs (struct toshoboe_cb *self)
+{
+ int i;
+
+ DEBUG (4, __FUNCTION__ "()\n");
+
+ cli ();
+
+ for (i = 0; i < TX_SLOTS; ++i)
+ {
+ self->taskfile->xmit[i].len = 0;
+ self->taskfile->xmit[i].control = 0x00;
+ self->taskfile->xmit[i].buffer = virt_to_bus (self->xmit_bufs[i]);
+ }
+
+ for (i = 0; i < RX_SLOTS; ++i)
+ {
+ self->taskfile->recv[i].len = 0;
+ self->taskfile->recv[i].control = 0x83;
+ self->taskfile->recv[i].buffer = virt_to_bus (self->recv_bufs[i]);
+ }
+
+ sti ();
+}
+
+
+/*Transmit something */
+static int
+toshoboe_hard_xmit (struct sk_buff *skb, struct device *dev)
+{
+ struct irda_device *idev;
+ struct toshoboe_cb *self;
+ int mtt, len;
+
+ 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;);
+
+
+#ifdef ONETASK
+ if (self->txpending)
+ return -EBUSY;
+
+ self->txs = inb_p (OBOE_XMTT) - OBOE_XMTT_OFFSET;
+
+ self->txs &= 0x3f;
+
+#endif
+
+ if (self->taskfile->xmit[self->txs].control)
+ return -EBUSY;
+
+
+ if (inb_p (OBOE_RST) & OBOE_RST_WRAP)
+ {
+ len = async_wrap_skb (skb, self->xmit_bufs[self->txs], TX_BUF_SZ);
+ }
+ else
+ {
+ len = skb->len;
+ memcpy (self->xmit_bufs[self->txs], skb->data, len);
+ }
+ self->taskfile->xmit[self->txs].len = len & 0x0fff;
+
+
+
+ outb_p (0, OBOE_RST);
+ outb_p (0x1e, OBOE_REG_11);
+
+ self->taskfile->xmit[self->txs].control = 0x84;
+
+ mtt = irda_get_mtt (skb);
+ if (mtt)
+ udelay (mtt);
+
+ self->txpending++;
+
+ /*FIXME: ask about tbusy,media_busy stuff, for the moment */
+ /*tbusy means can't queue any more */
+#ifndef ONETASK
+ if (self->txpending == TX_SLOTS)
+ {
+#else
+ {
+#endif
+ if (irda_lock ((void *) &dev->tbusy) == FALSE)
+ return -EBUSY;
+ }
+
+ outb_p (0x80, OBOE_RST);
+ outb_p (1, OBOE_REG_9);
+
+ self->txs++;
+ self->txs %= TX_SLOTS;
+
+ dev_kfree_skb (skb);
+
+ return 0;
+}
+
+/*interrupt handler */
+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;
+ __u8 irqstat;
+ struct sk_buff *skb;
+
+ if (idev == 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");
+
+ irqstat = inb_p (OBOE_ISR);
+
+/* woz it us */
+ if (!(irqstat & 0xf8))
+ return;
+
+ outb_p (irqstat, OBOE_ISR); /*Acknologede it */
+
+
+/* Txdone */
+ if (irqstat & OBOE_ISR_TXDONE)
+ {
+ self->txpending--;
+
+ idev->stats.tx_packets++;
+
+ idev->media_busy = FALSE;
+ idev->netdev.tbusy = 0;
+
+ mark_bh (NET_BH);
+ }
+
+ if (irqstat & OBOE_ISR_RXDONE)
+ {
+
+#ifdef ONETASK
+ self->rxs = inb_p (OBOE_RCVT);
+ self->rxs += (RX_SLOTS - 1);
+ self->rxs %= RX_SLOTS;
+#else
+ while (self->taskfile->recv[self->rxs].control == 0)
+#endif
+ {
+ int len = self->taskfile->recv[self->rxs].len;
+
+ if (len>2) len-=2;
+
+ skb = dev_alloc_skb (len + 1);
+ if (skb)
+ {
+ skb_reserve (skb, 1);
+
+ skb_put (skb, len);
+ memcpy (skb->data, self->recv_bufs[self->rxs], len);
+
+ idev->stats.rx_packets++;
+ skb->dev = &idev->netdev;
+ skb->mac.raw = skb->data;
+ skb->protocol = htons (ETH_P_IRDA);
+ }
+ else
+ {
+ printk (KERN_INFO __FUNCTION__
+ "(), memory squeeze, dropping frame.\n");
+ }
+
+
+
+ self->taskfile->recv[self->rxs].control = 0x83;
+ self->taskfile->recv[self->rxs].len = 0x0;
+
+ self->rxs++;
+ self->rxs %= RX_SLOTS;
+
+ if (skb)
+ netif_rx (skb);
+
+ }
+
+ }
+
+ if (irqstat & OBOE_ISR_20)
+ {
+ printk (KERN_WARNING "Oboe_irq: 20\n");
+ }
+ if (irqstat & OBOE_ISR_10)
+ {
+ printk (KERN_WARNING "Oboe_irq: 10\n");
+ }
+ if (irqstat & 0x8)
+ {
+ /*FIXME: I think this is a TX or RX error of some sort */
+
+ idev->stats.tx_errors++;
+ idev->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
+toshoboe_net_init (struct device *dev)
+{
+ DEBUG (4, __FUNCTION__ "()\n");
+
+ /* Setup to be a normal IrDA network device driver */
+ irda_device_setup (dev);
+
+ /* Insert overrides below this line! */
+ return 0;
+}
+
+
+
+
+static int
+toshoboe_net_open (struct device *dev)
+{
+ 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);
+
+
+ cli ();
+
+ /*FIXME: need to test this carefully to check which one */
+ /*of the two possible startup logics the chip uses */
+ /*although it won't make any difference if no-one xmits durining init */
+ /*and none what soever if using ONETASK */
+
+ self->rxs = inb_p (OBOE_RCVT);
+ self->txs = inb_p (OBOE_XMTT) - OBOE_XMTT_OFFSET;
+
+#ifdef 0
+ self->rxs = 0;
+ self->txs = 0;
+#endif
+#ifdef 0
+ self->rxs = RX_SLOTS - 1;
+ self->txs = 0;
+#endif
+
+
+ self->txpending = 0;
+
+ sti ();
+
+
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+
+ MOD_INC_USE_COUNT;
+
+ return 0;
+
+}
+
+static int
+toshoboe_net_close (struct device *dev)
+{
+ 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;);
+
+ dev->tbusy = 1;
+ dev->start = 0;
+
+
+ self = idev->priv;
+
+ ASSERT (self != NULL, return 0;);
+
+ free_irq (idev->io.irq, (void *) idev);
+
+ toshoboe_stopchip (self);
+ toshoboe_disablebm (self);
+
+ MOD_DEC_USE_COUNT;
+
+ return 0;
+
+}
+
+
+
+#ifdef MODULE
+
+static int
+toshoboe_close (struct irda_device *idev)
+{
+ struct toshoboe_cb *self;
+ int i;
+
+ DEBUG (4, __FUNCTION__ "()\n");
+
+ ASSERT (idev != NULL, return -1;);
+ ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+ self = idev->priv;
+
+ ASSERT (self != NULL, return -1;);
+
+ toshoboe_stopchip (self);
+
+ release_region (idev->io.iobase, idev->io.io_ext);
+
+
+ for (i = 0; i < TX_SLOTS; ++i)
+ {
+ kfree (self->xmit_bufs[i]);
+ self->xmit_bufs[i] = NULL;
+ }
+
+ for (i = 0; i < RX_SLOTS; ++i)
+ {
+ kfree (self->recv_bufs[i]);
+ self->recv_bufs[i] = NULL;
+ }
+
+
+ kfree (self->taskfilebuf);
+ self->taskfilebuf = NULL;
+ self->taskfile = NULL;
+
+
+ irda_device_close (idev);
+
+ return (0);
+
+}
+
+#endif
+
+
+
+static int
+toshoboe_open (struct pci_dev *pci_dev)
+{
+ struct toshoboe_cb *self;
+ struct irda_device *idev;
+ int i = 0;
+ int ok=0;
+
+
+ DEBUG (4, __FUNCTION__ "()\n");
+
+ while (dev_self[i])
+ i++;
+
+ if (i == NSELFS)
+ {
+ printk (KERN_ERR "Oboe: No more instances available");
+ return -ENOMEM;
+ }
+
+ self = kmalloc (sizeof (struct toshoboe_cb), GFP_KERNEL);
+
+ if (self == NULL)
+ {
+ printk (KERN_ERR "IrDA: Can't allocate memory for "
+ "IrDA control block!\n");
+ return -ENOMEM;
+ }
+
+ memset (self, 0, sizeof (struct toshoboe_cb));
+
+
+ dev_self[i] = self;
+
+ 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;
+
+ /* Lock the port that we need */
+ i = check_region (idev->io.iobase, idev->io.io_ext);
+ if (i < 0)
+ {
+ DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+ idev->io.iobase);
+
+ dev_self[i] = NULL;
+ kfree (self);
+
+ return -ENODEV;
+ }
+
+ request_region (idev->io.iobase, idev->io.io_ext, driver_name);
+
+ irda_init_max_qos_capabilies (&idev->qos);
+
+ idev->qos.baud_rate.bits = IR_2400 | /*IR_4800 | */ IR_9600 | IR_19200 |
+ IR_115200;
+#ifdef ENABLE_FAST
+ idev->qos.baud_rate.bits|= IR_576000 | IR_1152000 | (IR_4000000 << 8);
+#endif
+
+ idev->qos.min_turn_time.bits = 0xff; /*FIXME: what does this do? */
+
+ irda_qos_bits_to_value (&idev->qos);
+
+ idev->flags = IFF_SIR | IFF_DMA | IFF_PIO;
+
+#ifdef ENABLE_FAST
+ idev->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;
+ }
+
+
+ memset (self->taskfilebuf, 0, OBOE_TASK_BUF_LEN);
+
+ /*We need to align the taskfile on a taskfile size boundary */
+ {
+ __u32 addr;
+
+ addr = (__u32) self->taskfilebuf;
+ addr &= ~(sizeof (struct OboeTaskFile) - 1);
+ addr += sizeof (struct OboeTaskFile);
+
+ self->taskfile = (struct OboeTaskFile *) addr;
+ }
+
+ 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++;
+ }
+
+ 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 (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]);
+
+ kfree(self);
+ return -ENOMEM;
+
+ }
+
+
+ irda_device_open (idev, driver_name, self);
+
+ printk (KERN_WARNING "ToshOboe: Using ");
+#ifdef ONETASK
+ printk ("single");
+#else
+ printk ("multiple");
+#endif
+ printk (" tasks, version %s\n", rcsid);
+
+ return (0);
+}
+
+__initfunc (int toshoboe_init (void))
+{
+ struct pci_dev *pci_dev = NULL;
+ int found = 0;
+
+ do
+ {
+ pci_dev = pci_find_device (PCI_VENDOR_ID_TOSHIBA,
+ PCI_DEVICE_ID_FIR701, pci_dev);
+ if (pci_dev)
+ {
+ printk (KERN_WARNING "ToshOboe: Found 701 chip at 0x%0lx irq %d\n",
+ pci_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK,
+ pci_dev->irq);
+
+ if (!toshoboe_open (pci_dev))
+ found++;
+ }
+
+ }
+ while (pci_dev);
+
+ if (found)
+ return 0;
+
+ return -ENODEV;
+}
+
+#ifdef MODULE
+
+static void
+toshoboe_cleanup (void)
+{
+ int i;
+
+ DEBUG (4, __FUNCTION__ "()\n");
+
+ for (i = 0; i < 4; i++)
+ {
+ if (dev_self[i])
+ toshoboe_close (&(dev_self[i]->idev));
+ }
+}
+
+
+
+int
+init_module (void)
+{
+ return toshoboe_init ();
+}
+
+
+void
+cleanup_module (void)
+{
+ toshoboe_cleanup ();
+}
+
+
+#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)