toshoboe.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:21k
- /*********************************************************************
- *
- * 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
- * Modified: Paul Bristow <paul.bristow@technologist.com>
- * Modified: Mon Nov 11 19:10:05 1999
- *
- * 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
- * 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.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
- /* To adjust the number of tasks in use edit toshoboe.h */
- /* Define this to enable FIR and MIR support */
- #define ENABLE_FAST
- /* 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/slab.h>
- #include <linux/init.h>
- #include <linux/pci.h>
- #include <linux/rtnetlink.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 <linux/pm.h>
- #include <net/irda/toshoboe.h>
- #define PCI_DEVICE_ID_FIR701b 0x0d01
- static struct pci_device_id toshoboe_pci_tbl[] __initdata = {
- { PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIR701, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIR701b, PCI_ANY_ID, PCI_ANY_ID, },
- { } /* Terminating entry */
- };
- MODULE_DEVICE_TABLE(pci, toshoboe_pci_tbl);
- static const char *driver_name = "toshoboe";
- static int max_baud = 4000000;
- /* Shutdown the chip and point the taskfile reg somewhere else */
- static void
- toshoboe_stopchip (struct toshoboe_cb *self)
- {
- IRDA_DEBUG (4, "%s()n", __FUNCTION__);
- 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)
- {
- unsigned long flags;
- IRDA_DEBUG (4, "%s()n", __FUNCTION__);
- printk (KERN_WARNING "ToshOboe: setting baud to %dn", baud);
- save_flags (flags);
- 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;
- }
- 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
- toshoboe_startchip (struct toshoboe_cb *self)
- {
- __u32 physaddr;
- IRDA_DEBUG (4, "%s()n", __FUNCTION__);
- 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_1B);
- outb_p (0xff, OBOE_REG_1A);
- 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)
- {
- IRDA_DEBUG (4, "%s()n", __FUNCTION__);
- pci_set_master (self->pdev);
- }
- /*Don't let the chip look at memory */
- static void
- toshoboe_disablebm (struct toshoboe_cb *self)
- {
- __u8 command;
- IRDA_DEBUG (4, "%s()n", __FUNCTION__);
- 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;
- unsigned long flags;
- IRDA_DEBUG (4, "%s()n", __FUNCTION__);
- save_flags (flags);
- 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]);
- }
- restore_flags (flags);
- }
- /*Transmit something */
- static int
- toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev)
- {
- struct toshoboe_cb *self;
- __s32 speed;
- int mtt, len;
- self = (struct toshoboe_cb *) dev->priv;
- ASSERT (self != NULL, return 0;
- );
- /* Check if we need to change the speed */
- speed = irda_get_next_speed(skb);
- if ((speed != self->io.speed) && (speed != -1)) {
- /* Check for empty frame */
- if (!skb->len) {
- toshoboe_setbaud(self, speed);
- dev_kfree_skb(skb);
- return 0;
- } else
- self->new_speed = speed;
- }
- netif_stop_queue(dev);
-
- if (self->stopped) {
- dev_kfree_skb(skb);
- 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 busy,media_busy stuff, for the moment */
- /*busy means can't queue any more */
- #ifndef ONETASK
- if (self->txpending != TX_SLOTS)
- {
- netif_wake_queue(dev);
- }
- #endif
- 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 toshoboe_cb *self = (struct toshoboe_cb *) dev_id;
- __u8 irqstat;
- struct sk_buff *skb;
- if (self == NULL)
- {
- printk (KERN_WARNING "%s: irq %d for unknown device.n",
- driver_name, irq);
- return;
- }
- IRDA_DEBUG (4, "%s()n", __FUNCTION__);
- 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--;
- self->stats.tx_packets++;
- if (self->new_speed) {
- toshoboe_setbaud(self, self->new_speed);
- self->new_speed = 0;
- }
- /* Tell network layer that we want more frames */
- netif_wake_queue(self->netdev);
- }
- 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);
- self->stats.rx_packets++;
- skb->dev = self->netdev;
- skb->mac.raw = skb->data;
- skb->protocol = htons (ETH_P_IRDA);
- }
- else
- {
- printk (KERN_INFO "%s(), memory squeeze, dropping frame.n", __FUNCTION__);
- }
- 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: 20n");
- }
- if (irqstat & OBOE_ISR_10)
- {
- printk (KERN_WARNING "Oboe_irq: 10n");
- }
- if (irqstat & 0x8)
- {
- /*FIXME: I think this is a TX or RX error of some sort */
- self->stats.tx_errors++;
- self->stats.rx_errors++;
- }
- }
- static int
- toshoboe_net_init (struct net_device *dev)
- {
- IRDA_DEBUG (4, "%s()n", __FUNCTION__);
- /* Setup to be a normal IrDA network device driver */
- irda_device_setup (dev);
- /* Insert overrides below this line! */
- return 0;
- }
- static void
- toshoboe_initptrs (struct toshoboe_cb *self)
- {
- unsigned long flags;
- save_flags (flags);
- 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;
- #if 0
- self->rxs = 0;
- self->txs = 0;
- #endif
- #if 0
- self->rxs = RX_SLOTS - 1;
- self->txs = 0;
- #endif
- self->txpending = 0;
- restore_flags (flags);
- }
- static int
- toshoboe_net_open (struct net_device *dev)
- {
- struct toshoboe_cb *self;
- char hwname[32];
- IRDA_DEBUG (4, "%s()n", __FUNCTION__);
- 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! */
- netif_start_queue(dev);
- /* Give self a hardware name */
- sprintf(hwname, "Toshiba-FIR @ 0x%03x", self->base);
- /*
- * Open new IrLAP layer instance, now that everything should be
- * initialized properly
- */
- self->irlap = irlap_open(dev, &self->qos, hwname);
- self->open = 1;
-
- MOD_INC_USE_COUNT;
- return 0;
- }
- static int
- toshoboe_net_close (struct net_device *dev)
- {
- struct toshoboe_cb *self;
- IRDA_DEBUG (4, "%s()n", __FUNCTION__);
- ASSERT (dev != NULL, return -1;
- );
- self = (struct toshoboe_cb *) dev->priv;
- /* Stop device */
- netif_stop_queue(dev);
-
- /* Stop and remove instance of IrLAP */
- if (self->irlap)
- irlap_close(self->irlap);
- self->irlap = NULL;
- self->open = 0;
- free_irq (self->io.irq, (void *) self);
- if (!self->stopped)
- {
- toshoboe_stopchip (self);
- toshoboe_disablebm (self);
- }
- MOD_DEC_USE_COUNT;
- return 0;
- }
- /*
- * Function toshoboe_net_ioctl (dev, rq, cmd)
- *
- * Process IOCTL commands for this device
- *
- */
- static int toshoboe_net_ioctl(struct net_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, "%s(), %s, (cmd=0x%X)n", __FUNCTION__, dev->name, cmd);
-
- /* Disable interrupts & save flags */
- save_flags(flags);
- cli();
- switch (cmd) {
- case SIOCSBANDWIDTH: /* Set bandwidth */
- if (!capable(CAP_NET_ADMIN)) {
- ret = -EPERM;
- goto out;
- }
- /* 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)) {
- ret = -EPERM;
- goto out;
- }
- 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;
- }
- out:
- restore_flags(flags);
- return ret;
- }
- MODULE_DESCRIPTION("Toshiba OBOE IrDA Device Driver");
- MODULE_AUTHOR("James McKenzie <james@fishsoup.dhs.org>");
- MODULE_LICENSE("GPL");
- MODULE_PARM (max_baud, "i");
- MODULE_PARM_DESC(max_baus, "Maximum baud rate");
- static void
- toshoboe_remove (struct pci_dev *pci_dev)
- {
- int i;
- struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev);
- IRDA_DEBUG (4, "%s()n", __FUNCTION__);
- ASSERT (self != NULL, return;
- );
- if (!self->stopped)
- {
- toshoboe_stopchip (self);
- toshoboe_disablebm (self);
- }
- release_region (self->io.sir_base, self->io.sir_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;
- }
- if (self->netdev) {
- /* Remove netdevice */
- rtnl_lock();
- unregister_netdevice(self->netdev);
- rtnl_unlock();
- }
- kfree (self->taskfilebuf);
- self->taskfilebuf = NULL;
- self->taskfile = NULL;
- return;
- }
- static int
- toshoboe_probe (struct pci_dev *pci_dev, const struct pci_device_id *pdid)
- {
- struct toshoboe_cb *self;
- struct net_device *dev;
- int i = 0;
- int ok = 0;
- int err;
- IRDA_DEBUG (4, "%s()n", __FUNCTION__);
- if ((err=pci_enable_device(pci_dev)))
- return err;
- 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));
- self->open = 0;
- self->stopped = 0;
- self->pdev = pci_dev;
- self->base = pci_resource_start(pci_dev,0);
- 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 */
- if (NULL==request_region (self->io.sir_base, self->io.sir_ext, driver_name))
- {
- IRDA_DEBUG (0, "%s(), can't get iobase of 0x%03xn",
- __FUNCTION__, self->io.sir_base);
- err = -EBUSY;
- goto freeself;
- }
- irda_init_max_qos_capabilies (&self->qos);
- self->qos.baud_rate.bits = 0;
- 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
- 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
- self->qos.min_turn_time.bits = 0xff; /*FIXME: what does this do? */
- irda_qos_bits_to_value (&self->qos);
- self->flags = IFF_SIR | IFF_DMA | IFF_PIO;
- #ifdef ENABLE_FAST
- if (max_baud >= 576000)
- self->flags |= IFF_FIR;
- #endif
- /* Now setup the endless buffers we need */
- self->txs = 0;
- self->rxs = 0;
- self->taskfilebuf = kmalloc (OBOE_TASK_BUF_LEN, GFP_KERNEL);
- if (!self->taskfilebuf)
- {
- printk (KERN_ERR "toshoboe: kmalloc for DMA failed()n");
- err = -ENOMEM;
- goto freeregion;
- }
- 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");
- err = -ENOMEM;
- goto freebufs;
- }
- if (!(dev = dev_alloc("irda%d", &err))) {
- ERROR("%s(), dev_alloc() failed!n", __FUNCTION__);
- err = -ENOMEM;
- goto freebufs;
- }
- dev->priv = (void *) self;
- self->netdev = dev;
-
- MESSAGE("IrDA: Registered device %sn", 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("%s(), register_netdev() failed!n", __FUNCTION__);
- /* XXX there is not freeing for dev? */
- goto freebufs;
- }
- pci_set_drvdata(pci_dev,self);
- printk (KERN_WARNING "ToshOboe: Using ");
- #ifdef ONETASK
- printk ("single");
- #else
- printk ("multiple");
- #endif
- printk (" tasks, version %sn", rcsid);
- return (0);
- freebufs:
- 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->taskfilebuf);
- freeregion:
- release_region (self->io.sir_base, self->io.sir_ext);
- freeself:
- kfree (self);
- return err;
- }
- static int
- toshoboe_suspend (struct pci_dev *pci_dev, u32 crap)
- {
- int i = 10;
- struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev);
- printk (KERN_WARNING "ToshOboe: suspendingn");
- if (!self || self->stopped)
- return 0;
- self->stopped = 1;
- if (!self->open)
- return 0;
- /*FIXME: can't sleep here wait one second */
- while ((i--) && (self->txpending))
- udelay (100);
- toshoboe_stopchip (self);
- toshoboe_disablebm (self);
- self->txpending = 0;
- return 0;
- }
- static int
- toshoboe_resume (struct pci_dev *pci_dev)
- {
- struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev);
- unsigned long flags;
- if (!self)
- return 0;
- if (!self->stopped)
- return 0;
- if (!self->open)
- {
- self->stopped = 0;
- return 0;
- }
- save_flags (flags);
- cli ();
- toshoboe_initbuffs (self);
- toshoboe_enablebm (self);
- toshoboe_startchip (self);
- toshoboe_setbaud (self, self->io.speed);
- toshoboe_initptrs (self);
- netif_wake_queue(self->netdev);
- restore_flags (flags);
- printk (KERN_WARNING "ToshOboe: waking upn");
- return 0;
- }
- static struct pci_driver toshoboe_pci_driver = {
- name : "toshoboe",
- id_table : toshoboe_pci_tbl,
- probe : toshoboe_probe,
- remove : toshoboe_remove,
- suspend : toshoboe_suspend,
- resume : toshoboe_resume
- };
- int __init
- toshoboe_init (void)
- {
- return pci_module_init(&toshoboe_pci_driver);
- }
- void
- toshoboe_cleanup (void)
- {
- pci_unregister_driver(&toshoboe_pci_driver);
- }
- module_init(toshoboe_init);
- module_exit(toshoboe_cleanup);