Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

irport.c

Go to the documentation of this file.
00001 /*********************************************************************
00002  * 
00003  * Filename:      irport.c
00004  * Version:       1.0
00005  * Description:   Half duplex serial port SIR driver for IrDA. 
00006  * Status:        Experimental.
00007  * Author:        Dag Brattli <dagb@cs.uit.no>
00008  * Created at:    Sun Aug  3 13:49:59 1997
00009  * Modified at:   Tue Apr 25 21:18:48 2000
00010  * Modified by:   Dag Brattli <dagb@cs.uit.no>
00011  * Sources:       serial.c by Linus Torvalds 
00012  * 
00013  *     Copyright (c) 1997, 1998, 1999-2000 Dag Brattli, All Rights Reserved.
00014  *     
00015  *     This program is free software; you can redistribute it and/or 
00016  *     modify it under the terms of the GNU General Public License as 
00017  *     published by the Free Software Foundation; either version 2 of 
00018  *     the License, or (at your option) any later version.
00019  * 
00020  *     This program is distributed in the hope that it will be useful,
00021  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00023  *     GNU General Public License for more details.
00024  * 
00025  *     You should have received a copy of the GNU General Public License 
00026  *     along with this program; if not, write to the Free Software 
00027  *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
00028  *     MA 02111-1307 USA
00029  *
00030  *     This driver is ment to be a small half duplex serial driver to be
00031  *     used for IR-chipsets that has a UART (16550) compatibility mode. 
00032  *     Eventually it will replace irtty, because of irtty has some 
00033  *     problems that is hard to get around when we don't have control
00034  *     over the serial driver. This driver may also be used by FIR 
00035  *     drivers to handle SIR mode for them.
00036  *
00037  ********************************************************************/
00038 
00039 #include <linux/module.h>
00040 
00041 #include <linux/kernel.h>
00042 #include <linux/types.h>
00043 #include <linux/ioport.h>
00044 #include <linux/malloc.h>
00045 #include <linux/string.h>
00046 #include <linux/skbuff.h>
00047 #include <linux/serial_reg.h>
00048 #include <linux/errno.h>
00049 #include <linux/init.h>
00050 #include <asm/spinlock.h>
00051 #include <linux/rtnetlink.h>
00052 
00053 #include <asm/system.h>
00054 #include <asm/bitops.h>
00055 #include <asm/io.h>
00056 
00057 #include <net/irda/irda.h>
00058 #include <net/irda/irmod.h>
00059 #include <net/irda/wrapper.h>
00060 #include <net/irda/irport.h>
00061 
00062 #define IO_EXTENT 8
00063 
00064 /* 
00065  * Currently you'll need to set these values using insmod like this:
00066  * insmod irport io=0x3e8 irq=11
00067  */
00068 static unsigned int io[]  = { ~0, ~0, ~0, ~0 };
00069 static unsigned int irq[] = { 0, 0, 0, 0 };
00070 
00071 static unsigned int qos_mtt_bits = 0x03;
00072 
00073 static struct irport_cb *dev_self[] = { NULL, NULL, NULL, NULL};
00074 static char *driver_name = "irport";
00075 
00076 static void irport_write_wakeup(struct irport_cb *self);
00077 static int  irport_write(int iobase, int fifo_size, __u8 *buf, int len);
00078 static void irport_receive(struct irport_cb *self);
00079 
00080 static int  irport_net_init(struct device *dev);
00081 static int  irport_net_ioctl(struct device *dev, struct ifreq *rq, 
00082                              int cmd);
00083 static int  irport_is_receiving(struct irport_cb *self);
00084 static int  irport_set_dtr_rts(struct device *dev, int dtr, int rts);
00085 static int  irport_raw_write(struct device *dev, __u8 *buf, int len);
00086 static struct net_device_stats *irport_net_get_stats(struct device *dev);
00087 static int irport_change_speed_complete(struct irda_task *task);
00088 
00089 EXPORT_SYMBOL(irport_open);
00090 EXPORT_SYMBOL(irport_close);
00091 EXPORT_SYMBOL(irport_start);
00092 EXPORT_SYMBOL(irport_stop);
00093 EXPORT_SYMBOL(irport_interrupt);
00094 EXPORT_SYMBOL(irport_hard_xmit);
00095 EXPORT_SYMBOL(irport_change_speed);
00096 EXPORT_SYMBOL(irport_net_open);
00097 EXPORT_SYMBOL(irport_net_close);
00098 
00099 int __init irport_init(void)
00100 {
00101         int i;
00102 
00103         for (i=0; (io[i] < 2000) && (i < 4); i++) {
00104                 int ioaddr = io[i];
00105                 if (check_region(ioaddr, IO_EXTENT))
00106                         continue;
00107                 if (irport_open(i, io[i], irq[i]) != NULL)
00108                         return 0;
00109         }
00110         /* 
00111          * Maybe something failed, but we can still be usable for FIR drivers 
00112          */
00113         return 0;
00114 }
00115 
00116 /*
00117  * Function irport_cleanup ()
00118  *
00119  *    Close all configured ports
00120  *
00121  */
00122 #ifdef MODULE
00123 static void irport_cleanup(void)
00124 {
00125         int i;
00126 
00127         IRDA_DEBUG( 4, __FUNCTION__ "()\n");
00128 
00129         for (i=0; i < 4; i++) {
00130                 if (dev_self[i])
00131                         irport_close(dev_self[i]);
00132         }
00133 }
00134 #endif /* MODULE */
00135 
00136 struct irport_cb *
00137 irport_open(int i, unsigned int iobase, unsigned int irq)
00138 {
00139         struct device *dev;
00140         struct irport_cb *self;
00141         int ret;
00142         int err;
00143 
00144         IRDA_DEBUG(0, __FUNCTION__ "()\n");
00145 
00146         /*
00147          *  Allocate new instance of the driver
00148          */
00149         self = kmalloc(sizeof(struct irport_cb), GFP_KERNEL);
00150         if (!self) {
00151                 ERROR(__FUNCTION__ "(), can't allocate memory for "
00152                       "control block!\n");
00153                 return NULL;
00154         }
00155         memset(self, 0, sizeof(struct irport_cb));
00156         spin_lock_init(&self->lock);
00157 
00158         /* Need to store self somewhere */
00159         dev_self[i] = self;
00160         self->priv = self;
00161         self->index = i;
00162 
00163         /* Initialize IO */
00164         self->io.sir_base  = iobase;
00165         self->io.sir_ext   = IO_EXTENT;
00166         self->io.irq       = irq;
00167         self->io.fifo_size = 16;
00168 
00169         /* Lock the port that we need */
00170         ret = check_region(self->io.sir_base, self->io.sir_ext);
00171         if (ret < 0) { 
00172                 IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
00173                            self->io.sir_base);
00174                 return NULL;
00175         }
00176         request_region(self->io.sir_base, self->io.sir_ext, driver_name);
00177 
00178         /* Initialize QoS for this device */
00179         irda_init_max_qos_capabilies(&self->qos);
00180         
00181         self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
00182                 IR_115200;
00183 
00184         self->qos.min_turn_time.bits = qos_mtt_bits;
00185         irda_qos_bits_to_value(&self->qos);
00186         
00187         self->flags = IFF_SIR|IFF_PIO;
00188 
00189         /* Specify how much memory we want */
00190         self->rx_buff.truesize = 4000; 
00191         self->tx_buff.truesize = 4000;
00192         
00193         /* Allocate memory if needed */
00194         if (self->rx_buff.truesize > 0) {
00195                 self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
00196                                                       GFP_KERNEL);
00197                 if (self->rx_buff.head == NULL)
00198                         return NULL;
00199                 memset(self->rx_buff.head, 0, self->rx_buff.truesize);
00200         }
00201         if (self->tx_buff.truesize > 0) {
00202                 self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
00203                                                       GFP_KERNEL);
00204                 if (self->tx_buff.head == NULL) {
00205                         kfree(self->rx_buff.head);
00206                         return NULL;
00207                 }
00208                 memset(self->tx_buff.head, 0, self->tx_buff.truesize);
00209         }       
00210         self->rx_buff.in_frame = FALSE;
00211         self->rx_buff.state = OUTSIDE_FRAME;
00212         self->tx_buff.data = self->tx_buff.head;
00213         self->rx_buff.data = self->rx_buff.head;
00214         self->mode = IRDA_IRLAP;
00215 
00216         if (!(dev = dev_alloc("irda%d", &err))) {
00217                 ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
00218                 return NULL;
00219         }
00220         /* dev_alloc doesn't clear the struct */
00221         memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct device)-sizeof(char*));
00222 
00223         self->netdev = dev;
00224 
00225         /* May be overridden by piggyback drivers */
00226         dev->priv = (void *) self;
00227         self->interrupt    = irport_interrupt;
00228         self->change_speed = irport_change_speed;
00229 
00230         /* Override the network functions we need to use */
00231         dev->init            = irport_net_init;
00232         dev->hard_start_xmit = irport_hard_xmit;
00233         dev->open            = irport_net_open;
00234         dev->stop            = irport_net_close;
00235         dev->get_stats       = irport_net_get_stats;
00236         dev->do_ioctl        = irport_net_ioctl;
00237 
00238         /* Make ifconfig display some details */
00239         dev->base_addr = iobase;
00240         dev->irq = irq;
00241 
00242         rtnl_lock();
00243         err = register_netdevice(dev);
00244         rtnl_unlock();
00245         if (err) {
00246                 ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
00247                 return NULL;
00248         }
00249         MESSAGE("IrDA: Registered device %s\n", dev->name);
00250 
00251         return self;
00252 }
00253 
00254 int irport_close(struct irport_cb *self)
00255 {
00256         ASSERT(self != NULL, return -1;);
00257 
00258         /* We are not using any dongle anymore! */
00259         if (self->dongle)
00260                 irda_device_dongle_cleanup(self->dongle);
00261         self->dongle = NULL;
00262         
00263         /* Remove netdevice */
00264         if (self->netdev) {
00265                 rtnl_lock();
00266                 unregister_netdevice(self->netdev);
00267                 rtnl_unlock();
00268                 /* Must free the old-style 2.2.x device */
00269                 kfree(self->netdev);
00270         }
00271 
00272         /* Release the IO-port that this driver is using */
00273         IRDA_DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", 
00274                    self->io.sir_base);
00275         release_region(self->io.sir_base, self->io.sir_ext);
00276 
00277         if (self->tx_buff.head)
00278                 kfree(self->tx_buff.head);
00279         
00280         if (self->rx_buff.head)
00281                 kfree(self->rx_buff.head);
00282         
00283         /* Remove ourselves */
00284         dev_self[self->index] = NULL;
00285         kfree(self);
00286         
00287         return 0;
00288 }
00289 
00290 void irport_start(struct irport_cb *self)
00291 {
00292         unsigned long flags;
00293         int iobase;
00294 
00295         iobase = self->io.sir_base;
00296 
00297         spin_lock_irqsave(&self->lock, flags);
00298 
00299         irport_stop(self);
00300 
00301         /* Initialize UART */
00302         outb(UART_LCR_WLEN8, iobase+UART_LCR);  /* Reset DLAB */
00303         outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR);
00304         
00305         /* Turn on interrups */
00306         outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, iobase+UART_IER);
00307 
00308         spin_unlock_irqrestore(&self->lock, flags);
00309 }
00310 
00311 void irport_stop(struct irport_cb *self)
00312 {
00313         unsigned long flags;
00314         int iobase;
00315 
00316         iobase = self->io.sir_base;
00317 
00318         spin_lock_irqsave(&self->lock, flags);
00319 
00320         /* Reset UART */
00321         outb(0, iobase+UART_MCR);
00322         
00323         /* Turn off interrupts */
00324         outb(0, iobase+UART_IER);
00325 
00326         spin_unlock_irqrestore(&self->lock, flags);
00327 }
00328 
00329 /*
00330  * Function irport_probe (void)
00331  *
00332  *    Start IO port 
00333  *
00334  */
00335 int irport_probe(int iobase)
00336 {
00337         IRDA_DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase);
00338 
00339         return 0;
00340 }
00341 
00342 /*
00343  * Function irport_change_speed (self, speed)
00344  *
00345  *    Set speed of IrDA port to specified baudrate
00346  *
00347  */
00348 void irport_change_speed(void *priv, __u32 speed)
00349 {
00350         struct irport_cb *self = (struct irport_cb *) priv;
00351         unsigned long flags;
00352         int iobase; 
00353         int fcr;    /* FIFO control reg */
00354         int lcr;    /* Line control reg */
00355         int divisor;
00356 
00357         IRDA_DEBUG(2, __FUNCTION__ "(), Setting speed to: %d\n", speed);
00358 
00359         ASSERT(self != NULL, return;);
00360 
00361         iobase = self->io.sir_base;
00362         
00363         /* Update accounting for new speed */
00364         self->io.speed = speed;
00365 
00366         spin_lock_irqsave(&self->lock, flags);
00367 
00368         /* Turn off interrupts */
00369         outb(0, iobase+UART_IER); 
00370 
00371         divisor = SPEED_MAX/speed;
00372         
00373         fcr = UART_FCR_ENABLE_FIFO;
00374 
00375         /* 
00376          * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and
00377          * almost 1,7 ms at 19200 bps. At speeds above that we can just forget
00378          * about this timeout since it will always be fast enough. 
00379          */
00380         if (self->io.speed < 38400)
00381                 fcr |= UART_FCR_TRIGGER_1;
00382         else 
00383                 fcr |= UART_FCR_TRIGGER_14;
00384         
00385         /* IrDA ports use 8N1 */
00386         lcr = UART_LCR_WLEN8;
00387         
00388         outb(UART_LCR_DLAB | lcr, iobase+UART_LCR); /* Set DLAB */
00389         outb(divisor & 0xff,      iobase+UART_DLL); /* Set speed */
00390         outb(divisor >> 8,        iobase+UART_DLM);
00391         outb(lcr,                 iobase+UART_LCR); /* Set 8N1  */
00392         outb(fcr,                 iobase+UART_FCR); /* Enable FIFO's */
00393 
00394         /* Turn on interrups */
00395         outb(/*UART_IER_RLSI|*/UART_IER_RDI/*|UART_IER_THRI*/, iobase+UART_IER);
00396 
00397         spin_unlock_irqrestore(&self->lock, flags);
00398 }
00399 
00400 /*
00401  * Function __irport_change_speed (instance, state, param)
00402  *
00403  *    State machine for changing speed of the device. We do it this way since
00404  *    we cannot use schedule_timeout() when we are in interrupt context
00405  */
00406 int __irport_change_speed(struct irda_task *task)
00407 {
00408         struct irport_cb *self;
00409         __u32 speed = (__u32) task->param;
00410         int ret = 0;
00411 
00412         IRDA_DEBUG(2, __FUNCTION__ "(), <%ld>\n", jiffies); 
00413 
00414         self = (struct irport_cb *) task->instance;
00415 
00416         ASSERT(self != NULL, return -1;);
00417 
00418         switch (task->state) {
00419         case IRDA_TASK_INIT:
00420         case IRDA_TASK_WAIT:
00421                 /* Are we ready to change speed yet? */
00422                 if (self->tx_buff.len > 0) {
00423                         task->state = IRDA_TASK_WAIT;
00424 
00425                         /* Try again later */
00426                         ret = MSECS_TO_JIFFIES(20);
00427                         break;
00428                 }
00429 
00430                 if (self->dongle)
00431                         irda_task_next_state(task, IRDA_TASK_CHILD_INIT);
00432                 else
00433                         irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
00434                 break;
00435         case IRDA_TASK_CHILD_INIT:
00436                 /* Go to default speed */
00437                 self->change_speed(self->priv, 9600);
00438 
00439                 /* Change speed of dongle */
00440                 if (irda_task_execute(self->dongle,
00441                                       self->dongle->issue->change_speed, 
00442                                       NULL, task, (void *) speed))
00443                 {
00444                         /* Dongle need more time to change its speed */
00445                         irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
00446 
00447                         /* Give dongle 1 sec to finish */
00448                         ret = MSECS_TO_JIFFIES(1000);
00449                 } else
00450                         /* Child finished immediately */
00451                         irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
00452                 break;
00453         case IRDA_TASK_CHILD_WAIT:
00454                 WARNING(__FUNCTION__ 
00455                         "(), changing speed of dongle timed out!\n");
00456                 ret = -1;               
00457                 break;
00458         case IRDA_TASK_CHILD_DONE:
00459                 /* Finally we are ready to change the speed */
00460                 self->change_speed(self->priv, speed);
00461                 
00462                 irda_task_next_state(task, IRDA_TASK_DONE);
00463                 break;
00464         default:
00465                 ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
00466                 irda_task_next_state(task, IRDA_TASK_DONE);
00467                 ret = -1;
00468                 break;
00469         }       
00470         return ret;
00471 }
00472 
00473 /*
00474  * Function irport_write_wakeup (tty)
00475  *
00476  *    Called by the driver when there's room for more data.  If we have
00477  *    more packets to send, we send them here.
00478  *
00479  */
00480 static void irport_write_wakeup(struct irport_cb *self)
00481 {
00482         int actual = 0;
00483         int iobase;
00484         int fcr;
00485 
00486         ASSERT(self != NULL, return;);
00487 
00488         IRDA_DEBUG(4, __FUNCTION__ "()\n");
00489 
00490         iobase = self->io.sir_base;
00491 
00492         /* Finished with frame?  */
00493         if (self->tx_buff.len > 0)  {
00494                 /* Write data left in transmit buffer */
00495                 actual = irport_write(iobase, self->io.fifo_size, 
00496                                       self->tx_buff.data, self->tx_buff.len);
00497                 self->tx_buff.data += actual;
00498                 self->tx_buff.len  -= actual;
00499         } else {
00500                 
00501                 /* 
00502                  *  Now serial buffer is almost free & we can start 
00503                  *  transmission of another packet. But first we must check
00504                  *  if we need to change the speed of the hardware
00505                  */
00506                 if (self->new_speed) {
00507                         IRDA_DEBUG(5, __FUNCTION__ "(), Changing speed!\n");
00508                         irda_task_execute(self, __irport_change_speed, 
00509                                           irport_change_speed_complete, 
00510                                           NULL, (void *) self->new_speed);
00511                         self->new_speed = 0;
00512                 } else {
00513                         self->netdev->tbusy = 0; /* Unlock */
00514                 
00515                         /* Tell network layer that we want more frames */
00516                         mark_bh(NET_BH);
00517                 }
00518                 self->stats.tx_packets++;
00519 
00520                 /* Schedule network layer, so we can get some more frames */
00521                 mark_bh(NET_BH);
00522 
00523                 /* 
00524                  * Reset Rx FIFO to make sure that all reflected transmit data
00525                  * is discarded. This is needed for half duplex operation
00526                  */
00527                 fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR;
00528                 if (self->io.speed < 38400)
00529                         fcr |= UART_FCR_TRIGGER_1;
00530                 else 
00531                         fcr |= UART_FCR_TRIGGER_14;
00532 
00533                 outb(fcr, iobase+UART_FCR);
00534 
00535                 /* Turn on receive interrupts */
00536                 outb(UART_IER_RDI, iobase+UART_IER);
00537         }
00538 }
00539 
00540 /*
00541  * Function irport_write (driver)
00542  *
00543  *    Fill Tx FIFO with transmit data
00544  *
00545  */
00546 static int irport_write(int iobase, int fifo_size, __u8 *buf, int len)
00547 {
00548         int actual = 0;
00549 
00550         /* Tx FIFO should be empty! */
00551         if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
00552                 IRDA_DEBUG(0, __FUNCTION__ "(), failed, fifo not empty!\n");
00553                 return 0;
00554         }
00555         
00556         /* Fill FIFO with current frame */
00557         while ((fifo_size-- > 0) && (actual < len)) {
00558                 /* Transmit next byte */
00559                 outb(buf[actual], iobase+UART_TX);
00560 
00561                 actual++;
00562         }
00563         
00564         return actual;
00565 }
00566 
00567 /*
00568  * Function irport_change_speed_complete (task)
00569  *
00570  *    Called when the change speed operation completes
00571  *
00572  */
00573 static int irport_change_speed_complete(struct irda_task *task)
00574 {
00575         struct irport_cb *self;
00576 
00577         IRDA_DEBUG(0, __FUNCTION__ "()\n");
00578 
00579         self = (struct irport_cb *) task->instance;
00580 
00581         ASSERT(self != NULL, return -1;);
00582         ASSERT(self->netdev != NULL, return -1;);
00583 
00584         /* Finished changing speed, so we are not busy any longer */
00585         self->netdev->tbusy = 0;
00586 
00587         /* Signal network layer so it can try to send the frame */
00588         mark_bh(NET_BH);
00589 
00590         return 0;
00591 }
00592 
00593 /*
00594  * Function irport_xmit (void)
00595  *
00596  *    Transmits the current frame until FIFO is full, then
00597  *    waits until the next transmitt interrupt, and continues until the
00598  *    frame is transmited.
00599  */
00600 int irport_hard_xmit(struct sk_buff *skb, struct device *dev)
00601 {
00602         struct irport_cb *self;
00603         unsigned long flags;
00604         int iobase;
00605         __u32 speed;
00606 
00607         ASSERT(dev != NULL, return 0;);
00608         
00609         self = (struct irport_cb *) dev->priv;
00610         ASSERT(self != NULL, return 0;);
00611 
00612         iobase = self->io.sir_base;
00613 
00614         /* Lock transmit buffer */
00615         if (irda_lock((void *) &dev->tbusy) == FALSE) {
00616                 int tickssofar = jiffies - dev->trans_start;
00617                 if ((tickssofar < 5) || !dev->start)
00618                         return -EBUSY;
00619 
00620                 WARNING("%s: transmit timed out\n", dev->name);
00621                 irport_start(self);
00622                 self->change_speed(self->priv, self->io.speed);
00623 
00624                 dev->trans_start = jiffies;
00625         }
00626 
00627         /* Check if we need to change the speed */
00628         if ((speed = irda_get_speed(skb)) != self->io.speed)
00629                 self->new_speed = speed;
00630 
00631         spin_lock_irqsave(&self->lock, flags);
00632 
00633         /* Init tx buffer */
00634         self->tx_buff.data = self->tx_buff.head;
00635 
00636         /* Copy skb to tx_buff while wrapping, stuffing and making CRC */
00637         self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 
00638                                            self->tx_buff.truesize);
00639         
00640         self->stats.tx_bytes += self->tx_buff.len;
00641 
00642         /* Turn on transmit finished interrupt. Will fire immediately!  */
00643         outb(UART_IER_THRI, iobase+UART_IER); 
00644 
00645         spin_unlock_irqrestore(&self->lock, flags);
00646 
00647         dev_kfree_skb(skb);
00648         
00649         return 0;
00650 }
00651         
00652 /*
00653  * Function irport_receive (self)
00654  *
00655  *    Receive one frame from the infrared port
00656  *
00657  */
00658 static void irport_receive(struct irport_cb *self) 
00659 {
00660         int boguscount = 0;
00661         int iobase;
00662 
00663         ASSERT(self != NULL, return;);
00664 
00665         iobase = self->io.sir_base;
00666 
00667         /*  
00668          * Receive all characters in Rx FIFO, unwrap and unstuff them. 
00669          * async_unwrap_char will deliver all found frames  
00670          */
00671         do {
00672                 async_unwrap_char(self->netdev, &self->stats, &self->rx_buff, 
00673                                   inb(iobase+UART_RX));
00674 
00675                 /* Make sure we don't stay here to long */
00676                 if (boguscount++ > 32) {
00677                         IRDA_DEBUG(2,__FUNCTION__ "(), breaking!\n");
00678                         break;
00679                 }
00680         } while (inb(iobase+UART_LSR) & UART_LSR_DR);   
00681 }
00682 
00683 /*
00684  * Function irport_interrupt (irq, dev_id, regs)
00685  *
00686  *    Interrupt handler
00687  */
00688 void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs) 
00689 {
00690         struct device *dev = (struct device *) dev_id;
00691         struct irport_cb *self;
00692         int boguscount = 0;
00693         int iobase;
00694         int iir, lsr;
00695 
00696         if (!dev) {
00697                 WARNING(__FUNCTION__ "() irq %d for unknown device.\n", irq);
00698                 return;
00699         }
00700         self = (struct irport_cb *) dev->priv;
00701 
00702         spin_lock(&self->lock);
00703 
00704         dev->interrupt = 1;
00705 
00706         iobase = self->io.sir_base;
00707 
00708         iir = inb(iobase+UART_IIR) & UART_IIR_ID;
00709         while (iir) {
00710                 /* Clear interrupt */
00711                 lsr = inb(iobase+UART_LSR);
00712 
00713                 IRDA_DEBUG(4, __FUNCTION__ 
00714                            "(), iir=%02x, lsr=%02x, iobase=%#x\n", 
00715                            iir, lsr, iobase);
00716 
00717                 switch (iir) {
00718                 case UART_IIR_RLSI:
00719                         IRDA_DEBUG(2, __FUNCTION__ "(), RLSI\n");
00720                         break;
00721                 case UART_IIR_RDI:
00722                         /* Receive interrupt */
00723                         irport_receive(self);
00724                         break;
00725                 case UART_IIR_THRI:
00726                         if (lsr & UART_LSR_THRE)
00727                                 /* Transmitter ready for data */
00728                                 irport_write_wakeup(self);
00729                         break;
00730                 default:
00731                         IRDA_DEBUG(0, __FUNCTION__ "(), unhandled IIR=%#x\n", iir);
00732                         break;
00733                 } 
00734                 
00735                 /* Make sure we don't stay here to long */
00736                 if (boguscount++ > 100)
00737                         break;
00738 
00739                 iir = inb(iobase + UART_IIR) & UART_IIR_ID;
00740         }
00741         dev->interrupt = 0;
00742 
00743         spin_unlock(&self->lock);
00744 }
00745 
00746 static int irport_net_init(struct device *dev)
00747 {
00748         /* Set up to be a normal IrDA network device driver */
00749         irda_device_setup(dev);
00750 
00751         /* Insert overrides below this line! */
00752 
00753         return 0;
00754 }
00755 
00756 /*
00757  * Function irport_net_open (dev)
00758  *
00759  *    Network device is taken up. Usually this is done by "ifconfig irda0 up" 
00760  *   
00761  */
00762 int irport_net_open(struct device *dev)
00763 {
00764         struct irport_cb *self;
00765         int iobase;
00766 
00767         ASSERT(dev != NULL, return -1;);
00768         self = (struct irport_cb *) dev->priv;
00769 
00770         iobase = self->io.sir_base;
00771 
00772         if (request_irq(self->io.irq, self->interrupt, 0, dev->name, 
00773                         (void *) dev))
00774                 return -EAGAIN;
00775 
00776         irport_start(self);
00777 
00778         /* Ready to play! */
00779         dev->tbusy = 0;
00780         dev->interrupt = 0;
00781         dev->start = 1;
00782 
00783         /* 
00784          * Open new IrLAP layer instance, now that everything should be
00785          * initialized properly 
00786          */
00787         self->irlap = irlap_open(dev, &self->qos);
00788 
00789         /* FIXME: change speed of dongle */
00790 
00791         MOD_INC_USE_COUNT;
00792 
00793         return 0;
00794 }
00795 
00796 /*
00797  * Function irport_net_close (self)
00798  *
00799  *    Network device is taken down. Usually this is done by 
00800  *    "ifconfig irda0 down" 
00801  */
00802 int irport_net_close(struct device *dev)
00803 {
00804         struct irport_cb *self;
00805         int iobase;
00806 
00807         IRDA_DEBUG(4, __FUNCTION__ "()\n");
00808 
00809         ASSERT(dev != NULL, return -1;);
00810         self = (struct irport_cb *) dev->priv;
00811 
00812         ASSERT(self != NULL, return -1;);
00813 
00814         iobase = self->io.sir_base;
00815 
00816         /* Stop device */
00817         dev->tbusy = 1;
00818         dev->start = 0;
00819 
00820         /* Stop and remove instance of IrLAP */
00821         if (self->irlap)
00822                 irlap_close(self->irlap);
00823         self->irlap = NULL;
00824 
00825         irport_stop(self);
00826 
00827         free_irq(self->io.irq, dev);
00828 
00829         MOD_DEC_USE_COUNT;
00830 
00831         return 0;
00832 }
00833 
00834 /*
00835  * Function irport_wait_until_sent (self)
00836  *
00837  *    Delay exectution until finished transmitting
00838  *
00839  */
00840 #if 0
00841 void irport_wait_until_sent(struct irport_cb *self)
00842 {
00843         int iobase;
00844 
00845         iobase = self->io.sir_base;
00846 
00847         /* Wait until Tx FIFO is empty */
00848         while (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
00849                 IRDA_DEBUG(2, __FUNCTION__ "(), waiting!\n");
00850                 current->state = TASK_INTERRUPTIBLE;
00851                 schedule_timeout(MSECS_TO_JIFFIES(60));
00852         }
00853 }
00854 #endif
00855 
00856 /*
00857  * Function irport_is_receiving (self)
00858  *
00859  *    Returns true is we are currently receiving data
00860  *
00861  */
00862 static int irport_is_receiving(struct irport_cb *self)
00863 {
00864         return (self->rx_buff.state != OUTSIDE_FRAME);
00865 }
00866 
00867 /*
00868  * Function irport_set_dtr_rts (tty, dtr, rts)
00869  *
00870  *    This function can be used by dongles etc. to set or reset the status
00871  *    of the dtr and rts lines
00872  */
00873 static int irport_set_dtr_rts(struct device *dev, int dtr, int rts)
00874 {
00875         struct irport_cb *self = dev->priv;
00876         int iobase;
00877 
00878         ASSERT(self != NULL, return -1;);
00879 
00880         iobase = self->io.sir_base;
00881 
00882         if (dtr)
00883                 dtr = UART_MCR_DTR;
00884         if (rts)
00885                 rts = UART_MCR_RTS;
00886 
00887         outb(dtr|rts|UART_MCR_OUT2, iobase+UART_MCR);
00888 
00889         return 0;
00890 }
00891 
00892 static int irport_raw_write(struct device *dev, __u8 *buf, int len)
00893 {
00894         struct irport_cb *self = (struct irport_cb *) dev->priv;
00895         int actual = 0;
00896         int iobase;
00897 
00898         ASSERT(self != NULL, return -1;);
00899 
00900         iobase = self->io.sir_base;
00901 
00902         /* Tx FIFO should be empty! */
00903         if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
00904                 IRDA_DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n");
00905                 return -1;
00906         }
00907         
00908         /* Fill FIFO with current frame */
00909         while (actual < len) {
00910                 /* Transmit next byte */
00911                 outb(buf[actual], iobase+UART_TX);
00912                 actual++;
00913         }
00914 
00915         return actual;
00916 }
00917 
00918 /*
00919  * Function irport_net_ioctl (dev, rq, cmd)
00920  *
00921  *    Process IOCTL commands for this device
00922  *
00923  */
00924 static int irport_net_ioctl(struct device *dev, struct ifreq *rq, int cmd)
00925 {
00926         struct if_irda_req *irq = (struct if_irda_req *) rq;
00927         struct irport_cb *self;
00928         dongle_t *dongle;
00929         unsigned long flags;
00930         int ret = 0;
00931 
00932         ASSERT(dev != NULL, return -1;);
00933 
00934         self = dev->priv;
00935 
00936         ASSERT(self != NULL, return -1;);
00937 
00938         IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
00939         
00940         /* Disable interrupts & save flags */
00941         save_flags(flags);
00942         cli();
00943         
00944         switch (cmd) {
00945         case SIOCSBANDWIDTH: /* Set bandwidth */
00946                 /*
00947                  * This function will also be used by IrLAP to change the
00948                  * speed, so we still must allow for speed change within
00949                  * interrupt context.
00950                  */
00951                 if (!in_interrupt() && !capable(CAP_NET_ADMIN))
00952                         return -EPERM;
00953                 irda_task_execute(self, __irport_change_speed, NULL, NULL, 
00954                                   (void *) irq->ifr_baudrate);
00955                 break;
00956         case SIOCSDONGLE: /* Set dongle */
00957                 if (!capable(CAP_NET_ADMIN))
00958                         return -EPERM;
00959                 /* Initialize dongle */
00960                 dongle = irda_device_dongle_init(dev, irq->ifr_dongle);
00961                 if (!dongle)
00962                         break;
00963                 
00964                 dongle->set_mode    = NULL;
00965                 dongle->read        = NULL;
00966                 dongle->write       = irport_raw_write;
00967                 dongle->set_dtr_rts = irport_set_dtr_rts;
00968                 
00969                 self->dongle = dongle;
00970 
00971                 /* Now initialize the dongle!  */
00972                 dongle->issue->open(dongle, &self->qos);
00973                 
00974                 /* Reset dongle */
00975                 irda_task_execute(dongle, dongle->issue->reset, NULL, NULL, 
00976                                   NULL);        
00977                 break;
00978         case SIOCSMEDIABUSY: /* Set media busy */
00979                 if (!capable(CAP_NET_ADMIN))
00980                         return -EPERM;
00981                 irda_device_set_media_busy(self->netdev, TRUE);
00982                 break;
00983         case SIOCGRECEIVING: /* Check if we are receiving right now */
00984                 irq->ifr_receiving = irport_is_receiving(self);
00985                 break;
00986         case SIOCSDTRRTS:
00987                 if (!capable(CAP_NET_ADMIN))
00988                         return -EPERM;
00989                 irport_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
00990                 break;
00991         default:
00992                 ret = -EOPNOTSUPP;
00993         }
00994         
00995         restore_flags(flags);
00996         
00997         return ret;
00998 }
00999 
01000 static struct net_device_stats *irport_net_get_stats(struct device *dev)
01001 {
01002         struct irport_cb *self = (struct irport_cb *) dev->priv;
01003         
01004         return &self->stats;
01005 }
01006 
01007 #ifdef MODULE
01008 MODULE_PARM(io, "1-4i");
01009 MODULE_PARM(irq, "1-4i");
01010 
01011 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
01012 MODULE_DESCRIPTION("Half duplex serial driver for IrDA SIR mode");
01013 
01014 void cleanup_module(void)
01015 {
01016         irport_cleanup();
01017 }
01018 
01019 int init_module(void)
01020 {
01021         return irport_init();
01022 }
01023 #endif /* MODULE */
01024