patch-2.3.35 linux/drivers/net/irda/smc-ircc.c
Next file: linux/drivers/net/irda/tekram.c
Previous file: linux/drivers/net/irda/pc87108.c
Back to the patch index
Back to the overall index
- Lines: 465
- Date:
Tue Dec 21 10:17:31 1999
- Orig file:
v2.3.34/linux/drivers/net/irda/smc-ircc.c
- Orig date:
Tue Nov 23 22:42:20 1999
diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/smc-ircc.c linux/drivers/net/irda/smc-ircc.c
@@ -6,7 +6,7 @@
* Status: Experimental.
* Author: Thomas Davis (tadavis@jps.net)
* Created at:
- * Modified at: Fri Nov 12 21:08:09 1999
+ * Modified at: Sat Dec 11 14:38:26 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Thomas Davis, All Rights Reserved.
@@ -68,12 +68,10 @@
static int ircc_dma_receive_complete(struct ircc_cb *self, int iobase);
static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev);
static void ircc_dma_write(struct ircc_cb *self, int iobase);
-static void ircc_change_speed(struct ircc_cb *self, __u32 speed);
+static void ircc_change_speed(void *priv, __u32 speed);
static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void ircc_wait_until_sent(struct ircc_cb *self);
static int ircc_is_receiving(struct ircc_cb *self);
-static int ircc_net_init(struct net_device *dev);
static int ircc_net_open(struct net_device *dev);
static int ircc_net_close(struct net_device *dev);
@@ -149,11 +147,10 @@
*/
static int ircc_open(int i, unsigned int iobase, unsigned int iobase2)
{
- struct net_device *dev;
struct ircc_cb *self;
+ struct irport_cb *irport;
int config;
int ret;
- int err;
IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
@@ -177,21 +174,30 @@
/* Need to store self somewhere */
dev_self[i] = self;
+ irport = irport_open(0, iobase2, config >> 4 & 0x0f);
+ if (!irport)
+ return -ENODEV;
+
+ /* Steal the network device from irport */
+ self->netdev = irport->netdev;
+ self->irport = irport;
+ irport->priv = self;
+
/* Initialize IO */
self->io.iobase = iobase;
self->io.iobase2 = iobase2; /* Used by irport */
self->io.irq = config >> 4 & 0x0f;
if (ircc_irq < 255) {
- printk(KERN_INFO "smc: Overriding IRQ - chip says %d, using %d\n",
- self->io.irq, ircc_irq);
+ MESSAGE("smc_ircc: Overriding IRQ - chip says %d, using %d\n",
+ self->io.irq, ircc_irq);
self->io.irq = ircc_irq;
}
self->io.io_ext = CHIP_IO_EXTENT;
self->io.io_ext2 = 8; /* Used by irport */
self->io.dma = config & 0x0f;
if (ircc_dma < 255) {
- printk(KERN_INFO "smc: Overriding DMA - chip says %d, using %d\n",
- self->io.dma, ircc_dma);
+ MESSAGE("smc: Overriding DMA - chip says %d, using %d\n",
+ self->io.dma, ircc_dma);
self->io.dma = ircc_dma;
}
self->io.fifo_size = 16;
@@ -204,15 +210,8 @@
/* ircc_cleanup(self->self); */
return -ENODEV;
}
- ret = check_region(self->io.iobase2, self->io.io_ext2);
- if (ret < 0) {
- IRDA_DEBUG(0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
- self->io.iobase2);
- /* ircc_cleanup(self->self); */
- return -ENODEV;
- }
+
request_region(self->io.iobase, self->io.io_ext, driver_name);
- request_region(self->io.iobase2, self->io.io_ext2, driver_name);
/* Initialize QoS for this device */
irda_init_max_qos_capabilies(&self->qos);
@@ -227,10 +226,10 @@
IR_115200;
#endif
- self->qos.min_turn_time.bits = 0x07;
- irda_qos_bits_to_value(&self->qos);
+ irport->qos.min_turn_time.bits = 0x07;
+ irda_qos_bits_to_value(&irport->qos);
- self->flags = IFF_FIR|IFF_SIR|IFF_DMA|IFF_PIO;
+ irport->flags = IFF_FIR|IFF_SIR|IFF_DMA|IFF_PIO;
/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
self->rx_buff.truesize = 4000;
@@ -259,31 +258,12 @@
self->tx_buff.data = self->tx_buff.head;
self->rx_buff.data = self->rx_buff.head;
- if (!(dev = dev_alloc("irda%d", &err))) {
- ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
- return -ENOMEM;
- }
+ /* Override the speed change function, since we must control it now */
+ irport->change_speed = &ircc_change_speed;
+ self->netdev->open = &ircc_net_open;
+ self->netdev->stop = &ircc_net_close;
- dev->priv = (void *) self;
- self->netdev = dev;
-
- /* Override the network functions we need to use */
- dev->init = ircc_net_init;
- dev->hard_start_xmit = ircc_hard_xmit;
- dev->open = ircc_net_open;
- dev->stop = ircc_net_close;
-
- rtnl_lock();
- err = register_netdevice(dev);
- rtnl_unlock();
- if (err) {
- ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
- return -1;
- }
-
- MESSAGE("IrDA: Registered device %s\n", dev->name);
-
- irport_start(&self->irport, iobase2);
+ irport_start(self->irport);
IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
return 0;
@@ -306,14 +286,7 @@
iobase = self->io.iobase;
- irport_stop(&self->irport, self->io.iobase2);
-
- /* Remove netdevice */
- if (self->netdev) {
- rtnl_lock();
- unregister_netdev(self->netdev);
- rtnl_unlock();
- }
+ irport_close(self->irport);
register_bank(iobase, 0);
serial_out(iobase, UART_IER, 0);
@@ -331,12 +304,6 @@
release_region(self->io.iobase, self->io.io_ext);
- if (self->io.iobase2) {
- IRDA_DEBUG(ircc_debug, __FUNCTION__ ": releasing 0x%03x\n",
- self->io.iobase2);
- release_region(self->io.iobase2, self->io.io_ext2);
- }
-
if (self->tx_buff.head)
kfree(self->tx_buff.head);
@@ -394,14 +361,17 @@
* Change the speed of the device
*
*/
-static void ircc_change_speed(struct ircc_cb *self, __u32 speed)
+static void ircc_change_speed(void *priv, __u32 speed)
{
int iobase, ir_mode, select, fast;
+ struct ircc_cb *self = (struct ircc_cb *) priv;
+ struct net_device *dev;
IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
ASSERT(self != NULL, return;);
+ dev = self->netdev;
iobase = self->io.iobase;
/* Update accounting for new speed */
@@ -420,8 +390,14 @@
serial_out(iobase, UART_IER, 0);
serial_out(iobase, UART_MASTER, UART_MASTER_RESET);
serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
- irport_start(&self->irport, self->io.iobase2);
- __irport_change_speed(&self->irport, speed);
+
+ dev->hard_start_xmit = &irport_hard_xmit;
+
+ /* We must give the interrupt back to irport */
+ self->irport->interrupt = irport_interrupt;
+
+ irport_start(self->irport);
+ irport_change_speed(self->irport, speed);
return;
break;
@@ -429,22 +405,26 @@
ir_mode = UART_CFGA_IRDA_HDLC;
select = 0;
fast = 0;
- IRDA_DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 576000\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__
+ "(), handling baud of 576000\n");
break;
case 1152000:
ir_mode = UART_CFGA_IRDA_HDLC;
select = UART_1152;
fast = 0;
- IRDA_DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 1152000\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__
+ "(), handling baud of 1152000\n");
break;
case 4000000:
ir_mode = UART_CFGA_IRDA_4PPM;
select = 0;
fast = UART_LCR_A_FAST;
- IRDA_DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 4000000\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__
+ "(), handling baud of 4000000\n");
break;
default:
- IRDA_DEBUG(0, __FUNCTION__ ": unknown baud rate of %d\n", speed);
+ IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n",
+ speed);
return;
}
@@ -457,9 +437,15 @@
register_bank(iobase, 0);
serial_out(iobase, UART_IER, 0);
- irport_stop(&self->irport, self->io.iobase2);
+ irport_stop(self->irport);
- self->netdev->tbusy = 0;
+ /* Install FIR transmit handler */
+ dev->hard_start_xmit = &ircc_hard_xmit;
+
+ /* Need to steal the interrupt as well */
+ self->irport->interrupt = &ircc_interrupt;
+
+ dev->tbusy = 0;
register_bank(iobase, 1);
@@ -493,13 +479,15 @@
*/
static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
+ struct irport_cb *irport;
struct ircc_cb *self;
int iobase;
int mtt;
__u32 speed;
IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
- self = (struct ircc_cb *) dev->priv;
+ irport = (struct irport_cb *) dev->priv;
+ self = (struct ircc_cb *) irport->priv;
ASSERT(self != NULL, return 0;);
@@ -510,14 +498,7 @@
/* Check if we need to change the speed */
if ((speed = irda_get_speed(skb)) != self->io.speed)
- ircc_change_speed(self, speed);
-
- /* Use irport for SIR speeds */
- if (self->io.speed <= 115200) {
- IRDA_DEBUG(ircc_debug+1, __FUNCTION__
- ": calling irport_hard_xmit\n");
- return irport_hard_xmit(skb, dev);
- }
+ self->new_speed = speed;
IRDA_DEBUG(ircc_debug, __FUNCTION__ ": using dma; len=%d\n", skb->len);
@@ -631,11 +612,17 @@
/* Check for underrrun! */
if (underrun) {
- self->stats.tx_errors++;
- self->stats.tx_fifo_errors++;
+ self->irport->stats.tx_errors++;
+ self->irport->stats.tx_fifo_errors++;
} else {
- self->stats.tx_packets++;
- self->stats.tx_bytes += self->tx_buff.len;
+ self->irport->stats.tx_packets++;
+ self->irport->stats.tx_bytes += self->tx_buff.len;
+ }
+
+ if (self->new_speed) {
+ ircc_change_speed(self, self->new_speed);
+
+ self->new_speed = 0;
}
/* Unlock tx_buff and request another frame */
@@ -733,7 +720,7 @@
skb_put(skb, len);
memcpy(skb->data, self->rx_buff.data, len);
- self->stats.rx_packets++;
+ self->irport->stats.rx_packets++;
skb->dev = self->netdev;
skb->mac.raw = skb->data;
@@ -771,12 +758,6 @@
self = (struct ircc_cb *) dev->priv;
- if (self->io.speed <= 115200) {
- IRDA_DEBUG(ircc_debug+1, __FUNCTION__
- ": routing interrupt to irport_interrupt\n");
- return irport_interrupt(irq, dev_id, regs);
- }
-
iobase = self->io.iobase;
dev->interrupt = 1;
@@ -823,23 +804,6 @@
}
/*
- * Function ircc_wait_until_sent (self)
- *
- * This function should put the current thread to sleep until all data
- * have been sent, so it is safe to change the speed.
- */
-static void ircc_wait_until_sent(struct ircc_cb *self)
-{
- IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
-
- /* Just delay 60 ms */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(60));
-
- IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
-}
-
-/*
* Function ircc_is_receiving (self)
*
* Return TRUE is we are currently receiving a frame
@@ -865,26 +829,6 @@
}
/*
- * Function ircc_net_init (dev)
- *
- * Initialize network device
- *
- */
-static int ircc_net_init(struct net_device *dev)
-{
- IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
-
- /* Setup to be a normal IrDA network device driver */
- irda_device_setup(dev);
-
- /* Insert overrides below this line! */
-
- IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
- return 0;
-}
-
-
-/*
* Function ircc_net_open (dev)
*
* Start the device
@@ -892,22 +836,22 @@
*/
static int ircc_net_open(struct net_device *dev)
{
+ struct irport_cb *irport;
struct ircc_cb *self;
int iobase;
-
+
IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
ASSERT(dev != NULL, return -1;);
- self = (struct ircc_cb *) dev->priv;
-
+ irport = (struct irport_cb *) dev->priv;
+ self = (struct ircc_cb *) irport->priv;
+
ASSERT(self != NULL, return 0;);
iobase = self->io.iobase;
- if (request_irq(self->io.irq, ircc_interrupt, 0, dev->name,
- (void *) dev)) {
- return -EAGAIN;
- }
+ irport_net_open(dev);
+
/*
* Always allocate the DMA channel after the IRQ,
* and clean up on failure.
@@ -916,17 +860,6 @@
free_irq(self->io.irq, dev);
return -EAGAIN;
}
-
- /* Ready to play! */
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
-
- /*
- * Open new IrLAP layer instance, now that everything should be
- * initialized properly
- */
- self->irlap = irlap_open(dev, &self->qos);
MOD_INC_USE_COUNT;
@@ -942,31 +875,24 @@
*/
static int ircc_net_close(struct net_device *dev)
{
+ struct irport_cb *irport;
struct ircc_cb *self;
int iobase;
IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
ASSERT(dev != NULL, return -1;);
- self = (struct ircc_cb *) dev->priv;
+ irport = (struct irport_cb *) dev->priv;
+ self = (struct ircc_cb *) irport->priv;
ASSERT(self != NULL, return 0;);
iobase = self->io.iobase;
- /* Stop device */
- dev->tbusy = 1;
- dev->start = 0;
-
- /* Stop and remove instance of IrLAP */
- if (self->irlap)
- irlap_close(self->irlap);
- self->irlap = NULL;
+ irport_net_close(dev);
disable_dma(self->io.dma);
- /* Disable interrupts */
- free_irq(self->io.irq, dev);
free_dma(self->io.dma);
MOD_DEC_USE_COUNT;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)