1 /*********************************************************************
5 * Description: Driver for the Toshiba OBOE (or type-O or 700 or 701)
7 * Status: Experimental.
8 * Author: James McKenzie <james@fishsoup.dhs.org>
9 * Created at: Sat May 8 12:35:27 1999
10 * Modified: Paul Bristow <paul.bristow@technologist.com>
11 * Modified: Mon Nov 11 19:10:05 1999
13 * Copyright (c) 1999-2000 James McKenzie, All Rights Reserved.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of
18 * the License, or (at your option) any later version.
20 * Neither James McKenzie nor Cambridge University admit liability nor
21 * provide warranty for any of this software. This material is
22 * provided "AS-IS" and at no charge.
24 * Applicable Models : Libretto 100CT. and many more
25 * Toshiba refers to this chip as the type-O IR port.
27 ********************************************************************/
29 /* This driver is experimental, I have only three ir devices */
30 /* an olivetti notebook which doesn't have FIR, a toshiba libretto, and */
31 /* an hp printer, this works fine at 4MBPS with my HP printer */
33 static char *rcsid = "$Id: toshoboe.c,v 1.91 1999/06/29 14:21:06 root Exp $";
35 /* Define this to have only one frame in the XMIT or RECV queue */
36 /* Toshiba's drivers do this, but it disables back to back tansfers */
37 /* I think that the chip may have some problems certainly, I have */
38 /* seen it jump over tasks in the taskfile->xmit with this turned on */
41 /* To adjust the number of tasks in use edit toshoboe.h */
43 /* Define this to enable FIR and MIR support */
46 /* Size of IO window */
47 #define CHIP_IO_EXTENT 0x1f
49 /* Transmit and receive buffer sizes, adjust at your peril */
50 #define RX_BUF_SZ 4196
51 #define TX_BUF_SZ 4196
53 /* No user servicable parts below here */
55 #include <linux/module.h>
56 #include <linux/kernel.h>
57 #include <linux/types.h>
58 #include <linux/skbuff.h>
59 #include <linux/netdevice.h>
60 #include <linux/ioport.h>
61 #include <linux/delay.h>
62 #include <linux/slab.h>
63 #include <linux/init.h>
64 #include <linux/pci.h>
65 #include <linux/rtnetlink.h>
67 #include <asm/system.h>
70 #include <net/irda/wrapper.h>
71 #include <net/irda/irda.h>
72 #include <net/irda/irda_device.h>
76 #include <net/irda/toshoboe.h>
78 #define PCI_DEVICE_ID_FIR701b 0x0d01
80 static struct pci_device_id toshoboe_pci_tbl[] __initdata = {
81 { PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIR701, PCI_ANY_ID, PCI_ANY_ID, },
82 { PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIR701b, PCI_ANY_ID, PCI_ANY_ID, },
83 { } /* Terminating entry */
85 MODULE_DEVICE_TABLE(pci, toshoboe_pci_tbl);
87 static const char *driver_name = "toshoboe";
89 static int max_baud = 4000000;
91 /* Shutdown the chip and point the taskfile reg somewhere else */
93 toshoboe_stopchip (struct toshoboe_cb *self)
95 IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
97 outb_p (0x0e, OBOE_REG_11);
99 outb_p (0x00, OBOE_RST);
100 outb_p (0x3f, OBOE_TFP2); /*Write the taskfile address */
101 outb_p (0xff, OBOE_TFP1);
102 outb_p (0xff, OBOE_TFP0);
103 outb_p (0x0f, OBOE_REG_1B);
104 outb_p (0xff, OBOE_REG_1A);
105 outb_p (0x00, OBOE_ISR); /*FIXME: should i do this to disbale ints */
106 outb_p (0x80, OBOE_RST);
107 outb_p (0xe, OBOE_LOCK);
111 /*Set the baud rate */
113 toshoboe_setbaud (struct toshoboe_cb *self, int baud)
116 IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
118 printk (KERN_WARNING "ToshOboe: setting baud to %d\n", baud);
125 outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
126 outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
127 outb_p (0xbf, OBOE_UDIV);
130 outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
131 outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
132 outb_p (0x5f, OBOE_UDIV);
135 outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
136 outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
137 outb_p (0x2f, OBOE_UDIV);
140 outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
141 outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
142 outb_p (0x17, OBOE_UDIV);
145 outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
146 outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
147 outb_p (0xb, OBOE_UDIV);
150 outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
151 outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
152 outb_p (0x7, OBOE_UDIV);
155 outb_p (OBOE_PMDL_SIR, OBOE_PMDL);
156 outb_p (OBOE_SMDL_SIR, OBOE_SMDL);
157 outb_p (0x3, OBOE_UDIV);
160 outb_p (OBOE_PMDL_MIR, OBOE_PMDL);
161 outb_p (OBOE_SMDL_MIR, OBOE_SMDL);
162 outb_p (0x1, OBOE_UDIV);
165 outb_p (OBOE_PMDL_FIR, OBOE_PMDL);
166 outb_p (OBOE_SMDL_FIR, OBOE_SMDL);
167 outb_p (0x0, OBOE_UDIV);
171 restore_flags (flags);
173 outb_p (0x00, OBOE_RST);
174 outb_p (0x80, OBOE_RST);
175 outb_p (0x01, OBOE_REG_9);
177 self->io.speed = baud;
180 /* Wake the chip up and get it looking at the taskfile */
182 toshoboe_startchip (struct toshoboe_cb *self)
186 IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
189 outb_p (0, OBOE_LOCK);
190 outb_p (0, OBOE_RST);
191 outb_p (OBOE_NTR_VAL, OBOE_NTR);
192 outb_p (0xf0, OBOE_REG_D);
193 outb_p (0xff, OBOE_ISR);
194 outb_p (0x0f, OBOE_REG_1B);
195 outb_p (0xff, OBOE_REG_1A);
198 physaddr = virt_to_bus (self->taskfile);
200 outb_p ((physaddr >> 0x0a) & 0xff, OBOE_TFP0);
201 outb_p ((physaddr >> 0x12) & 0xff, OBOE_TFP1);
202 outb_p ((physaddr >> 0x1a) & 0x3f, OBOE_TFP2);
204 outb_p (0x0e, OBOE_REG_11);
205 outb_p (0x80, OBOE_RST);
207 toshoboe_setbaud (self, 9600);
211 /*Let the chip look at memory */
213 toshoboe_enablebm (struct toshoboe_cb *self)
215 IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
216 pci_set_master (self->pdev);
219 /*Don't let the chip look at memory */
221 toshoboe_disablebm (struct toshoboe_cb *self)
224 IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
226 pci_read_config_byte (self->pdev, PCI_COMMAND, &command);
227 command &= ~PCI_COMMAND_MASTER;
228 pci_write_config_byte (self->pdev, PCI_COMMAND, command);
232 /*setup the taskfile */
234 toshoboe_initbuffs (struct toshoboe_cb *self)
239 IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
244 for (i = 0; i < TX_SLOTS; ++i)
246 self->taskfile->xmit[i].len = 0;
247 self->taskfile->xmit[i].control = 0x00;
248 self->taskfile->xmit[i].buffer = virt_to_bus (self->xmit_bufs[i]);
251 for (i = 0; i < RX_SLOTS; ++i)
253 self->taskfile->recv[i].len = 0;
254 self->taskfile->recv[i].control = 0x83;
255 self->taskfile->recv[i].buffer = virt_to_bus (self->recv_bufs[i]);
258 restore_flags (flags);
261 /*Transmit something */
263 toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev)
265 struct toshoboe_cb *self;
269 self = (struct toshoboe_cb *) dev->priv;
271 ASSERT (self != NULL, return 0;
274 /* Check if we need to change the speed */
275 speed = irda_get_next_speed(skb);
276 if ((speed != self->io.speed) && (speed != -1)) {
277 /* Check for empty frame */
279 toshoboe_setbaud(self, speed);
283 self->new_speed = speed;
286 netif_stop_queue(dev);
297 self->txs = inb_p (OBOE_XMTT) - OBOE_XMTT_OFFSET;
303 if (self->taskfile->xmit[self->txs].control)
307 if (inb_p (OBOE_RST) & OBOE_RST_WRAP)
309 len = async_wrap_skb (skb, self->xmit_bufs[self->txs], TX_BUF_SZ);
314 memcpy (self->xmit_bufs[self->txs], skb->data, len);
316 self->taskfile->xmit[self->txs].len = len & 0x0fff;
320 outb_p (0, OBOE_RST);
321 outb_p (0x1e, OBOE_REG_11);
323 self->taskfile->xmit[self->txs].control = 0x84;
325 mtt = irda_get_mtt (skb);
331 /*FIXME: ask about busy,media_busy stuff, for the moment */
332 /*busy means can't queue any more */
334 if (self->txpending != TX_SLOTS)
336 netif_wake_queue(dev);
340 outb_p (0x80, OBOE_RST);
341 outb_p (1, OBOE_REG_9);
344 self->txs %= TX_SLOTS;
351 /*interrupt handler */
353 toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs)
355 struct toshoboe_cb *self = (struct toshoboe_cb *) dev_id;
361 printk (KERN_WARNING "%s: irq %d for unknown device.\n",
366 IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
368 irqstat = inb_p (OBOE_ISR);
371 if (!(irqstat & 0xf8))
374 outb_p (irqstat, OBOE_ISR); /*Acknologede it */
378 if (irqstat & OBOE_ISR_TXDONE)
382 self->stats.tx_packets++;
384 if (self->new_speed) {
385 toshoboe_setbaud(self, self->new_speed);
389 /* Tell network layer that we want more frames */
390 netif_wake_queue(self->netdev);
393 if (irqstat & OBOE_ISR_RXDONE)
397 self->rxs = inb_p (OBOE_RCVT);
398 self->rxs += (RX_SLOTS - 1);
399 self->rxs %= RX_SLOTS;
401 while (self->taskfile->recv[self->rxs].control == 0)
404 int len = self->taskfile->recv[self->rxs].len;
409 skb = dev_alloc_skb (len + 1);
412 skb_reserve (skb, 1);
415 memcpy (skb->data, self->recv_bufs[self->rxs], len);
417 self->stats.rx_packets++;
418 skb->dev = self->netdev;
419 skb->mac.raw = skb->data;
420 skb->protocol = htons (ETH_P_IRDA);
425 "%s(), memory squeeze, dropping frame.\n", __FUNCTION__);
428 self->taskfile->recv[self->rxs].control = 0x83;
429 self->taskfile->recv[self->rxs].len = 0x0;
432 self->rxs %= RX_SLOTS;
436 self->netdev->last_rx = jiffies;
443 if (irqstat & OBOE_ISR_20)
445 printk (KERN_WARNING "Oboe_irq: 20\n");
447 if (irqstat & OBOE_ISR_10)
449 printk (KERN_WARNING "Oboe_irq: 10\n");
453 /*FIXME: I think this is a TX or RX error of some sort */
455 self->stats.tx_errors++;
456 self->stats.rx_errors++;
463 toshoboe_net_init (struct net_device *dev)
465 IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
467 /* Setup to be a normal IrDA network device driver */
468 irda_device_setup (dev);
470 /* Insert overrides below this line! */
476 toshoboe_initptrs (struct toshoboe_cb *self)
483 /*FIXME: need to test this carefully to check which one */
484 /*of the two possible startup logics the chip uses */
485 /*although it won't make any difference if no-one xmits durining init */
486 /*and none what soever if using ONETASK */
488 self->rxs = inb_p (OBOE_RCVT);
489 self->txs = inb_p (OBOE_XMTT) - OBOE_XMTT_OFFSET;
496 self->rxs = RX_SLOTS - 1;
503 restore_flags (flags);
509 toshoboe_net_open (struct net_device *dev)
511 struct toshoboe_cb *self;
514 IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
516 ASSERT (dev != NULL, return -1;
518 self = (struct toshoboe_cb *) dev->priv;
520 ASSERT (self != NULL, return 0;
526 if (request_irq (self->io.irq, toshoboe_interrupt,
527 SA_SHIRQ | SA_INTERRUPT, dev->name, (void *) self))
533 toshoboe_initbuffs (self);
534 toshoboe_enablebm (self);
535 toshoboe_startchip (self);
536 toshoboe_initptrs (self);
539 netif_start_queue(dev);
540 /* Give self a hardware name */
541 sprintf(hwname, "Toshiba-FIR @ 0x%03x", self->base);
543 * Open new IrLAP layer instance, now that everything should be
544 * initialized properly
546 self->irlap = irlap_open(dev, &self->qos, hwname);
557 toshoboe_net_close (struct net_device *dev)
559 struct toshoboe_cb *self;
561 IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
563 ASSERT (dev != NULL, return -1;
565 self = (struct toshoboe_cb *) dev->priv;
568 netif_stop_queue(dev);
570 /* Stop and remove instance of IrLAP */
572 irlap_close(self->irlap);
577 free_irq (self->io.irq, (void *) self);
581 toshoboe_stopchip (self);
582 toshoboe_disablebm (self);
592 * Function toshoboe_net_ioctl (dev, rq, cmd)
594 * Process IOCTL commands for this device
597 static int toshoboe_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
599 struct if_irda_req *irq = (struct if_irda_req *) rq;
600 struct toshoboe_cb *self;
604 ASSERT(dev != NULL, return -1;);
608 ASSERT(self != NULL, return -1;);
610 IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__ , dev->name, cmd);
612 /* Disable interrupts & save flags */
616 case SIOCSBANDWIDTH: /* Set bandwidth */
617 if (!capable(CAP_NET_ADMIN)) {
621 /* toshoboe_setbaud(self, irq->ifr_baudrate); */
622 /* Just change speed once - inserted by Paul Bristow */
623 self->new_speed = irq->ifr_baudrate;
625 case SIOCSMEDIABUSY: /* Set media busy */
626 if (!capable(CAP_NET_ADMIN)) {
630 irda_device_set_media_busy(self->netdev, TRUE);
632 case SIOCGRECEIVING: /* Check if we are receiving right now */
633 irq->ifr_receiving = 0; /* Can't tell */
639 restore_flags(flags);
643 MODULE_DESCRIPTION("Toshiba OBOE IrDA Device Driver");
644 MODULE_AUTHOR("James McKenzie <james@fishsoup.dhs.org>");
645 MODULE_LICENSE("GPL");
647 MODULE_PARM (max_baud, "i");
648 MODULE_PARM_DESC(max_baus, "Maximum baud rate");
651 toshoboe_remove (struct pci_dev *pci_dev)
654 struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev);
656 IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
658 ASSERT (self != NULL, return;
663 toshoboe_stopchip (self);
664 toshoboe_disablebm (self);
667 release_region (self->io.sir_base, self->io.sir_ext);
670 for (i = 0; i < TX_SLOTS; ++i)
672 kfree (self->xmit_bufs[i]);
673 self->xmit_bufs[i] = NULL;
676 for (i = 0; i < RX_SLOTS; ++i)
678 kfree (self->recv_bufs[i]);
679 self->recv_bufs[i] = NULL;
683 unregister_netdev(self->netdev);
685 kfree (self->taskfilebuf);
686 self->taskfilebuf = NULL;
687 self->taskfile = NULL;
694 toshoboe_probe (struct pci_dev *pci_dev, const struct pci_device_id *pdid)
696 struct toshoboe_cb *self;
697 struct net_device *dev;
702 IRDA_DEBUG (4, "%s()\n", __FUNCTION__ );
704 if ((err=pci_enable_device(pci_dev)))
707 self = kmalloc (sizeof (struct toshoboe_cb), GFP_KERNEL);
711 printk (KERN_ERR "IrDA: Can't allocate memory for "
712 "IrDA control block!\n");
716 memset (self, 0, sizeof (struct toshoboe_cb));
720 self->pdev = pci_dev;
721 self->base = pci_resource_start(pci_dev,0);
723 self->io.sir_base = self->base;
724 self->io.irq = pci_dev->irq;
725 self->io.sir_ext = CHIP_IO_EXTENT;
726 self->io.speed = 9600;
728 /* Lock the port that we need */
729 if (NULL==request_region (self->io.sir_base, self->io.sir_ext, driver_name))
731 IRDA_DEBUG (0, "%s(), can't get iobase of 0x%03x\n", __FUNCTION__ ,
738 irda_init_max_qos_capabilies (&self->qos);
739 self->qos.baud_rate.bits = 0;
741 if (max_baud >= 2400)
742 self->qos.baud_rate.bits |= IR_2400;
743 /*if (max_baud>=4800) idev->qos.baud_rate.bits|=IR_4800; */
744 if (max_baud >= 9600)
745 self->qos.baud_rate.bits |= IR_9600;
746 if (max_baud >= 19200)
747 self->qos.baud_rate.bits |= IR_19200;
748 if (max_baud >= 115200)
749 self->qos.baud_rate.bits |= IR_115200;
751 if (max_baud >= 576000)
752 self->qos.baud_rate.bits |= IR_576000;
753 if (max_baud >= 1152000)
754 self->qos.baud_rate.bits |= IR_1152000;
755 if (max_baud >= 4000000)
756 self->qos.baud_rate.bits |= (IR_4000000 << 8);
760 self->qos.min_turn_time.bits = 0xff; /*FIXME: what does this do? */
762 irda_qos_bits_to_value (&self->qos);
764 self->flags = IFF_SIR | IFF_DMA | IFF_PIO;
767 if (max_baud >= 576000)
768 self->flags |= IFF_FIR;
771 /* Now setup the endless buffers we need */
776 self->taskfilebuf = kmalloc (OBOE_TASK_BUF_LEN, GFP_KERNEL);
777 if (!self->taskfilebuf)
779 printk (KERN_ERR "toshoboe: kmalloc for DMA failed()\n");
785 memset (self->taskfilebuf, 0, OBOE_TASK_BUF_LEN);
787 /*We need to align the taskfile on a taskfile size boundary */
791 addr = (__u32) self->taskfilebuf;
792 addr &= ~(sizeof (struct OboeTaskFile) - 1);
793 addr += sizeof (struct OboeTaskFile);
795 self->taskfile = (struct OboeTaskFile *) addr;
798 for (i = 0; i < TX_SLOTS; ++i)
800 self->xmit_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL | GFP_DMA);
801 if (self->xmit_bufs[i])
805 for (i = 0; i < RX_SLOTS; ++i)
807 self->recv_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL | GFP_DMA);
808 if (self->recv_bufs[i])
812 if (ok != RX_SLOTS + TX_SLOTS)
814 printk (KERN_ERR "toshoboe: kmalloc for buffers failed()\n");
821 if (!(dev = dev_alloc("irda%d", &err))) {
822 ERROR("%s(), dev_alloc() failed!\n", __FUNCTION__);
826 dev->priv = (void *) self;
829 MESSAGE("IrDA: Registered device %s\n", dev->name);
831 dev->init = toshoboe_net_init;
832 dev->hard_start_xmit = toshoboe_hard_xmit;
833 dev->open = toshoboe_net_open;
834 dev->stop = toshoboe_net_close;
835 dev->do_ioctl = toshoboe_net_ioctl;
838 err = register_netdevice(dev);
841 ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
842 /* XXX there is not freeing for dev? */
845 pci_set_drvdata(pci_dev,self);
847 printk (KERN_WARNING "ToshOboe: Using ");
853 printk (" tasks, version %s\n", rcsid);
857 for (i = 0; i < TX_SLOTS; ++i)
858 if (self->xmit_bufs[i])
859 kfree (self->xmit_bufs[i]);
860 for (i = 0; i < RX_SLOTS; ++i)
861 if (self->recv_bufs[i])
862 kfree (self->recv_bufs[i]);
863 kfree(self->taskfilebuf);
865 release_region (self->io.sir_base, self->io.sir_ext);
872 toshoboe_suspend (struct pci_dev *pci_dev, u32 crap)
875 struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev);
877 printk (KERN_WARNING "ToshOboe: suspending\n");
879 if (!self || self->stopped)
887 /*FIXME: can't sleep here wait one second */
889 while ((i--) && (self->txpending))
892 toshoboe_stopchip (self);
893 toshoboe_disablebm (self);
901 toshoboe_resume (struct pci_dev *pci_dev)
903 struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev);
921 toshoboe_initbuffs (self);
922 toshoboe_enablebm (self);
923 toshoboe_startchip (self);
925 toshoboe_setbaud (self, self->io.speed);
927 toshoboe_initptrs (self);
929 netif_wake_queue(self->netdev);
930 restore_flags (flags);
931 printk (KERN_WARNING "ToshOboe: waking up\n");
935 static struct pci_driver toshoboe_pci_driver = {
937 .id_table = toshoboe_pci_tbl,
938 .probe = toshoboe_probe,
939 .remove = toshoboe_remove,
940 .suspend = toshoboe_suspend,
941 .resume = toshoboe_resume
947 return pci_module_init(&toshoboe_pci_driver);
951 toshoboe_cleanup (void)
953 pci_unregister_driver(&toshoboe_pci_driver);
956 module_init(toshoboe_init);
957 module_exit(toshoboe_cleanup);