summaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-24 00:12:35 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-24 00:12:35 +0000
commit482368b1a8e45430672c58c9a42e7d2004367126 (patch)
treece2a1a567d4d62dee7c2e71a46a99cf72cf1d606 /drivers/net
parente4d0251c6f56ab2e191afb70f80f382793e23f74 (diff)
Merge with 2.3.47. Guys, this is buggy as shit. You've been warned.
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/3c505.c183
-rw-r--r--drivers/net/3c505.h1
-rw-r--r--drivers/net/3c507.c99
-rw-r--r--drivers/net/3c509.c17
-rw-r--r--drivers/net/3c515.c1195
-rw-r--r--drivers/net/3c523.c6
-rw-r--r--drivers/net/3c527.c4
-rw-r--r--drivers/net/3c59x.c41
-rw-r--r--drivers/net/8139too.c1879
-rw-r--r--drivers/net/82596.c135
-rw-r--r--drivers/net/8390.c21
-rw-r--r--drivers/net/Config.in51
-rw-r--r--drivers/net/Makefile17
-rw-r--r--drivers/net/Space.c4
-rw-r--r--drivers/net/a2065.c147
-rw-r--r--drivers/net/acenic.c1112
-rw-r--r--drivers/net/acenic.h175
-rw-r--r--drivers/net/acenic_firmware.h8499
-rw-r--r--drivers/net/arcnet/arc-rimi.c13
-rw-r--r--drivers/net/arcnet/arcnet.c137
-rw-r--r--drivers/net/arcnet/com20020-isa.c7
-rw-r--r--drivers/net/arcnet/com20020-pci.c8
-rw-r--r--drivers/net/arcnet/com90io.c11
-rw-r--r--drivers/net/arcnet/com90xx.c45
-rw-r--r--drivers/net/arcnet/rfc1201.c8
-rw-r--r--drivers/net/ariadne.c20
-rw-r--r--drivers/net/at1700.c177
-rw-r--r--drivers/net/atp.c258
-rw-r--r--drivers/net/atp.h6
-rw-r--r--drivers/net/bmac.c327
-rw-r--r--drivers/net/cops.c166
-rw-r--r--drivers/net/cs89x0.c159
-rw-r--r--drivers/net/de4x5.c53
-rw-r--r--drivers/net/de600.c38
-rw-r--r--drivers/net/de620.c134
-rw-r--r--drivers/net/defxx.c50
-rw-r--r--drivers/net/depca.c200
-rw-r--r--drivers/net/dmfe.c58
-rw-r--r--drivers/net/eepro.c10
-rw-r--r--drivers/net/eepro100.c852
-rw-r--r--drivers/net/eexpress.c105
-rw-r--r--drivers/net/epic100.c697
-rw-r--r--drivers/net/eth16i.c347
-rw-r--r--drivers/net/ewrk3.c342
-rw-r--r--drivers/net/fc/iph5526.c94
-rw-r--r--drivers/net/fmv18x.c215
-rw-r--r--drivers/net/gmac.c106
-rw-r--r--drivers/net/hamradio/6pack.c143
-rw-r--r--drivers/net/hamradio/baycom_epp.c202
-rw-r--r--drivers/net/hamradio/baycom_par.c64
-rw-r--r--drivers/net/hamradio/baycom_ser_fdx.c29
-rw-r--r--drivers/net/hamradio/baycom_ser_hdx.c25
-rw-r--r--drivers/net/hamradio/bpqether.c41
-rw-r--r--drivers/net/hamradio/dmascc.c43
-rw-r--r--drivers/net/hamradio/hdlcdrv.c91
-rw-r--r--drivers/net/hamradio/scc.c133
-rw-r--r--drivers/net/hamradio/soundmodem/sm.c31
-rw-r--r--drivers/net/hamradio/yam.c27
-rw-r--r--drivers/net/hydra.c9
-rw-r--r--drivers/net/ioc3-eth.c3
-rw-r--r--drivers/net/irda/irport.c71
-rw-r--r--drivers/net/irda/irtty.c26
-rw-r--r--drivers/net/irda/nsc-ircc.c40
-rw-r--r--drivers/net/irda/toshoboe.c35
-rw-r--r--drivers/net/irda/w83977af_ir.c35
-rw-r--r--drivers/net/lance.c128
-rw-r--r--drivers/net/ltpc.c18
-rw-r--r--drivers/net/mace.c110
-rw-r--r--drivers/net/myri_sbus.c18
-rw-r--r--drivers/net/ncr885e.c46
-rw-r--r--drivers/net/ne2.c15
-rw-r--r--drivers/net/net_init.c4
-rw-r--r--drivers/net/ni5010.c98
-rw-r--r--drivers/net/ni52.c138
-rw-r--r--drivers/net/ni65.c82
-rw-r--r--drivers/net/pcmcia/3c574_cs.c199
-rw-r--r--drivers/net/pcmcia/3c575_cb.c250
-rw-r--r--drivers/net/pcmcia/3c589_cs.c89
-rw-r--r--drivers/net/pcmcia/Config.in1
-rw-r--r--drivers/net/pcmcia/Makefile4
-rw-r--r--drivers/net/pcmcia/aironet4500_cs.c15
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c124
-rw-r--r--drivers/net/pcmcia/netwave_cs.c86
-rw-r--r--drivers/net/pcmcia/nmclan_cs.c100
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c29
-rw-r--r--drivers/net/pcmcia/ray_cs.c13
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c101
-rw-r--r--drivers/net/pcmcia/tulip_cb.c126
-rw-r--r--drivers/net/pcmcia/wavelan_cs.c224
-rw-r--r--drivers/net/pcmcia/wavelan_cs.h5
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c88
-rw-r--r--drivers/net/pcnet32.c6
-rw-r--r--drivers/net/plip.c49
-rw-r--r--drivers/net/ppp_generic.c12
-rw-r--r--drivers/net/rcpci45.c39
-rw-r--r--drivers/net/rtl8129.c (renamed from drivers/net/rtl8139.c)64
-rw-r--r--drivers/net/sb1000.c15
-rw-r--r--drivers/net/seeq8005.c95
-rw-r--r--drivers/net/setup.c8
-rw-r--r--drivers/net/sgiseeq.c5
-rw-r--r--drivers/net/sis900.c50
-rw-r--r--drivers/net/sk98lin/skge.c79
-rw-r--r--drivers/net/sk_g16.c39
-rw-r--r--drivers/net/sk_mca.c1428
-rw-r--r--drivers/net/skeleton.c5
-rw-r--r--drivers/net/skfp/.cvsignore10
-rw-r--r--drivers/net/skfp/Makefile39
-rw-r--r--drivers/net/skfp/can.c83
-rw-r--r--drivers/net/skfp/cfm.c642
-rw-r--r--drivers/net/skfp/drvfbi.c1612
-rw-r--r--drivers/net/skfp/ecm.c547
-rw-r--r--drivers/net/skfp/ess.c732
-rw-r--r--drivers/net/skfp/fplustm.c1645
-rw-r--r--drivers/net/skfp/h/cmtdef.h801
-rw-r--r--drivers/net/skfp/h/fddi.h69
-rw-r--r--drivers/net/skfp/h/fddimib.h349
-rw-r--r--drivers/net/skfp/h/fplustm.h274
-rw-r--r--drivers/net/skfp/h/hwmtm.h424
-rw-r--r--drivers/net/skfp/h/lnkstat.h84
-rw-r--r--drivers/net/skfp/h/mbuf.h54
-rw-r--r--drivers/net/skfp/h/osdef1st.h118
-rw-r--r--drivers/net/skfp/h/sba.h142
-rw-r--r--drivers/net/skfp/h/sba_def.h76
-rw-r--r--drivers/net/skfp/h/skfbi.h1920
-rw-r--r--drivers/net/skfp/h/skfbiinc.h123
-rw-r--r--drivers/net/skfp/h/smc.h471
-rw-r--r--drivers/net/skfp/h/smt.h882
-rw-r--r--drivers/net/skfp/h/smt_p.h326
-rw-r--r--drivers/net/skfp/h/smtstate.h100
-rw-r--r--drivers/net/skfp/h/supern_2.h1059
-rw-r--r--drivers/net/skfp/h/targethw.h173
-rw-r--r--drivers/net/skfp/h/targetos.h163
-rw-r--r--drivers/net/skfp/h/types.h48
-rw-r--r--drivers/net/skfp/hwmtm.c2261
-rw-r--r--drivers/net/skfp/hwt.c314
-rw-r--r--drivers/net/skfp/lnkstat.c209
-rw-r--r--drivers/net/skfp/pcmplc.c2094
-rw-r--r--drivers/net/skfp/pmf.c1701
-rw-r--r--drivers/net/skfp/queue.c185
-rw-r--r--drivers/net/skfp/rmt.c674
-rw-r--r--drivers/net/skfp/skfddi.c2495
-rw-r--r--drivers/net/skfp/smt.c2225
-rw-r--r--drivers/net/skfp/smtdef.c371
-rw-r--r--drivers/net/skfp/smtinit.c126
-rw-r--r--drivers/net/skfp/smtparse.c475
-rw-r--r--drivers/net/skfp/smttimer.c173
-rw-r--r--drivers/net/skfp/srf.c441
-rw-r--r--drivers/net/slip.c12
-rw-r--r--drivers/net/smc-mca.c5
-rw-r--r--drivers/net/smc-ultra.c3
-rw-r--r--drivers/net/smc-ultra32.c5
-rw-r--r--drivers/net/smc9194.c241
-rw-r--r--drivers/net/starfire.c22
-rw-r--r--drivers/net/strip.c28
-rw-r--r--drivers/net/sunbmac.c30
-rw-r--r--drivers/net/sunhme.c108
-rw-r--r--drivers/net/sunhme.h8
-rw-r--r--drivers/net/sunlance.c37
-rw-r--r--drivers/net/sunqe.c4
-rw-r--r--drivers/net/tlan.c43
-rw-r--r--drivers/net/tokenring/ibmtr.c77
-rw-r--r--drivers/net/tokenring/olympic.c37
-rw-r--r--drivers/net/tokenring/smctr.c65
-rw-r--r--drivers/net/tokenring/tms380tr.c73
-rw-r--r--drivers/net/tulip.c3205
-rw-r--r--drivers/net/via-rhine.c8
-rw-r--r--drivers/net/wan/cosa.c19
-rw-r--r--drivers/net/wan/cycx_x25.c62
-rw-r--r--drivers/net/wan/dlci.c67
-rw-r--r--drivers/net/wan/hostess_sv11.c7
-rw-r--r--drivers/net/wan/lapbether.c15
-rw-r--r--drivers/net/wan/sbni.c73
-rw-r--r--drivers/net/wan/sbni.h2
-rw-r--r--drivers/net/wan/sdla.c163
-rw-r--r--drivers/net/wan/sdla_chdlc.c3
-rw-r--r--drivers/net/wan/sdla_fr.c137
-rw-r--r--drivers/net/wan/sdla_ppp.c3
-rw-r--r--drivers/net/wan/sdla_x25.c62
-rw-r--r--drivers/net/wan/sealevel.c7
-rw-r--r--drivers/net/wan/x25_asy.c63
-rw-r--r--drivers/net/wan/z85230.c389
-rw-r--r--drivers/net/wan/z85230.h6
-rw-r--r--drivers/net/wavelan.c6044
-rw-r--r--drivers/net/yellowfin.c845
-rw-r--r--drivers/net/znet.c90
185 files changed, 45682 insertions, 16378 deletions
diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c
index 1bd65d54f..d66393649 100644
--- a/drivers/net/3c505.c
+++ b/drivers/net/3c505.c
@@ -101,6 +101,7 @@
#include <linux/in.h>
#include <linux/malloc.h>
#include <linux/ioport.h>
+#include <linux/spinlock.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/dma.h>
@@ -183,23 +184,9 @@ static const int addr_list[] __initdata = {0x300, 0x280, 0x310, 0};
/* Dma Memory related stuff */
-/* Pure 2^n version of get_order */
-static inline int __get_order(unsigned long size)
-{
- int order;
-
- size = (size - 1) >> (PAGE_SHIFT - 1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
static unsigned long dma_mem_alloc(int size)
{
- int order = __get_order(size);
+ int order = get_order(size);
return __get_dma_pages(GFP_KERNEL, order);
}
@@ -374,7 +361,8 @@ static inline unsigned int send_pcb_fast(unsigned int base_addr, unsigned char b
static inline void prime_rx(struct net_device *dev)
{
elp_device *adapter = dev->priv;
- while (adapter->rx_active < ELP_RX_PCBS && dev->start) {
+ while (adapter->rx_active < ELP_RX_PCBS &&
+ netif_running(dev->state)) {
if (!start_receive(dev, &adapter->itx_pcb))
break;
}
@@ -672,23 +660,10 @@ static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
elp_device *adapter;
int timeout;
- if (irq < 0 || irq > 15) {
- printk("elp_interrupt(): illegal IRQ number found in interrupt routine (%i)\n", irq);
- return;
- }
dev = dev_id;
-
- if (dev == NULL) {
- printk("elp_interrupt(): irq %d for unknown device.\n", irq);
- return;
- }
adapter = (elp_device *) dev->priv;
-
- if (dev->interrupt) {
- printk("%s: re-entering the interrupt handler!\n", dev->name);
- return;
- }
- dev->interrupt = 1;
+
+ spin_lock(&adapter->lock);
do {
/*
@@ -702,20 +677,19 @@ static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
printk("%s: %s DMA complete, status %02x\n", dev->name, adapter->current_dma.direction ? "tx" : "rx", inb_status(dev->base_addr));
}
- outb_control(adapter->hcr_val & ~(DMAE | TCEN | DIR),
- dev);
+ outb_control(adapter->hcr_val & ~(DMAE | TCEN | DIR), dev);
if (adapter->current_dma.direction) {
- dev_kfree_skb(adapter->current_dma.skb);
+ dev_kfree_skb_irq(adapter->current_dma.skb);
} else {
struct sk_buff *skb = adapter->current_dma.skb;
if (skb) {
- if (adapter->current_dma.target) {
- /* have already done the skb_put() */
- memcpy(adapter->current_dma.target, adapter->dma_buffer, adapter->current_dma.length);
- }
- skb->protocol = eth_type_trans(skb,dev);
- adapter->stats.rx_bytes += skb->len;
- netif_rx(skb);
+ if (adapter->current_dma.target) {
+ /* have already done the skb_put() */
+ memcpy(adapter->current_dma.target, adapter->dma_buffer, adapter->current_dma.length);
+ }
+ skb->protocol = eth_type_trans(skb,dev);
+ adapter->stats.rx_bytes += skb->len;
+ netif_rx(skb);
}
}
adapter->dmaing = 0;
@@ -733,15 +707,14 @@ static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
check_3c505_dma(dev);
}
- sti();
-
/*
* receive a PCB from the adapter
*/
timeout = jiffies + 3*HZ/100;
while ((inb_status(dev->base_addr) & ACRF) != 0 && time_before(jiffies, timeout)) {
if (receive_pcb(dev, &adapter->irx_pcb)) {
- switch (adapter->irx_pcb.command) {
+ switch (adapter->irx_pcb.command)
+ {
case 0:
break;
/*
@@ -750,19 +723,15 @@ static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
case 0xff:
case CMD_RECEIVE_PACKET_COMPLETE:
/* if the device isn't open, don't pass packets up the stack */
- if (dev->start == 0)
+ if (!netif_running(dev))
break;
- cli();
len = adapter->irx_pcb.data.rcv_resp.pkt_len;
dlen = adapter->irx_pcb.data.rcv_resp.buf_len;
if (adapter->irx_pcb.data.rcv_resp.timeout != 0) {
- printk("%s: interrupt - packet not received correctly\n", dev->name);
- sti();
+ printk(KERN_ERR "%s: interrupt - packet not received correctly\n", dev->name);
} else {
if (elp_debug >= 3) {
- sti();
printk("%s: interrupt - packet received of length %i (%i)\n", dev->name, len, dlen);
- cli();
}
if (adapter->irx_pcb.command == 0xff) {
if (elp_debug >= 2)
@@ -772,7 +741,6 @@ static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
} else {
receive_packet(dev, dlen);
}
- sti();
if (elp_debug >= 3)
printk("%s: packet received\n", dev->name);
}
@@ -839,7 +807,7 @@ static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
case CMD_TRANSMIT_PACKET_COMPLETE:
if (elp_debug >= 3)
printk("%s: interrupt - packet sent\n", dev->name);
- if (dev->start == 0)
+ if (!netif_running(dev))
break;
switch (adapter->irx_pcb.data.xmit_resp.c_stat) {
case 0xffff:
@@ -851,8 +819,7 @@ static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
printk(KERN_INFO "%s: transmit timed out, FIFO underrun\n", dev->name);
break;
}
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
break;
/*
@@ -875,7 +842,7 @@ static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
/*
* indicate no longer in interrupt routine
*/
- dev->interrupt = 0;
+ spin_unlock(&adapter->lock);
}
@@ -913,16 +880,6 @@ static int elp_open(struct net_device *dev)
adapter_reset(dev);
/*
- * interrupt routine not entered
- */
- dev->interrupt = 0;
-
- /*
- * transmitter not busy
- */
- dev->tbusy = 0;
-
- /*
* no receive PCBs active
*/
adapter->rx_active = 0;
@@ -931,6 +888,8 @@ static int elp_open(struct net_device *dev)
adapter->send_pcb_semaphore = 0;
adapter->rx_backlog.in = 0;
adapter->rx_backlog.out = 0;
+
+ spin_lock_init(&adapter->lock);
/*
* install our interrupt service routine
@@ -1008,8 +967,8 @@ static int elp_open(struct net_device *dev)
/*
* device is now officially open!
*/
- dev->start = 1;
+ netif_wake_queue(dev);
MOD_INC_USE_COUNT;
return 0; /* Always succeed */
@@ -1085,6 +1044,25 @@ static int send_packet(struct net_device *dev, struct sk_buff *skb)
return TRUE;
}
+/*
+ * The upper layer thinks we timed out
+ */
+
+static void elp_timeout(struct net_device *dev)
+{
+ unsigned long flags;
+ elp_device *adapter = dev->priv;
+ int stat;
+
+ stat = inb_status(dev->base_addr);
+ printk(KERN_WARNING "%s: transmit timed out, lost %s?\n", dev->name, (stat & ACRF) ? "interrupt" : "command");
+ if (elp_debug >= 1)
+ printk("%s: status %#02x\n", dev->name, stat);
+ dev->trans_start = jiffies;
+ adapter->stats.tx_dropped++;
+ netif_wake_queue(dev);
+}
+
/******************************************************
*
* start the transmitter
@@ -1094,40 +1072,17 @@ static int send_packet(struct net_device *dev, struct sk_buff *skb)
static int elp_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- if (dev->interrupt) {
- printk("%s: start_xmit aborted (in irq)\n", dev->name);
- return 1;
- }
-
+ unsigned long flags;
+ elp_device *adapter = dev->priv;
+
+ spin_lock_irqsave(&adapter->lock, flags);
check_3c505_dma(dev);
- /*
- * if the transmitter is still busy, we have a transmit timeout...
- */
- if (dev->tbusy) {
- elp_device *adapter = dev->priv;
- int tickssofar = jiffies - dev->trans_start;
- int stat;
-
- if (tickssofar < 1000)
- return 1;
-
- stat = inb_status(dev->base_addr);
- printk("%s: transmit timed out, lost %s?\n", dev->name, (stat & ACRF) ? "interrupt" : "command");
- if (elp_debug >= 1)
- printk("%s: status %#02x\n", dev->name, stat);
- dev->trans_start = jiffies;
- dev->tbusy = 0;
- adapter->stats.tx_dropped++;
- }
-
if (elp_debug >= 3)
printk("%s: request to send packet of length %d\n", dev->name, (int) skb->len);
- if (test_and_set_bit(0, (void *) &dev->tbusy)) {
- printk("%s: transmitter access conflict\n", dev->name);
- return 1;
- }
+ netif_stop_queue(dev);
+
/*
* send the packet at skb->data for skb->len
*/
@@ -1135,7 +1090,7 @@ static int elp_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (elp_debug >= 2) {
printk("%s: failed to transmit packet\n", dev->name);
}
- dev->tbusy = 0;
+ spin_unlock_irqrestore(&adapter->lock, flags);
return 1;
}
if (elp_debug >= 3)
@@ -1147,7 +1102,8 @@ static int elp_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
prime_rx(dev);
-
+ spin_unlock_irqrestore(&adapter->lock, flags);
+ netif_start_queue(dev);
return 0;
}
@@ -1166,7 +1122,7 @@ static struct net_device_stats *elp_get_stats(struct net_device *dev)
/* If the device is closed, just return the latest stats we have,
- we cannot ask from the adapter without interrupts */
- if (!dev->start)
+ if (!netif_running(dev))
return &adapter->stats;
/* send a get statistics command to the board */
@@ -1203,6 +1159,8 @@ static int elp_close(struct net_device *dev)
if (elp_debug >= 3)
printk("%s: request to close device\n", dev->name);
+ netif_stop_queue(dev);
+
/* Someone may request the device statistic information even when
* the interface is closed. The following will update the statistics
* structure in the driver, so we'll be able to give current statistics.
@@ -1215,22 +1173,12 @@ static int elp_close(struct net_device *dev)
outb_control(0, dev);
/*
- * flag transmitter as busy (i.e. not available)
- */
- dev->tbusy = 1;
-
- /*
- * indicate device is closed
- */
- dev->start = 0;
-
- /*
* release the IRQ
*/
free_irq(dev->irq, dev);
free_dma(dev->dma);
- free_pages((unsigned long) adapter->dma_buffer, __get_order(DMA_BUFFER_SIZE));
+ free_pages((unsigned long) adapter->dma_buffer, get_order(DMA_BUFFER_SIZE));
MOD_DEC_USE_COUNT;
@@ -1252,10 +1200,13 @@ static void elp_set_mc_list(struct net_device *dev)
elp_device *adapter = (elp_device *) dev->priv;
struct dev_mc_list *dmi = dev->mc_list;
int i;
+ unsigned long flags;
if (elp_debug >= 3)
printk("%s: request to set multicast list\n", dev->name);
+ spin_lock_irqsave(&adapter->lock, flags);
+
if (!(dev->flags & (IFF_PROMISC | IFF_ALLMULTI))) {
/* send a "load multicast list" command to the board, max 10 addrs/cmd */
/* if num_addrs==0 the list will be cleared */
@@ -1291,9 +1242,13 @@ static void elp_set_mc_list(struct net_device *dev)
adapter->tx_pcb.length = 2;
adapter->got[CMD_CONFIGURE_82586] = 0;
if (!send_pcb(dev, &adapter->tx_pcb))
+ {
+ spin_unlock_irqrestore(&lp->lock, flags);
printk("%s: couldn't send 82586 configure command\n", dev->name);
+ }
else {
int timeout = jiffies + TIMEOUT;
+ spin_unlock_irqrestore(&lp->lock, flags);
while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout));
if (time_after_eq(jiffies, timeout))
TIMEOUT_MSG(__LINE__);
@@ -1313,10 +1268,12 @@ static inline void elp_init(struct net_device *dev)
/*
* set ptrs to various functions
*/
- dev->open = elp_open; /* local */
- dev->stop = elp_close; /* local */
- dev->get_stats = elp_get_stats; /* local */
- dev->hard_start_xmit = elp_start_xmit; /* local */
+ dev->open = elp_open; /* local */
+ dev->stop = elp_close; /* local */
+ dev->get_stats = elp_get_stats; /* local */
+ dev->hard_start_xmit = elp_start_xmit; /* local */
+ dev->tx_timeout = elp_timeout; /* local */
+ dev->watchdog_timeo = 10*HZ;
dev->set_multicast_list = elp_set_mc_list; /* local */
/* Setup the generic properties */
diff --git a/drivers/net/3c505.h b/drivers/net/3c505.h
index 41993d4ec..1cbf41fae 100644
--- a/drivers/net/3c505.h
+++ b/drivers/net/3c505.h
@@ -289,4 +289,5 @@ typedef struct {
unsigned int rx_active; /* number of receive PCBs */
volatile unsigned char hcr_val; /* what we think the HCR contains */
+ spinlock_t lock; /* Interrupt v tx lock */
} elp_device;
diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c
index 2a6ddac7a..faecb72ad 100644
--- a/drivers/net/3c507.c
+++ b/drivers/net/3c507.c
@@ -199,6 +199,8 @@ struct net_local {
#define RX_BUF_SIZE (1518+14+18) /* packet+header+RBD */
#define RX_BUF_END (dev->mem_end - dev->mem_start)
+#define TX_TIMEOUT 5
+
/*
That's it: only 86 bytes to set up the beast, including every extra
command available. The 170 byte buffer at DUMP_DATA is shared between the
@@ -287,6 +289,7 @@ static void el16_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void el16_rx(struct net_device *dev);
static int el16_close(struct net_device *dev);
static struct net_device_stats *el16_get_stats(struct net_device *dev);
+static void el16_tx_timeout (struct net_device *dev);
static void hardware_send_packet(struct net_device *dev, void *buf, short length);
static void init_82586_mem(struct net_device *dev);
@@ -325,7 +328,7 @@ int __init el16_probe(struct net_device *dev)
return ENODEV;
}
-int __init el16_probe1(struct net_device *dev, int ioaddr)
+static int __init el16_probe1(struct net_device *dev, int ioaddr)
{
static unsigned char init_ID_done = 0, version_printed = 0;
int i, irq, irqval;
@@ -423,6 +426,8 @@ int __init el16_probe1(struct net_device *dev, int ioaddr)
dev->stop = el16_close;
dev->hard_start_xmit = el16_send_packet;
dev->get_stats = el16_get_stats;
+ dev->tx_timeout = el16_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
ether_setup(dev); /* Generic ethernet behaviour */
@@ -443,62 +448,59 @@ static int el16_open(struct net_device *dev)
return 0;
}
-static int el16_send_packet(struct sk_buff *skb, struct net_device *dev)
+
+static void el16_tx_timeout (struct net_device *dev)
{
- struct net_local *lp = (struct net_local *)dev->priv;
+ struct net_local *lp = (struct net_local *) dev->priv;
int ioaddr = dev->base_addr;
unsigned long shmem = dev->mem_start;
- unsigned long flags;
-#if 0 /* LINK_STATE_XOFF is never set when we reach here */
- if (test_bit(LINK_STATE_XOFF, &dev->flags))
- {
- /* If we get here, some higher level has decided we are broken.
- There should really be a "kick me" function call instead. */
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 5)
- return 1;
+ if (net_debug > 1)
+ printk ("%s: transmit timed out, %s? ", dev->name,
+ isa_readw (shmem + iSCB_STATUS) & 0x8000 ? "IRQ conflict" :
+ "network cable problem");
+ /* Try to restart the adaptor. */
+ if (lp->last_restart == lp->stats.tx_packets) {
if (net_debug > 1)
- printk("%s: transmit timed out, %s? ", dev->name,
- isa_readw(shmem+iSCB_STATUS) & 0x8000 ? "IRQ conflict" :
- "network cable problem");
- /* Try to restart the adaptor. */
- if (lp->last_restart == lp->stats.tx_packets) {
- if (net_debug > 1) printk("Resetting board.\n");
- /* Completely reset the adaptor. */
- init_82586_mem(dev);
- } else {
- /* Issue the channel attention signal and hope it "gets better". */
- if (net_debug > 1) printk("Kicking board.\n");
- isa_writew(0xf000|CUC_START|RX_START,shmem+iSCB_CMD);
- outb(0, ioaddr + SIGNAL_CA); /* Issue channel-attn. */
- lp->last_restart = lp->stats.tx_packets;
- }
- netif_start_queue(dev);
- dev->trans_start = jiffies;
+ printk ("Resetting board.\n");
+ /* Completely reset the adaptor. */
+ init_82586_mem (dev);
+ } else {
+ /* Issue the channel attention signal and hope it "gets better". */
+ if (net_debug > 1)
+ printk ("Kicking board.\n");
+ isa_writew (0xf000 | CUC_START | RX_START, shmem + iSCB_CMD);
+ outb (0, ioaddr + SIGNAL_CA); /* Issue channel-attn. */
+ lp->last_restart = lp->stats.tx_packets;
}
-#endif
+ dev->trans_start = jiffies;
+ netif_wake_queue (dev);
+}
- {
- short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned char *buf = skb->data;
- spin_lock_irqsave(&lp->lock, flags);
+static int el16_send_packet (struct sk_buff *skb, struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *) dev->priv;
+ int ioaddr = dev->base_addr;
+ unsigned long flags;
+ short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+ unsigned char *buf = skb->data;
- lp->stats.tx_bytes+=length;
- /* Disable the 82586's input to the interrupt line. */
- outb(0x80, ioaddr + MISC_CTRL);
+ netif_stop_queue (dev);
- hardware_send_packet(dev, buf, length);
+ spin_lock_irqsave (&lp->lock, flags);
- dev->trans_start = jiffies;
- /* Enable the 82586 interrupt input. */
- outb(0x84, ioaddr + MISC_CTRL);
+ lp->stats.tx_bytes += length;
+ /* Disable the 82586's input to the interrupt line. */
+ outb (0x80, ioaddr + MISC_CTRL);
- spin_unlock_irqrestore(&lp->lock, flags);
+ hardware_send_packet (dev, buf, length);
- netif_stop_queue(dev);
- }
+ dev->trans_start = jiffies;
+ /* Enable the 82586 interrupt input. */
+ outb (0x84, ioaddr + MISC_CTRL);
+
+ spin_unlock_irqrestore (&lp->lock, flags);
dev_kfree_skb (skb);
@@ -574,8 +576,7 @@ static void el16_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* Acknowledge the interrupt sources. */
ack_cmd = status & 0xf000;
- if ((status & 0x0700) != 0x0200 &&
- (test_bit(LINK_STATE_START, &dev->state))) {
+ if ((status & 0x0700) != 0x0200 && netif_running(dev)) {
if (net_debug)
printk("%s: Command unit stopped, status %04x, restarting.\n",
dev->name, status);
@@ -585,9 +586,7 @@ static void el16_interrupt(int irq, void *dev_id, struct pt_regs *regs)
ack_cmd |= CUC_RESUME;
}
- if ((status & 0x0070) != 0x0040 &&
- (test_bit(LINK_STATE_START, &dev->state)))
- {
+ if ((status & 0x0070) != 0x0040 && netif_running(dev)) {
static void init_rx_bufs(struct net_device *);
/* The Rx unit is not ready, it must be hung. Restart the receiver by
initializing the rx buffers, and issuing an Rx start command. */
@@ -788,7 +787,7 @@ static void hardware_send_packet(struct net_device *dev, void *buf, short length
}
if (lp->tx_head != lp->tx_reap)
- netif_start_queue(dev);
+ netif_wake_queue(dev);
}
static void el16_rx(struct net_device *dev)
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index 07038b4ba..06a616592 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -412,6 +412,9 @@ no_pnp:
}
}
+ if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509"))
+ return -EBUSY;
+
/* Set the adaptor tag so that the next card can be found. */
outb(0xd0 + ++current_tag, id_port);
@@ -419,22 +422,26 @@ no_pnp:
outb((ioaddr >> 4) | 0xe0, id_port);
EL3WINDOW(0);
- if (inw(ioaddr) != 0x6d50)
+ if (inw(ioaddr) != 0x6d50) {
+ release_region(ioaddr, EL3_IO_EXTENT);
return -ENODEV;
+ }
/* Free the interrupt so that some other card can use it. */
outw(0x0f00, ioaddr + WN0_IRQ);
found:
if (dev == NULL) {
dev = init_etherdev(dev, sizeof(struct el3_private));
+ if (dev == NULL) {
+ release_region(ioaddr, EL3_IO_EXTENT);
+ return -ENOMEM;
+ }
}
memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
dev->base_addr = ioaddr;
dev->irq = irq;
dev->if_port = (dev->mem_start & 0x1f) ? dev->mem_start & 3 : if_port;
- request_region(dev->base_addr, EL3_IO_EXTENT, "3c509");
-
{
const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
printk("%s: 3c509 at %#3.3lx, %s port, address ",
@@ -599,7 +606,7 @@ el3_tx_timeout (struct net_device *dev)
/* Issue TX_RESET and TX_START commands. */
outw(TxReset, ioaddr + EL3_CMD);
outw(TxEnable, ioaddr + EL3_CMD);
- netif_start_queue(dev);
+ netif_wake_queue(dev);
}
@@ -610,6 +617,8 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
int ioaddr = dev->base_addr;
unsigned long flags;
+ netif_stop_queue (dev);
+
lp->stats.tx_bytes += skb->len;
if (el3_debug > 4) {
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
index 5012dae6e..36f15f0cb 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/3c515.c
@@ -10,17 +10,22 @@
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+
+ Cleaned up for 2.3.x/softnet by Jeff Garzik and Alan Cox.
*/
-static char *version = "3c515.c:v0.99 4/7/98 becker@cesdis.gsfc.nasa.gov\n";
+static char *version = "3c515.c:v0.99-sn 2000/02/12 becker@cesdis.gsfc.nasa.gov and others\n";
+
#define CORKSCREW 1
/* "Knobs" that adjust features and parameters. */
/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
Setting to > 1512 effectively disables this feature. */
static const int rx_copybreak = 200;
+
/* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
static const int mtu = 1500;
+
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
static int max_interrupt_work = 20;
@@ -37,7 +42,7 @@ static int max_interrupt_work = 20;
/* Keep the ring sizes a power of two for efficiency. */
#define TX_RING_SIZE 16
#define RX_RING_SIZE 16
-#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
+#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */
#include <linux/module.h>
#include <linux/version.h>
@@ -65,15 +70,10 @@ static int max_interrupt_work = 20;
/* Kernel version compatibility functions. */
#define RUN_AT(x) (jiffies + (x))
-#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2)
-#define FREE_IRQ(irqnum, dev) free_irq(irqnum, dev)
#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance)
#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
-#if (LINUX_VERSION_CODE < 0x20123)
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#elif defined(MODULE)
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_DESCRIPTION("3Com 3c515 Corkscrew driver");
MODULE_PARM(debug, "i");
@@ -81,7 +81,6 @@ MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
MODULE_PARM(rx_copybreak, "i");
MODULE_PARM(max_interrupt_work, "i");
-#endif
/* "Knobs" for adjusting internal parameters. */
/* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */
@@ -102,15 +101,10 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0;
*/
#define CORKSCREW_TOTAL_SIZE 0x20
-#ifdef HAVE_DEVLIST
-struct netdev_entry tc515_drv =
-{"3c515", tc515_probe, CORKSCREW_TOTAL_SIZE, NULL};
-#endif
-
#ifdef DRIVER_DEBUG
-int vortex_debug = DRIVER_DEBUG;
+int corkscrew_debug = DRIVER_DEBUG;
#else
-int vortex_debug = 1;
+int corkscrew_debug = 1;
#endif
#define CORKSCREW_ID 10
@@ -149,8 +143,8 @@ correctly-sized skbuff.
IIIC. Synchronization
The driver runs as two independent, single-threaded flows of control. One
-is the send-packet routine, which enforces single-threaded use by the
-dev->tbusy flag. The other thread is the interrupt handler, which is single
+is the send-packet routine, which enforces single-threaded use by the netif
+layer. The other thread is the interrupt handler, which is single
threaded by the hardware and other software.
IV. Notes
@@ -184,87 +178,98 @@ of 1.5K, but the changes to support 4.5K are minimal.
can handle FDDI length frames (~4500 octets) and now parameters count
32-bit 'Dwords' rather than octets. */
-enum vortex_cmd {
- TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
- RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11,
- UpStall = 6<<11, UpUnstall = (6<<11)+1,
- DownStall = (6<<11)+2, DownUnstall = (6<<11)+3,
- RxDiscard = 8<<11, TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
- FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
- SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
- SetTxThreshold = 18<<11, SetTxStart = 19<<11,
- StartDMAUp = 20<<11, StartDMADown = (20<<11)+1, StatsEnable = 21<<11,
- StatsDisable = 22<<11, StopCoax = 23<<11,};
+enum corkscrew_cmd {
+ TotalReset = 0 << 11, SelectWindow = 1 << 11, StartCoax = 2 << 11,
+ RxDisable = 3 << 11, RxEnable = 4 << 11, RxReset = 5 << 11,
+ UpStall = 6 << 11, UpUnstall = (6 << 11) + 1,
+ DownStall = (6 << 11) + 2, DownUnstall = (6 << 11) + 3,
+ RxDiscard = 8 << 11, TxEnable = 9 << 11, TxDisable =
+ 10 << 11, TxReset = 11 << 11,
+ FakeIntr = 12 << 11, AckIntr = 13 << 11, SetIntrEnb = 14 << 11,
+ SetStatusEnb = 15 << 11, SetRxFilter = 16 << 11, SetRxThreshold =
+ 17 << 11,
+ SetTxThreshold = 18 << 11, SetTxStart = 19 << 11,
+ StartDMAUp = 20 << 11, StartDMADown = (20 << 11) + 1, StatsEnable =
+ 21 << 11,
+ StatsDisable = 22 << 11, StopCoax = 23 << 11,
+};
/* The SetRxFilter command accepts the following classes: */
enum RxFilter {
- RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 };
+ RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8
+};
/* Bits in the general status register. */
-enum vortex_status {
+enum corkscrew_status {
IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
IntReq = 0x0040, StatsFull = 0x0080,
- DMADone = 1<<8, DownComplete = 1<<9, UpComplete = 1<<10,
- DMAInProgress = 1<<11, /* DMA controller is still busy.*/
- CmdInProgress = 1<<12, /* EL3_CMD is still busy.*/
+ DMADone = 1 << 8, DownComplete = 1 << 9, UpComplete = 1 << 10,
+ DMAInProgress = 1 << 11, /* DMA controller is still busy. */
+ CmdInProgress = 1 << 12, /* EL3_CMD is still busy. */
};
/* Register window 1 offsets, the window used in normal operation.
On the Corkscrew this window is always mapped at offsets 0x10-0x1f. */
enum Window1 {
- TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14,
- RxStatus = 0x18, Timer=0x1A, TxStatus = 0x1B,
- TxFree = 0x1C, /* Remaining free bytes in Tx buffer. */
+ TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14,
+ RxStatus = 0x18, Timer = 0x1A, TxStatus = 0x1B,
+ TxFree = 0x1C, /* Remaining free bytes in Tx buffer. */
};
enum Window0 {
- Wn0IRQ = 0x08,
+ Wn0IRQ = 0x08,
#if defined(CORKSCREW)
- Wn0EepromCmd = 0x200A, /* Corkscrew EEPROM command register. */
- Wn0EepromData = 0x200C, /* Corkscrew EEPROM results register. */
+ Wn0EepromCmd = 0x200A, /* Corkscrew EEPROM command register. */
+ Wn0EepromData = 0x200C, /* Corkscrew EEPROM results register. */
#else
- Wn0EepromCmd = 10, /* Window 0: EEPROM command register. */
- Wn0EepromData = 12, /* Window 0: EEPROM results register. */
+ Wn0EepromCmd = 10, /* Window 0: EEPROM command register. */
+ Wn0EepromData = 12, /* Window 0: EEPROM results register. */
#endif
};
enum Win0_EEPROM_bits {
EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0,
- EEPROM_EWENB = 0x30, /* Enable erasing/writing for 10 msec. */
- EEPROM_EWDIS = 0x00, /* Disable EWENB before 10 msec timeout. */
+ EEPROM_EWENB = 0x30, /* Enable erasing/writing for 10 msec. */
+ EEPROM_EWDIS = 0x00, /* Disable EWENB before 10 msec timeout. */
};
+
/* EEPROM locations. */
enum eeprom_offset {
- PhysAddr01=0, PhysAddr23=1, PhysAddr45=2, ModelID=3,
- EtherLink3ID=7, };
+ PhysAddr01 = 0, PhysAddr23 = 1, PhysAddr45 = 2, ModelID = 3,
+ EtherLink3ID = 7,
+};
enum Window3 { /* Window 3: MAC/config bits. */
- Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8,
+ Wn3_Config = 0, Wn3_MAC_Ctrl = 6, Wn3_Options = 8,
};
union wn3_config {
int i;
struct w3_config_fields {
- unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2;
+ unsigned int ram_size:3, ram_width:1, ram_speed:2,
+ rom_size:2;
int pad8:8;
- unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1, autoselect:1;
+ unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1,
+ autoselect:1;
int pad24:7;
} u;
};
enum Window4 {
- Wn4_NetDiag = 6, Wn4_Media = 10, /* Window 4: Xcvr/media bits. */
+ Wn4_NetDiag = 6, Wn4_Media = 10, /* Window 4: Xcvr/media bits. */
};
enum Win4_Media_bits {
- Media_SQE = 0x0008, /* Enable SQE error counting for AUI. */
+ Media_SQE = 0x0008, /* Enable SQE error counting for AUI. */
Media_10TP = 0x00C0, /* Enable link beat and jabber for 10baseT. */
- Media_Lnk = 0x0080, /* Enable just link beat for 100TX/100FX. */
+ Media_Lnk = 0x0080, /* Enable just link beat for 100TX/100FX. */
Media_LnkBeat = 0x0800,
};
-enum Window7 { /* Window 7: Bus Master control. */
+enum Window7 { /* Window 7: Bus Master control. */
Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
};
+
/* Boomerang-style bus master control registers. Note ISA aliases! */
enum MasterCtrl {
- PktStatus = 0x400, DownListPtr = 0x404, FragAddr = 0x408, FragLen = 0x40c,
+ PktStatus = 0x400, DownListPtr = 0x404, FragAddr = 0x408, FragLen =
+ 0x40c,
TxFreeThreshold = 0x40f, UpPktStatus = 0x410, UpListPtr = 0x418,
};
@@ -277,9 +282,10 @@ struct boom_rx_desc {
u32 addr;
s32 length;
};
+
/* Values for the Rx status entry. */
enum rx_desc_status {
- RxDComplete=0x00008000, RxDError=0x4000,
+ RxDComplete = 0x00008000, RxDError = 0x4000,
/* See boomerang_rx() for actual error bits */
};
@@ -290,111 +296,112 @@ struct boom_tx_desc {
s32 length;
};
-struct vortex_private {
- char devname[8]; /* "ethN" string, also for kernel debug. */
+struct corkscrew_private {
+ char devname[8]; /* "ethN" string, also for kernel debug. */
const char *product_name;
struct net_device *next_module;
/* The Rx and Tx rings are here to keep them quad-word-aligned. */
struct boom_rx_desc rx_ring[RX_RING_SIZE];
struct boom_tx_desc tx_ring[TX_RING_SIZE];
/* The addresses of transmit- and receive-in-place skbuffs. */
- struct sk_buff* rx_skbuff[RX_RING_SIZE];
- struct sk_buff* tx_skbuff[TX_RING_SIZE];
- unsigned int cur_rx, cur_tx; /* The next free ring entry */
- unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
+ struct sk_buff *rx_skbuff[RX_RING_SIZE];
+ struct sk_buff *tx_skbuff[TX_RING_SIZE];
+ unsigned int cur_rx, cur_tx; /* The next free ring entry */
+ unsigned int dirty_rx, dirty_tx;/* The ring entries to be free()ed. */
struct enet_statistics stats;
- struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */
+ struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */
struct timer_list timer; /* Media selection timer. */
- int capabilities; /* Adapter capabilities word. */
- int options; /* User-settable misc. driver options. */
+ int capabilities ; /* Adapter capabilities word. */
+ int options; /* User-settable misc. driver options. */
int last_rx_packets; /* For media autoselection. */
unsigned int available_media:8, /* From Wn3_Options */
- media_override:3, /* Passed-in media type. */
- default_media:3, /* Read from the EEPROM. */
- full_duplex:1, autoselect:1,
- bus_master:1, /* Vortex can only do a fragment bus-m. */
- full_bus_master_tx:1, full_bus_master_rx:1, /* Boomerang */
- tx_full:1;
+ media_override:3, /* Passed-in media type. */
+ default_media:3, /* Read from the EEPROM. */
+ full_duplex:1, autoselect:1, bus_master:1, /* Vortex can only do a fragment bus-m. */
+ full_bus_master_tx:1, full_bus_master_rx:1, /* Boomerang */
+ tx_full:1;
};
/* The action to take with a media selection timer tick.
Note that we deviate from the 3Com order by checking 10base2 before AUI.
*/
enum xcvr_types {
- XCVR_10baseT=0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx,
- XCVR_100baseFx, XCVR_MII=6, XCVR_Default=8,
+ XCVR_10baseT =
+ 0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx,
+ XCVR_100baseFx, XCVR_MII = 6, XCVR_Default = 8,
};
static struct media_table {
- char *name;
- unsigned int media_bits:16, /* Bits to set in Wn4_Media register. */
- mask:8, /* The transceiver-present bit in Wn3_Config.*/
- next:8; /* The media type to try next. */
- short wait; /* Time before we check media status. */
-} media_tbl[] = {
- { "10baseT", Media_10TP,0x08, XCVR_10base2, (14*HZ)/10},
- { "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1*HZ)/10},
- { "undefined", 0, 0x80, XCVR_10baseT, 10000},
- { "10base2", 0, 0x10, XCVR_AUI, (1*HZ)/10},
- { "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14*HZ)/10},
- { "100baseFX", Media_Lnk, 0x04, XCVR_MII, (14*HZ)/10},
- { "MII", 0, 0x40, XCVR_10baseT, 3*HZ },
- { "undefined", 0, 0x01, XCVR_10baseT, 10000},
- { "Default", 0, 0xFF, XCVR_10baseT, 10000},
+ char *name;
+ unsigned int media_bits:16, /* Bits to set in Wn4_Media register. */
+ mask:8, /* The transceiver-present bit in Wn3_Config. */
+ next:8; /* The media type to try next. */
+ short wait; /* Time before we check media status. */
+} media_tbl[] = {
+ { "10baseT", Media_10TP, 0x08, XCVR_10base2, (14 * HZ) / 10 },
+ { "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1 * HZ) / 10},
+ { "undefined", 0, 0x80, XCVR_10baseT, 10000},
+ { "10base2", 0, 0x10, XCVR_AUI, (1 * HZ) / 10},
+ { "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14 * HZ) / 10},
+ { "100baseFX", Media_Lnk, 0x04, XCVR_MII, (14 * HZ) / 10},
+ { "MII", 0, 0x40, XCVR_10baseT, 3 * HZ},
+ { "undefined", 0, 0x01, XCVR_10baseT, 10000},
+ { "Default", 0, 0xFF, XCVR_10baseT, 10000},
};
-static int vortex_scan(struct net_device *dev);
-static struct net_device *vortex_found_device(struct net_device *dev, int ioaddr,
- int irq, int product_index,
- int options);
-static int vortex_probe1(struct net_device *dev);
-static int vortex_open(struct net_device *dev);
-static void vortex_timer(unsigned long arg);
-static int vortex_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static int vortex_rx(struct net_device *dev);
+static int corkscrew_scan(struct net_device *dev);
+static struct net_device *corkscrew_found_device(struct net_device *dev,
+ int ioaddr, int irq,
+ int product_index,
+ int options);
+static int corkscrew_probe1(struct net_device *dev);
+static int corkscrew_open(struct net_device *dev);
+static void corkscrew_timer(unsigned long arg);
+static int corkscrew_start_xmit(struct sk_buff *skb,
+ struct net_device *dev);
+static int corkscrew_rx(struct net_device *dev);
+static void corkscrew_timeout(struct net_device *dev);
static int boomerang_rx(struct net_device *dev);
-static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs);
-static int vortex_close(struct net_device *dev);
+static void corkscrew_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs);
+static int corkscrew_close(struct net_device *dev);
static void update_stats(int addr, struct net_device *dev);
-static struct enet_statistics *vortex_get_stats(struct net_device *dev);
+static struct enet_statistics *corkscrew_get_stats(struct net_device *dev);
static void set_rx_mode(struct net_device *dev);
-/* Unlike the other PCI cards the 59x cards don't need a large contiguous
- memory region, so making the driver a loadable module is feasible.
-
+/*
Unfortunately maximizing the shared code between the integrated and
module version of the driver results in a complicated set of initialization
procedures.
init_module() -- modules / tc59x_init() -- built-in
- The wrappers for vortex_scan()
- vortex_scan() The common routine that scans for PCI and EISA cards
- vortex_found_device() Allocate a device structure when we find a card.
+ The wrappers for corkscrew_scan()
+ corkscrew_scan() The common routine that scans for PCI and EISA cards
+ corkscrew_found_device() Allocate a device structure when we find a card.
Different versions exist for modules and built-in.
- vortex_probe1() Fill in the device structure -- this is separated
+ corkscrew_probe1() Fill in the device structure -- this is separated
so that the modules code can put it in dev->init.
*/
/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
/* Note: this is the only limit on the number of cards supported!! */
-static int options[8] = { -1, -1, -1, -1, -1, -1, -1, -1,};
+static int options[8] = { -1, -1, -1, -1, -1, -1, -1, -1, };
#ifdef MODULE
static int debug = -1;
/* A list of all installed Vortex devices, for removing the driver module. */
-static struct net_device *root_vortex_dev = NULL;
+static struct net_device *root_corkscrew_dev = NULL;
-int
-init_module(void)
+int init_module(void)
{
int cards_found;
if (debug >= 0)
- vortex_debug = debug;
- if (vortex_debug)
+ corkscrew_debug = debug;
+ if (corkscrew_debug)
printk(version);
- root_vortex_dev = NULL;
- cards_found = vortex_scan(0);
+ root_corkscrew_dev = NULL;
+ cards_found = corkscrew_scan(0);
return cards_found ? 0 : -ENODEV;
}
@@ -403,80 +410,86 @@ int tc515_probe(struct net_device *dev)
{
int cards_found = 0;
- cards_found = vortex_scan(dev);
+ cards_found = corkscrew_scan(dev);
- if (vortex_debug > 0 && cards_found)
+ if (corkscrew_debug > 0 && cards_found)
printk(version);
return cards_found ? 0 : -ENODEV;
}
-#endif /* not MODULE */
+#endif /* not MODULE */
-static int vortex_scan(struct net_device *dev)
+static int corkscrew_scan(struct net_device *dev)
{
int cards_found = 0;
static int ioaddr = 0x100;
/* Check all locations on the ISA bus -- evil! */
for (; ioaddr < 0x400; ioaddr += 0x20) {
- int irq;
- if (check_region(ioaddr, CORKSCREW_TOTAL_SIZE))
- continue;
- /* Check the resource configuration for a matching ioaddr. */
- if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0))
- continue;
- /* Verify by reading the device ID from the EEPROM. */
- {
- int timer;
- outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd);
- /* Pause for at least 162 us. for the read to take place. */
- for (timer = 4; timer >= 0; timer--) {
- udelay(162);
- if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
- break;
+ int irq;
+ if (check_region(ioaddr, CORKSCREW_TOTAL_SIZE))
+ continue;
+ /* Check the resource configuration for a matching ioaddr. */
+ if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0))
+ continue;
+ /* Verify by reading the device ID from the EEPROM. */
+ {
+ int timer;
+ outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd);
+ /* Pause for at least 162 us. for the read to take place. */
+ for (timer = 4; timer >= 0; timer--) {
+ udelay(162);
+ if ((inw(ioaddr + Wn0EepromCmd) & 0x0200)
+ == 0)
+ break;
+ }
+ if (inw(ioaddr + Wn0EepromData) != 0x6d50)
+ continue;
}
- if (inw(ioaddr + Wn0EepromData) != 0x6d50)
- continue;
- }
- printk("3c515 Resource configuraiton register %#4.4x, DCR %4.4x.\n",
- inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
- irq = inw(ioaddr + 0x2002) & 15;
- vortex_found_device(dev, ioaddr, irq, CORKSCREW_ID, dev && dev->mem_start
- ? dev->mem_start : options[cards_found]);
- dev = 0;
- cards_found++;
+ printk(KERN_INFO "3c515 Resource configuraiton register %#4.4x, DCR %4.4x.\n",
+ inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
+ irq = inw(ioaddr + 0x2002) & 15;
+ corkscrew_found_device(dev, ioaddr, irq, CORKSCREW_ID, dev
+ && dev->mem_start ? dev->
+ mem_start : options[cards_found]);
+ dev = 0;
+ cards_found++;
}
- if (vortex_debug)
- printk("%d 3c515 cards found.\n", cards_found);
+ if (corkscrew_debug)
+ printk(KERN_INFO "%d 3c515 cards found.\n", cards_found);
return cards_found;
}
-static struct net_device *vortex_found_device(struct net_device *dev, int ioaddr,
- int irq, int product_index,
- int options)
+static struct net_device *corkscrew_found_device(struct net_device *dev,
+ int ioaddr, int irq,
+ int product_index,
+ int options)
{
- struct vortex_private *vp;
+ struct corkscrew_private *vp;
#ifdef MODULE
/* Allocate and fill new device structure. */
int dev_size = sizeof(struct net_device) +
- sizeof(struct vortex_private) + 15; /* Pad for alignment */
-
+ sizeof(struct corkscrew_private) + 15; /* Pad for alignment */
+
dev = (struct net_device *) kmalloc(dev_size, GFP_KERNEL);
memset(dev, 0, dev_size);
/* Align the Rx and Tx ring entries. */
- dev->priv = (void *)(((long)dev + sizeof(struct net_device) + 15) & ~15);
- vp = (struct vortex_private *)dev->priv;
- dev->name = vp->devname; /* An empty string. */
+ dev->priv =
+ (void *) (((long) dev + sizeof(struct net_device) + 15) & ~15);
+ vp = (struct corkscrew_private *) dev->priv;
+ dev->name = vp->devname; /* An empty string. */
dev->base_addr = ioaddr;
dev->irq = irq;
- dev->dma = (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0);
- dev->init = vortex_probe1;
+ dev->dma =
+ (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0);
+ dev->init = corkscrew_probe1;
vp->product_name = "3c515";
vp->options = options;
if (options >= 0) {
- vp->media_override = ((options & 7) == 2) ? 0 : options & 7;
+ vp->media_override =
+ ((options & 7) == 2) ? 0 : options & 7;
vp->full_duplex = (options & 8) ? 1 : 0;
vp->bus_master = (options & 16) ? 1 : 0;
} else {
@@ -485,25 +498,28 @@ static struct net_device *vortex_found_device(struct net_device *dev, int ioaddr
vp->bus_master = 0;
}
ether_setup(dev);
- vp->next_module = root_vortex_dev;
- root_vortex_dev = dev;
+ vp->next_module = root_corkscrew_dev;
+ root_corkscrew_dev = dev;
if (register_netdev(dev) != 0)
return 0;
-#else /* not a MODULE */
+#else /* not a MODULE */
if (dev) {
/* Caution: quad-word alignment required for rings! */
- dev->priv = kmalloc(sizeof (struct vortex_private), GFP_KERNEL);
- memset(dev->priv, 0, sizeof (struct vortex_private));
+ dev->priv =
+ kmalloc(sizeof(struct corkscrew_private), GFP_KERNEL);
+ memset(dev->priv, 0, sizeof(struct corkscrew_private));
}
- dev = init_etherdev(dev, sizeof(struct vortex_private));
+ dev = init_etherdev(dev, sizeof(struct corkscrew_private));
dev->base_addr = ioaddr;
dev->irq = irq;
- dev->dma = (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0);
- vp = (struct vortex_private *)dev->priv;
+ dev->dma =
+ (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0);
+ vp = (struct corkscrew_private *) dev->priv;
vp->product_name = "3c515";
vp->options = options;
if (options >= 0) {
- vp->media_override = ((options & 7) == 2) ? 0 : options & 7;
+ vp->media_override =
+ ((options & 7) == 2) ? 0 : options & 7;
vp->full_duplex = (options & 8) ? 1 : 0;
vp->bus_master = (options & 16) ? 1 : 0;
} else {
@@ -512,25 +528,26 @@ static struct net_device *vortex_found_device(struct net_device *dev, int ioaddr
vp->bus_master = 0;
}
- vortex_probe1(dev);
-#endif /* MODULE */
+ corkscrew_probe1(dev);
+#endif /* MODULE */
return dev;
}
-static int vortex_probe1(struct net_device *dev)
+static int corkscrew_probe1(struct net_device *dev)
{
int ioaddr = dev->base_addr;
- struct vortex_private *vp = (struct vortex_private *)dev->priv;
- unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */
+ struct corkscrew_private *vp =
+ (struct corkscrew_private *) dev->priv;
+ unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */
int i;
- printk("%s: 3Com %s at %#3x,", dev->name,
- vp->product_name, ioaddr);
+ printk(KERN_INFO "%s: 3Com %s at %#3x,", dev->name,
+ vp->product_name, ioaddr);
/* Read the station address from the EEPROM. */
EL3WINDOW(0);
for (i = 0; i < 0x18; i++) {
- short *phys_addr = (short *)dev->dev_addr;
+ short *phys_addr = (short *) dev->dev_addr;
int timer;
outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
/* Pause for at least 162 us. for the read to take place. */
@@ -549,97 +566,100 @@ static int vortex_probe1(struct net_device *dev)
printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);
for (i = 0; i < 6; i++)
printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]);
- if (eeprom[16] == 0x11c7) { /* Corkscrew */
- if (request_dma(dev->dma, "3c515")) {
- printk(", DMA %d allocation failed", dev->dma);
- dev->dma = 0;
- } else
- printk(", DMA %d", dev->dma);
+ if (eeprom[16] == 0x11c7) { /* Corkscrew */
+ if (request_dma(dev->dma, "3c515")) {
+ printk(", DMA %d allocation failed", dev->dma);
+ dev->dma = 0;
+ } else
+ printk(", DMA %d", dev->dma);
}
printk(", IRQ %d\n", dev->irq);
/* Tell them about an invalid IRQ. */
- if (vortex_debug && (dev->irq <= 0 || dev->irq > 15))
- printk(" *** Warning: this IRQ is unlikely to work! ***\n");
+ if (corkscrew_debug && (dev->irq <= 0 || dev->irq > 15))
+ printk(KERN_WARNING " *** Warning: this IRQ is unlikely to work! ***\n");
{
- char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
+ char *ram_split[] = { "5:3", "3:1", "1:1", "3:5" };
union wn3_config config;
EL3WINDOW(3);
vp->available_media = inw(ioaddr + Wn3_Options);
config.i = inl(ioaddr + Wn3_Config);
- if (vortex_debug > 1)
- printk(" Internal config register is %4.4x, transceivers %#x.\n",
- config.i, inw(ioaddr + Wn3_Options));
- printk(" %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
- 8 << config.u.ram_size,
- config.u.ram_width ? "word" : "byte",
- ram_split[config.u.ram_split],
- config.u.autoselect ? "autoselect/" : "",
- media_tbl[config.u.xcvr].name);
+ if (corkscrew_debug > 1)
+ printk(KERN_INFO " Internal config register is %4.4x, transceivers %#x.\n",
+ config.i, inw(ioaddr + Wn3_Options));
+ printk(KERN_INFO " %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
+ 8 << config.u.ram_size,
+ config.u.ram_width ? "word" : "byte",
+ ram_split[config.u.ram_split],
+ config.u.autoselect ? "autoselect/" : "",
+ media_tbl[config.u.xcvr].name);
dev->if_port = config.u.xcvr;
vp->default_media = config.u.xcvr;
vp->autoselect = config.u.autoselect;
}
if (vp->media_override != 7) {
- printk(" Media override to transceiver type %d (%s).\n",
- vp->media_override, media_tbl[vp->media_override].name);
+ printk(KERN_INFO " Media override to transceiver type %d (%s).\n",
+ vp->media_override,
+ media_tbl[vp->media_override].name);
dev->if_port = vp->media_override;
}
vp->capabilities = eeprom[16];
vp->full_bus_master_tx = (vp->capabilities & 0x20) ? 1 : 0;
/* Rx is broken at 10mbps, so we always disable it. */
- /* vp->full_bus_master_rx = 0;*/
+ /* vp->full_bus_master_rx = 0; */
vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0;
/* We do a request_region() to register /proc/ioports info. */
request_region(ioaddr, CORKSCREW_TOTAL_SIZE, vp->product_name);
- /* The 3c59x-specific entries in the device structure. */
- dev->open = &vortex_open;
- dev->hard_start_xmit = &vortex_start_xmit;
- dev->stop = &vortex_close;
- dev->get_stats = &vortex_get_stats;
+ /* The 3c51x-specific entries in the device structure. */
+ dev->open = &corkscrew_open;
+ dev->hard_start_xmit = &corkscrew_start_xmit;
+ dev->tx_timeout = &corkscrew_timeout;
+ dev->watchdog_timeo = (400 * HZ) / 1000;
+ dev->stop = &corkscrew_close;
+ dev->get_stats = &corkscrew_get_stats;
dev->set_multicast_list = &set_rx_mode;
return 0;
}
-
-static int
-vortex_open(struct net_device *dev)
+
+static int corkscrew_open(struct net_device *dev)
{
int ioaddr = dev->base_addr;
- struct vortex_private *vp = (struct vortex_private *)dev->priv;
+ struct corkscrew_private *vp =
+ (struct corkscrew_private *) dev->priv;
union wn3_config config;
int i;
/* Before initializing select the active media port. */
EL3WINDOW(3);
if (vp->full_duplex)
- outb(0x20, ioaddr + Wn3_MAC_Ctrl); /* Set the full-duplex bit. */
+ outb(0x20, ioaddr + Wn3_MAC_Ctrl); /* Set the full-duplex bit. */
config.i = inl(ioaddr + Wn3_Config);
if (vp->media_override != 7) {
- if (vortex_debug > 1)
- printk("%s: Media override to transceiver %d (%s).\n",
- dev->name, vp->media_override,
- media_tbl[vp->media_override].name);
+ if (corkscrew_debug > 1)
+ printk(KERN_INFO "%s: Media override to transceiver %d (%s).\n",
+ dev->name, vp->media_override,
+ media_tbl[vp->media_override].name);
dev->if_port = vp->media_override;
} else if (vp->autoselect) {
/* Find first available media type, starting with 100baseTx. */
dev->if_port = 4;
- while (! (vp->available_media & media_tbl[dev->if_port].mask))
+ while (!(vp->available_media & media_tbl[dev->if_port].mask))
dev->if_port = media_tbl[dev->if_port].next;
- if (vortex_debug > 1)
+ if (corkscrew_debug > 1)
printk("%s: Initial media type %s.\n",
- dev->name, media_tbl[dev->if_port].name);
+ dev->name, media_tbl[dev->if_port].name);
init_timer(&vp->timer);
vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
- vp->timer.data = (unsigned long)dev;
- vp->timer.function = &vortex_timer; /* timer handler */
+ vp->timer.data = (unsigned long) dev;
+ vp->timer.function = &corkscrew_timer; /* timer handler */
add_timer(&vp->timer);
} else
dev->if_port = vp->default_media;
@@ -647,63 +667,62 @@ vortex_open(struct net_device *dev)
config.u.xcvr = dev->if_port;
outl(config.i, ioaddr + Wn3_Config);
- if (vortex_debug > 1) {
- printk("%s: vortex_open() InternalConfig %8.8x.\n",
- dev->name, config.i);
+ if (corkscrew_debug > 1) {
+ printk("%s: corkscrew_open() InternalConfig %8.8x.\n",
+ dev->name, config.i);
}
outw(TxReset, ioaddr + EL3_CMD);
- for (i = 20; i >= 0 ; i--)
- if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+ for (i = 20; i >= 0; i--)
+ if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
break;
outw(RxReset, ioaddr + EL3_CMD);
/* Wait a few ticks for the RxReset command to complete. */
- for (i = 20; i >= 0 ; i--)
- if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+ for (i = 20; i >= 0; i--)
+ if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
break;
outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
/* Use the now-standard shared IRQ implementation. */
if (vp->capabilities == 0x11c7) {
- /* Corkscrew: Cannot share ISA resources. */
- if (dev->irq == 0
- || dev->dma == 0
- || request_irq(dev->irq, &vortex_interrupt, 0,
- vp->product_name, dev))
+ /* Corkscrew: Cannot share ISA resources. */
+ if (dev->irq == 0
+ || dev->dma == 0
+ || request_irq(dev->irq, &corkscrew_interrupt, 0,
+ vp->product_name, dev)) return -EAGAIN;
+ enable_dma(dev->dma);
+ set_dma_mode(dev->dma, DMA_MODE_CASCADE);
+ } else if (request_irq(dev->irq, &corkscrew_interrupt, SA_SHIRQ,
+ vp->product_name, dev)) {
return -EAGAIN;
- enable_dma(dev->dma);
- set_dma_mode(dev->dma, DMA_MODE_CASCADE);
- } else if (request_irq(dev->irq, &vortex_interrupt, SA_SHIRQ,
- vp->product_name, dev)) {
- return -EAGAIN;
}
- if (vortex_debug > 1) {
+ if (corkscrew_debug > 1) {
EL3WINDOW(4);
- printk("%s: vortex_open() irq %d media status %4.4x.\n",
- dev->name, dev->irq, inw(ioaddr + Wn4_Media));
+ printk("%s: corkscrew_open() irq %d media status %4.4x.\n",
+ dev->name, dev->irq, inw(ioaddr + Wn4_Media));
}
/* Set the station address and mask in window 2 each time opened. */
EL3WINDOW(2);
for (i = 0; i < 6; i++)
outb(dev->dev_addr[i], ioaddr + i);
- for (; i < 12; i+=2)
+ for (; i < 12; i += 2)
outw(0, ioaddr + i);
if (dev->if_port == 3)
- /* Start the thinnet transceiver. We should really wait 50ms...*/
+ /* Start the thinnet transceiver. We should really wait 50ms... */
outw(StartCoax, ioaddr + EL3_CMD);
EL3WINDOW(4);
- outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) |
- media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
+ outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP | Media_SQE)) |
+ media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
/* Switch to the stats window, and clear all stats by reading. */
outw(StatsDisable, ioaddr + EL3_CMD);
EL3WINDOW(6);
- for (i = 0; i < 10; i++)
+ for (i = 0; i < 10; i++)
inb(ioaddr + i);
inw(ioaddr + 10);
inw(ioaddr + 12);
@@ -716,32 +735,34 @@ vortex_open(struct net_device *dev)
/* Switch to register set 7 for normal use. */
EL3WINDOW(7);
- if (vp->full_bus_master_rx) { /* Boomerang bus master. */
+ if (vp->full_bus_master_rx) { /* Boomerang bus master. */
vp->cur_rx = vp->dirty_rx = 0;
- if (vortex_debug > 2)
- printk("%s: Filling in the Rx ring.\n", dev->name);
+ if (corkscrew_debug > 2)
+ printk("%s: Filling in the Rx ring.\n",
+ dev->name);
for (i = 0; i < RX_RING_SIZE; i++) {
struct sk_buff *skb;
if (i < (RX_RING_SIZE - 1))
- vp->rx_ring[i].next = virt_to_bus(&vp->rx_ring[i+1]);
+ vp->rx_ring[i].next =
+ virt_to_bus(&vp->rx_ring[i + 1]);
else
- vp->rx_ring[i].next = 0;
+ vp->rx_ring[i].next = 0;
vp->rx_ring[i].status = 0; /* Clear complete bit. */
vp->rx_ring[i].length = PKT_BUF_SZ | 0x80000000;
skb = dev_alloc_skb(PKT_BUF_SZ);
vp->rx_skbuff[i] = skb;
if (skb == NULL)
- break; /* Bad news! */
- skb->dev = dev; /* Mark as being used by this device. */
+ break; /* Bad news! */
+ skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
vp->rx_ring[i].addr = virt_to_bus(skb->tail);
}
- vp->rx_ring[i-1].next = virt_to_bus(&vp->rx_ring[0]); /* Wrap the ring. */
+ vp->rx_ring[i - 1].next = virt_to_bus(&vp->rx_ring[0]); /* Wrap the ring. */
outl(virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
}
- if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */
+ if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */
vp->cur_tx = vp->dirty_tx = 0;
- outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */
+ outb(PKT_BUF_SZ >> 8, ioaddr + TxFreeThreshold); /* Room for a packet. */
/* Clear the Tx ring. */
for (i = 0; i < TX_RING_SIZE; i++)
vp->tx_skbuff[i] = 0;
@@ -749,175 +770,188 @@ vortex_open(struct net_device *dev)
}
/* Set receiver mode: presumably accept b-case and phys addr only. */
set_rx_mode(dev);
- outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
+ outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue(dev);
- outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
- outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
+ outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
+ outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
/* Allow status bits to be seen. */
- outw(SetStatusEnb | AdapterFailure|IntReq|StatsFull |
- (vp->full_bus_master_tx ? DownComplete : TxAvailable) |
- (vp->full_bus_master_rx ? UpComplete : RxComplete) |
- (vp->bus_master ? DMADone : 0),
- ioaddr + EL3_CMD);
+ outw(SetStatusEnb | AdapterFailure | IntReq | StatsFull |
+ (vp->full_bus_master_tx ? DownComplete : TxAvailable) |
+ (vp->full_bus_master_rx ? UpComplete : RxComplete) |
+ (vp->bus_master ? DMADone : 0), ioaddr + EL3_CMD);
/* Ack all pending events, and set active indicator mask. */
outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
- ioaddr + EL3_CMD);
+ ioaddr + EL3_CMD);
outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
- | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
- ioaddr + EL3_CMD);
+ | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
+ ioaddr + EL3_CMD);
MOD_INC_USE_COUNT;
return 0;
}
-static void vortex_timer(unsigned long data)
+static void corkscrew_timer(unsigned long data)
{
#ifdef AUTOMEDIA
- struct net_device *dev = (struct net_device *)data;
- struct vortex_private *vp = (struct vortex_private *)dev->priv;
+ struct net_device *dev = (struct net_device *) data;
+ struct corkscrew_private *vp =
+ (struct corkscrew_private *) dev->priv;
int ioaddr = dev->base_addr;
unsigned long flags;
int ok = 0;
- if (vortex_debug > 1)
+ if (corkscrew_debug > 1)
printk("%s: Media selection timer tick happened, %s.\n",
- dev->name, media_tbl[dev->if_port].name);
-
- save_flags(flags); cli(); {
- int old_window = inw(ioaddr + EL3_CMD) >> 13;
- int media_status;
- EL3WINDOW(4);
- media_status = inw(ioaddr + Wn4_Media);
- switch (dev->if_port) {
- case 0: case 4: case 5: /* 10baseT, 100baseTX, 100baseFX */
- if (media_status & Media_LnkBeat) {
- ok = 1;
- if (vortex_debug > 1)
- printk("%s: Media %s has link beat, %x.\n",
- dev->name, media_tbl[dev->if_port].name, media_status);
- } else if (vortex_debug > 1)
- printk("%s: Media %s is has no link beat, %x.\n",
- dev->name, media_tbl[dev->if_port].name, media_status);
-
- break;
- default: /* Other media types handled by Tx timeouts. */
- if (vortex_debug > 1)
- printk("%s: Media %s is has no indication, %x.\n",
- dev->name, media_tbl[dev->if_port].name, media_status);
- ok = 1;
- }
- if ( ! ok) {
- union wn3_config config;
+ dev->name, media_tbl[dev->if_port].name);
- do {
- dev->if_port = media_tbl[dev->if_port].next;
- } while ( ! (vp->available_media & media_tbl[dev->if_port].mask));
- if (dev->if_port == 8) { /* Go back to default. */
- dev->if_port = vp->default_media;
- if (vortex_debug > 1)
- printk("%s: Media selection failing, using default %s port.\n",
- dev->name, media_tbl[dev->if_port].name);
- } else {
- if (vortex_debug > 1)
- printk("%s: Media selection failed, now trying %s port.\n",
- dev->name, media_tbl[dev->if_port].name);
- vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
- add_timer(&vp->timer);
+ save_flags(flags);
+ cli(); {
+ int old_window = inw(ioaddr + EL3_CMD) >> 13;
+ int media_status;
+ EL3WINDOW(4);
+ media_status = inw(ioaddr + Wn4_Media);
+ switch (dev->if_port) {
+ case 0:
+ case 4:
+ case 5: /* 10baseT, 100baseTX, 100baseFX */
+ if (media_status & Media_LnkBeat) {
+ ok = 1;
+ if (corkscrew_debug > 1)
+ printk("%s: Media %s has link beat, %x.\n",
+ dev->name,
+ media_tbl[dev->if_port].name,
+ media_status);
+ } else if (corkscrew_debug > 1)
+ printk("%s: Media %s is has no link beat, %x.\n",
+ dev->name,
+ media_tbl[dev->if_port].name,
+ media_status);
+
+ break;
+ default: /* Other media types handled by Tx timeouts. */
+ if (corkscrew_debug > 1)
+ printk("%s: Media %s is has no indication, %x.\n",
+ dev->name,
+ media_tbl[dev->if_port].name,
+ media_status);
+ ok = 1;
}
- outw((media_status & ~(Media_10TP|Media_SQE)) |
- media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
+ if (!ok) {
+ union wn3_config config;
- EL3WINDOW(3);
- config.i = inl(ioaddr + Wn3_Config);
- config.u.xcvr = dev->if_port;
- outl(config.i, ioaddr + Wn3_Config);
-
- outw(dev->if_port == 3 ? StartCoax : StopCoax, ioaddr + EL3_CMD);
- }
- EL3WINDOW(old_window);
- } restore_flags(flags);
- if (vortex_debug > 1)
- printk("%s: Media selection timer finished, %s.\n",
- dev->name, media_tbl[dev->if_port].name);
-
-#endif /* AUTOMEDIA*/
+ do {
+ dev->if_port =
+ media_tbl[dev->if_port].next;
+ }
+ while (!(vp->available_media & media_tbl[dev->if_port].mask));
+
+ if (dev->if_port == 8) { /* Go back to default. */
+ dev->if_port = vp->default_media;
+ if (corkscrew_debug > 1)
+ printk("%s: Media selection failing, using default %s port.\n",
+ dev->name,
+ media_tbl[dev->if_port].name);
+ } else {
+ if (corkscrew_debug > 1)
+ printk("%s: Media selection failed, now trying %s port.\n",
+ dev->name,
+ media_tbl[dev->if_port].name);
+ vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
+ add_timer(&vp->timer);
+ }
+ outw((media_status & ~(Media_10TP | Media_SQE)) |
+ media_tbl[dev->if_port].media_bits,
+ ioaddr + Wn4_Media);
+
+ EL3WINDOW(3);
+ config.i = inl(ioaddr + Wn3_Config);
+ config.u.xcvr = dev->if_port;
+ outl(config.i, ioaddr + Wn3_Config);
+
+ outw(dev->if_port == 3 ? StartCoax : StopCoax,
+ ioaddr + EL3_CMD);
+ }
+ EL3WINDOW(old_window);
+ }
+ restore_flags(flags);
+ if (corkscrew_debug > 1)
+ printk("%s: Media selection timer finished, %s.\n",
+ dev->name, media_tbl[dev->if_port].name);
+
+#endif /* AUTOMEDIA */
return;
}
-static int
-vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static void corkscrew_timeout(struct net_device *dev)
{
- struct vortex_private *vp = (struct vortex_private *)dev->priv;
+ int i;
+ struct corkscrew_private *vp =
+ (struct corkscrew_private *) dev->priv;
int ioaddr = dev->base_addr;
- if (dev->tbusy) {
- int tickssofar = jiffies - dev->trans_start;
- int i;
-
- /* Min. wait before assuming a Tx failed == 400ms. */
-
- if (tickssofar < 400*HZ/1000) /* We probably aren't empty. */
- return 1;
- printk("%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
- dev->name, inb(ioaddr + TxStatus),
- inw(ioaddr + EL3_STATUS));
- /* Slight code bloat to be user friendly. */
- if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
- printk("%s: Transmitter encountered 16 collisions -- network"
- " network cable problem?\n", dev->name);
+ printk(KERN_WARNING
+ "%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
+ dev->name, inb(ioaddr + TxStatus),
+ inw(ioaddr + EL3_STATUS));
+ /* Slight code bloat to be user friendly. */
+ if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
+ printk(KERN_WARNING
+ "%s: Transmitter encountered 16 collisions -- network"
+ " network cable problem?\n", dev->name);
#ifndef final_version
- printk(" Flags; bus-master %d, full %d; dirty %d current %d.\n",
- vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx, vp->cur_tx);
- printk(" Down list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr),
- &vp->tx_ring[0]);
- for (i = 0; i < TX_RING_SIZE; i++) {
- printk(" %d: %p length %8.8x status %8.8x\n", i,
- &vp->tx_ring[i],
- vp->tx_ring[i].length,
- vp->tx_ring[i].status);
- }
-#endif
- /* Issue TX_RESET and TX_START commands. */
- outw(TxReset, ioaddr + EL3_CMD);
- for (i = 20; i >= 0 ; i--)
- if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
- break;
- outw(TxEnable, ioaddr + EL3_CMD);
- dev->trans_start = jiffies;
- /* dev->tbusy = 0;*/
- vp->stats.tx_errors++;
- vp->stats.tx_dropped++;
- return 0; /* Yes, silently *drop* the packet! */
+ printk(" Flags; bus-master %d, full %d; dirty %d current %d.\n",
+ vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx,
+ vp->cur_tx);
+ printk(" Down list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr),
+ &vp->tx_ring[0]);
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ printk(" %d: %p length %8.8x status %8.8x\n", i,
+ &vp->tx_ring[i],
+ vp->tx_ring[i].length, vp->tx_ring[i].status);
}
+#endif
+ /* Issue TX_RESET and TX_START commands. */
+ outw(TxReset, ioaddr + EL3_CMD);
+ for (i = 20; i >= 0; i--)
+ if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
+ break;
+ outw(TxEnable, ioaddr + EL3_CMD);
+ dev->trans_start = jiffies;
+ vp->stats.tx_errors++;
+ vp->stats.tx_dropped++;
+ netif_wake_queue(dev);
+}
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
- If this ever occurs the queue layer is doing something evil! */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
- printk("%s: Transmitter access conflict.\n", dev->name);
- return 1;
- }
+static int corkscrew_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct corkscrew_private *vp =
+ (struct corkscrew_private *) dev->priv;
+ int ioaddr = dev->base_addr;
+
+ /* Block a timer-based transmit from overlapping. */
- if (vp->full_bus_master_tx) { /* BOOMERANG bus-master */
+ netif_stop_queue(dev);
+
+ if (vp->full_bus_master_tx) { /* BOOMERANG bus-master */
/* Calculate the next Tx descriptor entry. */
int entry = vp->cur_tx % TX_RING_SIZE;
struct boom_tx_desc *prev_entry;
unsigned long flags, i;
- if (vp->tx_full) /* No room to transmit with */
- return 1;
+ if (vp->tx_full) /* No room to transmit with */
+ return 1;
if (vp->cur_tx != 0)
- prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE];
+ prev_entry =
+ &vp->tx_ring[(vp->cur_tx - 1) % TX_RING_SIZE];
else
- prev_entry = NULL;
- if (vortex_debug > 3)
+ prev_entry = NULL;
+ if (corkscrew_debug > 3)
printk("%s: Trying to send a packet, Tx index %d.\n",
- dev->name, vp->cur_tx);
+ dev->name, vp->cur_tx);
/* vp->tx_full = 1; */
vp->tx_skbuff[entry] = skb;
vp->tx_ring[entry].next = 0;
@@ -929,13 +963,15 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
cli();
outw(DownStall, ioaddr + EL3_CMD);
/* Wait for the stall to complete. */
- for (i = 20; i >= 0 ; i--)
- if ( (inw(ioaddr + EL3_STATUS) & CmdInProgress) == 0)
- break;
+ for (i = 20; i >= 0; i--)
+ if ((inw(ioaddr + EL3_STATUS) & CmdInProgress) ==
+ 0) break;
if (prev_entry)
- prev_entry->next = virt_to_bus(&vp->tx_ring[entry]);
+ prev_entry->next =
+ virt_to_bus(&vp->tx_ring[entry]);
if (inl(ioaddr + DownListPtr) == 0) {
- outl(virt_to_bus(&vp->tx_ring[entry]), ioaddr + DownListPtr);
+ outl(virt_to_bus(&vp->tx_ring[entry]),
+ ioaddr + DownListPtr);
queued_packet++;
}
outw(DownUnstall, ioaddr + EL3_CMD);
@@ -944,10 +980,10 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
vp->cur_tx++;
if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1)
vp->tx_full = 1;
- else { /* Clear previous interrupt enable. */
- if (prev_entry)
- prev_entry->status &= ~0x80000000;
- dev->tbusy = 0;
+ else { /* Clear previous interrupt enable. */
+ if (prev_entry)
+ prev_entry->status &= ~0x80000000;
+ netif_wake_queue(dev);
}
dev->trans_start = jiffies;
return 0;
@@ -957,31 +993,32 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
#ifdef VORTEX_BUS_MASTER
if (vp->bus_master) {
/* Set the bus-master controller to transfer the packet. */
- outl((int)(skb->data), ioaddr + Wn7_MasterAddr);
+ outl((int) (skb->data), ioaddr + Wn7_MasterAddr);
outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
vp->tx_skb = skb;
outw(StartDMADown, ioaddr + EL3_CMD);
- /* dev->tbusy will be cleared at the DMADone interrupt. */
+ /* queue will be woken at the DMADone interrupt. */
} else {
/* ... and the packet rounded to a doubleword. */
outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
- dev_kfree_skb (skb);
+ dev_kfree_skb(skb);
if (inw(ioaddr + TxFree) > 1536) {
- dev->tbusy = 0;
+ netif_wake_queue(dev);
} else
/* Interrupt us when the FIFO has room for max-sized packet. */
- outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
+ outw(SetTxThreshold + (1536 >> 2),
+ ioaddr + EL3_CMD);
}
#else
/* ... and the packet rounded to a doubleword. */
outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
- dev_kfree_skb (skb);
+ dev_kfree_skb(skb);
if (inw(ioaddr + TxFree) > 1536) {
- dev->tbusy = 0;
+ netif_wake_queue(dev);
} else
/* Interrupt us when the FIFO has room for max-sized packet. */
- outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
-#endif /* bus master */
+ outw(SetTxThreshold + (1536 >> 2), ioaddr + EL3_CMD);
+#endif /* bus master */
dev->trans_start = jiffies;
@@ -990,80 +1027,79 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
short tx_status;
int i = 4;
- while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) {
- if (tx_status & 0x3C) { /* A Tx-disabling error occurred. */
- if (vortex_debug > 2)
- printk("%s: Tx error, status %2.2x.\n",
- dev->name, tx_status);
- if (tx_status & 0x04) vp->stats.tx_fifo_errors++;
- if (tx_status & 0x38) vp->stats.tx_aborted_errors++;
+ while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) {
+ if (tx_status & 0x3C) { /* A Tx-disabling error occurred. */
+ if (corkscrew_debug > 2)
+ printk("%s: Tx error, status %2.2x.\n",
+ dev->name, tx_status);
+ if (tx_status & 0x04)
+ vp->stats.tx_fifo_errors++;
+ if (tx_status & 0x38)
+ vp->stats.tx_aborted_errors++;
if (tx_status & 0x30) {
int j;
outw(TxReset, ioaddr + EL3_CMD);
- for (j = 20; j >= 0 ; j--)
- if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+ for (j = 20; j >= 0; j--)
+ if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
break;
}
outw(TxEnable, ioaddr + EL3_CMD);
}
- outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */
+ outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */
}
}
- vp->stats.tx_bytes+=skb->len;
+ vp->stats.tx_bytes += skb->len;
return 0;
}
/* The interrupt handler does all of the Rx thread work and cleans up
after the Tx thread. */
-static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs)
+
+static void corkscrew_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
{
/* Use the now-standard shared IRQ implementation. */
struct net_device *dev = dev_id;
- struct vortex_private *lp;
+ struct corkscrew_private *lp;
int ioaddr, status;
int latency;
int i = max_interrupt_work;
- if (test_and_set_bit(0, (void*)&dev->interrupt)) {
- printk("%s: Re-entering the interrupt handler.\n", dev->name);
- return;
- }
-
ioaddr = dev->base_addr;
latency = inb(ioaddr + Timer);
- lp = (struct vortex_private *)dev->priv;
+ lp = (struct corkscrew_private *) dev->priv;
status = inw(ioaddr + EL3_STATUS);
- if (vortex_debug > 4)
- printk("%s: interrupt, status %4.4x, timer %d.\n", dev->name,
- status, latency);
+ if (corkscrew_debug > 4)
+ printk("%s: interrupt, status %4.4x, timer %d.\n",
+ dev->name, status, latency);
if ((status & 0xE000) != 0xE000) {
- static int donedidthis=0;
+ static int donedidthis = 0;
/* Some interrupt controllers store a bogus interrupt from boot-time.
Ignore a single early interrupt, but don't hang the machine for
other interrupt problems. */
if (donedidthis++ > 100) {
- printk("%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n",
- dev->name, status, dev->start);
- FREE_IRQ(dev->irq, dev);
+ printk(KERN_ERR "%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n",
+ dev->name, status, netif_running(dev));
+ free_irq(dev->irq, dev);
}
}
do {
- if (vortex_debug > 5)
- printk("%s: In interrupt loop, status %4.4x.\n",
- dev->name, status);
+ if (corkscrew_debug > 5)
+ printk("%s: In interrupt loop, status %4.4x.\n",
+ dev->name, status);
if (status & RxComplete)
- vortex_rx(dev);
+ corkscrew_rx(dev);
if (status & TxAvailable) {
- if (vortex_debug > 5)
- printk(" TX room bit was handled.\n");
+ if (corkscrew_debug > 5)
+ printk
+ (" TX room bit was handled.\n");
/* There's room in the FIFO for a full-sized packet. */
outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
}
if (status & DownComplete) {
unsigned int dirty_tx = lp->dirty_tx;
@@ -1071,28 +1107,29 @@ static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs)
while (lp->cur_tx - dirty_tx > 0) {
int entry = dirty_tx % TX_RING_SIZE;
if (inl(ioaddr + DownListPtr) ==
- virt_to_bus(&lp->tx_ring[entry]))
- break; /* It still hasn't been processed. */
+ virt_to_bus(&lp->tx_ring[entry]))
+ break; /* It still hasn't been processed. */
if (lp->tx_skbuff[entry]) {
- dev_kfree_skb(lp->tx_skbuff[entry]);
+ dev_kfree_skb_irq(lp->
+ tx_skbuff
+ [entry]);
lp->tx_skbuff[entry] = 0;
}
dirty_tx++;
}
lp->dirty_tx = dirty_tx;
outw(AckIntr | DownComplete, ioaddr + EL3_CMD);
- if (lp->tx_full && (lp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) {
- lp->tx_full= 0;
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ if (lp->tx_full
+ && (lp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) {
+ lp->tx_full = 0;
+ netif_wake_queue(dev);
}
}
#ifdef VORTEX_BUS_MASTER
if (status & DMADone) {
- outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
- dev->tbusy = 0;
- dev_kfree_skb (lp->tx_skb); /* Release the transfered buffer */
- mark_bh(NET_BH);
+ outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
+ dev_kfree_skb_irq(lp->tx_skb); /* Release the transfered buffer */
+ netif_wake_queue(dev);
}
#endif
if (status & UpComplete) {
@@ -1101,32 +1138,36 @@ static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs)
}
if (status & (AdapterFailure | RxEarly | StatsFull)) {
/* Handle all uncommon interrupts at once. */
- if (status & RxEarly) { /* Rx early is unused. */
- vortex_rx(dev);
+ if (status & RxEarly) { /* Rx early is unused. */
+ corkscrew_rx(dev);
outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
}
- if (status & StatsFull) { /* Empty statistics. */
+ if (status & StatsFull) { /* Empty statistics. */
static int DoneDidThat = 0;
- if (vortex_debug > 4)
- printk("%s: Updating stats.\n", dev->name);
+ if (corkscrew_debug > 4)
+ printk("%s: Updating stats.\n",
+ dev->name);
update_stats(ioaddr, dev);
/* DEBUG HACK: Disable statistics as an interrupt source. */
/* This occurs when we have the wrong media type! */
- if (DoneDidThat == 0 &&
- inw(ioaddr + EL3_STATUS) & StatsFull) {
+ if (DoneDidThat == 0 &&
+ inw(ioaddr + EL3_STATUS) & StatsFull) {
int win, reg;
printk("%s: Updating stats failed, disabling stats as an"
- " interrupt source.\n", dev->name);
+ " interrupt source.\n",
+ dev->name);
for (win = 0; win < 8; win++) {
EL3WINDOW(win);
printk("\n Vortex window %d:", win);
for (reg = 0; reg < 16; reg++)
- printk(" %2.2x", inb(ioaddr+reg));
+ printk(" %2.2x",
+ inb(ioaddr + reg));
}
EL3WINDOW(7);
- outw(SetIntrEnb | TxAvailable | RxComplete | AdapterFailure
- | UpComplete | DownComplete | TxComplete,
- ioaddr + EL3_CMD);
+ outw(SetIntrEnb | TxAvailable |
+ RxComplete | AdapterFailure |
+ UpComplete | DownComplete |
+ TxComplete, ioaddr + EL3_CMD);
DoneDidThat++;
}
}
@@ -1135,139 +1176,150 @@ static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs)
outw(RxReset, ioaddr + EL3_CMD);
/* Set the Rx filter to the current state. */
set_rx_mode(dev);
- outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
- outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
+ outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
+ outw(AckIntr | AdapterFailure,
+ ioaddr + EL3_CMD);
}
}
if (--i < 0) {
- printk("%s: Too much work in interrupt, status %4.4x. "
- "Disabling functions (%4.4x).\n",
- dev->name, status, SetStatusEnb | ((~status) & 0x7FE));
+ printk(KERN_ERR "%s: Too much work in interrupt, status %4.4x. "
+ "Disabling functions (%4.4x).\n", dev->name,
+ status, SetStatusEnb | ((~status) & 0x7FE));
/* Disable all pending interrupts. */
- outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD);
+ outw(SetStatusEnb | ((~status) & 0x7FE),
+ ioaddr + EL3_CMD);
outw(AckIntr | 0x7FF, ioaddr + EL3_CMD);
break;
}
/* Acknowledge the IRQ. */
outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
- } while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
+ } while ((status = inw(ioaddr + EL3_STATUS)) &
+ (IntLatch | RxComplete));
- if (vortex_debug > 4)
- printk("%s: exiting interrupt, status %4.4x.\n", dev->name, status);
-
- dev->interrupt = 0;
- return;
+ if (corkscrew_debug > 4)
+ printk("%s: exiting interrupt, status %4.4x.\n", dev->name,
+ status);
}
-static int
-vortex_rx(struct net_device *dev)
+static int corkscrew_rx(struct net_device *dev)
{
- struct vortex_private *vp = (struct vortex_private *)dev->priv;
+ struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv;
int ioaddr = dev->base_addr;
int i;
short rx_status;
- if (vortex_debug > 5)
+ if (corkscrew_debug > 5)
printk(" In rx_packet(), status %4.4x, rx_status %4.4x.\n",
- inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
+ inw(ioaddr + EL3_STATUS), inw(ioaddr + RxStatus));
while ((rx_status = inw(ioaddr + RxStatus)) > 0) {
- if (rx_status & 0x4000) { /* Error, update stats. */
+ if (rx_status & 0x4000) { /* Error, update stats. */
unsigned char rx_error = inb(ioaddr + RxErrors);
- if (vortex_debug > 2)
- printk(" Rx error: status %2.2x.\n", rx_error);
+ if (corkscrew_debug > 2)
+ printk(" Rx error: status %2.2x.\n",
+ rx_error);
vp->stats.rx_errors++;
- if (rx_error & 0x01) vp->stats.rx_over_errors++;
- if (rx_error & 0x02) vp->stats.rx_length_errors++;
- if (rx_error & 0x04) vp->stats.rx_frame_errors++;
- if (rx_error & 0x08) vp->stats.rx_crc_errors++;
- if (rx_error & 0x10) vp->stats.rx_length_errors++;
+ if (rx_error & 0x01)
+ vp->stats.rx_over_errors++;
+ if (rx_error & 0x02)
+ vp->stats.rx_length_errors++;
+ if (rx_error & 0x04)
+ vp->stats.rx_frame_errors++;
+ if (rx_error & 0x08)
+ vp->stats.rx_crc_errors++;
+ if (rx_error & 0x10)
+ vp->stats.rx_length_errors++;
} else {
/* The packet length: up to 4.5K!. */
short pkt_len = rx_status & 0x1fff;
struct sk_buff *skb;
- skb = DEV_ALLOC_SKB(pkt_len + 5);
- if (vortex_debug > 4)
+ skb = dev_alloc_skb(pkt_len + 5 + 2);
+ if (corkscrew_debug > 4)
printk("Receiving packet size %d status %4.4x.\n",
- pkt_len, rx_status);
+ pkt_len, rx_status);
if (skb != NULL) {
skb->dev = dev;
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
/* 'skb_put()' points to the start of sk_buff data area. */
- insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len),
- (pkt_len + 3) >> 2);
- outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
+ insl(ioaddr + RX_FIFO,
+ skb_put(skb, pkt_len),
+ (pkt_len + 3) >> 2);
+ outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
dev->last_rx = jiffies;
vp->stats.rx_packets++;
- vp->stats.rx_bytes+=skb->len;
+ vp->stats.rx_bytes += skb->len;
/* Wait a limited time to go to next packet. */
for (i = 200; i >= 0; i--)
- if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+ if (! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
break;
continue;
- } else if (vortex_debug)
- printk("%s: Couldn't allocate a sk_buff of size %d.\n",
- dev->name, pkt_len);
+ } else if (corkscrew_debug)
+ printk("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, pkt_len);
}
outw(RxDiscard, ioaddr + EL3_CMD);
vp->stats.rx_dropped++;
/* Wait a limited time to skip this packet. */
for (i = 200; i >= 0; i--)
- if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+ if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
break;
}
-
return 0;
}
-static int
-boomerang_rx(struct net_device *dev)
+static int boomerang_rx(struct net_device *dev)
{
- struct vortex_private *vp = (struct vortex_private *)dev->priv;
+ struct corkscrew_private *vp =
+ (struct corkscrew_private *) dev->priv;
int entry = vp->cur_rx % RX_RING_SIZE;
int ioaddr = dev->base_addr;
int rx_status;
- if (vortex_debug > 5)
+ if (corkscrew_debug > 5)
printk(" In boomerang_rx(), status %4.4x, rx_status %4.4x.\n",
- inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
+ inw(ioaddr + EL3_STATUS), inw(ioaddr + RxStatus));
while ((rx_status = vp->rx_ring[entry].status) & RxDComplete) {
- if (rx_status & RxDError) { /* Error, update stats. */
+ if (rx_status & RxDError) { /* Error, update stats. */
unsigned char rx_error = rx_status >> 16;
- if (vortex_debug > 2)
- printk(" Rx error: status %2.2x.\n", rx_error);
+ if (corkscrew_debug > 2)
+ printk(" Rx error: status %2.2x.\n",
+ rx_error);
vp->stats.rx_errors++;
- if (rx_error & 0x01) vp->stats.rx_over_errors++;
- if (rx_error & 0x02) vp->stats.rx_length_errors++;
- if (rx_error & 0x04) vp->stats.rx_frame_errors++;
- if (rx_error & 0x08) vp->stats.rx_crc_errors++;
- if (rx_error & 0x10) vp->stats.rx_length_errors++;
+ if (rx_error & 0x01)
+ vp->stats.rx_over_errors++;
+ if (rx_error & 0x02)
+ vp->stats.rx_length_errors++;
+ if (rx_error & 0x04)
+ vp->stats.rx_frame_errors++;
+ if (rx_error & 0x08)
+ vp->stats.rx_crc_errors++;
+ if (rx_error & 0x10)
+ vp->stats.rx_length_errors++;
} else {
/* The packet length: up to 4.5K!. */
short pkt_len = rx_status & 0x1fff;
struct sk_buff *skb;
- vp->stats.rx_bytes+=pkt_len;
- if (vortex_debug > 4)
+ vp->stats.rx_bytes += pkt_len;
+ if (corkscrew_debug > 4)
printk("Receiving packet size %d status %4.4x.\n",
- pkt_len, rx_status);
+ pkt_len, rx_status);
/* Check if the packet is long enough to just accept without
copying to a properly sized skbuff. */
if (pkt_len < rx_copybreak
- && (skb = DEV_ALLOC_SKB(pkt_len + 2)) != 0) {
+ && (skb = dev_alloc_skb(pkt_len + 4)) != 0) {
skb->dev = dev;
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
/* 'skb_put()' points to the start of sk_buff data area. */
memcpy(skb_put(skb, pkt_len),
- bus_to_virt(vp->rx_ring[entry].addr),
- pkt_len);
+ bus_to_virt(vp->rx_ring[entry].
+ addr), pkt_len);
rx_copy++;
- } else{
+ } else {
void *temp;
/* Pass up the skbuff already on the Rx ring. */
skb = vp->rx_skbuff[entry];
@@ -1275,10 +1327,13 @@ boomerang_rx(struct net_device *dev)
temp = skb_put(skb, pkt_len);
/* Remove this checking code for final release. */
if (bus_to_virt(vp->rx_ring[entry].addr) != temp)
- printk("%s: Warning -- the skbuff addresses do not match"
- " in boomerang_rx: %p vs. %p / %p.\n", dev->name,
- bus_to_virt(vp->rx_ring[entry].addr),
- skb->head, temp);
+ printk("%s: Warning -- the skbuff addresses do not match"
+ " in boomerang_rx: %p vs. %p / %p.\n",
+ dev->name,
+ bus_to_virt(vp->
+ rx_ring[entry].
+ addr), skb->head,
+ temp);
rx_nocopy++;
}
skb->protocol = eth_type_trans(skb, dev);
@@ -1295,8 +1350,8 @@ boomerang_rx(struct net_device *dev)
if (vp->rx_skbuff[entry] == NULL) {
skb = dev_alloc_skb(PKT_BUF_SZ);
if (skb == NULL)
- break; /* Bad news! */
- skb->dev = dev; /* Mark as being used by this device. */
+ break; /* Bad news! */
+ skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
vp->rx_ring[entry].addr = virt_to_bus(skb->tail);
vp->rx_skbuff[entry] = skb;
@@ -1306,22 +1361,22 @@ boomerang_rx(struct net_device *dev)
return 0;
}
-static int
-vortex_close(struct net_device *dev)
+static int corkscrew_close(struct net_device *dev)
{
- struct vortex_private *vp = (struct vortex_private *)dev->priv;
+ struct corkscrew_private *vp =
+ (struct corkscrew_private *) dev->priv;
int ioaddr = dev->base_addr;
int i;
- dev->start = 0;
- dev->tbusy = 1;
+ netif_stop_queue(dev);
- if (vortex_debug > 1) {
- printk("%s: vortex_close() status %4.4x, Tx status %2.2x.\n",
- dev->name, inw(ioaddr + EL3_STATUS), inb(ioaddr + TxStatus));
- printk("%s: vortex close stats: rx_nocopy %d rx_copy %d"
- " tx_queued %d.\n",
- dev->name, rx_nocopy, rx_copy, queued_packet);
+ if (corkscrew_debug > 1) {
+ printk("%s: corkscrew_close() status %4.4x, Tx status %2.2x.\n",
+ dev->name, inw(ioaddr + EL3_STATUS),
+ inb(ioaddr + TxStatus));
+ printk("%s: corkscrew close stats: rx_nocopy %d rx_copy %d"
+ " tx_queued %d.\n", dev->name, rx_nocopy, rx_copy,
+ queued_packet);
}
del_timer(&vp->timer);
@@ -1337,28 +1392,20 @@ vortex_close(struct net_device *dev)
/* Turn off thinnet power. Green! */
outw(StopCoax, ioaddr + EL3_CMD);
-#ifdef SA_SHIRQ
free_irq(dev->irq, dev);
-#else
- free_irq(dev->irq);
- irq2dev_map[dev->irq] = 0;
-#endif
outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
update_stats(ioaddr, dev);
- if (vp->full_bus_master_rx) { /* Free Boomerang bus master Rx buffers. */
+ if (vp->full_bus_master_rx) { /* Free Boomerang bus master Rx buffers. */
outl(0, ioaddr + UpListPtr);
for (i = 0; i < RX_RING_SIZE; i++)
if (vp->rx_skbuff[i]) {
-#if LINUX_VERSION_CODE < 0x20100
- vp->rx_skbuff[i]->free = 1;
-#endif
- dev_kfree_skb (vp->rx_skbuff[i]);
+ dev_kfree_skb(vp->rx_skbuff[i]);
vp->rx_skbuff[i] = 0;
}
}
- if (vp->full_bus_master_tx) { /* Free Boomerang bus master Tx buffers. */
+ if (vp->full_bus_master_tx) { /* Free Boomerang bus master Tx buffers. */
outl(0, ioaddr + DownListPtr);
for (i = 0; i < TX_RING_SIZE; i++)
if (vp->tx_skbuff[i]) {
@@ -1372,13 +1419,13 @@ vortex_close(struct net_device *dev)
return 0;
}
-static struct enet_statistics *
-vortex_get_stats(struct net_device *dev)
+static struct enet_statistics *corkscrew_get_stats(struct net_device *dev)
{
- struct vortex_private *vp = (struct vortex_private *)dev->priv;
+ struct corkscrew_private *vp =
+ (struct corkscrew_private *) dev->priv;
unsigned long flags;
- if (dev->start) {
+ if (netif_running(dev)) {
save_flags(flags);
cli();
update_stats(dev->base_addr, dev);
@@ -1396,21 +1443,23 @@ vortex_get_stats(struct net_device *dev)
*/
static void update_stats(int ioaddr, struct net_device *dev)
{
- struct vortex_private *vp = (struct vortex_private *)dev->priv;
+ struct corkscrew_private *vp =
+ (struct corkscrew_private *) dev->priv;
/* Unlike the 3c5x9 we need not turn off stats updates while reading. */
/* Switch to the stats window, and read everything. */
EL3WINDOW(6);
- vp->stats.tx_carrier_errors += inb(ioaddr + 0);
- vp->stats.tx_heartbeat_errors += inb(ioaddr + 1);
- /* Multiple collisions. */ inb(ioaddr + 2);
- vp->stats.collisions += inb(ioaddr + 3);
- vp->stats.tx_window_errors += inb(ioaddr + 4);
- vp->stats.rx_fifo_errors += inb(ioaddr + 5);
- vp->stats.tx_packets += inb(ioaddr + 6);
- vp->stats.tx_packets += (inb(ioaddr + 9)&0x30) << 4;
- /* Rx packets */ inb(ioaddr + 7); /* Must read to clear */
- /* Tx deferrals */ inb(ioaddr + 8);
+ vp->stats.tx_carrier_errors += inb(ioaddr + 0);
+ vp->stats.tx_heartbeat_errors += inb(ioaddr + 1);
+ /* Multiple collisions. */ inb(ioaddr + 2);
+ vp->stats.collisions += inb(ioaddr + 3);
+ vp->stats.tx_window_errors += inb(ioaddr + 4);
+ vp->stats.rx_fifo_errors += inb(ioaddr + 5);
+ vp->stats.tx_packets += inb(ioaddr + 6);
+ vp->stats.tx_packets += (inb(ioaddr + 9) & 0x30) << 4;
+ /* Rx packets */ inb(ioaddr + 7);
+ /* Must read to clear */
+ /* Tx deferrals */ inb(ioaddr + 8);
/* Don't bother with register 9, an extension of registers 6&7.
If we do use the 6&7 values the atomic update assumption above
is invalid. */
@@ -1429,18 +1478,18 @@ static void update_stats(int ioaddr, struct net_device *dev)
The Vortex chip has no documented multicast filter, so the only
multicast setting is to receive all multicast frames. At least
the chip has a very clean way to set the mode, unlike many others. */
-static void
-set_rx_mode(struct net_device *dev)
+static void set_rx_mode(struct net_device *dev)
{
int ioaddr = dev->base_addr;
short new_mode;
if (dev->flags & IFF_PROMISC) {
- if (vortex_debug > 3)
- printk("%s: Setting promiscuous mode.\n", dev->name);
- new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast|RxProm;
- } else if ((dev->mc_list) || (dev->flags & IFF_ALLMULTI)) {
- new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast;
+ if (corkscrew_debug > 3)
+ printk("%s: Setting promiscuous mode.\n",
+ dev->name);
+ new_mode = SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm;
+ } else if ((dev->mc_list) || (dev->flags & IFF_ALLMULTI)) {
+ new_mode = SetRxFilter | RxStation | RxMulticast | RxBroadcast;
} else
new_mode = SetRxFilter | RxStation | RxBroadcast;
@@ -1448,24 +1497,26 @@ set_rx_mode(struct net_device *dev)
}
#ifdef MODULE
-void
-cleanup_module(void)
+void cleanup_module(void)
{
struct net_device *next_dev;
/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
- while (root_vortex_dev) {
- next_dev = ((struct vortex_private *)root_vortex_dev->priv)->next_module;
- if (root_vortex_dev->dma)
- free_dma(root_vortex_dev->dma);
- unregister_netdev(root_vortex_dev);
- outw(TotalReset, root_vortex_dev->base_addr + EL3_CMD);
- release_region(root_vortex_dev->base_addr, CORKSCREW_TOTAL_SIZE);
- kfree(root_vortex_dev);
- root_vortex_dev = next_dev;
+ while (root_corkscrew_dev) {
+ next_dev =
+ ((struct corkscrew_private *) root_corkscrew_dev->
+ priv)->next_module;
+ if (root_corkscrew_dev->dma)
+ free_dma(root_corkscrew_dev->dma);
+ unregister_netdev(root_corkscrew_dev);
+ outw(TotalReset, root_corkscrew_dev->base_addr + EL3_CMD);
+ release_region(root_corkscrew_dev->base_addr,
+ CORKSCREW_TOTAL_SIZE);
+ kfree(root_corkscrew_dev);
+ root_corkscrew_dev = next_dev;
}
}
-#endif /* MODULE */
+#endif /* MODULE */
/*
* Local variables:
diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c
index fe150fac5..9e3f72b33 100644
--- a/drivers/net/3c523.c
+++ b/drivers/net/3c523.c
@@ -297,7 +297,7 @@ static int elmc_open(struct net_device *dev)
alloc586(dev);
init586(dev);
startrecv586(dev);
- netif_wake_queue(dev);
+ netif_start_queue(dev);
MOD_INC_USE_COUNT;
return 0; /* most done by init */
}
@@ -869,7 +869,7 @@ static void elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
if (dev == NULL) {
printk(KERN_ERR "elmc-interrupt: irq %d for unknown device.\n", (int) -(((struct pt_regs *) reg_ptr)->orig_eax + 2));
return;
- } else if (!test_bit(LINK_STATE_START, &dev->state)) {
+ } else if (!netif_running(dev)) {
/* The 3c523 has this habit of generating interrupts during the
reset. I'm not sure if the ni52 has this same problem, but it's
really annoying if we haven't finished initializing it. I was
@@ -902,7 +902,7 @@ static void elmc_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
#ifndef NO_NOPCOMMANDS
if (stat & STAT_CNA) {
/* CU went 'not ready' */
- if (test_bit(LINK_STATE_START, &dev->state)) {
+ if (netif_running(dev->state)) {
printk(KERN_WARNING "%s: oops! CU has left active state. stat: %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status);
}
}
diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c
index 9cce2fa76..dab3f99b9 100644
--- a/drivers/net/3c527.c
+++ b/drivers/net/3c527.c
@@ -902,7 +902,7 @@ static int mc32_open(struct net_device *dev)
mc32_rx_begin(dev);
mc32_tx_begin(dev);
- netif_wake_queue(dev);
+ netif_start_queue(dev);
MOD_INC_USE_COUNT;
return 0;
@@ -1156,7 +1156,7 @@ static void mc32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
basically a FIFO queue of buffers matching
the card ring */
lp->net_stats.tx_bytes+=lp->tx_skb[lp->tx_skb_top]->len;
- dev_kfree_skb(lp->tx_skb[lp->tx_skb_top]);
+ dev_kfree_skb_irq(lp->tx_skb[lp->tx_skb_top]);
lp->tx_skb[lp->tx_skb_top]=NULL;
lp->tx_skb_top++;
lp->tx_skb_top&=(TX_RING_MAX-1);
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 4710b1d37..839c15ebc 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -14,6 +14,7 @@
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
Version history:
+ 0.99H+lk0.9 - David S. Miller - softnet, PCI DMA updates
0.99H+lk1.0 - Jeff Garzik <jgarzik@mandrakesoft.com>
Remove compatibility defines for kernel versions < 2.2.x.
Update for new 2.3.x module interface
@@ -402,8 +403,6 @@ struct vortex_private {
struct sk_buff* rx_skbuff[RX_RING_SIZE];
struct sk_buff* tx_skbuff[TX_RING_SIZE];
struct net_device *next_module;
- void *priv_addr;
- dma_addr_t ring_dma;
unsigned int cur_rx, cur_tx; /* The next free ring entry */
unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
struct net_device_stats stats;
@@ -768,13 +767,11 @@ static struct net_device *vortex_probe1(struct pci_dev *pdev,
vp->pci_devfn = pdev == NULL ? 0 : pdev->devfn;
vp->pdev = pdev;
- vp->priv_addr = pci_alloc_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE
- + sizeof(struct boom_tx_desc) * TX_RING_SIZE
- + 15, &vp->ring_dma);
- /* Make sure rings are 16 byte aligned. */
- vp->rx_ring = (void *)(((long)vp->priv_addr + 15) & ~15);
+ /* Makes sure rings are at least 16 byte aligned. */
+ vp->rx_ring = pci_alloc_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE
+ + sizeof(struct boom_tx_desc) * TX_RING_SIZE,
+ &vp->rx_ring_dma);
vp->tx_ring = (struct boom_tx_desc *)(vp->rx_ring + RX_RING_SIZE);
- vp->rx_ring_dma = (vp->ring_dma + 15) & ~15;
vp->tx_ring_dma = vp->rx_ring_dma + sizeof(struct boom_rx_desc) * RX_RING_SIZE;
/* The lower four bits are the media type. */
@@ -1088,7 +1085,7 @@ vortex_open(struct net_device *dev)
break; /* Bad news! */
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- vp->rx_ring[i].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->tail, PKT_BUF_SZ));
+ vp->rx_ring[i].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE));
}
/* Wrap the ring. */
vp->rx_ring[i-1].next = cpu_to_le32(vp->rx_ring_dma);
@@ -1410,7 +1407,7 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (vp->bus_master) {
/* Set the bus-master controller to transfer the packet. */
int len = (skb->len + 3) & ~3;
- outl(vp->tx_skb_dma = pci_map_single(vp->pdev, skb->data, len), ioaddr + Wn7_MasterAddr);
+ outl(vp->tx_skb_dma = pci_map_single(vp->pdev, skb->data, len, PCI_DMA_TODEVICE), ioaddr + Wn7_MasterAddr);
outw(len, ioaddr + Wn7_MasterLen);
vp->tx_skb = skb;
outw(StartDMADown, ioaddr + EL3_CMD);
@@ -1482,7 +1479,7 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
vp->tx_skbuff[entry] = skb;
vp->tx_ring[entry].next = 0;
- vp->tx_ring[entry].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->data, skb->len));
+ vp->tx_ring[entry].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->data, skb->len, PCI_DMA_TODEVICE));
vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG);
vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
@@ -1562,7 +1559,7 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (vp->tx_skbuff[entry]) {
struct sk_buff *skb = vp->tx_skbuff[entry];
- pci_unmap_single(vp->pdev, le32_to_cpu(vp->tx_ring[entry].addr), skb->len);
+ pci_unmap_single(vp->pdev, le32_to_cpu(vp->tx_ring[entry].addr), skb->len, PCI_DMA_TODEVICE);
dev_kfree_skb_irq(vp->tx_skbuff[entry]);
vp->tx_skbuff[entry] = 0;
}
@@ -1579,7 +1576,7 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (status & DMADone) {
if (inw(ioaddr + Wn7_MasterStatus) & 0x1000) {
outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
- pci_unmap_single(vp->pdev, vp->tx_skb_dma, (vp->tx_skb->len + 3) & ~3);
+ pci_unmap_single(vp->pdev, vp->tx_skb_dma, (vp->tx_skb->len + 3) & ~3, PCI_DMA_TODEVICE);
dev_kfree_skb_irq(vp->tx_skb); /* Release the transfered buffer */
if (inw(ioaddr + TxFree) > 1536) {
netif_wake_queue(dev);
@@ -1660,13 +1657,13 @@ static int vortex_rx(struct net_device *dev)
if (vp->bus_master &&
! (inw(ioaddr + Wn7_MasterStatus) & 0x8000)) {
dma_addr_t dma = pci_map_single(vp->pdev, skb_put(skb, pkt_len),
- pkt_len);
+ pkt_len, PCI_DMA_FROMDEVICE);
outl(dma, ioaddr + Wn7_MasterAddr);
outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
outw(StartDMAUp, ioaddr + EL3_CMD);
while (inw(ioaddr + Wn7_MasterStatus) & 0x8000)
;
- pci_unmap_single(vp->pdev, dma, pkt_len);
+ pci_unmap_single(vp->pdev, dma, pkt_len, PCI_DMA_FROMDEVICE);
} else {
insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len),
(pkt_len + 3) >> 2);
@@ -1740,7 +1737,7 @@ boomerang_rx(struct net_device *dev)
&& (skb = dev_alloc_skb(pkt_len + 2)) != 0) {
skb->dev = dev;
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- pci_dma_sync_single(vp->pdev, dma, PKT_BUF_SZ);
+ pci_dma_sync_single(vp->pdev, dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
/* 'skb_put()' points to the start of sk_buff data area. */
memcpy(skb_put(skb, pkt_len),
vp->rx_skbuff[entry]->tail,
@@ -1751,7 +1748,7 @@ boomerang_rx(struct net_device *dev)
skb = vp->rx_skbuff[entry];
vp->rx_skbuff[entry] = NULL;
skb_put(skb, pkt_len);
- pci_unmap_single(vp->pdev, dma, PKT_BUF_SZ);
+ pci_unmap_single(vp->pdev, dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
rx_nocopy++;
}
skb->protocol = eth_type_trans(skb, dev);
@@ -1780,7 +1777,7 @@ boomerang_rx(struct net_device *dev)
break; /* Bad news! */
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- vp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->tail, PKT_BUF_SZ));
+ vp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE));
vp->rx_skbuff[entry] = skb;
}
vp->rx_ring[entry].status = 0; /* Clear complete bit. */
@@ -1828,7 +1825,7 @@ vortex_close(struct net_device *dev)
outl(0, ioaddr + UpListPtr);
for (i = 0; i < RX_RING_SIZE; i++)
if (vp->rx_skbuff[i]) {
- pci_unmap_single(vp->pdev, le32_to_cpu(vp->rx_ring[i].addr), PKT_BUF_SZ);
+ pci_unmap_single(vp->pdev, le32_to_cpu(vp->rx_ring[i].addr), PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
DEV_FREE_SKB(vp->rx_skbuff[i]);
vp->rx_skbuff[i] = 0;
}
@@ -1839,7 +1836,7 @@ vortex_close(struct net_device *dev)
if (vp->tx_skbuff[i]) {
struct sk_buff *skb = vp->tx_skbuff[i];
- pci_unmap_single(vp->pdev, le32_to_cpu(vp->tx_ring[i].addr), skb->len);
+ pci_unmap_single(vp->pdev, le32_to_cpu(vp->tx_ring[i].addr), skb->len, PCI_DMA_TODEVICE);
DEV_FREE_SKB(skb);
vp->tx_skbuff[i] = 0;
}
@@ -1855,7 +1852,7 @@ static struct net_device_stats *vortex_get_stats(struct net_device *dev)
struct vortex_private *vp = (struct vortex_private *)dev->priv;
unsigned long flags;
- if (test_bit(LINK_STATE_START, &dev->state)) {
+ if (netif_running(dev)) {
save_flags(flags);
cli();
update_stats(dev->base_addr, dev);
@@ -2061,7 +2058,7 @@ static void __exit vortex_cleanup_module (void)
kfree(root_vortex_dev);
pci_free_consistent(vp->pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE
+ sizeof(struct boom_tx_desc) * TX_RING_SIZE
- + 15, vp->priv_addr, vp->ring_dma);
+ + 15, vp->rx_ring, vp->rx_ring_dma);
kfree(vp);
root_vortex_dev = next_dev;
}
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
new file mode 100644
index 000000000..c2eceb8db
--- /dev/null
+++ b/drivers/net/8139too.c
@@ -0,0 +1,1879 @@
+/*
+
+ 8139too.c: A RealTek RTL-8139 Fast Ethernet driver for Linux.
+
+ Copyright 2000 Jeff Garzik <jgarzik@mandrakesoft.com>
+ Originally: Written 1997-1999 by Donald Becker.
+
+ This software may be used and distributed according to the terms
+ of the GNU Public License, incorporated herein by reference.
+
+ Contributors:
+
+ Donald Becker - he wrote the original driver, kudos to him!
+ (but please don't e-mail him for support, this isn't his driver)
+
+ Tigran Aivazian - bug fixes, skbuff free cleanup
+
+ Martin Mares - suggestions for PCI cleanup
+
+ David S. Miller - PCI DMA and softnet updates
+
+ Ernst Gill - fixes ported from BSD driver
+
+ Daniel Kobras - identified specific locations of
+ posted MMIO write bugginess
+
+-----------------------------------------------------------------------------
+
+ Theory of Operation
+
+I. Board Compatibility
+
+This device driver is designed for the RealTek RTL8139 series, the RealTek
+Fast Ethernet controllers for PCI and CardBus. This chip is used on many
+low-end boards, sometimes with its markings changed.
+
+
+II. Board-specific settings
+
+PCI bus devices are configured by the system at boot time, so no jumpers
+need to be set on the board. The system BIOS will assign the
+PCI INTA signal to a (preferably otherwise unused) system IRQ line.
+
+III. Driver operation
+
+IIIa. Rx Ring buffers
+
+The receive unit uses a single linear ring buffer rather than the more
+common (and more efficient) descriptor-based architecture. Incoming frames
+are sequentially stored into the Rx region, and the host copies them into
+skbuffs.
+
+Comment: While it is theoretically possible to process many frames in place,
+any delay in Rx processing would cause us to drop frames. More importantly,
+the Linux protocol stack is not designed to operate in this manner.
+
+IIIb. Tx operation
+
+The RTL8139 uses a fixed set of four Tx descriptors in register space.
+In a stunningly bad design choice, Tx frames must be 32 bit aligned. Linux
+aligns the IP header on word boundaries, and 14 byte ethernet header means
+that almost all frames will need to be copied to an alignment buffer.
+
+IVb. References
+
+http://www.realtek.com.tw/cn/cn.html
+http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
+
+IVc. Errata
+
+1) The RTL-8139 has a serious problem with motherboards which do
+posted MMIO writes to PCI space. This driver works around the
+problem by having an MMIO register write be immediately followed by
+an MMIO register read.
+
+2) The RTL-8129 is only supported in Donald Becker's rtl8139 driver.
+
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <asm/io.h>
+
+
+#define RTL8139_VERSION "0.9.3"
+#define RTL8139_MODULE_NAME "8139too"
+#define RTL8139_DRIVER_NAME RTL8139_MODULE_NAME " Fast Ethernet driver " RTL8139_VERSION
+#define PFX RTL8139_MODULE_NAME ": "
+
+#undef RTL8139_DEBUG /* define to 1 to enable copious debugging info */
+
+#ifdef RTL8139_DEBUG
+/* note: prints function name for you */
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#define RTL8139_NDEBUG 0 /* define to 1 to disable lightweight runtime checks */
+#if RTL8139_NDEBUG
+#define assert(expr)
+#else
+#define assert(expr) \
+ if(!(expr)) { \
+ printk( "Assertion failed! %s,%s,%s,line=%d\n", \
+ #expr,__FILE__,__FUNCTION__,__LINE__); \
+ }
+#endif
+
+#define arraysize(x) (sizeof(x)/sizeof(*(x)))
+
+
+#ifndef PCI_GET_DRIVER_DATA
+ #define PCI_GET_DRIVER_DATA(pdev) ((pdev)->driver_data)
+ #define PCI_SET_DRIVER_DATA(pdev,data) (((pdev)->driver_data) = (data))
+#endif /* PCI_GET_DRIVER_DATA */
+
+
+/* A few user-configurable values. */
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static int max_interrupt_work = 20;
+
+/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
+ The RTL chips use a 64 element hash table based on the Ethernet CRC. */
+static int multicast_filter_limit = 32;
+
+/* Size of the in-memory receive ring. */
+#define RX_BUF_LEN_IDX 2 /* 0==8K, 1==16K, 2==32K, 3==64K */
+#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX)
+/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */
+#define TX_BUF_SIZE 1536
+
+/* PCI Tuning Parameters
+ Threshold is bytes transferred to chip before transmission starts. */
+#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */
+
+/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024. */
+#define RX_FIFO_THRESH 4 /* Rx buffer level before first PCI xfer. */
+#define RX_DMA_BURST 4 /* Maximum PCI burst, '4' is 256 bytes */
+#define TX_DMA_BURST 4 /* Calculate as 16<<val. */
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT (6*HZ)
+
+
+enum {
+ HAS_CHIP_XCVR = 0x020000,
+ HAS_LNK_CHNG = 0x040000,
+};
+
+#define RTL_IO_SIZE 0x80
+
+#define RTL8139_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG
+
+typedef enum {
+ RTL8139,
+ RTL8139_CB,
+ SMC1211TX,
+ /*MPX5030,*/
+ DELTA8139,
+ ADDTRON8139,
+} chip_t;
+
+
+static struct {
+ chip_t chip;
+ const char *name;
+} chip_info[] __devinitdata = {
+ { RTL8139, "RealTek RTL8139 Fast Ethernet"},
+ { RTL8139_CB, "RealTek RTL8139B PCI/CardBus"},
+ { SMC1211TX, "SMC1211TX EZCard 10/100 (RealTek RTL8139)"},
+/* { MPX5030, "Accton MPX5030 (RealTek RTL8139)"},*/
+ { DELTA8139, "Delta Electronics 8139 10/100BaseTX"},
+ { ADDTRON8139, "Addtron Technolgy 8139 10/100BaseTX"},
+ {0,},
+};
+
+
+static struct pci_device_id rtl8139_pci_tbl[] __devinitdata = {
+ {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
+ {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139_CB },
+ {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMC1211TX },
+/* {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MPX5030 },*/
+ {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DELTA8139 },
+ {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ADDTRON8139 },
+ {0,},
+};
+MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl);
+
+
+/* The rest of these values should never change. */
+#define NUM_TX_DESC 4 /* Number of Tx descriptor registers. */
+
+/* Symbolic offsets to registers. */
+enum RTL8139_registers {
+ MAC0 = 0, /* Ethernet hardware address. */
+ MAR0 = 8, /* Multicast filter. */
+ TxStatus0 = 0x10, /* Transmit status (Four 32bit registers). */
+ TxAddr0 = 0x20, /* Tx descriptors (also four 32bit). */
+ RxBuf = 0x30,
+ RxEarlyCnt = 0x34,
+ RxEarlyStatus = 0x36,
+ ChipCmd = 0x37,
+ RxBufPtr = 0x38,
+ RxBufAddr = 0x3A,
+ IntrMask = 0x3C,
+ IntrStatus = 0x3E,
+ TxConfig = 0x40,
+ RxConfig = 0x44,
+ Timer = 0x48, /* A general-purpose counter. */
+ RxMissed = 0x4C, /* 24 bits valid, write clears. */
+ Cfg9346 = 0x50,
+ Config0 = 0x51,
+ Config1 = 0x52,
+ FlashReg = 0x54,
+ GPPinData = 0x58,
+ GPPinDir = 0x59,
+ Config4 = 0x5A, /* absent on RTL-8139A */
+ HltClk = 0x5B,
+ MultiIntr = 0x5C,
+ TxSummary = 0x60,
+ BasicModeCtrl = 0x62,
+ BasicModeStatus = 0x64,
+ NWayAdvert = 0x66,
+ NWayLPAR = 0x68,
+ NWayExpansion = 0x6A,
+ /* Undocumented registers, but required for proper operation. */
+ FIFOTMS = 0x70, /* FIFO Control and test. */
+ CSCR = 0x74, /* Chip Status and Configuration Register. */
+ PARA78 = 0x78,
+ PARA7c = 0x7c, /* Magic transceiver parameter register. */
+};
+
+enum ChipCmdBits {
+ CmdReset = 0x10,
+ CmdRxEnb = 0x08,
+ CmdTxEnb = 0x04,
+ RxBufEmpty = 0x01,
+};
+
+/* Interrupt register bits, using my own meaningful names. */
+enum IntrStatusBits {
+ PCIErr = 0x8000,
+ PCSTimeout = 0x4000,
+ RxFIFOOver = 0x40,
+ RxUnderrun = 0x20,
+ RxOverflow = 0x10,
+ TxErr = 0x08,
+ TxOK = 0x04,
+ RxErr = 0x02,
+ RxOK = 0x01,
+};
+enum TxStatusBits {
+ TxHostOwns = 0x2000,
+ TxUnderrun = 0x4000,
+ TxStatOK = 0x8000,
+ TxOutOfWindow = 0x20000000,
+ TxAborted = 0x40000000,
+ TxCarrierLost = 0x80000000,
+};
+enum RxStatusBits {
+ RxMulticast = 0x8000,
+ RxPhysical = 0x4000,
+ RxBroadcast = 0x2000,
+ RxBadSymbol = 0x0020,
+ RxRunt = 0x0010,
+ RxTooLong = 0x0008,
+ RxCRCErr = 0x0004,
+ RxBadAlign = 0x0002,
+ RxStatusOK = 0x0001,
+};
+
+/* Bits in RxConfig. */
+enum rx_mode_bits {
+ AcceptErr = 0x20,
+ AcceptRunt = 0x10,
+ AcceptBroadcast = 0x08,
+ AcceptMulticast = 0x04,
+ AcceptMyPhys = 0x02,
+ AcceptAllPhys = 0x01,
+};
+
+/* Bits in Config1 */
+enum Config1Bits {
+ Cfg1_PM_Enable = 0x01,
+ Cfg1_VPD_Enable = 0x02,
+ Cfg1_PIO = 0x04,
+ Cfg1_MMIO = 0x08,
+ Cfg1_LWAKE = 0x10,
+ Cfg1_Driver_Load = 0x20,
+ Cfg1_LED0 = 0x40,
+ Cfg1_LED1 = 0x80,
+};
+
+/* Twister tuning parameters from RealTek.
+ Completely undocumented, but required to tune bad links. */
+enum CSCRBits {
+ CSCR_LinkOKBit = 0x0400,
+ CSCR_LinkChangeBit = 0x0800,
+ CSCR_LinkStatusBits = 0x0f000,
+ CSCR_LinkDownOffCmd = 0x003c0,
+ CSCR_LinkDownCmd = 0x0f3c0,
+};
+#define PARA78_default 0x78fa8388
+#define PARA7c_default 0xcb38de43 /* param[0][3] */
+#define PARA7c_xxx 0xcb38de43
+static const unsigned long param[4][4] = {
+ {0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43},
+ {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83},
+ {0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83},
+ {0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83}
+};
+
+struct ring_info {
+ struct sk_buff *skb;
+ dma_addr_t mapping;
+};
+
+
+#define PRIV_ALIGN 15 /* Required alignment mask */
+struct rtl8139_private {
+ chip_t chip;
+ void *mmio_addr;
+ spinlock_t lock;
+ int drv_flags;
+ struct pci_dev *pci_dev;
+ struct net_device_stats stats;
+ struct timer_list timer; /* Media selection timer. */
+ unsigned char *rx_ring;
+ unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */
+ unsigned int cur_tx, dirty_tx, tx_flag;
+ /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+ struct ring_info tx_info[NUM_TX_DESC];
+ unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */
+ unsigned char *tx_bufs; /* Tx bounce buffer region. */
+ dma_addr_t rx_ring_dma;
+ dma_addr_t tx_bufs_dma;
+ char phys[4]; /* MII device addresses. */
+ char twistie, twist_row, twist_col; /* Twister tune state. */
+ unsigned int full_duplex:1; /* Full-duplex operation requested. */
+ unsigned int duplex_lock:1;
+ unsigned int default_port:4; /* Last dev->if_port value. */
+ unsigned int media2:4; /* Secondary monitored media port. */
+ unsigned int medialock:1; /* Don't sense media type. */
+ unsigned int mediasense:1; /* Media sensing in progress. */
+};
+
+MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");
+MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver");
+MODULE_PARM (multicast_filter_limit, "i");
+MODULE_PARM (max_interrupt_work, "i");
+MODULE_PARM (debug, "i");
+
+static int read_eeprom (void *ioaddr, int location, int addr_len);
+static int rtl8139_open (struct net_device *dev);
+static int mdio_read (struct net_device *dev, int phy_id, int location);
+static void mdio_write (struct net_device *dev, int phy_id, int location,
+ int val);
+static void rtl8139_timer (unsigned long data);
+static void rtl8139_tx_timeout (struct net_device *dev);
+static void rtl8139_init_ring (struct net_device *dev);
+static int rtl8139_start_xmit (struct sk_buff *skb,
+ struct net_device *dev);
+static void rtl8139_interrupt (int irq, void *dev_instance,
+ struct pt_regs *regs);
+static int rtl8139_close (struct net_device *dev);
+static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
+static struct net_device_stats *rtl8139_get_stats (struct net_device *dev);
+static inline u32 ether_crc (int length, unsigned char *data);
+static void rtl8139_set_rx_mode (struct net_device *dev);
+
+/* write MMIO register, with flush */
+/* Flush avoids rtl8139 bug w/ posted MMIO writes */
+#define RTL_W8_F(reg, val8) do { writeb ((val8), ioaddr + (reg)); readb (ioaddr + (reg)); } while (0)
+#define RTL_W16_F(reg, val16) do { writew ((val16), ioaddr + (reg)); readw (ioaddr + (reg)); } while (0)
+#define RTL_W32_F(reg, val32) do { writel ((val32), ioaddr + (reg)); readl (ioaddr + (reg)); } while (0)
+
+
+#if MMIO_FLUSH_AUDIT_COMPLETE
+
+/* write MMIO register */
+#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg))
+#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg))
+#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg))
+
+#else
+
+/* write MMIO register, then flush */
+#define RTL_W8 RTL_W8_F
+#define RTL_W16 RTL_W16_F
+#define RTL_W32 RTL_W32_F
+
+#endif /* MMIO_FLUSH_AUDIT_COMPLETE */
+
+/* read MMIO register */
+#define RTL_R8(reg) readb (ioaddr + (reg))
+#define RTL_R16(reg) readw (ioaddr + (reg))
+#define RTL_R32(reg) readl (ioaddr + (reg))
+
+
+static const u16 rtl8139_intr_mask =
+ PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver |
+ TxErr | TxOK | RxErr | RxOK;
+
+static const unsigned int rtl8139_rx_config =
+ (RX_FIFO_THRESH << 13) |
+ (RX_BUF_LEN_IDX << 11) |
+ (RX_DMA_BURST << 8);
+
+
+static const char * __devinit rtl8139_name_from_chip (chip_t chip)
+{
+ int i;
+
+ for (i = 0; i < arraysize (chip_info); i++)
+ if (chip == chip_info[i].chip)
+ return chip_info[i].name;
+
+ return "unknown";
+}
+
+
+static int __devinit rtl8139_init_pci (struct pci_dev *pdev, void **ioaddr_out)
+{
+ void *ioaddr = NULL;
+ u8 tmp8;
+ int rc;
+ u32 pio_start, pio_end, pio_flags;
+ u32 mmio_start, mmio_end, mmio_flags;
+
+ DPRINTK ("ENTER\n");
+
+ assert (pdev != NULL);
+ assert (ioaddr_out != NULL);
+
+ *ioaddr_out = NULL;
+
+ pio_start = pci_resource_start (pdev, 0);
+ pio_end = pci_resource_end (pdev, 0);
+ pio_flags = pci_resource_flags (pdev, 0);
+
+ mmio_start = pci_resource_start (pdev, 1);
+ mmio_end = pci_resource_end (pdev, 1);
+ mmio_flags = pci_resource_flags (pdev, 1);
+
+ /* make sure PCI base addr 0 is PIO */
+ if (pio_start == 0 || pio_end <= pio_start ||
+ (!(pio_flags & IORESOURCE_IO))) {
+ printk (KERN_ERR PFX "no PIO resource, aborting\n");
+ return -ENODEV;
+ }
+
+ /* make sure PCI base addr 1 is MMIO */
+ if (mmio_start == 0 || mmio_end <= mmio_start ||
+ (!(mmio_flags & IORESOURCE_MEM))) {
+ printk (KERN_ERR PFX "no MMIO resource, aborting\n");
+ return -ENODEV;
+ }
+
+ /* make sure our PIO region in PCI space is available */
+ if (!request_region (pio_start, RTL_IO_SIZE, RTL8139_MODULE_NAME)) {
+ printk (KERN_ERR PFX "no I/O resource available, aborting\n");
+ return -EBUSY;
+ }
+
+ /* make sure our MMIO region in PCI space is available */
+ if (!request_mem_region (mmio_start, RTL_IO_SIZE, RTL8139_MODULE_NAME)) {
+ release_region (pio_start, RTL_IO_SIZE);
+ printk (KERN_ERR PFX "no mem resource available, aborting\n");
+ return -EBUSY;
+ }
+
+ /* enable device (incl. PCI PM wakeup), and bus-mastering */
+ pci_enable_device (pdev);
+ pci_set_master (pdev);
+
+ /* ioremap MMIO region */
+ ioaddr = ioremap (mmio_start, RTL_IO_SIZE);
+ if (ioaddr == NULL) {
+ printk (KERN_ERR PFX "cannot remap MMIO, aborting\n");
+ rc = -EIO;
+ goto err_out;
+ }
+
+ /* Bring the chip out of low-power mode. */
+ RTL_W8 (Config1, 0x00);
+
+ /* make sure chip thinks PIO and MMIO are enabled */
+ tmp8 = RTL_R8 (Config1);
+ if ((tmp8 & Cfg1_PIO) == 0) {
+ printk (KERN_ERR PFX "PIO not enabled, Cfg1=%02X, aborting\n", tmp8);
+ rc = -EIO;
+ goto err_out;
+ }
+ if ((tmp8 & Cfg1_MMIO) == 0) {
+ printk (KERN_ERR PFX "MMIO not enabled, Cfg1=%02X, aborting\n", tmp8);
+ rc = -EIO;
+ goto err_out;
+ }
+
+ /* sanity checks -- ensure PIO and MMIO registers agree */
+ assert (inb (pio_start+Config0) == RTL_R8 (Config0));
+ assert (inb (pio_start+Config1) == RTL_R8 (Config1));
+ assert (inb (pio_start+TxConfig) == RTL_R8 (TxConfig));
+ assert (inb (pio_start+RxConfig) == RTL_R8 (RxConfig));
+
+ DPRINTK ("EXIT, returning 0\n");
+ *ioaddr_out = ioaddr;
+ return 0;
+
+err_out:
+ if (ioaddr)
+ iounmap (ioaddr);
+ release_region (pio_start, RTL_IO_SIZE);
+ release_mem_region (mmio_start, RTL_IO_SIZE);
+ DPRINTK ("EXIT, returning %d\n", rc);
+ return rc;
+}
+
+
+static int __devinit rtl8139_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct net_device *dev;
+ struct rtl8139_private *tp;
+ int i, addr_len, option = -1;
+ void *ioaddr = NULL;
+
+ DPRINTK ("ENTER\n");
+
+ assert (pdev != NULL);
+ assert (ent != NULL);
+
+ i = rtl8139_init_pci (pdev, &ioaddr);
+ if (i < 0) {
+ DPRINTK ("EXIT, returning %d\n", i);
+ return i;
+ }
+
+ assert (ioaddr != NULL);
+
+ /* dev zeroed in init_etherdev */
+ dev = init_etherdev (NULL, sizeof (*tp) + PRIV_ALIGN);
+ if (dev == NULL) {
+ iounmap (ioaddr);
+ printk (KERN_ERR PFX "unable to alloc new ethernet\n");
+ DPRINTK ("EXIT, returning -ENOMEM\n");
+ return -ENOMEM;
+ }
+
+ addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6;
+ for (i = 0; i < 3; i++)
+ ((u16 *) (dev->dev_addr))[i] =
+ le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len));
+
+ /* The Rtl8139-specific entries in the device structure. */
+ dev->open = rtl8139_open;
+ dev->hard_start_xmit = rtl8139_start_xmit;
+ dev->stop = rtl8139_close;
+ dev->get_stats = rtl8139_get_stats;
+ dev->set_multicast_list = rtl8139_set_rx_mode;
+ dev->do_ioctl = mii_ioctl;
+ dev->tx_timeout = rtl8139_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
+ dev->irq = pdev->irq;
+ dev->base_addr = pci_resource_start (pdev, 1);
+
+ dev->priv = tp = (void *)
+ (((long)dev->priv + PRIV_ALIGN) & ~PRIV_ALIGN);
+
+ printk (KERN_INFO "%s: %s at 0x%lx, IRQ %d, "
+ "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
+ dev->name, rtl8139_name_from_chip(ent->driver_data),
+ dev->base_addr, dev->irq,
+ dev->dev_addr[0], dev->dev_addr[1],
+ dev->dev_addr[2], dev->dev_addr[3],
+ dev->dev_addr[4], dev->dev_addr[5]);
+
+ /* tp zeroed in init_etherdev */
+ tp->drv_flags = PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER | RTL8139_CAPS;
+ tp->pci_dev = pdev;
+ tp->chip = ent->driver_data;
+ tp->mmio_addr = ioaddr;
+ tp->lock = SPIN_LOCK_UNLOCKED;
+
+ PCI_SET_DRIVER_DATA (pdev, dev);
+
+ tp->phys[0] = 32;
+
+ /* Put the chip into low-power mode. */
+ RTL_W8 (Cfg9346, 0xC0);
+ RTL_W8 (Config1, 0x03); /* Enable PM & PCI VPD */
+ RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */
+
+ /* The lower four bits are the media type. */
+ if (option > 0) {
+ tp->full_duplex = (option & 0x200) ? 1 : 0;
+ tp->default_port = option & 15;
+ if (tp->default_port)
+ tp->medialock = 1;
+ }
+
+ if (tp->full_duplex) {
+ printk (KERN_INFO
+ "%s: Media type forced to Full Duplex.\n",
+ dev->name);
+ mdio_write (dev, tp->phys[0], 4, 0x141);
+ tp->duplex_lock = 1;
+ }
+
+ DPRINTK ("EXIT - returning 0\n");
+ return 0;
+}
+
+
+static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
+{
+ struct net_device *dev = PCI_GET_DRIVER_DATA (pdev);
+ struct rtl8139_private *np;
+
+ DPRINTK ("ENTER\n");
+
+ assert (dev != NULL);
+
+ np = (struct rtl8139_private *) (dev->priv);
+ assert (np != NULL);
+
+ unregister_netdev (dev);
+
+ iounmap (np->mmio_addr);
+ release_region (pci_resource_start (pdev, 0), RTL_IO_SIZE);
+ release_mem_region (pci_resource_start (pdev, 1), RTL_IO_SIZE);
+
+#ifndef RTL8139_NDEBUG
+ /* poison memory before freeing */
+ memset (dev, 0xC0,
+ sizeof (struct net_device) +
+ sizeof (struct rtl8139_private) +
+ PRIV_ALIGN);
+#endif
+
+ kfree (dev);
+
+ DPRINTK ("EXIT\n");
+}
+
+
+/* Serial EEPROM section. */
+
+/* EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */
+#define EE_CS 0x08 /* EEPROM chip select. */
+#define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */
+#define EE_WRITE_0 0x00
+#define EE_WRITE_1 0x02
+#define EE_DATA_READ 0x01 /* EEPROM chip data out. */
+#define EE_ENB (0x80 | EE_CS)
+
+/* Delay between EEPROM clock transitions.
+ No extra delay is needed with 33Mhz PCI, but 66Mhz may change this.
+ */
+
+#define eeprom_delay() readl(ee_addr)
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD (5)
+#define EE_READ_CMD (6)
+#define EE_ERASE_CMD (7)
+
+static int __devinit read_eeprom (void *ioaddr, int location, int addr_len)
+{
+ int i;
+ unsigned retval = 0;
+ void *ee_addr = ioaddr + Cfg9346;
+ int read_cmd = location | (EE_READ_CMD << addr_len);
+
+ DPRINTK ("ENTER\n");
+
+ writeb (EE_ENB & ~EE_CS, ee_addr);
+ writeb (EE_ENB, ee_addr);
+ eeprom_delay ();
+
+ /* Shift the read command bits out. */
+ for (i = 4 + addr_len; i >= 0; i--) {
+ int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+ writeb (EE_ENB | dataval, ee_addr);
+ eeprom_delay ();
+ writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+ eeprom_delay ();
+ }
+ writeb (EE_ENB, ee_addr);
+ eeprom_delay ();
+
+ for (i = 16; i > 0; i--) {
+ writeb (EE_ENB | EE_SHIFT_CLK, ee_addr);
+ eeprom_delay ();
+ retval =
+ (retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 :
+ 0);
+ writeb (EE_ENB, ee_addr);
+ eeprom_delay ();
+ }
+
+ /* Terminate the EEPROM access. */
+ writeb (~EE_CS, ee_addr);
+ eeprom_delay ();
+
+ DPRINTK ("EXIT - returning %d\n", retval);
+ return retval;
+}
+
+/* MII serial management: mostly bogus for now. */
+/* Read and write the MII management registers using software-generated
+ serial MDIO protocol.
+ The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
+ met by back-to-back PCI I/O cycles, but we insert a delay to avoid
+ "overclocking" issues. */
+#define MDIO_DIR 0x80
+#define MDIO_DATA_OUT 0x04
+#define MDIO_DATA_IN 0x02
+#define MDIO_CLK 0x01
+#define MDIO_WRITE0 (MDIO_DIR)
+#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT)
+
+#define mdio_delay() readb(mdio_addr)
+
+
+static char mii_2_8139_map[8] = {
+ BasicModeCtrl,
+ BasicModeStatus,
+ 0,
+ 0,
+ NWayAdvert,
+ NWayLPAR,
+ NWayExpansion,
+ 0
+};
+
+
+/* Syncronize the MII management interface by shifting 32 one bits out. */
+static void mdio_sync (void *mdio_addr)
+{
+ int i;
+
+ DPRINTK ("ENTER\n");
+
+ for (i = 32; i >= 0; i--) {
+ writeb (MDIO_WRITE1, mdio_addr);
+ mdio_delay ();
+ writeb (MDIO_WRITE1 | MDIO_CLK, mdio_addr);
+ mdio_delay ();
+ }
+
+ DPRINTK ("EXIT\n");
+}
+
+
+static int mdio_read (struct net_device *dev, int phy_id, int location)
+{
+ struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ void *mdio_addr = tp->mmio_addr + Config4;
+ int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+ int retval = 0;
+ int i;
+
+ DPRINTK ("ENTER\n");
+
+ if (phy_id > 31) { /* Really a 8139. Use internal registers. */
+ DPRINTK ("EXIT after directly using 8139 internal regs\n");
+ return location < 8 && mii_2_8139_map[location] ?
+ readw (tp->mmio_addr + mii_2_8139_map[location]) : 0;
+ }
+ mdio_sync (mdio_addr);
+ /* Shift the read command bits out. */
+ for (i = 15; i >= 0; i--) {
+ int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;
+
+ writeb (MDIO_DIR | dataval, mdio_addr);
+ mdio_delay ();
+ writeb (MDIO_DIR | dataval | MDIO_CLK, mdio_addr);
+ mdio_delay ();
+ }
+
+ /* Read the two transition, 16 data, and wire-idle bits. */
+ for (i = 19; i > 0; i--) {
+ writeb (0, mdio_addr);
+ mdio_delay ();
+ retval =
+ (retval << 1) | ((readb (mdio_addr) & MDIO_DATA_IN) ? 1
+ : 0);
+ writeb (MDIO_CLK, mdio_addr);
+ mdio_delay ();
+ }
+
+ DPRINTK ("EXIT, returning %d\n", (retval >> 1) & 0xffff);
+ return (retval >> 1) & 0xffff;
+}
+
+
+static void mdio_write (struct net_device *dev, int phy_id, int location,
+ int value)
+{
+ struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ void *mdio_addr = tp->mmio_addr + Config4;
+ int mii_cmd =
+ (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
+ int i;
+
+ DPRINTK ("ENTER\n");
+
+ if (phy_id > 31) { /* Really a 8139. Use internal registers. */
+ if (location < 8 && mii_2_8139_map[location]) {
+ writew (value,
+ tp->mmio_addr + mii_2_8139_map[location]);
+ readw (tp->mmio_addr + mii_2_8139_map[location]);
+ }
+ DPRINTK ("EXIT after directly using 8139 internal regs\n");
+ return;
+ }
+ mdio_sync (mdio_addr);
+
+ /* Shift the command bits out. */
+ for (i = 31; i >= 0; i--) {
+ int dataval =
+ (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
+ writeb (dataval, mdio_addr);
+ mdio_delay ();
+ writeb (dataval | MDIO_CLK, mdio_addr);
+ mdio_delay ();
+ }
+
+ /* Clear out extra bits. */
+ for (i = 2; i > 0; i--) {
+ writeb (0, mdio_addr);
+ mdio_delay ();
+ writeb (MDIO_CLK, mdio_addr);
+ mdio_delay ();
+ }
+
+ DPRINTK ("EXIT\n");
+}
+
+
+static int rtl8139_open (struct net_device *dev)
+{
+ struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ void *ioaddr = tp->mmio_addr;
+ int i;
+
+ DPRINTK ("ENTER\n");
+
+ MOD_INC_USE_COUNT;
+
+ /* Soft reset the chip. */
+ RTL_W8 (ChipCmd, CmdReset);
+
+ if (request_irq (dev->irq, &rtl8139_interrupt, SA_SHIRQ, dev->name, dev)) {
+ DPRINTK ("EXIT, returning -EBUSY\n");
+ MOD_DEC_USE_COUNT;
+ return -EBUSY;
+ }
+
+ tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_SIZE * NUM_TX_DESC,
+ &tp->tx_bufs_dma);
+ tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_LEN + 16,
+ &tp->rx_ring_dma);
+ if (tp->tx_bufs == NULL || tp->rx_ring == NULL) {
+ free_irq(dev->irq, dev);
+
+ if (tp->tx_bufs)
+ pci_free_consistent(tp->pci_dev, TX_BUF_SIZE * NUM_TX_DESC,
+ tp->tx_bufs, tp->tx_bufs_dma);
+ if (tp->rx_ring)
+ pci_free_consistent(tp->pci_dev, RX_BUF_LEN + 16,
+ tp->rx_ring, tp->rx_ring_dma);
+
+ DPRINTK ("EXIT, returning -ENOMEM\n");
+ MOD_DEC_USE_COUNT;
+ return -ENOMEM;
+
+ }
+
+ rtl8139_init_ring (dev);
+ tp->full_duplex = tp->duplex_lock;
+ tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
+
+ /* Check that the chip has finished the reset. */
+ for (i = 1000; i > 0; i--)
+ if ((RTL_R8 (ChipCmd) & CmdReset) == 0)
+ break;
+
+ RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0)));
+ RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4)));
+
+ /* Must enable Tx/Rx before setting transfer thresholds! */
+ RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
+ RTL_W32 (RxConfig, rtl8139_rx_config);
+ RTL_W32 (TxConfig, (TX_DMA_BURST << 8) | 0x00000000);
+
+ /* Reset N-Way to chipset defaults */
+ RTL_W16 (BasicModeCtrl, (1<<15)|(1<<12)|(1<<9));
+ for (i = 1000; i > 0; i--)
+ if ((RTL_R8 (BasicModeCtrl) & (1<<15)) == 0)
+ break;
+
+ /* Set N-Way to sane defaults */
+ RTL_W16 (FIFOTMS, 0x0000);
+ RTL_W16 (NWayAdvert, (1<<13)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|0x1);
+ RTL_W16 (BasicModeCtrl, (1<<13)|(1<<12)|(1<<9)|(1<<8));
+
+ RTL_W8 (Cfg9346, 0xC0);
+ RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
+ RTL_W8 (Cfg9346, 0x00);
+
+ RTL_W32 (RxBuf, tp->rx_ring_dma);
+
+ /* Start the chip's Tx and Rx process. */
+ RTL_W32 (RxMissed, 0);
+ rtl8139_set_rx_mode (dev);
+
+ RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
+
+ /* Enable all known interrupts by setting the interrupt mask. */
+ RTL_W16 (IntrMask, rtl8139_intr_mask);
+
+ DPRINTK ("%s: rtl8139_open() ioaddr %#lx IRQ %d"
+ " GP Pins %2.2x %s-duplex.\n",
+ dev->name, pci_resource_start (tp->pci_dev, 1),
+ dev->irq, RTL_R8 (GPPinData),
+ tp->full_duplex ? "full" : "half");
+
+ /* Set the timer to switch to check for link beat and perhaps switch
+ to an alternate media type. */
+ init_timer (&tp->timer);
+ tp->timer.expires = jiffies + 3 * HZ;
+ tp->timer.data = (unsigned long) dev;
+ tp->timer.function = &rtl8139_timer;
+ add_timer (&tp->timer);
+
+ netif_start_queue (dev);
+
+ DPRINTK ("EXIT, returning 0\n");
+ return 0;
+}
+
+/* Start the hardware at open or resume. */
+static void rtl8139_hw_start (struct net_device *dev)
+{
+ struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ void *ioaddr = tp->mmio_addr;
+ int i;
+
+ DPRINTK ("ENTER\n");
+
+ /* Soft reset the chip. */
+ RTL_W8 (ChipCmd, CmdReset);
+ /* Check that the chip has finished the reset. */
+ for (i = 1000; i > 0; i--)
+ if ((RTL_R8 (ChipCmd) & CmdReset) == 0)
+ break;
+
+ /* Restore our idea of the MAC address. */
+ RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0)));
+ RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4)));
+
+ /* Hmmm, do these belong here? */
+ RTL_W8 (Cfg9346, 0x00);
+ tp->cur_rx = 0;
+
+ /* Must enable Tx/Rx before setting transfer thresholds! */
+ RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
+ RTL_W32 (RxConfig, rtl8139_rx_config);
+ /* Check this value: the documentation contradicts ifself. Is the
+ IFG correct with bit 28:27 zero, or with |0x03000000 ? */
+ RTL_W32 (TxConfig, (TX_DMA_BURST << 8) | 0x00000000);
+
+ /* Reset N-Way to chipset defaults */
+ RTL_W16 (BasicModeCtrl, (1<<15)|(1<<12)|(1<<9));
+ for (i = 1000; i > 0; i--)
+ if ((RTL_R8 (BasicModeCtrl) & (1<<15)) == 0)
+ break;
+
+ /* Set N-Way to sane defaults */
+ RTL_W16 (FIFOTMS, 0x0000);
+ RTL_W16 (NWayAdvert, (1<<13)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|0x1);
+ RTL_W16 (BasicModeCtrl, (1<<13)|(1<<12)|(1<<9)|(1<<8));
+
+ /* check_duplex() here. */
+ RTL_W8 (Cfg9346, 0xC0);
+ RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
+ RTL_W8 (Cfg9346, 0x00);
+
+ RTL_W32 (RxBuf, tp->rx_ring_dma);
+ /* Start the chip's Tx and Rx process. */
+ RTL_W32 (RxMissed, 0);
+ rtl8139_set_rx_mode (dev);
+ RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
+ /* Enable all known interrupts by setting the interrupt mask. */
+ RTL_W16 (IntrMask, rtl8139_intr_mask);
+
+ netif_start_queue (dev);
+
+ DPRINTK ("EXIT\n");
+}
+
+
+#ifndef RTL_TUNE_TWISTER
+static inline void rtl8139_tune_twister (struct net_device *dev,
+ struct rtl8139_private *tp) {}
+#else
+static void rtl8139_tune_twister (struct net_device *dev,
+ struct rtl8139_private *tp)
+{
+ int linkcase;
+
+ DPRINTK ("ENTER\n");
+
+ /* This is a complicated state machine to configure the "twister" for
+ impedance/echos based on the cable length.
+ All of this is magic and undocumented.
+ */
+ switch (tp->twistie) {
+ case 1:
+ if (RTL_R16 (CSCR) & CSCR_LinkOKBit) {
+ /* We have link beat, let us tune the twister. */
+ RTL_W16 (CSCR, CSCR_LinkDownOffCmd);
+ tp->twistie = 2; /* Change to state 2. */
+ next_tick = HZ / 10;
+ } else {
+ /* Just put in some reasonable defaults for when beat returns. */
+ RTL_W16 (CSCR, CSCR_LinkDownCmd);
+ RTL_W32 (FIFOTMS, 0x20); /* Turn on cable test mode. */
+ RTL_W32 (PARA78, PARA78_default);
+ RTL_W32 (PARA7c, PARA7c_default);
+ tp->twistie = 0; /* Bail from future actions. */
+ }
+ break;
+ case 2:
+ /* Read how long it took to hear the echo. */
+ linkcase = RTL_R16 (CSCR) & CSCR_LinkStatusBits;
+ if (linkcase == 0x7000)
+ tp->twist_row = 3;
+ else if (linkcase == 0x3000)
+ tp->twist_row = 2;
+ else if (linkcase == 0x1000)
+ tp->twist_row = 1;
+ else
+ tp->twist_row = 0;
+ tp->twist_col = 0;
+ tp->twistie = 3; /* Change to state 2. */
+ next_tick = HZ / 10;
+ break;
+ case 3:
+ /* Put out four tuning parameters, one per 100msec. */
+ if (tp->twist_col == 0)
+ RTL_W16 (FIFOTMS, 0);
+ RTL_W32 (PARA7c, param[(int) tp->twist_row]
+ [(int) tp->twist_col]);
+ next_tick = HZ / 10;
+ if (++tp->twist_col >= 4) {
+ /* For short cables we are done.
+ For long cables (row == 3) check for mistune. */
+ tp->twistie =
+ (tp->twist_row == 3) ? 4 : 0;
+ }
+ break;
+ case 4:
+ /* Special case for long cables: check for mistune. */
+ if ((RTL_R16 (CSCR) &
+ CSCR_LinkStatusBits) == 0x7000) {
+ tp->twistie = 0;
+ break;
+ } else {
+ RTL_W32 (PARA7c, 0xfb38de03);
+ tp->twistie = 5;
+ next_tick = HZ / 10;
+ }
+ break;
+ case 5:
+ /* Retune for shorter cable (column 2). */
+ RTL_W32 (FIFOTMS, 0x20);
+ RTL_W32 (PARA78, PARA78_default);
+ RTL_W32 (PARA7c, PARA7c_default);
+ RTL_W32 (FIFOTMS, 0x00);
+ tp->twist_row = 2;
+ tp->twist_col = 0;
+ tp->twistie = 3;
+ next_tick = HZ / 10;
+ break;
+
+ default:
+ /* do nothing */
+ break;
+ }
+
+ DPRINTK ("EXIT\n");
+}
+#endif /* RTL_TUNE_TWISTER */
+
+
+static void rtl8139_timer (unsigned long data)
+{
+ struct net_device *dev = (struct net_device *) data;
+ struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ void *ioaddr = tp->mmio_addr;
+ int next_tick = 60 * HZ;
+ int mii_reg5 = mdio_read (dev, tp->phys[0], 5);
+
+ DPRINTK ("ENTER\n");
+
+ if (!tp->duplex_lock && mii_reg5 != 0xffff) {
+ int duplex = (mii_reg5 & 0x0100)
+ || (mii_reg5 & 0x01C0) == 0x0040;
+ if (tp->full_duplex != duplex) {
+ tp->full_duplex = duplex;
+ printk (KERN_INFO
+ "%s: Setting %s-duplex based on MII #%d link"
+ " partner ability of %4.4x.\n", dev->name,
+ tp->full_duplex ? "full" : "half",
+ tp->phys[0], mii_reg5);
+ RTL_W8 (Cfg9346, 0xC0);
+ RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
+ RTL_W8 (Cfg9346, 0x00);
+ }
+ }
+
+ rtl8139_tune_twister (dev, tp);
+
+ DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n",
+ dev->name, RTL_R16 (NWayLPAR));
+ DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x"
+ " RxStatus %4.4x.\n", dev->name,
+ RTL_R16 (IntrMask),
+ RTL_R16 (IntrStatus),
+ RTL_R32 (RxEarlyStatus));
+ DPRINTK ("%s: Chip config %2.2x %2.2x.\n",
+ dev->name, RTL_R8 (Config0),
+ RTL_R8 (Config1));
+
+ tp->timer.expires = jiffies + next_tick;
+ add_timer (&tp->timer);
+
+ DPRINTK ("EXIT\n");
+}
+
+
+static void rtl8139_tx_timeout (struct net_device *dev)
+{
+ struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ void *ioaddr = tp->mmio_addr;
+ int mii_reg, i;
+
+ DPRINTK ("ENTER\n");
+
+ netif_stop_queue (dev);
+
+ DPRINTK ("%s: Transmit timeout, status %2.2x %4.4x "
+ "media %2.2x.\n", dev->name,
+ RTL_R8 (ChipCmd),
+ RTL_R16 (IntrStatus),
+ RTL_R8 (GPPinData));
+
+ /* Disable interrupts by clearing the interrupt mask. */
+ RTL_W16 (IntrMask, 0x0000);
+ /* Emit info to figure out what went wrong. */
+ printk (KERN_DEBUG
+ "%s: Tx queue start entry %d dirty entry %d.\n",
+ dev->name, tp->cur_tx, tp->dirty_tx);
+ for (i = 0; i < NUM_TX_DESC; i++)
+ printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8x.%s\n",
+ dev->name, i, RTL_R32 (TxStatus0 + (i * 4)),
+ i ==
+ tp->dirty_tx % NUM_TX_DESC ? " (queue head)" : "");
+ printk (KERN_DEBUG "%s: MII #%d registers are:", dev->name,
+ tp->phys[0]);
+ for (mii_reg = 0; mii_reg < 8; mii_reg++)
+ printk (" %4.4x", mdio_read (dev, tp->phys[0], mii_reg));
+ printk (".\n");
+
+ /* Stop a shared interrupt from scavenging while we are. */
+ tp->dirty_tx = tp->cur_tx = 0;
+
+ /* Dump the unsent Tx packets. */
+ for (i = 0; i < NUM_TX_DESC; i++) {
+ struct ring_info *rp = &tp->tx_info[i];
+ if (rp->skb) {
+ dev_kfree_skb (rp->skb);
+ rp->skb = NULL;
+ tp->stats.tx_dropped++;
+ }
+ if (rp->mapping != 0) {
+ pci_unmap_single (tp->pci_dev, rp->mapping, rp->skb->len, PCI_DMA_TODEVICE);
+ rp->mapping = 0;
+ }
+ }
+
+ rtl8139_hw_start (dev);
+
+ DPRINTK ("EXIT\n");
+}
+
+
+/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+static void rtl8139_init_ring (struct net_device *dev)
+{
+ struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ int i;
+
+ DPRINTK ("ENTER\n");
+
+ tp->cur_rx = 0;
+ tp->dirty_tx = tp->cur_tx = 0;
+
+ for (i = 0; i < NUM_TX_DESC; i++) {
+ tp->tx_info[i].skb = NULL;
+ tp->tx_info[i].mapping = 0;
+ tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE];
+ }
+
+ DPRINTK ("EXIT\n");
+}
+
+static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
+{
+ struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ void *ioaddr = tp->mmio_addr;
+ int entry;
+ unsigned long flags;
+
+ DPRINTK ("ENTER\n");
+
+ netif_stop_queue (dev);
+
+ /* Calculate the next Tx descriptor entry. */
+ entry = tp->cur_tx % NUM_TX_DESC;
+
+ spin_lock_irqsave (&tp->lock, flags);
+
+ tp->tx_info[entry].skb = skb;
+ if ((long) skb->data & 3) { /* Must use alignment buffer. */
+ tp->tx_info[entry].mapping = 0;
+ memcpy (tp->tx_buf[entry], skb->data, skb->len);
+
+ assert (tp->tx_bufs_dma > 0);
+ RTL_W32 (TxAddr0 + entry * 4, tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs));
+ } else {
+ tp->tx_info[entry].mapping =
+ pci_map_single(tp->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE);
+
+ assert (tp->tx_info[entry].mapping > 0);
+ RTL_W32 (TxAddr0 + entry * 4, tp->tx_info[entry].mapping);
+ }
+
+ /* Note: the chip doesn't have auto-pad! */
+ RTL_W32 (TxStatus0 + entry * 4,
+ tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
+
+ dev->trans_start = jiffies;
+ if (++tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) /* Typical path */
+ netif_start_queue (dev);
+
+ spin_unlock_irqrestore (&tp->lock, flags);
+
+ DPRINTK ("%s: Queued Tx packet at %p size %lu to slot %d.\n",
+ dev->name, skb->data, skb->len, entry);
+
+ DPRINTK ("EXIT\n");
+ return 0;
+}
+
+
+static inline void rtl8139_tx_interrupt (struct net_device *dev,
+ struct rtl8139_private *tp)
+{
+ void *ioaddr;
+ unsigned int dirty_tx;
+
+ assert (dev != NULL);
+ assert (tp != NULL);
+
+ dirty_tx = tp->dirty_tx;
+ ioaddr = tp->mmio_addr;
+
+ while (tp->cur_tx - dirty_tx > 0) {
+ int entry = dirty_tx % NUM_TX_DESC;
+ int txstatus = RTL_R32 (TxStatus0 + (entry * 4));
+
+ if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted)))
+ break; /* It still hasn't been Txed */
+
+ /* Note: TxCarrierLost is always asserted at 100mbps. */
+ if (txstatus & (TxOutOfWindow | TxAborted)) {
+ /* There was an major error, log it. */
+ DPRINTK ("%s: Transmit error, Tx status %8.8x.\n",
+ dev->name, txstatus);
+ tp->stats.tx_errors++;
+ if (txstatus & TxAborted) {
+ tp->stats.tx_aborted_errors++;
+ RTL_W32 (TxConfig, (TX_DMA_BURST << 8) | 0x03000001);
+ }
+ if (txstatus & TxCarrierLost)
+ tp->stats.tx_carrier_errors++;
+ if (txstatus & TxOutOfWindow)
+ tp->stats.tx_window_errors++;
+#ifdef ETHER_STATS
+ if ((txstatus & 0x0f000000) == 0x0f000000)
+ tp->stats.collisions16++;
+#endif
+ } else {
+ if (txstatus & TxUnderrun) {
+ /* Add 64 to the Tx FIFO threshold. */
+ if (tp->tx_flag < 0x00300000)
+ tp->tx_flag += 0x00020000;
+ tp->stats.tx_fifo_errors++;
+ }
+ tp->stats.collisions += (txstatus >> 24) & 15;
+ tp->stats.tx_bytes += txstatus & 0x7ff;
+ tp->stats.tx_packets++;
+ }
+
+ if (tp->tx_info[entry].mapping != 0) {
+ pci_unmap_single (tp->pci_dev,
+ tp->tx_info[entry].mapping,
+ tp->tx_info[entry].skb->len,
+ PCI_DMA_TODEVICE);
+ tp->tx_info[entry].mapping = 0;
+ }
+ /* Free the original skb. */
+ dev_kfree_skb_irq (tp->tx_info[entry].skb);
+ tp->tx_info[entry].skb = NULL;
+ dirty_tx++;
+ if (tp->cur_tx - dirty_tx < NUM_TX_DESC)
+ netif_wake_queue (dev);
+ else
+ netif_stop_queue (dev);
+ }
+
+#ifndef RTL8139_NDEBUG
+ if (tp->cur_tx - dirty_tx > NUM_TX_DESC) {
+ printk (KERN_ERR
+ "%s: Out-of-sync dirty pointer, %d vs. %d.\n",
+ dev->name, dirty_tx, tp->cur_tx);
+ dirty_tx += NUM_TX_DESC;
+ }
+#endif
+
+ tp->dirty_tx = dirty_tx;
+}
+
+
+/* The data sheet doesn't describe the Rx ring at all, so I'm guessing at the
+ field alignments and semantics. */
+static inline void rtl8139_rx_interrupt (struct net_device *dev,
+ struct rtl8139_private *tp)
+{
+ void *ioaddr = tp->mmio_addr;
+ unsigned char *rx_ring = tp->rx_ring;
+ u16 cur_rx = tp->cur_rx;
+
+ DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x,"
+ " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx,
+ RTL_R16 (RxBufAddr),
+ RTL_R16 (RxBufPtr),
+ RTL_R8 (ChipCmd));
+
+ while ((RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
+ int ring_offset = cur_rx % RX_BUF_LEN;
+ u32 rx_status =
+ le32_to_cpu (*(u32 *) (rx_ring + ring_offset));
+ int rx_size = rx_status >> 16;
+
+#ifdef RTL8139_DEBUG
+ int i;
+ DPRINTK ("%s: rtl8139_rx() status %4.4x, size %4.4x,"
+ " cur %4.4x.\n", dev->name, rx_status,
+ rx_size, cur_rx);
+ DPRINTK ("%s: Frame contents ", dev->name);
+ for (i = 0; i < 70; i++)
+ printk (" %2.2x", rx_ring[ring_offset + i]);
+ printk (".\n");
+#endif
+
+ /* E. Gill */
+ /* Note from BSD driver:
+ * Here's a totally undocumented fact for you. When the
+ * RealTek chip is in the process of copying a packet into
+ * RAM for you, the length will be 0xfff0. If you spot a
+ * packet header with this value, you need to stop. The
+ * datasheet makes absolutely no mention of this and
+ * RealTek should be shot for this.
+ */
+ if (rx_size == 0xfff0)
+ break;
+
+ if (rx_status &
+ (RxBadSymbol | RxRunt | RxTooLong | RxCRCErr |
+ RxBadAlign)) {
+ DPRINTK ("%s: Ethernet frame had errors,"
+ " status %8.8x.\n", dev->name,
+ rx_status);
+ if (rx_status & RxTooLong) {
+ DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n",
+ dev->name, rx_status);
+ /* A.C.: The chip hangs here. */
+ }
+ tp->stats.rx_errors++;
+ if (rx_status & (RxBadSymbol | RxBadAlign))
+ tp->stats.rx_frame_errors++;
+ if (rx_status & (RxRunt | RxTooLong))
+ tp->stats.rx_length_errors++;
+ if (rx_status & RxCRCErr)
+ tp->stats.rx_crc_errors++;
+ /* Reset the receiver, based on RealTek recommendation. (Bug?) */
+ tp->cur_rx = 0;
+ RTL_W8 (ChipCmd, CmdTxEnb);
+ /* A.C.: Reset the multicast list. */
+ rtl8139_set_rx_mode (dev);
+ RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
+ } else {
+ /* Malloc up new buffer, compatible with net-2e. */
+ /* Omit the four octet CRC from the length. */
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb (rx_size + 2);
+ if (skb == NULL) {
+ printk (KERN_WARNING
+ "%s: Memory squeeze, deferring packet.\n",
+ dev->name);
+ /* We should check that some rx space is free.
+ If not, free one and mark stats->rx_dropped++. */
+ tp->stats.rx_dropped++;
+ break;
+ }
+ skb->dev = dev;
+ skb_reserve (skb, 2); /* 16 byte align the IP fields. */
+ if (ring_offset + rx_size + 4 > RX_BUF_LEN) {
+ int semi_count =
+ RX_BUF_LEN - ring_offset - 4;
+ /* This could presumably use two calls to copy_and_sum()? */
+ memcpy (skb_put (skb, semi_count),
+ &rx_ring[ring_offset + 4],
+ semi_count);
+ memcpy (skb_put
+ (skb, rx_size - semi_count),
+ rx_ring, rx_size - semi_count);
+#ifdef RTL8139_DEBUG
+ {
+ int i;
+ printk (KERN_DEBUG
+ "%s: Frame wrap @%d",
+ dev->name, semi_count);
+ for (i = 0; i < 16; i++)
+ printk (" %2.2x",
+ rx_ring[i]);
+ printk (".\n");
+ memset (rx_ring, 0xcc, 16);
+ }
+#endif /* RTL8139_DEBUG */
+
+ } else {
+ eth_copy_and_sum (skb,
+ &rx_ring[ring_offset +
+ 4], rx_size, 0);
+ skb_put (skb, rx_size);
+ }
+ skb->protocol = eth_type_trans (skb, dev);
+ netif_rx (skb);
+ tp->stats.rx_bytes += rx_size;
+ tp->stats.rx_packets++;
+ }
+
+ cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
+ RTL_W16_F (RxBufPtr, cur_rx - 16);
+ }
+ DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x,"
+ " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx,
+ RTL_R16 (RxBufAddr),
+ RTL_R16 (RxBufPtr),
+ RTL_R8 (ChipCmd));
+ tp->cur_rx = cur_rx;
+}
+
+
+static inline int rtl8139_weird_interrupt (struct net_device *dev,
+ struct rtl8139_private *tp,
+ int status, int link_changed)
+{
+ void *ioaddr;
+
+ DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n",
+ dev->name, status);
+
+ assert (dev != NULL);
+ assert (tp != NULL);
+
+ ioaddr = tp->mmio_addr;
+
+ if (status == 0xffffffff) {
+ printk (KERN_WARNING PFX "abnormal interrupt, card ejected? (ok to ignore)\n");
+ return -1;
+ }
+
+ /* Update the error count. */
+ tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
+ RTL_W32 (RxMissed, 0);
+
+ if ((status & RxUnderrun) && link_changed &&
+ (tp->drv_flags & HAS_LNK_CHNG)) {
+ /* Really link-change on new chips. */
+ int lpar = RTL_R16 (NWayLPAR);
+ int duplex = (lpar & 0x0100) || (lpar & 0x01C0) == 0x0040
+ || tp->duplex_lock;
+ if (tp->full_duplex != duplex) {
+ tp->full_duplex = duplex;
+ RTL_W8 (Cfg9346, 0xC0);
+ RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
+ RTL_W8 (Cfg9346, 0x00);
+ }
+ status &= ~RxUnderrun;
+ }
+ if (status &
+ (RxUnderrun | RxOverflow | RxErr | RxFIFOOver))
+ tp->stats.rx_errors++;
+
+ if (status & (PCSTimeout))
+ tp->stats.rx_length_errors++;
+ if (status & (RxUnderrun | RxFIFOOver))
+ tp->stats.rx_fifo_errors++;
+ if (status & RxOverflow) {
+ tp->stats.rx_over_errors++;
+ tp->cur_rx = RTL_R16 (RxBufAddr) % RX_BUF_LEN;
+ RTL_W16_F (RxBufPtr, tp->cur_rx - 16);
+ }
+ if (status & PCIErr) {
+ u16 pci_cmd_status;
+ pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status);
+
+ printk (KERN_ERR "%s: PCI Bus error %4.4x.\n",
+ dev->name, pci_cmd_status);
+ }
+
+ return 0;
+}
+
+
+/* The interrupt handler does all of the Rx thread work and cleans up
+ after the Tx thread. */
+static void rtl8139_interrupt (int irq, void *dev_instance,
+ struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *) dev_instance;
+ struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ int boguscnt = max_interrupt_work;
+ void *ioaddr = tp->mmio_addr;
+ int link_changed = 0; /* Grrr, avoid bogus "uninitialized" warning */
+
+ spin_lock_irq (&tp->lock);
+
+ /* disable interrupt generation while handling this interrupt */
+ RTL_W16 (IntrMask, 0x0000);
+
+ do {
+ int status = RTL_R16 (IntrStatus);
+ /* Acknowledge all of the current interrupt sources ASAP, but
+ an first get an additional status bit from CSCR. */
+ if (status & RxUnderrun)
+ link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit;
+
+ /* E. Gill */
+ /* In case of an RxFIFOOver we must also clear the RxOverflow
+ bit to avoid dropping frames for ever. Believe me, I got a
+ lot of troubles copying huge data (approximately 2 RxFIFOOver
+ errors per 1GB data transfer).
+ The following is written in the 'p-guide.pdf' file (RTL8139(A/B)
+ Programming guide V0.1, from 1999/1/15) on page 9 from REALTEC.
+ -----------------------------------------------------------
+ 2. RxFIFOOvw handling:
+ When RxFIFOOvw occurs, all incoming packets are discarded.
+ Clear ISR(RxFIFOOvw) doesn't dismiss RxFIFOOvw event. To
+ dismiss RxFIFOOvw event, the ISR(RxBufOvw) must be written
+ with a '1'.
+ -----------------------------------------------------------
+ Unfortunately I was not able to find any reason for the
+ RxFIFOOver error (I got the feeling this depends on the
+ CPU speed, lower CPU speed --> more errors).
+ After clearing the RxOverflow bit the transfer of the
+ packet was repeated and all data are error free transfered */
+ RTL_W16 (IntrStatus, (status & RxFIFOOver) ? (status | RxOverflow) : status);
+
+ DPRINTK ("%s: interrupt status=%#4.4x new intstat=%#4.4x.\n",
+ dev->name, status,
+ RTL_R16 (IntrStatus));
+
+ if ((status &
+ (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |
+ RxFIFOOver | TxErr | TxOK | RxErr | RxOK)) == 0)
+ break;
+
+ /* Check uncommon events with one test. */
+ if (status & (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |
+ RxFIFOOver | TxErr | RxErr))
+ if (rtl8139_weird_interrupt (dev, tp, status,
+ link_changed) == -1)
+ break;
+
+ if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver)) /* Rx interrupt */
+ rtl8139_rx_interrupt (dev, tp);
+
+ if (status & (TxOK | TxErr))
+ rtl8139_tx_interrupt (dev, tp);
+
+ if (--boguscnt < 0) {
+ printk (KERN_WARNING
+ "%s: Too much work at interrupt, "
+ "IntrStatus=0x%4.4x.\n", dev->name,
+ status);
+ /* Clear all interrupt sources. */
+ RTL_W16 (IntrStatus, 0xffff);
+ break;
+ }
+ } while (1);
+
+ /* Enable all known interrupts by setting the interrupt mask. */
+ RTL_W16 (IntrMask, rtl8139_intr_mask);
+
+ spin_unlock_irq (&tp->lock);
+
+ DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n",
+ dev->name, RTL_R16 (IntrStatus));
+
+}
+
+static int rtl8139_close (struct net_device *dev)
+{
+ struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ void *ioaddr = tp->mmio_addr;
+ int i;
+
+ DPRINTK ("ENTER\n");
+
+ netif_stop_queue (dev);
+
+ DPRINTK ("%s: Shutting down ethercard, status was 0x%4.4x.\n",
+ dev->name, RTL_R16 (IntrStatus));
+
+ /* Disable interrupts by clearing the interrupt mask. */
+ RTL_W16 (IntrMask, 0x0000);
+
+ /* Stop the chip's Tx and Rx DMA processes. */
+ RTL_W8 (ChipCmd, 0x00);
+
+ /* Update the error counts. */
+ tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
+ RTL_W32 (RxMissed, 0);
+
+ del_timer (&tp->timer);
+
+ free_irq (dev->irq, dev);
+
+ for (i = 0; i < NUM_TX_DESC; i++) {
+ struct sk_buff *skb = tp->tx_info[i].skb;
+ dma_addr_t mapping = tp->tx_info[i].mapping;
+
+ if (skb) {
+ if (mapping)
+ pci_unmap_single (tp->pci_dev, mapping, skb->len, PCI_DMA_TODEVICE);
+ dev_kfree_skb (skb);
+ }
+ tp->tx_info[i].skb = NULL;
+ tp->tx_info[i].mapping = 0;
+ }
+
+ pci_free_consistent(tp->pci_dev, RX_BUF_LEN + 16,
+ tp->rx_ring, tp->rx_ring_dma);
+ pci_free_consistent(tp->pci_dev, TX_BUF_SIZE * NUM_TX_DESC,
+ tp->tx_bufs, tp->tx_bufs_dma);
+ tp->rx_ring = NULL;
+ tp->tx_bufs = NULL;
+
+ /* Green! Put the chip in low-power mode. */
+ RTL_W8 (Cfg9346, 0xC0);
+ RTL_W8 (Config1, 0x03);
+ RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */
+
+ MOD_DEC_USE_COUNT;
+
+ DPRINTK ("EXIT\n");
+ return 0;
+}
+
+static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ u16 *data = (u16 *) & rq->ifr_data;
+
+ DPRINTK ("ENTER\n");
+
+ switch (cmd) {
+ case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
+ data[0] = tp->phys[0] & 0x3f;
+ /* Fall Through */
+ case SIOCDEVPRIVATE + 1: /* Read the specified MII register. */
+ data[3] = mdio_read (dev, data[0], data[1] & 0x1f);
+ DPRINTK ("EXIT\n");
+ return 0;
+ case SIOCDEVPRIVATE + 2: /* Write the specified MII register */
+ if (!capable (CAP_NET_ADMIN))
+ return -EPERM;
+ mdio_write (dev, data[0], data[1] & 0x1f, data[2]);
+ DPRINTK ("EXIT\n");
+ return 0;
+ default:
+ DPRINTK ("EXIT\n");
+ return -EOPNOTSUPP;
+ }
+
+ DPRINTK ("EXIT\n");
+}
+
+static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
+{
+ struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ void *ioaddr = tp->mmio_addr;
+
+ DPRINTK ("ENTER\n");
+
+ assert (tp != NULL);
+
+ if (netif_running(dev)) {
+ tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
+ RTL_W32 (RxMissed, 0);
+ }
+
+ DPRINTK ("EXIT\n");
+ return &tp->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+ This routine is not state sensitive and need not be SMP locked. */
+
+static unsigned const ethernet_polynomial = 0x04c11db7U;
+static inline u32 ether_crc (int length, unsigned char *data)
+{
+ int crc = -1;
+
+ DPRINTK ("ENTER\n");
+
+ while (--length >= 0) {
+ unsigned char current_octet = *data++;
+ int bit;
+ for (bit = 0; bit < 8; bit++, current_octet >>= 1)
+ crc = (crc << 1) ^
+ ((crc < 0) ^ (current_octet & 1) ?
+ ethernet_polynomial : 0);
+ }
+
+ DPRINTK ("EXIT\n");
+ return crc;
+}
+
+static void rtl8139_set_rx_mode (struct net_device *dev)
+{
+ struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ void *ioaddr = tp->mmio_addr;
+ u32 mc_filter[2]; /* Multicast hash filter */
+ int i, rx_mode;
+
+ DPRINTK ("ENTER\n");
+
+ DPRINTK ("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8x.\n",
+ dev->name, dev->flags, RTL_R32 (RxConfig));
+
+ /* Note: do not reorder, GCC is clever about common statements. */
+ if (dev->flags & IFF_PROMISC) {
+ /* Unconditionally log net taps. */
+ printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n",
+ dev->name);
+ rx_mode =
+ AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
+ AcceptAllPhys;
+ mc_filter[1] = mc_filter[0] = 0xffffffff;
+ } else if ((dev->mc_count > multicast_filter_limit)
+ || (dev->flags & IFF_ALLMULTI)) {
+ /* Too many to filter perfectly -- accept all multicasts. */
+ rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
+ mc_filter[1] = mc_filter[0] = 0xffffffff;
+ } else {
+ struct dev_mc_list *mclist;
+ rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
+ mc_filter[1] = mc_filter[0] = 0;
+ for (i = 0, mclist = dev->mc_list;
+ mclist && i < dev->mc_count;
+ i++, mclist =
+ mclist->next) set_bit (ether_crc (ETH_ALEN,
+ mclist->
+ dmi_addr) >> 26,
+ mc_filter);
+ }
+ /* We can safely update without stopping the chip. */
+ RTL_W32 (RxConfig, rtl8139_rx_config | rx_mode);
+ RTL_W32_F (MAR0 + 0, mc_filter[0]);
+ RTL_W32_F (MAR0 + 4, mc_filter[1]);
+
+ DPRINTK ("EXIT\n");
+}
+
+
+static void rtl8139_suspend (struct pci_dev *pdev)
+{
+ struct net_device *dev = PCI_GET_DRIVER_DATA (pdev);
+ struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+ void *ioaddr = tp->mmio_addr;
+
+ netif_stop_queue (dev);
+
+ /* Disable interrupts, stop Tx and Rx. */
+ RTL_W16 (IntrMask, 0x0000);
+ RTL_W8 (ChipCmd, 0x00);
+
+ /* Update the error counts. */
+ tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
+ RTL_W32 (RxMissed, 0);
+}
+
+
+static void rtl8139_resume (struct pci_dev *pdev)
+{
+ struct net_device *dev = PCI_GET_DRIVER_DATA (pdev);
+
+ rtl8139_hw_start(dev);
+}
+
+
+static struct pci_driver rtl8139_pci_driver = {
+ name: RTL8139_MODULE_NAME,
+ id_table: rtl8139_pci_tbl,
+ probe: rtl8139_init_one,
+ remove: rtl8139_remove_one,
+ suspend: rtl8139_suspend,
+ resume: rtl8139_resume,
+};
+
+
+static int __init rtl8139_init_module (void)
+{
+ int rc;
+
+ DPRINTK ("ENTER\n");
+
+ rc = pci_register_driver (&rtl8139_pci_driver);
+
+ if (rc > 0) {
+ printk (KERN_INFO RTL8139_DRIVER_NAME
+ " loaded (%d device%s registered)\n",
+ rc, rc > 1 ? "s" : "");
+ } else {
+ pci_unregister_driver (&rtl8139_pci_driver);
+ }
+
+ DPRINTK ("EXIT\n");
+ return rc > 0 ? 0 : -ENODEV;
+}
+
+
+static void __exit rtl8139_cleanup_module (void)
+{
+ pci_unregister_driver (&rtl8139_pci_driver);
+}
+
+
+module_init(rtl8139_init_module);
+module_exit(rtl8139_cleanup_module);
diff --git a/drivers/net/82596.c b/drivers/net/82596.c
index 0b8a9723b..55c85bbd1 100644
--- a/drivers/net/82596.c
+++ b/drivers/net/82596.c
@@ -164,6 +164,8 @@ enum commands {
#define RX_SUSPEND 0x0030
#define RX_ABORT 0x0040
+#define TX_TIMEOUT 5
+
struct i596_reg {
unsigned short porthi;
unsigned short portlo;
@@ -267,6 +269,7 @@ struct i596_private {
struct tx_cmd tx_cmds[TX_RING_SIZE];
struct i596_tbd tbds[TX_RING_SIZE];
int next_tx_cmd;
+ spinlock_t lock;
};
char init_setup[] =
@@ -296,6 +299,7 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int i596_close(struct net_device *dev);
static struct net_device_stats *i596_get_stats(struct net_device *dev);
static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
+static void i596_tx_timeout (struct net_device *dev);
static void print_eth(char *);
static void set_multicast_list(struct net_device *dev);
@@ -561,8 +565,7 @@ static inline void init_i596_mem(struct net_device *dev)
boguscnt = 200000;
- save_flags(flags);
- cli();
+ spin_lock_irqsave (&lp->lock, flags);
while (lp->scb.command)
if (--boguscnt == 0) {
@@ -573,7 +576,7 @@ static inline void init_i596_mem(struct net_device *dev)
lp->scb.command = RX_START;
CA(dev);
- restore_flags(flags);
+ spin_unlock_irqrestore (&lp->lock, flags);
boguscnt = 2000;
while (lp->scb.command)
@@ -778,8 +781,7 @@ static inline void i596_reset(struct net_device *dev, struct i596_private *lp, i
if (i596_debug > 1)
printk("i596_reset\n");
- save_flags(flags);
- cli();
+ spin_lock_irqsave (&lp->lock, flags);
while (lp->scb.command)
if (--boguscnt == 0) {
@@ -787,8 +789,8 @@ static inline void i596_reset(struct net_device *dev, struct i596_private *lp, i
lp->scb.status, lp->scb.command);
break;
}
- dev->start = 0;
- dev->tbusy = 1;
+
+ netif_stop_queue(dev);
lp->scb.command = CUC_ABORT | RX_ABORT;
CA(dev);
@@ -802,14 +804,12 @@ static inline void i596_reset(struct net_device *dev, struct i596_private *lp, i
lp->scb.status, lp->scb.command);
break;
}
- restore_flags(flags);
+ spin_unlock_irqrestore (&lp->lock, flags);
i596_cleanup_cmd(lp);
i596_rx(dev);
- dev->start = 1;
- dev->tbusy = 0;
- dev->interrupt = 0;
+ netif_start_queue(dev);
init_i596_mem(dev);
}
@@ -826,8 +826,8 @@ static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
cmd->status = 0;
cmd->command |= (CMD_EOL | CMD_INTR);
cmd->next = (struct i596_cmd *) I596_NULL;
- save_flags(flags);
- cli();
+
+ spin_lock_irqsave (&lp->lock, flags);
/*
* RGH 300597: Looks to me like there could be a race condition
@@ -857,7 +857,8 @@ static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
lp->cmd_backlog++;
lp->cmd_head = WSWAPcmd(lp->scb.cmd); /* Is this redundant? RGH 300597 */
- restore_flags(flags);
+
+ spin_unlock_irqrestore (&lp->lock, flags);
if (lp->cmd_backlog > max_cmd_backlog) {
unsigned long tickssofar = jiffies - lp->last_cmd;
@@ -886,9 +887,8 @@ static int i596_open(struct net_device *dev)
#endif
init_rx_bufs(dev);
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue(dev);
+
MOD_INC_USE_COUNT;
/* Initialize the 82596 memory */
@@ -897,51 +897,53 @@ static int i596_open(struct net_device *dev)
return 0; /* Always succeed */
}
-static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static void i596_tx_timeout (struct net_device *dev)
{
struct i596_private *lp = (struct i596_private *) dev->priv;
int ioaddr = dev->base_addr;
+
+ /* Transmitter timeout, serious problems. */
+ printk ("%s: transmit timed out, status resetting.\n", dev->name);
+
+ lp->stats.tx_errors++;
+
+ /* Try to restart the adaptor */
+ if (lp->last_restart == lp->stats.tx_packets) {
+ if (i596_debug > 1)
+ printk ("Resetting board.\n");
+
+ /* Shutdown and restart */
+ i596_reset (dev, lp, ioaddr);
+ } else {
+ /* Issue a channel attention signal */
+ if (i596_debug > 1)
+ printk ("Kicking board.\n");
+ lp->scb.command = CUC_START | RX_START;
+ CA (dev);
+ lp->last_restart = lp->stats.tx_packets;
+ }
+
+ dev->trans_start = jiffies;
+ netif_wake_queue (dev);
+}
+
+
+static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct i596_private *lp = (struct i596_private *) dev->priv;
struct tx_cmd *tx_cmd;
struct i596_tbd *tbd;
if (i596_debug > 2)
printk("%s: 82596 start xmit\n", dev->name);
- /* Transmitter timeout, serious problems. */
- if (dev->tbusy) {
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 5)
- return 1;
- printk("%s: transmit timed out, status resetting.\n",
- dev->name);
- lp->stats.tx_errors++;
- /* Try to restart the adaptor */
- if (lp->last_restart == lp->stats.tx_packets) {
- if (i596_debug > 1)
- printk("Resetting board.\n");
-
- /* Shutdown and restart */
- i596_reset(dev, lp, ioaddr);
- } else {
- /* Issue a channel attention signal */
- if (i596_debug > 1)
- printk("Kicking board.\n");
- lp->scb.command = CUC_START | RX_START;
- CA(dev);
- lp->last_restart = lp->stats.tx_packets;
- }
- dev->tbusy = 0;
- dev->trans_start = jiffies;
- }
if (i596_debug > 3)
printk("%s: i596_start_xmit(%x,%x) called\n", dev->name,
skb->len, (unsigned int)skb->data);
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if (test_and_set_bit(0, (void *) &dev->tbusy) != 0)
- printk("%s: Transmitter access conflict.\n", dev->name);
- else {
+ netif_stop_queue(dev);
+
+ {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
dev->trans_start = jiffies;
@@ -982,7 +984,7 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
}
- dev->tbusy = 0;
+ netif_start_queue(dev);
return 0;
}
@@ -1086,11 +1088,14 @@ int __init i82596_probe(struct net_device *dev)
printk(version);
/* The 82596-specific entries in the device structure. */
- dev->open = &i596_open;
- dev->stop = &i596_close;
- dev->hard_start_xmit = &i596_start_xmit;
- dev->get_stats = &i596_get_stats;
- dev->set_multicast_list = &set_multicast_list;
+ dev->open = i596_open;
+ dev->stop = i596_close;
+ dev->hard_start_xmit = i596_start_xmit;
+ dev->get_stats = i596_get_stats;
+ dev->set_multicast_list = set_multicast_list;
+ dev->tx_timeout = i596_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
dev->mem_start = (int)__get_free_pages(GFP_ATOMIC, 0);
dev->priv = (void *)(dev->mem_start);
@@ -1110,6 +1115,7 @@ int __init i82596_probe(struct net_device *dev)
lp->scb.command = 0;
lp->scb.cmd = (struct i596_cmd *) I596_NULL;
lp->scb.rfd = (struct i596_rfd *) I596_NULL;
+ lp->lock = SPIN_LOCK_UNLOCKED;
return 0;
}
@@ -1137,14 +1143,10 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (i596_debug > 3)
printk("%s: i596_interrupt(): irq %d\n", dev->name, irq);
- if (dev->interrupt)
- printk("%s: Re-entering the interrupt handler.\n", dev->name);
-
- dev->interrupt = 1;
-
ioaddr = dev->base_addr;
-
lp = (struct i596_private *) dev->priv;
+
+ spin_lock (&lp->lock);
while (lp->scb.command)
if (--boguscnt == 0) {
@@ -1248,7 +1250,8 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
ptr = WSWAPcmd(ptr->next);
}
- if ((lp->cmd_head != (struct i596_cmd *) I596_NULL) && (dev->start))
+ if ((lp->cmd_head != (struct i596_cmd *) I596_NULL) &&
+ netif_running(dev))
ack_cmd |= CUC_START;
lp->scb.cmd = WSWAPcmd(lp->cmd_head);
}
@@ -1257,7 +1260,7 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
printk("%s: i596 interrupt received a frame.\n", dev->name);
/* Only RX_START if stopped - RGH 07-07-96 */
if (status & 0x1000) {
- if (dev->start)
+ if (netif_running(dev))
ack_cmd |= RX_START;
if (i596_debug > 1)
printk("%s: i596 interrupt receive unit inactive %x.\n", dev->name, status & 0x00f0);
@@ -1304,7 +1307,8 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (i596_debug > 4)
printk("%s: exiting interrupt.\n", dev->name);
- dev->interrupt = 0;
+ spin_unlock (&lp->lock);
+
return;
}
@@ -1314,8 +1318,7 @@ static int i596_close(struct net_device *dev)
int boguscnt = 2000;
unsigned long flags;
- dev->start = 0;
- dev->tbusy = 1;
+ netif_stop_queue(dev);
if (i596_debug > 1)
printk("%s: Shutting down ethercard, status was %4.4x.\n",
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index f63e1c310..641693f45 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -167,7 +167,6 @@ int ei_open(struct net_device *dev)
NS8390_init(dev, 1);
/* Set the flag before we drop the lock, That way the IRQ arrives
after its set and we get no silly warnings */
- clear_bit(LINK_STATE_RXSEM, &dev->state);
netif_start_queue(dev);
spin_unlock_irqrestore(&ei_local->page_lock, flags);
ei_local->irqlock = 0;
@@ -203,8 +202,8 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
* board has died and kick it.
*/
- if (test_bit(LINK_STATE_XOFF, &dev->state))
- { /* Do timeouts, just like the 8003 driver. */
+ if (netif_queue_stopped(dev)) {
+ /* Do timeouts, just like the 8003 driver. */
int txsr;
int isr;
int tickssofar = jiffies - dev->trans_start;
@@ -224,8 +223,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
ei_local->stat.tx_errors++;
isr = inb(e8390_base+EN0_ISR);
- if (!test_bit(LINK_STATE_START, &dev->state))
- {
+ if (!netif_running(dev)) {
spin_unlock_irqrestore(&ei_local->page_lock, flags);
printk(KERN_WARNING "%s: xmit on stopped card\n", dev->name);
return 1;
@@ -430,8 +428,6 @@ void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
return;
}
- set_bit(LINK_STATE_RXSEM, &dev->state);
-
/* Change to page 0 and read the intr status reg. */
outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
if (ei_debug > 3)
@@ -442,8 +438,7 @@ void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0
&& ++nr_serviced < MAX_SERVICE)
{
- if (!test_bit(LINK_STATE_START, &dev->state))
- {
+ if (!netif_running(dev)) {
printk(KERN_WARNING "%s: interrupt from stopped card\n", dev->name);
interrupts = 0;
break;
@@ -491,7 +486,6 @@ void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
}
}
- clear_bit(LINK_STATE_RXSEM, &dev->state);
spin_unlock(&ei_local->page_lock);
return;
}
@@ -567,7 +561,6 @@ static void ei_tx_intr(struct net_device *dev)
printk(KERN_ERR "%s: bogus last_tx_buffer %d, tx1=%d.\n",
ei_local->name, ei_local->lasttx, ei_local->tx1);
ei_local->tx1 = 0;
- netif_start_queue(dev);
if (ei_local->tx2 > 0)
{
ei_local->txing = 1;
@@ -584,7 +577,6 @@ static void ei_tx_intr(struct net_device *dev)
printk("%s: bogus last_tx_buffer %d, tx2=%d.\n",
ei_local->name, ei_local->lasttx, ei_local->tx2);
ei_local->tx2 = 0;
- netif_start_queue(dev);
if (ei_local->tx1 > 0)
{
ei_local->txing = 1;
@@ -604,7 +596,6 @@ static void ei_tx_intr(struct net_device *dev)
* Single Tx buffer: mark it free so another packet can be loaded.
*/
ei_local->txing = 0;
- netif_start_queue(dev);
#endif
/* Minimize Tx latency: update the statistics after we restart TXing. */
@@ -840,7 +831,7 @@ static struct net_device_stats *get_stats(struct net_device *dev)
unsigned long flags;
/* If the card is stopped, just return the present stats. */
- if (!test_bit(LINK_STATE_START, &dev->state))
+ if (!netif_running(dev))
return &ei_local->stat;
spin_lock_irqsave(&ei_local->page_lock,flags);
@@ -936,7 +927,7 @@ static void do_set_multicast_list(struct net_device *dev)
* Ultra32 EISA) appears to have this bug fixed.
*/
- if (test_bit(LINK_STATE_START, &dev->state))
+ if (netif_running(dev))
outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
for(i = 0; i < 8; i++)
diff --git a/drivers/net/Config.in b/drivers/net/Config.in
index 835995197..f3cc0af3a 100644
--- a/drivers/net/Config.in
+++ b/drivers/net/Config.in
@@ -76,7 +76,9 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
fi
tristate ' SMC Ultra support' CONFIG_ULTRA
tristate ' SMC Ultra32 EISA support' CONFIG_ULTRA32
- tristate ' SMC 9194 support' CONFIG_SMC9194
+ if [ "$CONFIG_OBSOLETE" = "y" ]; then
+ tristate ' SMC 9194 support' CONFIG_SMC9194
+ fi
fi
bool ' Racal-Interlan (Micom) NI cards' CONFIG_NET_VENDOR_RACAL
if [ "$CONFIG_NET_VENDOR_RACAL" = "y" ]; then
@@ -86,10 +88,6 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
tristate ' NI5210 support' CONFIG_NI52
tristate ' NI6510 support' CONFIG_NI65
fi
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- tristate ' RealTek 8129/8139 (not 8019/8029!) support (EXPERIMENTAL)' CONFIG_RTL8139
- tristate ' DM9102 PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_DM9102
- fi
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate ' AT1700/1720 support (EXPERIMENTAL)' CONFIG_AT1700
fi
@@ -97,18 +95,22 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
bool ' Other ISA cards' CONFIG_NET_ISA
if [ "$CONFIG_NET_ISA" = "y" ]; then
tristate ' Cabletron E21xx support' CONFIG_E2100
- tristate ' EtherWORKS 3 (DE203, DE204, DE205) support' CONFIG_EWRK3
+ if [ "$CONFIG_OBSOLETE" = "y" ]; then
+ tristate ' EtherWORKS 3 (DE203, DE204, DE205) support' CONFIG_EWRK3
+ fi
tristate ' EtherExpress 16 support' CONFIG_EEXPRESS
tristate ' EtherExpressPro support' CONFIG_EEXPRESS_PRO
- tristate ' FMV-181/182/183/184 support' CONFIG_FMV18X
+ if [ "$CONFIG_OBSOLETE" = "y" ]; then
+ tristate ' FMV-181/182/183/184 support' CONFIG_FMV18X
+ fi
tristate ' HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS
tristate ' HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN
tristate ' HP 10/100VG PCLAN (ISA, EISA, PCI) support' CONFIG_HP100
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- tristate ' ICL EtherTeam 16i/32 support (EXPERIMENTAL)' CONFIG_ETH16I
+ if [ "$CONFIG_OBSOLETE" = "y" ]; then
+ tristate ' ICL EtherTeam 16i/32 support' CONFIG_ETH16I
fi
tristate ' NE2000/NE1000 support' CONFIG_NE2000
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ if [ "$CONFIG_OBSOLETE" = "y" ]; then
tristate ' SEEQ8005 support (EXPERIMENTAL)' CONFIG_SEEQ8005
fi
bool ' SK_G16 support' CONFIG_SK_G16
@@ -117,8 +119,8 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
tristate ' SKnet MCA support' CONFIG_SKMC
tristate ' NE/2 (ne2000 MCA version) support' CONFIG_NE2_MCA
fi
- bool ' EISA, VLB, PCI and on board controllers' CONFIG_NET_EISA
- if [ "$CONFIG_NET_EISA" = "y" ]; then
+ bool ' EISA, VLB, PCI and on board controllers' CONFIG_NET_PCI
+ if [ "$CONFIG_NET_PCI" = "y" ]; then
tristate ' AMD PCnet32 (VLB and PCI) support' CONFIG_PCNET32
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate ' Adaptec Starfire support (EXPERIMENTAL)' CONFIG_ADAPTEC_STARFIRE
@@ -128,29 +130,43 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
fi
tristate ' Apricot Xen-II on board Ethernet' CONFIG_APRICOT
- tristate ' CS89x0 support' CONFIG_CS89x0
+ if [ "$CONFIG_OBSOLETE" = "y" ]; then
+ tristate ' CS89x0 support' CONFIG_CS89x0
+ fi
tristate ' Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
tristate ' DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP
tristate ' Digi Intl. RightSwitch SE-X support' CONFIG_DGRS
- tristate ' EtherExpressPro/100 support' CONFIG_EEXPRESS_PRO100
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate ' DM9102 PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_DM9102
+ fi
+ tristate ' EtherExpressPro/100 support' CONFIG_EEPRO100
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ if [ "$CONFIG_EEPRO100" = "y" -o "$CONFIG_EEPRO100" = "m" ]; then
+ bool ' Enable Power Management (EXPERIMENTAL)' CONFIG_EEPRO100_PM
+ fi
tristate ' Mylex EISA LNE390A/B support (EXPERIMENTAL)' CONFIG_LNE390
tristate ' Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)' CONFIG_NE3210
fi
tristate ' PCI NE2000 support' CONFIG_NE2K_PCI
# tristate ' Sundance Alta support' CONFIG_ALTA
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate ' RealTek 8129 (not 8019/8029!) support (EXPERIMENTAL)' CONFIG_RTL8129
+ fi
+ tristate ' RealTek RTL-8139 PCI Fast Ethernet Adapter support' CONFIG_8139TOO
tristate ' SiS 900/7016 PCI Fast Ethernet Adapter support' CONFIG_SIS900
tristate ' TI ThunderLAN support' CONFIG_TLAN
tristate ' VIA Rhine support' CONFIG_VIA_RHINE
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate ' Racal-Interlan EISA ES3210 support (EXPERIMENTAL)' CONFIG_ES3210
tristate ' SMC EtherPower II (EXPERIMENTAL)' CONFIG_EPIC100
+ fi
+ if [ "$CONFIG_OBSOLETE" = "y" ]; then
bool ' Zenith Z-Note support (EXPERIMENTAL)' CONFIG_ZNET
fi
fi
bool ' Pocket and portable adapters' CONFIG_NET_POCKET
if [ "$CONFIG_NET_POCKET" = "y" ]; then
- bool ' AT-LAN-TEC/RealTek pocket adapter support' CONFIG_ATP
+ tristate ' AT-LAN-TEC/RealTek pocket adapter support' CONFIG_ATP
tristate ' D-Link DE600 pocket adapter support' CONFIG_DE600
tristate ' D-Link DE620 pocket adapter support' CONFIG_DE620
fi
@@ -179,6 +195,7 @@ endmenu
bool 'FDDI driver support' CONFIG_FDDI
if [ "$CONFIG_FDDI" = "y" ]; then
bool ' Digital DEFEA and DEFPA adapter support' CONFIG_DEFXX
+ tristate ' SysKonnect FDDI PCI support' CONFIG_SKFP
fi
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
@@ -237,7 +254,9 @@ comment 'Wireless LAN (non-hamradio)'
bool 'Wireless LAN (non-hamradio)' CONFIG_NET_RADIO
if [ "$CONFIG_NET_RADIO" = "y" ]; then
dep_tristate ' STRIP (Metricom starmode radio IP)' CONFIG_STRIP $CONFIG_INET
- tristate ' AT&T WaveLAN & DEC RoamAbout DS support' CONFIG_WAVELAN
+ if [ "$CONFIG_OBSOLETE" = "y" ]; then
+ tristate ' AT&T WaveLAN & DEC RoamAbout DS support' CONFIG_WAVELAN
+ fi
tristate ' Aironet Arlan 655 & IC2200 DS support' CONFIG_ARLAN
tristate ' Aironet 4500/4800 series adapters' CONFIG_AIRONET4500
dep_tristate ' Aironet 4500/4800 ISA/PCI/PNP/365 support ' CONFIG_AIRONET4500_NONCS $CONFIG_AIRONET4500
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 3d7e6e851..3c2ede8f5 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -17,7 +17,8 @@ obj- :=
SUB_DIRS :=
MOD_SUB_DIRS :=
MOD_IN_SUB_DIRS :=
-ALL_SUB_DIRS := $(SUB_DIRS) fc hamradio irda pcmcia tokenring wan sk98lin arcnet
+ALL_SUB_DIRS := $(SUB_DIRS) fc hamradio irda pcmcia tokenring wan sk98lin \
+ arcnet skfp
O_TARGET := net.o
MOD_LIST_NAME := NET_MODULES
@@ -119,7 +120,7 @@ obj-$(CONFIG_RCPCI) += rcpci.o
obj-$(CONFIG_VORTEX) += 3c59x.o
obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
obj-$(CONFIG_PCNET32) += pcnet32.o
-obj-$(CONFIG_EEXPRESS_PRO100) += eepro100.o
+obj-$(CONFIG_EEPRO100) += eepro100.o
obj-$(CONFIG_TLAN) += tlan.o
obj-$(CONFIG_TULIP) += tulip.o
obj-$(CONFIG_EPIC100) += epic100.o
@@ -137,6 +138,15 @@ else
endif
endif
+ifeq ($(CONFIG_SKFP),y)
+ SUB_DIRS += skfp
+ obj-y += skfp/skfp.o
+else
+ ifeq ($(CONFIG_SKFP),m)
+ MOD_IN_SUB_DIRS += skfp
+ endif
+endif
+
obj-$(CONFIG_VIA_RHINE) += via-rhine.o
obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
@@ -228,7 +238,8 @@ obj-$(CONFIG_EL3) += 3c509.o
obj-$(CONFIG_3C515) += 3c515.o
obj-$(CONFIG_EEXPRESS) += eexpress.o
obj-$(CONFIG_EEXPRESS_PRO) += eepro.o
-obj-$(CONFIG_RTL8139) += rtl8139.o
+obj-$(CONFIG_RTL8129) += rtl8129.o
+obj-$(CONFIG_8139TOO) += 8139too.o
obj-$(CONFIG_WAVELAN) += wavelan.o
obj-$(CONFIG_ARLAN) += arlan.o arlan-proc.o
obj-$(CONFIG_ZNET) += znet.o
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index 50508db31..758914520 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -121,6 +121,7 @@ extern int de620_probe(struct net_device *);
/* FDDI adapters */
extern int dfx_probe(struct net_device *dev);
extern int apfddi_init(struct net_device *dev);
+extern int skfp_probe(struct net_device *dev);
/* Fibre Channel adapters */
extern int iph5526_probe(struct net_device *dev);
@@ -474,6 +475,9 @@ static int __init fddiif_probe(struct net_device *dev)
#ifdef CONFIG_APFDDI
&& apfddi_init(dev)
#endif
+#ifdef CONFIG_SKFP
+ && skfp_probe(dev)
+#endif
&& 1 ) {
return 1; /* -ENODEV or -EAGAIN would be more accurate. */
}
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c
index f15e31ae4..25364d920 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/a2065.c
@@ -164,7 +164,6 @@ static void load_csrs (struct lance_private *lp)
#define ZERO 0
/* Setup the Lance Rx and Tx rings */
-/* Sets dev->tbusy */
static void lance_init_ring (struct net_device *dev)
{
struct lance_private *lp = (struct lance_private *) dev->priv;
@@ -176,7 +175,7 @@ static void lance_init_ring (struct net_device *dev)
aib = lp->lance_init_block;
/* Lock out other processes while setting up hardware */
- dev->tbusy = 1;
+ netif_stop_queue(dev);
lp->rx_new = lp->tx_new = 0;
lp->rx_old = lp->tx_old = 0;
@@ -442,11 +441,6 @@ static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs)
if (!(csr0 & LE_C0_INTR)) /* Check if any interrupt has */
return; /* been generated by the Lance. */
- if (dev->interrupt)
- printk ("%s: again", dev->name);
-
- dev->interrupt = 1;
-
/* Acknowledge all the interrupt sources ASAP */
ll->rdp = csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT|
LE_C0_INIT);
@@ -473,15 +467,13 @@ static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs)
ll->rdp = LE_C0_STRT;
}
- if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) {
- dev->tbusy = 0;
- mark_bh (NET_BH);
- }
+ if (netif_queue_stopped(dev) && TX_BUFFS_AVAIL > 0)
+ netif_wake_queue(dev);
+
ll->rap = LE_CSR0;
ll->rdp = LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|
LE_C0_IDON|LE_C0_INEA;
- dev->interrupt = 0;
}
struct net_device *last_dev = 0;
@@ -506,9 +498,7 @@ static int lance_open (struct net_device *dev)
load_csrs (lp);
lance_init_ring (dev);
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue(dev);
status = init_restart_lance (lp);
@@ -522,9 +512,8 @@ static int lance_close (struct net_device *dev)
struct lance_private *lp = (struct lance_private *) dev->priv;
volatile struct lance_regs *ll = lp->ll;
- dev->start = 0;
- dev->tbusy = 1;
- del_timer(&lp->multicast_timer);
+ netif_stop_queue(dev);
+ del_timer_sync(&lp->multicast_timer);
/* Stop the card */
ll->rap = LE_CSR0;
@@ -548,11 +537,11 @@ static inline int lance_reset (struct net_device *dev)
ll->rdp = LE_C0_STOP;
load_csrs (lp);
+
lance_init_ring (dev);
dev->trans_start = jiffies;
- dev->interrupt = 0;
- dev->start = 1;
- dev->tbusy = 0;
+ netif_start_queue(dev);
+
status = init_restart_lance (lp);
#ifdef DEBUG_DRIVER
printk ("Lance restart=%d\n", status);
@@ -560,6 +549,17 @@ static inline int lance_reset (struct net_device *dev)
return status;
}
+static void lance_tx_timeout(struct net_device *dev)
+{
+ struct lance_private *lp = (struct lance_private *) dev->priv;
+ volatile struct lance_regs *ll = lp->ll;
+
+ printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n",
+ dev->name, ll->rdp);
+ lance_reset(dev);
+ netif_wake_queue(dev);
+}
+
static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
{
struct lance_private *lp = (struct lance_private *)dev->priv;
@@ -570,26 +570,6 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
static int outs;
unsigned long flags;
- /* Transmitter timeout, serious problems */
- if (dev->tbusy) {
- int tickssofar = jiffies - dev->trans_start;
-
- if (tickssofar < 100) {
- status = -1;
- } else {
- printk ("%s: transmit timed out, status %04x, resetting\n",
- dev->name, ll->rdp);
- lance_reset (dev);
- }
- return status;
- }
-
- /* Block a timer-based transmit from overlapping. */
- if (test_and_set_bit (0, (void *) &dev->tbusy) != 0) {
- printk ("Transmitter access conflict.\n");
- return -1;
- }
-
skblen = skb->len;
save_flags(flags);
@@ -628,13 +608,15 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask;
outs++;
+
+ if (TX_BUFFS_AVAIL <= 0)
+ netif_stop_queue(dev);
+
/* Kick the lance: transmit now */
ll->rdp = LE_C0_INEA | LE_C0_TDMD;
dev->trans_start = jiffies;
dev_kfree_skb (skb);
- if (TX_BUFFS_AVAIL)
- dev->tbusy = 0;
restore_flags(flags);
return status;
@@ -704,21 +686,17 @@ static void lance_set_multicast (struct net_device *dev)
volatile struct lance_init_block *ib = lp->init_block;
volatile struct lance_regs *ll = lp->ll;
- if (!dev->start)
+ if (!netif_running(dev))
return;
- if (dev->tbusy) {
- mod_timer(&lp->multicast_timer, jiffies + 2);
- return;
- }
- set_bit (0, (void *) &dev->tbusy);
-
if (lp->tx_old != lp->tx_new) {
mod_timer(&lp->multicast_timer, jiffies + 4);
- dev->tbusy = 0;
+ netif_wake_queue(dev);
return;
}
+ netif_stop_queue(dev);
+
ll->rap = LE_CSR0;
ll->rdp = LE_C0_STOP;
lance_init_ring (dev);
@@ -731,14 +709,19 @@ static void lance_set_multicast (struct net_device *dev)
}
load_csrs (lp);
init_restart_lance (lp);
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
}
-int __init a2065_probe(struct net_device *dev)
+static int __init a2065_probe(void)
{
+ struct net_device *dev = NULL;
+ static int called = 0;
struct zorro_dev *z = NULL;
+ if (called)
+ return -ENODEV;
+ called++;
+
while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
unsigned long board, base_addr, ram_start;
int is_cbm;
@@ -765,6 +748,18 @@ int __init a2065_probe(struct net_device *dev)
continue;
}
strcpy(z->name, "A2065 Ethernet Card");
+
+ dev = init_etherdev(NULL, sizeof(struct lance_private));
+
+ if (dev == NULL) {
+ release_mem_region(base_addr,
+ sizeof(struct lance_regs));
+ release_mem_region(ram_start, A2065_RAM_SIZE);
+ return -ENOMEM;
+ }
+ priv = (struct lance_private *)dev->priv;
+ memset(priv, 0, sizeof(struct lance_private));
+
if (is_cbm) { /* Commodore */
dev->dev_addr[0] = 0x00;
dev->dev_addr[1] = 0x80;
@@ -782,18 +777,6 @@ int __init a2065_probe(struct net_device *dev)
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
- init_etherdev(dev, 0);
-
- dev->priv = kmalloc(sizeof(struct lance_private), GFP_KERNEL);
- if (dev->priv == NULL) {
- release_mem_region(base_addr,
- sizeof(struct lance_regs));
- release_mem_region(ram_start, A2065_RAM_SIZE);
- return -ENOMEM;
- }
- priv = (struct lance_private *)dev->priv;
- memset(priv, 0, sizeof(struct lance_private));
-
dev->base_addr = ZTWO_VADDR(base_addr);
dev->mem_start = ZTWO_VADDR(ram_start);
dev->mem_end = dev->mem_start+A2065_RAM_SIZE;
@@ -812,6 +795,8 @@ int __init a2065_probe(struct net_device *dev)
dev->open = &lance_open;
dev->stop = &lance_close;
dev->hard_start_xmit = &lance_start_xmit;
+ dev->tx_timeout = &lance_tx_timeout;
+ dev->watchdog_timeo = 5*HZ;
dev->get_stats = &lance_get_stats;
dev->set_multicast_list = &lance_set_multicast;
dev->dma = 0;
@@ -828,31 +813,9 @@ int __init a2065_probe(struct net_device *dev)
}
-#ifdef MODULE
-static char devicename[9] = { 0, };
-
-static struct net_device a2065_dev =
-{
- devicename, /* filled in by register_netdev() */
- 0, 0, 0, 0, /* memory */
- 0, 0, /* base, irq */
- 0, 0, 0, NULL, a2065_probe,
-};
-
-int init_module(void)
-{
- int err;
-
- if ((err = register_netdev(&a2065_dev))) {
- if (err == -EIO)
- printk("No A2065 board found. Module not loaded.\n");
- return(err);
- }
- return(0);
-}
-
-void cleanup_module(void)
+static void __exit a2065_cleanup(void)
{
+#ifdef MODULE
struct lance_private *priv = (struct lance_private *)a2065_dev.priv;
unregister_netdev(&a2065_dev);
@@ -860,6 +823,8 @@ void cleanup_module(void)
sizeof(struct lance_regs));
release_mem_region(ZTWO_PADDR(a2065_dev.mem_start), A2065_RAM_SIZE);
kfree(priv);
+#endif
}
-#endif /* MODULE */
+module_init(a2065_probe);
+module_exit(a2065_cleanup);
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 8420b3e07..3587dfe16 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -2,7 +2,7 @@
* acenic.c: Linux driver for the Alteon AceNIC Gigabit Ethernet card
* and other Tigon based cards.
*
- * Copyright 1998, 1999 by Jes Sorensen, <Jes.Sorensen@cern.ch>.
+ * Copyright 1998-2000 by Jes Sorensen, <Jes.Sorensen@cern.ch>.
*
* Thanks to Alteon and 3Com for providing hardware and documentation
* enabling me to write this driver.
@@ -17,16 +17,23 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- * Additional work by Pete Wyckoff <wyckoff@ca.sandia.gov> for initial
- * Alpha and trace dump support. The trace dump support has not been
- * integrated yet however.
- *
- * Big-endian+Sparc fixes and conversion to new PCI dma mapping
- * infrastructure by David S. Miller <davem@redhat.com>.
+ * Additional credits:
+ * Pete Wyckoff <wyckoff@ca.sandia.gov>: Initial Linux/Alpha and trace
+ * dump support. The trace dump support has not been
+ * integrated yet however.
+ * Troy Benjegerdes: Big Endian (PPC) patches.
+ * Nate Stahl: Better out of memory handling and stats support.
+ * Aman Singla: Nasty race between interrupt handler and tx code dealing
+ * with 'testing the tx_ret_csm and setting tx_full'
+ * David S. Miller <davem@redhat.com>: conversion to new PCI dma mapping
+ * infrastructure and Sparc support
+ * Pierrick Pinasseau (CERN): For lending me an Ultra 5 to test the
+ * driver under Linux/Sparc64
*/
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/version.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/ioport.h>
@@ -38,6 +45,10 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/mm.h>
+
+#undef ETHTOOL
+#undef INDEX_DEBUG
+
#ifdef ETHTOOL
#include <linux/ethtool.h>
#endif
@@ -85,6 +96,62 @@
#define wmb() mb()
#endif
+#ifndef __exit
+#define __exit
+#endif
+
+#if (LINUX_VERSION_CODE < 0x02030e)
+#define net_device device
+#endif
+
+#if (LINUX_VERSION_CODE >= 0x02031b)
+#define NEW_NETINIT
+#endif
+
+#if (LINUX_VERSION_CODE < 0x02032a)
+typedef u32 dma_addr_t;
+
+static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+ dma_addr_t *dma_handle)
+{
+ void *virt_ptr;
+
+ virt_ptr = kmalloc(size, GFP_KERNEL);
+ *dma_handle = virt_to_bus(virt_ptr);
+ return virt_ptr;
+}
+#define pci_free_consistent(cookie, size, ptr, dma_ptr) kfree(ptr)
+#define pci_map_single(cookie, address, size, dir) virt_to_bus(address)
+#define pci_unmap_single(cookie, address, size, dir)
+#endif
+
+#if (LINUX_VERSION_CODE < 0x02032b)
+/*
+ * SoftNet
+ */
+#define dev_kfree_skb_irq(a) dev_kfree_skb(a)
+#define netif_wake_queue(dev) clear_bit(0, &dev->tbusy)
+#define netif_stop_queue(dev) set_bit(0, &dev->tbusy)
+
+static inline void netif_start_queue(struct net_device *dev)
+{
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+}
+
+#define ace_mark_net_bh(foo) mark_bh(foo)
+#define ace_if_busy(dev) dev->tbusy
+#define ace_if_running(dev) dev->start
+#define ace_if_down(dev) {do{dev->start = 0;}while (0);}
+#else
+#define NET_BH 0
+#define ace_mark_net_bh(foo) {do{} while(0);}
+#define ace_if_busy(dev) netif_queue_stopped(dev)
+#define ace_if_running(dev) netif_running(dev)
+#define ace_if_down(dev) {do{} while(0);}
+#endif
+
#include "acenic.h"
/*
@@ -98,9 +165,10 @@
/*
* This driver currently supports Tigon I and Tigon II based cards
- * including the Alteon AceNIC and the 3Com 3C985. The driver should
- * also work on the NetGear GA620, however I have not been able to
- * test that myself.
+ * including the Alteon AceNIC, the 3Com 3C985[B] and NetGear
+ * GA620. The driver should also work on the SGI, DEC and Farallon
+ * versions of the card, however I have not been able to test that
+ * myself.
*
* This card is really neat, it supports receive hardware checksumming
* and jumbo frames (up to 9000 bytes) and does a lot of work in the
@@ -269,10 +337,14 @@
#define ACE_JUMBO_BUFSIZE (ACE_JUMBO_MTU + ETH_HLEN + 2+4+16)
#define DEF_TX_RATIO 24
-#define DEF_TX_COAL 1000
+/*
+ * There seems to be a magic difference in the effect between 995 and 996
+ * but little difference between 900 and 995 ... no idea why.
+ */
+#define DEF_TX_COAL 996
#define DEF_TX_MAX_DESC 40
#define DEF_RX_COAL 1000
-#define DEF_RX_MAX_DESC 20
+#define DEF_RX_MAX_DESC 25
#define TX_COAL_INTS_ONLY 0 /* seems not worth it */
#define DEF_TRACE 0
#define DEF_STAT 2 * TICKS_PER_SEC
@@ -286,115 +358,29 @@ static int max_rx_desc[8] = {0, };
static int tx_ratio[8] = {0, };
static int dis_pci_mem_inval[8] = {1, 1, 1, 1, 1, 1, 1, 1};
-static const char __initdata *version = "acenic.c: v0.34 09/03/99 Jes Sorensen (Jes.Sorensen@cern.ch)\n";
+static const char __initdata *version =
+ "acenic.c: v0.41 02/16/2000 Jes Sorensen, linux-acenic@SunSITE.auc.dk\n"
+ " http://home.cern.ch/~jes/gige/acenic.html\n";
static struct net_device *root_dev = NULL;
static int probed __initdata = 0;
-void ace_free_descriptors(struct net_device *dev)
-{
- struct ace_private *ap = dev->priv;
- int size;
- if (ap->rx_std_ring != NULL) {
- size = (sizeof(struct rx_desc) *
- (RX_STD_RING_ENTRIES +
- RX_JUMBO_RING_ENTRIES +
- RX_MINI_RING_ENTRIES +
- RX_RETURN_RING_ENTRIES));
- pci_free_consistent(ap->pdev, size,
- ap->rx_std_ring,
- ap->rx_ring_base_dma);
- ap->rx_std_ring = NULL;
- ap->rx_jumbo_ring = NULL;
- ap->rx_mini_ring = NULL;
- ap->rx_return_ring = NULL;
- }
- if (ap->evt_ring != NULL) {
- size = (sizeof(struct event) * EVT_RING_ENTRIES);
- pci_free_consistent(ap->pdev, size,
- ap->evt_ring,
- ap->evt_ring_dma);
- ap->evt_ring = NULL;
- }
- if (ap->evt_prd != NULL) {
- pci_free_consistent(ap->pdev, sizeof(u32),
- (void *)ap->evt_prd, ap->evt_prd_dma);
- ap->evt_prd = NULL;
- }
- if (ap->rx_ret_prd != NULL) {
- pci_free_consistent(ap->pdev, sizeof(u32),
- (void *)ap->rx_ret_prd, ap->rx_ret_prd_dma);
- ap->rx_ret_prd = NULL;
- }
- if (ap->tx_csm != NULL) {
- pci_free_consistent(ap->pdev, sizeof(u32),
- (void *)ap->tx_csm, ap->tx_csm_dma);
- ap->tx_csm = NULL;
- }
-}
-
-int ace_allocate_descriptors(struct net_device *dev)
+#ifdef NEW_NETINIT
+int __init acenic_probe (void)
+#else
+int __init acenic_probe (struct net_device *dev)
+#endif
{
- struct ace_private *ap = dev->priv;
- int size;
-
- size = (sizeof(struct rx_desc) *
- (RX_STD_RING_ENTRIES +
- RX_JUMBO_RING_ENTRIES +
- RX_MINI_RING_ENTRIES +
- RX_RETURN_RING_ENTRIES));
-
- ap->rx_std_ring = pci_alloc_consistent(ap->pdev, size,
- &ap->rx_ring_base_dma);
- if (ap->rx_std_ring == NULL)
- goto fail;
-
- ap->rx_jumbo_ring = ap->rx_std_ring + RX_STD_RING_ENTRIES;
- ap->rx_mini_ring = ap->rx_jumbo_ring + RX_JUMBO_RING_ENTRIES;
- ap->rx_return_ring = ap->rx_mini_ring + RX_MINI_RING_ENTRIES;
-
- size = (sizeof(struct event) * EVT_RING_ENTRIES);
-
- ap->evt_ring = pci_alloc_consistent(ap->pdev, size,
- &ap->evt_ring_dma);
-
- if (ap->evt_ring == NULL)
- goto fail;
-
- ap->evt_prd = pci_alloc_consistent(ap->pdev, sizeof(u32),
- &ap->evt_prd_dma);
- if (ap->evt_prd == NULL)
- goto fail;
-
- ap->rx_ret_prd = pci_alloc_consistent(ap->pdev, sizeof(u32),
- &ap->rx_ret_prd_dma);
- if (ap->rx_ret_prd == NULL)
- goto fail;
-
- ap->tx_csm = pci_alloc_consistent(ap->pdev, sizeof(u32),
- &ap->tx_csm_dma);
- if (ap->tx_csm == NULL)
- goto fail;
-
- return 0;
-
-fail:
- /* Clean up. */
- ace_free_descriptors(dev);
- iounmap(ap->regs);
- unregister_netdev(dev);
- return 1;
-}
+#ifdef NEW_NETINIT
+ struct net_device *dev;
+#endif
-static int __init acenic_probe(void)
-{
- int boards_found = 0;
- int version_disp;
struct ace_private *ap;
struct pci_dev *pdev = NULL;
- struct net_device *dev;
+ int boards_found = 0;
+ int version_disp;
if (probed)
return -ENODEV;
@@ -405,7 +391,7 @@ static int __init acenic_probe(void)
version_disp = 0;
- while ((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET<<8, pdev))){
+ while ((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET<<8, pdev))) {
if (!((pdev->vendor == PCI_VENDOR_ID_ALTEON) &&
(pdev->device == PCI_DEVICE_ID_ALTEON_ACENIC)) &&
@@ -425,24 +411,23 @@ static int __init acenic_probe(void)
dev = init_etherdev(NULL, sizeof(struct ace_private));
- if (dev == NULL){
- printk(KERN_ERR "acenic: Unable to allocate net_device "
- "structure!\n");
+ if (dev == NULL) {
+ printk(KERN_ERR "acenic: Unable to allocate "
+ "net_device structure!\n");
break;
}
if (!dev->priv)
dev->priv = kmalloc(sizeof(*ap), GFP_KERNEL);
- if (!dev->priv)
- {
- printk(KERN_ERR "acenic: Unable to allocate memory.\n");
+ if (!dev->priv) {
+ printk(KERN_ERR "acenic: Unable to allocate memory\n");
return -ENOMEM;
}
+
ap = dev->priv;
ap->pdev = pdev;
dev->irq = pdev->irq;
-
dev->open = &ace_open;
dev->hard_start_xmit = &ace_start_xmit;
dev->stop = &ace_close;
@@ -463,9 +448,20 @@ static int __init acenic_probe(void)
pci_read_config_word(pdev, PCI_COMMAND, &ap->pci_command);
+ /* OpenFirmware on Mac's does not set this - DOH.. */
+ if (!ap->pci_command & PCI_COMMAND_MEMORY) {
+ printk(KERN_INFO "%s: Enabling PCI Memory Mapped "
+ "access - was not enabled by BIOS/Firmware\n",
+ dev->name);
+ ap->pci_command = ap->pci_command | PCI_COMMAND_MEMORY;
+ pci_write_config_word(ap->pdev, PCI_COMMAND,
+ ap->pci_command);
+ wmb();
+ }
+
pci_read_config_byte(pdev, PCI_LATENCY_TIMER,
&ap->pci_latency);
- if (ap->pci_latency <= 0x40){
+ if (ap->pci_latency <= 0x40) {
ap->pci_latency = 0x40;
pci_write_config_byte(pdev, PCI_LATENCY_TIMER,
ap->pci_latency);
@@ -477,53 +473,68 @@ static int __init acenic_probe(void)
/* NOTE: Cache line size is in 32-bit word units. */
pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x10);
#endif
+
/*
* Remap the regs into kernel space - this is abuse of
* dev->base_addr since it was means for I/O port
* addresses but who gives a damn.
*/
+#if (LINUX_VERSION_CODE < 0x02030d)
+ dev->base_addr = pdev->base_address[0];
+#else
dev->base_addr = pdev->resource[0].start;
+#endif
ap->regs = (struct ace_regs *)ioremap(dev->base_addr, 0x4000);
- if (!ap->regs){
+ if (!ap->regs) {
printk(KERN_ERR "%s: Unable to map I/O register, "
"AceNIC %i will be disabled.\n",
dev->name, boards_found);
break;
}
- switch(pdev->vendor){
+ switch(pdev->vendor) {
case PCI_VENDOR_ID_ALTEON:
- sprintf(ap->name, "AceNIC Gigabit Ethernet");
+ strncpy(ap->name, "AceNIC Gigabit Ethernet",
+ sizeof (ap->name));
printk(KERN_INFO "%s: Alteon AceNIC ", dev->name);
break;
case PCI_VENDOR_ID_3COM:
- sprintf(ap->name, "3Com 3C985 Gigabit Ethernet");
+ strncpy(ap->name, "3Com 3C985 Gigabit Ethernet",
+ sizeof (ap->name));
printk(KERN_INFO "%s: 3Com 3C985 ", dev->name);
break;
case PCI_VENDOR_ID_NETGEAR:
- sprintf(ap->name, "NetGear GA620 Gigabit Ethernet");
+ strncpy(ap->name, "NetGear GA620 Gigabit Ethernet",
+ sizeof (ap->name));
printk(KERN_INFO "%s: NetGear GA620 ", dev->name);
break;
case PCI_VENDOR_ID_DEC:
if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX) {
- sprintf(ap->name, "Farallon PN9000-SX "
- "Gigabit Ethernet");
+ strncpy(ap->name, "Farallon PN9000-SX "
+ "Gigabit Ethernet", sizeof (ap->name));
printk(KERN_INFO "%s: Farallon PN9000-SX ",
dev->name);
break;
}
case PCI_VENDOR_ID_SGI:
- sprintf(ap->name, "SGI AceNIC Gigabit Ethernet");
+ strncpy(ap->name, "SGI AceNIC Gigabit Ethernet",
+ sizeof (ap->name));
printk(KERN_INFO "%s: SGI AceNIC ", dev->name);
break;
default:
- sprintf(ap->name, "Unknown AceNIC based Gigabit Ethernet");
+ strncpy(ap->name, "Unknown AceNIC based Gigabit "
+ "Ethernet", sizeof (ap->name));
printk(KERN_INFO "%s: Unknown AceNIC ", dev->name);
break;
}
- printk("Gigabit Ethernet at 0x%08lx, irq %i\n",
- dev->base_addr, dev->irq);
+ ap->name [sizeof (ap->name) - 1] = '\0';
+ printk("Gigabit Ethernet at 0x%08lx, ", dev->base_addr);
+#ifdef __sparc__
+ printk("irq %s\n", __irq_itoa(dev->irq));
+#else
+ printk("irq %i\n", dev->irq);
+#endif
#ifdef CONFIG_ACENIC_OMIT_TIGON_I
if ((readl(&ap->regs->HostCtrl) >> 28) == 4) {
@@ -566,6 +577,7 @@ static int __init acenic_probe(void)
}
+#ifdef MODULE
MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@cern.ch>");
MODULE_DESCRIPTION("AceNIC/3C985 Gigabit Ethernet driver");
MODULE_PARM(link, "1-" __MODULE_STRING(8) "i");
@@ -576,25 +588,14 @@ MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i");
MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i");
-static int __init acenic_init_module (void)
-{
- int cards;
-
- root_dev = NULL;
-
- cards = acenic_probe();
- return cards ? 0 : -ENODEV;
-}
-
-
-static void __exit acenic_cleanup_module (void)
+void __exit ace_module_cleanup(void)
{
struct ace_private *ap;
struct ace_regs *regs;
struct net_device *next;
short i;
- while (root_dev){
+ while (root_dev) {
next = ((struct ace_private *)root_dev->priv)->next;
ap = (struct ace_private *)root_dev->priv;
@@ -607,7 +608,7 @@ static void __exit acenic_cleanup_module (void)
/*
* This clears any pending interrupts
*/
- writel(0, &regs->Mb0Lo);
+ writel(1, &regs->Mb0Lo);
/*
* Make sure no other CPUs are processing interrupts
@@ -629,11 +630,11 @@ static void __exit acenic_cleanup_module (void)
mapping = ap->skb->rx_std_skbuff[i].mapping;
ap->rx_std_ring[i].size = 0;
- set_aceaddr(&ap->rx_std_ring[i].addr, 0);
+ ap->skb->rx_std_skbuff[i].skb = NULL;
pci_unmap_single(ap->pdev, mapping,
- ACE_STD_BUFSIZE - (2 + 16));
+ ACE_STD_BUFSIZE - (2 + 16),
+ PCI_DMA_FROMDEVICE);
dev_kfree_skb(skb);
- ap->skb->rx_std_skbuff[i].skb = NULL;
}
}
if (ap->version >= 2) {
@@ -644,34 +645,183 @@ static void __exit acenic_cleanup_module (void)
dma_addr_t mapping;
mapping = ap->skb->rx_mini_skbuff[i].mapping;
-
ap->rx_mini_ring[i].size = 0;
- set_aceaddr(&ap->rx_mini_ring[i].addr, 0);
+ ap->skb->rx_mini_skbuff[i].skb = NULL;
pci_unmap_single(ap->pdev, mapping,
- ACE_MINI_BUFSIZE - (2 + 16));
+ ACE_MINI_BUFSIZE - (2 + 16),
+ PCI_DMA_FROMDEVICE);
dev_kfree_skb(skb);
}
}
}
+ for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++) {
+ struct sk_buff *skb = ap->skb->rx_jumbo_skbuff[i].skb;
+ if (skb) {
+ dma_addr_t mapping;
+
+ mapping = ap->skb->rx_jumbo_skbuff[i].mapping;
+
+ ap->rx_jumbo_ring[i].size = 0;
+ ap->skb->rx_jumbo_skbuff[i].skb = NULL;
+ pci_unmap_single(ap->pdev, mapping,
+ ACE_JUMBO_BUFSIZE - (2 + 16),
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(skb);
+ }
+ }
ace_free_descriptors(root_dev);
- iounmap(regs);
- if(ap->trace_buf)
+ if (ap->trace_buf)
kfree(ap->trace_buf);
- pci_free_consistent(ap->pdev, sizeof(struct ace_info),
- ap->info, ap->info_dma);
- kfree(ap->skb);
- free_irq(root_dev->irq, root_dev);
+ if (ap->info)
+ pci_free_consistent(ap->pdev, sizeof(struct ace_info),
+ ap->info, ap->info_dma);
+ if (ap->skb)
+ kfree(ap->skb);
+ if (root_dev->irq)
+ free_irq(root_dev->irq, root_dev);
unregister_netdev(root_dev);
+ iounmap(regs);
kfree(root_dev);
root_dev = next;
}
}
-module_init(acenic_init_module);
-module_exit(acenic_cleanup_module);
+
+int __init ace_module_init(void)
+{
+ int cards;
+
+ root_dev = NULL;
+
+#ifdef NEW_NETINIT
+ cards = acenic_probe();
+#else
+ cards = acenic_probe(NULL);
+#endif
+ return cards ? 0 : -ENODEV;
+}
+
+
+#if (LINUX_VERSION_CODE < 0x02032a)
+int init_module(void)
+{
+ return ace_module_init();
+}
+
+
+void cleanup_module(void)
+{
+ ace_module_cleanup();
+}
+#endif
+#endif
+
+
+#if (LINUX_VERSION_CODE >= 0x02032a)
+module_init(ace_module_init);
+module_exit(ace_module_cleanup);
+#endif
+
+
+static void ace_free_descriptors(struct net_device *dev)
+{
+ struct ace_private *ap = dev->priv;
+ int size;
+
+ if (ap->rx_std_ring != NULL) {
+ size = (sizeof(struct rx_desc) *
+ (RX_STD_RING_ENTRIES +
+ RX_JUMBO_RING_ENTRIES +
+ RX_MINI_RING_ENTRIES +
+ RX_RETURN_RING_ENTRIES));
+ pci_free_consistent(ap->pdev, size,
+ ap->rx_std_ring,
+ ap->rx_ring_base_dma);
+ ap->rx_std_ring = NULL;
+ ap->rx_jumbo_ring = NULL;
+ ap->rx_mini_ring = NULL;
+ ap->rx_return_ring = NULL;
+ }
+ if (ap->evt_ring != NULL) {
+ size = (sizeof(struct event) * EVT_RING_ENTRIES);
+ pci_free_consistent(ap->pdev, size,
+ ap->evt_ring,
+ ap->evt_ring_dma);
+ ap->evt_ring = NULL;
+ }
+ if (ap->evt_prd != NULL) {
+ pci_free_consistent(ap->pdev, sizeof(u32),
+ (void *)ap->evt_prd, ap->evt_prd_dma);
+ ap->evt_prd = NULL;
+ }
+ if (ap->rx_ret_prd != NULL) {
+ pci_free_consistent(ap->pdev, sizeof(u32),
+ (void *)ap->rx_ret_prd, ap->rx_ret_prd_dma);
+ ap->rx_ret_prd = NULL;
+ }
+ if (ap->tx_csm != NULL) {
+ pci_free_consistent(ap->pdev, sizeof(u32),
+ (void *)ap->tx_csm, ap->tx_csm_dma);
+ ap->tx_csm = NULL;
+ }
+}
+
+
+static int ace_allocate_descriptors(struct net_device *dev)
+{
+ struct ace_private *ap = dev->priv;
+ int size;
+
+ size = (sizeof(struct rx_desc) *
+ (RX_STD_RING_ENTRIES +
+ RX_JUMBO_RING_ENTRIES +
+ RX_MINI_RING_ENTRIES +
+ RX_RETURN_RING_ENTRIES));
+
+ ap->rx_std_ring = pci_alloc_consistent(ap->pdev, size,
+ &ap->rx_ring_base_dma);
+ if (ap->rx_std_ring == NULL)
+ goto fail;
+
+ ap->rx_jumbo_ring = ap->rx_std_ring + RX_STD_RING_ENTRIES;
+ ap->rx_mini_ring = ap->rx_jumbo_ring + RX_JUMBO_RING_ENTRIES;
+ ap->rx_return_ring = ap->rx_mini_ring + RX_MINI_RING_ENTRIES;
+
+ size = (sizeof(struct event) * EVT_RING_ENTRIES);
+
+ ap->evt_ring = pci_alloc_consistent(ap->pdev, size,
+ &ap->evt_ring_dma);
+
+ if (ap->evt_ring == NULL)
+ goto fail;
+
+ ap->evt_prd = pci_alloc_consistent(ap->pdev, sizeof(u32),
+ &ap->evt_prd_dma);
+ if (ap->evt_prd == NULL)
+ goto fail;
+
+ ap->rx_ret_prd = pci_alloc_consistent(ap->pdev, sizeof(u32),
+ &ap->rx_ret_prd_dma);
+ if (ap->rx_ret_prd == NULL)
+ goto fail;
+
+ ap->tx_csm = pci_alloc_consistent(ap->pdev, sizeof(u32),
+ &ap->tx_csm_dma);
+ if (ap->tx_csm == NULL)
+ goto fail;
+
+ return 0;
+
+fail:
+ /* Clean up. */
+ ace_free_descriptors(dev);
+ iounmap(ap->regs);
+ unregister_netdev(dev);
+ return 1;
+}
/*
@@ -694,19 +844,38 @@ static int __init ace_init(struct net_device *dev, int board_idx)
{
struct ace_private *ap;
struct ace_regs *regs;
- struct ace_info *info;
+ struct ace_info *info = NULL;
unsigned long tmp_ptr, myjif;
u32 tig_ver, mac1, mac2, tmp, pci_state;
+ int ecode = 0;
short i;
ap = dev->priv;
regs = ap->regs;
/*
+ * aman@sgi.com - its useful to do a NIC reset here to
+ * address the `Firmware not running' problem subsequent
+ * to any crashes involving the NIC
+ */
+ writel(HW_RESET | (HW_RESET << 24), &regs->HostCtrl);
+ wmb();
+
+ /*
* Don't access any other registes before this point!
*/
+#ifdef __BIG_ENDIAN
+ /*
+ * This will most likely need BYTE_SWAP once we switch
+ * to using __raw_writel()
+ */
+ writel((WORD_SWAP | CLR_INT |
+ ((WORD_SWAP | CLR_INT) << 24)),
+ &regs->HostCtrl);
+#else
writel((CLR_INT | WORD_SWAP | ((CLR_INT | WORD_SWAP) << 24)),
&regs->HostCtrl);
+#endif
mb();
/*
@@ -720,7 +889,7 @@ static int __init ace_init(struct net_device *dev, int board_idx)
switch(tig_ver){
#ifndef CONFIG_ACENIC_OMIT_TIGON_I
case 4:
- printk(KERN_INFO" Tigon I (Rev. 4), Firmware: %i.%i.%i, ",
+ printk(KERN_INFO" Tigon I (Rev. 4), Firmware: %i.%i.%i, ",
tigonFwReleaseMajor, tigonFwReleaseMinor,
tigonFwReleaseFix);
writel(0, &regs->LocalCtrl);
@@ -732,6 +901,11 @@ static int __init ace_init(struct net_device *dev, int board_idx)
tig_ver, tigon2FwReleaseMajor, tigon2FwReleaseMinor,
tigon2FwReleaseFix);
writel(readl(&regs->CpuBCtrl) | CPU_HALT, &regs->CpuBCtrl);
+ /*
+ * The SRAM bank size does _not_ indicate the amount
+ * of memory on the card, it controls the _bank_ size!
+ * Ie. a 1MB AceNIC will have two banks of 512KB.
+ */
writel(SRAM_BANK_512K, &regs->LocalCtrl);
writel(SYNC_SRAM_TIMING, &regs->MiscCfg);
ap->version = 2;
@@ -739,7 +913,8 @@ static int __init ace_init(struct net_device *dev, int board_idx)
default:
printk(KERN_INFO" Unsupported Tigon version detected (%i), ",
tig_ver);
- return -ENODEV;
+ ecode = -ENODEV;
+ goto init_error;
}
/*
@@ -749,18 +924,34 @@ static int __init ace_init(struct net_device *dev, int board_idx)
* value a second time works as well. This is what caused the
* `Firmware not running' problem on the Tigon II.
*/
- writel(ACE_BYTE_SWAP_DATA | ACE_WARN | ACE_FATAL |
- ACE_WORD_SWAP | ACE_NO_JUMBO_FRAG, &regs->ModeStat);
+#ifdef __BIG_ENDIAN
+ writel(ACE_BYTE_SWAP_DMA | ACE_WARN | ACE_FATAL | ACE_BYTE_SWAP_BD |
+ ACE_WORD_SWAP_BD | ACE_NO_JUMBO_FRAG, &regs->ModeStat);
+#else
+ writel(ACE_BYTE_SWAP_DMA | ACE_WARN | ACE_FATAL |
+ ACE_WORD_SWAP_BD | ACE_NO_JUMBO_FRAG, &regs->ModeStat);
+#endif
+ mb();
mac1 = 0;
- for(i = 0; i < 4; i++){
+ for(i = 0; i < 4; i++) {
mac1 = mac1 << 8;
- mac1 |= read_eeprom_byte(regs, 0x8c+i);
+ tmp = read_eeprom_byte(dev, 0x8c+i);
+ if (tmp < 0) {
+ ecode = -EIO;
+ goto init_error;
+ } else
+ mac1 |= (tmp & 0xff);
}
mac2 = 0;
- for(i = 4; i < 8; i++){
+ for(i = 4; i < 8; i++) {
mac2 = mac2 << 8;
- mac2 |= read_eeprom_byte(regs, 0x8c+i);
+ tmp = read_eeprom_byte(dev, 0x8c+i);
+ if (tmp < 0) {
+ ecode = -EIO;
+ goto init_error;
+ } else
+ mac2 |= (tmp & 0xff);
}
writel(mac1, &regs->MacAddrHi);
@@ -778,8 +969,11 @@ static int __init ace_init(struct net_device *dev, int board_idx)
dev->dev_addr[5] = mac2 & 0xff;
pci_state = readl(&regs->PciState);
- printk(KERN_INFO " PCI bus speed: %iMHz, latency: %i clks\n",
- (pci_state & PCI_66MHZ) ? 66 : 33, ap->pci_latency);
+ printk(KERN_INFO " PCI bus width: %i bits, speed: %iMHz, "
+ "latency: %i clks\n",
+ (pci_state & PCI_32BIT) ? 32 : 64,
+ (pci_state & PCI_66MHZ) ? 66 : 33,
+ ap->pci_latency);
/*
* Set the max DMA transfer size. Seems that for most systems
@@ -792,7 +986,7 @@ static int __init ace_init(struct net_device *dev, int board_idx)
* - that is what Alteon does for NT.
*/
tmp = READ_CMD_MEM | WRITE_CMD_MEM;
- if (ap->version >= 2){
+ if (ap->version >= 2) {
tmp |= (MEM_READ_MULTIPLE | (pci_state & PCI_66MHZ));
/*
* Tuning parameters only supported for 8 cards
@@ -805,11 +999,11 @@ static int __init ace_init(struct net_device *dev, int board_idx)
printk(KERN_INFO "%s: disabling PCI memory "
"write and invalidate\n", dev->name);
}
- } else if (ap->pci_command & PCI_COMMAND_INVALIDATE){
+ } else if (ap->pci_command & PCI_COMMAND_INVALIDATE) {
printk(KERN_INFO "%s: PCI memory write & invalidate "
"enabled by BIOS, enabling counter "
"measures\n", dev->name);
- switch(L1_CACHE_BYTES){
+ switch(L1_CACHE_BYTES) {
case 16:
tmp |= DMA_WRITE_MAX_16;
break;
@@ -829,6 +1023,21 @@ static int __init ace_init(struct net_device *dev, int board_idx)
}
}
}
+#ifdef __sparc__
+ /* On this platform, we know what the best dma settings
+ * are. We use 64-byte maximum bursts, because if we
+ * burst larger than the cache line size (or even cross
+ * a 64byte boundry in a single burst) the UltraSparc
+ * PCI controller will disconnect at 64-byte multiples.
+ *
+ * Read-multiple will be properly enabled above, and when
+ * set will give the PCI controller proper hints about
+ * prefetching.
+ */
+ tmp = (tmp & ~(0xfc));
+ tmp |= DMA_READ_MAX_64;
+ tmp |= DMA_WRITE_MAX_64;
+#endif
writel(tmp, &regs->PciState);
/*
@@ -836,23 +1045,26 @@ static int __init ace_init(struct net_device *dev, int board_idx)
* and the control blocks for the transmit and receive rings
* as they need to be setup once and for all.
*/
- info = pci_alloc_consistent(ap->pdev, sizeof(struct ace_info),
- &ap->info_dma);
- if (info == NULL)
- goto fail;
+ if (!(info = pci_alloc_consistent(ap->pdev, sizeof(struct ace_info),
+ &ap->info_dma))) {
+ ecode = -EAGAIN;
+ goto init_error;
+ }
+ ap->info = info;
/*
* Get the memory for the skb rings.
*/
- if (!(ap->skb = kmalloc(sizeof(struct ace_skb), GFP_KERNEL)))
- goto fail;
-
- memset(ap->skb, 0, sizeof(struct ace_skb));
+ if (!(ap->skb = kmalloc(sizeof(struct ace_skb), GFP_KERNEL))) {
+ ecode = -EAGAIN;
+ goto init_error;
+ }
if (request_irq(dev->irq, ace_interrupt, SA_SHIRQ, ap->name, dev)) {
printk(KERN_WARNING "%s: Requested IRQ %d is busy\n",
dev->name, dev->irq);
- goto fail;
+ ecode = -EAGAIN;
+ goto init_error;
}
/*
@@ -862,7 +1074,15 @@ static int __init ace_init(struct net_device *dev, int board_idx)
ap->next = root_dev;
root_dev = dev;
- ap->info = info;
+#ifdef INDEX_DEBUG
+ spin_lock_init(&ap->debug_lock);
+ ap->last_tx = TX_RING_ENTRIES - 1;
+ ap->last_std_rx = 0;
+ ap->last_mini_rx = 0;
+#endif
+
+ memset(ap->info, 0, sizeof(struct ace_info));
+ memset(ap->skb, 0, sizeof(struct ace_skb));
ace_load_firmware(dev);
ap->fw_running = 0;
@@ -900,14 +1120,14 @@ static int __init ace_init(struct net_device *dev, int board_idx)
set_aceaddr(&info->stats2_ptr, (dma_addr_t) tmp_ptr);
set_aceaddr(&info->rx_std_ctrl.rngptr, ap->rx_ring_base_dma);
- info->rx_std_ctrl.max_len = cpu_to_le16(ACE_STD_MTU + ETH_HLEN + 4);
- info->rx_std_ctrl.flags = cpu_to_le16(RCB_FLG_TCP_UDP_SUM);
+ info->rx_std_ctrl.max_len = ACE_STD_MTU + ETH_HLEN + 4;
+ info->rx_std_ctrl.flags = RCB_FLG_TCP_UDP_SUM;
memset(ap->rx_std_ring, 0,
RX_STD_RING_ENTRIES * sizeof(struct rx_desc));
for (i = 0; i < RX_STD_RING_ENTRIES; i++)
- ap->rx_std_ring[i].flags = cpu_to_le16(BD_FLG_TCP_UDP_SUM);
+ ap->rx_std_ring[i].flags = BD_FLG_TCP_UDP_SUM;
ap->rx_std_skbprd = 0;
atomic_set(&ap->cur_rx_bufs, 0);
@@ -916,14 +1136,13 @@ static int __init ace_init(struct net_device *dev, int board_idx)
(ap->rx_ring_base_dma +
(sizeof(struct rx_desc) * RX_STD_RING_ENTRIES)));
info->rx_jumbo_ctrl.max_len = 0;
- info->rx_jumbo_ctrl.flags = cpu_to_le16(RCB_FLG_TCP_UDP_SUM);
+ info->rx_jumbo_ctrl.flags = RCB_FLG_TCP_UDP_SUM;
memset(ap->rx_jumbo_ring, 0,
RX_JUMBO_RING_ENTRIES * sizeof(struct rx_desc));
for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++)
- ap->rx_jumbo_ring[i].flags =
- cpu_to_le16(BD_FLG_TCP_UDP_SUM | BD_FLG_JUMBO);
+ ap->rx_jumbo_ring[i].flags = BD_FLG_TCP_UDP_SUM | BD_FLG_JUMBO;
ap->rx_jumbo_skbprd = 0;
atomic_set(&ap->cur_jumbo_bufs, 0);
@@ -937,15 +1156,15 @@ static int __init ace_init(struct net_device *dev, int board_idx)
(sizeof(struct rx_desc) *
(RX_STD_RING_ENTRIES +
RX_JUMBO_RING_ENTRIES))));
- info->rx_mini_ctrl.max_len = cpu_to_le16(ACE_MINI_SIZE);
- info->rx_mini_ctrl.flags = cpu_to_le16(RCB_FLG_TCP_UDP_SUM);
+ info->rx_mini_ctrl.max_len = ACE_MINI_SIZE;
+ info->rx_mini_ctrl.flags = RCB_FLG_TCP_UDP_SUM;
for (i = 0; i < RX_MINI_RING_ENTRIES; i++)
ap->rx_mini_ring[i].flags =
- cpu_to_le16(BD_FLG_TCP_UDP_SUM | BD_FLG_MINI);
+ BD_FLG_TCP_UDP_SUM | BD_FLG_MINI;
} else {
set_aceaddr(&info->rx_mini_ctrl.rngptr, 0);
- info->rx_mini_ctrl.flags = cpu_to_le16(RCB_FLG_RNG_DISABLE);
+ info->rx_mini_ctrl.flags = RCB_FLG_RNG_DISABLE;
info->rx_mini_ctrl.max_len = 0;
}
@@ -959,7 +1178,7 @@ static int __init ace_init(struct net_device *dev, int board_idx)
RX_JUMBO_RING_ENTRIES +
RX_MINI_RING_ENTRIES))));
info->rx_return_ctrl.flags = 0;
- info->rx_return_ctrl.max_len = cpu_to_le16(RX_RETURN_RING_ENTRIES);
+ info->rx_return_ctrl.max_len = RX_RETURN_RING_ENTRIES;
memset(ap->rx_return_ring, 0,
RX_RETURN_RING_ENTRIES * sizeof(struct rx_desc));
@@ -969,14 +1188,14 @@ static int __init ace_init(struct net_device *dev, int board_idx)
writel(TX_RING_BASE, &regs->WinBase);
ap->tx_ring = (struct tx_desc *)regs->Window;
- for (i = 0; i < (TX_RING_ENTRIES * sizeof(struct tx_desc) / 4); i++){
+ for (i = 0; i < (TX_RING_ENTRIES * sizeof(struct tx_desc) / 4); i++) {
writel(0, (unsigned long)ap->tx_ring + i * 4);
}
set_aceaddr(&info->tx_ctrl.rngptr, TX_RING_BASE);
- info->tx_ctrl.max_len = cpu_to_le16(TX_RING_ENTRIES);
+ info->tx_ctrl.max_len = TX_RING_ENTRIES;
#if TX_COAL_INTS_ONLY
- info->tx_ctrl.flags = cpu_to_le16(RCB_FLG_COAL_INT_ONLY);
+ info->tx_ctrl.flags = RCB_FLG_COAL_INT_ONLY;
#else
info->tx_ctrl.flags = 0;
#endif
@@ -1044,7 +1263,7 @@ static int __init ace_init(struct net_device *dev, int board_idx)
tmp = LNK_ENABLE;
- if (option & 0x01){
+ if (option & 0x01) {
printk(KERN_INFO "%s: Setting half duplex link\n",
dev->name);
tmp &= ~LNK_FULL_DUPLEX;
@@ -1057,7 +1276,7 @@ static int __init ace_init(struct net_device *dev, int board_idx)
tmp |= LNK_100MB;
if (option & 0x40)
tmp |= LNK_1000MB;
- if ((option & 0x70) == 0){
+ if ((option & 0x70) == 0) {
printk(KERN_WARNING "%s: No media speed specified, "
"forcing auto negotiation\n", dev->name);
tmp |= LNK_NEGOTIATE | LNK_1000MB |
@@ -1070,7 +1289,7 @@ static int __init ace_init(struct net_device *dev, int board_idx)
"negotiation\n", dev->name);
if (option & 0x200)
tmp |= LNK_RX_FLOW_CTL_Y;
- if ((option & 0x400) && (ap->version >= 2)){
+ if ((option & 0x400) && (ap->version >= 2)) {
printk(KERN_INFO "%s: Enabling TX flow control\n",
dev->name);
tmp |= LNK_TX_FLOW_CTL_Y;
@@ -1100,7 +1319,7 @@ static int __init ace_init(struct net_device *dev, int board_idx)
ap->tx_prd = *(ap->tx_csm) = ap->tx_ret_csm = 0;
wmb();
- writel(0, &regs->TxPrd);
+ ace_set_txprd(regs, ap, 0);
writel(0, &regs->RxRetCsm);
/*
@@ -1113,11 +1332,31 @@ static int __init ace_init(struct net_device *dev, int board_idx)
*/
myjif = jiffies + 3 * HZ;
while (time_before(jiffies, myjif) && !ap->fw_running);
- if (!ap->fw_running){
+
+ if (!ap->fw_running) {
printk(KERN_ERR "%s: Firmware NOT running!\n", dev->name);
+
ace_dump_trace(ap);
writel(readl(&regs->CpuCtrl) | CPU_HALT, &regs->CpuCtrl);
- return -EBUSY;
+
+ /* aman@sgi.com - account for badly behaving firmware/NIC:
+ * - have observed that the NIC may continue to generate
+ * interrupts for some reason; attempt to stop it - halt
+ * second CPU for Tigon II cards, and also clear Mb0
+ * - if we're a module, we'll fail to load if this was
+ * the only GbE card in the system => if the kernel does
+ * see an interrupt from the NIC, code to handle it is
+ * gone and OOps! - so free_irq also
+ */
+ if (ap->version >= 2)
+ writel(readl(&regs->CpuBCtrl) | CPU_HALT,
+ &regs->CpuBCtrl);
+ writel(0, &regs->Mb0Lo);
+ free_irq(dev->irq, dev);
+ dev->irq = 0;
+
+ ecode = -EBUSY;
+ goto init_error;
}
/*
@@ -1137,17 +1376,17 @@ static int __init ace_init(struct net_device *dev, int board_idx)
"the RX mini ring\n", dev->name);
}
return 0;
-
-fail:
- if (info != NULL)
- pci_free_consistent(ap->pdev, sizeof(struct ace_info),
- info, ap->info_dma);
- if (ap->skb != NULL) {
+ init_error:
+ iounmap(ap->regs);
+ unregister_netdev(dev);
+ if (ap->skb) {
kfree(ap->skb);
ap->skb = NULL;
}
-
- return -EAGAIN;
+ if (ap->info)
+ pci_free_consistent(ap->pdev, sizeof(struct ace_info),
+ info, ap->info_dma);
+ return ecode;
}
@@ -1165,7 +1404,7 @@ static void ace_timer(unsigned long data)
* seconds and there is data in the transmit queue, thus we
* asume the card is stuck.
*/
- if (le32_to_cpu(*(ap->tx_csm)) != ap->tx_ret_csm){
+ if (*ap->tx_csm != ap->tx_ret_csm) {
printk(KERN_WARNING "%s: Transmitter is stuck, %08x\n",
dev->name, (unsigned int)readl(&regs->HostCtrl));
}
@@ -1248,23 +1487,30 @@ static void ace_load_std_rx_ring(struct ace_private *ap, int nr_bufs)
dma_addr_t mapping;
skb = alloc_skb(ACE_STD_BUFSIZE, GFP_ATOMIC);
+ if (!skb)
+ break;
+
/*
* Make sure IP header starts on a fresh cache line.
*/
skb_reserve(skb, 2 + 16);
mapping = pci_map_single(ap->pdev, skb->data,
- ACE_STD_BUFSIZE - (2 + 16));
+ ACE_STD_BUFSIZE - (2 + 16),
+ PCI_DMA_FROMDEVICE);
ap->skb->rx_std_skbuff[idx].skb = skb;
ap->skb->rx_std_skbuff[idx].mapping = mapping;
rd = &ap->rx_std_ring[idx];
set_aceaddr(&rd->addr, mapping);
- rd->size = cpu_to_le16(ACE_STD_MTU + ETH_HLEN + 4);
- rd->idx = cpu_to_le16(idx);
+ rd->size = ACE_STD_MTU + ETH_HLEN + 4;
+ rd->idx = idx;
idx = (idx + 1) % RX_STD_RING_ENTRIES;
}
- atomic_add(nr_bufs, &ap->cur_rx_bufs);
+ if (!i)
+ goto error_out;
+
+ atomic_add(i, &ap->cur_rx_bufs);
ap->rx_std_skbprd = idx;
if (ACE_IS_TIGON_I(ap)) {
@@ -1278,8 +1524,14 @@ static void ace_load_std_rx_ring(struct ace_private *ap, int nr_bufs)
wmb();
}
+ out:
clear_bit(0, &ap->std_refill_busy);
return;
+
+ error_out:
+ printk(KERN_INFO "Out of memory when allocating "
+ "standard receive buffers\n");
+ goto out;
}
@@ -1297,31 +1549,43 @@ static void ace_load_mini_rx_ring(struct ace_private *ap, int nr_bufs)
dma_addr_t mapping;
skb = alloc_skb(ACE_MINI_BUFSIZE, GFP_ATOMIC);
+ if (!skb)
+ break;
+
/*
* Make sure the IP header ends up on a fresh cache line
*/
skb_reserve(skb, 2 + 16);
mapping = pci_map_single(ap->pdev, skb->data,
- ACE_MINI_BUFSIZE - (2 + 16));
+ ACE_MINI_BUFSIZE - (2 + 16),
+ PCI_DMA_FROMDEVICE);
ap->skb->rx_mini_skbuff[idx].skb = skb;
ap->skb->rx_mini_skbuff[idx].mapping = mapping;
rd = &ap->rx_mini_ring[idx];
set_aceaddr(&rd->addr, mapping);
- rd->size = cpu_to_le16(ACE_MINI_SIZE);
- rd->idx = cpu_to_le16(idx);
+ rd->size = ACE_MINI_SIZE;
+ rd->idx = idx;
idx = (idx + 1) % RX_MINI_RING_ENTRIES;
}
- atomic_add(nr_bufs, &ap->cur_mini_bufs);
+ if (!i)
+ goto error_out;
+
+ atomic_add(i, &ap->cur_mini_bufs);
ap->rx_mini_skbprd = idx;
writel(idx, &regs->RxMiniPrd);
wmb();
+ out:
clear_bit(0, &ap->mini_refill_busy);
return;
+ error_out:
+ printk(KERN_INFO "Out of memory when allocating "
+ "mini receive buffers\n");
+ goto out;
}
@@ -1344,23 +1608,30 @@ static void ace_load_jumbo_rx_ring(struct ace_private *ap, int nr_bufs)
dma_addr_t mapping;
skb = alloc_skb(ACE_JUMBO_BUFSIZE, GFP_ATOMIC);
+ if (!skb)
+ break;
+
/*
* Make sure the IP header ends up on a fresh cache line
*/
skb_reserve(skb, 2 + 16);
mapping = pci_map_single(ap->pdev, skb->data,
- ACE_JUMBO_BUFSIZE - (2 + 16));
+ ACE_JUMBO_BUFSIZE - (2 + 16),
+ PCI_DMA_FROMDEVICE);
ap->skb->rx_jumbo_skbuff[idx].skb = skb;
ap->skb->rx_jumbo_skbuff[idx].mapping = mapping;
rd = &ap->rx_jumbo_ring[idx];
set_aceaddr(&rd->addr, mapping);
- rd->size = cpu_to_le16(ACE_JUMBO_MTU + ETH_HLEN + 4);
- rd->idx = cpu_to_le16(idx);
+ rd->size = ACE_JUMBO_MTU + ETH_HLEN + 4;
+ rd->idx = idx;
idx = (idx + 1) % RX_JUMBO_RING_ENTRIES;
}
- atomic_add(nr_bufs, &ap->cur_jumbo_bufs);
+ if (!i)
+ goto error_out;
+
+ atomic_add(i, &ap->cur_jumbo_bufs);
ap->rx_jumbo_skbprd = idx;
if (ACE_IS_TIGON_I(ap)) {
@@ -1374,52 +1645,13 @@ static void ace_load_jumbo_rx_ring(struct ace_private *ap, int nr_bufs)
wmb();
}
+ out:
clear_bit(0, &ap->jumbo_refill_busy);
return;
-}
-
-
-/*
- * Tell the firmware not to accept jumbos and flush the jumbo ring.
- */
-static int ace_flush_jumbo_rx_ring(struct net_device *dev)
-{
- struct ace_private *ap;
- struct ace_regs *regs;
- struct cmd cmd;
- short i;
-
- ap = (struct ace_private *)dev->priv;
- regs = ap->regs;
-
- if (ap->jumbo){
- cmd.evt = C_RESET_JUMBO_RNG;
- cmd.code = 0;
- cmd.idx = 0;
- ace_issue_cmd(regs, &cmd);
-
- for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++) {
- struct sk_buff *skb;
-
- skb = ap->skb->rx_jumbo_skbuff[i].skb;
- if (skb) {
- dma_addr_t mapping;
-
- mapping = ap->skb->rx_jumbo_skbuff[i].mapping;
-
- ap->rx_jumbo_ring[i].size = 0;
- set_aceaddr(&ap->rx_jumbo_ring[i].addr, 0);
- pci_unmap_single(ap->pdev, mapping,
- ACE_JUMBO_BUFSIZE - (2 + 16));
- dev_kfree_skb(skb);
- ap->skb->rx_jumbo_skbuff[i].skb = NULL;
- }
- }
- }else
- printk(KERN_ERR "%s: Trying to flush Jumbo ring without "
- "Jumbo support enabled\n", dev->name);
-
- return 0;
+ error_out:
+ printk(KERN_INFO "Out of memory when allocating "
+ "jumbo receive buffers\n");
+ goto out;
}
@@ -1434,23 +1666,20 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd)
ap = (struct ace_private *)dev->priv;
- while (evtcsm != evtprd){
- struct event evt_local;
-
- memcpy(&evt_local, &ap->evt_ring[evtcsm], sizeof(evt_local));
- evt_local.u.word = le32_to_cpu(evt_local.u.word);
- switch (evt_local.u.data.evt){
+ while (evtcsm != evtprd) {
+ switch (ap->evt_ring[evtcsm].evt) {
case E_FW_RUNNING:
printk(KERN_INFO "%s: Firmware up and running\n",
dev->name);
ap->fw_running = 1;
+ wmb();
break;
case E_STATS_UPDATED:
break;
case E_LNK_STATE:
{
- u16 code = evt_local.u.data.code;
- if (code == E_C_LINK_UP){
+ u16 code = ap->evt_ring[evtcsm].code;
+ if (code == E_C_LINK_UP) {
printk(KERN_WARNING "%s: Optical link UP\n",
dev->name);
}
@@ -1463,7 +1692,7 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd)
break;
}
case E_ERROR:
- switch(evt_local.u.data.code){
+ switch(ap->evt_ring[evtcsm].code) {
case E_C_ERR_INVAL_CMD:
printk(KERN_ERR "%s: invalid command error\n",
dev->name);
@@ -1478,14 +1707,31 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd)
break;
default:
printk(KERN_ERR "%s: unknown error %02x\n",
- dev->name, evt_local.u.data.code);
+ dev->name, ap->evt_ring[evtcsm].code);
}
break;
case E_RESET_JUMBO_RNG:
+ {
+ int i;
+ for (i = 0; i < RX_JUMBO_RING_ENTRIES; i++) {
+ if (ap->skb->rx_jumbo_skbuff[i].skb) {
+ ap->rx_jumbo_ring[i].size = 0;
+ set_aceaddr(&ap->rx_jumbo_ring[i].addr, 0);
+ dev_kfree_skb(ap->skb->rx_jumbo_skbuff[i].skb);
+ ap->skb->rx_jumbo_skbuff[i].skb = NULL;
+ }
+ }
+ ap->jumbo = 0;
+ printk(KERN_INFO "%s: Jumbo ring flushed\n",
+ dev->name);
+ if (!ap->tx_full)
+ netif_wake_queue(dev);
+ clear_bit(0, &ap->jumbo_refill_busy);
break;
+ }
default:
printk(KERN_ERR "%s: Unhandled event 0x%02x\n",
- dev->name, evt_local.u.data.evt);
+ dev->name, ap->evt_ring[evtcsm].evt);
}
evtcsm = (evtcsm + 1) % EVT_RING_ENTRIES;
}
@@ -1502,18 +1748,17 @@ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
idx = rxretcsm;
- while (idx != rxretprd){
+ while (idx != rxretprd) {
struct ring_info *rip;
struct sk_buff *skb;
- struct rx_desc *rxdesc;
- dma_addr_t mapping;
+ struct rx_desc *rxdesc, *retdesc;
u32 skbidx;
int desc_type, mapsize;
u16 csum;
- skbidx = le16_to_cpu(ap->rx_return_ring[idx].idx);
- desc_type = le16_to_cpu(ap->rx_return_ring[idx].flags) &
- (BD_FLG_JUMBO | BD_FLG_MINI);
+ retdesc = &ap->rx_return_ring[idx];
+ skbidx = retdesc->idx;
+ desc_type = retdesc->flags & (BD_FLG_JUMBO | BD_FLG_MINI);
switch(desc_type) {
/*
@@ -1544,27 +1789,23 @@ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
default:
printk(KERN_INFO "%s: unknown frame type (0x%02x) "
"returned by NIC\n", dev->name,
- le16_to_cpu(ap->rx_return_ring[idx].flags));
+ retdesc->flags);
goto error;
}
skb = rip->skb;
- mapping = rip->mapping;
-#if DEBUG
- if (skb == NULL) {
- printk("Mayday! illegal skb received! (idx %i)\n", skbidx);
- goto error;
- }
-#endif
rip->skb = NULL;
- pci_unmap_single(ap->pdev, mapping, mapsize);
- skb_put(skb, le16_to_cpu(rxdesc->size));
+ pci_unmap_single(ap->pdev, rip->mapping, mapsize, PCI_DMA_FROMDEVICE);
+ skb_put(skb, retdesc->size);
+#if 0
+ /* unncessary */
rxdesc->size = 0;
+#endif
/*
* Fly baby, fly!
*/
- csum = le16_to_cpu(ap->rx_return_ring[idx].tcp_udp_csum);
+ csum = retdesc->tcp_udp_csum;
skb->dev = dev;
skb->protocol = eth_type_trans(skb, dev);
@@ -1583,7 +1824,7 @@ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
netif_rx(skb); /* send it up */
ap->stats.rx_packets++;
- ap->stats.rx_bytes += skb->len;
+ ap->stats.rx_bytes += retdesc->size;
idx = (idx + 1) % RX_RETURN_RING_ENTRIES;
}
@@ -1642,13 +1883,13 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
* working on the other stuff - hey we don't need a spin lock
* anymore.
*/
- rxretprd = le32_to_cpu(*(ap->rx_ret_prd));
+ rxretprd = *ap->rx_ret_prd;
rxretcsm = ap->cur_rx;
if (rxretprd != rxretcsm)
ace_rx_int(dev, rxretprd, rxretcsm);
- txcsm = le32_to_cpu(*(ap->tx_csm));
+ txcsm = *ap->tx_csm;
idx = ap->tx_ret_csm;
if (txcsm != idx) {
@@ -1661,9 +1902,8 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
ap->stats.tx_packets++;
ap->stats.tx_bytes += skb->len;
-
- pci_unmap_single(ap->pdev, mapping, skb->len);
- dev_kfree_skb(skb);
+ pci_unmap_single(ap->pdev, mapping, skb->len, PCI_DMA_TODEVICE);
+ dev_kfree_skb_irq(skb);
ap->skb->tx_skbuff[idx].skb = NULL;
@@ -1688,14 +1928,13 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
* Ie. skip the comparison of the tx producer vs. the
* consumer.
*/
- if (ap->tx_full &&
- test_bit(LINK_STATE_XOFF, &dev->state)) {
- ap->tx_full = 0;
+ if (ace_if_busy(dev) && xchg(&ap->tx_full, 0)) {
/*
* This does not need to be atomic (and expensive),
* I've seen cases where it would fail otherwise ;-(
*/
netif_wake_queue(dev);
+ ace_mark_net_bh(NET_BH);
/*
* TX ring is no longer full, aka the
@@ -1709,7 +1948,7 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
}
evtcsm = readl(&regs->EvtCsm);
- evtprd = le32_to_cpu(*(ap->evt_prd));
+ evtprd = *ap->evt_prd;
if (evtcsm != evtprd) {
evtcsm = ace_handle_event(dev, evtcsm, evtprd);
@@ -1720,7 +1959,7 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
* This has to go last in the interrupt handler and run with
* the spin lock released ... what lock?
*/
- if (test_bit(LINK_STATE_START, &dev->state)) {
+ if (ace_if_running(dev)) {
int cur_size;
int run_bh = 0;
@@ -1733,7 +1972,7 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
#endif
ace_load_std_rx_ring(ap,
RX_RING_SIZE - cur_size);
- }
+ } else
run_bh = 1;
}
@@ -1791,13 +2030,23 @@ static int ace_open(struct net_device *dev)
ap = dev->priv;
regs = ap->regs;
- if (!(ap->fw_running)){
+ if (!(ap->fw_running)) {
printk(KERN_WARNING "%s: Firmware not running!\n", dev->name);
return -EBUSY;
}
writel(dev->mtu + ETH_HLEN + 4, &regs->IfMtu);
+ /*
+ * Zero the stats when restarting the interface...
+ */
+ memset(&ap->stats, 0, sizeof(ap->stats));
+
+ cmd.evt = C_CLEAR_STATS;
+ cmd.code = 0;
+ cmd.idx = 0;
+ ace_issue_cmd(regs, &cmd);
+
cmd.evt = C_HOST_STATE;
cmd.code = C_C_STACK_UP;
cmd.idx = 0;
@@ -1807,7 +2056,7 @@ static int ace_open(struct net_device *dev)
!test_and_set_bit(0, &ap->jumbo_refill_busy))
ace_load_jumbo_rx_ring(ap, RX_JUMBO_SIZE);
- if (dev->flags & IFF_PROMISC){
+ if (dev->flags & IFF_PROMISC) {
cmd.evt = C_SET_PROMISC_MODE;
cmd.code = C_C_PROMISC_ENABLE;
cmd.idx = 0;
@@ -1825,6 +2074,8 @@ static int ace_open(struct net_device *dev)
ace_issue_cmd(regs, &cmd);
#endif
+ netif_start_queue(dev);
+
MOD_INC_USE_COUNT;
/*
@@ -1854,6 +2105,7 @@ static int ace_close(struct net_device *dev)
unsigned long flags;
short i;
+ ace_if_down(dev);
netif_stop_queue(dev);
ap = (struct ace_private *)dev->priv;
@@ -1861,7 +2113,7 @@ static int ace_close(struct net_device *dev)
del_timer(&ap->timer);
- if (ap->promisc){
+ if (ap->promisc) {
cmd.evt = C_SET_PROMISC_MODE;
cmd.code = C_C_PROMISC_DISABLE;
cmd.idx = 0;
@@ -1891,13 +2143,18 @@ static int ace_close(struct net_device *dev)
writel(0, &ap->tx_ring[i].addr.addrhi);
writel(0, &ap->tx_ring[i].addr.addrlo);
writel(0, &ap->tx_ring[i].flagsize);
- pci_unmap_single(ap->pdev, mapping, skb->len);
+ pci_unmap_single(ap->pdev, mapping, skb->len, PCI_DMA_TODEVICE);
dev_kfree_skb(skb);
+ ap->skb->tx_skbuff[i].skb = NULL;
}
}
- if (ap->jumbo)
- ace_flush_jumbo_rx_ring(dev);
+ if (ap->jumbo) {
+ cmd.evt = C_RESET_JUMBO_RNG;
+ cmd.code = 0;
+ cmd.idx = 0;
+ ace_issue_cmd(regs, &cmd);
+ }
restore_flags(flags);
@@ -1913,6 +2170,16 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
unsigned long addr;
u32 idx, flagsize;
+ /*
+ * ARGH, there is just no pretty way to do this
+ */
+#if (LINUX_VERSION_CODE < 0x02032b)
+ if (test_and_set_bit(0, &dev->tbusy))
+ return 1;
+#else
+ netif_stop_queue(dev);
+#endif
+
idx = ap->tx_prd;
if ((idx + 1) % TX_RING_ENTRIES == ap->tx_ret_csm) {
@@ -1926,7 +2193,7 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
ap->skb->tx_skbuff[idx].skb = skb;
ap->skb->tx_skbuff[idx].mapping =
- pci_map_single(ap->pdev, skb->data, skb->len);
+ pci_map_single(ap->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
addr = (unsigned long) ap->skb->tx_skbuff[idx].mapping;
#if (BITS_PER_LONG == 64)
writel(addr >> 32, &ap->tx_ring[idx].addr.addrhi);
@@ -1938,14 +2205,13 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
idx = (idx + 1) % TX_RING_ENTRIES;
ap->tx_prd = idx;
- writel(idx, &regs->TxPrd);
- wmb();
+ ace_set_txprd(regs, ap, idx);
/*
* tx_csm is set by the NIC whereas we set tx_ret_csm which
* is always trying to catch tx_csm
*/
- if ((idx + 2) % TX_RING_ENTRIES == ap->tx_ret_csm){
+ if ((idx + 2) % TX_RING_ENTRIES == ap->tx_ret_csm) {
ap->tx_full = 1;
/*
* Queue is full, add timer to detect whether the
@@ -1954,11 +2220,25 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
* timers.
*/
mod_timer(&ap->timer, jiffies + (3 * HZ));
+
+ /* The following check will fix a race between the interrupt
+ * handler increasing the tx_ret_csm and testing for tx_full
+ * and this tx routine's testing the tx_ret_csm and setting
+ * the tx_full; note that this fix makes assumptions on the
+ * ordering of writes (sequential consistency will fly; TSO
+ * processor order would work too) but that's what lock-less
+ * programming is all about
+ */
+ if (((idx + 2) % TX_RING_ENTRIES != ap->tx_ret_csm)
+ && xchg(&ap->tx_full, 0)) {
+ del_timer(&ap->timer);
+ netif_wake_queue(dev);
+ }
} else {
/*
* No need for it to be atomic - seems it needs to be
*/
- netif_stop_queue(dev);
+ netif_wake_queue(dev);
}
dev->trans_start = jiffies;
@@ -1977,23 +2257,27 @@ static int ace_change_mtu(struct net_device *dev, int new_mtu)
writel(new_mtu + ETH_HLEN + 4, &regs->IfMtu);
dev->mtu = new_mtu;
- if (new_mtu > ACE_STD_MTU){
- if (!(ap->jumbo)){
+ if (new_mtu > ACE_STD_MTU) {
+ if (!(ap->jumbo)) {
printk(KERN_INFO "%s: Enabling Jumbo frame "
"support\n", dev->name);
ap->jumbo = 1;
if (!test_and_set_bit(0, &ap->jumbo_refill_busy))
ace_load_jumbo_rx_ring(ap, RX_JUMBO_SIZE);
+ ap->jumbo = 1;
}
- ap->jumbo = 1;
- }else{
+ } else {
+ netif_stop_queue(dev);
+ while (test_and_set_bit(0, &ap->jumbo_refill_busy));
+ synchronize_irq();
if (ap->jumbo){
- ace_flush_jumbo_rx_ring(dev);
+ struct cmd cmd;
- printk(KERN_INFO "%s: Disabling Jumbo frame support\n",
- dev->name);
+ cmd.evt = C_RESET_JUMBO_RNG;
+ cmd.code = 0;
+ cmd.idx = 0;
+ ace_issue_cmd(regs, &cmd);
}
- ap->jumbo = 0;
}
return 0;
@@ -2008,6 +2292,21 @@ static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
struct ethtool_cmd ecmd;
u32 link, speed;
+#ifdef SPIN_DEBUG
+ if (cmd == (SIOCDEVPRIVATE+0x0e)) {
+ printk(KERN_NOTICE "%s: dumping debug info\n", dev->name);
+ printk(KERN_NOTICE "%s: tbusy %li, tx_ret_csm %i, "
+ "tx_prd %i\n", dev->name, dev->tbusy,
+ ap->tx_ret_csm, ap->tx_prd);
+ printk(KERN_NOTICE "%s: cur_rx %i, std_refill %li, "
+ "mini_rx %i, mini_refill %li\n", dev->name,
+ atomic_read(&ap->cur_rx_bufs), ap->std_refill_busy,
+ atomic_read(&ap->cur_mini_bufs), ap->mini_refill_busy);
+ printk(KERN_NOTICE "%s: CpuCtrl %08x\n",
+ dev->name, readl(&regs->CpuCtrl));
+ return 0;
+ }
+#endif
if (cmd != SIOCETHTOOL)
return -EOPNOTSUPP;
if (copy_from_user(&ecmd, ifr->ifr_data, sizeof(ecmd)))
@@ -2130,7 +2429,7 @@ static int ace_set_mac_addr(struct net_device *dev, void *p)
u16 *da;
struct cmd cmd;
- if(test_bit(LINK_STATE_START, &dev->state))
+ if(ace_if_running(dev))
return -EBUSY;
memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
@@ -2162,9 +2461,9 @@ static void ace_set_multicast_list(struct net_device *dev)
cmd.idx = 0;
ace_issue_cmd(regs, &cmd);
ap->mcast_all = 1;
- } else if (ap->mcast_all){
+ } else if (ap->mcast_all) {
cmd.evt = C_SET_MULTICAST_MODE;
- cmd.code = C_C_MCAST_ENABLE;
+ cmd.code = C_C_MCAST_DISABLE;
cmd.idx = 0;
ace_issue_cmd(regs, &cmd);
ap->mcast_all = 0;
@@ -2176,7 +2475,7 @@ static void ace_set_multicast_list(struct net_device *dev)
cmd.idx = 0;
ace_issue_cmd(regs, &cmd);
ap->promisc = 1;
- }else if (!(dev->flags & IFF_PROMISC) && (ap->promisc)){
+ }else if (!(dev->flags & IFF_PROMISC) && (ap->promisc)) {
cmd.evt = C_SET_PROMISC_MODE;
cmd.code = C_C_PROMISC_DISABLE;
cmd.idx = 0;
@@ -2207,28 +2506,38 @@ static void ace_set_multicast_list(struct net_device *dev)
static struct net_device_stats *ace_get_stats(struct net_device *dev)
{
struct ace_private *ap = dev->priv;
+ struct ace_mac_stats *mac_stats =
+ (struct ace_mac_stats *)ap->regs->Stats;
+
+ ap->stats.rx_missed_errors = readl(&mac_stats->drop_space);
+ ap->stats.multicast = readl(&mac_stats->kept_mc);
+ ap->stats.collisions = readl(&mac_stats->coll);
return(&ap->stats);
}
-void __init ace_copy(struct ace_regs *regs, void *src, unsigned long dest, int size)
+void __init ace_copy(struct ace_regs *regs, void *src, u32 dest, int size)
{
unsigned long tdest;
u32 *wsrc;
- unsigned long tsize, i;
+ short tsize, i;
if (size <= 0)
return;
- while (size > 0){
+ while (size > 0) {
tsize = min(((~dest & (ACE_WINDOW_SIZE - 1)) + 1),
min(size, ACE_WINDOW_SIZE));
tdest = (unsigned long)&regs->Window +
(dest & (ACE_WINDOW_SIZE - 1));
writel(dest & ~(ACE_WINDOW_SIZE - 1), &regs->WinBase);
+ /*
+ * This requires byte swapping on big endian, however
+ * writel does that for us
+ */
wsrc = src;
- for (i = 0; i < (tsize / 4); i++){
+ for (i = 0; i < (tsize / 4); i++) {
writel(wsrc[i], tdest + i*4);
}
dest += tsize;
@@ -2240,22 +2549,22 @@ void __init ace_copy(struct ace_regs *regs, void *src, unsigned long dest, int s
}
-void __init ace_clear(struct ace_regs *regs, unsigned long dest, int size)
+void __init ace_clear(struct ace_regs *regs, u32 dest, int size)
{
unsigned long tdest;
- unsigned long tsize = 0, i;
+ short tsize = 0, i;
if (size <= 0)
return;
- while (size > 0){
+ while (size > 0) {
tsize = min(((~dest & (ACE_WINDOW_SIZE - 1)) + 1),
min(size, ACE_WINDOW_SIZE));
tdest = (unsigned long)&regs->Window +
(dest & (ACE_WINDOW_SIZE - 1));
writel(dest & ~(ACE_WINDOW_SIZE - 1), &regs->WinBase);
- for (i = 0; i < (tsize / 4); i++){
+ for (i = 0; i < (tsize / 4); i++) {
writel(0, tdest + i*4);
}
@@ -2281,7 +2590,7 @@ int __init ace_load_firmware(struct net_device *dev)
ap = (struct ace_private *)dev->priv;
regs = ap->regs;
- if (!(readl(&regs->CpuCtrl) & CPU_HALTED)){
+ if (!(readl(&regs->CpuCtrl) & CPU_HALTED)) {
printk(KERN_ERR "%s: trying to download firmware while the "
"CPU is running!\n", dev->name);
return -EFAULT;
@@ -2292,14 +2601,14 @@ int __init ace_load_firmware(struct net_device *dev)
* funny things on NICs with only 512KB SRAM
*/
ace_clear(regs, 0x2000, 0x80000-0x2000);
- if (ACE_IS_TIGON_I(ap)){
+ if (ACE_IS_TIGON_I(ap)) {
ace_copy(regs, tigonFwText, tigonFwTextAddr, tigonFwTextLen);
ace_copy(regs, tigonFwData, tigonFwDataAddr, tigonFwDataLen);
ace_copy(regs, tigonFwRodata, tigonFwRodataAddr,
tigonFwRodataLen);
ace_clear(regs, tigonFwBssAddr, tigonFwBssLen);
ace_clear(regs, tigonFwSbssAddr, tigonFwSbssLen);
- }else if (ap->version == 2){
+ }else if (ap->version == 2) {
ace_clear(regs, tigon2FwBssAddr, tigon2FwBssLen);
ace_clear(regs, tigon2FwSbssAddr, tigon2FwSbssLen);
ace_copy(regs, tigon2FwText, tigon2FwTextAddr,tigon2FwTextLen);
@@ -2323,24 +2632,28 @@ int __init ace_load_firmware(struct net_device *dev)
* specs.
*
* Oh yes, this is only the beginning!
+ *
+ * Thanks to Stevarino Webinski for helping tracking down the bugs in the
+ * code i2c readout code by beta testing all my hacks.
*/
static void __init eeprom_start(struct ace_regs *regs)
{
- u32 local = readl(&regs->LocalCtrl);
+ u32 local;
- udelay(1);
+ udelay(ACE_SHORT_DELAY);
+ local = readl(&regs->LocalCtrl);
local |= EEPROM_DATA_OUT | EEPROM_WRITE_ENABLE;
writel(local, &regs->LocalCtrl);
mb();
- udelay(1);
+ udelay(ACE_SHORT_DELAY);
local |= EEPROM_CLK_OUT;
writel(local, &regs->LocalCtrl);
mb();
- udelay(1);
+ udelay(ACE_SHORT_DELAY);
local &= ~EEPROM_DATA_OUT;
writel(local, &regs->LocalCtrl);
mb();
- udelay(1);
+ udelay(ACE_SHORT_DELAY);
local &= ~EEPROM_CLK_OUT;
writel(local, &regs->LocalCtrl);
mb();
@@ -2352,7 +2665,7 @@ static void __init eeprom_prep(struct ace_regs *regs, u8 magic)
short i;
u32 local;
- udelay(2);
+ udelay(ACE_SHORT_DELAY);
local = readl(&regs->LocalCtrl);
local &= ~EEPROM_DATA_OUT;
local |= EEPROM_WRITE_ENABLE;
@@ -2360,7 +2673,7 @@ static void __init eeprom_prep(struct ace_regs *regs, u8 magic)
mb();
for (i = 0; i < 8; i++, magic <<= 1) {
- udelay(2);
+ udelay(ACE_SHORT_DELAY);
if (magic & 0x80)
local |= EEPROM_DATA_OUT;
else
@@ -2368,11 +2681,11 @@ static void __init eeprom_prep(struct ace_regs *regs, u8 magic)
writel(local, &regs->LocalCtrl);
mb();
- udelay(1);
+ udelay(ACE_SHORT_DELAY);
local |= EEPROM_CLK_OUT;
writel(local, &regs->LocalCtrl);
mb();
- udelay(1);
+ udelay(ACE_SHORT_DELAY);
local &= ~(EEPROM_CLK_OUT | EEPROM_DATA_OUT);
writel(local, &regs->LocalCtrl);
mb();
@@ -2389,14 +2702,14 @@ static int __init eeprom_check_ack(struct ace_regs *regs)
local &= ~EEPROM_WRITE_ENABLE;
writel(local, &regs->LocalCtrl);
mb();
- udelay(2);
+ udelay(ACE_LONG_DELAY);
local |= EEPROM_CLK_OUT;
writel(local, &regs->LocalCtrl);
mb();
- udelay(1);
+ udelay(ACE_SHORT_DELAY);
/* sample data in middle of high clk */
state = (readl(&regs->LocalCtrl) & EEPROM_DATA_IN) != 0;
- udelay(1);
+ udelay(ACE_SHORT_DELAY);
mb();
writel(readl(&regs->LocalCtrl) & ~EEPROM_CLK_OUT, &regs->LocalCtrl);
mb();
@@ -2409,23 +2722,24 @@ static void __init eeprom_stop(struct ace_regs *regs)
{
u32 local;
+ udelay(ACE_SHORT_DELAY);
local = readl(&regs->LocalCtrl);
local |= EEPROM_WRITE_ENABLE;
writel(local, &regs->LocalCtrl);
mb();
- udelay(1);
+ udelay(ACE_SHORT_DELAY);
local &= ~EEPROM_DATA_OUT;
writel(local, &regs->LocalCtrl);
mb();
- udelay(1);
+ udelay(ACE_SHORT_DELAY);
local |= EEPROM_CLK_OUT;
writel(local, &regs->LocalCtrl);
mb();
- udelay(1);
+ udelay(ACE_SHORT_DELAY);
local |= EEPROM_DATA_OUT;
writel(local, &regs->LocalCtrl);
mb();
- udelay(2);
+ udelay(ACE_LONG_DELAY);
local &= ~EEPROM_CLK_OUT;
writel(local, &regs->LocalCtrl);
mb();
@@ -2435,73 +2749,115 @@ static void __init eeprom_stop(struct ace_regs *regs)
/*
* Read a whole byte from the EEPROM.
*/
-static u8 __init read_eeprom_byte(struct ace_regs *regs, unsigned long offset)
+static int __init read_eeprom_byte(struct net_device *dev,
+ unsigned long offset)
{
+ struct ace_regs *regs;
+ unsigned long flags;
u32 local;
+ int result = 0;
short i;
- u8 result = 0;
- if (!regs){
- printk(KERN_ERR "No regs!\n");
- return 0;
+ if (!dev) {
+ printk(KERN_ERR "No device!\n");
+ result = -ENODEV;
+ goto eeprom_read_error;
}
+ regs = ((struct ace_private *)dev->priv)->regs;
+
+ /*
+ * Don't take interrupts on this CPU will bit banging
+ * the %#%#@$ I2C device
+ */
+ __save_flags(flags);
+ __cli();
+
eeprom_start(regs);
eeprom_prep(regs, EEPROM_WRITE_SELECT);
- if (eeprom_check_ack(regs)){
- printk("Unable to sync eeprom\n");
- return 0;
+ if (eeprom_check_ack(regs)) {
+ __restore_flags(flags);
+ printk(KERN_ERR "%s: Unable to sync eeprom\n", dev->name);
+ result = -EIO;
+ goto eeprom_read_error;
}
eeprom_prep(regs, (offset >> 8) & 0xff);
- if (eeprom_check_ack(regs))
- return 0;
+ if (eeprom_check_ack(regs)) {
+ __restore_flags(flags);
+ printk(KERN_ERR "%s: Unable to set address byte 0\n",
+ dev->name);
+ result = -EIO;
+ goto eeprom_read_error;
+ }
eeprom_prep(regs, offset & 0xff);
- if (eeprom_check_ack(regs))
- return 0;
+ if (eeprom_check_ack(regs)) {
+ __restore_flags(flags);
+ printk(KERN_ERR "%s: Unable to set address byte 1\n",
+ dev->name);
+ result = -EIO;
+ goto eeprom_read_error;
+ }
eeprom_start(regs);
eeprom_prep(regs, EEPROM_READ_SELECT);
- if (eeprom_check_ack(regs))
- return 0;
+ if (eeprom_check_ack(regs)) {
+ __restore_flags(flags);
+ printk(KERN_ERR "%s: Unable to set READ_SELECT\n",
+ dev->name);
+ result = -EIO;
+ goto eeprom_read_error;
+ }
for (i = 0; i < 8; i++) {
local = readl(&regs->LocalCtrl);
local &= ~EEPROM_WRITE_ENABLE;
writel(local, &regs->LocalCtrl);
- udelay(2);
+ udelay(ACE_LONG_DELAY);
mb();
local |= EEPROM_CLK_OUT;
writel(local, &regs->LocalCtrl);
- udelay(1);
mb();
+ udelay(ACE_SHORT_DELAY);
/* sample data mid high clk */
result = (result << 1) |
((readl(&regs->LocalCtrl) & EEPROM_DATA_IN) != 0);
- udelay(1);
+ udelay(ACE_SHORT_DELAY);
mb();
local = readl(&regs->LocalCtrl);
local &= ~EEPROM_CLK_OUT;
writel(local, &regs->LocalCtrl);
+ udelay(ACE_SHORT_DELAY);
mb();
- if (i == 7){
+ if (i == 7) {
local |= EEPROM_WRITE_ENABLE;
writel(local, &regs->LocalCtrl);
mb();
+ udelay(ACE_SHORT_DELAY);
}
}
local |= EEPROM_DATA_OUT;
writel(local, &regs->LocalCtrl);
- udelay(1);
+ mb();
+ udelay(ACE_SHORT_DELAY);
writel(readl(&regs->LocalCtrl) | EEPROM_CLK_OUT, &regs->LocalCtrl);
- udelay(2);
+ udelay(ACE_LONG_DELAY);
writel(readl(&regs->LocalCtrl) & ~EEPROM_CLK_OUT, &regs->LocalCtrl);
+ mb();
+ udelay(ACE_SHORT_DELAY);
eeprom_stop(regs);
+ __restore_flags(flags);
+ out:
return result;
+
+ eeprom_read_error:
+ printk(KERN_ERR "%s: Unable to read eeprom byte 0x%02lx\n",
+ dev->name, offset);
+ goto out;
}
diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h
index 50f290c89..7719338ab 100644
--- a/drivers/net/acenic.h
+++ b/drivers/net/acenic.h
@@ -18,25 +18,6 @@
* modified to deal properly with readl/writel usage.
*/
-typedef struct {
- u32 addrhi;
- u32 addrlo;
-} aceaddr;
-
-
-static inline void set_aceaddr(aceaddr *aa, dma_addr_t addr)
-{
- unsigned long baddr = (unsigned long) addr;
-#if (BITS_PER_LONG == 64)
- aa->addrlo = cpu_to_le32(baddr & 0xffffffff);
- aa->addrhi = cpu_to_le32(baddr >> 32);
-#else
- /* Don't bother setting zero every time */
- aa->addrlo = cpu_to_le32(baddr);
-#endif
- mb();
-}
-
struct ace_regs {
u32 pad0[16]; /* PCI control registers */
@@ -167,6 +148,13 @@ struct ace_regs {
u32 Window[0x200];
};
+
+typedef struct {
+ u32 addrhi;
+ u32 addrlo;
+} aceaddr;
+
+
#define ACE_WINDOW_SIZE 0x800
#define ACE_JUMBO_MTU 9000
@@ -180,6 +168,7 @@ struct ace_regs {
#define IN_INT 0x01
#define CLR_INT 0x02
+#define HW_RESET 0x08
#define BYTE_SWAP 0x10
#define WORD_SWAP 0x20
#define MASK_INTS 0x40
@@ -202,6 +191,13 @@ struct ace_regs {
/*
+ * udelay() values for when clocking the eeprom
+ */
+#define ACE_SHORT_DELAY 1
+#define ACE_LONG_DELAY 2
+
+
+/*
* Misc Config bits
*/
@@ -239,6 +235,7 @@ struct ace_regs {
#define DMA_WRITE_MAX_1K 0xe0
#define MEM_READ_MULTIPLE 0x00020000
#define PCI_66MHZ 0x00080000
+#define PCI_32BIT 0x00100000
#define DMA_WRITE_ALL_ALIGN 0x00800000
#define READ_CMD_MEM 0x06000000
#define WRITE_CMD_MEM 0x70000000
@@ -248,9 +245,10 @@ struct ace_regs {
* Mode status
*/
-#define ACE_BYTE_SWAP_DATA 0x10
+#define ACE_BYTE_SWAP_BD 0x02
+#define ACE_WORD_SWAP_BD 0x04 /* not actually used */
#define ACE_WARN 0x08
-#define ACE_WORD_SWAP 0x04
+#define ACE_BYTE_SWAP_DMA 0x10
#define ACE_NO_JUMBO_FRAG 0x200
#define ACE_FATAL 0x40000000
@@ -300,20 +298,15 @@ struct ace_regs {
#define EVT_RING_SIZE (EVT_RING_ENTRIES * sizeof(struct event))
struct event {
- union {
- u32 word;
- struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
- u32 idx:12;
- u32 code:12;
- u32 evt:8;
+#ifdef __LITTLE_ENDIAN_BITFIELD
+ u32 idx:12;
+ u32 code:12;
+ u32 evt:8;
#else
- u32 evt:8;
- u32 code:12;
- u32 idx:12;
+ u32 evt:8;
+ u32 code:12;
+ u32 idx:12;
#endif
- } data;
- } u;
u32 pad;
};
@@ -351,7 +344,7 @@ struct event {
#define CMD_RING_ENTRIES 64
struct cmd {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
+#ifdef __LITTLE_ENDIAN_BITFIELD
u32 idx:12;
u32 code:12;
u32 evt:8;
@@ -435,10 +428,17 @@ struct tx_desc{
* This is in PCI shared mem and must be accessed with readl/writel
* real layout is:
*/
+#if __LITTLE_ENDIAN
u16 flags;
u16 size;
u16 vlan;
u16 reserved;
+#else
+ u16 size;
+ u16 flags;
+ u16 reserved;
+ u16 vlan;
+#endif
#endif
u32 vlanres;
};
@@ -459,14 +459,34 @@ struct tx_desc{
struct rx_desc{
aceaddr addr;
+#ifdef __LITTLE_ENDIAN
u16 size;
u16 idx;
+#else
+ u16 idx;
+ u16 size;
+#endif
+#ifdef __LITTLE_ENDIAN
u16 flags;
u16 type;
+#else
+ u16 type;
+ u16 flags;
+#endif
+#ifdef __LITTLE_ENDIAN
u16 tcp_udp_csum;
u16 ip_csum;
+#else
+ u16 ip_csum;
+ u16 tcp_udp_csum;
+#endif
+#ifdef __LITTLE_ENDIAN
u16 vlan;
u16 err_flags;
+#else
+ u16 err_flags;
+ u16 vlan;
+#endif
u32 reserved;
u32 opague;
};
@@ -477,8 +497,13 @@ struct rx_desc{
*/
struct ring_ctrl {
aceaddr rngptr;
+#ifdef __LITTLE_ENDIAN
u16 flags;
u16 max_len;
+#else
+ u16 max_len;
+ u16 flags;
+#endif
u32 pad;
};
@@ -535,16 +560,17 @@ struct ace_info {
};
-/*
- * struct ace_skb holding the rings of skb's. This is an awful lot of
- * pointers, but I don't see any other smart mode to do this in an
- * efficient manner ;-(
- */
struct ring_info {
struct sk_buff *skb;
dma_addr_t mapping;
};
+
+/*
+ * struct ace_skb holding the rings of skb's. This is an awful lot of
+ * pointers, but I don't see any other smart mode to do this in an
+ * efficient manner ;-(
+ */
struct ace_skb
{
struct ring_info tx_skbuff[TX_RING_ENTRIES];
@@ -575,9 +601,10 @@ struct ace_private
* The send ring is located in the shared memory window
*/
struct ace_info *info;
- dma_addr_t info_dma;
struct tx_desc *tx_ring;
- u32 tx_prd, tx_full, tx_ret_csm;
+ dma_addr_t info_dma;
+ u32 tx_prd;
+ volatile u32 tx_full, tx_ret_csm;
struct timer_list timer;
unsigned long std_refill_busy
@@ -590,9 +617,8 @@ struct ace_private
u32 cur_rx;
struct tq_struct immediate;
int bh_pending, jumbo;
-
- /* These elements are allocated using consistent PCI
- * dma memory.
+ /*
+ * These elements are allocated using consistent PCI dma memory.
*/
struct rx_desc *rx_std_ring;
struct rx_desc *rx_jumbo_ring;
@@ -611,10 +637,64 @@ struct ace_private
struct net_device *next;
u16 pci_command;
u8 pci_latency;
- char name[24];
+ char name[48];
+#ifdef INDEX_DEBUG
+ spinlock_t debug_lock
+ __attribute__ ((aligned (L1_CACHE_BYTES)));;
+ u32 last_tx, last_std_rx, last_mini_rx;
+#endif
struct net_device_stats stats;
};
+
+static inline void set_aceaddr(aceaddr *aa, dma_addr_t addr)
+{
+ unsigned long baddr = (unsigned long) addr;
+#if (BITS_PER_LONG == 64)
+ aa->addrlo = baddr & 0xffffffff;
+ aa->addrhi = baddr >> 32;
+#else
+ /* Don't bother setting zero every time */
+ aa->addrlo = baddr;
+#endif
+ mb();
+}
+
+
+#if 0
+static inline void *get_aceaddr(aceaddr *aa)
+{
+ unsigned long addr;
+ mb();
+#if (BITS_PER_LONG == 64)
+ addr = (u64)aa->addrhi << 32 | aa->addrlo;
+#else
+ addr = aa->addrlo;
+#endif
+ return (void *)addr;
+}
+#endif
+
+
+static inline void ace_set_txprd(struct ace_regs *regs,
+ struct ace_private *ap, u32 value)
+{
+#ifdef INDEX_DEBUG
+ unsigned long flags;
+ spin_lock_irqsave(&ap->debug_lock, flags);
+ writel(value, &regs->TxPrd);
+ if (value == ap->last_tx)
+ printk(KERN_ERR "AceNIC RACE ALERT! writing identical value "
+ "to tx producer (%i)\n", value);
+ ap->last_tx = value;
+ spin_unlock_irqrestore(&ap->debug_lock, flags);
+#else
+ writel(value, &regs->TxPrd);
+#endif
+ wmb();
+}
+
+
/*
* Prototypes
*/
@@ -622,7 +702,6 @@ static int ace_init(struct net_device *dev, int board_idx);
static void ace_load_std_rx_ring(struct ace_private *ap, int nr_bufs);
static void ace_load_mini_rx_ring(struct ace_private *ap, int nr_bufs);
static void ace_load_jumbo_rx_ring(struct ace_private *ap, int nr_bufs);
-static int ace_flush_jumbo_rx_ring(struct net_device *dev);
static void ace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int ace_load_firmware(struct net_device *dev);
static int ace_open(struct net_device *dev);
@@ -638,7 +717,9 @@ extern int ace_recycle(struct sk_buff *skb);
#endif
static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
static int ace_set_mac_addr(struct net_device *dev, void *p);
+static int ace_allocate_descriptors(struct net_device *dev);
+static void ace_free_descriptors(struct net_device *dev);
static struct net_device_stats *ace_get_stats(struct net_device *dev);
-static u8 read_eeprom_byte(struct ace_regs *regs, unsigned long offset);
+static int read_eeprom_byte(struct net_device *dev, unsigned long offset);
#endif /* _ACENIC_H_ */
diff --git a/drivers/net/acenic_firmware.h b/drivers/net/acenic_firmware.h
index d28e266a0..729eac664 100644
--- a/drivers/net/acenic_firmware.h
+++ b/drivers/net/acenic_firmware.h
@@ -4,38 +4,37 @@
* the compiler complaining about undefined symbols.
*/
#define tigonFwReleaseMajor 0xc
-#define tigonFwReleaseMinor 0x3
-#define tigonFwReleaseFix 0xd
+#define tigonFwReleaseMinor 0x4
+#define tigonFwReleaseFix 0x5
#define tigonFwStartAddr 0x00004000
#define tigonFwTextAddr 0x00004000
-#define tigonFwTextLen 0x10920
-#define tigonFwRodataAddr 0x00014920
-#define tigonFwRodataLen 0xaa0
-#define tigonFwDataAddr 0x000153e0
-#define tigonFwDataLen 0x150
-#define tigonFwSbssAddr 0x00015530
-#define tigonFwSbssLen 0x2c
-#define tigonFwBssAddr 0x00015560
+#define tigonFwTextLen 0x11190
+#define tigonFwRodataAddr 0x00015190
+#define tigonFwRodataLen 0xac0
+#define tigonFwDataAddr 0x00015c80
+#define tigonFwDataLen 0x170
+#define tigonFwSbssAddr 0x00015df0
+#define tigonFwSbssLen 0x34
+#define tigonFwBssAddr 0x00015e30
#define tigonFwBssLen 0x2080
u32 tigonFwText[];
u32 tigonFwData[];
u32 tigonFwRodata[];
-
#ifndef CONFIG_ACENIC_OMIT_TIGON_I
/* Generated by genfw.c */
u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x10000003,
0x0, 0xd, 0xd, 0x3c1d0001,
-0x8fbd5414, 0x3a0f021, 0x3c100000, 0x26104000,
+0x8fbd5cb4, 0x3a0f021, 0x3c100000, 0x26104000,
0xc00100c, 0x0, 0xd, 0x27bdffd8,
0x3c1cc000, 0x3c1b0013, 0x377bd800, 0xd021,
0x3c170013, 0x36f75418, 0x2e02021, 0x340583e8,
0xafbf0024, 0xc002488, 0xafb00020, 0xc0023e8,
-0x0, 0x3c040001, 0x24844984, 0x24050001,
-0x2e03021, 0x3821, 0x3c100001, 0x261075e0,
+0x0, 0x3c040001, 0x248451f4, 0x24050001,
+0x2e03021, 0x3821, 0x3c100001, 0x26107eb0,
0xafb00010, 0xc002403, 0xafbb0014, 0x3c02000f,
0x3442ffff, 0x2021024, 0x362102b, 0x10400009,
-0x24050003, 0x3c040001, 0x24844990, 0x2003021,
+0x24050003, 0x3c040001, 0x24845200, 0x2003021,
0x3603821, 0x3c020010, 0xafa20010, 0xc002403,
0xafa00014, 0x2021, 0x3405c000, 0x3c010001,
0x370821, 0xa02083b0, 0x3c010001, 0x370821,
@@ -73,7 +72,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x0, 0x8ee20450, 0x8ee30454, 0xaee304fc,
0x8ee204fc, 0x2442e000, 0x2c422001, 0x1440000d,
0x26e40030, 0x8ee20450, 0x8ee30454, 0x3c040001,
-0x2484499c, 0x3c050001, 0xafa00010, 0xafa00014,
+0x2484520c, 0x3c050001, 0xafa00010, 0xafa00014,
0x8ee704fc, 0x34a5f000, 0xc002403, 0x603021,
0x26e40030, 0xc002488, 0x24050400, 0x27440080,
0xc002488, 0x24050080, 0x26e4777c, 0xc002488,
@@ -83,7 +82,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x3442ca00, 0x2021, 0x24030002, 0xaee30074,
0xaee30070, 0xaee2006c, 0x240203e8, 0xaee20104,
0x24020001, 0xaee30100, 0xaee2010c, 0x3c030001,
-0x641821, 0x906353e0, 0x2e41021, 0x24840001,
+0x641821, 0x90635c80, 0x2e41021, 0x24840001,
0xa043009c, 0x2c82000f, 0x1440fff8, 0x0,
0x8f820040, 0x2e41821, 0x24840001, 0x21702,
0x24420030, 0xa062009c, 0x2e41021, 0xa040009c,
@@ -129,7 +128,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30,
0x210c0, 0x24425038, 0x2e22021, 0x24020007,
0xac820000, 0x24020001, 0xac820004, 0x54c0000c,
-0xaee90608, 0x3c040001, 0x248449a8, 0xafa00010,
+0xaee90608, 0x3c040001, 0x24845218, 0xafa00010,
0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009,
0xc002403, 0x34a5f000, 0x8001223, 0x0,
0x8f830120, 0x27623800, 0x24660020, 0xc2102b,
@@ -155,21 +154,21 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
0x24425038, 0x2e22021, 0x24020012, 0xac820000,
0x24020001, 0xac820004, 0x14c0001b, 0x0,
-0x3c040001, 0x248449b0, 0xafa00010, 0xafa00014,
+0x3c040001, 0x24845220, 0xafa00010, 0xafa00014,
0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403,
0x34a5f001, 0x8ee201b0, 0x24420001, 0xaee201b0,
-0x8001223, 0x8ee201b0, 0x3c040001, 0x248449bc,
+0x8001223, 0x8ee201b0, 0x3c040001, 0x2484522c,
0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009,
0xc002403, 0x34a5f005, 0x8ee201ac, 0x24420001,
0xaee201ac, 0x8ee201ac, 0x8ee20160, 0x3c040001,
-0x248449c8, 0x3405f001, 0x24420001, 0xaee20160,
+0x24845238, 0x3405f001, 0x24420001, 0xaee20160,
0x8ee20160, 0x3021, 0x3821, 0xafa00010,
0xc002403, 0xafa00014, 0x8001238, 0x0,
0x3c020001, 0x2442f5a8, 0x21100, 0x21182,
0x431025, 0x3c010001, 0xac221278, 0x96e2045a,
0x30420003, 0x10400025, 0x3c050fff, 0x8ee204c8,
0x34a5ffff, 0x34420a00, 0xaee204c8, 0x8ee304c8,
-0x3c040001, 0x248449d4, 0x24020001, 0xa2e204ec,
+0x3c040001, 0x24845244, 0x24020001, 0xa2e204ec,
0xa2e204ed, 0x3c020002, 0x621825, 0x3c020001,
0x2442a390, 0x451024, 0x21082, 0xaee304c8,
0x3c030800, 0x431025, 0x3c010001, 0xac221220,
@@ -212,7 +211,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038,
0x2e22021, 0x24020007, 0xac820000, 0x24020001,
0xac820004, 0x54c0000c, 0xaee90608, 0x3c040001,
-0x248449a8, 0xafa00010, 0xafa00014, 0x8ee60608,
+0x24845218, 0xafa00010, 0xafa00014, 0x8ee60608,
0x8f470228, 0x3c050009, 0xc002403, 0x34a5f000,
0x800136d, 0x0, 0x8f830120, 0x27623800,
0x24660020, 0xc2102b, 0x50400001, 0x27663000,
@@ -237,17 +236,17 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
0x24020012, 0xac820000, 0x24020001, 0xac820004,
-0x14c0001b, 0x0, 0x3c040001, 0x248449b0,
+0x14c0001b, 0x0, 0x3c040001, 0x24845220,
0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228,
0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201b0,
0x24420001, 0xaee201b0, 0x800136d, 0x8ee201b0,
-0x3c040001, 0x248449bc, 0xafa00014, 0x8ee60608,
+0x3c040001, 0x2484522c, 0xafa00014, 0x8ee60608,
0x8f470228, 0x3c050009, 0xc002403, 0x34a5f005,
0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac,
-0x8ee20160, 0x3c040001, 0x248449c8, 0x3405f002,
+0x8ee20160, 0x3c040001, 0x24845238, 0x3405f002,
0x24420001, 0xaee20160, 0x8ee20160, 0x3021,
0x3821, 0xafa00010, 0xc002403, 0xafa00014,
-0x96e6047a, 0x96e7046a, 0x3c040001, 0x248449e0,
+0x96e6047a, 0x96e7046a, 0x3c040001, 0x24845250,
0x24050012, 0xafa00010, 0xc002403, 0xafa00014,
0xc004500, 0x0, 0xc002318, 0x0,
0x3c060001, 0x34c63800, 0xaee00608, 0xaf400228,
@@ -290,7 +289,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038,
0x2e22021, 0x24020007, 0xac820000, 0x24020001,
0xac820004, 0x54c0000c, 0xaee90608, 0x3c040001,
-0x248449a8, 0xafa00010, 0xafa00014, 0x8ee60608,
+0x24845218, 0xafa00010, 0xafa00014, 0x8ee60608,
0x8f470228, 0x3c050009, 0xc002403, 0x34a5f000,
0x80014a5, 0x0, 0x8f830120, 0x27623800,
0x24660020, 0xc2102b, 0x50400001, 0x27663000,
@@ -315,11 +314,11 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
0x24020012, 0xac820000, 0x24020001, 0xac820004,
-0x14c0001b, 0x0, 0x3c040001, 0x248449b0,
+0x14c0001b, 0x0, 0x3c040001, 0x24845220,
0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228,
0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201b0,
0x24420001, 0xaee201b0, 0x80014a5, 0x8ee201b0,
-0x3c040001, 0x248449bc, 0xafa00014, 0x8ee60608,
+0x3c040001, 0x2484522c, 0xafa00014, 0x8ee60608,
0x8f470228, 0x3c050009, 0xc002403, 0x34a5f005,
0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac,
0x8ee20154, 0x24420001, 0xaee20154, 0xc0014dc,
@@ -341,7 +340,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xaee07b8c, 0xaee07b84, 0x3c010001, 0x370821,
0xac2083bc, 0x3c010001, 0x370821, 0x3e00008,
0xa02083b9, 0x27bdffd8, 0xafbf0024, 0xafb00020,
-0x8f820054, 0x3c030001, 0x8c635498, 0x24420067,
+0x8f820054, 0x3c030001, 0x8c635d38, 0x24420067,
0x1060000d, 0xaf820058, 0x3c020001, 0x571021,
0x904283b8, 0x10400005, 0x3c030200, 0x3c010001,
0x370821, 0x8001503, 0xa02083b8, 0x8ee20000,
@@ -359,7 +358,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x0, 0x3c030001, 0x771821, 0x8c6383d4,
0x8f8200b4, 0x1462007c, 0x0, 0x3c070001,
0xf73821, 0x8ce783d0, 0x8f8200b0, 0x3c040001,
-0x24844a50, 0xafa00014, 0xafa20010, 0x8f8600b0,
+0x248452c0, 0xafa00014, 0xafa20010, 0x8f8600b0,
0x3c050005, 0xc002403, 0x34a50900, 0x8f82011c,
0x34420002, 0xaf82011c, 0x8f830104, 0x8f8200b0,
0x34420001, 0xaf8200b0, 0xaf830104, 0x8f830120,
@@ -387,10 +386,10 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xac820000, 0x24020001, 0xac820004, 0x8f82011c,
0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201e4,
0x3c070001, 0xf73821, 0x8ce783d0, 0x24420001,
-0xaee201e4, 0x8ee201e4, 0x3c040001, 0x24844a5c,
+0xaee201e4, 0x8ee201e4, 0x3c040001, 0x248452cc,
0x80015bd, 0xafa00010, 0x8f820104, 0x3c010001,
0x370821, 0xac2283d0, 0x8f8200b4, 0x3c070001,
-0xf73821, 0x8ce783d0, 0x3c040001, 0x24844a64,
+0xf73821, 0x8ce783d0, 0x3c040001, 0x248452d4,
0x3c010001, 0x370821, 0xac2283d4, 0xafa00010,
0xafa00014, 0x8f8600b0, 0x3c050005, 0xc002403,
0x34a50900, 0x80015cc, 0x0, 0x8f820104,
@@ -423,7 +422,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
0x24425038, 0x2e22021, 0x24020012, 0xac820000,
0x24020001, 0xac820004, 0x5600000b, 0x24100001,
-0x8ee204e4, 0x3c040001, 0x24844a6c, 0xafa00014,
+0x8ee204e4, 0x3c040001, 0x248452dc, 0xafa00014,
0xafa20010, 0x8ee60608, 0x8f470228, 0x3c050009,
0xc002403, 0x34a5f006, 0x16000003, 0x24020001,
0x8001650, 0xa2e204f4, 0x8ee20170, 0x24420001,
@@ -453,7 +452,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
0x24020012, 0xac820000, 0x24020001, 0xac820004,
0x5600000b, 0x24100001, 0x8ee2724c, 0x3c040001,
-0x24844a78, 0xafa00014, 0xafa20010, 0x8ee6724c,
+0x248452e8, 0xafa00014, 0xafa20010, 0x8ee6724c,
0x8f470280, 0x3c050009, 0xc002403, 0x34a5f008,
0x56000001, 0xaee00e1c, 0x8ee20174, 0x24420001,
0xaee20174, 0x8ee20174, 0x8ee24e24, 0x10400019,
@@ -564,11 +563,11 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6,
0x0, 0x316300ff, 0x24020001, 0x14620003,
0x3c050009, 0x800197c, 0x24100001, 0x3c040001,
-0x24844a84, 0xafa00010, 0xafa00014, 0x8f860120,
+0x248452f4, 0xafa00010, 0xafa00014, 0x8f860120,
0x8f870124, 0x800187b, 0x34a5f011, 0x3c040001,
-0x24844a90, 0xafa00010, 0xafa00014, 0x8f860120,
+0x24845300, 0xafa00010, 0xafa00014, 0x8f860120,
0x8f870124, 0x34a5f010, 0xc002403, 0x8021,
-0x800197c, 0x0, 0x3c040001, 0x24844a9c,
+0x800197c, 0x0, 0x3c040001, 0x2484530c,
0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009,
0x8001975, 0x34a5f00f, 0x8ee20608, 0x8f430228,
0x24420001, 0x304900ff, 0x512300e2, 0xafa00010,
@@ -599,7 +598,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
0x24425038, 0x2e22021, 0x24020007, 0xac820000,
0x24020001, 0xac820004, 0x5600000c, 0xaee90608,
-0x3c040001, 0x24844aa8, 0xafa00010, 0xafa00014,
+0x3c040001, 0x24845318, 0xafa00010, 0xafa00014,
0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403,
0x34a5f000, 0x800197c, 0x0, 0x8f830120,
0x27623800, 0x24660020, 0xc2102b, 0x50400001,
@@ -625,10 +624,10 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038,
0x2e22021, 0x24020012, 0xac820000, 0x24020001,
0xac820004, 0x5600001d, 0x24100001, 0x3c040001,
-0x24844ab0, 0xafa00010, 0xafa00014, 0x8ee60608,
+0x24845320, 0xafa00010, 0xafa00014, 0x8ee60608,
0x8f470228, 0x3c050009, 0xc002403, 0x34a5f001,
0x8ee201b0, 0x24420001, 0xaee201b0, 0x800197c,
-0x8ee201b0, 0x3c040001, 0x24844abc, 0xafa00014,
+0x8ee201b0, 0x3c040001, 0x2484532c, 0xafa00014,
0x8ee60608, 0x8f470228, 0x3c050009, 0x34a5f005,
0xc002403, 0x0, 0x8ee201ac, 0x8021,
0x24420001, 0xaee201ac, 0x8ee201ac, 0x1200000c,
@@ -636,7 +635,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8f420238, 0x8ee30158, 0x24630001, 0xaee30158,
0x8ee30158, 0x800198c, 0xaee27278, 0x24020001,
0x3c010001, 0x370821, 0xa02283b0, 0x3c020001,
-0x8c425498, 0x10400187, 0x0, 0x8ee27b84,
+0x8c425d38, 0x10400187, 0x0, 0x8ee27b84,
0x24430001, 0x284200c9, 0x144001a4, 0xaee37b84,
0x8ee204d4, 0x30420002, 0x14400119, 0xaee07b84,
0x8ee204d4, 0x3c030600, 0x34631000, 0x34420002,
@@ -700,12 +699,12 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x56000006, 0x240b0001, 0x8f820054, 0x1221023,
0x2c420033, 0x1440ffa6, 0x0, 0x316300ff,
0x24020001, 0x10620022, 0x0, 0x3c040001,
-0x24844a84, 0xafa00010, 0xafa00014, 0x8f860120,
+0x248452f4, 0xafa00010, 0xafa00014, 0x8f860120,
0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011,
-0x8001aad, 0x0, 0x3c040001, 0x24844a90,
+0x8001aad, 0x0, 0x3c040001, 0x24845300,
0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009,
0xc002403, 0x34a5f010, 0x8001aad, 0x0,
-0x3c040001, 0x24844a9c, 0xafa00014, 0x8ee60608,
+0x3c040001, 0x2484530c, 0xafa00014, 0x8ee60608,
0x8f470228, 0x3c050009, 0xc002403, 0x34a5f00f,
0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac,
0x8ee2015c, 0x24420001, 0xaee2015c, 0x8ee2015c,
@@ -742,7 +741,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xaf820044, 0x8f820044, 0x34420040, 0xaf820044,
0x8ee27b88, 0x24430001, 0x28421389, 0x14400005,
0xaee37b88, 0x8f820044, 0x38420020, 0xaf820044,
-0xaee07b88, 0xc0045c2, 0x0, 0x8fbf0024,
+0xaee07b88, 0xc0045f4, 0x0, 0x8fbf0024,
0x8fb00020, 0x3e00008, 0x27bd0028, 0x27bdffb8,
0xafbf0044, 0xafb60040, 0xafb5003c, 0xafb40038,
0xafb30034, 0xafb20030, 0xafb1002c, 0xafb00028,
@@ -752,18 +751,18 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xaee2016c, 0x80022f4, 0x8ee2016c, 0x32c20001,
0x10400004, 0x24020001, 0xaf820064, 0x80022f4,
0x0, 0x32c20002, 0x1440000c, 0x3c050003,
-0x3c040001, 0x24844b34, 0x34a50001, 0x2c03021,
+0x3c040001, 0x248453a4, 0x34a50001, 0x2c03021,
0x3821, 0xafa00010, 0xc002403, 0xafa00014,
0x2402fff8, 0x80022f4, 0xaf820064, 0x8f43022c,
0x8f42010c, 0x5062000c, 0xafa00010, 0x8f42022c,
0x21080, 0x5a1021, 0x8c420300, 0xafa20020,
0x8f42022c, 0x24070001, 0x24420001, 0x3042003f,
-0x8001b80, 0xaf42022c, 0x3c040001, 0x24844b40,
+0x8001b80, 0xaf42022c, 0x3c040001, 0x248453b0,
0xafa00014, 0x8f46022c, 0x8f47010c, 0x3c050003,
0xc002403, 0x34a5f01f, 0x3821, 0x14e00003,
0x0, 0x80022ed, 0xaf960064, 0x93a20020,
0x2443ffff, 0x2c620011, 0x10400658, 0x31080,
-0x3c010001, 0x220821, 0x8c224bf8, 0x400008,
+0x3c010001, 0x220821, 0x8c225468, 0x400008,
0x0, 0x8fa20020, 0x30420fff, 0xaee20e0c,
0x8f820060, 0x34420200, 0xaf820060, 0x8ee20118,
0x24420001, 0xaee20118, 0x80022e8, 0x8ee20118,
@@ -779,7 +778,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8f840054, 0x41442, 0x41c82, 0x431021,
0x41cc2, 0x431023, 0x41d02, 0x431021,
0x41d42, 0x431023, 0x8001bd0, 0xaee20078,
-0x3c040001, 0x24844b4c, 0xafa00014, 0x8fa60020,
+0x3c040001, 0x248453bc, 0xafa00014, 0x8fa60020,
0x3c050003, 0xc002403, 0x34a50004, 0x8ee20110,
0x24420001, 0xaee20110, 0x80022e8, 0x8ee20110,
0x27440212, 0xc0022fe, 0x24050006, 0x3049001f,
@@ -795,7 +794,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x2c820080, 0x1440fff8, 0x410c0, 0x4c10010,
0x618c0, 0x610c0, 0x571821, 0x8c63737c,
0x571021, 0xafa30010, 0x8c427380, 0x3c040001,
-0x24844b58, 0xafa20014, 0x8f470214, 0x3c050003,
+0x248453c8, 0xafa20014, 0x8f470214, 0x3c050003,
0xc002403, 0x34a50013, 0x8001c90, 0x3c020800,
0x97440212, 0x771021, 0xa444737e, 0x8f440214,
0x771021, 0x2e31821, 0xac447380, 0x34028000,
@@ -813,7 +812,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x24840001, 0x2c820080, 0x1440fff8, 0x410c0,
0x4c10023, 0x618c0, 0x910c0, 0x571821,
0x8c63727c, 0x571021, 0xafa30010, 0x8c427280,
-0x3c040001, 0x24844b64, 0xafa20014, 0x8f470214,
+0x3c040001, 0x248453d4, 0xafa20014, 0x8f470214,
0x3c050003, 0xc002403, 0x34a5f017, 0x8001c90,
0x3c020800, 0x8f430210, 0xb71021, 0xac43777c,
0x8f430214, 0xb71021, 0xac437780, 0x3c020001,
@@ -888,13 +887,13 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x2e22021, 0xac8a0000, 0xac8c0004, 0x54e00006,
0x240b0001, 0x8f820054, 0x1221023, 0x2c420033,
0x1440ffa6, 0x0, 0x316300ff, 0x24020001,
-0x10620022, 0x0, 0x3c040001, 0x24844b70,
+0x10620022, 0x0, 0x3c040001, 0x248453e0,
0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124,
0x3c050009, 0xc002403, 0x34a5f011, 0x8001da0,
-0x0, 0x3c040001, 0x24844b7c, 0xafa00014,
+0x0, 0x3c040001, 0x248453ec, 0xafa00014,
0x8f860120, 0x8f870124, 0x3c050009, 0xc002403,
0x34a5f010, 0x8001da0, 0x0, 0x3c040001,
-0x24844b88, 0xafa00014, 0x8ee60608, 0x8f470228,
+0x248453f8, 0xafa00014, 0x8ee60608, 0x8f470228,
0x3c050009, 0xc002403, 0x34a5f00f, 0x8ee201ac,
0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee20124,
0x24420001, 0xaee20124, 0x8001f97, 0x8ee20124,
@@ -909,7 +908,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x1221004, 0x21027, 0x621824, 0xaf830228,
0x910c0, 0x2e21821, 0x3402c000, 0x8001e4e,
0xa462727c, 0x8f420214, 0xafa20010, 0x910c0,
-0x571021, 0x8c42727c, 0x3c040001, 0x24844b94,
+0x571021, 0x8c42727c, 0x3c040001, 0x24845404,
0x3c050003, 0xafa20014, 0x8f470210, 0x34a5f01c,
0xc002403, 0x1203021, 0x8001e83, 0x3c020800,
0xb71021, 0x9443727e, 0x97420212, 0x14620019,
@@ -937,7 +936,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x910c0, 0x2e41821, 0x3402c000, 0x15000015,
0xa462737c, 0x910c0, 0x2e21821, 0x34028000,
0x8001e4e, 0xa462727c, 0x571021, 0x8c42727c,
-0x3c040001, 0x24844ba0, 0x3c050003, 0xafa20010,
+0x3c040001, 0x24845410, 0x3c050003, 0xafa20010,
0x710c0, 0x571021, 0x8c42737c, 0x34a5001e,
0x1203021, 0xc002403, 0xafa20014, 0x8001e83,
0x3c020800, 0x2021, 0x428c0, 0xb71021,
@@ -1013,12 +1012,12 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xac8a0000, 0xac8c0004, 0x54e00006, 0x240b0001,
0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6,
0x0, 0x316300ff, 0x24020001, 0x10620022,
-0x0, 0x3c040001, 0x24844b70, 0xafa00010,
+0x0, 0x3c040001, 0x248453e0, 0xafa00010,
0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009,
0xc002403, 0x34a5f011, 0x8001f93, 0x0,
-0x3c040001, 0x24844b7c, 0xafa00014, 0x8f860120,
+0x3c040001, 0x248453ec, 0xafa00014, 0x8f860120,
0x8f870124, 0x3c050009, 0xc002403, 0x34a5f010,
-0x8001f93, 0x0, 0x3c040001, 0x24844b88,
+0x8001f93, 0x0, 0x3c040001, 0x248453f8,
0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009,
0xc002403, 0x34a5f00f, 0x8ee201ac, 0x24420001,
0xaee201ac, 0x8ee201ac, 0x8ee20128, 0x24420001,
@@ -1030,7 +1029,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8f820228, 0xaee204dc, 0x2402ffff, 0xaf820228,
0x24020001, 0x8001fbe, 0xa2e204d8, 0x92e204d8,
0x5040000c, 0xa2e004d8, 0x8ee204dc, 0xaf820228,
-0x8001fbe, 0xa2e004d8, 0x3c040001, 0x24844ba8,
+0x8001fbe, 0xa2e004d8, 0x3c040001, 0x24845418,
0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403,
0x34a5f009, 0x8ee2013c, 0x24420001, 0xaee2013c,
0x80022e8, 0x8ee2013c, 0x8fa20020, 0x21200,
@@ -1041,7 +1040,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x370821, 0xa02283b2, 0x8001fea, 0xaee40108,
0x8f820220, 0x3c0308ff, 0x3463fff7, 0x431024,
0xaf820220, 0x3c010001, 0x370821, 0xa02083b2,
-0x8001fea, 0xaee40108, 0x3c040001, 0x24844bb4,
+0x8001fea, 0xaee40108, 0x3c040001, 0x24845424,
0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403,
0x34a5f00a, 0x8ee2012c, 0x24420001, 0xaee2012c,
0x80022e8, 0x8ee2012c, 0x8fa20020, 0x21200,
@@ -1053,13 +1052,13 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x571021, 0x904283b2, 0x3c010001, 0x370821,
0x1440000e, 0xa02083b3, 0x8f820220, 0x3c0308ff,
0x3463fff7, 0x431024, 0x8002018, 0xaf820220,
-0x3c040001, 0x24844bc0, 0xafa00014, 0x8fa60020,
+0x3c040001, 0x24845430, 0xafa00014, 0x8fa60020,
0x3c050003, 0xc002403, 0x34a5f00b, 0x8ee20114,
0x24420001, 0xaee20114, 0x80022e8, 0x8ee20114,
0x27840208, 0x27450200, 0xc00249a, 0x24060008,
0x26e40094, 0x27450200, 0xc00249a, 0x24060008,
0x8ee20134, 0x24420001, 0xaee20134, 0x80022e8,
-0x8ee20134, 0x8f460248, 0x2021, 0xc004fa8,
+0x8ee20134, 0x8f460248, 0x2021, 0xc0050e0,
0x24050004, 0x8ee20130, 0x24420001, 0xaee20130,
0x80022e8, 0x8ee20130, 0x8ef301cc, 0x8ef401d0,
0x8ef501d8, 0x8ee20140, 0x26e40030, 0x24420001,
@@ -1073,7 +1072,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xaee20104, 0xaee40100, 0xaee3010c, 0x8f820220,
0x30420008, 0x10400004, 0x0, 0xaee30108,
0x8002061, 0x2021, 0xaee40108, 0x2021,
-0x3c030001, 0x641821, 0x906353f0, 0x2e41021,
+0x3c030001, 0x641821, 0x90635c90, 0x2e41021,
0x24840001, 0xa043009c, 0x2c82000f, 0x1440fff8,
0x0, 0x8f820040, 0x2e41821, 0x24840001,
0x21702, 0x24420030, 0xa062009c, 0x2e41021,
@@ -1153,13 +1152,13 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x2e22021, 0xac8a0000, 0xac8c0004, 0x54e00006,
0x240b0001, 0x8f820054, 0x1221023, 0x2c420033,
0x1440ffa6, 0x0, 0x316300ff, 0x24020001,
-0x10620022, 0x0, 0x3c040001, 0x24844b70,
+0x10620022, 0x0, 0x3c040001, 0x248453e0,
0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124,
0x3c050009, 0xc002403, 0x34a5f011, 0x80021c4,
-0x0, 0x3c040001, 0x24844b7c, 0xafa00014,
+0x0, 0x3c040001, 0x248453ec, 0xafa00014,
0x8f860120, 0x8f870124, 0x3c050009, 0xc002403,
0x34a5f010, 0x80021c4, 0x0, 0x3c040001,
-0x24844b88, 0xafa00014, 0x8ee60608, 0x8f470228,
+0x248453f8, 0xafa00014, 0x8ee60608, 0x8f470228,
0x3c050009, 0xc002403, 0x34a5f00f, 0x8ee201ac,
0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee20120,
0x24420001, 0xaee20120, 0x8ee20120, 0x8ee20168,
@@ -1169,7 +1168,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8f820220, 0x30420008, 0x14400002, 0x24020001,
0x24020002, 0xaee20108, 0x8ee2011c, 0x24420001,
0xaee2011c, 0x80022e8, 0x8ee2011c, 0x3c040001,
-0x24844bcc, 0xafa00010, 0xafa00014, 0x8fa60020,
+0x2484543c, 0xafa00010, 0xafa00014, 0x8fa60020,
0x3c050003, 0xc002403, 0x34a5f00f, 0x93a20020,
0x3c030700, 0x34631000, 0x431025, 0xafa20018,
0x8ee20608, 0x8f430228, 0x24420001, 0x304900ff,
@@ -1200,7 +1199,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
0x24020007, 0xac820000, 0x24020001, 0xac820004,
-0x54e0000c, 0xaee90608, 0x3c040001, 0x24844bd4,
+0x54e0000c, 0xaee90608, 0x3c040001, 0x24845444,
0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228,
0x3c050009, 0xc002403, 0x34a5f000, 0x80022e0,
0x0, 0x8f830120, 0x27623800, 0x24660020,
@@ -1226,11 +1225,11 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30,
0x210c0, 0x24425038, 0x2e22021, 0x24020012,
0xac820000, 0x24020001, 0xac820004, 0x14e0001b,
-0x0, 0x3c040001, 0x24844bdc, 0xafa00010,
+0x0, 0x3c040001, 0x2484544c, 0xafa00010,
0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009,
0xc002403, 0x34a5f001, 0x8ee201b0, 0x24420001,
0xaee201b0, 0x80022e0, 0x8ee201b0, 0x3c040001,
-0x24844be8, 0xafa00014, 0x8ee60608, 0x8f470228,
+0x24845458, 0xafa00014, 0x8ee60608, 0x8f470228,
0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201ac,
0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee20150,
0x24420001, 0xaee20150, 0x8ee20150, 0x8ee20160,
@@ -1257,7 +1256,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xaf82011c, 0x8fbf0010, 0x3e00008, 0x27bd0018,
0x27bdffe0, 0xafbf0018, 0x8f820104, 0xafa20010,
0x8f820100, 0x3c050002, 0xafa20014, 0x8f8600b0,
-0x8f87011c, 0x3c040001, 0x24844ca0, 0xc002403,
+0x8f87011c, 0x3c040001, 0x24845510, 0xc002403,
0x34a5f000, 0x8f8300b0, 0x3c027f00, 0x621824,
0x3c020400, 0x10620029, 0x43102b, 0x14400008,
0x3c022000, 0x3c020100, 0x10620024, 0x3c020200,
@@ -1274,7 +1273,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x27bd0020, 0x27bdffe0, 0xafbf001c, 0xafb00018,
0x8f820120, 0xafa20010, 0x8f820124, 0x3c050001,
0xafa20014, 0x8f8600a0, 0x8f87011c, 0x3c040001,
-0x24844cac, 0xc002403, 0x34a5f000, 0x8f8300a0,
+0x2484551c, 0xc002403, 0x34a5f000, 0x8f8300a0,
0x3c027f00, 0x621824, 0x3c020400, 0x10620053,
0x8021, 0x43102b, 0x14400008, 0x3c042000,
0x3c020100, 0x1062004d, 0x3c020200, 0x1062003a,
@@ -1299,43 +1298,43 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xaee2019c, 0x80023e3, 0x8ee2019c, 0x8f8200a0,
0x34420001, 0xaf8200a0, 0x8fbf001c, 0x8fb00018,
0x3e00008, 0x27bd0020, 0x0, 0x3c020001,
-0x8c425418, 0x27bdffe8, 0xafbf0014, 0x14400012,
-0xafb00010, 0x3c100001, 0x26105560, 0x2002021,
+0x8c425cb8, 0x27bdffe8, 0xafbf0014, 0x14400012,
+0xafb00010, 0x3c100001, 0x26105e30, 0x2002021,
0xc002488, 0x24052000, 0x26021fe0, 0x3c010001,
-0xac225534, 0x3c010001, 0xac225530, 0xaf420250,
+0xac225df4, 0x3c010001, 0xac225df0, 0xaf420250,
0x24022000, 0xaf500254, 0xaf420258, 0x24020001,
-0x3c010001, 0xac225418, 0x8fbf0014, 0x8fb00010,
-0x3e00008, 0x27bd0018, 0x3c030001, 0x8c635534,
+0x3c010001, 0xac225cb8, 0x8fbf0014, 0x8fb00010,
+0x3e00008, 0x27bd0018, 0x3c030001, 0x8c635df4,
0x8c820000, 0x8fa80010, 0x8fa90014, 0xac620000,
-0x3c020001, 0x8c425534, 0x8c830004, 0xac430004,
+0x3c020001, 0x8c425df4, 0x8c830004, 0xac430004,
0xac450008, 0x8f840054, 0x2443ffe0, 0xac460010,
0xac470014, 0xac480018, 0xac49001c, 0x3c010001,
-0xac235534, 0xac44000c, 0x3c020001, 0x24425560,
+0xac235df4, 0xac44000c, 0x3c020001, 0x24425e30,
0x62182b, 0x10600005, 0x0, 0x3c020001,
-0x8c425530, 0x3c010001, 0xac225534, 0x3c030001,
-0x8c635534, 0x3c020001, 0x8c425400, 0xac620000,
-0x3c030001, 0x8c635534, 0x3c020001, 0x8c425400,
+0x8c425df0, 0x3c010001, 0xac225df4, 0x3c030001,
+0x8c635df4, 0x3c020001, 0x8c425ca0, 0xac620000,
+0x3c030001, 0x8c635df4, 0x3c020001, 0x8c425ca0,
0xac620004, 0x3e00008, 0xaf430250, 0x3c030001,
-0x8c635534, 0x3c020001, 0x8c425400, 0x27bdffd0,
+0x8c635df4, 0x3c020001, 0x8c425ca0, 0x27bdffd0,
0xafb40020, 0x8fb40040, 0xafb00010, 0x808021,
0xafb50024, 0x8fb50044, 0x8fa40048, 0xafb10014,
0xa08821, 0xafbf0028, 0xafb3001c, 0xafb20018,
-0xac620000, 0x3c050001, 0x8ca55534, 0x3c020001,
-0x8c425400, 0xc09021, 0xe09821, 0x10800006,
+0xac620000, 0x3c050001, 0x8ca55df4, 0x3c020001,
+0x8c425ca0, 0xc09021, 0xe09821, 0x10800006,
0xaca20004, 0x24a50008, 0xc002490, 0x24060018,
0x800244e, 0x0, 0x24a40008, 0xc002488,
-0x24050018, 0x3c020001, 0x8c425534, 0x3c050001,
-0x24a55560, 0x2442ffe0, 0x3c010001, 0xac225534,
+0x24050018, 0x3c020001, 0x8c425df4, 0x3c050001,
+0x24a55e30, 0x2442ffe0, 0x3c010001, 0xac225df4,
0x45102b, 0x10400005, 0x0, 0x3c020001,
-0x8c425530, 0x3c010001, 0xac225534, 0x3c030001,
-0x8c635534, 0x8e020000, 0xac620000, 0x3c030001,
-0x8c635534, 0x8e020004, 0xac620004, 0xac710008,
-0x8f840054, 0x2462ffe0, 0x3c010001, 0xac225534,
+0x8c425df0, 0x3c010001, 0xac225df4, 0x3c030001,
+0x8c635df4, 0x8e020000, 0xac620000, 0x3c030001,
+0x8c635df4, 0x8e020004, 0xac620004, 0xac710008,
+0x8f840054, 0x2462ffe0, 0x3c010001, 0xac225df4,
0x45102b, 0xac720010, 0xac730014, 0xac740018,
0xac75001c, 0x10400005, 0xac64000c, 0x3c020001,
-0x8c425530, 0x3c010001, 0xac225534, 0x3c030001,
-0x8c635534, 0x3c020001, 0x8c425400, 0xac620000,
-0x3c030001, 0x8c635534, 0x3c020001, 0x8c425400,
+0x8c425df0, 0x3c010001, 0xac225df4, 0x3c030001,
+0x8c635df4, 0x3c020001, 0x8c425ca0, 0xac620000,
+0x3c030001, 0x8c635df4, 0x3c020001, 0x8c425ca0,
0xac620004, 0xaf430250, 0x8fbf0028, 0x8fb50024,
0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
0x8fb00010, 0x3e00008, 0x27bd0030, 0x10a00005,
@@ -1381,7 +1380,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x210c0, 0x24424e38, 0x2e22021, 0x24020005,
0xac820000, 0x24020001, 0xac820004, 0x1520000a,
0x3c040001, 0xafab0010, 0x8ee27264, 0x3c040001,
-0x24844f10, 0x3c050004, 0xafa20014, 0x8ee604e4,
+0x24845780, 0x3c050004, 0xafa20014, 0x8ee604e4,
0x80028be, 0x34a5f114, 0x8ee27264, 0x34843800,
0x3641821, 0x24420010, 0x43102b, 0x14400073,
0x0, 0x8ee27264, 0x24480010, 0x3641021,
@@ -1410,7 +1409,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x210c0, 0x24424e38, 0x2e22021, 0x24020005,
0xac820000, 0x24020001, 0xac820004, 0x1520000a,
0x2508fffc, 0xafab0010, 0x8ee27264, 0x3c040001,
-0x24844f10, 0x3c050004, 0xafa20014, 0x8ee604e4,
+0x24845780, 0x3c050004, 0xafa20014, 0x8ee604e4,
0x80028be, 0x34a5f125, 0x34028100, 0xa5020000,
0x9582000e, 0x800261d, 0xa5020002, 0x8f850100,
0x27623000, 0x24a60020, 0xc2102b, 0x50400001,
@@ -1437,7 +1436,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021,
0x24020005, 0xac820000, 0x24020001, 0xac820004,
0x1520000a, 0x34028100, 0xafab0010, 0x8ee27264,
-0x3c040001, 0x24844f10, 0x3c050004, 0xafa20014,
+0x3c040001, 0x24845780, 0x3c050004, 0xafa20014,
0x8ee604e4, 0x80028be, 0x34a5f015, 0x8ee37264,
0xa462000c, 0x8ee37264, 0x9582000e, 0xa462000e,
0x8002681, 0x24e70004, 0x8f840100, 0x27623000,
@@ -1463,7 +1462,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x24420001, 0xaee24e28, 0x8ee24e28, 0x210c0,
0x24424e38, 0x2e22021, 0x24020005, 0xac820000,
0x24020001, 0xac820004, 0x15200009, 0x3c050004,
-0xafab0010, 0x8ee27264, 0x3c040001, 0x24844f10,
+0xafab0010, 0x8ee27264, 0x3c040001, 0x24845780,
0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f004,
0x8ee2725c, 0x30e7ffff, 0x471021, 0xaee2725c,
0x8ee204e4, 0x8ee304fc, 0x8ee47258, 0x21100,
@@ -1483,7 +1482,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8f8200f0, 0x24090001, 0x8fa30018, 0x8fa4001c,
0xac430000, 0xac440004, 0xaf8700f0, 0x15200012,
0xd1142, 0x8f8200f0, 0xafa20010, 0x8f8200f4,
-0x3c040001, 0x24844f1c, 0xafa20014, 0x8fa60018,
+0x3c040001, 0x2484578c, 0xafa20014, 0x8fa60018,
0x8fa7001c, 0x3c050004, 0xc002403, 0x34a5f005,
0x8ee20088, 0x24420001, 0xaee20088, 0x8ee20088,
0x80028d3, 0xaee0725c, 0x30430003, 0x24020002,
@@ -1525,7 +1524,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38,
0x2e22021, 0x24020005, 0xac820000, 0x24020001,
0xac820004, 0x1520000a, 0x3c040001, 0xafab0010,
-0x8ee27264, 0x3c040001, 0x24844f10, 0x3c050004,
+0x8ee27264, 0x3c040001, 0x24845780, 0x3c050004,
0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f014,
0x8ee27264, 0x34843800, 0x3641821, 0x24420010,
0x43102b, 0x14400073, 0x0, 0x8ee27264,
@@ -1554,7 +1553,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38,
0x2e22021, 0x24020005, 0xac820000, 0x24020001,
0xac820004, 0x1520000a, 0x2508fffc, 0xafab0010,
-0x8ee27264, 0x3c040001, 0x24844f10, 0x3c050004,
+0x8ee27264, 0x3c040001, 0x24845780, 0x3c050004,
0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f015,
0x34028100, 0xa5020000, 0x9582000e, 0x800285f,
0xa5020002, 0x8f850100, 0x27623000, 0x24a60020,
@@ -1581,7 +1580,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x24420001, 0xaee24e28, 0x8ee24e28, 0x210c0,
0x24424e38, 0x2e22021, 0x24020005, 0xac820000,
0x24020001, 0xac820004, 0x1520000a, 0x34028100,
-0xafab0010, 0x8ee27264, 0x3c040001, 0x24844f10,
+0xafab0010, 0x8ee27264, 0x3c040001, 0x24845780,
0x3c050004, 0xafa20014, 0x8ee604e4, 0x80028be,
0x34a5f016, 0x8ee37264, 0xa462000c, 0x8ee37264,
0x9582000e, 0xa462000e, 0x80028c2, 0x24e70004,
@@ -1607,7 +1606,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38,
0x2e22021, 0x24020005, 0xac820000, 0x24020001,
0xac820004, 0x1520000b, 0x3c050004, 0x3c040001,
-0x24844f28, 0xafab0010, 0xafa00014, 0x8ee604e4,
+0x24845798, 0xafab0010, 0xafa00014, 0x8ee604e4,
0x34a5f017, 0xc002403, 0x30e7ffff, 0x80028e1,
0x0, 0x8ee27264, 0x3c050001, 0x30e4ffff,
0x441021, 0xaee27264, 0x8ee2725c, 0x8ee37264,
@@ -1673,7 +1672,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x24420001, 0xaee24e28, 0x8ee24e28, 0x210c0,
0x24424e38, 0x2e22021, 0x24020005, 0xac820000,
0x24020001, 0xac820004, 0x1540000a, 0x24020001,
-0xafa90010, 0x8ee27264, 0x3c040001, 0x24844f10,
+0xafa90010, 0x8ee27264, 0x3c040001, 0x24845780,
0x3c050004, 0xafa20014, 0x8ee604e4, 0x8002a4f,
0x34a5f204, 0xa2e204ed, 0x8ee204e8, 0x8ee304fc,
0x8ee47258, 0x3c060001, 0x34c63800, 0x3c010001,
@@ -1707,7 +1706,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38,
0x2e22021, 0x24020005, 0xac820000, 0x24020001,
0xac820004, 0x1540000c, 0x30e5ffff, 0x3c040001,
-0x24844f28, 0x3c050004, 0xafa90010, 0xafa00014,
+0x24845798, 0x3c050004, 0xafa90010, 0xafa00014,
0x8ee604e4, 0x34a5f237, 0xc002403, 0x30e7ffff,
0x8002a72, 0x0, 0x8ee27264, 0x451021,
0xaee27264, 0x8ee2726c, 0x8ee37264, 0x3c040001,
@@ -1731,7 +1730,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8f830108, 0x21140, 0x621821, 0xaf830108,
0xac800000, 0x8cc20018, 0x2443fffe, 0x2c620013,
0x104000c1, 0x31080, 0x3c010001, 0x220821,
-0x8c224f50, 0x400008, 0x0, 0x8ee204f0,
+0x8c2257c0, 0x400008, 0x0, 0x8ee204f0,
0x471021, 0xaee204f0, 0x8ee204f0, 0x8f43023c,
0x43102b, 0x144000be, 0x0, 0x8ee304e4,
0x8ee204f8, 0x506200ba, 0xa2e004f4, 0x8f830120,
@@ -1758,7 +1757,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038,
0x2e22021, 0x24020012, 0xac820000, 0x24020001,
0xac820004, 0x5600000b, 0x24100001, 0x8ee204e4,
-0x3c040001, 0x24844f34, 0xafa00014, 0xafa20010,
+0x3c040001, 0x248457a4, 0xafa00014, 0xafa20010,
0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403,
0x34a5f006, 0x16000003, 0x24020001, 0x8002b71,
0xa2e204f4, 0x8ee20170, 0x24420001, 0xaee20170,
@@ -1779,7 +1778,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8002b71, 0xaee20000, 0x8ee2014c, 0x3c010001,
0x370821, 0xa02083e0, 0x24420001, 0xaee2014c,
0x8002b71, 0x8ee2014c, 0x94c7000e, 0x8cc2001c,
-0x3c040001, 0x24844f40, 0xafa60014, 0xafa20010,
+0x3c040001, 0x248457b0, 0xafa60014, 0xafa20010,
0x8cc60018, 0x3c050008, 0xc002403, 0x34a50910,
0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020,
0x27bdff98, 0xafbf0060, 0xafbe005c, 0xafb60058,
@@ -1788,7 +1787,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xafa00024, 0x106203e7, 0xafa0002c, 0x3c1e0001,
0x37de3800, 0x3c0bffff, 0x8f930108, 0x8e620018,
0x8f830104, 0x2443fffe, 0x2c620014, 0x104003cf,
-0x31080, 0x3c010001, 0x220821, 0x8c224fa0,
+0x31080, 0x3c010001, 0x220821, 0x8c225810,
0x400008, 0x0, 0x9663000e, 0x8ee2725c,
0x8ee404f0, 0x431021, 0xaee2725c, 0x8e63001c,
0x96e20458, 0x24840001, 0xaee404f0, 0x24630001,
@@ -1817,7 +1816,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038,
0x2e22021, 0x24020012, 0x240c0001, 0xac820000,
0xac8c0004, 0x5600000d, 0x24100001, 0x8ee204e4,
-0x3c040001, 0x24844f34, 0xafa00014, 0xafa20010,
+0x3c040001, 0x248457a4, 0xafa00014, 0xafa20010,
0x8ee60608, 0x8f470228, 0x3c050009, 0x34a5f006,
0xc002403, 0xafab0038, 0x8fab0038, 0x1200030a,
0x240c0001, 0x8002f19, 0x0, 0x966c001c,
@@ -2011,7 +2010,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
0x24425038, 0x2e22021, 0x24020012, 0x240c0001,
0xac820000, 0xac8c0004, 0x5600000d, 0x24100001,
-0x8ee204e4, 0x3c040001, 0x24844f34, 0xafa00014,
+0x8ee204e4, 0x3c040001, 0x248457a4, 0xafa00014,
0xafa20010, 0x8ee60608, 0x8f470228, 0x3c050009,
0x34a5f006, 0xc002403, 0xafab0038, 0x8fab0038,
0x16000003, 0x240c0001, 0x8002f5c, 0xa2ec04f4,
@@ -2066,7 +2065,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8821, 0x8f8200e4, 0x24110001, 0x8c430000,
0x8c440004, 0xafa30018, 0xafa4001c, 0x1620000e,
0x3c02ffff, 0x8f8200c4, 0xafa20010, 0x8f8200c8,
-0x3c040001, 0x24845050, 0xafa20014, 0x8f8600e0,
+0x3c040001, 0x248458c0, 0xafa20014, 0x8f8600e0,
0x8f8700e4, 0x3c050006, 0xc002403, 0x34a5f000,
0x80034cc, 0x0, 0x8fa3001c, 0x8fb20018,
0x3074ffff, 0x2694fffc, 0x621024, 0x10400058,
@@ -2164,11 +2163,11 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x862021, 0xaee400c0, 0xaee500c4, 0x8ee20058,
0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c,
0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0,
-0xafa20010, 0x8f8200e4, 0x3c040001, 0x24845058,
+0xafa20010, 0x8f8200e4, 0x3c040001, 0x248458c8,
0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006,
0xc002403, 0x34a5f003, 0x80034cc, 0x0,
0x8ee25240, 0xafa20010, 0x8ee25244, 0x3c040001,
-0x24845064, 0xafa20014, 0x8ee60e10, 0x8ee70e18,
+0x248458d4, 0xafa20014, 0x8ee60e10, 0x8ee70e18,
0x3c050006, 0xc002403, 0x34a5f002, 0x8ee201c0,
0x24420001, 0xaee201c0, 0x8ee20000, 0x8ee301c0,
0x2403ffbf, 0x431024, 0x8003470, 0xaee20000,
@@ -2220,7 +2219,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x50550003, 0x1021, 0x8ee24e30, 0x24420001,
0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038,
0x2e22021, 0xac960000, 0xac9e0004, 0x16200018,
-0x3c050006, 0x8e020018, 0x3c040001, 0x24845070,
+0x3c050006, 0x8e020018, 0x3c040001, 0x248458e0,
0xafa20010, 0x8e020000, 0x8e030004, 0x34a5f009,
0x2003021, 0xc002403, 0xafa30014, 0x93a20037,
0x10400216, 0x340f8100, 0x8e420004, 0x8e430008,
@@ -2253,7 +2252,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x210c0, 0x24425038, 0x2e22021, 0xac960000,
0xac9e0004, 0x1620000d, 0x0, 0xa60c000a,
0xa60a000e, 0x8f820100, 0xafa20010, 0x8f820104,
-0x3c040001, 0x2484507c, 0x3c050006, 0xafa20014,
+0x3c040001, 0x248458ec, 0x3c050006, 0xafa20014,
0x8ee6724c, 0x800343b, 0x34a5f00b, 0x3c010001,
0x370821, 0xa02083c0, 0xadab0000, 0x8ee201d8,
0x8ee3724c, 0x2442ffff, 0xaee201d8, 0x8ee201d8,
@@ -2285,7 +2284,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
0xac8e0000, 0xac9e0004, 0x5620000d, 0x24110001,
-0x8ee2724c, 0x3c040001, 0x24845088, 0xafa00014,
+0x8ee2724c, 0x3c040001, 0x248458f8, 0xafa00014,
0xafa20010, 0x8ee6724c, 0x8f470280, 0x3c050009,
0x34a5f008, 0xc002403, 0xafae0048, 0x8fae0048,
0x56200001, 0xaee00e1c, 0x8ee20188, 0x24420001,
@@ -2312,7 +2311,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30,
0x210c0, 0x24425038, 0x2e22021, 0xac8e0000,
0xac9e0004, 0x1620000d, 0x0, 0x8ee2724c,
-0x3c040001, 0x24845088, 0xafa00014, 0xafa20010,
+0x3c040001, 0x248458f8, 0xafa00014, 0xafa20010,
0x8ee6724c, 0x8f470280, 0x3c050009, 0x34a5f008,
0xc002403, 0xafae0048, 0x8fae0048, 0x8ee20174,
0x24420001, 0xaee20174, 0x8ee20174, 0x800346e,
@@ -2342,7 +2341,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
0xac960000, 0xac9e0004, 0x1620001d, 0x0,
0xa60c000a, 0x8f820100, 0xafa20010, 0x8f820104,
-0x3c040001, 0x2484507c, 0x3c050006, 0xafa20014,
+0x3c040001, 0x248458ec, 0x3c050006, 0xafa20014,
0x8ee6724c, 0x34a5f00d, 0xc002403, 0x2003821,
0x93a20037, 0x10400031, 0x340f8100, 0x8e420004,
0x8e430008, 0x8e44000c, 0xa64f000c, 0xae420000,
@@ -2404,7 +2403,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x10430007, 0x4821, 0x8f8200e4, 0x24090001,
0x8c430000, 0x8c440004, 0xafa30018, 0xafa4001c,
0x1520000e, 0x3c02ffff, 0x8f8200c4, 0xafa20010,
-0x8f8200c8, 0x3c040001, 0x24845050, 0xafa20014,
+0x8f8200c8, 0x3c040001, 0x248458c0, 0xafa20014,
0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc002403,
0x34a5f000, 0x8003850, 0x0, 0x8fa3001c,
0x8fb20018, 0x3073ffff, 0x2673fffc, 0x621024,
@@ -2502,15 +2501,15 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x862021, 0xaee400c0, 0xaee500c4, 0x8ee20058,
0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c,
0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0,
-0xafa20010, 0x8f8200e4, 0x3c040001, 0x24845058,
+0xafa20010, 0x8f8200e4, 0x3c040001, 0x248458c8,
0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006,
0xc002403, 0x34a5f003, 0x8003850, 0x0,
0x8ee25240, 0xafa20010, 0x8ee25244, 0x3c040001,
-0x24845064, 0xafa20014, 0x8ee60e10, 0x8ee70e18,
+0x248458d4, 0xafa20014, 0x8ee60e10, 0x8ee70e18,
0xc002403, 0x34a5f002, 0x8ee201c0, 0x24420001,
0xaee201c0, 0x8ee20000, 0x8ee301c0, 0x2403ffbf,
0x431024, 0x80037f8, 0xaee20000, 0x8ee25240,
-0xafa20010, 0x8ee25244, 0x3c040001, 0x24845064,
+0xafa20010, 0x8ee25244, 0x3c040001, 0x248458d4,
0xafa20014, 0x8ee60e10, 0x8ee70e18, 0x3c050006,
0xc002403, 0x34a5f002, 0x8ee201c0, 0x24420001,
0xaee201c0, 0x80037f8, 0x8ee201c0, 0x96e20468,
@@ -2569,7 +2568,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
0x24425038, 0x2e22021, 0x24020007, 0xac820000,
0x24020001, 0xac820004, 0x15200018, 0x3c050006,
-0x8e020018, 0x3c040001, 0x24845070, 0xafa20010,
+0x8e020018, 0x3c040001, 0x248458e0, 0xafa20010,
0x8e020000, 0x8e030004, 0x34a5f009, 0x2003021,
0xc002403, 0xafa30014, 0x32c200ff, 0x1040002b,
0x34028100, 0x8e430004, 0x8e440008, 0x8e45000c,
@@ -2629,7 +2628,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x10430007, 0x3821, 0x8f8200e4, 0x24070001,
0x8c430000, 0x8c440004, 0xafa30018, 0xafa4001c,
0x14e0000e, 0x3c02ffff, 0x8f8200c4, 0xafa20010,
-0x8f8200c8, 0x3c040001, 0x24845094, 0xafa20014,
+0x8f8200c8, 0x3c040001, 0x24845904, 0xafa20014,
0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc002403,
0x34a5f200, 0x8003c5b, 0x0, 0x8fa3001c,
0x8fb20018, 0x3073ffff, 0x2673fffc, 0x621024,
@@ -2727,11 +2726,11 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x862021, 0xaee400c0, 0xaee500c4, 0x8ee20058,
0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c,
0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0,
-0xafa20010, 0x8f8200e4, 0x3c040001, 0x248450a0,
+0xafa20010, 0x8f8200e4, 0x3c040001, 0x24845910,
0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006,
0xc002403, 0x34a5f203, 0x8003c5b, 0x0,
0x8ee25240, 0xafa20010, 0x8ee25244, 0x3c040001,
-0x248450ac, 0xafa20014, 0x8ee60e10, 0x8ee70e18,
+0x2484591c, 0xafa20014, 0x8ee60e10, 0x8ee70e18,
0x3c050006, 0xc002403, 0x34a5f202, 0x8ee201c0,
0x24420001, 0xaee201c0, 0x8003c02, 0x8ee201c0,
0x96e20468, 0x53102b, 0x54400001, 0x3c168000,
@@ -2827,7 +2826,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
0x24020007, 0xac820000, 0x24020001, 0xac820004,
-0x14e00019, 0x3c050006, 0x3c040001, 0x24845070,
+0x14e00019, 0x3c050006, 0x3c040001, 0x248458e0,
0x8e220018, 0x34a5f209, 0xafa20010, 0x8e220000,
0x8e230004, 0x2203021, 0x1603821, 0xc002403,
0xafa30014, 0x93a2002f, 0x1040002a, 0x34028100,
@@ -2891,7 +2890,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x24020001, 0xac620004, 0x1480000e, 0x24030040,
0x8ee20e14, 0xafa20010, 0x8ee20e18, 0x3c050007,
0xafa20014, 0x8ee60e0c, 0x8ee70e10, 0x3c040001,
-0x248450b4, 0xc002403, 0x34a5f001, 0x8003cdd,
+0x24845924, 0xc002403, 0x34a5f001, 0x8003cdd,
0x0, 0x8ee20500, 0x24420001, 0x50430003,
0x1021, 0x8ee20500, 0x24420001, 0xaee20500,
0x8ee20500, 0x21080, 0x571021, 0xac490508,
@@ -2923,7 +2922,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x24020003, 0xac620000, 0x24020001, 0xac620004,
0x1480000e, 0x24030040, 0x8ee2523c, 0xafa20010,
0x8ee25244, 0x3c050007, 0xafa20014, 0x8ee65238,
-0x8ee75240, 0x3c040001, 0x248450c0, 0xc002403,
+0x8ee75240, 0x3c040001, 0x24845930, 0xc002403,
0x34a5f010, 0x8003d5f, 0x0, 0x8ee20500,
0x24420001, 0x50430003, 0x1021, 0x8ee20500,
0x24420001, 0xaee20500, 0x8ee20500, 0x21080,
@@ -2943,7 +2942,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8f830128, 0x21140, 0x621821, 0xaf830128,
0xaca00000, 0x8cc20018, 0x2443fffe, 0x2c620012,
0x10400008, 0x31080, 0x3c010001, 0x220821,
-0x8c2250d0, 0x400008, 0x0, 0x24020001,
+0x8c225940, 0x400008, 0x0, 0x24020001,
0xaee24e24, 0x3e00008, 0x0, 0x27bdffc8,
0xafbf0030, 0xafb5002c, 0xafb40028, 0xafb30024,
0xafb20020, 0xafb1001c, 0xafb00018, 0x8f830128,
@@ -2952,7 +2951,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x24140040, 0x8f8c0128, 0x8f820128, 0x24420020,
0xaf820128, 0x9182001b, 0x8f830128, 0x2443fffe,
0x2c620012, 0x1040029c, 0x31080, 0x3c010001,
-0x220821, 0x8c225128, 0x400008, 0x0,
+0x220821, 0x8c225998, 0x400008, 0x0,
0x8f420218, 0x30420100, 0x10400007, 0x0,
0x95830016, 0x95820018, 0x621823, 0x31402,
0x431021, 0xa5820016, 0x8d82001c, 0x3c038000,
@@ -3053,7 +3052,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
0x24425038, 0x2e22021, 0x24020007, 0xac820000,
0x24020001, 0xac820004, 0x1600000d, 0x0,
-0x8f820120, 0x3c040001, 0x24845118, 0xafa00014,
+0x8f820120, 0x3c040001, 0x24845988, 0xafa00014,
0xafa20010, 0x8d86001c, 0x8f870124, 0x3c050008,
0xc002403, 0x34a50001, 0x8004057, 0x0,
0x8ee2724c, 0x24420001, 0x304207ff, 0x11a00006,
@@ -3088,7 +3087,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
0x24425038, 0x2e22021, 0x24020001, 0xac950000,
0xac820004, 0x5600000b, 0x24100001, 0x8ee2724c,
-0x3c040001, 0x24845088, 0xafa00014, 0xafa20010,
+0x3c040001, 0x248458f8, 0xafa00014, 0xafa20010,
0x8ee6724c, 0x8f470280, 0x3c050009, 0xc002403,
0x34a5f008, 0x56000001, 0xaee00e1c, 0x8ee20188,
0x24420001, 0xaee20188, 0x8004050, 0x8ee20188,
@@ -3114,7 +3113,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
0x24020001, 0xac950000, 0xac820004, 0x1600000b,
-0x0, 0x8ee2724c, 0x3c040001, 0x24845088,
+0x0, 0x8ee2724c, 0x3c040001, 0x248458f8,
0xafa00014, 0xafa20010, 0x8ee6724c, 0x8f470280,
0x3c050009, 0xc002403, 0x34a5f008, 0x8ee20174,
0x24420001, 0xaee20174, 0x8004057, 0x8ee20174,
@@ -3126,16 +3125,16 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xc00249a, 0xafb00010, 0x2021, 0x24100001,
0x2402241f, 0xaf900210, 0xaf900200, 0xaf800204,
0xaf820214, 0x8f460248, 0x24030004, 0x3c020040,
-0x3c010001, 0xac235484, 0x3c010001, 0xac235488,
-0x3c010001, 0xac20553c, 0x3c010001, 0xac225480,
-0x3c010001, 0xac235488, 0xc004fa8, 0x24050004,
-0xc004785, 0x0, 0x8ee20000, 0x3c03feff,
+0x3c010001, 0xac235d24, 0x3c010001, 0xac235d28,
+0x3c010001, 0xac205dfc, 0x3c010001, 0xac225d20,
+0x3c010001, 0xac235d28, 0xc0050e0, 0x24050004,
+0xc0047fc, 0x0, 0x8ee20000, 0x3c03feff,
0x3463fffd, 0x431024, 0xaee20000, 0x3c023c00,
0xaf82021c, 0x3c010001, 0x370821, 0xac3083ac,
0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
0x27bdffe0, 0x3c050008, 0x34a50400, 0xafbf0018,
0xafa00010, 0xafa00014, 0x8f860200, 0x3c040001,
-0x248451d0, 0xc002403, 0x3821, 0x8ee20280,
+0x24845a40, 0xc002403, 0x3821, 0x8ee20280,
0x24420001, 0xaee20280, 0x8ee20280, 0x8f830200,
0x3c023f00, 0x621824, 0x8fbf0018, 0x3c020400,
0x3e00008, 0x27bd0020, 0x27bdffd8, 0xafbf0020,
@@ -3147,16 +3146,16 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xaee20218, 0x8ee20218, 0x80040c6, 0x3c03fdff,
0x8ee2021c, 0x24420001, 0xaee2021c, 0x8ee2021c,
0x3c03fdff, 0x3463ffff, 0x3c0808ff, 0x3508ffff,
-0x8ee20000, 0x3c040001, 0x248451dc, 0x3c050008,
+0x8ee20000, 0x3c040001, 0x24845a4c, 0x3c050008,
0x2003021, 0x431024, 0xaee20000, 0x8f820220,
0x3821, 0x3c030300, 0x481024, 0x431025,
0xaf820220, 0xafa00010, 0xc002403, 0xafa00014,
0x8004296, 0x0, 0x2111024, 0x1040001f,
0x3c024000, 0x8f830224, 0x24021402, 0x1462000b,
-0x3c03fdff, 0x3c040001, 0x248451e8, 0x3c050008,
+0x3c03fdff, 0x3c040001, 0x24845a58, 0x3c050008,
0xafa00010, 0xafa00014, 0x8f860224, 0x34a5ffff,
0xc002403, 0x3821, 0x3c03fdff, 0x8ee20000,
-0x3463ffff, 0x2002021, 0x431024, 0xc004cf4,
+0x3463ffff, 0x2002021, 0x431024, 0xc004e2c,
0xaee20000, 0x8ee20220, 0x24420001, 0xaee20220,
0x8ee20220, 0x8f820220, 0x3c0308ff, 0x3463ffff,
0x431024, 0x8004295, 0x511025, 0x2021024,
@@ -3227,7 +3226,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x431025, 0xaf820220, 0x8f8600e0, 0x8f8400e4,
0x10c4002a, 0x0, 0x8ee2007c, 0x24420001,
0xaee2007c, 0x8ee2007c, 0x24c2fff8, 0xaf8200e0,
-0x3c020001, 0x8c4275c0, 0x3c030008, 0x8f8600e0,
+0x3c020001, 0x8c427e90, 0x3c030008, 0x8f8600e0,
0x431024, 0x1040001d, 0x0, 0x10c4001b,
0x240dfff8, 0x3c0a000a, 0x354af000, 0x3c0c0080,
0x24850008, 0x27622800, 0x50a20001, 0x27651800,
@@ -3263,12 +3262,12 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x621023, 0x2c420002, 0x1440fffc, 0x0,
0x8f820220, 0x3c0308ff, 0x3463fffb, 0x431024,
0xaf820220, 0x8fbf0020, 0x8fb1001c, 0x8fb00018,
-0x3e00008, 0x27bd0028, 0x3c020001, 0x8c425498,
+0x3e00008, 0x27bd0028, 0x3c020001, 0x8c425d38,
0x27bdffd8, 0x10400012, 0xafbf0020, 0x3c040001,
-0x248451f4, 0x3c050008, 0x24020001, 0x3c010001,
+0x24845a64, 0x3c050008, 0x24020001, 0x3c010001,
0x370821, 0xac2283ac, 0xafa00010, 0xafa00014,
-0x8f860220, 0x34a50498, 0x3c010001, 0xac205498,
-0x3c010001, 0xac22548c, 0xc002403, 0x3821,
+0x8f860220, 0x34a50498, 0x3c010001, 0xac205d38,
+0x3c010001, 0xac225d2c, 0xc002403, 0x3821,
0x8f420268, 0x3c037fff, 0x3463ffff, 0x431024,
0xaf420268, 0x8ee204d0, 0x8ee404d4, 0x2403fffe,
0x431024, 0x30840002, 0x1080011e, 0xaee204d0,
@@ -3334,24 +3333,24 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x54a00006, 0x240b0001, 0x8f820054, 0x1221023,
0x2c420033, 0x1440ffa6, 0x0, 0x316300ff,
0x24020001, 0x54620003, 0xafa00010, 0x80043d6,
-0x0, 0x3c040001, 0x24845200, 0xafa00014,
+0x0, 0x3c040001, 0x24845a70, 0xafa00014,
0x8f860120, 0x8f870124, 0x3c050009, 0xc002403,
0x34a5f011, 0x80043d6, 0x0, 0x3c040001,
-0x2484520c, 0xafa00014, 0x8f860120, 0x8f870124,
+0x24845a7c, 0xafa00014, 0x8f860120, 0x8f870124,
0x3c050009, 0xc002403, 0x34a5f010, 0x80043d6,
-0x0, 0x3c040001, 0x24845218, 0xafa00014,
+0x0, 0x3c040001, 0x24845a88, 0xafa00014,
0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403,
0x34a5f00f, 0x8ee201ac, 0x24420001, 0xaee201ac,
0x8ee201ac, 0x8ee2015c, 0x24420001, 0xaee2015c,
0x8ee2015c, 0x8fbf0020, 0x3e00008, 0x27bd0028,
-0x3c020001, 0x8c425498, 0x27bdffe0, 0x1440000d,
-0xafbf0018, 0x3c040001, 0x24845224, 0x3c050008,
+0x3c020001, 0x8c425d38, 0x27bdffe0, 0x1440000d,
+0xafbf0018, 0x3c040001, 0x24845a94, 0x3c050008,
0xafa00010, 0xafa00014, 0x8f860220, 0x34a50499,
-0x24020001, 0x3c010001, 0xac225498, 0xc002403,
+0x24020001, 0x3c010001, 0xac225d38, 0xc002403,
0x3821, 0x8ee204d0, 0x3c030001, 0x771821,
0x946383b2, 0x34420001, 0x10600007, 0xaee204d0,
0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024,
-0x34420008, 0xaf820220, 0x2021, 0xc0050b3,
+0x34420008, 0xaf820220, 0x2021, 0xc005276,
0x24050004, 0xaf420268, 0x8fbf0018, 0x3e00008,
0x27bd0020, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
@@ -3369,7 +3368,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x3c120001,
-0x26521200, 0x3c140001, 0x8e945410, 0x3c100001,
+0x26521200, 0x3c140001, 0x8e945cb0, 0x3c100001,
0x26101120, 0x3c15c000, 0x36b50060, 0x8e8a0000,
0x8eb30000, 0x26a400b, 0x248000a, 0x200f821,
0x0, 0xd, 0x0, 0x0,
@@ -3430,843 +3429,978 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x1062000c, 0x43102b, 0x14400006, 0x3c026000,
0x3c024000, 0x10620008, 0x24020800, 0x8004539,
0x0, 0x10620004, 0x24020800, 0x8004539,
-0x0, 0x24020700, 0x3c010001, 0xac22549c,
+0x0, 0x24020700, 0x3c010001, 0xac225d3c,
0x3e00008, 0x0, 0x27bdffd0, 0xafbf0028,
-0x3c010001, 0xc004cd1, 0xac205484, 0x24040001,
-0x2821, 0x27a60020, 0x34028000, 0xc0048ee,
-0xa7a20020, 0x8f830054, 0x8f820054, 0x800454b,
-0x24630064, 0x8f820054, 0x621023, 0x2c420065,
-0x1440fffc, 0x24040001, 0x24050001, 0xc0048ac,
-0x27a60020, 0x8f830054, 0x8f820054, 0x8004557,
-0x24630064, 0x8f820054, 0x621023, 0x2c420065,
-0x1440fffc, 0x24040001, 0x24050001, 0xc0048ac,
-0x27a60020, 0x8f830054, 0x8f820054, 0x8004563,
-0x24630064, 0x8f820054, 0x621023, 0x2c420065,
-0x1440fffc, 0x24040001, 0x24050002, 0xc0048ac,
-0x27a60018, 0x8f830054, 0x8f820054, 0x800456f,
-0x24630064, 0x8f820054, 0x621023, 0x2c420065,
-0x1440fffc, 0x24040001, 0x24050003, 0xc0048ac,
-0x27a6001a, 0x97a20020, 0x10400028, 0x24030001,
-0x3c020001, 0x8c425484, 0x97a30018, 0x34420001,
-0x3c010001, 0xac225484, 0x24020015, 0x1462000e,
-0x0, 0x97a2001a, 0x3042fff0, 0x3843f420,
-0x2c630001, 0x3842f430, 0x2c420001, 0x621825,
-0x10600005, 0x24020003, 0x3c010001, 0xac225550,
-0x80045a8, 0x3c08fff0, 0x97a30018, 0x24027810,
-0x1462000a, 0x24020002, 0x97a2001a, 0x3042fff0,
-0x14400006, 0x24020002, 0x24020004, 0x3c010001,
-0xac225550, 0x80045a8, 0x3c08fff0, 0x3c010001,
-0xac225550, 0x80045a8, 0x3c08fff0, 0x3c020001,
-0x8c425484, 0x3c010001, 0xac235550, 0x34420004,
-0x3c010001, 0xac225484, 0x3c08fff0, 0x3508bdc0,
-0x8f830054, 0x97a60018, 0x3c070001, 0x8ce75550,
-0x3c040001, 0x24845290, 0x24020001, 0x3c010001,
-0xac22548c, 0xafa60010, 0x3c060001, 0x8cc65484,
-0x97a2001a, 0x3c05000d, 0x34a50100, 0x3c010001,
-0xac205488, 0x681821, 0x3c010001, 0xac235548,
-0xc002403, 0xafa20014, 0x8fbf0028, 0x3e00008,
-0x27bd0030, 0x27bdffe8, 0x24070004, 0x3c040001,
-0x8c845488, 0x3021, 0x24020001, 0x1482000a,
-0xafbf0010, 0x3c020001, 0x8c4275cc, 0x3c050004,
-0x30428000, 0x1040000c, 0x34a593e0, 0x3c05000f,
-0x80045db, 0x34a54240, 0x3c020001, 0x8c4275cc,
-0x3c05000f, 0x30428000, 0x10400003, 0x34a54240,
-0x3c05001e, 0x34a58480, 0x3c020001, 0x8c425548,
-0x8f830054, 0x451021, 0x431023, 0x45102b,
-0x1440002e, 0x0, 0x3c020001, 0x8c425490,
-0x1440002a, 0x2cc20001, 0x7182b, 0x431024,
-0x1040001d, 0x0, 0x3c090001, 0x8d295484,
-0x240b0001, 0x3c054000, 0x3c080001, 0x250875cc,
-0x250afffc, 0x42042, 0x14800002, 0x24e7ffff,
-0x24040008, 0x891024, 0x5040000b, 0x2cc20001,
-0x148b0004, 0x0, 0x8d020000, 0x8004600,
-0x451024, 0x8d420000, 0x451024, 0x54400001,
-0x24060001, 0x2cc20001, 0x7182b, 0x431024,
-0x5440ffed, 0x42042, 0x3c010001, 0x10c00024,
-0xac245488, 0x8f830054, 0x24020001, 0x3c010001,
-0xac22548c, 0x3c010001, 0xac235548, 0x3c020001,
-0x8c42548c, 0x10400006, 0x24020001, 0x3c010001,
-0xac20548c, 0x3c010001, 0x370821, 0xac2283ac,
-0x3c030001, 0x771821, 0x8c6383ac, 0x24020008,
-0x10620005, 0x24020001, 0xc004630, 0x0,
-0x800462d, 0x0, 0x3c030001, 0x8c635488,
-0x10620007, 0x2402000e, 0x3c030001, 0x8c637560,
-0x10620003, 0x0, 0xc004cf4, 0x8f840220,
-0x8fbf0010, 0x3e00008, 0x27bd0018, 0x27bdffe0,
-0x3c02fdff, 0xafbf0018, 0x8ee30000, 0x3c050001,
-0x8ca55488, 0x3c040001, 0x8c8454a8, 0x3442ffff,
-0x621824, 0x14a40008, 0xaee30000, 0x3c030001,
-0x771821, 0x8c6383ac, 0x3c020001, 0x8c4254ac,
-0x10620008, 0x0, 0x3c020001, 0x571021,
-0x8c4283ac, 0x3c010001, 0xac2554a8, 0x3c010001,
-0xac2254ac, 0x3c030001, 0x8c635488, 0x24020002,
-0x10620131, 0x2c620003, 0x10400005, 0x24020001,
-0x10620008, 0x0, 0x800477f, 0x0,
-0x24020004, 0x10620079, 0x24020001, 0x8004780,
+0x8f830054, 0x8f820054, 0x3c010001, 0xac205d24,
+0x8004544, 0x24630064, 0x8f820054, 0x621023,
+0x2c420065, 0x1440fffc, 0x0, 0xc004d49,
+0x0, 0x24040001, 0x2821, 0x27a60020,
+0x34028000, 0xc004966, 0xa7a20020, 0x8f830054,
+0x8f820054, 0x8004555, 0x24630064, 0x8f820054,
+0x621023, 0x2c420065, 0x1440fffc, 0x24040001,
+0x24050001, 0xc004924, 0x27a60020, 0x8f830054,
+0x8f820054, 0x8004561, 0x24630064, 0x8f820054,
+0x621023, 0x2c420065, 0x1440fffc, 0x24040001,
+0x24050001, 0xc004924, 0x27a60020, 0x8f830054,
+0x8f820054, 0x800456d, 0x24630064, 0x8f820054,
+0x621023, 0x2c420065, 0x1440fffc, 0x24040001,
+0x24050002, 0xc004924, 0x27a60018, 0x8f830054,
+0x8f820054, 0x8004579, 0x24630064, 0x8f820054,
+0x621023, 0x2c420065, 0x1440fffc, 0x24040001,
+0x24050003, 0xc004924, 0x27a6001a, 0x3c040001,
+0x24845b00, 0x97a60020, 0x97a70018, 0x97a2001a,
+0x3c05000d, 0x34a50100, 0xafa00014, 0xc002403,
+0xafa20010, 0x97a20020, 0x10400045, 0x24036040,
+0x97a2001a, 0x3042fff0, 0x14430009, 0x24020020,
+0x97a30018, 0x54620008, 0x24027830, 0x24020003,
+0x3c010001, 0xac225d24, 0x80045a4, 0x24020005,
+0x97a30018, 0x24027830, 0x1462000e, 0x24030010,
+0x97a2001a, 0x3042fff0, 0x1443000a, 0x24020003,
+0x3c010001, 0xac225d24, 0x24020006, 0x3c010001,
+0xac225e0c, 0x3c010001, 0xac225e18, 0x80045da,
+0x3c09fff0, 0x3c020001, 0x8c425d24, 0x97a30018,
+0x34420001, 0x3c010001, 0xac225d24, 0x24020015,
+0x1462000e, 0x0, 0x97a2001a, 0x3042fff0,
+0x3843f420, 0x2c630001, 0x3842f430, 0x2c420001,
+0x621825, 0x10600005, 0x24020003, 0x3c010001,
+0xac225e18, 0x80045da, 0x3c09fff0, 0x97a30018,
+0x24027810, 0x1462000a, 0x24020002, 0x97a2001a,
+0x3042fff0, 0x14400006, 0x24020002, 0x24020004,
+0x3c010001, 0xac225e18, 0x80045da, 0x3c09fff0,
+0x3c010001, 0xac225e18, 0x80045da, 0x3c09fff0,
+0x3c020001, 0x8c425d24, 0x24030001, 0x3c010001,
+0xac235e18, 0x34420004, 0x3c010001, 0xac225d24,
+0x3c09fff0, 0x3529bdc0, 0x8f830054, 0x3c060001,
+0x8cc65d24, 0x3c070001, 0x8ce75e18, 0x97a80018,
+0x3c040001, 0x24845b00, 0x24020001, 0x3c010001,
+0xac225d2c, 0xafa80010, 0x97a2001a, 0x3c05000d,
+0x34a50100, 0x3c010001, 0xac205d28, 0x691821,
+0x3c010001, 0xac235e08, 0xc002403, 0xafa20014,
+0x8fbf0028, 0x3e00008, 0x27bd0030, 0x27bdffe8,
+0x3c050001, 0x8ca55d28, 0x24060004, 0x24020001,
+0x14a20014, 0xafbf0010, 0x3c020001, 0x8c427e9c,
+0x30428000, 0x10400005, 0x3c04000f, 0x3c030001,
+0x8c635e18, 0x8004608, 0x34844240, 0x3c040004,
+0x3c030001, 0x8c635e18, 0x348493e0, 0x24020005,
+0x14620016, 0x0, 0x3c04003d, 0x8004620,
+0x34840900, 0x3c020001, 0x8c427e98, 0x30428000,
+0x10400005, 0x3c04001e, 0x3c030001, 0x8c635e18,
+0x800461b, 0x34848480, 0x3c04000f, 0x3c030001,
+0x8c635e18, 0x34844240, 0x24020005, 0x14620003,
+0x0, 0x3c04007a, 0x34841200, 0x3c020001,
+0x8c425e08, 0x8f830054, 0x441021, 0x431023,
+0x44102b, 0x14400037, 0x0, 0x3c020001,
+0x8c425d30, 0x14400033, 0x0, 0x3c010001,
+0x10c00025, 0xac205d40, 0x3c090001, 0x8d295d24,
+0x24070001, 0x3c044000, 0x3c080001, 0x25087e9c,
+0x250afffc, 0x52842, 0x14a00002, 0x24c6ffff,
+0x24050008, 0xa91024, 0x10400010, 0x0,
+0x14a70008, 0x0, 0x8d020000, 0x441024,
+0x1040000a, 0x0, 0x3c010001, 0x800464c,
+0xac255d40, 0x8d420000, 0x441024, 0x10400003,
+0x0, 0x3c010001, 0xac275d40, 0x3c020001,
+0x8c425d40, 0x6182b, 0x2c420001, 0x431024,
+0x5440ffe5, 0x52842, 0x8f820054, 0x3c030001,
+0x8c635d40, 0x3c010001, 0xac225e08, 0x1060002a,
+0x24020001, 0x3c010001, 0xac255d28, 0x3c010001,
+0xac225d2c, 0x3c020001, 0x8c425d40, 0x10400022,
+0x0, 0x3c020001, 0x8c425d2c, 0x1040000a,
+0x24020001, 0x3c010001, 0xac205d2c, 0x3c010001,
+0x370821, 0xac2283ac, 0x3c010001, 0xac205dac,
+0x3c010001, 0xac225d64, 0x3c030001, 0x771821,
+0x8c6383ac, 0x24020008, 0x10620005, 0x24020001,
+0xc004686, 0x0, 0x8004683, 0x0,
+0x3c030001, 0x8c635d28, 0x10620007, 0x2402000e,
+0x3c030001, 0x8c637e30, 0x10620003, 0x0,
+0xc004e2c, 0x8f840220, 0x8fbf0010, 0x3e00008,
+0x27bd0018, 0x27bdffe0, 0x3c02fdff, 0xafbf001c,
+0xafb00018, 0x8ee30000, 0x3c050001, 0x8ca55d28,
+0x3c040001, 0x8c845d50, 0x3442ffff, 0x621824,
+0x14a40008, 0xaee30000, 0x3c030001, 0x771821,
+0x8c6383ac, 0x3c020001, 0x8c425d54, 0x10620008,
0x0, 0x3c020001, 0x571021, 0x8c4283ac,
-0x2443ffff, 0x2c620008, 0x10400122, 0x31080,
-0x3c010001, 0x220821, 0x8c2252a8, 0x400008,
-0x0, 0xc004785, 0x0, 0x3c020001,
-0x8c425494, 0x3c010001, 0xac205420, 0x104000bd,
-0x24020002, 0x3c010001, 0x370821, 0xac2283ac,
-0x3c010001, 0x8004782, 0xac205494, 0xc00492f,
-0x0, 0x3c030001, 0x8c6354b0, 0x80046f1,
-0x24020011, 0x3c050001, 0x8ca55488, 0x3c060001,
-0x8cc675cc, 0xc004fa8, 0x2021, 0x24020005,
-0x3c010001, 0xac205494, 0x3c010001, 0x370821,
-0x8004782, 0xac2283ac, 0x3c040001, 0x2484529c,
-0x3c05000f, 0x34a50100, 0x3021, 0x3821,
-0xafa00010, 0xc002403, 0xafa00014, 0x8004782,
-0x0, 0x8f820220, 0x3c03f700, 0x431025,
-0x800471a, 0xaf820220, 0x8f820220, 0x3c030004,
-0x431024, 0x14400090, 0x24020007, 0x8f830054,
-0x3c020001, 0x8c425540, 0x2463d8f0, 0x431023,
-0x2c422710, 0x144000df, 0x24020001, 0x8004780,
-0x0, 0x3c050001, 0x8ca55488, 0xc0050b3,
-0x2021, 0xc00517e, 0x2021, 0x3c030001,
-0x8c6375c4, 0x46100d1, 0x24020001, 0x3c020008,
-0x621024, 0x10400006, 0x0, 0x8f820214,
-0x3c03ffff, 0x431024, 0x80046bd, 0x3442251f,
-0x8f820214, 0x3c03ffff, 0x431024, 0x3442241f,
-0xaf820214, 0x8ee20000, 0x3c030200, 0x431025,
-0xaee20000, 0x8f820220, 0x2403fffb, 0x431024,
-0xaf820220, 0x8f820220, 0x34420002, 0xaf820220,
-0x24020008, 0x3c010001, 0x370821, 0xc0043dd,
-0xac2283ac, 0x8004782, 0x0, 0x3c020001,
-0x571021, 0x8c4283ac, 0x2443ffff, 0x2c620008,
-0x104000ac, 0x31080, 0x3c010001, 0x220821,
-0x8c2252c8, 0x400008, 0x0, 0xc00429b,
-0x0, 0x3c010001, 0xac20548c, 0xaf800204,
-0x3c010001, 0xc004785, 0xac2075b0, 0x24020001,
-0x3c010001, 0xac2254a0, 0x24020002, 0x3c010001,
-0x370821, 0x8004782, 0xac2283ac, 0xc004802,
-0x0, 0x3c030001, 0x8c6354a0, 0x24020009,
-0x14620090, 0x24020003, 0x3c010001, 0x370821,
-0x8004782, 0xac2283ac, 0x3c020001, 0x8c4275c8,
-0x30424000, 0x10400005, 0x0, 0x8f820044,
-0x3c03ffff, 0x8004702, 0x34637fff, 0x8f820044,
-0x2403ff7f, 0x431024, 0xaf820044, 0x8f830054,
-0x800471c, 0x24020004, 0x8f830054, 0x3c020001,
-0x8c425540, 0x2463d8f0, 0x431023, 0x2c422710,
-0x14400074, 0x24020005, 0x3c010001, 0x370821,
-0x8004782, 0xac2283ac, 0x8f820220, 0x3c03f700,
-0x431025, 0xaf820220, 0xaf800204, 0x3c010001,
-0xac2075b0, 0x8f830054, 0x24020006, 0x3c010001,
-0x370821, 0xac2283ac, 0x3c010001, 0x8004782,
-0xac235540, 0x8f830054, 0x3c020001, 0x8c425540,
-0x2463fff6, 0x431023, 0x2c42000a, 0x14400059,
-0x0, 0x24020007, 0x3c010001, 0x370821,
-0x8004782, 0xac2283ac, 0x8f820220, 0x3c04f700,
-0x441025, 0xaf820220, 0x8f820220, 0x3c030300,
-0x431024, 0x14400005, 0x1821, 0x8f820220,
-0x24030001, 0x441025, 0xaf820220, 0x10600043,
-0x24020001, 0x8f820214, 0x3c03ffff, 0x3c040001,
-0x8c845538, 0x431024, 0x3442251f, 0xaf820214,
-0x24020008, 0x3c010001, 0x370821, 0x1080000b,
-0xac2283ac, 0x3c020001, 0x8c425514, 0x14400007,
-0x24020001, 0x3c010001, 0xac227560, 0xc004cf4,
-0x8f840220, 0x800476f, 0x0, 0x8f820220,
-0x3c030008, 0x431024, 0x14400017, 0x2402000e,
-0x3c010001, 0xac227560, 0x8ee20000, 0x2021,
-0x3c030200, 0x431025, 0xc00517e, 0xaee20000,
-0x8f820220, 0x2403fffb, 0x431024, 0xaf820220,
-0x8f820220, 0x34420002, 0xc0043dd, 0xaf820220,
-0x3c050001, 0x8ca55488, 0xc0050b3, 0x2021,
-0x8004782, 0x0, 0x3c020001, 0x8c425514,
-0x10400010, 0x0, 0x3c020001, 0x8c425510,
-0x2442ffff, 0x3c010001, 0xac225510, 0x14400009,
-0x24020002, 0x3c010001, 0xac205514, 0x3c010001,
-0x8004782, 0xac225510, 0x24020001, 0x3c010001,
-0xac22548c, 0x8fbf0018, 0x3e00008, 0x27bd0020,
-0x8f820200, 0x8f820220, 0x8f820220, 0x34420004,
-0xaf820220, 0x8f820200, 0x3c060001, 0x8cc65488,
-0x34420004, 0xaf820200, 0x24020002, 0x10c2003a,
-0x2cc20003, 0x10400005, 0x24020001, 0x10c20008,
-0x0, 0x80047cb, 0x0, 0x24020004,
-0x10c20013, 0x24020001, 0x80047cb, 0x0,
-0x3c030001, 0x8c635478, 0x3c020001, 0x8c425480,
-0x3c040001, 0x8c84549c, 0x3c050001, 0x8ca5547c,
-0xaf860200, 0xaf860220, 0x34630022, 0x441025,
-0x451025, 0x34420002, 0x80047ca, 0xaf830200,
-0x3c030001, 0x8c635538, 0xaf820200, 0x10600009,
-0xaf820220, 0x3c020001, 0x8c425514, 0x14400005,
-0x3c033f00, 0x3c020001, 0x8c425470, 0x80047be,
-0x346300e0, 0x3c020001, 0x8c425470, 0x3c033f00,
-0x346300e2, 0x431025, 0xaf820200, 0x3c030001,
-0x8c635474, 0x3c04f700, 0x3c020001, 0x8c425480,
-0x3c050001, 0x8ca5549c, 0x641825, 0x431025,
-0x451025, 0xaf820220, 0x3e00008, 0x0,
-0x8f820220, 0x3c030001, 0x8c635488, 0x34420004,
-0xaf820220, 0x24020001, 0x1062000f, 0x0,
-0x8f830054, 0x8f820054, 0x24630002, 0x621023,
-0x2c420003, 0x10400011, 0x0, 0x8f820054,
-0x621023, 0x2c420003, 0x1040000c, 0x0,
-0x80047dc, 0x0, 0x8f830054, 0x8f820054,
-0x80047e8, 0x24630007, 0x8f820054, 0x621023,
-0x2c420008, 0x1440fffc, 0x0, 0x8f8400e0,
-0x30820007, 0x1040000d, 0x0, 0x8f820054,
-0x8f8300e0, 0x14830009, 0x24450032, 0x8f820054,
-0xa21023, 0x2c420033, 0x10400004, 0x0,
-0x8f8200e0, 0x1082fff9, 0x0, 0x8f820220,
-0x2403fffd, 0x431024, 0xaf820220, 0x3e00008,
-0x0, 0x3c030001, 0x8c6354a0, 0x3c020001,
-0x8c4254a4, 0x50620004, 0x2463ffff, 0x3c010001,
-0xac2354a4, 0x2463ffff, 0x2c620009, 0x1040009d,
-0x31080, 0x3c010001, 0x220821, 0x8c2252e8,
-0x400008, 0x0, 0x8f820044, 0x34428080,
-0xaf820044, 0x8f830054, 0x800489b, 0x24020002,
-0x8f830054, 0x3c020001, 0x8c425544, 0x2463d8f0,
-0x431023, 0x2c422710, 0x1440008a, 0x24020003,
-0x80048a8, 0x0, 0x8f820044, 0x3c03ffff,
-0x34637fff, 0x431024, 0xaf820044, 0x8f830054,
-0x800489b, 0x24020004, 0x8f830054, 0x3c020001,
-0x8c425544, 0x2463fff6, 0x431023, 0x2c42000a,
-0x14400078, 0x24020005, 0x80048a8, 0x0,
+0x3c010001, 0xac255d50, 0x3c010001, 0xac225d54,
+0x3c030001, 0x8c635d28, 0x24020002, 0x10620150,
+0x2c620003, 0x10400005, 0x24020001, 0x10620008,
+0x0, 0x80047f5, 0x0, 0x24020004,
+0x10620098, 0x24020001, 0x80047f6, 0x0,
+0x3c020001, 0x571021, 0x8c4283ac, 0x2443ffff,
+0x2c620008, 0x10400141, 0x31080, 0x3c010001,
+0x220821, 0x8c225b18, 0x400008, 0x0,
+0x3c030001, 0x8c635e18, 0x24020005, 0x14620014,
+0x0, 0x3c020001, 0x8c425d34, 0x1040000a,
+0x24020003, 0xc0047fc, 0x0, 0x24020002,
+0x3c010001, 0x370821, 0xac2283ac, 0x3c010001,
+0x80046d2, 0xac205d34, 0x3c010001, 0x370821,
+0xac2283ac, 0x3c010001, 0x80047f8, 0xac205cc0,
+0xc0047fc, 0x0, 0x3c020001, 0x8c425d34,
+0x3c010001, 0xac205cc0, 0x104000c4, 0x24020002,
+0x3c010001, 0x370821, 0xac2283ac, 0x3c010001,
+0x80047f8, 0xac205d34, 0x24020001, 0x3c010001,
+0xc0049a7, 0xac225d60, 0x3c030001, 0x8c635d60,
+0x8004767, 0x24020011, 0x3c020001, 0x8c425e18,
+0x24100005, 0x10500007, 0x0, 0x3c050001,
+0x8ca55d28, 0x3c060001, 0x8cc67e9c, 0xc0050e0,
+0x2021, 0x3c010001, 0xac205d34, 0x3c010001,
+0x370821, 0x80047f8, 0xac3083ac, 0x3c040001,
+0x24845b0c, 0x3c05000f, 0x34a50100, 0x3021,
+0x3821, 0xafa00010, 0xc002403, 0xafa00014,
+0x80047f8, 0x0, 0x8f820220, 0x3c03f700,
+0x431025, 0x8004790, 0xaf820220, 0x8f820220,
+0x3c030004, 0x431024, 0x14400091, 0x24020007,
+0x8f830054, 0x3c020001, 0x8c425e00, 0x2463d8f0,
+0x431023, 0x2c422710, 0x144000e0, 0x24020001,
+0x80047f6, 0x0, 0x3c050001, 0x8ca55d28,
+0xc005276, 0x2021, 0xc005397, 0x2021,
+0x3c030001, 0x8c637e94, 0x46100d2, 0x24020001,
+0x3c020008, 0x621024, 0x10400006, 0x0,
+0x8f820214, 0x3c03ffff, 0x431024, 0x8004732,
+0x3442251f, 0x8f820214, 0x3c03ffff, 0x431024,
+0x3442241f, 0xaf820214, 0x8ee20000, 0x3c030200,
+0x431025, 0xaee20000, 0x8f820220, 0x2403fffb,
+0x431024, 0xaf820220, 0x8f820220, 0x34420002,
+0xaf820220, 0x24020008, 0x3c010001, 0x370821,
+0xc0043dd, 0xac2283ac, 0x3c010001, 0x80047f8,
+0xac205db0, 0x3c020001, 0x571021, 0x8c4283ac,
+0x2443ffff, 0x2c620008, 0x104000ac, 0x31080,
+0x3c010001, 0x220821, 0x8c225b38, 0x400008,
+0x0, 0xc00429b, 0x0, 0x3c010001,
+0xac205d2c, 0xaf800204, 0x3c010001, 0xc0047fc,
+0xac207e80, 0x24020001, 0x3c010001, 0xac225d44,
+0x24020002, 0x3c010001, 0x370821, 0x80047f8,
+0xac2283ac, 0xc004879, 0x0, 0x3c030001,
+0x8c635d44, 0x24020009, 0x14620090, 0x24020003,
+0x3c010001, 0x370821, 0x80047f8, 0xac2283ac,
+0x3c020001, 0x8c427e98, 0x30424000, 0x10400005,
+0x0, 0x8f820044, 0x3c03ffff, 0x8004778,
+0x34637fff, 0x8f820044, 0x2403ff7f, 0x431024,
+0xaf820044, 0x8f830054, 0x8004792, 0x24020004,
+0x8f830054, 0x3c020001, 0x8c425e00, 0x2463d8f0,
+0x431023, 0x2c422710, 0x14400074, 0x24020005,
+0x3c010001, 0x370821, 0x80047f8, 0xac2283ac,
0x8f820220, 0x3c03f700, 0x431025, 0xaf820220,
-0x8f820220, 0x2403fffb, 0x431024, 0xaf820220,
-0x8f820220, 0x34420002, 0xaf820220, 0x3c023f00,
-0x344200e0, 0xaf820200, 0x8f820200, 0x2403fffd,
-0x431024, 0xaf820200, 0x24040001, 0x3405ffff,
-0xaf840204, 0x8f830054, 0x8f820054, 0x800484f,
-0x24630001, 0x8f820054, 0x621023, 0x2c420002,
-0x1440fffc, 0x0, 0x8f820224, 0x42040,
-0xa4102b, 0x1040fff2, 0x0, 0x8f820220,
-0x3c03f700, 0x431025, 0xaf820220, 0x8f820214,
-0x3c03ffff, 0x431024, 0x3442251f, 0xaf820214,
-0x8f820220, 0x2403fffb, 0x431024, 0xaf820220,
-0x8f820220, 0x3c04f700, 0x34840008, 0x34420002,
-0xaf820220, 0x8f820220, 0x3c033f00, 0x346300e2,
-0x441025, 0xaf820220, 0xaf830200, 0x8f8400f0,
-0x276217f8, 0x14820002, 0x24850008, 0x27651000,
-0x8f8200f4, 0x10a20007, 0x3c038000, 0x34630040,
-0x3c020001, 0x24425430, 0xac820000, 0xac830004,
-0xaf8500f0, 0x8f830054, 0x800489b, 0x24020006,
-0x8f830054, 0x3c020001, 0x8c425544, 0x2463fff6,
-0x431023, 0x2c42000a, 0x14400022, 0x24020007,
-0x80048a8, 0x0, 0x8f8200e0, 0xaf8200e4,
-0x8f8200e0, 0xaf8200e8, 0x8f820220, 0x34420004,
-0xaf820220, 0x8f820220, 0x2403fff7, 0x431024,
-0xaf820220, 0x8f820044, 0x34428080, 0xaf820044,
-0x8f830054, 0x24020008, 0x3c010001, 0xac2254a0,
-0x3c010001, 0x80048aa, 0xac235544, 0x8f830054,
-0x3c020001, 0x8c425544, 0x2463d8f0, 0x431023,
-0x2c422710, 0x14400003, 0x24020009, 0x3c010001,
-0xac2254a0, 0x3e00008, 0x0, 0x27bdffd8,
+0xaf800204, 0x3c010001, 0xac207e80, 0x8f830054,
+0x24020006, 0x3c010001, 0x370821, 0xac2283ac,
+0x3c010001, 0x80047f8, 0xac235e00, 0x8f830054,
+0x3c020001, 0x8c425e00, 0x2463fff6, 0x431023,
+0x2c42000a, 0x14400059, 0x0, 0x24020007,
+0x3c010001, 0x370821, 0x80047f8, 0xac2283ac,
+0x8f820220, 0x3c04f700, 0x441025, 0xaf820220,
+0x8f820220, 0x3c030300, 0x431024, 0x14400005,
+0x1821, 0x8f820220, 0x24030001, 0x441025,
+0xaf820220, 0x10600043, 0x24020001, 0x8f820214,
+0x3c03ffff, 0x3c040001, 0x8c845df8, 0x431024,
+0x3442251f, 0xaf820214, 0x24020008, 0x3c010001,
+0x370821, 0x1080000b, 0xac2283ac, 0x3c020001,
+0x8c425dd4, 0x14400007, 0x24020001, 0x3c010001,
+0xac227e30, 0xc004e2c, 0x8f840220, 0x80047e5,
+0x0, 0x8f820220, 0x3c030008, 0x431024,
+0x14400017, 0x2402000e, 0x3c010001, 0xac227e30,
+0x8ee20000, 0x2021, 0x3c030200, 0x431025,
+0xc005397, 0xaee20000, 0x8f820220, 0x2403fffb,
+0x431024, 0xaf820220, 0x8f820220, 0x34420002,
+0xc0043dd, 0xaf820220, 0x3c050001, 0x8ca55d28,
+0xc005276, 0x2021, 0x80047f8, 0x0,
+0x3c020001, 0x8c425dd4, 0x10400010, 0x0,
+0x3c020001, 0x8c425dd0, 0x2442ffff, 0x3c010001,
+0xac225dd0, 0x14400009, 0x24020002, 0x3c010001,
+0xac205dd4, 0x3c010001, 0x80047f8, 0xac225dd0,
+0x24020001, 0x3c010001, 0xac225d2c, 0x8fbf001c,
+0x8fb00018, 0x3e00008, 0x27bd0020, 0x8f820200,
+0x8f820220, 0x8f820220, 0x34420004, 0xaf820220,
+0x8f820200, 0x3c060001, 0x8cc65d28, 0x34420004,
+0xaf820200, 0x24020002, 0x10c2003a, 0x2cc20003,
+0x10400005, 0x24020001, 0x10c20008, 0x0,
+0x8004842, 0x0, 0x24020004, 0x10c20013,
+0x24020001, 0x8004842, 0x0, 0x3c030001,
+0x8c635d18, 0x3c020001, 0x8c425d20, 0x3c040001,
+0x8c845d3c, 0x3c050001, 0x8ca55d1c, 0xaf860200,
+0xaf860220, 0x34630022, 0x441025, 0x451025,
+0x34420002, 0x8004841, 0xaf830200, 0x3c030001,
+0x8c635df8, 0xaf820200, 0x10600009, 0xaf820220,
+0x3c020001, 0x8c425dd4, 0x14400005, 0x3c033f00,
+0x3c020001, 0x8c425d10, 0x8004835, 0x346300e0,
+0x3c020001, 0x8c425d10, 0x3c033f00, 0x346300e2,
+0x431025, 0xaf820200, 0x3c030001, 0x8c635d14,
+0x3c04f700, 0x3c020001, 0x8c425d20, 0x3c050001,
+0x8ca55d3c, 0x641825, 0x431025, 0x451025,
+0xaf820220, 0x3e00008, 0x0, 0x8f820220,
+0x3c030001, 0x8c635d28, 0x34420004, 0xaf820220,
+0x24020001, 0x1062000f, 0x0, 0x8f830054,
+0x8f820054, 0x24630002, 0x621023, 0x2c420003,
+0x10400011, 0x0, 0x8f820054, 0x621023,
+0x2c420003, 0x1040000c, 0x0, 0x8004853,
+0x0, 0x8f830054, 0x8f820054, 0x800485f,
+0x24630007, 0x8f820054, 0x621023, 0x2c420008,
+0x1440fffc, 0x0, 0x8f8400e0, 0x30820007,
+0x1040000d, 0x0, 0x8f820054, 0x8f8300e0,
+0x14830009, 0x24450032, 0x8f820054, 0xa21023,
+0x2c420033, 0x10400004, 0x0, 0x8f8200e0,
+0x1082fff9, 0x0, 0x8f820220, 0x2403fffd,
+0x431024, 0xaf820220, 0x3e00008, 0x0,
+0x3c030001, 0x8c635d44, 0x3c020001, 0x8c425d48,
+0x50620004, 0x2463ffff, 0x3c010001, 0xac235d48,
+0x2463ffff, 0x2c620009, 0x1040009d, 0x31080,
+0x3c010001, 0x220821, 0x8c225b58, 0x400008,
+0x0, 0x8f820044, 0x34428080, 0xaf820044,
+0x8f830054, 0x8004912, 0x24020002, 0x8f830054,
+0x3c020001, 0x8c425e04, 0x2463d8f0, 0x431023,
+0x2c422710, 0x1440008a, 0x24020003, 0x800491f,
+0x0, 0x8f820044, 0x3c03ffff, 0x34637fff,
+0x431024, 0xaf820044, 0x8f830054, 0x8004912,
+0x24020004, 0x8f830054, 0x3c020001, 0x8c425e04,
+0x2463fff6, 0x431023, 0x2c42000a, 0x14400078,
+0x24020005, 0x800491f, 0x0, 0x8f820220,
+0x3c03f700, 0x431025, 0xaf820220, 0x8f820220,
+0x2403fffb, 0x431024, 0xaf820220, 0x8f820220,
+0x34420002, 0xaf820220, 0x3c023f00, 0x344200e0,
+0xaf820200, 0x8f820200, 0x2403fffd, 0x431024,
+0xaf820200, 0x24040001, 0x3405ffff, 0xaf840204,
+0x8f830054, 0x8f820054, 0x80048c6, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
+0x0, 0x8f820224, 0x42040, 0xa4102b,
+0x1040fff2, 0x0, 0x8f820220, 0x3c03f700,
+0x431025, 0xaf820220, 0x8f820214, 0x3c03ffff,
+0x431024, 0x3442251f, 0xaf820214, 0x8f820220,
+0x2403fffb, 0x431024, 0xaf820220, 0x8f820220,
+0x3c04f700, 0x34840008, 0x34420002, 0xaf820220,
+0x8f820220, 0x3c033f00, 0x346300e2, 0x441025,
+0xaf820220, 0xaf830200, 0x8f8400f0, 0x276217f8,
+0x14820002, 0x24850008, 0x27651000, 0x8f8200f4,
+0x10a20007, 0x3c038000, 0x34630040, 0x3c020001,
+0x24425cd0, 0xac820000, 0xac830004, 0xaf8500f0,
+0x8f830054, 0x8004912, 0x24020006, 0x8f830054,
+0x3c020001, 0x8c425e04, 0x2463fff6, 0x431023,
+0x2c42000a, 0x14400022, 0x24020007, 0x800491f,
+0x0, 0x8f8200e0, 0xaf8200e4, 0x8f8200e0,
+0xaf8200e8, 0x8f820220, 0x34420004, 0xaf820220,
+0x8f820220, 0x2403fff7, 0x431024, 0xaf820220,
+0x8f820044, 0x34428080, 0xaf820044, 0x8f830054,
+0x24020008, 0x3c010001, 0xac225d44, 0x3c010001,
+0x8004921, 0xac235e04, 0x8f830054, 0x3c020001,
+0x8c425e04, 0x2463d8f0, 0x431023, 0x2c422710,
+0x14400003, 0x24020009, 0x3c010001, 0xac225d44,
+0x3e00008, 0x0, 0x0, 0x27bdffd8,
0xafb20018, 0x809021, 0xafb3001c, 0xa09821,
0xafb10014, 0xc08821, 0xafb00010, 0x8021,
-0xafbf0020, 0xa6200000, 0xc004cab, 0x24040001,
+0xafbf0020, 0xa6200000, 0xc004d23, 0x24040001,
0x26100001, 0x2e020020, 0x1440fffb, 0x0,
-0xc004cab, 0x2021, 0xc004cab, 0x24040001,
-0xc004cab, 0x24040001, 0xc004cab, 0x2021,
+0xc004d23, 0x2021, 0xc004d23, 0x24040001,
+0xc004d23, 0x24040001, 0xc004d23, 0x2021,
0x24100010, 0x2501024, 0x10400002, 0x2021,
-0x24040001, 0xc004cab, 0x108042, 0x1600fffa,
+0x24040001, 0xc004d23, 0x108042, 0x1600fffa,
0x2501024, 0x24100010, 0x2701024, 0x10400002,
-0x2021, 0x24040001, 0xc004cab, 0x108042,
-0x1600fffa, 0x2701024, 0xc004cd1, 0x34108000,
-0xc004cd1, 0x0, 0xc004c8b, 0x0,
+0x2021, 0x24040001, 0xc004d23, 0x108042,
+0x1600fffa, 0x2701024, 0xc004d49, 0x34108000,
+0xc004d49, 0x0, 0xc004d03, 0x0,
0x50400005, 0x108042, 0x96220000, 0x501025,
0xa6220000, 0x108042, 0x1600fff7, 0x0,
-0xc004cd1, 0x0, 0x8fbf0020, 0x8fb3001c,
+0xc004d49, 0x0, 0x8fbf0020, 0x8fb3001c,
0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
0x27bd0028, 0x27bdffd8, 0xafb10014, 0x808821,
0xafb20018, 0xa09021, 0xafb3001c, 0xc09821,
-0xafb00010, 0x8021, 0xafbf0020, 0xc004cab,
+0xafb00010, 0x8021, 0xafbf0020, 0xc004d23,
0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004cab, 0x2021, 0xc004cab,
-0x24040001, 0xc004cab, 0x2021, 0xc004cab,
+0x0, 0xc004d23, 0x2021, 0xc004d23,
+0x24040001, 0xc004d23, 0x2021, 0xc004d23,
0x24040001, 0x24100010, 0x2301024, 0x10400002,
-0x2021, 0x24040001, 0xc004cab, 0x108042,
+0x2021, 0x24040001, 0xc004d23, 0x108042,
0x1600fffa, 0x2301024, 0x24100010, 0x2501024,
-0x10400002, 0x2021, 0x24040001, 0xc004cab,
-0x108042, 0x1600fffa, 0x2501024, 0xc004cab,
-0x24040001, 0xc004cab, 0x2021, 0x34108000,
+0x10400002, 0x2021, 0x24040001, 0xc004d23,
+0x108042, 0x1600fffa, 0x2501024, 0xc004d23,
+0x24040001, 0xc004d23, 0x2021, 0x34108000,
0x96620000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004cab, 0x108042, 0x1600fff8,
-0x0, 0xc004cd1, 0x0, 0x8fbf0020,
+0x24040001, 0xc004d23, 0x108042, 0x1600fff8,
+0x0, 0xc004d49, 0x0, 0x8fbf0020,
0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0028, 0x3c030001, 0x8c6354b0,
-0x3c020001, 0x8c4254f4, 0x27bdffd8, 0xafbf0020,
+0x3e00008, 0x27bd0028, 0x3c030001, 0x8c635d60,
+0x3c020001, 0x8c425da8, 0x27bdffd8, 0xafbf0020,
0xafb1001c, 0x10620003, 0xafb00018, 0x3c010001,
-0xac2354f4, 0x2463ffff, 0x2c620013, 0x10400349,
-0x31080, 0x3c010001, 0x220821, 0x8c225310,
-0x400008, 0x0, 0xc004cd1, 0x8021,
-0x34028000, 0xa7a20010, 0x27b10010, 0xc004cab,
+0xac235da8, 0x2463ffff, 0x2c620013, 0x10400349,
+0x31080, 0x3c010001, 0x220821, 0x8c225b80,
+0x400008, 0x0, 0xc004d49, 0x8021,
+0x34028000, 0xa7a20010, 0x27b10010, 0xc004d23,
0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004cab, 0x2021, 0xc004cab,
-0x24040001, 0xc004cab, 0x2021, 0xc004cab,
+0x0, 0xc004d23, 0x2021, 0xc004d23,
+0x24040001, 0xc004d23, 0x2021, 0xc004d23,
0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004cab, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0xc004cab,
+0x2021, 0x24040001, 0xc004d23, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0xc004d23,
0x2021, 0x108042, 0x1600fffc, 0x0,
-0xc004cab, 0x24040001, 0xc004cab, 0x2021,
+0xc004d23, 0x24040001, 0xc004d23, 0x2021,
0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004cab, 0x108042,
-0x1600fff8, 0x0, 0xc004cd1, 0x0,
-0x8004c84, 0x24020002, 0x27b10010, 0xa7a00010,
-0x8021, 0xc004cab, 0x24040001, 0x26100001,
-0x2e020020, 0x1440fffb, 0x0, 0xc004cab,
-0x2021, 0xc004cab, 0x24040001, 0xc004cab,
-0x24040001, 0xc004cab, 0x2021, 0x24100010,
+0x2021, 0x24040001, 0xc004d23, 0x108042,
+0x1600fff8, 0x0, 0xc004d49, 0x0,
+0x8004cfc, 0x24020002, 0x27b10010, 0xa7a00010,
+0x8021, 0xc004d23, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004d23,
+0x2021, 0xc004d23, 0x24040001, 0xc004d23,
+0x24040001, 0xc004d23, 0x2021, 0x24100010,
0x32020001, 0x10400002, 0x2021, 0x24040001,
-0xc004cab, 0x108042, 0x1600fffa, 0x32020001,
-0x24100010, 0xc004cab, 0x2021, 0x108042,
-0x1600fffc, 0x0, 0xc004cd1, 0x34108000,
-0xc004cd1, 0x0, 0xc004c8b, 0x0,
+0xc004d23, 0x108042, 0x1600fffa, 0x32020001,
+0x24100010, 0xc004d23, 0x2021, 0x108042,
+0x1600fffc, 0x0, 0xc004d49, 0x34108000,
+0xc004d49, 0x0, 0xc004d03, 0x0,
0x50400005, 0x108042, 0x96220000, 0x501025,
0xa6220000, 0x108042, 0x1600fff7, 0x0,
-0xc004cd1, 0x0, 0x97a20010, 0x30428000,
-0x144002dc, 0x24020003, 0x8004c84, 0x0,
+0xc004d49, 0x0, 0x97a20010, 0x30428000,
+0x144002dc, 0x24020003, 0x8004cfc, 0x0,
0x24021200, 0xa7a20010, 0x27b10010, 0x8021,
-0xc004cab, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004cab, 0x2021,
-0xc004cab, 0x24040001, 0xc004cab, 0x2021,
-0xc004cab, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004cab,
+0xc004d23, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d23, 0x2021,
+0xc004d23, 0x24040001, 0xc004d23, 0x2021,
+0xc004d23, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d23,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0xc004cab, 0x2021, 0x108042, 0x1600fffc,
-0x0, 0xc004cab, 0x24040001, 0xc004cab,
+0xc004d23, 0x2021, 0x108042, 0x1600fffc,
+0x0, 0xc004d23, 0x24040001, 0xc004d23,
0x2021, 0x34108000, 0x96220000, 0x501024,
-0x10400002, 0x2021, 0x24040001, 0xc004cab,
-0x108042, 0x1600fff8, 0x0, 0xc004cd1,
-0x0, 0x8f830054, 0x8004c76, 0x24020004,
-0x8f830054, 0x3c020001, 0x8c42554c, 0x2463ff9c,
+0x10400002, 0x2021, 0x24040001, 0xc004d23,
+0x108042, 0x1600fff8, 0x0, 0xc004d49,
+0x0, 0x8f830054, 0x8004cee, 0x24020004,
+0x8f830054, 0x3c020001, 0x8c425e14, 0x2463ff9c,
0x431023, 0x2c420064, 0x1440029e, 0x24020002,
-0x3c030001, 0x8c635550, 0x10620297, 0x2c620003,
+0x3c030001, 0x8c635e18, 0x10620297, 0x2c620003,
0x14400296, 0x24020011, 0x24020003, 0x10620005,
-0x24020004, 0x10620291, 0x2402000f, 0x8004c84,
-0x24020011, 0x8004c84, 0x24020005, 0x24020014,
-0xa7a20010, 0x27b10010, 0x8021, 0xc004cab,
+0x24020004, 0x10620291, 0x2402000f, 0x8004cfc,
+0x24020011, 0x8004cfc, 0x24020005, 0x24020014,
+0xa7a20010, 0x27b10010, 0x8021, 0xc004d23,
0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004cab, 0x2021, 0xc004cab,
-0x24040001, 0xc004cab, 0x2021, 0xc004cab,
+0x0, 0xc004d23, 0x2021, 0xc004d23,
+0x24040001, 0xc004d23, 0x2021, 0xc004d23,
0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004cab, 0x108042,
+0x2021, 0x24040001, 0xc004d23, 0x108042,
0x1600fffa, 0x32020001, 0x24100010, 0x32020012,
-0x10400002, 0x2021, 0x24040001, 0xc004cab,
-0x108042, 0x1600fffa, 0x32020012, 0xc004cab,
-0x24040001, 0xc004cab, 0x2021, 0x34108000,
+0x10400002, 0x2021, 0x24040001, 0xc004d23,
+0x108042, 0x1600fffa, 0x32020012, 0xc004d23,
+0x24040001, 0xc004d23, 0x2021, 0x34108000,
0x96220000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004cab, 0x108042, 0x1600fff8,
-0x0, 0xc004cd1, 0x0, 0x8f830054,
-0x8004c76, 0x24020006, 0x8f830054, 0x3c020001,
-0x8c42554c, 0x2463ff9c, 0x431023, 0x2c420064,
-0x14400250, 0x24020007, 0x8004c84, 0x0,
+0x24040001, 0xc004d23, 0x108042, 0x1600fff8,
+0x0, 0xc004d49, 0x0, 0x8f830054,
+0x8004cee, 0x24020006, 0x8f830054, 0x3c020001,
+0x8c425e14, 0x2463ff9c, 0x431023, 0x2c420064,
+0x14400250, 0x24020007, 0x8004cfc, 0x0,
0x24020006, 0xa7a20010, 0x27b10010, 0x8021,
-0xc004cab, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004cab, 0x2021,
-0xc004cab, 0x24040001, 0xc004cab, 0x2021,
-0xc004cab, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004cab,
+0xc004d23, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d23, 0x2021,
+0xc004d23, 0x24040001, 0xc004d23, 0x2021,
+0xc004d23, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d23,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
0x32020013, 0x10400002, 0x2021, 0x24040001,
-0xc004cab, 0x108042, 0x1600fffa, 0x32020013,
-0xc004cab, 0x24040001, 0xc004cab, 0x2021,
+0xc004d23, 0x108042, 0x1600fffa, 0x32020013,
+0xc004d23, 0x24040001, 0xc004d23, 0x2021,
0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004cab, 0x108042,
-0x1600fff8, 0x0, 0xc004cd1, 0x0,
-0x8f830054, 0x8004c76, 0x24020008, 0x8f830054,
-0x3c020001, 0x8c42554c, 0x2463ff9c, 0x431023,
-0x2c420064, 0x1440020f, 0x24020009, 0x8004c84,
+0x2021, 0x24040001, 0xc004d23, 0x108042,
+0x1600fff8, 0x0, 0xc004d49, 0x0,
+0x8f830054, 0x8004cee, 0x24020008, 0x8f830054,
+0x3c020001, 0x8c425e14, 0x2463ff9c, 0x431023,
+0x2c420064, 0x1440020f, 0x24020009, 0x8004cfc,
0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004cab, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004cab, 0x2021,
-0xc004cab, 0x24040001, 0xc004cab, 0x24040001,
-0xc004cab, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004cab,
+0xc004d23, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d23, 0x2021,
+0xc004d23, 0x24040001, 0xc004d23, 0x24040001,
+0xc004d23, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d23,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004cab, 0x108042, 0x1600fffa, 0x32020018,
-0xc004cd1, 0x34108000, 0xc004cd1, 0x0,
-0xc004c8b, 0x0, 0x50400005, 0x108042,
+0xc004d23, 0x108042, 0x1600fffa, 0x32020018,
+0xc004d49, 0x34108000, 0xc004d49, 0x0,
+0xc004d03, 0x0, 0x50400005, 0x108042,
0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004cd1, 0x8021,
+0x1600fff7, 0x0, 0xc004d49, 0x8021,
0x97a20010, 0x27b10010, 0x34420001, 0xa7a20010,
-0xc004cab, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004cab, 0x2021,
-0xc004cab, 0x24040001, 0xc004cab, 0x2021,
-0xc004cab, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004cab,
+0xc004d23, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d23, 0x2021,
+0xc004d23, 0x24040001, 0xc004d23, 0x2021,
+0xc004d23, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d23,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004cab, 0x108042, 0x1600fffa, 0x32020018,
-0xc004cab, 0x24040001, 0xc004cab, 0x2021,
+0xc004d23, 0x108042, 0x1600fffa, 0x32020018,
+0xc004d23, 0x24040001, 0xc004d23, 0x2021,
0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004cab, 0x108042,
-0x1600fff8, 0x0, 0xc004cd1, 0x0,
-0x8f830054, 0x8004c76, 0x2402000a, 0x8f830054,
-0x3c020001, 0x8c42554c, 0x2463ff9c, 0x431023,
-0x2c420064, 0x1440019b, 0x2402000b, 0x8004c84,
+0x2021, 0x24040001, 0xc004d23, 0x108042,
+0x1600fff8, 0x0, 0xc004d49, 0x0,
+0x8f830054, 0x8004cee, 0x2402000a, 0x8f830054,
+0x3c020001, 0x8c425e14, 0x2463ff9c, 0x431023,
+0x2c420064, 0x1440019b, 0x2402000b, 0x8004cfc,
0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004cab, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004cab, 0x2021,
-0xc004cab, 0x24040001, 0xc004cab, 0x24040001,
-0xc004cab, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004cab,
+0xc004d23, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d23, 0x2021,
+0xc004d23, 0x24040001, 0xc004d23, 0x24040001,
+0xc004d23, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d23,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
0x32020017, 0x10400002, 0x2021, 0x24040001,
-0xc004cab, 0x108042, 0x1600fffa, 0x32020017,
-0xc004cd1, 0x34108000, 0xc004cd1, 0x0,
-0xc004c8b, 0x0, 0x50400005, 0x108042,
+0xc004d23, 0x108042, 0x1600fffa, 0x32020017,
+0xc004d49, 0x34108000, 0xc004d49, 0x0,
+0xc004d03, 0x0, 0x50400005, 0x108042,
0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004cd1, 0x8021,
+0x1600fff7, 0x0, 0xc004d49, 0x8021,
0x97a20010, 0x27b10010, 0x34420700, 0xa7a20010,
-0xc004cab, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004cab, 0x2021,
-0xc004cab, 0x24040001, 0xc004cab, 0x2021,
-0xc004cab, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004cab,
+0xc004d23, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d23, 0x2021,
+0xc004d23, 0x24040001, 0xc004d23, 0x2021,
+0xc004d23, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d23,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
0x32020017, 0x10400002, 0x2021, 0x24040001,
-0xc004cab, 0x108042, 0x1600fffa, 0x32020017,
-0xc004cab, 0x24040001, 0xc004cab, 0x2021,
+0xc004d23, 0x108042, 0x1600fffa, 0x32020017,
+0xc004d23, 0x24040001, 0xc004d23, 0x2021,
0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004cab, 0x108042,
-0x1600fff8, 0x0, 0xc004cd1, 0x0,
-0x8f830054, 0x8004c76, 0x2402000c, 0x8f830054,
-0x3c020001, 0x8c42554c, 0x2463ff9c, 0x431023,
-0x2c420064, 0x14400127, 0x24020012, 0x8004c84,
+0x2021, 0x24040001, 0xc004d23, 0x108042,
+0x1600fff8, 0x0, 0xc004d49, 0x0,
+0x8f830054, 0x8004cee, 0x2402000c, 0x8f830054,
+0x3c020001, 0x8c425e14, 0x2463ff9c, 0x431023,
+0x2c420064, 0x14400127, 0x24020012, 0x8004cfc,
0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004cab, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004cab, 0x2021,
-0xc004cab, 0x24040001, 0xc004cab, 0x24040001,
-0xc004cab, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004cab,
+0xc004d23, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d23, 0x2021,
+0xc004d23, 0x24040001, 0xc004d23, 0x24040001,
+0xc004d23, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d23,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
0x32020014, 0x10400002, 0x2021, 0x24040001,
-0xc004cab, 0x108042, 0x1600fffa, 0x32020014,
-0xc004cd1, 0x34108000, 0xc004cd1, 0x0,
-0xc004c8b, 0x0, 0x50400005, 0x108042,
+0xc004d23, 0x108042, 0x1600fffa, 0x32020014,
+0xc004d49, 0x34108000, 0xc004d49, 0x0,
+0xc004d03, 0x0, 0x50400005, 0x108042,
0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004cd1, 0x8021,
+0x1600fff7, 0x0, 0xc004d49, 0x8021,
0x97a20010, 0x27b10010, 0x34420010, 0xa7a20010,
-0xc004cab, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004cab, 0x2021,
-0xc004cab, 0x24040001, 0xc004cab, 0x2021,
-0xc004cab, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004cab,
+0xc004d23, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d23, 0x2021,
+0xc004d23, 0x24040001, 0xc004d23, 0x2021,
+0xc004d23, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d23,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
0x32020014, 0x10400002, 0x2021, 0x24040001,
-0xc004cab, 0x108042, 0x1600fffa, 0x32020014,
-0xc004cab, 0x24040001, 0xc004cab, 0x2021,
+0xc004d23, 0x108042, 0x1600fffa, 0x32020014,
+0xc004d23, 0x24040001, 0xc004d23, 0x2021,
0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004cab, 0x108042,
-0x1600fff8, 0x0, 0xc004cd1, 0x0,
-0x8f830054, 0x8004c76, 0x24020013, 0x8f830054,
-0x3c020001, 0x8c42554c, 0x2463ff9c, 0x431023,
-0x2c420064, 0x144000b3, 0x2402000d, 0x8004c84,
+0x2021, 0x24040001, 0xc004d23, 0x108042,
+0x1600fff8, 0x0, 0xc004d49, 0x0,
+0x8f830054, 0x8004cee, 0x24020013, 0x8f830054,
+0x3c020001, 0x8c425e14, 0x2463ff9c, 0x431023,
+0x2c420064, 0x144000b3, 0x2402000d, 0x8004cfc,
0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004cab, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004cab, 0x2021,
-0xc004cab, 0x24040001, 0xc004cab, 0x24040001,
-0xc004cab, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004cab,
+0xc004d23, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d23, 0x2021,
+0xc004d23, 0x24040001, 0xc004d23, 0x24040001,
+0xc004d23, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d23,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004cab, 0x108042, 0x1600fffa, 0x32020018,
-0xc004cd1, 0x34108000, 0xc004cd1, 0x0,
-0xc004c8b, 0x0, 0x50400005, 0x108042,
+0xc004d23, 0x108042, 0x1600fffa, 0x32020018,
+0xc004d49, 0x34108000, 0xc004d49, 0x0,
+0xc004d03, 0x0, 0x50400005, 0x108042,
0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004cd1, 0x8021,
+0x1600fff7, 0x0, 0xc004d49, 0x8021,
0x97a20010, 0x27b10010, 0x3042fffe, 0xa7a20010,
-0xc004cab, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004cab, 0x2021,
-0xc004cab, 0x24040001, 0xc004cab, 0x2021,
-0xc004cab, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004cab,
+0xc004d23, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004d23, 0x2021,
+0xc004d23, 0x24040001, 0xc004d23, 0x2021,
+0xc004d23, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004d23,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004cab, 0x108042, 0x1600fffa, 0x32020018,
-0xc004cab, 0x24040001, 0xc004cab, 0x2021,
+0xc004d23, 0x108042, 0x1600fffa, 0x32020018,
+0xc004d23, 0x24040001, 0xc004d23, 0x2021,
0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004cab, 0x108042,
-0x1600fff8, 0x0, 0xc004cd1, 0x0,
-0x8f830054, 0x8004c76, 0x2402000e, 0x24020840,
-0xa7a20010, 0x27b10010, 0x8021, 0xc004cab,
+0x2021, 0x24040001, 0xc004d23, 0x108042,
+0x1600fff8, 0x0, 0xc004d49, 0x0,
+0x8f830054, 0x8004cee, 0x2402000e, 0x24020840,
+0xa7a20010, 0x27b10010, 0x8021, 0xc004d23,
0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004cab, 0x2021, 0xc004cab,
-0x24040001, 0xc004cab, 0x2021, 0xc004cab,
+0x0, 0xc004d23, 0x2021, 0xc004d23,
+0x24040001, 0xc004d23, 0x2021, 0xc004d23,
0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004cab, 0x108042,
+0x2021, 0x24040001, 0xc004d23, 0x108042,
0x1600fffa, 0x32020001, 0x24100010, 0x32020013,
-0x10400002, 0x2021, 0x24040001, 0xc004cab,
-0x108042, 0x1600fffa, 0x32020013, 0xc004cab,
-0x24040001, 0xc004cab, 0x2021, 0x34108000,
+0x10400002, 0x2021, 0x24040001, 0xc004d23,
+0x108042, 0x1600fffa, 0x32020013, 0xc004d23,
+0x24040001, 0xc004d23, 0x2021, 0x34108000,
0x96220000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004cab, 0x108042, 0x1600fff8,
-0x0, 0xc004cd1, 0x0, 0x8f830054,
-0x24020010, 0x3c010001, 0xac2254b0, 0x3c010001,
-0x8004c86, 0xac23554c, 0x8f830054, 0x3c020001,
-0x8c42554c, 0x2463ff9c, 0x431023, 0x2c420064,
+0x24040001, 0xc004d23, 0x108042, 0x1600fff8,
+0x0, 0xc004d49, 0x0, 0x8f830054,
+0x24020010, 0x3c010001, 0xac225d60, 0x3c010001,
+0x8004cfe, 0xac235e14, 0x8f830054, 0x3c020001,
+0x8c425e14, 0x2463ff9c, 0x431023, 0x2c420064,
0x14400004, 0x0, 0x24020011, 0x3c010001,
-0xac2254b0, 0x8fbf0020, 0x8fb1001c, 0x8fb00018,
+0xac225d60, 0x8fbf0020, 0x8fb1001c, 0x8fb00018,
0x3e00008, 0x27bd0028, 0x8f850044, 0x8f820044,
0x3c030001, 0x431025, 0x3c030008, 0xaf820044,
-0x8f840054, 0x8f820054, 0xa32824, 0x8004c97,
+0x8f840054, 0x8f820054, 0xa32824, 0x8004d0f,
0x24840001, 0x8f820054, 0x821023, 0x2c420002,
0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe,
0x3463ffff, 0x431024, 0xaf820044, 0x8f830054,
-0x8f820054, 0x8004ca5, 0x24630001, 0x8f820054,
+0x8f820054, 0x8004d1d, 0x24630001, 0x8f820054,
0x621023, 0x2c420002, 0x1440fffc, 0x0,
0x3e00008, 0xa01021, 0x8f830044, 0x3c02fff0,
0x3442ffff, 0x42480, 0x621824, 0x3c020002,
0x822025, 0x641825, 0xaf830044, 0x8f820044,
-0x3c030001, 0x431025, 0xaf820044, 0x8f830054,
-0x8f820054, 0x8004cbd, 0x24630001, 0x8f820054,
-0x621023, 0x2c420002, 0x1440fffc, 0x0,
-0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024,
-0xaf820044, 0x8f830054, 0x8f820054, 0x8004ccb,
+0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044,
+0x8f830054, 0x8f820054, 0x8004d36, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
+0x0, 0x8f820044, 0x3c030001, 0x431025,
+0xaf820044, 0x8f830054, 0x8f820054, 0x8004d43,
0x24630001, 0x8f820054, 0x621023, 0x2c420002,
0x1440fffc, 0x0, 0x3e00008, 0x0,
0x8f820044, 0x3c03fff0, 0x3463ffff, 0x431024,
0xaf820044, 0x8f820044, 0x3c030001, 0x431025,
-0xaf820044, 0x8f830054, 0x8f820054, 0x8004cdf,
+0xaf820044, 0x8f830054, 0x8f820054, 0x8004d57,
0x24630001, 0x8f820054, 0x621023, 0x2c420002,
0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe,
0x3463ffff, 0x431024, 0xaf820044, 0x8f830054,
-0x8f820054, 0x8004ced, 0x24630001, 0x8f820054,
+0x8f820054, 0x8004d65, 0x24630001, 0x8f820054,
0x621023, 0x2c420002, 0x1440fffc, 0x0,
-0x3e00008, 0x0, 0x0, 0x27bdffe8,
+0x3e00008, 0x0, 0x27bdffc8, 0xafb30024,
+0x809821, 0xafb5002c, 0xa0a821, 0xafb20020,
+0xc09021, 0x32a2ffff, 0xafbf0030, 0xafb40028,
+0xafb1001c, 0xafb00018, 0x14400034, 0xa7b20010,
+0x3271ffff, 0x27b20010, 0x8021, 0xc004d23,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d23, 0x2021, 0xc004d23,
+0x24040001, 0xc004d23, 0x2021, 0xc004d23,
+0x24040001, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004d23, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x2301024,
+0x10400002, 0x2021, 0x24040001, 0xc004d23,
+0x108042, 0x1600fffa, 0x2301024, 0xc004d23,
+0x24040001, 0xc004d23, 0x2021, 0x34108000,
+0x96420000, 0x501024, 0x10400002, 0x2021,
+0x24040001, 0xc004d23, 0x108042, 0x12000075,
+0x0, 0x8004da1, 0x0, 0x3274ffff,
+0x27b10010, 0xa7a00010, 0x8021, 0xc004d23,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d23, 0x2021, 0xc004d23,
+0x24040001, 0xc004d23, 0x24040001, 0xc004d23,
+0x2021, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004d23, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x2901024,
+0x10400002, 0x2021, 0x24040001, 0xc004d23,
+0x108042, 0x1600fffa, 0x2901024, 0xc004d49,
+0x34108000, 0xc004d49, 0x0, 0xc004d03,
+0x0, 0x50400005, 0x108042, 0x96220000,
+0x501025, 0xa6220000, 0x108042, 0x1600fff7,
+0x0, 0xc004d49, 0x0, 0x32a5ffff,
+0x24020001, 0x54a20004, 0x24020002, 0x97a20010,
+0x8004dec, 0x521025, 0x14a20006, 0x3271ffff,
+0x97a20010, 0x121827, 0x431024, 0xa7a20010,
+0x3271ffff, 0x27b20010, 0x8021, 0xc004d23,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004d23, 0x2021, 0xc004d23,
+0x24040001, 0xc004d23, 0x2021, 0xc004d23,
+0x24040001, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004d23, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x2301024,
+0x10400002, 0x2021, 0x24040001, 0xc004d23,
+0x108042, 0x1600fffa, 0x2301024, 0xc004d23,
+0x24040001, 0xc004d23, 0x2021, 0x34108000,
+0x96420000, 0x501024, 0x10400002, 0x2021,
+0x24040001, 0xc004d23, 0x108042, 0x1600fff8,
+0x0, 0xc004d49, 0x0, 0x8fbf0030,
+0x8fb5002c, 0x8fb40028, 0x8fb30024, 0x8fb20020,
+0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0038,
+0x0, 0x0, 0x0, 0x27bdffe8,
0xafbf0010, 0x3c030001, 0x771821, 0x8c6383ac,
0x24020008, 0x1462022c, 0x803021, 0x3c020001,
-0x8c425538, 0x14400033, 0x0, 0x8f850224,
+0x8c425df8, 0x14400033, 0x0, 0x8f850224,
0x38a30020, 0x2c630001, 0x38a20010, 0x2c420001,
0x621825, 0x1460000d, 0x38a30030, 0x2c630001,
0x38a20400, 0x2c420001, 0x621825, 0x14600007,
0x38a30402, 0x2c630001, 0x38a20404, 0x2c420001,
0x621825, 0x10600005, 0x0, 0xc00429b,
-0x0, 0x8004d2d, 0x2402000e, 0xc0043dd,
-0x0, 0x3c050001, 0x8ca55488, 0xc0050b3,
-0x2021, 0x3c030001, 0x8c635488, 0x24020004,
-0x14620005, 0x2403fffb, 0x3c020001, 0x8c425484,
-0x8004d29, 0x2403fff7, 0x3c020001, 0x8c425484,
-0x431024, 0x3c010001, 0xac225484, 0x2402000e,
-0x3c010001, 0xc00429b, 0xac227560, 0x8004f27,
+0x0, 0x8004e65, 0x2402000e, 0xc0043dd,
+0x0, 0x3c050001, 0x8ca55d28, 0xc005276,
+0x2021, 0x3c030001, 0x8c635d28, 0x24020004,
+0x14620005, 0x2403fffb, 0x3c020001, 0x8c425d24,
+0x8004e61, 0x2403fff7, 0x3c020001, 0x8c425d24,
+0x431024, 0x3c010001, 0xac225d24, 0x2402000e,
+0x3c010001, 0xc00429b, 0xac227e30, 0x800505f,
0x0, 0x8f820220, 0x3c030400, 0x431024,
0x10400027, 0x2403ffbf, 0x8f850224, 0x3c020001,
-0x8c42756c, 0xa32024, 0x431024, 0x1482000c,
-0x0, 0x3c020001, 0x8c427570, 0x24420001,
-0x3c010001, 0xac227570, 0x2c420002, 0x14400008,
-0x24020001, 0x3c010001, 0x8004d4d, 0xac227590,
-0x3c010001, 0xac207570, 0x3c010001, 0xac207590,
-0x3c020001, 0x8c427590, 0x10400006, 0x30a20040,
-0x10400004, 0x24020001, 0x3c010001, 0x8004d58,
-0xac227594, 0x3c010001, 0xac207594, 0x3c010001,
-0xac25756c, 0x3c010001, 0x8004d68, 0xac2075a0,
-0x24020001, 0x3c010001, 0xac2275a0, 0x3c010001,
-0xac207590, 0x3c010001, 0xac207570, 0x3c010001,
-0xac207594, 0x3c010001, 0xac20756c, 0x3c030001,
-0x8c637560, 0x3c020001, 0x8c427564, 0x10620003,
-0x3c020200, 0x3c010001, 0xac237564, 0xc21024,
+0x8c427e3c, 0xa32024, 0x431024, 0x1482000c,
+0x0, 0x3c020001, 0x8c427e40, 0x24420001,
+0x3c010001, 0xac227e40, 0x2c420002, 0x14400008,
+0x24020001, 0x3c010001, 0x8004e85, 0xac227e60,
+0x3c010001, 0xac207e40, 0x3c010001, 0xac207e60,
+0x3c020001, 0x8c427e60, 0x10400006, 0x30a20040,
+0x10400004, 0x24020001, 0x3c010001, 0x8004e90,
+0xac227e64, 0x3c010001, 0xac207e64, 0x3c010001,
+0xac257e3c, 0x3c010001, 0x8004ea0, 0xac207e70,
+0x24020001, 0x3c010001, 0xac227e70, 0x3c010001,
+0xac207e60, 0x3c010001, 0xac207e40, 0x3c010001,
+0xac207e64, 0x3c010001, 0xac207e3c, 0x3c030001,
+0x8c637e30, 0x3c020001, 0x8c427e34, 0x10620003,
+0x3c020200, 0x3c010001, 0xac237e34, 0xc21024,
0x10400007, 0x2463ffff, 0x8f820220, 0x24030001,
-0x3c010001, 0xac23548c, 0x8004f25, 0x3c03f700,
+0x3c010001, 0xac235d2c, 0x800505d, 0x3c03f700,
0x2c62000e, 0x104001a8, 0x31080, 0x3c010001,
-0x220821, 0x8c225360, 0x400008, 0x0,
-0x3c010001, 0xac207590, 0x3c010001, 0xac207570,
-0x3c010001, 0xac20756c, 0x3c010001, 0xac207594,
-0x3c010001, 0xac207588, 0x3c010001, 0xac207580,
-0xc0047cd, 0xaf800224, 0x24020002, 0x3c010001,
-0xac227560, 0x3c020001, 0x8c4275a0, 0x14400056,
+0x220821, 0x8c225bd0, 0x400008, 0x0,
+0x3c010001, 0xac207e60, 0x3c010001, 0xac207e40,
+0x3c010001, 0xac207e3c, 0x3c010001, 0xac207e64,
+0x3c010001, 0xac207e58, 0x3c010001, 0xac207e50,
+0xc004844, 0xaf800224, 0x24020002, 0x3c010001,
+0xac227e30, 0x3c020001, 0x8c427e70, 0x14400056,
0x3c03fdff, 0x8ee20000, 0x3463ffff, 0x431024,
0xc00429b, 0xaee20000, 0xaf800204, 0x8f820200,
0x2403fffd, 0x431024, 0xaf820200, 0x3c010001,
-0xac2075b0, 0x8f830054, 0x3c020001, 0x8c427588,
-0x24040001, 0x3c010001, 0xac24759c, 0x24420001,
-0x3c010001, 0xac227588, 0x2c420004, 0x3c010001,
-0xac237584, 0x14400006, 0x24020003, 0x3c010001,
-0xac24548c, 0x3c010001, 0x8004f23, 0xac207588,
-0x3c010001, 0x8004f23, 0xac227560, 0x8f830054,
-0x3c020001, 0x8c427584, 0x2463d8f0, 0x431023,
+0xac207e80, 0x8f830054, 0x3c020001, 0x8c427e58,
+0x24040001, 0x3c010001, 0xac247e6c, 0x24420001,
+0x3c010001, 0xac227e58, 0x2c420004, 0x3c010001,
+0xac237e54, 0x14400006, 0x24020003, 0x3c010001,
+0xac245d2c, 0x3c010001, 0x800505b, 0xac207e58,
+0x3c010001, 0x800505b, 0xac227e30, 0x8f830054,
+0x3c020001, 0x8c427e54, 0x2463d8f0, 0x431023,
0x2c422710, 0x14400003, 0x24020004, 0x3c010001,
-0xac227560, 0x3c020001, 0x8c4275a0, 0x14400026,
+0xac227e30, 0x3c020001, 0x8c427e70, 0x14400026,
0x3c03fdff, 0x8ee20000, 0x3463ffff, 0x431024,
-0x8004f23, 0xaee20000, 0x3c040001, 0x8c84553c,
-0x3c010001, 0xc004f2a, 0xac207578, 0x3c020001,
-0x8c4275ac, 0xaf820204, 0x3c020001, 0x8c4275a0,
+0x800505b, 0xaee20000, 0x3c040001, 0x8c845dfc,
+0x3c010001, 0xc005062, 0xac207e48, 0x3c020001,
+0x8c427e7c, 0xaf820204, 0x3c020001, 0x8c427e70,
0x14400015, 0x3c03fdff, 0x8ee20000, 0x3463ffff,
0x431024, 0xaee20000, 0x8f820204, 0x30420030,
-0x1440013c, 0x24020002, 0x3c030001, 0x8c6375ac,
-0x24020005, 0x3c010001, 0xac227560, 0x3c010001,
-0x8004f23, 0xac2375b0, 0x3c020001, 0x8c4275a0,
-0x10400010, 0x3c03fdff, 0x3c020001, 0x8c42550c,
-0x24420001, 0x3c010001, 0xac22550c, 0x2c420002,
-0x14400131, 0x24020001, 0x3c010001, 0xac225514,
-0x3c010001, 0xac20550c, 0x3c010001, 0x8004f23,
-0xac22548c, 0x8ee20000, 0x3463ffff, 0x431024,
-0xaee20000, 0x3c020001, 0x8c427590, 0x10400122,
-0x0, 0x3c020001, 0x8c42756c, 0x1040011e,
-0x0, 0x3c010001, 0xac227598, 0x24020003,
-0x3c010001, 0xac227570, 0x8004ec4, 0x24020006,
-0x3c010001, 0xac207578, 0x8f820204, 0x34420040,
-0xaf820204, 0x3c020001, 0x8c4275b0, 0x24030007,
-0x3c010001, 0xac237560, 0x34420040, 0x3c010001,
-0xac2275b0, 0x3c020001, 0x8c427590, 0x10400005,
-0x0, 0x3c020001, 0x8c42756c, 0x104000f9,
-0x24020002, 0x3c050001, 0x24a57570, 0x8ca20000,
+0x1440013c, 0x24020002, 0x3c030001, 0x8c637e7c,
+0x24020005, 0x3c010001, 0xac227e30, 0x3c010001,
+0x800505b, 0xac237e80, 0x3c020001, 0x8c427e70,
+0x10400010, 0x3c03fdff, 0x3c020001, 0x8c425dcc,
+0x24420001, 0x3c010001, 0xac225dcc, 0x2c420002,
+0x14400131, 0x24020001, 0x3c010001, 0xac225dd4,
+0x3c010001, 0xac205dcc, 0x3c010001, 0x800505b,
+0xac225d2c, 0x8ee20000, 0x3463ffff, 0x431024,
+0xaee20000, 0x3c020001, 0x8c427e60, 0x10400122,
+0x0, 0x3c020001, 0x8c427e3c, 0x1040011e,
+0x0, 0x3c010001, 0xac227e68, 0x24020003,
+0x3c010001, 0xac227e40, 0x8004ffc, 0x24020006,
+0x3c010001, 0xac207e48, 0x8f820204, 0x34420040,
+0xaf820204, 0x3c020001, 0x8c427e80, 0x24030007,
+0x3c010001, 0xac237e30, 0x34420040, 0x3c010001,
+0xac227e80, 0x3c020001, 0x8c427e60, 0x10400005,
+0x0, 0x3c020001, 0x8c427e3c, 0x104000f9,
+0x24020002, 0x3c050001, 0x24a57e40, 0x8ca20000,
0x2c424e21, 0x104000f3, 0x24020002, 0x3c020001,
-0x8c427594, 0x104000f8, 0x2404ffbf, 0x3c020001,
-0x8c42756c, 0x3c030001, 0x8c637598, 0x441024,
+0x8c427e64, 0x104000f8, 0x2404ffbf, 0x3c020001,
+0x8c427e3c, 0x3c030001, 0x8c637e68, 0x441024,
0x641824, 0x10430004, 0x24020001, 0x3c010001,
-0x8004f23, 0xac227560, 0x24020003, 0xaca20000,
-0x24020008, 0x3c010001, 0xac227560, 0x3c020001,
-0x8c42759c, 0x1040000c, 0x24020001, 0x3c040001,
-0xc004f37, 0x8c84756c, 0x3c020001, 0x8c4275b8,
-0x14400005, 0x24020001, 0x3c020001, 0x8c4275b4,
-0x10400006, 0x24020001, 0x3c010001, 0xac22548c,
-0x3c010001, 0x8004f23, 0xac207588, 0x3c020001,
-0x8c427580, 0x3c030001, 0x8c63756c, 0x2c420001,
-0x210c0, 0x30630008, 0x3c010001, 0xac227580,
-0x3c010001, 0xac23757c, 0x8f830054, 0x24020009,
-0x3c010001, 0xac227560, 0x3c010001, 0x8004f23,
-0xac237584, 0x8f830054, 0x3c020001, 0x8c427584,
+0x800505b, 0xac227e30, 0x24020003, 0xaca20000,
+0x24020008, 0x3c010001, 0xac227e30, 0x3c020001,
+0x8c427e6c, 0x1040000c, 0x24020001, 0x3c040001,
+0xc00506f, 0x8c847e3c, 0x3c020001, 0x8c427e88,
+0x14400005, 0x24020001, 0x3c020001, 0x8c427e84,
+0x10400006, 0x24020001, 0x3c010001, 0xac225d2c,
+0x3c010001, 0x800505b, 0xac207e58, 0x3c020001,
+0x8c427e50, 0x3c030001, 0x8c637e3c, 0x2c420001,
+0x210c0, 0x30630008, 0x3c010001, 0xac227e50,
+0x3c010001, 0xac237e4c, 0x8f830054, 0x24020009,
+0x3c010001, 0xac227e30, 0x3c010001, 0x800505b,
+0xac237e54, 0x8f830054, 0x3c020001, 0x8c427e54,
0x2463d8f0, 0x431023, 0x2c422710, 0x144000a8,
-0x0, 0x3c020001, 0x8c427590, 0x10400005,
-0x0, 0x3c020001, 0x8c42756c, 0x104000a9,
-0x24020002, 0x3c030001, 0x24637570, 0x8c620000,
+0x0, 0x3c020001, 0x8c427e60, 0x10400005,
+0x0, 0x3c020001, 0x8c427e3c, 0x104000a9,
+0x24020002, 0x3c030001, 0x24637e40, 0x8c620000,
0x2c424e21, 0x104000a3, 0x24020002, 0x3c020001,
-0x8c42759c, 0x1040000e, 0x0, 0x3c020001,
-0x8c42756c, 0x3c010001, 0xac20759c, 0x30420080,
+0x8c427e6c, 0x1040000e, 0x0, 0x3c020001,
+0x8c427e3c, 0x3c010001, 0xac207e6c, 0x30420080,
0x1040002f, 0x2402000c, 0x8f820204, 0x30420080,
-0x1440000c, 0x24020003, 0x8004eb1, 0x2402000c,
-0x3c020001, 0x8c42756c, 0x30420080, 0x14400005,
+0x1440000c, 0x24020003, 0x8004fe9, 0x2402000c,
+0x3c020001, 0x8c427e3c, 0x30420080, 0x14400005,
0x24020003, 0x8f820204, 0x30420080, 0x1040001f,
0x24020003, 0xac620000, 0x2402000a, 0x3c010001,
-0xac227560, 0x3c040001, 0x248475a8, 0x8c820000,
-0x3c030001, 0x8c637580, 0x431025, 0xaf820204,
-0x8c830000, 0x3c040001, 0x8c847580, 0x2402000b,
-0x3c010001, 0xac227560, 0x641825, 0x3c010001,
-0xac2375b0, 0x3c050001, 0x24a57570, 0x8ca20000,
+0xac227e30, 0x3c040001, 0x24847e78, 0x8c820000,
+0x3c030001, 0x8c637e50, 0x431025, 0xaf820204,
+0x8c830000, 0x3c040001, 0x8c847e50, 0x2402000b,
+0x3c010001, 0xac227e30, 0x641825, 0x3c010001,
+0xac237e80, 0x3c050001, 0x24a57e40, 0x8ca20000,
0x2c424e21, 0x1040006f, 0x24020002, 0x3c020001,
-0x8c4275a0, 0x10400005, 0x0, 0x2402000c,
-0x3c010001, 0x8004f23, 0xac227560, 0x3c020001,
-0x8c427590, 0x1040006c, 0x0, 0x3c040001,
-0x8c84756c, 0x1080005e, 0x30820008, 0x3c030001,
-0x8c63757c, 0x10620064, 0x24020003, 0x3c010001,
-0xac247598, 0xaca20000, 0x24020006, 0x3c010001,
-0x8004f23, 0xac227560, 0x8f820200, 0x34420002,
+0x8c427e70, 0x10400005, 0x0, 0x2402000c,
+0x3c010001, 0x800505b, 0xac227e30, 0x3c020001,
+0x8c427e60, 0x1040006c, 0x0, 0x3c040001,
+0x8c847e3c, 0x1080005e, 0x30820008, 0x3c030001,
+0x8c637e4c, 0x10620064, 0x24020003, 0x3c010001,
+0xac247e68, 0xaca20000, 0x24020006, 0x3c010001,
+0x800505b, 0xac227e30, 0x8f820200, 0x34420002,
0xaf820200, 0x8f830054, 0x2402000d, 0x3c010001,
-0xac227560, 0x3c010001, 0xac237584, 0x8f830054,
-0x3c020001, 0x8c427584, 0x2463d8f0, 0x431023,
+0xac227e30, 0x3c010001, 0xac237e54, 0x8f830054,
+0x3c020001, 0x8c427e54, 0x2463d8f0, 0x431023,
0x2c422710, 0x1440003a, 0x0, 0x3c020001,
-0x8c4275a0, 0x10400029, 0x2402000e, 0x3c030001,
-0x8c6375b4, 0x3c010001, 0x14600015, 0xac227560,
-0xc0043dd, 0x0, 0x3c050001, 0x8ca55488,
-0xc0050b3, 0x2021, 0x3c030001, 0x8c635488,
+0x8c427e70, 0x10400029, 0x2402000e, 0x3c030001,
+0x8c637e84, 0x3c010001, 0x14600015, 0xac227e30,
+0xc0043dd, 0x0, 0x3c050001, 0x8ca55d28,
+0xc005276, 0x2021, 0x3c030001, 0x8c635d28,
0x24020004, 0x14620005, 0x2403fffb, 0x3c020001,
-0x8c425484, 0x8004ef2, 0x2403fff7, 0x3c020001,
-0x8c425484, 0x431024, 0x3c010001, 0xac225484,
+0x8c425d24, 0x800502a, 0x2403fff7, 0x3c020001,
+0x8c425d24, 0x431024, 0x3c010001, 0xac225d24,
0x8ee20000, 0x3c030200, 0x431025, 0xaee20000,
-0x8f820224, 0x3c010001, 0xac2275bc, 0x8f820220,
+0x8f820224, 0x3c010001, 0xac227e8c, 0x8f820220,
0x2403fffb, 0x431024, 0xaf820220, 0x8f820220,
-0x34420002, 0x8004f23, 0xaf820220, 0x3c020001,
-0x8c427590, 0x10400005, 0x0, 0x3c020001,
-0x8c42756c, 0x1040000f, 0x24020002, 0x3c020001,
-0x8c427570, 0x2c424e21, 0x1040000a, 0x24020002,
-0x3c020001, 0x8c427590, 0x1040000f, 0x0,
-0x3c020001, 0x8c42756c, 0x1440000b, 0x0,
-0x24020002, 0x3c010001, 0x8004f23, 0xac227560,
-0x3c020001, 0x8c427590, 0x10400003, 0x0,
+0x34420002, 0x800505b, 0xaf820220, 0x3c020001,
+0x8c427e60, 0x10400005, 0x0, 0x3c020001,
+0x8c427e3c, 0x1040000f, 0x24020002, 0x3c020001,
+0x8c427e40, 0x2c424e21, 0x1040000a, 0x24020002,
+0x3c020001, 0x8c427e60, 0x1040000f, 0x0,
+0x3c020001, 0x8c427e3c, 0x1440000b, 0x0,
+0x24020002, 0x3c010001, 0x800505b, 0xac227e30,
+0x3c020001, 0x8c427e60, 0x10400003, 0x0,
0xc00429b, 0x0, 0x8f820220, 0x3c03f700,
0x431025, 0xaf820220, 0x8fbf0010, 0x3e00008,
-0x27bd0018, 0x3c030001, 0x246375b8, 0x8c620000,
-0x10400005, 0x34422000, 0x3c010001, 0xac2275ac,
-0x8004f35, 0xac600000, 0x3c010001, 0xac2475ac,
+0x27bd0018, 0x3c030001, 0x24637e88, 0x8c620000,
+0x10400005, 0x34422000, 0x3c010001, 0xac227e7c,
+0x800506d, 0xac600000, 0x3c010001, 0xac247e7c,
0x3e00008, 0x0, 0x27bdffe0, 0x30820030,
-0xafbf0018, 0x3c010001, 0xac2275b4, 0x14400067,
+0xafbf0018, 0x3c010001, 0xac227e84, 0x14400067,
0x3c02ffff, 0x34421f0e, 0x821024, 0x14400061,
0x24020030, 0x30822000, 0x1040005d, 0x30838000,
0x31a02, 0x30820001, 0x21200, 0x3c040001,
-0x8c84553c, 0x621825, 0x331c2, 0x3c030001,
-0x24635518, 0x30828000, 0x21202, 0x30840001,
+0x8c845dfc, 0x621825, 0x331c2, 0x3c030001,
+0x24635dd8, 0x30828000, 0x21202, 0x30840001,
0x42200, 0x441025, 0x239c2, 0x61080,
0x431021, 0x471021, 0x90430000, 0x24020001,
0x10620025, 0x0, 0x10600007, 0x24020002,
0x10620013, 0x24020003, 0x1062002c, 0x3c05000f,
-0x8004f99, 0x0, 0x8f820200, 0x2403feff,
+0x80050d1, 0x0, 0x8f820200, 0x2403feff,
0x431024, 0xaf820200, 0x8f820220, 0x3c03fffe,
0x3463ffff, 0x431024, 0xaf820220, 0x3c010001,
-0xac2075d4, 0x3c010001, 0x8004fa4, 0xac2075dc,
+0xac207ea4, 0x3c010001, 0x80050dc, 0xac207eac,
0x8f820200, 0x34420100, 0xaf820200, 0x8f820220,
0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220,
-0x24020100, 0x3c010001, 0xac2275d4, 0x3c010001,
-0x8004fa4, 0xac2075dc, 0x8f820200, 0x2403feff,
+0x24020100, 0x3c010001, 0xac227ea4, 0x3c010001,
+0x80050dc, 0xac207eac, 0x8f820200, 0x2403feff,
0x431024, 0xaf820200, 0x8f820220, 0x3c030001,
-0x431025, 0xaf820220, 0x3c010001, 0xac2075d4,
-0x3c010001, 0x8004fa4, 0xac2375dc, 0x8f820200,
+0x431025, 0xaf820220, 0x3c010001, 0xac207ea4,
+0x3c010001, 0x80050dc, 0xac237eac, 0x8f820200,
0x34420100, 0xaf820200, 0x8f820220, 0x3c030001,
0x431025, 0xaf820220, 0x24020100, 0x3c010001,
-0xac2275d4, 0x3c010001, 0x8004fa4, 0xac2375dc,
-0x34a5ffff, 0x3c040001, 0x24845398, 0xafa30010,
-0xc002403, 0xafa00014, 0x8004fa4, 0x0,
-0x24020030, 0x3c010001, 0xac2275b8, 0x8fbf0018,
+0xac227ea4, 0x3c010001, 0x80050dc, 0xac237eac,
+0x34a5ffff, 0x3c040001, 0x24845c08, 0xafa30010,
+0xc002403, 0xafa00014, 0x80050dc, 0x0,
+0x24020030, 0x3c010001, 0xac227e88, 0x8fbf0018,
0x3e00008, 0x27bd0020, 0x0, 0x27bdffc8,
-0xafb10024, 0x808821, 0xafb3002c, 0xa09821,
-0xafb00020, 0xc08021, 0x3c040001, 0x248453b0,
-0x3c050009, 0x3c020001, 0x8c425488, 0x34a59001,
-0x2203021, 0x2603821, 0xafbf0030, 0xafb20028,
+0xafb20028, 0x809021, 0xafb3002c, 0xa09821,
+0xafb00020, 0xc08021, 0x3c040001, 0x24845c20,
+0x3c050009, 0x3c020001, 0x8c425d28, 0x34a59001,
+0x2403021, 0x2603821, 0xafbf0030, 0xafb10024,
0xa7a0001a, 0xafb00014, 0xc002403, 0xafa20010,
-0x24020002, 0x126200ed, 0x2e620003, 0x10400005,
-0x24020001, 0x1262000a, 0x3c02fffb, 0x80050ac,
-0x0, 0x24020004, 0x1262006d, 0x24020008,
-0x1262006c, 0x3c02ffec, 0x80050ac, 0x0,
-0x3442ffff, 0x2028024, 0x119140, 0x3c010001,
-0x320821, 0xac3075cc, 0x3c024000, 0x2021024,
-0x10400046, 0x1023c2, 0x30840030, 0x101382,
-0x3042000c, 0x3c030001, 0x246354b4, 0x431021,
-0x823821, 0x3c020020, 0x2021024, 0x10400006,
-0x24020100, 0x3c010001, 0x320821, 0xac2275d0,
-0x8004feb, 0x3c020080, 0x3c010001, 0x320821,
-0xac2075d0, 0x3c020080, 0x2021024, 0x10400006,
-0x111940, 0x3c020001, 0x3c010001, 0x230821,
-0x8004ff7, 0xac2275d8, 0x111140, 0x3c010001,
-0x220821, 0xac2075d8, 0x94e30000, 0x32024000,
-0x10400003, 0xa7a30018, 0x34624000, 0xa7a20018,
-0x24040001, 0x94e20002, 0x24050004, 0x24e60002,
-0x34420001, 0xc0048ee, 0xa4e20002, 0x24040001,
-0x2821, 0xc0048ee, 0x27a60018, 0x3c020001,
-0x8c425488, 0x24110001, 0x3c010001, 0xac315494,
-0x14530004, 0x32028000, 0xc00429b, 0x0,
-0x32028000, 0x10400099, 0x0, 0xc00429b,
-0x0, 0x24020002, 0x3c010001, 0xac31548c,
-0x3c010001, 0x80050ac, 0xac225488, 0x24040001,
-0x24050004, 0x27b0001a, 0xc0048ee, 0x2003021,
-0x24040001, 0x2821, 0xc0048ee, 0x2003021,
-0x3c020001, 0x521021, 0x8c4275c4, 0x3c040001,
-0x8c845488, 0x3c03bfff, 0x3463ffff, 0x3c010001,
-0xac335494, 0x431024, 0x3c010001, 0x320821,
-0x10930078, 0xac2275c4, 0x80050ac, 0x0,
-0x3c02ffec, 0x3442ffff, 0x2028024, 0x3c020008,
-0x2028025, 0x111140, 0x3c010001, 0x220821,
-0xac3075c8, 0x3c022000, 0x2021024, 0x10400009,
-0x0, 0x3c020001, 0x8c425514, 0x14400005,
-0x24020001, 0x3c010001, 0xac225538, 0x800504d,
-0x3c024000, 0x3c010001, 0xac205538, 0x3c024000,
-0x2021024, 0x1440001c, 0x0, 0x3c020001,
-0x8c425538, 0x10400007, 0x24022020, 0x3c010001,
-0xac22553c, 0x24020001, 0x3c010001, 0x370821,
-0xac2283ac, 0x3c04bfff, 0x111940, 0x3c020001,
-0x431021, 0x8c4275c0, 0x3c050001, 0x8ca55488,
-0x3484ffff, 0x441024, 0x3c010001, 0x230821,
-0xac2275c0, 0x24020001, 0x10a20044, 0x0,
-0x80050aa, 0x0, 0x3c020001, 0x8c425538,
-0x1040001c, 0x24022000, 0x3c010001, 0xac22553c,
-0x3c0300a0, 0x2031024, 0x14430005, 0x111140,
-0x3402a000, 0x3c010001, 0x80050a5, 0xac22553c,
-0x3c030001, 0x621821, 0x8c6375c8, 0x3c020020,
-0x621024, 0x10400004, 0x24022001, 0x3c010001,
-0x80050a5, 0xac22553c, 0x3c020080, 0x621024,
-0x1040001f, 0x3402a001, 0x3c010001, 0x80050a5,
-0xac22553c, 0x3c020020, 0x2021024, 0x10400007,
-0x111940, 0x24020100, 0x3c010001, 0x230821,
-0xac2275d4, 0x8005099, 0x3c020080, 0x111140,
-0x3c010001, 0x220821, 0xac2075d4, 0x3c020080,
-0x2021024, 0x10400006, 0x111940, 0x3c020001,
-0x3c010001, 0x230821, 0x80050a5, 0xac2275dc,
-0x111140, 0x3c010001, 0x220821, 0xac2075dc,
-0x3c030001, 0x8c635488, 0x24020001, 0x10620003,
-0x0, 0xc00429b, 0x0, 0x8fbf0030,
-0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
-0x3e00008, 0x27bd0038, 0x27bdffd0, 0xafb40028,
-0x80a021, 0xafb20020, 0x9021, 0xafb30024,
-0x9821, 0xafb1001c, 0x8821, 0x24020002,
-0xafbf002c, 0xafb00018, 0xa7a00012, 0x10a20068,
-0xa7a00010, 0x2ca20003, 0x10400005, 0x24020001,
-0x10a2000a, 0x148140, 0x8005176, 0x2201021,
-0x24020004, 0x10a2005e, 0x24020008, 0x10a2005d,
-0x142940, 0x8005176, 0x2201021, 0x3c030001,
-0x701821, 0x8c6375cc, 0x3c024000, 0x621024,
-0x14400009, 0x24040001, 0x3c027fff, 0x3442ffff,
-0x628824, 0x3c010001, 0x300821, 0xac3175c4,
-0x8005176, 0x2201021, 0x24050001, 0xc0048ac,
-0x27a60010, 0x24040001, 0x24050001, 0xc0048ac,
-0x27a60010, 0x97a20010, 0x30420004, 0x10400034,
-0x3c114000, 0x3c030001, 0x8c635550, 0x24020003,
-0x10620008, 0x2c620004, 0x14400029, 0x3c028000,
-0x24020004, 0x10620014, 0x24040001, 0x8005119,
-0x3c028000, 0x24040001, 0x24050011, 0x27b00012,
-0xc0048ac, 0x2003021, 0x24040001, 0x24050011,
-0xc0048ac, 0x2003021, 0x97a30012, 0x30624000,
-0x10400002, 0x3c130010, 0x3c130008, 0x3c120001,
-0x8005116, 0x30628000, 0x24050014, 0x27b00012,
-0xc0048ac, 0x2003021, 0x24040001, 0x24050014,
-0xc0048ac, 0x2003021, 0x97a30012, 0x30621000,
-0x10400002, 0x3c130010, 0x3c130008, 0x3c120001,
-0x30620800, 0x54400001, 0x3c120002, 0x3c028000,
-0x2221025, 0x2531825, 0x8005123, 0x438825,
-0x3c110001, 0x2308821, 0x8e3175cc, 0x3c027fff,
-0x3442ffff, 0x2228824, 0x141140, 0x3c010001,
-0x220821, 0xac3175c4, 0x8005176, 0x2201021,
-0x142940, 0x3c030001, 0x651821, 0x8c6375c8,
-0x3c024000, 0x621024, 0x14400008, 0x3c027fff,
-0x3442ffff, 0x628824, 0x3c010001, 0x250821,
-0xac3175c0, 0x8005176, 0x2201021, 0x3c020001,
-0x8c425498, 0x10400033, 0x3c11c00c, 0x3c020001,
-0x8c425514, 0x3c04c00c, 0x34842000, 0x3c030001,
-0x8c635538, 0x2102b, 0x21023, 0x441024,
-0x10600003, 0x518825, 0x3c022000, 0x2228825,
-0x3c020001, 0x451021, 0x8c4275d4, 0x10400003,
-0x3c020020, 0x8005153, 0x2228825, 0x3c02ffdf,
+0x24020002, 0x1262007f, 0x2e620003, 0x10400005,
+0x24020001, 0x1262000a, 0x0, 0x800526f,
+0x0, 0x24020004, 0x126200f6, 0x24020008,
+0x126200f5, 0x3c02ffec, 0x800526f, 0x0,
+0x3c020001, 0x8c425d24, 0x30420002, 0x14400004,
+0x128940, 0x3c02fffb, 0x3442ffff, 0x2028024,
+0x3c010001, 0x310821, 0xac307e9c, 0x3c024000,
+0x2021024, 0x1040004a, 0x1023c2, 0x30840030,
+0x101382, 0x3042001c, 0x3c030001, 0x24635d68,
+0x431021, 0x823821, 0x3c020020, 0x2021024,
+0x10400006, 0x24020100, 0x3c010001, 0x310821,
+0xac227ea0, 0x8005128, 0x3c020080, 0x3c010001,
+0x310821, 0xac207ea0, 0x3c020080, 0x2021024,
+0x10400006, 0x121940, 0x3c020001, 0x3c010001,
+0x230821, 0x8005134, 0xac227ea8, 0x121140,
+0x3c010001, 0x220821, 0xac207ea8, 0x94e30000,
+0x32024000, 0x10400003, 0xa7a30018, 0x34624000,
+0xa7a20018, 0x24040001, 0x94e20002, 0x24050004,
+0x24e60002, 0x34420001, 0xc004966, 0xa4e20002,
+0x24040001, 0x2821, 0xc004966, 0x27a60018,
+0x3c020001, 0x8c425d28, 0x24110001, 0x3c010001,
+0xac315d34, 0x14530004, 0x32028000, 0xc00429b,
+0x0, 0x32028000, 0x1040011f, 0x0,
+0xc00429b, 0x0, 0x3c030001, 0x8c635e18,
+0x24020005, 0x10620118, 0x24020002, 0x3c010001,
+0xac315d2c, 0x3c010001, 0x800526f, 0xac225d28,
+0x24040001, 0x24050004, 0x27b0001a, 0xc004966,
+0x2003021, 0x24040001, 0x2821, 0xc004966,
+0x2003021, 0x3c020001, 0x511021, 0x8c427e94,
+0x3c040001, 0x8c845d28, 0x3c03bfff, 0x3463ffff,
+0x3c010001, 0xac335d34, 0x431024, 0x3c010001,
+0x310821, 0x109300fa, 0xac227e94, 0x800526f,
+0x0, 0x3c022000, 0x2021024, 0x10400005,
+0x24020001, 0x3c010001, 0xac225df8, 0x8005181,
+0x128940, 0x3c010001, 0xac205df8, 0x128940,
+0x3c010001, 0x310821, 0xac307e98, 0x3c024000,
+0x2021024, 0x14400016, 0x0, 0x3c020001,
+0x8c425df8, 0x10400008, 0x24040004, 0x24050001,
+0xc004d6b, 0x24062000, 0x24020001, 0x3c010001,
+0x370821, 0xac2283ac, 0x3c020001, 0x511021,
+0x8c427e90, 0x3c03bfff, 0x3463ffff, 0x431024,
+0x3c010001, 0x310821, 0x800526d, 0xac227e90,
+0x3c020001, 0x8c425df8, 0x10400028, 0x3c0300a0,
+0x2031024, 0x5443000d, 0x3c020020, 0x3c020001,
+0x8c425dfc, 0x24030100, 0x3c010001, 0x310821,
+0xac237ea4, 0x3c030001, 0x3c010001, 0x310821,
+0xac237eac, 0x80051c4, 0x34420400, 0x2021024,
+0x10400008, 0x24030100, 0x3c020001, 0x8c425dfc,
+0x3c010001, 0x310821, 0xac237ea4, 0x80051c4,
+0x34420800, 0x3c020080, 0x2021024, 0x1040002e,
+0x3c030001, 0x3c020001, 0x8c425dfc, 0x3c010001,
+0x310821, 0xac237eac, 0x34420c00, 0x3c010001,
+0xac225dfc, 0x80051ec, 0x24040001, 0x3c020020,
+0x2021024, 0x10400006, 0x24020100, 0x3c010001,
+0x310821, 0xac227ea4, 0x80051d5, 0x3c020080,
+0x3c010001, 0x310821, 0xac207ea4, 0x3c020080,
+0x2021024, 0x10400007, 0x121940, 0x3c020001,
+0x3c010001, 0x230821, 0xac227eac, 0x80051e3,
+0x24040001, 0x121140, 0x3c010001, 0x220821,
+0xac207eac, 0x24040001, 0x2821, 0x27b0001e,
+0xc004924, 0x2003021, 0x24040001, 0x2821,
+0xc004924, 0x2003021, 0x24040001, 0x24050001,
+0x27b0001c, 0xc004924, 0x2003021, 0x24040001,
+0x24050001, 0xc004924, 0x2003021, 0x800526d,
+0x0, 0x3c02ffec, 0x3442ffff, 0x2028024,
+0x3c020008, 0x2028025, 0x121140, 0x3c010001,
+0x220821, 0xac307e98, 0x3c022000, 0x2021024,
+0x10400009, 0x0, 0x3c020001, 0x8c425dd4,
+0x14400005, 0x24020001, 0x3c010001, 0xac225df8,
+0x800520e, 0x3c024000, 0x3c010001, 0xac205df8,
+0x3c024000, 0x2021024, 0x1440001e, 0x0,
+0x3c020001, 0x8c425df8, 0x3c010001, 0xac205d40,
+0x10400007, 0x24022020, 0x3c010001, 0xac225dfc,
+0x24020001, 0x3c010001, 0x370821, 0xac2283ac,
+0x3c04bfff, 0x121940, 0x3c020001, 0x431021,
+0x8c427e90, 0x3c050001, 0x8ca55d28, 0x3484ffff,
+0x441024, 0x3c010001, 0x230821, 0xac227e90,
+0x24020001, 0x10a20044, 0x0, 0x800526d,
+0x0, 0x3c020001, 0x8c425df8, 0x1040001c,
+0x24022000, 0x3c010001, 0xac225dfc, 0x3c0300a0,
+0x2031024, 0x14430005, 0x121140, 0x3402a000,
+0x3c010001, 0x8005268, 0xac225dfc, 0x3c030001,
+0x621821, 0x8c637e98, 0x3c020020, 0x621024,
+0x10400004, 0x24022001, 0x3c010001, 0x8005268,
+0xac225dfc, 0x3c020080, 0x621024, 0x1040001f,
+0x3402a001, 0x3c010001, 0x8005268, 0xac225dfc,
+0x3c020020, 0x2021024, 0x10400007, 0x121940,
+0x24020100, 0x3c010001, 0x230821, 0xac227ea4,
+0x800525c, 0x3c020080, 0x121140, 0x3c010001,
+0x220821, 0xac207ea4, 0x3c020080, 0x2021024,
+0x10400006, 0x121940, 0x3c020001, 0x3c010001,
+0x230821, 0x8005268, 0xac227eac, 0x121140,
+0x3c010001, 0x220821, 0xac207eac, 0x3c030001,
+0x8c635d28, 0x24020001, 0x10620003, 0x0,
+0xc00429b, 0x0, 0x8fbf0030, 0x8fb3002c,
+0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008,
+0x27bd0038, 0x27bdffc0, 0xafb40038, 0x80a021,
+0xafb20030, 0x9021, 0xafb1002c, 0x8821,
+0x24020002, 0xafbf003c, 0xafb30034, 0xafb00028,
+0xa7a00020, 0xa7a00018, 0xa7a0001a, 0xa7a0001c,
+0x10a20108, 0xa7a0001e, 0x2ca20003, 0x10400005,
+0x24020001, 0x10a2000a, 0x149940, 0x800538f,
+0x2201021, 0x24020004, 0x10a200b2, 0x24020008,
+0x10a200b1, 0x142940, 0x800538f, 0x2201021,
+0x3c030001, 0x731821, 0x8c637e9c, 0x3c024000,
+0x621024, 0x14400009, 0x24040001, 0x3c027fff,
+0x3442ffff, 0x628824, 0x3c010001, 0x330821,
+0xac317e94, 0x800538f, 0x2201021, 0x2821,
+0xc004924, 0x27a60018, 0x24040001, 0x2821,
+0xc004924, 0x27a60018, 0x24040001, 0x24050001,
+0x27b0001a, 0xc004924, 0x2003021, 0x24040001,
+0x24050001, 0xc004924, 0x2003021, 0x24040001,
+0x24050004, 0x27b0001c, 0xc004924, 0x2003021,
+0x24040001, 0x24050004, 0xc004924, 0x2003021,
+0x24040001, 0x24050005, 0x27b0001e, 0xc004924,
+0x2003021, 0x24040001, 0x24050005, 0xc004924,
+0x2003021, 0x24040001, 0x24050009, 0xc004924,
+0x2003021, 0x24040001, 0x24050009, 0xc004924,
+0x2003021, 0x24040001, 0x24050001, 0xc004924,
+0x27a60018, 0x24040001, 0x24050001, 0xc004924,
+0x27a60018, 0x97a20018, 0x30420004, 0x10400034,
+0x3c114000, 0x3c020001, 0x8c425e18, 0x2443ffff,
+0x2c620006, 0x10400034, 0x31080, 0x3c010001,
+0x220821, 0x8c225c38, 0x400008, 0x0,
+0x24040001, 0x24050011, 0x27b00020, 0xc004924,
+0x2003021, 0x24040001, 0x24050011, 0xc004924,
+0x2003021, 0x97a40020, 0x30824000, 0x10400002,
+0x3c030010, 0x3c030008, 0x3c120001, 0x8005306,
+0x30828000, 0x24040001, 0x24050014, 0x27b00020,
+0xc004924, 0x2003021, 0x24040001, 0x24050014,
+0xc004924, 0x2003021, 0x97a40020, 0x30821000,
+0x10400002, 0x3c030010, 0x3c030008, 0x3c120001,
+0x30820800, 0x54400001, 0x3c120002, 0x3c028000,
+0x2221025, 0x2431825, 0x8005313, 0x438825,
+0x3c110001, 0x2338821, 0x8e317e9c, 0x3c027fff,
+0x3442ffff, 0x2228824, 0x3c020001, 0x8c425d38,
+0x1040001c, 0x0, 0x3c020001, 0x8c425df8,
+0x10400002, 0x3c022000, 0x2228825, 0x141140,
+0x3c010001, 0x220821, 0x8c227ea0, 0x10400003,
+0x3c020020, 0x8005327, 0x2228825, 0x3c02ffdf,
0x3442ffff, 0x2228824, 0x141140, 0x3c010001,
-0x220821, 0x8c2275dc, 0x10400003, 0x3c020080,
-0x800515e, 0x2228825, 0x3c02ff7f, 0x3442ffff,
-0x2228824, 0x3c020001, 0x8c425500, 0x10400002,
-0x3c020800, 0x2228825, 0x3c020001, 0x8c425504,
-0x10400002, 0x3c020400, 0x2228825, 0x3c020001,
-0x8c425508, 0x10400006, 0x3c020100, 0x8005171,
-0x2228825, 0x3c027fff, 0x3442ffff, 0x628824,
-0x141140, 0x3c010001, 0x220821, 0xac3175c0,
-0x2201021, 0x8fbf002c, 0x8fb40028, 0x8fb30024,
-0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008,
-0x27bd0030, 0x27bdffd8, 0xafb40020, 0x80a021,
-0xafbf0024, 0xafb3001c, 0xafb20018, 0xafb10014,
-0xafb00010, 0x8f900200, 0x3c030001, 0x8c635488,
-0x8f930220, 0x24020002, 0x106200b4, 0x2c620003,
-0x10400005, 0x24020001, 0x1062000a, 0x141940,
-0x8005240, 0x0, 0x24020004, 0x1062005a,
-0x24020008, 0x10620059, 0x149140, 0x8005240,
-0x0, 0x3c040001, 0x832021, 0x8c8475cc,
-0x3c110001, 0x2238821, 0x8e3175c4, 0x3c024000,
-0x821024, 0x1040003e, 0x3c020008, 0x2221024,
-0x10400020, 0x36100002, 0x3c020001, 0x431021,
-0x8c4275d0, 0x10400005, 0x36100020, 0x36100100,
-0x3c020020, 0x80051b5, 0x2228825, 0x2402feff,
-0x2028024, 0x3c02ffdf, 0x3442ffff, 0x2228824,
-0x141140, 0x3c010001, 0x220821, 0x8c2275d8,
-0x10400005, 0x3c020001, 0x2629825, 0x3c020080,
-0x80051d4, 0x2228825, 0x3c02fffe, 0x3442ffff,
-0x2629824, 0x3c02ff7f, 0x3442ffff, 0x80051d4,
-0x2228824, 0x2402fedf, 0x2028024, 0x3c02fffe,
-0x3442ffff, 0x2629824, 0x3c02ff5f, 0x3442ffff,
-0x2228824, 0x3c010001, 0x230821, 0xac2075d0,
-0x3c010001, 0x230821, 0xac2075d8, 0xc0047cd,
-0x0, 0xaf900200, 0xaf930220, 0x8f820220,
-0x2403fffb, 0x431024, 0xaf820220, 0x8f820220,
-0x34420002, 0xaf820220, 0x80051eb, 0x141140,
-0x8f820200, 0x2403fffd, 0x431024, 0xc0047cd,
-0xaf820200, 0x3c02bfff, 0x3442ffff, 0xc00429b,
+0x220821, 0x8c227ea8, 0x10400003, 0x3c020080,
+0x8005332, 0x2228825, 0x3c02ff7f, 0x3442ffff,
+0x2228824, 0x3c040001, 0x24845c2c, 0x3c05000c,
+0x34a50326, 0x3c070001, 0x8ce75d28, 0x3021,
+0x141140, 0x3c010001, 0x220821, 0xac317e94,
+0xafb20010, 0xc002403, 0xafb10014, 0x800538f,
+0x2201021, 0x142940, 0x3c030001, 0x651821,
+0x8c637e98, 0x3c024000, 0x621024, 0x14400008,
+0x3c027fff, 0x3442ffff, 0x628824, 0x3c010001,
+0x250821, 0xac317e90, 0x800538f, 0x2201021,
+0x3c020001, 0x8c425d38, 0x10400033, 0x3c11c00c,
+0x3c020001, 0x8c425dd4, 0x3c04c00c, 0x34842000,
+0x3c030001, 0x8c635df8, 0x2102b, 0x21023,
+0x441024, 0x10600003, 0x518825, 0x3c022000,
+0x2228825, 0x3c020001, 0x451021, 0x8c427ea4,
+0x10400003, 0x3c020020, 0x800536c, 0x2228825,
+0x3c02ffdf, 0x3442ffff, 0x2228824, 0x141140,
+0x3c010001, 0x220821, 0x8c227eac, 0x10400003,
+0x3c020080, 0x8005377, 0x2228825, 0x3c02ff7f,
+0x3442ffff, 0x2228824, 0x3c020001, 0x8c425dc0,
+0x10400002, 0x3c020800, 0x2228825, 0x3c020001,
+0x8c425dc4, 0x10400002, 0x3c020400, 0x2228825,
+0x3c020001, 0x8c425dc8, 0x10400006, 0x3c020100,
+0x800538a, 0x2228825, 0x3c027fff, 0x3442ffff,
+0x628824, 0x141140, 0x3c010001, 0x220821,
+0xac317e90, 0x2201021, 0x8fbf003c, 0x8fb40038,
+0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028,
+0x3e00008, 0x27bd0040, 0x27bdffd8, 0xafb40020,
+0x80a021, 0xafbf0024, 0xafb3001c, 0xafb20018,
+0xafb10014, 0xafb00010, 0x8f900200, 0x3c030001,
+0x8c635d28, 0x8f930220, 0x24020002, 0x10620063,
+0x2c620003, 0x10400005, 0x24020001, 0x1062000a,
+0x141940, 0x8005459, 0x0, 0x24020004,
+0x1062005a, 0x24020008, 0x10620059, 0x149140,
+0x8005459, 0x0, 0x3c040001, 0x832021,
+0x8c847e9c, 0x3c110001, 0x2238821, 0x8e317e94,
+0x3c024000, 0x821024, 0x1040003e, 0x3c020008,
+0x2221024, 0x10400020, 0x36100002, 0x3c020001,
+0x431021, 0x8c427ea0, 0x10400005, 0x36100020,
+0x36100100, 0x3c020020, 0x80053ce, 0x2228825,
+0x2402feff, 0x2028024, 0x3c02ffdf, 0x3442ffff,
0x2228824, 0x141140, 0x3c010001, 0x220821,
-0x8005240, 0xac3175c4, 0x149140, 0x3c040001,
-0x922021, 0x8c8475c8, 0x3c110001, 0x2328821,
-0x8e3175c0, 0x3c024000, 0x821024, 0x14400011,
-0x0, 0x3c020001, 0x8c425538, 0x14400006,
-0x3c02bfff, 0x8f820200, 0x34420002, 0xc0047cd,
-0xaf820200, 0x3c02bfff, 0x3442ffff, 0xc00429b,
-0x2228824, 0x3c010001, 0x320821, 0x8005240,
-0xac3175c0, 0x3c020001, 0x8c425538, 0x10400005,
-0x3c020020, 0x3c020001, 0x8c425514, 0x1040002b,
-0x3c020020, 0x821024, 0x10400007, 0x36100020,
-0x24020100, 0x3c010001, 0x320821, 0xac2275d4,
-0x8005220, 0x36100100, 0x3c010001, 0x320821,
-0xac2075d4, 0x2402feff, 0x2028024, 0x3c020080,
-0x821024, 0x10400007, 0x141940, 0x3c020001,
-0x3c010001, 0x230821, 0xac2275dc, 0x8005231,
-0x2629825, 0x141140, 0x3c010001, 0x220821,
-0xac2075dc, 0x3c02fffe, 0x3442ffff, 0x2629824,
-0xc0047cd, 0x0, 0xaf900200, 0xaf930220,
+0x8c227ea8, 0x10400005, 0x3c020001, 0x2629825,
+0x3c020080, 0x80053ed, 0x2228825, 0x3c02fffe,
+0x3442ffff, 0x2629824, 0x3c02ff7f, 0x3442ffff,
+0x80053ed, 0x2228824, 0x2402fedf, 0x2028024,
+0x3c02fffe, 0x3442ffff, 0x2629824, 0x3c02ff5f,
+0x3442ffff, 0x2228824, 0x3c010001, 0x230821,
+0xac207ea0, 0x3c010001, 0x230821, 0xac207ea8,
+0xc004844, 0x0, 0xaf900200, 0xaf930220,
0x8f820220, 0x2403fffb, 0x431024, 0xaf820220,
-0x8f820220, 0x34420002, 0xaf820220, 0x141140,
-0x3c010001, 0x220821, 0xac3175c0, 0x8fbf0024,
-0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0x3e00008, 0x27bd0028, 0x0 };
+0x8f820220, 0x34420002, 0xaf820220, 0x8005404,
+0x141140, 0x8f820200, 0x2403fffd, 0x431024,
+0xc004844, 0xaf820200, 0x3c02bfff, 0x3442ffff,
+0xc00429b, 0x2228824, 0x141140, 0x3c010001,
+0x220821, 0x8005459, 0xac317e94, 0x149140,
+0x3c040001, 0x922021, 0x8c847e98, 0x3c110001,
+0x2328821, 0x8e317e90, 0x3c024000, 0x821024,
+0x14400011, 0x0, 0x3c020001, 0x8c425df8,
+0x14400006, 0x3c02bfff, 0x8f820200, 0x34420002,
+0xc004844, 0xaf820200, 0x3c02bfff, 0x3442ffff,
+0xc00429b, 0x2228824, 0x3c010001, 0x320821,
+0x8005459, 0xac317e90, 0x3c020001, 0x8c425df8,
+0x10400005, 0x3c020020, 0x3c020001, 0x8c425dd4,
+0x1040002b, 0x3c020020, 0x821024, 0x10400007,
+0x36100020, 0x24020100, 0x3c010001, 0x320821,
+0xac227ea4, 0x8005439, 0x36100100, 0x3c010001,
+0x320821, 0xac207ea4, 0x2402feff, 0x2028024,
+0x3c020080, 0x821024, 0x10400007, 0x141940,
+0x3c020001, 0x3c010001, 0x230821, 0xac227eac,
+0x800544a, 0x2629825, 0x141140, 0x3c010001,
+0x220821, 0xac207eac, 0x3c02fffe, 0x3442ffff,
+0x2629824, 0xc004844, 0x0, 0xaf900200,
+0xaf930220, 0x8f820220, 0x2403fffb, 0x431024,
+0xaf820220, 0x8f820220, 0x34420002, 0xaf820220,
+0x141140, 0x3c010001, 0x220821, 0xac317e90,
+0x8fbf0024, 0x8fb40020, 0x8fb3001c, 0x8fb20018,
+0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028,
+0x0, 0x0, 0x0, 0x0 };
u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
0x24486561, 0x6465723a, 0x202f7072,
0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
@@ -4339,10 +4473,10 @@ u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
0x32203139, 0x39382f30, 0x342f3237, 0x2032323a,
0x31333a34, 0x30207368, 0x75616e67, 0x20457870,
0x20240000, 0x46575f56, 0x45525349, 0x4f4e3a20,
-0x23312054, 0x68752041, 0x75672031, 0x32203135,
-0x3a34393a, 0x35332050, 0x44542031, 0x39393900,
+0x23312053, 0x61742044, 0x65632031, 0x31203136,
+0x3a30333a, 0x31392050, 0x53542031, 0x39393900,
0x46575f43, 0x4f4d5049, 0x4c455f54, 0x494d453a,
-0x2031353a, 0x34393a35, 0x33000000, 0x46575f43,
+0x2031363a, 0x30333a31, 0x39000000, 0x46575f43,
0x4f4d5049, 0x4c455f42, 0x593a2064, 0x65767263,
0x73000000, 0x46575f43, 0x4f4d5049, 0x4c455f48,
0x4f53543a, 0x20636f6d, 0x70757465, 0x0,
@@ -4420,25 +4554,27 @@ u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
0x2e322031, 0x3939382f, 0x30342f32, 0x37203232,
0x3a31333a, 0x33392073, 0x6875616e, 0x67204578,
0x70202400, 0x50726f62, 0x65506879, 0x0,
-0x6c6e6b41, 0x53535254, 0x0, 0x11998,
-0x119d0, 0x119e8, 0x11a1c, 0x11a48,
-0x11a5c, 0x11a98, 0x11e08, 0x11b70,
-0x11bb0, 0x11bdc, 0x11c1c, 0x11c4c,
-0x11c88, 0x11cbc, 0x11e08, 0x1204c,
-0x12064, 0x1208c, 0x120ac, 0x120d4,
-0x12204, 0x1222c, 0x12280, 0x122a8,
-0x0, 0x1250c, 0x125dc, 0x126b4,
-0x12784, 0x127e0, 0x128bc, 0x128e4,
-0x129c0, 0x129e8, 0x12b90, 0x12bb8,
-0x12d60, 0x12f58, 0x131ec, 0x13100,
-0x131ec, 0x13218, 0x12d88, 0x12f30,
-0x0, 0x13604, 0x13648, 0x136e0,
-0x1372c, 0x1379c, 0x13834, 0x13868,
-0x138f0, 0x13988, 0x13a58, 0x13a98,
-0x13b1c, 0x13b40, 0x13c74, 0x646f4261,
+0x6c6e6b41, 0x53535254, 0x0, 0x11af4,
+0x11b8c, 0x11bac, 0x11bf0, 0x11c1c,
+0x11c30, 0x11c6c, 0x11fe0, 0x11d48,
+0x11d88, 0x11db4, 0x11df4, 0x11e24,
+0x11e60, 0x11e94, 0x11fe0, 0x12228,
+0x12240, 0x12268, 0x12288, 0x122b0,
+0x123e0, 0x12408, 0x1245c, 0x12484,
+0x0, 0x126ec, 0x127bc, 0x12894,
+0x12964, 0x129c0, 0x12a9c, 0x12ac4,
+0x12ba0, 0x12bc8, 0x12d70, 0x12d98,
+0x12f40, 0x13138, 0x133cc, 0x132e0,
+0x133cc, 0x133f8, 0x12f68, 0x13110,
+0x0, 0x13ae4, 0x13b28, 0x13bc0,
+0x13c0c, 0x13c7c, 0x13d14, 0x13d48,
+0x13dd0, 0x13e68, 0x13f38, 0x13f78,
+0x13ffc, 0x14020, 0x14154, 0x646f4261,
0x73655067, 0x0, 0x0, 0x0,
0x0, 0x73746d61, 0x634c4e4b, 0x0,
-0x0, 0x0 };
+0x6765746d, 0x636c6e6b, 0x0, 0x14c4c,
+0x14c4c, 0x14b94, 0x14bd8, 0x14c4c,
+0x14c4c, 0x0 };
u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __initdata = {
0x416c7465,
0x6f6e2041, 0x63654e49, 0x43205600, 0x416c7465,
@@ -4452,39 +4588,41 @@ u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __initdata = {
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x3, 0x0,
-0x1, 0x0, 0x0, 0x1,
+0x1, 0x0, 0x0, 0x0,
+0x1, 0x0, 0x1, 0x0,
0x0, 0x0, 0x0, 0x1,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x1000000, 0x21000000, 0x12000140,
-0x0, 0x0, 0x20000000, 0x120000a0,
-0x0, 0x12000060, 0x12000180, 0x120001e0,
-0x0, 0x0, 0x0, 0x0,
+0x1, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x1000000, 0x21000000,
+0x12000140, 0x0, 0x0, 0x20000000,
+0x120000a0, 0x0, 0x12000060, 0x12000180,
+0x120001e0, 0x0, 0x0, 0x0,
+0x1, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x2,
0x0, 0x0, 0x30001, 0x1,
0x30201, 0x0, 0x0, 0x0 };
#endif
/* Generated by genfw.c */
#define tigon2FwReleaseMajor 0xc
-#define tigon2FwReleaseMinor 0x3
-#define tigon2FwReleaseFix 0xd
+#define tigon2FwReleaseMinor 0x4
+#define tigon2FwReleaseFix 0x5
#define tigon2FwStartAddr 0x00004000
#define tigon2FwTextAddr 0x00004000
-#define tigon2FwTextLen 0xeca0
-#define tigon2FwRodataAddr 0x00012ca0
-#define tigon2FwRodataLen 0xff0
-#define tigon2FwDataAddr 0x00013cc0
-#define tigon2FwDataLen 0x170
-#define tigon2FwSbssAddr 0x00013e30
-#define tigon2FwSbssLen 0xbc
-#define tigon2FwBssAddr 0x00013ef0
+#define tigon2FwTextLen 0x11c50
+#define tigon2FwRodataAddr 0x00015c50
+#define tigon2FwRodataLen 0x10c0
+#define tigon2FwDataAddr 0x00016d40
+#define tigon2FwDataLen 0x1c0
+#define tigon2FwSbssAddr 0x00016f00
+#define tigon2FwSbssLen 0xc4
+#define tigon2FwBssAddr 0x00016fd0
#define tigon2FwBssLen 0x20c0
u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x0,
0x10000003, 0x0, 0xd, 0xd,
-0x3c1d0001, 0x8fbd3d10, 0x3a0f021, 0x3c100000,
+0x3c1d0001, 0x8fbd6da0, 0x3a0f021, 0x3c100000,
0x26104000, 0xc0010c0, 0x0, 0xd,
-0x3c1d0001, 0x8fbd3d14, 0x3a0f021, 0x3c100000,
-0x26104000, 0xc00178e, 0x0, 0xd,
+0x3c1d0001, 0x8fbd6da4, 0x3a0f021, 0x3c100000,
+0x26104000, 0xc0017c8, 0x0, 0xd,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
@@ -4496,22 +4634,22 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x2000008,
-0x0, 0x80016dd, 0x3c0a0001, 0x80016dd,
-0x3c0a0002, 0x80016dd, 0x0, 0x8002ab5,
-0x0, 0x8002a58, 0x0, 0x80016dd,
-0x3c0a0004, 0x800306c, 0x0, 0x8001a07,
-0x0, 0x80036c3, 0x0, 0x8004aad,
-0x0, 0x80016dd, 0x3c0a0006, 0x8003731,
-0x3c0a0007, 0x80016dd, 0x3c0a0008, 0x80016dd,
-0x3c0a0009, 0x8003789, 0x0, 0x8002caf,
-0x0, 0x80016dd, 0x3c0a000b, 0x80016dd,
-0x3c0a000c, 0x80016dd, 0x3c0a000d, 0x800277b,
-0x0, 0x8002710, 0x0, 0x80016dd,
-0x3c0a000e, 0x8001f20, 0x0, 0x8001919,
-0x0, 0x80019b9, 0x0, 0x8003a08,
-0x0, 0x80039f6, 0x0, 0x80016dd,
-0x0, 0x80018c6, 0x0, 0x80016dd,
-0x0, 0x80016dd, 0x3c0a0013, 0x80016dd,
+0x0, 0x8001717, 0x3c0a0001, 0x8001717,
+0x3c0a0002, 0x8001717, 0x0, 0x8002c68,
+0x0, 0x8002c0b, 0x0, 0x8001717,
+0x3c0a0004, 0x8003272, 0x0, 0x8001a3a,
+0x0, 0x8003925, 0x0, 0x80038cc,
+0x0, 0x8001717, 0x3c0a0006, 0x8003993,
+0x3c0a0007, 0x8001717, 0x3c0a0008, 0x8001717,
+0x3c0a0009, 0x80039eb, 0x0, 0x8002e62,
+0x0, 0x8001717, 0x3c0a000b, 0x8001717,
+0x3c0a000c, 0x8001717, 0x3c0a000d, 0x80028d7,
+0x0, 0x800286c, 0x0, 0x8001717,
+0x3c0a000e, 0x8002074, 0x0, 0x800194c,
+0x0, 0x80019ec, 0x0, 0x8003c7e,
+0x0, 0x8003c6c, 0x0, 0x8001717,
+0x0, 0x8001902, 0x0, 0x8001717,
+0x0, 0x8001717, 0x3c0a0013, 0x8001717,
0x3c0a0014, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
@@ -4529,78 +4667,78 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x27bdffe0,
0x3c1cc000, 0xafbf001c, 0xafb00018, 0x8f820140,
-0x24030003, 0xaf8300ec, 0x34420004, 0xc0029a0,
-0xaf820140, 0x3c0100c0, 0xc001711, 0xac203ffc,
-0x403021, 0x3c020008, 0x3c010001, 0xac263e48,
+0x24030003, 0xaf8300ec, 0x34420004, 0xc002afc,
+0xaf820140, 0x3c0100c0, 0xc00174b, 0xac203ffc,
+0x403021, 0x3c020008, 0x3c010001, 0xac266f18,
0x50c2000d, 0x24020008, 0x3c100010, 0x10d00009,
-0x24050100, 0x3c040001, 0x24842d54, 0x3821,
-0xafa00010, 0xc0029bb, 0xafa00014, 0x3c010001,
-0xac303e48, 0x24020008, 0x3c010001, 0xac223e60,
-0x2402001f, 0x3c010001, 0xac223e70, 0x24020016,
-0x3c010001, 0xac223e44, 0x3c05fffe, 0x34a56f08,
-0x3c020001, 0x8c423e48, 0x3c030001, 0x24635fb0,
-0x3c040001, 0x8c843cc4, 0x431023, 0x14800002,
-0x458021, 0x2610fa48, 0x2402f000, 0x2028024,
-0xc001733, 0x2002021, 0x2022823, 0x3c040020,
+0x24050100, 0x3c040001, 0x24845d04, 0x3821,
+0xafa00010, 0xc002b17, 0xafa00014, 0x3c010001,
+0xac306f18, 0x24020008, 0x3c010001, 0xac226f30,
+0x2402001f, 0x3c010001, 0xac226f40, 0x24020016,
+0x3c010001, 0xac226f14, 0x3c05fffe, 0x34a56f08,
+0x3c020001, 0x8c426f18, 0x3c030002, 0x24639090,
+0x3c040001, 0x8c846d44, 0x431023, 0x14800002,
+0x458021, 0x2610fa38, 0x2402f000, 0x2028024,
+0xc00176d, 0x2002021, 0x2022823, 0x3c040020,
0x821823, 0x651823, 0x247bb000, 0x3c03fffe,
0x3463bf08, 0x363b821, 0x3c0600bf, 0x34c6f000,
-0x3c070001, 0x8ce73cc0, 0x3c0300bf, 0x3463e000,
-0x852023, 0x3c010001, 0xac243e54, 0x822023,
-0x3c010001, 0xac253e3c, 0x52842, 0x3c010001,
-0xac223e30, 0x27620ffc, 0x3c010001, 0xac223d10,
+0x3c070001, 0x8ce76d40, 0x3c0300bf, 0x3463e000,
+0x852023, 0x3c010001, 0xac246f24, 0x822023,
+0x3c010001, 0xac256f0c, 0x52842, 0x3c010001,
+0xac226f00, 0x27620ffc, 0x3c010001, 0xac226da0,
0x27621ffc, 0xdb3023, 0x7b1823, 0x3c010001,
-0xac243e34, 0x3c010001, 0xac253e58, 0x3c010001,
-0xac223d14, 0xaf860150, 0x10e00011, 0xaf830250,
-0x3c1d0001, 0x8fbd3ccc, 0x3a0f021, 0xc0016f7,
-0x0, 0x3c020001, 0x8c423cd0, 0x3c030001,
-0x8c633cd4, 0x2442fe00, 0x24630200, 0x3c010001,
-0xac223cd0, 0x3c010001, 0x10000004, 0xac233cd4,
-0x3c1d0001, 0x8fbd3d10, 0x3a0f021, 0x3c020001,
-0x8c423cc4, 0x1040000d, 0x26fafa48, 0x3c020001,
-0x8c423cd0, 0x3c030001, 0x8c633cd4, 0x3c1a0001,
-0x8f5a3cd4, 0x2442fa48, 0x246305b8, 0x3c010001,
-0xac223cd0, 0x3c010001, 0xac233cd4, 0x3c020001,
-0x8c423cc8, 0x14400003, 0x0, 0x3c010001,
-0xac203cd0, 0xc00114c, 0x0, 0x8fbf001c,
+0xac246f04, 0x3c010001, 0xac256f28, 0x3c010001,
+0xac226da4, 0xaf860150, 0x10e00011, 0xaf830250,
+0x3c1d0001, 0x8fbd6d4c, 0x3a0f021, 0xc001731,
+0x0, 0x3c020001, 0x8c426d50, 0x3c030001,
+0x8c636d54, 0x2442fe00, 0x24630200, 0x3c010001,
+0xac226d50, 0x3c010001, 0x10000004, 0xac236d54,
+0x3c1d0001, 0x8fbd6da0, 0x3a0f021, 0x3c020001,
+0x8c426d44, 0x1040000d, 0x26fafa38, 0x3c020001,
+0x8c426d50, 0x3c030001, 0x8c636d54, 0x3c1a0001,
+0x8f5a6d54, 0x2442fa38, 0x246305c8, 0x3c010001,
+0xac226d50, 0x3c010001, 0xac236d54, 0x3c020001,
+0x8c426d48, 0x14400003, 0x0, 0x3c010001,
+0xac206d50, 0xc00114c, 0x0, 0x8fbf001c,
0x8fb00018, 0x3e00008, 0x27bd0020, 0x3c020001,
-0x8c423cd0, 0x3c030001, 0x8c633cd4, 0x27bdffa0,
-0xafb00040, 0x3c100001, 0x8e103738, 0x3c040001,
-0x24842d60, 0xafbf0058, 0xafbe0054, 0xafb50050,
+0x8c426d50, 0x3c030001, 0x8c636d54, 0x27bdffa0,
+0xafb00040, 0x3c100001, 0x8e106748, 0x3c040001,
+0x24845d10, 0xafbf0058, 0xafbe0054, 0xafb50050,
0xafb3004c, 0xafb20048, 0xafb10044, 0xafa20034,
0xafa30030, 0xafa00010, 0xafa00014, 0x8f860040,
-0x24050200, 0xc0029bb, 0x2003821, 0x8f830040,
+0x24050200, 0xc002b17, 0x2003821, 0x8f830040,
0x3c02f000, 0x621824, 0x3c026000, 0x1062000b,
-0xa3a0003f, 0x240e0001, 0x3c040001, 0x24842d68,
+0xa3a0003f, 0x240e0001, 0x3c040001, 0x24845d18,
0xa3ae003f, 0xafa00010, 0xafa00014, 0x8f860040,
-0x24050300, 0xc0029bb, 0x2003821, 0x8f820240,
+0x24050300, 0xc002b17, 0x2003821, 0x8f820240,
0x3c030001, 0x431025, 0xaf820240, 0xaf800048,
0x8f820048, 0x14400005, 0x0, 0xaf800048,
0x8f820048, 0x10400004, 0x0, 0xaf800048,
0x10000003, 0x2e02021, 0xaf80004c, 0x2e02021,
-0x3c050001, 0xc002a28, 0x34a540f8, 0x3402021,
-0xc002a28, 0x240505b8, 0x3c020001, 0x8c423e54,
-0x3c0d0001, 0x8dad3e34, 0x3c030001, 0x8c633e30,
-0x3c080001, 0x8d083e3c, 0x3c090001, 0x8d293e58,
-0x3c0a0001, 0x8d4a3e60, 0x3c0b0001, 0x8d6b3e70,
-0x3c0c0001, 0x8d8c3e44, 0x3c040001, 0x24842d74,
-0x24050400, 0xaf420130, 0x8f420130, 0x24060001,
-0x24070001, 0xaf400000, 0xaf4d012c, 0xaf430138,
-0xaf48013c, 0xaf490140, 0xaf4a0144, 0xaf4b0148,
-0xaf4c014c, 0x2442ff80, 0xaf420134, 0x24020001,
-0xafa20010, 0xc0029bb, 0xafa00014, 0x8f42012c,
-0xafa20010, 0x8f420130, 0xafa20014, 0x8f460138,
-0x8f47013c, 0x3c040001, 0x24842d80, 0xc0029bb,
-0x24050500, 0xafb70010, 0xafba0014, 0x8f460140,
-0x8f470144, 0x3c040001, 0x24842d8c, 0xc0029bb,
-0x24050600, 0x3c020001, 0x8c423e48, 0x3603821,
-0x3c060001, 0x24c65fb0, 0x2448ffff, 0x1061824,
+0x3c050001, 0xc002b84, 0x34a540f8, 0x3402021,
+0xc002b84, 0x240505c8, 0x3c020001, 0x8c426f24,
+0x3c0d0001, 0x8dad6f04, 0x3c030001, 0x8c636f00,
+0x3c080001, 0x8d086f0c, 0x3c090001, 0x8d296f28,
+0x3c0a0001, 0x8d4a6f30, 0x3c0b0001, 0x8d6b6f40,
+0x3c0c0001, 0x8d8c6f14, 0x3c040001, 0x24845d24,
+0x24050400, 0xaf42013c, 0x8f42013c, 0x24060001,
+0x24070001, 0xaf400000, 0xaf4d0138, 0xaf430144,
+0xaf480148, 0xaf49014c, 0xaf4a0150, 0xaf4b0154,
+0xaf4c0158, 0x2442ff80, 0xaf420140, 0x24020001,
+0xafa20010, 0xc002b17, 0xafa00014, 0x8f420138,
+0xafa20010, 0x8f42013c, 0xafa20014, 0x8f460144,
+0x8f470148, 0x3c040001, 0x24845d30, 0xc002b17,
+0x24050500, 0xafb70010, 0xafba0014, 0x8f46014c,
+0x8f470150, 0x3c040001, 0x24845d3c, 0xc002b17,
+0x24050600, 0x3c020001, 0x8c426f18, 0x3603821,
+0x3c060002, 0x24c69090, 0x2448ffff, 0x1061824,
0xe81024, 0x43102b, 0x10400006, 0x24050900,
-0x3c040001, 0x24842d98, 0xafa80010, 0xc0029bb,
+0x3c040001, 0x24845d48, 0xafa80010, 0xc002b17,
0xafa00014, 0x8f82000c, 0xafa20010, 0x8f82003c,
0xafa20014, 0x8f860000, 0x8f870004, 0x3c040001,
-0x24842da4, 0xc0029bb, 0x24051000, 0x8c020220,
+0x24845d54, 0xc002b17, 0x24051000, 0x8c020220,
0x8c030224, 0x8c060218, 0x8c07021c, 0x3c040001,
-0x24842dac, 0x24051100, 0xafa20010, 0xc0029bb,
+0x24845d5c, 0x24051100, 0xafa20010, 0xc002b17,
0xafa30014, 0xaf800054, 0xaf80011c, 0x8c020218,
0x30420002, 0x10400009, 0x0, 0x8c020220,
0x3c030002, 0x34630004, 0x431025, 0xaf42000c,
@@ -4619,11 +4757,20 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x24020490, 0xaee20010, 0xaee40008, 0xaee5000c,
0x26e40008, 0x8c820000, 0x8c830004, 0xaf820090,
0xaf830094, 0x8c820018, 0xaf8200b4, 0x9482000a,
-0xaf82009c, 0x8f8200b0, 0x8f430014, 0x431025,
-0xaf8200b0, 0x8f8200b0, 0x30420004, 0x1440fffd,
-0x24051200, 0x96e20472, 0x96e60452, 0x96e70462,
-0xafa20010, 0x96e20482, 0x3c040001, 0x24842db4,
-0xc0029bb, 0xafa20014, 0x96f00452, 0x32020001,
+0xaf82009c, 0x8f420014, 0xaf8200b0, 0x8f8200b0,
+0x30420004, 0x1440fffd, 0x0, 0x8f8200b0,
+0x3c03ef00, 0x431024, 0x10400021, 0x0,
+0x8f8200b4, 0xafa20010, 0x8f820090, 0x8f830094,
+0x3c040001, 0x24845d64, 0xafa30014, 0x8f8600b0,
+0x8f87009c, 0x3c050001, 0xc002b17, 0x34a5200d,
+0x3c040001, 0x24845d70, 0x240203ac, 0xafa20010,
+0xafa00014, 0x8f860144, 0x3c070001, 0x24e75d78,
+0xc002b17, 0x3405dead, 0x8f82011c, 0x34420002,
+0xaf82011c, 0x8f820220, 0x34420004, 0xaf820220,
+0x8f820140, 0x3c030001, 0x431025, 0xaf820140,
+0x96e20472, 0x96e60452, 0x96e70462, 0xafa20010,
+0x96e20482, 0x3c040001, 0x24845da4, 0x24051200,
+0xc002b17, 0xafa20014, 0x96f00452, 0x32020001,
0x10400002, 0xb021, 0x24160001, 0x32020002,
0x54400001, 0x36d60002, 0x32020008, 0x54400001,
0x36d60004, 0x32020010, 0x54400001, 0x36d60008,
@@ -4635,9 +4782,9 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x36d61000, 0x96f00462, 0x32c24000, 0x14400004,
0x3207009b, 0x30c2009b, 0x14e20007, 0x240e0001,
0x32c22000, 0x1440000d, 0x32020001, 0x3062009b,
-0x10e20009, 0x240e0001, 0x3c040001, 0x24842dc0,
+0x10e20009, 0x240e0001, 0x3c040001, 0x24845db0,
0x24051300, 0x2003821, 0xa3ae003f, 0xafa30010,
-0xc0029bb, 0xafa00014, 0x32020001, 0x54400001,
+0xc002b17, 0xafa00014, 0x32020001, 0x54400001,
0x36d60080, 0x32020002, 0x54400001, 0x36d60100,
0x32020008, 0x54400001, 0x36d60200, 0x32020010,
0x54400001, 0x36d60400, 0x32020080, 0x54400001,
@@ -4651,1060 +4798,1138 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x10400002, 0x3c020010, 0x2c2b025, 0x8c020218,
0x30424000, 0x10400002, 0x3c020020, 0x2c2b025,
0x8c020218, 0x30421000, 0x10400002, 0x3c020040,
-0x2c2b025, 0x8ee20498, 0x8ee3049c, 0xaf420150,
-0xaf430154, 0x8ee204a0, 0x8ee304a4, 0xaf420158,
-0xaf43015c, 0x8ee204a8, 0x8ee304ac, 0xaf420160,
-0xaf430164, 0x8ee20428, 0x8ee3042c, 0xaf420168,
-0xaf43016c, 0x8ee20448, 0x8ee3044c, 0xaf420170,
-0xaf430174, 0x8ee20458, 0x8ee3045c, 0xaf420178,
-0xaf43017c, 0x8ee20468, 0x8ee3046c, 0xaf420180,
-0xaf430184, 0x8ee20478, 0x8ee3047c, 0xaf420188,
-0xaf43018c, 0x8ee20488, 0x8ee3048c, 0xaf420190,
-0xaf430194, 0x8ee204b0, 0x8ee304b4, 0x24040080,
-0xaf420198, 0xaf43019c, 0xc002a28, 0x24050080,
-0x8c02025c, 0x27440214, 0xaf4201e0, 0x8c020260,
-0x24050200, 0x24060008, 0xc002a3f, 0xaf4201e8,
+0x2c2b025, 0x8ee20498, 0x8ee3049c, 0xaf420160,
+0xaf430164, 0x8ee204a0, 0x8ee304a4, 0xaf420168,
+0xaf43016c, 0x8ee204a8, 0x8ee304ac, 0xaf420170,
+0xaf430174, 0x8ee20428, 0x8ee3042c, 0xaf420178,
+0xaf43017c, 0x8ee20448, 0x8ee3044c, 0xaf420180,
+0xaf430184, 0x8ee20458, 0x8ee3045c, 0xaf420188,
+0xaf43018c, 0x8ee20468, 0x8ee3046c, 0xaf420190,
+0xaf430194, 0x8ee20478, 0x8ee3047c, 0xaf420198,
+0xaf43019c, 0x8ee20488, 0x8ee3048c, 0xaf4201a0,
+0xaf4301a4, 0x8ee204b0, 0x8ee304b4, 0x24040080,
+0xaf4201a8, 0xaf4301ac, 0xc002b84, 0x24050080,
+0x8c02025c, 0x27440224, 0xaf4201f0, 0x8c020260,
+0x24050200, 0x24060008, 0xc002b9b, 0xaf4201f8,
0x3c043b9a, 0x3484ca00, 0x3821, 0x24020006,
-0x24030002, 0xaf4201e4, 0x240203e8, 0xaf4301f4,
-0xaf4301f0, 0xaf4401ec, 0xaf420284, 0x24020001,
-0xaf430280, 0xaf42028c, 0x3c030001, 0x671821,
-0x90633cd8, 0x3471021, 0x24e70001, 0xa043021c,
+0x24030002, 0xaf4201f4, 0x240203e8, 0xaf430204,
+0xaf430200, 0xaf4401fc, 0xaf420294, 0x24020001,
+0xaf430290, 0xaf42029c, 0x3c030001, 0x671821,
+0x90636d58, 0x3471021, 0x24e70001, 0xa043022c,
0x2ce2000f, 0x1440fff8, 0x3471821, 0x24e70001,
0x3c080001, 0x350840f8, 0x8f820040, 0x3c040001,
-0x24842dcc, 0x24051400, 0x21702, 0x24420030,
-0xa062021c, 0x3471021, 0xa040021c, 0x8c070218,
-0x2c03021, 0x240205b8, 0xafa20010, 0xc0029bb,
-0xafa80014, 0x3c040001, 0x24842dd8, 0x3c050000,
-0x24a55b38, 0x24060010, 0x27b10030, 0x2203821,
-0x27b30034, 0xc001751, 0xafb30010, 0x3c030001,
-0x8c633cc8, 0x1060000a, 0x408021, 0x8fa30030,
+0x24845dbc, 0x24051400, 0x21702, 0x24420030,
+0xa062022c, 0x3471021, 0xa040022c, 0x8c070218,
+0x2c03021, 0x240205c8, 0xafa20010, 0xc002b17,
+0xafa80014, 0x3c040001, 0x24845dc8, 0x3c050000,
+0x24a55c20, 0x24060010, 0x27b10030, 0x2203821,
+0x27b30034, 0xc00178b, 0xafb30010, 0x3c030001,
+0x8c636d48, 0x1060000a, 0x408021, 0x8fa30030,
0x2405ff00, 0x8fa20034, 0x246400ff, 0x852024,
0x831823, 0x431023, 0xafa20034, 0xafa40030,
-0xafb30010, 0x3c040001, 0x24842de4, 0x3c050000,
-0x24a54100, 0x24060108, 0xc001751, 0x2203821,
+0xafb30010, 0x3c040001, 0x24845dd4, 0x3c050000,
+0x24a54100, 0x24060108, 0xc00178b, 0x2203821,
0x409021, 0x32c20003, 0x50400045, 0x2203821,
0x8f820050, 0x3c030010, 0x431024, 0x10400016,
0x0, 0x8c020218, 0x30420040, 0x1040000f,
0x24020001, 0x8f820050, 0x8c030218, 0x240e0001,
-0x3c040001, 0x24842df0, 0xa3ae003f, 0xafa20010,
-0xafa30014, 0x8f870040, 0x24051500, 0xc0029bb,
+0x3c040001, 0x24845de0, 0xa3ae003f, 0xafa20010,
+0xafa30014, 0x8f870040, 0x24051500, 0xc002b17,
0x2c03021, 0x10000004, 0x0, 0x3c010001,
-0x370821, 0xa02240f4, 0x3c040001, 0x24842dfc,
-0x3c050001, 0x24a52c20, 0x3c060001, 0x24c62c8c,
+0x370821, 0xa02240f4, 0x3c040001, 0x24845dec,
+0x3c050001, 0x24a55bd0, 0x3c060001, 0x24c65c3c,
0xc53023, 0x8f420010, 0x27b30030, 0x2603821,
-0x27b10034, 0x34420a00, 0xaf420010, 0xc001751,
-0xafb10010, 0x3c040001, 0x24842e10, 0x3c050001,
-0x24a5af38, 0x3c060001, 0x24c6b2b4, 0xc53023,
-0x2603821, 0xaf420108, 0xc001751, 0xafb10010,
-0x3c040001, 0x24842e2c, 0x3c050001, 0x24a5b6c4,
-0x3c060001, 0x24c6c1a8, 0xc53023, 0x2603821,
-0x3c010001, 0xac223ea0, 0xc001751, 0xafb10010,
-0x3c040001, 0x24842e44, 0x10000024, 0x24051600,
-0x3c040001, 0x24842e4c, 0x3c050001, 0x24a59b0c,
-0x3c060001, 0x24c69c38, 0xc53023, 0xc001751,
-0xafb30010, 0x3c040001, 0x24842e5c, 0x3c050001,
-0x24a5aad4, 0x3c060001, 0x24c6af30, 0xc53023,
-0x2203821, 0xaf420108, 0xc001751, 0xafb30010,
-0x3c040001, 0x24842e70, 0x3c050001, 0x24a5b2bc,
-0x3c060001, 0x24c6b6bc, 0xc53023, 0x2203821,
-0x3c010001, 0xac223ea0, 0xc001751, 0xafb30010,
-0x3c040001, 0x24842e84, 0x24051650, 0x2c03021,
-0x3821, 0x3c010001, 0xac223ea4, 0xafa00010,
-0xc0029bb, 0xafa00014, 0x32c20020, 0x10400021,
-0x27a70030, 0x3c040001, 0x24842e90, 0x3c050001,
-0x24a5a960, 0x3c060001, 0x24c6aacc, 0xc53023,
-0x24022000, 0xaf42001c, 0x27a20034, 0xc001751,
+0x27b10034, 0x34420a00, 0xaf420010, 0xc00178b,
+0xafb10010, 0x3c040001, 0x24845e00, 0x3c050001,
+0x24a5b604, 0x3c060001, 0x24c6b980, 0xc53023,
+0x2603821, 0xaf420108, 0xc00178b, 0xafb10010,
+0x3c040001, 0x24845e1c, 0x3c050001, 0x24a5bda0,
+0x3c060001, 0x24c6c8a0, 0xc53023, 0x2603821,
+0x3c010001, 0xac226f70, 0xc00178b, 0xafb10010,
+0x3c040001, 0x24845e34, 0x10000024, 0x24051600,
+0x3c040001, 0x24845e3c, 0x3c050001, 0x24a5a07c,
+0x3c060001, 0x24c6a1a8, 0xc53023, 0xc00178b,
+0xafb30010, 0x3c040001, 0x24845e4c, 0x3c050001,
+0x24a5b1a0, 0x3c060001, 0x24c6b5fc, 0xc53023,
+0x2203821, 0xaf420108, 0xc00178b, 0xafb30010,
+0x3c040001, 0x24845e60, 0x3c050001, 0x24a5b988,
+0x3c060001, 0x24c6bd98, 0xc53023, 0x2203821,
+0x3c010001, 0xac226f70, 0xc00178b, 0xafb30010,
+0x3c040001, 0x24845e74, 0x24051650, 0x2c03021,
+0x3821, 0x3c010001, 0xac226f74, 0xafa00010,
+0xc002b17, 0xafa00014, 0x32c20020, 0x10400021,
+0x27a70030, 0x3c040001, 0x24845e80, 0x3c050001,
+0x24a5b02c, 0x3c060001, 0x24c6b198, 0xc53023,
+0x24022000, 0xaf42001c, 0x27a20034, 0xc00178b,
0xafa20010, 0x21900, 0x31982, 0x3c040800,
0x641825, 0xae430028, 0x24030010, 0xaf43003c,
0x96e30450, 0xaf430040, 0x8f430040, 0x3c040001,
-0x24842ea4, 0xafa00014, 0xafa30010, 0x8f47001c,
-0x24051660, 0x3c010001, 0xac223e9c, 0x10000025,
+0x24845e94, 0xafa00014, 0xafa30010, 0x8f47001c,
+0x24051660, 0x3c010001, 0xac226f6c, 0x10000025,
0x32c60020, 0x8ee20448, 0x8ee3044c, 0xaf43001c,
0x8f42001c, 0x2442e000, 0x2c422001, 0x1440000a,
-0x240e0001, 0x3c040001, 0x24842eb0, 0xa3ae003f,
+0x240e0001, 0x3c040001, 0x24845ea0, 0xa3ae003f,
0xafa00010, 0xafa00014, 0x8f46001c, 0x24051700,
-0xc0029bb, 0x3821, 0x3c020000, 0x24425b74,
+0xc002b17, 0x3821, 0x3c020000, 0x24425c5c,
0x21100, 0x21182, 0x3c030800, 0x431025,
0xae420028, 0x24020008, 0xaf42003c, 0x96e20450,
-0xaf420040, 0x8f420040, 0x3c040001, 0x24842ebc,
+0xaf420040, 0x8f420040, 0x3c040001, 0x24845eac,
0xafa00014, 0xafa20010, 0x8f47001c, 0x24051800,
-0x32c60020, 0xc0029bb, 0x0, 0x3c030001,
-0x8c633ea0, 0x3c050fff, 0x34a5ffff, 0x3c020001,
-0x8c423ea4, 0x3c040800, 0x651824, 0x31882,
+0x32c60020, 0xc002b17, 0x0, 0x3c030001,
+0x8c636f70, 0x3c050fff, 0x34a5ffff, 0x3c020001,
+0x8c426f74, 0x3c040800, 0x651824, 0x31882,
0x641825, 0x451024, 0x21082, 0x441025,
0xae420080, 0x32c20180, 0x10400056, 0xae430020,
0x8f82005c, 0x3c030080, 0x431024, 0x1040000d,
0x0, 0x8f820050, 0xafa20010, 0x8f82005c,
-0x240e0001, 0x3c040001, 0x24842ec8, 0xa3ae003f,
-0xafa20014, 0x8f870040, 0x24051900, 0xc0029bb,
+0x240e0001, 0x3c040001, 0x24845eb8, 0xa3ae003f,
+0xafa20014, 0x8f870040, 0x24051900, 0xc002b17,
0x2c03021, 0x8f820050, 0x3c030010, 0x431024,
0x10400016, 0x0, 0x8c020218, 0x30420040,
0x1040000f, 0x24020001, 0x8f820050, 0x8c030218,
-0x240e0001, 0x3c040001, 0x24842df0, 0xa3ae003f,
+0x240e0001, 0x3c040001, 0x24845de0, 0xa3ae003f,
0xafa20010, 0xafa30014, 0x8f870040, 0x24052000,
-0xc0029bb, 0x2c03021, 0x10000004, 0x0,
+0xc002b17, 0x2c03021, 0x10000004, 0x0,
0x3c010001, 0x370821, 0xa02240f4, 0x3c040001,
-0x24842ed4, 0x3c050001, 0x24a52ba0, 0x3c060001,
-0x24c62c18, 0xc53023, 0x8f420008, 0x27b30030,
+0x24845ec4, 0x3c050001, 0x24a55b50, 0x3c060001,
+0x24c65bc8, 0xc53023, 0x8f420008, 0x27b30030,
0x2603821, 0x27b10034, 0x34420e00, 0xaf420008,
-0xc001751, 0xafb10010, 0x3c040001, 0x24842eec,
-0x3c050001, 0x24a5cffc, 0x3c060001, 0x24c6db04,
-0xc53023, 0x2603821, 0xaf42010c, 0xc001751,
-0xafb10010, 0x3c040001, 0x24842f04, 0x3c050001,
-0x24a5df84, 0x3c060001, 0x24c6e6bc, 0xc53023,
-0x2603821, 0x3c010001, 0xac223eb0, 0xc001751,
-0xafb10010, 0x3c040001, 0x24842f1c, 0x10000027,
-0x24052100, 0x3c040001, 0x24842f24, 0x3c050001,
-0x24a599c8, 0x3c060001, 0x24c69b04, 0xc53023,
-0x27b10030, 0x2203821, 0x27b30034, 0xc001751,
-0xafb30010, 0x3c040001, 0x24842f34, 0x3c050001,
-0x24a5c25c, 0x3c060001, 0x24c6cff4, 0xc53023,
-0x2203821, 0xaf42010c, 0xc001751, 0xafb30010,
-0x3c040001, 0x24842f44, 0x3c050001, 0x24a5de24,
-0x3c060001, 0x24c6df7c, 0xc53023, 0x2203821,
-0x3c010001, 0xac223eb0, 0xc001751, 0xafb30010,
-0x3c040001, 0x24842f58, 0x24052150, 0x2c03021,
-0x3821, 0x3c010001, 0xac223ebc, 0xafa00010,
-0xc0029bb, 0xafa00014, 0x3c030001, 0x8c633eb0,
-0x3c110fff, 0x3631ffff, 0x3c020001, 0x8c423ebc,
+0xc00178b, 0xafb10010, 0x3c040001, 0x24845edc,
+0x3c050001, 0x24a5d814, 0x3c060001, 0x24c6e328,
+0xc53023, 0x2603821, 0xaf42010c, 0xc00178b,
+0xafb10010, 0x3c040001, 0x24845ef4, 0x3c050001,
+0x24a5e90c, 0x3c060001, 0x24c6f050, 0xc53023,
+0x2603821, 0x3c010001, 0xac226f80, 0xc00178b,
+0xafb10010, 0x3c040001, 0x24845f0c, 0x10000027,
+0x24052100, 0x3c040001, 0x24845f14, 0x3c050001,
+0x24a59f38, 0x3c060001, 0x24c6a074, 0xc53023,
+0x27b10030, 0x2203821, 0x27b30034, 0xc00178b,
+0xafb30010, 0x3c040001, 0x24845f24, 0x3c050001,
+0x24a5ca74, 0x3c060001, 0x24c6d80c, 0xc53023,
+0x2203821, 0xaf42010c, 0xc00178b, 0xafb30010,
+0x3c040001, 0x24845f34, 0x3c050001, 0x24a5e7ac,
+0x3c060001, 0x24c6e904, 0xc53023, 0x2203821,
+0x3c010001, 0xac226f80, 0xc00178b, 0xafb30010,
+0x3c040001, 0x24845f48, 0x24052150, 0x2c03021,
+0x3821, 0x3c010001, 0xac226f8c, 0xafa00010,
+0xc002b17, 0xafa00014, 0x3c030001, 0x8c636f80,
+0x3c110fff, 0x3631ffff, 0x3c020001, 0x8c426f8c,
0x3c1e0800, 0x711824, 0x31882, 0x7e1825,
0x511024, 0x21082, 0x5e1025, 0xae430038,
0xae420078, 0x8c020218, 0x30420040, 0x14400004,
0x24020001, 0x3c010001, 0x370821, 0xa02240f4,
-0x3c040001, 0x24842f64, 0x3c050001, 0x24a52ab4,
-0x3c060001, 0x24c62b90, 0xc53023, 0x27b50030,
-0x2a03821, 0x27b30034, 0xc001751, 0xafb30010,
-0x3c010001, 0xac223ea8, 0x511024, 0x21082,
+0x3c040001, 0x24845f54, 0x3c050001, 0x24a5e330,
+0x3c060001, 0x24c6e48c, 0xc53023, 0x27b50030,
+0x2a03821, 0x27b30034, 0xc00178b, 0xafb30010,
+0x3c010001, 0xac226f78, 0x511024, 0x21082,
0x5e1025, 0xae420050, 0x32c22000, 0x10400005,
-0x2a03821, 0x3c020000, 0x24425b74, 0x1000000d,
-0x511024, 0x3c040001, 0x24842f78, 0x3c050001,
-0x24a5db0c, 0x3c060001, 0x24c6dcbc, 0xc53023,
-0xc001751, 0xafb30010, 0x3c010001, 0xac223ec0,
+0x2a03821, 0x3c020000, 0x24425c5c, 0x1000000d,
+0x511024, 0x3c040001, 0x24845f68, 0x3c050001,
+0x24a5e494, 0x3c060001, 0x24c6e644, 0xc53023,
+0xc00178b, 0xafb30010, 0x3c010001, 0xac226f90,
0x511024, 0x21082, 0x5e1025, 0xae420048,
0x32c24000, 0x10400005, 0x27a70030, 0x3c020000,
-0x24425b74, 0x1000000e, 0x21100, 0x3c040001,
-0x24842f90, 0x3c050001, 0x24a5dcc4, 0x3c060001,
-0x24c6de1c, 0xc53023, 0x27a20034, 0xc001751,
-0xafa20010, 0x3c010001, 0xac223eb4, 0x21100,
+0x24425c5c, 0x1000000e, 0x21100, 0x3c040001,
+0x24845f80, 0x3c050001, 0x24a5e64c, 0x3c060001,
+0x24c6e7a4, 0xc53023, 0x27a20034, 0xc00178b,
+0xafa20010, 0x3c010001, 0xac226f84, 0x21100,
0x21182, 0x3c030800, 0x431025, 0xae420060,
-0x3c040001, 0x24842fa8, 0x3c050000, 0x24a57c80,
-0x3c060001, 0x24c680a4, 0xc53023, 0x27b10030,
-0x2203821, 0x27b30034, 0xc001751, 0xafb30010,
-0x3c1e0fff, 0x37deffff, 0x3c040001, 0x24842fb4,
-0x3c050000, 0x24a56318, 0x3c060000, 0x24c6645c,
-0xc53023, 0x2203821, 0x3c010001, 0xac223e88,
+0x3c040001, 0x24845f98, 0x3c050001, 0x24a581d0,
+0x3c060001, 0x24c685f0, 0xc53023, 0x27b10030,
+0x2203821, 0x27b30034, 0xc00178b, 0xafb30010,
+0x3c1e0fff, 0x37deffff, 0x3c040001, 0x24845fa4,
+0x3c050000, 0x24a56408, 0x3c060000, 0x24c66528,
+0xc53023, 0x2203821, 0x3c010001, 0xac226f58,
0x5e1024, 0x21082, 0x3c150800, 0x551025,
-0xae4200b8, 0xc001751, 0xafb30010, 0x3c040001,
-0x24842fc0, 0x3c050000, 0x24a56464, 0x3c060000,
-0x24c666dc, 0xc53023, 0x2203821, 0x3c010001,
-0xac223e7c, 0x5e1024, 0x21082, 0x551025,
-0xae4200e8, 0xc001751, 0xafb30010, 0x3c040001,
-0x24842fd8, 0x3c050000, 0x24a566e4, 0x3c060000,
-0x24c66814, 0xc53023, 0x2203821, 0x3c010001,
-0xac223e74, 0x5e1024, 0x21082, 0x551025,
-0xae4200c0, 0xc001751, 0xafb30010, 0x3c040001,
-0x24842ff0, 0x3c050001, 0x24a5efb0, 0x3c060001,
-0x24c6f088, 0xc53023, 0x2203821, 0x3c010001,
-0xac223e80, 0x5e1024, 0x21082, 0x551025,
-0xae4200c8, 0xc001751, 0xafb30010, 0x3c040001,
-0x24842ffc, 0x3c050001, 0x24a529f0, 0x3c060001,
-0x24c62a78, 0xc53023, 0x2203821, 0xaf420110,
-0xc001751, 0xafb30010, 0x3c040001, 0x2484300c,
-0x3c050001, 0x24a52a80, 0x3c060001, 0x24c62aac,
-0xc53023, 0x2203821, 0xaf420114, 0xc001751,
-0xafb30010, 0x3c040001, 0x24843018, 0x3c050001,
-0x24a5e820, 0x3c060001, 0x24c6ec24, 0xc53023,
-0x2203821, 0xaf420118, 0xc001751, 0xafb30010,
-0x3c010001, 0xac223ec4, 0x5e1024, 0x21082,
-0x551025, 0xc003cfb, 0xae4200d0, 0xc0039b4,
-0x0, 0xc002628, 0x0, 0xac000228,
+0xae4200b8, 0xc00178b, 0xafb30010, 0x3c040001,
+0x24845fb0, 0x3c050000, 0x24a56530, 0x3c060000,
+0x24c667a8, 0xc53023, 0x2203821, 0x3c010001,
+0xac226f4c, 0x5e1024, 0x21082, 0x551025,
+0xae4200e8, 0xc00178b, 0xafb30010, 0x3c040001,
+0x24845fc8, 0x3c050000, 0x24a567b0, 0x3c060000,
+0x24c668e0, 0xc53023, 0x2203821, 0x3c010001,
+0xac226f44, 0x5e1024, 0x21082, 0x551025,
+0xae4200c0, 0xc00178b, 0xafb30010, 0x3c040001,
+0x24845fe0, 0x3c050001, 0x24a5fa30, 0x3c060001,
+0x24c6fb08, 0xc53023, 0x2203821, 0x3c010001,
+0xac226f50, 0x5e1024, 0x21082, 0x551025,
+0xae4200c8, 0xc00178b, 0xafb30010, 0x3c040001,
+0x24845fec, 0x3c050001, 0x24a5c8dc, 0x3c060001,
+0x24c6c9c0, 0xc53023, 0x2203821, 0xaf420110,
+0xc00178b, 0xafb30010, 0x3c040001, 0x24845ffc,
+0x3c050001, 0x24a5c8b0, 0x3c060001, 0x24c6c8d4,
+0xc53023, 0x2203821, 0xaf420124, 0xc00178b,
+0xafb30010, 0x3c040001, 0x2484600c, 0x3c050001,
+0x24a55b10, 0x3c060001, 0x24c65b3c, 0xc53023,
+0x2203821, 0xaf420120, 0xaf420114, 0xc00178b,
+0xafb30010, 0x3c040001, 0x24846018, 0x3c050001,
+0x24a5f1f8, 0x3c060001, 0x24c6f614, 0xc53023,
+0x2203821, 0xaf420118, 0xc00178b, 0xafb30010,
+0x3c010001, 0xac226f94, 0x5e1024, 0x21082,
+0x551025, 0xc003f9b, 0xae4200d0, 0xc003c18,
+0x0, 0xc002784, 0x0, 0xac000228,
0xac00022c, 0x96e20450, 0x2442ffff, 0xaf420038,
0x96e20460, 0xaf420080, 0x32c24000, 0x14400003,
0x0, 0x96e20480, 0xaf420084, 0x96e70490,
0x50e00001, 0x24070800, 0x24e2ffff, 0xaf420088,
0xaf42007c, 0x24020800, 0x10e2000f, 0x32c24000,
0x10400003, 0x24020400, 0x10e2000b, 0x0,
-0x240e0001, 0x3c040001, 0x24843028, 0xa3ae003f,
+0x240e0001, 0x3c040001, 0x24846028, 0xa3ae003f,
0x96e60490, 0x24052170, 0x2c03821, 0xafa00010,
-0xc0029bb, 0xafa00014, 0x8f43012c, 0x8f44012c,
-0x24020001, 0xa34205b3, 0xaf430094, 0xaf440098,
+0xc002b17, 0xafa00014, 0x8f430138, 0x8f440138,
+0x24020001, 0xa34205c2, 0xaf430094, 0xaf440098,
0xafa00010, 0xafa00014, 0x8f460080, 0x8f470084,
-0x3c040001, 0x24843034, 0xc0029bb, 0x24052200,
-0xc002324, 0x3c110800, 0x3c1433d8, 0x3694cb58,
-0x3c020800, 0x34420080, 0x3c040001, 0x24843040,
-0x3c050000, 0x24a55bb8, 0x3c060000, 0x24c65bd4,
+0x3c040001, 0x24846034, 0xc002b17, 0x24052200,
+0xc002480, 0x3c110800, 0x3c1433d8, 0x3694cb58,
+0x3c020800, 0x34420080, 0x3c040001, 0x24846040,
+0x3c050000, 0x24a55ca0, 0x3c060000, 0x24c65cbc,
0xc53023, 0x27a70030, 0xaf820060, 0x2402ffff,
-0xaf820064, 0x27a20034, 0xc001751, 0xafa20010,
-0x3c010001, 0xac223e64, 0x21100, 0x21182,
-0x511025, 0xc0018a8, 0xae420000, 0x8f820240,
+0xaf820064, 0x27a20034, 0xc00178b, 0xafa20010,
+0x3c010001, 0xac226f34, 0x21100, 0x21182,
+0x511025, 0xc0018e4, 0xae420000, 0x8f820240,
0x3c030001, 0x431025, 0xaf820240, 0x3c020000,
0x24424034, 0xaf820244, 0xaf800240, 0x8f820060,
0x511024, 0x14400005, 0x3c030800, 0x8f820060,
-0x431024, 0x1040fffd, 0x0, 0xc0039c1,
+0x431024, 0x1040fffd, 0x0, 0xc003c25,
0x8821, 0x3c020100, 0xafa20020, 0x8f530018,
0x240200ff, 0x56620001, 0x26710001, 0x8c020228,
-0x1622000e, 0x1330c0, 0x8f42032c, 0x24420001,
-0xaf42032c, 0x8f42032c, 0x8c020228, 0x3c040001,
-0x24842d04, 0x3c050009, 0xafa00014, 0xafa20010,
+0x1622000e, 0x1330c0, 0x8f42033c, 0x24420001,
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
+0x24845cb4, 0x3c050009, 0xafa00014, 0xafa20010,
0x8fa60020, 0x1000003f, 0x34a50100, 0xd71021,
0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
-0xc01821, 0x8f440168, 0x8f45016c, 0x1021,
+0xc01821, 0x8f440178, 0x8f45017c, 0x1021,
0x24070004, 0xafa70010, 0xafb10014, 0x8f48000c,
0x24c604c0, 0x2e63021, 0xafa80018, 0x8f48010c,
0x24070008, 0xa32821, 0xa3482b, 0x822021,
0x100f809, 0x892021, 0x1440000b, 0x24070008,
0x8f820120, 0xafa20010, 0x8f820124, 0x3c040001,
-0x24842d0c, 0x3c050009, 0xafa20014, 0x8fa60020,
-0x1000001c, 0x34a50200, 0x8f440150, 0x8f450154,
+0x24845cbc, 0x3c050009, 0xafa20014, 0x8fa60020,
+0x1000001c, 0x34a50200, 0x8f440160, 0x8f450164,
0x8f43000c, 0xaf510018, 0x8f860120, 0x24020010,
0xafa20010, 0xafb10014, 0xafa30018, 0x8f42010c,
0x40f809, 0x24c6001c, 0x14400010, 0x0,
-0x8f420330, 0x24420001, 0xaf420330, 0x8f420330,
+0x8f420340, 0x24420001, 0xaf420340, 0x8f420340,
0x8f820120, 0xafa20010, 0x8f820124, 0x3c040001,
-0x24842d14, 0x3c050009, 0xafa20014, 0x8fa60020,
-0x34a50300, 0xc0029bb, 0x2603821, 0x8f4202d4,
-0x24420001, 0xaf4202d4, 0x8f4202d4, 0x93a2003f,
+0x24845cc4, 0x3c050009, 0xafa20014, 0x8fa60020,
+0x34a50300, 0xc002b17, 0x2603821, 0x8f4202e4,
+0x24420001, 0xaf4202e4, 0x8f4202e4, 0x93a2003f,
0x10400069, 0x3c020700, 0x34423000, 0xafa20028,
0x8f530018, 0x240200ff, 0x12620002, 0x8821,
0x26710001, 0x8c020228, 0x1622000e, 0x1330c0,
-0x8f42032c, 0x24420001, 0xaf42032c, 0x8f42032c,
-0x8c020228, 0x3c040001, 0x24842d04, 0x3c050009,
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
+0x8c020228, 0x3c040001, 0x24845cb4, 0x3c050009,
0xafa00014, 0xafa20010, 0x8fa60028, 0x1000003f,
0x34a50100, 0xd71021, 0x8fa30028, 0x8fa4002c,
-0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440168,
-0x8f45016c, 0x1021, 0x24070004, 0xafa70010,
+0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178,
+0x8f45017c, 0x1021, 0x24070004, 0xafa70010,
0xafb10014, 0x8f48000c, 0x24c604c0, 0x2e63021,
0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
0xa3482b, 0x822021, 0x100f809, 0x892021,
0x1440000b, 0x24070008, 0x8f820120, 0xafa20010,
-0x8f820124, 0x3c040001, 0x24842d0c, 0x3c050009,
+0x8f820124, 0x3c040001, 0x24845cbc, 0x3c050009,
0xafa20014, 0x8fa60028, 0x1000001c, 0x34a50200,
-0x8f440150, 0x8f450154, 0x8f43000c, 0xaf510018,
+0x8f440160, 0x8f450164, 0x8f43000c, 0xaf510018,
0x8f860120, 0x24020010, 0xafa20010, 0xafb10014,
0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c,
-0x14400010, 0x0, 0x8f420330, 0x24420001,
-0xaf420330, 0x8f420330, 0x8f820120, 0xafa20010,
-0x8f820124, 0x3c040001, 0x24842d14, 0x3c050009,
-0xafa20014, 0x8fa60028, 0x34a50300, 0xc0029bb,
-0x2603821, 0x8f4202e0, 0x24420001, 0xaf4202e0,
-0x8f4202e0, 0x3c040001, 0x24843050, 0xafa00010,
-0xafa00014, 0x8fa60028, 0x24052300, 0xc0029bb,
+0x14400010, 0x0, 0x8f420340, 0x24420001,
+0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010,
+0x8f820124, 0x3c040001, 0x24845cc4, 0x3c050009,
+0xafa20014, 0x8fa60028, 0x34a50300, 0xc002b17,
+0x2603821, 0x8f4202f0, 0x24420001, 0xaf4202f0,
+0x8f4202f0, 0x3c040001, 0x24846050, 0xafa00010,
+0xafa00014, 0x8fa60028, 0x24052300, 0xc002b17,
0x3821, 0x10000004, 0x0, 0x8c020264,
0x10400005, 0x0, 0x8f8200a0, 0x30420004,
0x1440fffa, 0x0, 0x8f820044, 0x34420004,
-0xaf820044, 0x8f4202f8, 0x24420001, 0xaf4202f8,
-0x8f4202f8, 0x8f8200d8, 0x8f8300d4, 0x431023,
+0xaf820044, 0x8f420308, 0x24420001, 0xaf420308,
+0x8f420308, 0x8f8200d8, 0x8f8300d4, 0x431023,
0x2442ff80, 0xaf420090, 0x8f420090, 0x2842ff81,
-0x10400006, 0x24020001, 0x8f420090, 0x8f430138,
+0x10400006, 0x24020001, 0x8f420090, 0x8f430144,
0x431021, 0xaf420090, 0x24020001, 0xaf42008c,
0x32c20008, 0x10400006, 0x0, 0x8f820214,
0x3c038100, 0x3042ffff, 0x431025, 0xaf820214,
-0x3c020001, 0x8c423d84, 0x30420001, 0x10400009,
-0x0, 0x3c040001, 0x2484305c, 0x3c050000,
-0x24a56c24, 0x3c060000, 0x24c670cc, 0x10000008,
-0xc53023, 0x3c040001, 0x2484306c, 0x3c050000,
-0x24a5681c, 0x3c060000, 0x24c66c1c, 0xc53023,
-0x27a70030, 0x27a20034, 0xc001751, 0xafa20010,
-0x3c010001, 0xac223e78, 0x3c020001, 0x8c423e78,
-0x3c030800, 0x21100, 0x21182, 0x431025,
-0xae420040, 0x8f8200a0, 0xafa20010, 0x8f8200b0,
-0xafa20014, 0x8f86005c, 0x8f87011c, 0x3c040001,
-0x2484307c, 0x3c010001, 0xac363e50, 0x3c010001,
-0xac203e40, 0x3c010001, 0xac3c3e38, 0x3c010001,
-0xac3b3e68, 0x3c010001, 0xac373e6c, 0x3c010001,
-0xac3a3e4c, 0xc0029bb, 0x24052400, 0x8f820200,
-0xafa20010, 0x8f820220, 0xafa20014, 0x8f860044,
-0x8f870050, 0x3c040001, 0x24843088, 0xc0029bb,
-0x24052500, 0x8f830060, 0x74100b, 0x242000a,
-0x200f821, 0x0, 0xd, 0x8fbf0058,
-0x8fbe0054, 0x8fb50050, 0x8fb3004c, 0x8fb20048,
-0x8fb10044, 0x8fb00040, 0x3e00008, 0x27bd0060,
-0x27bdffe0, 0x3c040001, 0x24843094, 0x24052600,
-0x3021, 0x3821, 0xafbf0018, 0xafa00010,
-0xc0029bb, 0xafa00014, 0x8fbf0018, 0x3e00008,
-0x27bd0020, 0x3e00008, 0x0, 0x3e00008,
+0x3c030001, 0x8c636e14, 0x30620002, 0x10400009,
+0x30620001, 0x3c040001, 0x2484605c, 0x3c050000,
+0x24a56cf0, 0x3c060000, 0x24c67168, 0x10000012,
+0xc53023, 0x10400009, 0x0, 0x3c040001,
+0x2484606c, 0x3c050000, 0x24a57170, 0x3c060000,
+0x24c67618, 0x10000008, 0xc53023, 0x3c040001,
+0x2484607c, 0x3c050000, 0x24a568e8, 0x3c060000,
+0x24c66ce8, 0xc53023, 0x27a70030, 0x27a20034,
+0xc00178b, 0xafa20010, 0x3c010001, 0xac226f48,
+0x3c020001, 0x8c426f48, 0x3c030800, 0x21100,
+0x21182, 0x431025, 0xae420040, 0x8f8200a0,
+0xafa20010, 0x8f8200b0, 0xafa20014, 0x8f86005c,
+0x8f87011c, 0x3c040001, 0x2484608c, 0x3c010001,
+0xac366f20, 0x3c010001, 0xac206f10, 0x3c010001,
+0xac3c6f08, 0x3c010001, 0xac3b6f38, 0x3c010001,
+0xac376f3c, 0x3c010001, 0xac3a6f1c, 0xc002b17,
+0x24052400, 0x8f820200, 0xafa20010, 0x8f820220,
+0xafa20014, 0x8f860044, 0x8f870050, 0x3c040001,
+0x24846098, 0xc002b17, 0x24052500, 0x8f830060,
+0x74100b, 0x242000a, 0x200f821, 0x0,
+0xd, 0x8fbf0058, 0x8fbe0054, 0x8fb50050,
+0x8fb3004c, 0x8fb20048, 0x8fb10044, 0x8fb00040,
+0x3e00008, 0x27bd0060, 0x27bdffe0, 0x3c040001,
+0x248460a4, 0x24052600, 0x3021, 0x3821,
+0xafbf0018, 0xafa00010, 0xc002b17, 0xafa00014,
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x3e00008,
+0x0, 0x3e00008, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x3e00008, 0x0,
-0x3e00008, 0x0, 0x27bdfde0, 0x27a50018,
-0x3c04dead, 0x3484beef, 0xafbf0218, 0x8f820150,
-0x3c03001f, 0x3463ffff, 0xafa40018, 0xa22823,
-0xa32824, 0x8ca20000, 0x1044000a, 0x0,
-0xafa50010, 0x8ca20000, 0xafa20014, 0x8f860150,
-0x8f870250, 0x3c040001, 0x2484309c, 0xc0029bb,
-0x24052700, 0x8fbf0218, 0x3e00008, 0x27bd0220,
-0x27bdffe0, 0x3c06abba, 0x34c6babe, 0xafb00018,
-0x3c100004, 0x3c07007f, 0x34e7ffff, 0xafbf001c,
-0x102840, 0x8e040000, 0x8ca30000, 0xaca00000,
-0xae060000, 0x8ca20000, 0xaca30000, 0x10460005,
-0xae040000, 0xa08021, 0xf0102b, 0x1040fff5,
-0x102840, 0x3c040001, 0x248430a8, 0x24052800,
-0x2003021, 0x3821, 0xafa00010, 0xc0029bb,
-0xafa00014, 0x2001021, 0x8fbf001c, 0x8fb00018,
-0x3e00008, 0x27bd0020, 0x8c020224, 0x3047003f,
-0x10e00010, 0x803021, 0x2821, 0x24030020,
-0xe31024, 0x10400002, 0x63042, 0xa62821,
-0x31842, 0x1460fffb, 0xe31024, 0x2402f000,
-0xa22824, 0x3402ffff, 0x45102b, 0x14400003,
-0x3c020001, 0x10000008, 0x3c020001, 0x3442ffff,
-0x851823, 0x43102b, 0x14400003, 0xa01021,
-0x3c02fffe, 0x821021, 0x3e00008, 0x0,
-0x27bdffd0, 0xafb50028, 0x8fb50040, 0xafb20020,
-0xa09021, 0xafb1001c, 0x24c60003, 0xafbf002c,
-0xafb30024, 0xafb00018, 0x8ea20000, 0x2403fffc,
-0xc38024, 0x50102b, 0x1440001b, 0xe08821,
-0x8e330000, 0xafb00010, 0x8ea20000, 0xafa20014,
-0x8e270000, 0x24053000, 0xc0029bb, 0x2403021,
-0x8e230000, 0x702021, 0x64102b, 0x10400007,
-0x2402821, 0x8ca20000, 0xac620000, 0x24630004,
-0x64102b, 0x1440fffb, 0x24a50004, 0x8ea20000,
-0x501023, 0xaea20000, 0x8e220000, 0x501021,
-0x1000000b, 0xae220000, 0x2402002d, 0xa0820000,
-0xafb00010, 0x8ea20000, 0x2409821, 0xafa20014,
-0x8e270000, 0x24053100, 0xc0029bb, 0x2603021,
-0x2601021, 0x8fbf002c, 0x8fb50028, 0x8fb30024,
-0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008,
-0x27bd0030, 0x27bdffe8, 0x3c1cc000, 0x3c05fffe,
-0x3c030001, 0x8c633e30, 0x3c040001, 0x8c843e3c,
-0x34a5bf08, 0x24021ffc, 0x3c010001, 0xac223cd0,
-0x3c0200c0, 0x3c010001, 0xac223cd4, 0x3c020020,
-0xafbf0010, 0x3c0100c0, 0xac201ffc, 0x431023,
-0x441023, 0x245bb000, 0x365b821, 0x3c1d0001,
-0x8fbd3ccc, 0x3a0f021, 0x3c0400c0, 0x34840200,
-0x3c1a00c0, 0x3c0300c0, 0x346307b8, 0x24021dfc,
-0x3c010001, 0xac223cd0, 0x24021844, 0x3c010001,
-0xac243cd4, 0x3c010001, 0xac223cd0, 0x3c010001,
-0xac233cd4, 0xc0017bb, 0x375a0200, 0x8fbf0010,
-0x3e00008, 0x27bd0018, 0x27bdffc8, 0x3c040001,
-0x248430b4, 0x24053200, 0x3c020001, 0x8c423cd0,
-0x3c030001, 0x8c633cd4, 0x3021, 0x3603821,
-0xafbf0030, 0xafb3002c, 0xafb20028, 0xafb10024,
-0xafb00020, 0xafa2001c, 0xafa30018, 0xafb70010,
-0xc0029bb, 0xafba0014, 0xc0018c2, 0x0,
-0x8f820240, 0x34420004, 0xaf820240, 0x24020001,
-0xaf420000, 0x3c020001, 0x571021, 0x904240f4,
-0x10400092, 0x2403fffc, 0x3c100001, 0x2610a673,
-0x3c120001, 0x2652a24c, 0x2121023, 0x438024,
-0x8fa3001c, 0x3c040001, 0x248430c0, 0x70102b,
-0x1440001a, 0x27b30018, 0x8fb10018, 0x24053000,
-0x2403021, 0xafb00010, 0xafa30014, 0xc0029bb,
-0x2203821, 0x8fa30018, 0x702021, 0x64102b,
-0x10400007, 0x2403021, 0x8cc20000, 0xac620000,
-0x24630004, 0x64102b, 0x1440fffb, 0x24c60004,
-0x8fa2001c, 0x501023, 0xafa2001c, 0x8e620000,
-0x501021, 0x1000000a, 0xae620000, 0x2408821,
-0x24053100, 0xafb00010, 0xafa30014, 0x8fa70018,
-0x2203021, 0x2402002d, 0xc0029bb, 0xa0820000,
-0x24070020, 0x8fa3001c, 0x3c040001, 0x248430dc,
-0x24120020, 0x3c010001, 0xac313e5c, 0x2c620020,
-0x1440001d, 0x27b10018, 0x8fb00018, 0x24053000,
-0x3c060001, 0x24c63ef0, 0xafa70010, 0xafa30014,
-0xc0029bb, 0x2003821, 0x8fa30018, 0x3c040001,
-0x24843ef0, 0x24650020, 0x65102b, 0x10400007,
-0x0, 0x8c820000, 0xac620000, 0x24630004,
-0x65102b, 0x1440fffb, 0x24840004, 0x8fa2001c,
-0x521023, 0xafa2001c, 0x8e220000, 0x521021,
-0x1000000b, 0xae220000, 0x3c100001, 0x26103ef0,
-0x24053100, 0xafa70010, 0xafa30014, 0x8fa70018,
-0x2003021, 0x2402002d, 0xc0029bb, 0xa0820000,
-0x24070020, 0x3c040001, 0x248430f0, 0x8fa3001c,
-0x24120020, 0x3c010001, 0xac303e90, 0x2c620020,
-0x1440001d, 0x27b10018, 0x8fb00018, 0x24053000,
-0x3c060001, 0x24c63f10, 0xafa70010, 0xafa30014,
-0xc0029bb, 0x2003821, 0x8fa30018, 0x3c040001,
-0x24843f10, 0x24650020, 0x65102b, 0x10400007,
-0x0, 0x8c820000, 0xac620000, 0x24630004,
-0x65102b, 0x1440fffb, 0x24840004, 0x8fa2001c,
-0x521023, 0xafa2001c, 0x8e220000, 0x521021,
-0x1000000b, 0xae220000, 0x3c100001, 0x26103f10,
-0x24053100, 0xafa70010, 0xafa30014, 0x8fa70018,
-0x2003021, 0x2402002d, 0xc0029bb, 0xa0820000,
-0x3c010001, 0x10000031, 0xac303e8c, 0x3c100000,
-0x26107c73, 0x3c120000, 0x26527af0, 0x2121023,
-0x438024, 0x8fa3001c, 0x3c040001, 0x24843104,
-0x70102b, 0x1440001a, 0x27b30018, 0x8fb10018,
-0x24053000, 0x2403021, 0xafb00010, 0xafa30014,
-0xc0029bb, 0x2203821, 0x8fa30018, 0x702021,
-0x64102b, 0x10400007, 0x2403021, 0x8cc20000,
+0x3e00008, 0x0, 0x3e00008, 0x0,
+0x27bdfde0, 0x27a50018, 0x3c04dead, 0x3484beef,
+0xafbf0218, 0x8f820150, 0x3c03001f, 0x3463ffff,
+0xafa40018, 0xa22823, 0xa32824, 0x8ca20000,
+0x1044000a, 0x0, 0xafa50010, 0x8ca20000,
+0xafa20014, 0x8f860150, 0x8f870250, 0x3c040001,
+0x248460ac, 0xc002b17, 0x24052700, 0x8fbf0218,
+0x3e00008, 0x27bd0220, 0x27bdffe0, 0x3c06abba,
+0x34c6babe, 0xafb00018, 0x3c100004, 0x3c07007f,
+0x34e7ffff, 0xafbf001c, 0x102840, 0x8e040000,
+0x8ca30000, 0xaca00000, 0xae060000, 0x8ca20000,
+0xaca30000, 0x10460005, 0xae040000, 0xa08021,
+0xf0102b, 0x1040fff5, 0x102840, 0x3c040001,
+0x248460b8, 0x24052800, 0x2003021, 0x3821,
+0xafa00010, 0xc002b17, 0xafa00014, 0x2001021,
+0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020,
+0x8c020224, 0x3047003f, 0x10e00010, 0x803021,
+0x2821, 0x24030020, 0xe31024, 0x10400002,
+0x63042, 0xa62821, 0x31842, 0x1460fffb,
+0xe31024, 0x2402f000, 0xa22824, 0x3402ffff,
+0x45102b, 0x14400003, 0x3c020001, 0x10000008,
+0x3c020001, 0x3442ffff, 0x851823, 0x43102b,
+0x14400003, 0xa01021, 0x3c02fffe, 0x821021,
+0x3e00008, 0x0, 0x27bdffd0, 0xafb50028,
+0x8fb50040, 0xafb20020, 0xa09021, 0xafb1001c,
+0x24c60003, 0xafbf002c, 0xafb30024, 0xafb00018,
+0x8ea20000, 0x2403fffc, 0xc38024, 0x50102b,
+0x1440001b, 0xe08821, 0x8e330000, 0xafb00010,
+0x8ea20000, 0xafa20014, 0x8e270000, 0x24053000,
+0xc002b17, 0x2403021, 0x8e230000, 0x702021,
+0x64102b, 0x10400007, 0x2402821, 0x8ca20000,
0xac620000, 0x24630004, 0x64102b, 0x1440fffb,
-0x24c60004, 0x8fa2001c, 0x501023, 0xafa2001c,
-0x8e620000, 0x501021, 0x1000000a, 0xae620000,
-0x2408821, 0x24053100, 0xafb00010, 0xafa30014,
-0x8fa70018, 0x2203021, 0x2402002d, 0xc0029bb,
-0xa0820000, 0x3c010001, 0xac313e5c, 0x3c030001,
-0x8c633e5c, 0x24020400, 0x60f809, 0xaf820070,
-0x8fbf0030, 0x8fb3002c, 0x8fb20028, 0x8fb10024,
-0x8fb00020, 0x3e00008, 0x27bd0038, 0x8f820040,
+0x24a50004, 0x8ea20000, 0x501023, 0xaea20000,
+0x8e220000, 0x501021, 0x1000000b, 0xae220000,
+0x2402002d, 0xa0820000, 0xafb00010, 0x8ea20000,
+0x2409821, 0xafa20014, 0x8e270000, 0x24053100,
+0xc002b17, 0x2603021, 0x2601021, 0x8fbf002c,
+0x8fb50028, 0x8fb30024, 0x8fb20020, 0x8fb1001c,
+0x8fb00018, 0x3e00008, 0x27bd0030, 0x27bdffe8,
+0x3c1cc000, 0x3c05fffe, 0x3c030001, 0x8c636f00,
+0x3c040001, 0x8c846f0c, 0x34a5bf08, 0x24021ffc,
+0x3c010001, 0xac226d50, 0x3c0200c0, 0x3c010001,
+0xac226d54, 0x3c020020, 0xafbf0010, 0x3c0100c0,
+0xac201ffc, 0x431023, 0x441023, 0x245bb000,
+0x365b821, 0x3c1d0001, 0x8fbd6d4c, 0x3a0f021,
+0x3c0400c0, 0x34840200, 0x3c1a00c0, 0x3c0300c0,
+0x346307c8, 0x24021dfc, 0x3c010001, 0xac226d50,
+0x24021834, 0x3c010001, 0xac246d54, 0x3c010001,
+0xac226d50, 0x3c010001, 0xac236d54, 0xc0017f5,
+0x375a0200, 0x8fbf0010, 0x3e00008, 0x27bd0018,
+0x27bdffc8, 0x3c040001, 0x248460c4, 0x24053200,
+0x3c020001, 0x8c426d50, 0x3c030001, 0x8c636d54,
+0x3021, 0x3603821, 0xafbf0030, 0xafb3002c,
+0xafb20028, 0xafb10024, 0xafb00020, 0xafa2001c,
+0xafa30018, 0xafb70010, 0xc002b17, 0xafba0014,
+0xc0018fe, 0x0, 0x8f820240, 0x34420004,
+0xaf820240, 0x24020001, 0xaf420000, 0x3c020001,
+0x571021, 0x904240f4, 0x10400092, 0x2403fffc,
+0x3c100001, 0x2610abe3, 0x3c120001, 0x2652a7bc,
+0x2121023, 0x438024, 0x8fa3001c, 0x3c040001,
+0x248460d0, 0x70102b, 0x1440001a, 0x27b30018,
+0x8fb10018, 0x24053000, 0x2403021, 0xafb00010,
+0xafa30014, 0xc002b17, 0x2203821, 0x8fa30018,
+0x702021, 0x64102b, 0x10400007, 0x2403021,
+0x8cc20000, 0xac620000, 0x24630004, 0x64102b,
+0x1440fffb, 0x24c60004, 0x8fa2001c, 0x501023,
+0xafa2001c, 0x8e620000, 0x501021, 0x1000000a,
+0xae620000, 0x2408821, 0x24053100, 0xafb00010,
+0xafa30014, 0x8fa70018, 0x2203021, 0x2402002d,
+0xc002b17, 0xa0820000, 0x24070020, 0x8fa3001c,
+0x3c040001, 0x248460ec, 0x24120020, 0x3c010001,
+0xac316f2c, 0x2c620020, 0x1440001d, 0x27b10018,
+0x8fb00018, 0x24053000, 0x3c060001, 0x24c66fd0,
+0xafa70010, 0xafa30014, 0xc002b17, 0x2003821,
+0x8fa30018, 0x3c040001, 0x24846fd0, 0x24650020,
+0x65102b, 0x10400007, 0x0, 0x8c820000,
+0xac620000, 0x24630004, 0x65102b, 0x1440fffb,
+0x24840004, 0x8fa2001c, 0x521023, 0xafa2001c,
+0x8e220000, 0x521021, 0x1000000b, 0xae220000,
+0x3c100001, 0x26106fd0, 0x24053100, 0xafa70010,
+0xafa30014, 0x8fa70018, 0x2003021, 0x2402002d,
+0xc002b17, 0xa0820000, 0x24070020, 0x3c040001,
+0x24846100, 0x8fa3001c, 0x24120020, 0x3c010001,
+0xac306f60, 0x2c620020, 0x1440001d, 0x27b10018,
+0x8fb00018, 0x24053000, 0x3c060001, 0x24c66ff0,
+0xafa70010, 0xafa30014, 0xc002b17, 0x2003821,
+0x8fa30018, 0x3c040001, 0x24846ff0, 0x24650020,
+0x65102b, 0x10400007, 0x0, 0x8c820000,
+0xac620000, 0x24630004, 0x65102b, 0x1440fffb,
+0x24840004, 0x8fa2001c, 0x521023, 0xafa2001c,
+0x8e220000, 0x521021, 0x1000000b, 0xae220000,
+0x3c100001, 0x26106ff0, 0x24053100, 0xafa70010,
+0xafa30014, 0x8fa70018, 0x2003021, 0x2402002d,
+0xc002b17, 0xa0820000, 0x3c010001, 0x10000031,
+0xac306f5c, 0x3c100001, 0x261081bf, 0x3c120001,
+0x2652803c, 0x2121023, 0x438024, 0x8fa3001c,
+0x3c040001, 0x24846114, 0x70102b, 0x1440001a,
+0x27b30018, 0x8fb10018, 0x24053000, 0x2403021,
+0xafb00010, 0xafa30014, 0xc002b17, 0x2203821,
+0x8fa30018, 0x702021, 0x64102b, 0x10400007,
+0x2403021, 0x8cc20000, 0xac620000, 0x24630004,
+0x64102b, 0x1440fffb, 0x24c60004, 0x8fa2001c,
+0x501023, 0xafa2001c, 0x8e620000, 0x501021,
+0x1000000a, 0xae620000, 0x2408821, 0x24053100,
+0xafb00010, 0xafa30014, 0x8fa70018, 0x2203021,
+0x2402002d, 0xc002b17, 0xa0820000, 0x3c010001,
+0xac316f2c, 0x3c030001, 0x8c636f2c, 0x24020400,
+0x60f809, 0xaf820070, 0x8fbf0030, 0x8fb3002c,
+0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008,
+0x27bd0038, 0x0, 0x0, 0x8f820040,
0x3c03f000, 0x431024, 0x3c036000, 0x14430006,
0x0, 0x8f820050, 0x2403ff80, 0x431024,
0x34420055, 0xaf820050, 0x8f820054, 0x244203e8,
0xaf820058, 0x240201f4, 0xaf4200e0, 0x24020004,
-0xaf4200e8, 0x24020002, 0xaf4001a0, 0xaf4000e4,
+0xaf4200e8, 0x24020002, 0xaf4001b0, 0xaf4000e4,
0xaf4200dc, 0xaf4000d8, 0xaf4000d4, 0x3e00008,
0xaf4000d0, 0x8f820054, 0x24420005, 0x3e00008,
0xaf820078, 0x27bdffe8, 0xafbf0010, 0x8f820054,
0x244203e8, 0xaf820058, 0x3c020800, 0x2c21024,
0x10400004, 0x3c02f7ff, 0x3442ffff, 0x2c2b024,
-0x36940040, 0x3c020001, 0x8c423d98, 0x10400020,
-0x3c020200, 0x934305b1, 0x10600007, 0x282a025,
-0xa34005b1, 0x8f820220, 0x3c0308ff, 0x3463fffb,
-0x431024, 0xaf820220, 0x3c020001, 0x8c423ec8,
-0x10400016, 0x3c020200, 0x3c020001, 0x8c423e14,
-0x14400012, 0x3c020200, 0x3c020001, 0x8c423d84,
-0x30420001, 0x1440000d, 0x3c020200, 0x8f830224,
-0x3c020001, 0x8c425f8c, 0x10620008, 0x3c020200,
-0xc003b0b, 0x0, 0x10000004, 0x3c020200,
-0xc003e84, 0x0, 0x3c020200, 0x2c21024,
-0x10400003, 0x0, 0xc001de0, 0x0,
-0x8f4200d8, 0x8f4300dc, 0x24420001, 0xaf4200d8,
-0x43102b, 0x14400003, 0x0, 0xaf4000d8,
-0x36940080, 0x8c030238, 0x1060000c, 0x0,
-0x8f4201a0, 0x244203e8, 0xaf4201a0, 0x43102b,
-0x14400006, 0x0, 0x934205b6, 0x14400003,
-0x0, 0xc001c35, 0x0, 0x8fbf0010,
-0x3e00008, 0x27bd0018, 0x3e00008, 0x0,
-0x27bdffd8, 0xafbf0020, 0x8f43002c, 0x8f420038,
-0x10620059, 0x0, 0x3c020001, 0x571021,
-0x904240f0, 0x10400026, 0x24070008, 0x8f440160,
-0x8f450164, 0x8f48000c, 0x8f860120, 0x24020020,
-0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c,
-0x40f809, 0x24c6001c, 0x14400011, 0x24020001,
-0x3c010001, 0x370821, 0xa02240f0, 0x8f820124,
-0xafa20010, 0x8f820128, 0x3c040001, 0x248431a8,
-0xafa20014, 0x8f46002c, 0x8f870120, 0x3c050009,
-0xc0029bb, 0x34a50900, 0x1000005c, 0x0,
-0x8f4202f0, 0x24420001, 0xaf4202f0, 0x8f4202f0,
-0x8f42002c, 0xa34005b2, 0x10000027, 0xaf420038,
-0x8f440160, 0x8f450164, 0x8f43002c, 0x8f48000c,
-0x8f860120, 0x24020080, 0xafa20010, 0xafa30014,
-0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c,
-0x14400011, 0x24020001, 0x3c010001, 0x370821,
-0xa02240f1, 0x8f820124, 0xafa20010, 0x8f820128,
-0x3c040001, 0x248431b4, 0xafa20014, 0x8f46002c,
-0x8f870120, 0x3c050009, 0xc0029bb, 0x34a51100,
-0x10000036, 0x0, 0x8f4202f0, 0x8f43002c,
-0x24420001, 0xaf4202f0, 0x8f4202f0, 0x24020001,
-0xa34205b2, 0xaf430038, 0x3c010001, 0x370821,
-0xa02040f1, 0x3c010001, 0x370821, 0xa02040f0,
-0x10000026, 0xaf400034, 0x934205b2, 0x1040001d,
-0x0, 0xa34005b2, 0x8f820040, 0x30420001,
-0x14400008, 0x2021, 0x8c030104, 0x24020001,
-0x50620005, 0x24040001, 0x8c020264, 0x10400003,
-0x801021, 0x24040001, 0x801021, 0x10400006,
-0x0, 0x8f4202fc, 0x24420001, 0xaf4202fc,
-0x10000008, 0x8f4202fc, 0x8f820044, 0x34420004,
-0xaf820044, 0x8f4202f8, 0x24420001, 0xaf4202f8,
-0x8f4202f8, 0x3c010001, 0x370821, 0xa02040f0,
-0x3c010001, 0x370821, 0xa02040f1, 0x8f420000,
-0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
-0x1040fffd, 0x0, 0x10000005, 0x0,
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
-0x8f820060, 0x3c03ff7f, 0x3463ffff, 0x431024,
-0xaf820060, 0x8f420000, 0x10400003, 0x0,
-0x10000002, 0xaf80004c, 0xaf800048, 0x8fbf0020,
-0x3e00008, 0x27bd0028, 0x3e00008, 0x0,
-0x27bdffd8, 0xafbf0020, 0x8f430044, 0x8f42007c,
-0x10620029, 0x24070008, 0x8f440158, 0x8f45015c,
-0x8f48000c, 0x8f860120, 0x24020040, 0xafa20010,
+0x36940040, 0x3c020001, 0x8c426e28, 0x10400017,
+0x3c020200, 0x3c030001, 0x8c636f98, 0x10600016,
+0x282a025, 0x3c020001, 0x8c426ec4, 0x14400012,
+0x3c020200, 0x3c020001, 0x8c426e14, 0x30420003,
+0x1440000d, 0x3c020200, 0x8f830224, 0x3c020002,
+0x8c42906c, 0x10620008, 0x3c020200, 0xc003d87,
+0x0, 0x10000004, 0x3c020200, 0xc004161,
+0x0, 0x3c020200, 0x2c21024, 0x10400003,
+0x0, 0xc001f33, 0x0, 0x8f4200d8,
+0x8f4300dc, 0x24420001, 0xaf4200d8, 0x43102b,
+0x14400003, 0x0, 0xaf4000d8, 0x36940080,
+0x8c030238, 0x1060000c, 0x0, 0x8f4201b0,
+0x244203e8, 0xaf4201b0, 0x43102b, 0x14400006,
+0x0, 0x934205c5, 0x14400003, 0x0,
+0xc001d88, 0x0, 0x8fbf0010, 0x3e00008,
+0x27bd0018, 0x3e00008, 0x0, 0x27bdffd8,
+0xafbf0020, 0x8f43002c, 0x8f420038, 0x10620059,
+0x0, 0x3c020001, 0x571021, 0x904240f0,
+0x10400026, 0x24070008, 0x8f440170, 0x8f450174,
+0x8f48000c, 0x8f860120, 0x24020020, 0xafa20010,
0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809,
0x24c6001c, 0x14400011, 0x24020001, 0x3c010001,
-0x370821, 0xa02240f2, 0x8f820124, 0xafa20010,
-0x8f820128, 0x3c040001, 0x248431bc, 0xafa20014,
-0x8f460044, 0x8f870120, 0x3c050009, 0xc0029bb,
-0x34a51300, 0x1000000f, 0x0, 0x8f4202f4,
-0x24420001, 0xaf4202f4, 0x8f4202f4, 0x8f420044,
-0xaf42007c, 0x3c010001, 0x370821, 0xa02040f2,
-0x10000004, 0xaf400078, 0x3c010001, 0x370821,
-0xa02040f2, 0x8f420000, 0x10400007, 0x0,
-0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
-0x10000005, 0x0, 0xaf800048, 0x8f820048,
-0x1040fffd, 0x0, 0x8f820060, 0x3c03feff,
-0x3463ffff, 0x431024, 0xaf820060, 0x8f420000,
-0x10400003, 0x0, 0x10000002, 0xaf80004c,
-0xaf800048, 0x8fbf0020, 0x3e00008, 0x27bd0028,
-0x3e00008, 0x0, 0x3c020001, 0x8c423d98,
-0x27bdffa8, 0xafbf0050, 0xafbe004c, 0xafb50048,
-0xafb30044, 0xafb20040, 0xafb1003c, 0xafb00038,
-0x104000d5, 0x8f900044, 0x8f4200d0, 0x24430001,
-0x2842000b, 0x144000e4, 0xaf4300d0, 0x8f420004,
-0x30420002, 0x1440009c, 0xaf4000d0, 0x8f420004,
-0x3c030001, 0x8c633d88, 0x34420002, 0xaf420004,
+0x370821, 0xa02240f0, 0x8f820124, 0xafa20010,
+0x8f820128, 0x3c040001, 0x248461b8, 0xafa20014,
+0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b17,
+0x34a50900, 0x1000005c, 0x0, 0x8f420300,
+0x24420001, 0xaf420300, 0x8f420300, 0x8f42002c,
+0xa34005c1, 0x10000027, 0xaf420038, 0x8f440170,
+0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120,
+0x24020080, 0xafa20010, 0xafa30014, 0xafa80018,
+0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011,
+0x24020001, 0x3c010001, 0x370821, 0xa02240f1,
+0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001,
+0x248461c4, 0xafa20014, 0x8f46002c, 0x8f870120,
+0x3c050009, 0xc002b17, 0x34a51100, 0x10000036,
+0x0, 0x8f420300, 0x8f43002c, 0x24420001,
+0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1,
+0xaf430038, 0x3c010001, 0x370821, 0xa02040f1,
+0x3c010001, 0x370821, 0xa02040f0, 0x10000026,
+0xaf400034, 0x934205c1, 0x1040001d, 0x0,
+0xa34005c1, 0x8f820040, 0x30420001, 0x14400008,
+0x2021, 0x8c030104, 0x24020001, 0x50620005,
+0x24040001, 0x8c020264, 0x10400003, 0x801021,
+0x24040001, 0x801021, 0x10400006, 0x0,
+0x8f42030c, 0x24420001, 0xaf42030c, 0x10000008,
+0x8f42030c, 0x8f820044, 0x34420004, 0xaf820044,
+0x8f420308, 0x24420001, 0xaf420308, 0x8f420308,
+0x3c010001, 0x370821, 0xa02040f0, 0x3c010001,
+0x370821, 0xa02040f1, 0x8f420000, 0x10400007,
+0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd,
+0x0, 0x10000005, 0x0, 0xaf800048,
+0x8f820048, 0x1040fffd, 0x0, 0x8f820060,
+0x3c03ff7f, 0x3463ffff, 0x431024, 0xaf820060,
+0x8f420000, 0x10400003, 0x0, 0x10000002,
+0xaf80004c, 0xaf800048, 0x8fbf0020, 0x3e00008,
+0x27bd0028, 0x3e00008, 0x0, 0x27bdffd8,
+0xafbf0020, 0x8f430044, 0x8f42007c, 0x10620029,
+0x24070008, 0x8f440168, 0x8f45016c, 0x8f48000c,
+0x8f860120, 0x24020040, 0xafa20010, 0xafa30014,
+0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c,
+0x14400011, 0x24020001, 0x3c010001, 0x370821,
+0xa02240f2, 0x8f820124, 0xafa20010, 0x8f820128,
+0x3c040001, 0x248461cc, 0xafa20014, 0x8f460044,
+0x8f870120, 0x3c050009, 0xc002b17, 0x34a51300,
+0x1000000f, 0x0, 0x8f420304, 0x24420001,
+0xaf420304, 0x8f420304, 0x8f420044, 0xaf42007c,
+0x3c010001, 0x370821, 0xa02040f2, 0x10000004,
+0xaf400078, 0x3c010001, 0x370821, 0xa02040f2,
+0x8f420000, 0x10400007, 0x0, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x3c03feff, 0x3463ffff,
+0x431024, 0xaf820060, 0x8f420000, 0x10400003,
+0x0, 0x10000002, 0xaf80004c, 0xaf800048,
+0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3e00008,
+0x0, 0x3c020001, 0x8c426e28, 0x27bdffa8,
+0xafbf0050, 0xafbe004c, 0xafb50048, 0xafb30044,
+0xafb20040, 0xafb1003c, 0xafb00038, 0x104000d5,
+0x8f900044, 0x8f4200d0, 0x24430001, 0x2842000b,
+0x144000e4, 0xaf4300d0, 0x8f420004, 0x30420002,
+0x1440009c, 0xaf4000d0, 0x8f420004, 0x3c030001,
+0x8c636e18, 0x34420002, 0xaf420004, 0x24020001,
+0x14620003, 0x3c020600, 0x10000002, 0x34423000,
+0x34421000, 0xafa20020, 0x8f4a0018, 0xafaa0034,
+0x27aa0020, 0xafaa002c, 0x8faa0034, 0x240200ff,
+0x11420002, 0x1821, 0x25430001, 0x8c020228,
+0x609821, 0x1662000e, 0x3c050009, 0x8f42033c,
+0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228,
+0x8fa70034, 0x3c040001, 0x2484619c, 0xafa00014,
+0xafa20010, 0x8fa60020, 0x10000070, 0x34a50500,
+0x8faa0034, 0xa38c0, 0xf71021, 0x8fa30020,
+0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054,
+0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9,
+0x1040001b, 0xa821, 0xe09021, 0x265e04c0,
+0x8f440178, 0x8f45017c, 0x2401821, 0x240a0004,
+0xafaa0010, 0xafb30014, 0x8f48000c, 0x1021,
+0x2fe3021, 0xafa80018, 0x8f48010c, 0x24070008,
+0xa32821, 0xa3482b, 0x822021, 0x100f809,
+0x892021, 0x54400006, 0x24150001, 0x8f820054,
+0x2221023, 0x2c4203e9, 0x1440ffe9, 0x0,
+0x32a200ff, 0x54400018, 0xaf530018, 0x8f420378,
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
+0x8faa002c, 0x8fa70034, 0xafa20010, 0x8f820124,
+0x3c040001, 0x248461a8, 0xafa20014, 0x8d460000,
+0x3c050009, 0x10000035, 0x34a50600, 0x8f420308,
+0x24150001, 0x24420001, 0xaf420308, 0x8f420308,
+0x1000001e, 0x32a200ff, 0x8f830054, 0x8f820054,
+0x247103e8, 0x2221023, 0x2c4203e9, 0x10400016,
+0xa821, 0x3c1e0020, 0x24120010, 0x8f42000c,
+0x8f440160, 0x8f450164, 0x8f860120, 0xafb20010,
+0xafb30014, 0x5e1025, 0xafa20018, 0x8f42010c,
+0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe3,
+0x0, 0x8f820054, 0x2221023, 0x2c4203e9,
+0x1440ffee, 0x0, 0x32a200ff, 0x14400011,
+0x3c050009, 0x8f420378, 0x24420001, 0xaf420378,
+0x8f420378, 0x8f820120, 0x8faa002c, 0x8fa70034,
+0xafa20010, 0x8f820124, 0x3c040001, 0x248461b0,
+0xafa20014, 0x8d460000, 0x34a50700, 0xc002b17,
+0x0, 0x8f4202ec, 0x24420001, 0xaf4202ec,
+0x8f4202ec, 0x8f420004, 0x30420001, 0x50400029,
+0x36100040, 0x3c020400, 0x2c21024, 0x10400013,
+0x2404ffdf, 0x8f420250, 0x8f430254, 0x8f4401b4,
+0x14640006, 0x36100040, 0x8f420270, 0x8f430274,
+0x8f4401b8, 0x10640007, 0x2402ffdf, 0x8f420250,
+0x8f430254, 0x8f440270, 0x8f450274, 0x10000012,
+0x3a100020, 0x1000002b, 0x2028024, 0x8f420250,
+0x8f430254, 0x8f4501b4, 0x14650006, 0x2048024,
+0x8f420270, 0x8f430274, 0x8f4401b8, 0x50640021,
+0x36100040, 0x8f420250, 0x8f430254, 0x8f440270,
+0x8f450274, 0x3a100040, 0xaf4301b4, 0x10000019,
+0xaf4501b8, 0x8f4200d4, 0x24430001, 0x10000011,
+0x28420033, 0x8f420004, 0x30420001, 0x10400009,
+0x3c020400, 0x2c21024, 0x10400004, 0x2402ffdf,
+0x2028024, 0x1000000b, 0x36100040, 0x10000009,
+0x36100060, 0x8f4200d4, 0x36100040, 0x24430001,
+0x284201f5, 0x14400003, 0xaf4300d4, 0xaf4000d4,
+0x3a100020, 0xaf900044, 0x2402ff7f, 0x282a024,
+0x8fbf0050, 0x8fbe004c, 0x8fb50048, 0x8fb30044,
+0x8fb20040, 0x8fb1003c, 0x8fb00038, 0x3e00008,
+0x27bd0058, 0x3e00008, 0x0, 0x3c020001,
+0x8c426e28, 0x27bdffb0, 0xafbf0048, 0xafbe0044,
+0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034,
+0x104000c7, 0xafb00030, 0x8f4200d0, 0x24430001,
+0x2842000b, 0x144000da, 0xaf4300d0, 0x8f420004,
+0x30420002, 0x14400097, 0xaf4000d0, 0x8f420004,
+0x3c030001, 0x8c636e18, 0x34420002, 0xaf420004,
0x24020001, 0x14620003, 0x3c020600, 0x10000002,
-0x34423000, 0x34421000, 0xafa20020, 0x8f4a0018,
-0xafaa0034, 0x27aa0020, 0xafaa002c, 0x8faa0034,
-0x240200ff, 0x11420002, 0x1821, 0x25430001,
-0x8c020228, 0x609821, 0x1662000e, 0x3c050009,
-0x8f42032c, 0x24420001, 0xaf42032c, 0x8f42032c,
-0x8c020228, 0x8fa70034, 0x3c040001, 0x2484318c,
-0xafa00014, 0xafa20010, 0x8fa60020, 0x10000070,
-0x34a50500, 0x8faa0034, 0xa38c0, 0xf71021,
+0x34423000, 0x34421000, 0xafa20020, 0x1821,
+0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002,
+0xafaa002c, 0x27c30001, 0x8c020228, 0x609021,
+0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
+0x2484619c, 0x3c050009, 0xafa00014, 0xafa20010,
+0x8fa60020, 0x1000006d, 0x34a50500, 0xf71021,
0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
-0x8f830054, 0x8f820054, 0x247103e8, 0x2221023,
-0x2c4203e9, 0x1040001b, 0xa821, 0xe09021,
-0x265e04c0, 0x8f440168, 0x8f45016c, 0x2401821,
-0x240a0004, 0xafaa0010, 0xafb30014, 0x8f48000c,
-0x1021, 0x2fe3021, 0xafa80018, 0x8f48010c,
+0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
+0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
+0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
+0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c,
+0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
0x24070008, 0xa32821, 0xa3482b, 0x822021,
-0x100f809, 0x892021, 0x54400006, 0x24150001,
-0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffe9,
-0x0, 0x32a200ff, 0x54400018, 0xaf530018,
-0x8f420368, 0x24420001, 0xaf420368, 0x8f420368,
-0x8f820120, 0x8faa002c, 0x8fa70034, 0xafa20010,
-0x8f820124, 0x3c040001, 0x24843198, 0xafa20014,
-0x8d460000, 0x3c050009, 0x10000035, 0x34a50600,
-0x8f4202f8, 0x24150001, 0x24420001, 0xaf4202f8,
-0x8f4202f8, 0x1000001e, 0x32a200ff, 0x8f830054,
-0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9,
-0x10400016, 0xa821, 0x3c1e0020, 0x24120010,
-0x8f42000c, 0x8f440150, 0x8f450154, 0x8f860120,
-0xafb20010, 0xafb30014, 0x5e1025, 0xafa20018,
+0x100f809, 0x892021, 0x54400006, 0x24130001,
+0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
+0x0, 0x326200ff, 0x54400017, 0xaf520018,
+0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
+0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124,
+0x3c040001, 0x248461a8, 0x3c050009, 0xafa20014,
+0x8d460000, 0x10000035, 0x34a50600, 0x8f420308,
+0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
+0x1000001e, 0x326200ff, 0x8f830054, 0x8f820054,
+0x247003e8, 0x2021023, 0x2c4203e9, 0x10400016,
+0x9821, 0x3c150020, 0x24110010, 0x8f42000c,
+0x8f440160, 0x8f450164, 0x8f860120, 0xafb10010,
+0xafb20014, 0x551025, 0xafa20018, 0x8f42010c,
+0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe3,
+0x0, 0x8f820054, 0x2021023, 0x2c4203e9,
+0x1440ffee, 0x0, 0x326200ff, 0x14400011,
+0x0, 0x8f420378, 0x24420001, 0xaf420378,
+0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010,
+0x8f820124, 0x3c040001, 0x248461b0, 0x3c050009,
+0xafa20014, 0x8d460000, 0x34a50700, 0xc002b17,
+0x3c03821, 0x8f4202ec, 0x24420001, 0xaf4202ec,
+0x8f4202ec, 0x8f420004, 0x30420001, 0x10400018,
+0x24040001, 0x8f420250, 0x8f430254, 0x8f4501b4,
+0x3c010001, 0x14650006, 0xa0246d71, 0x8f420270,
+0x8f430274, 0x8f4401b8, 0x10640021, 0x0,
+0x8f420250, 0x8f430254, 0x3c040001, 0x90846d70,
+0x8f460270, 0x8f470274, 0x38840001, 0xaf4301b4,
+0xaf4701b8, 0x3c010001, 0x10000025, 0xa0246d70,
+0x8f4200d4, 0x3c010001, 0xa0206d70, 0x24430001,
+0x28420033, 0x1440001e, 0xaf4300d4, 0x3c020001,
+0x90426d71, 0xaf4000d4, 0x10000017, 0x38420001,
+0x8f420004, 0x30420001, 0x10400008, 0x0,
+0xc00567e, 0x2021, 0x3c010001, 0xa0206d71,
+0x3c010001, 0x1000000e, 0xa0206d70, 0x8f4200d4,
+0x3c010001, 0xa0206d70, 0x24430001, 0x284201f5,
+0x14400007, 0xaf4300d4, 0x3c020001, 0x90426d71,
+0xaf4000d4, 0x421026, 0x3c010001, 0xa0226d71,
+0x3c030001, 0x8c636e18, 0x24020002, 0x1462000c,
+0x3c030002, 0x3c030001, 0x90636d71, 0x24020001,
+0x5462001f, 0x2021, 0x3c020001, 0x90426d70,
+0x1443001b, 0x24040005, 0x10000019, 0x24040006,
+0x3c020002, 0x8c429074, 0x431024, 0x1040000b,
+0x24020001, 0x3c030001, 0x90636d71, 0x54620010,
+0x2021, 0x3c020001, 0x90426d70, 0x1443000c,
+0x24040003, 0x1000000a, 0x24040004, 0x3c030001,
+0x90636d71, 0x14620006, 0x2021, 0x3c020001,
+0x90426d70, 0x24040001, 0x50440001, 0x24040002,
+0xc00567e, 0x0, 0x2402ff7f, 0x282a024,
+0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c,
+0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008,
+0x27bd0050, 0x3e00008, 0x0, 0x3c020001,
+0x8c426e28, 0x27bdffb0, 0xafbf0048, 0xafbe0044,
+0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034,
+0x104000de, 0xafb00030, 0x8f4200d0, 0x3c040001,
+0x8c846e18, 0x24430001, 0x2842000b, 0xaf4400e8,
+0x144000fe, 0xaf4300d0, 0x8f420004, 0x30420002,
+0x14400095, 0xaf4000d0, 0x8f420004, 0x34420002,
+0xaf420004, 0x24020001, 0x14820003, 0x3c020600,
+0x10000002, 0x34423000, 0x34421000, 0xafa20020,
+0x1821, 0x8f5e0018, 0x27aa0020, 0x240200ff,
+0x13c20002, 0xafaa002c, 0x27c30001, 0x8c020228,
+0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c,
+0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228,
+0x3c040001, 0x2484619c, 0x3c050009, 0xafa00014,
+0xafa20010, 0x8fa60020, 0x1000006d, 0x34a50500,
+0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0,
+0xac4404c4, 0x8f830054, 0x8f820054, 0x247003e8,
+0x2021023, 0x2c4203e9, 0x1040001b, 0x9821,
+0xe08821, 0x263504c0, 0x8f440178, 0x8f45017c,
+0x2201821, 0x240a0004, 0xafaa0010, 0xafb20014,
+0x8f48000c, 0x1021, 0x2f53021, 0xafa80018,
+0x8f48010c, 0x24070008, 0xa32821, 0xa3482b,
+0x822021, 0x100f809, 0x892021, 0x54400006,
+0x24130001, 0x8f820054, 0x2021023, 0x2c4203e9,
+0x1440ffe9, 0x0, 0x326200ff, 0x54400017,
+0xaf520018, 0x8f420378, 0x24420001, 0xaf420378,
+0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010,
+0x8f820124, 0x3c040001, 0x248461a8, 0x3c050009,
+0xafa20014, 0x8d460000, 0x10000035, 0x34a50600,
+0x8f420308, 0x24130001, 0x24420001, 0xaf420308,
+0x8f420308, 0x1000001e, 0x326200ff, 0x8f830054,
+0x8f820054, 0x247003e8, 0x2021023, 0x2c4203e9,
+0x10400016, 0x9821, 0x3c150020, 0x24110010,
+0x8f42000c, 0x8f440160, 0x8f450164, 0x8f860120,
+0xafb10010, 0xafb20014, 0x551025, 0xafa20018,
0x8f42010c, 0x24070008, 0x40f809, 0x24c6001c,
-0x1440ffe3, 0x0, 0x8f820054, 0x2221023,
-0x2c4203e9, 0x1440ffee, 0x0, 0x32a200ff,
-0x14400011, 0x3c050009, 0x8f420368, 0x24420001,
-0xaf420368, 0x8f420368, 0x8f820120, 0x8faa002c,
-0x8fa70034, 0xafa20010, 0x8f820124, 0x3c040001,
-0x248431a0, 0xafa20014, 0x8d460000, 0x34a50700,
-0xc0029bb, 0x0, 0x8f4202dc, 0x24420001,
-0xaf4202dc, 0x8f4202dc, 0x8f420004, 0x30420001,
-0x50400029, 0x36100040, 0x3c020400, 0x2c21024,
-0x10400013, 0x2404ffdf, 0x8f420240, 0x8f430244,
-0x8f4401a4, 0x14640006, 0x36100040, 0x8f420260,
-0x8f430264, 0x8f4401a8, 0x10640007, 0x2402ffdf,
-0x8f420240, 0x8f430244, 0x8f440260, 0x8f450264,
-0x10000012, 0x3a100020, 0x1000002b, 0x2028024,
-0x8f420240, 0x8f430244, 0x8f4501a4, 0x14650006,
-0x2048024, 0x8f420260, 0x8f430264, 0x8f4401a8,
-0x50640021, 0x36100040, 0x8f420240, 0x8f430244,
-0x8f440260, 0x8f450264, 0x3a100040, 0xaf4301a4,
-0x10000019, 0xaf4501a8, 0x8f4200d4, 0x24430001,
-0x10000011, 0x28420033, 0x8f420004, 0x30420001,
-0x10400009, 0x3c020400, 0x2c21024, 0x10400004,
-0x2402ffdf, 0x2028024, 0x1000000b, 0x36100040,
-0x10000009, 0x36100060, 0x8f4200d4, 0x36100040,
-0x24430001, 0x284201f5, 0x14400003, 0xaf4300d4,
-0xaf4000d4, 0x3a100020, 0xaf900044, 0x2402ff7f,
-0x282a024, 0x8fbf0050, 0x8fbe004c, 0x8fb50048,
-0x8fb30044, 0x8fb20040, 0x8fb1003c, 0x8fb00038,
-0x3e00008, 0x27bd0058, 0x3e00008, 0x0,
-0x3c020001, 0x8c423d98, 0x27bdffb0, 0xafbf0048,
-0xafbe0044, 0xafb50040, 0xafb3003c, 0xafb20038,
-0xafb10034, 0x104000de, 0xafb00030, 0x8f4200d0,
-0x3c040001, 0x8c843d88, 0x24430001, 0x2842000b,
-0xaf4400e8, 0x144000fe, 0xaf4300d0, 0x8f420004,
-0x30420002, 0x14400095, 0xaf4000d0, 0x8f420004,
-0x34420002, 0xaf420004, 0x24020001, 0x14820003,
-0x3c020600, 0x10000002, 0x34423000, 0x34421000,
-0xafa20020, 0x1821, 0x8f5e0018, 0x27aa0020,
-0x240200ff, 0x13c20002, 0xafaa002c, 0x27c30001,
-0x8c020228, 0x609021, 0x1642000e, 0x1e38c0,
-0x8f42032c, 0x24420001, 0xaf42032c, 0x8f42032c,
-0x8c020228, 0x3c040001, 0x2484318c, 0x3c050009,
-0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006d,
-0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024,
-0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054,
-0x247003e8, 0x2021023, 0x2c4203e9, 0x1040001b,
-0x9821, 0xe08821, 0x263504c0, 0x8f440168,
-0x8f45016c, 0x2201821, 0x240a0004, 0xafaa0010,
-0xafb20014, 0x8f48000c, 0x1021, 0x2f53021,
-0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
-0xa3482b, 0x822021, 0x100f809, 0x892021,
-0x54400006, 0x24130001, 0x8f820054, 0x2021023,
-0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff,
-0x54400017, 0xaf520018, 0x8f420368, 0x24420001,
-0xaf420368, 0x8f420368, 0x8f820120, 0x8faa002c,
-0xafa20010, 0x8f820124, 0x3c040001, 0x24843198,
-0x3c050009, 0xafa20014, 0x8d460000, 0x10000035,
-0x34a50600, 0x8f4202f8, 0x24130001, 0x24420001,
-0xaf4202f8, 0x8f4202f8, 0x1000001e, 0x326200ff,
+0x1440ffe3, 0x0, 0x8f820054, 0x2021023,
+0x2c4203e9, 0x1440ffee, 0x0, 0x326200ff,
+0x14400011, 0x0, 0x8f420378, 0x24420001,
+0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c,
+0xafa20010, 0x8f820124, 0x3c040001, 0x248461b0,
+0x3c050009, 0xafa20014, 0x8d460000, 0x34a50700,
+0xc002b17, 0x3c03821, 0x8f4202ec, 0x24420001,
+0xaf4202ec, 0x8f4202ec, 0x8f420004, 0x30420001,
+0x10400033, 0x3c020400, 0x2c21024, 0x10400017,
+0x0, 0x934205c0, 0x8f440250, 0x8f450254,
+0x8f4301b4, 0x34420020, 0x14a30006, 0xa34205c0,
+0x8f420270, 0x8f430274, 0x8f4401b8, 0x10640008,
+0x0, 0x8f420250, 0x8f430254, 0x934405c0,
+0x8f460270, 0x8f470274, 0x10000016, 0x38840040,
+0x934205c0, 0x10000048, 0x304200bf, 0x934205c0,
+0x8f440250, 0x8f450254, 0x8f4301b4, 0x304200bf,
+0x14a30006, 0xa34205c0, 0x8f420270, 0x8f430274,
+0x8f4401b8, 0x1064000b, 0x0, 0x8f420250,
+0x8f430254, 0x934405c0, 0x8f460270, 0x8f470274,
+0x38840020, 0xaf4301b4, 0xaf4701b8, 0x10000033,
+0xa34405c0, 0x934205c0, 0x1000002f, 0x34420020,
+0x934205c0, 0x8f4300d4, 0x34420020, 0xa34205c0,
+0x24620001, 0x10000023, 0x28630033, 0x8f4200e4,
+0x8f4300e0, 0x24420001, 0xaf4200e4, 0x43102a,
+0x14400006, 0x24030001, 0x8f4200e8, 0x14430002,
+0xaf4000e4, 0x24030004, 0xaf4300e8, 0x8f420004,
+0x30420001, 0x1040000d, 0x3c020400, 0x2c21024,
+0x10400007, 0x0, 0x934205c0, 0x34420040,
+0xa34205c0, 0x934205c0, 0x1000000f, 0x304200df,
+0x934205c0, 0x1000000c, 0x34420060, 0x934205c0,
+0x8f4300d4, 0x34420020, 0xa34205c0, 0x24620001,
+0x286300fb, 0x14600005, 0xaf4200d4, 0x934205c0,
+0xaf4000d4, 0x38420040, 0xa34205c0, 0x934205c0,
+0x8f4300e8, 0x3042007f, 0xa34205c0, 0x24020001,
+0x14620005, 0x0, 0x934405c0, 0x42102,
+0x10000003, 0x348400f0, 0x934405c0, 0x3484000f,
+0xc005664, 0x0, 0x2402ff7f, 0x282a024,
+0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c,
+0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008,
+0x27bd0050, 0x3e00008, 0x0, 0x27bdffb0,
+0x274401c0, 0x26e30028, 0x24650400, 0x65102b,
+0xafbf0048, 0xafbe0044, 0xafb50040, 0xafb3003c,
+0xafb20038, 0xafb10034, 0x10400007, 0xafb00030,
+0x8c820000, 0xac620000, 0x24630004, 0x65102b,
+0x1440fffb, 0x24840004, 0x8c020080, 0xaee20044,
+0x8c0200c0, 0xaee20040, 0x8c020084, 0xaee20030,
+0x8c020084, 0xaee2023c, 0x8c020088, 0xaee20240,
+0x8c02008c, 0xaee20244, 0x8c020090, 0xaee20248,
+0x8c020094, 0xaee2024c, 0x8c020098, 0xaee20250,
+0x8c02009c, 0xaee20254, 0x8c0200a0, 0xaee20258,
+0x8c0200a4, 0xaee2025c, 0x8c0200a8, 0xaee20260,
+0x8c0200ac, 0xaee20264, 0x8c0200b0, 0xaee20268,
+0x8c0200b4, 0xaee2026c, 0x8c0200b8, 0xaee20270,
+0x8c0200bc, 0x24040001, 0xaee20274, 0xaee00034,
+0x41080, 0x571021, 0x8ee30034, 0x8c42023c,
+0x24840001, 0x621821, 0x2c82000f, 0xaee30034,
+0x1440fff8, 0x41080, 0x8c0200cc, 0xaee20048,
+0x8c0200d0, 0xaee2004c, 0x8c0200e0, 0xaee201f8,
+0x8c0200e4, 0xaee201fc, 0x8c0200e8, 0xaee20200,
+0x8c0200ec, 0xaee20204, 0x8c0200f0, 0xaee20208,
+0x8ee400c0, 0x8ee500c4, 0x8c0200fc, 0x45102b,
+0x1040000b, 0x0, 0x8ee200c0, 0x8ee300c4,
+0x24040001, 0x24050000, 0x651821, 0x65302b,
+0x441021, 0x461021, 0xaee200c0, 0xaee300c4,
+0x8c0200fc, 0x8ee400c0, 0x8ee500c4, 0x2408ffff,
+0x24090000, 0x401821, 0x1021, 0x882024,
+0xa92824, 0x822025, 0xa32825, 0xaee400c0,
+0xaee500c4, 0x8ee400d0, 0x8ee500d4, 0x8c0200f4,
+0x45102b, 0x1040000b, 0x0, 0x8ee200d0,
+0x8ee300d4, 0x24040001, 0x24050000, 0x651821,
+0x65302b, 0x441021, 0x461021, 0xaee200d0,
+0xaee300d4, 0x8c0200f4, 0x8ee400d0, 0x8ee500d4,
+0x401821, 0x1021, 0x882024, 0xa92824,
+0x822025, 0xa32825, 0xaee400d0, 0xaee500d4,
+0x8ee400c8, 0x8ee500cc, 0x8c0200f8, 0x45102b,
+0x1040000b, 0x0, 0x8ee200c8, 0x8ee300cc,
+0x24040001, 0x24050000, 0x651821, 0x65302b,
+0x441021, 0x461021, 0xaee200c8, 0xaee300cc,
+0x8c0200f8, 0x8ee400c8, 0x8ee500cc, 0x401821,
+0x1021, 0x882024, 0xa92824, 0x822025,
+0xa32825, 0x24020008, 0xaee400c8, 0xaee500cc,
+0xafa20010, 0xafa00014, 0x8f42000c, 0x8c040208,
+0x8c05020c, 0xafa20018, 0x8f42010c, 0x26e60028,
+0x40f809, 0x24070400, 0x104000f0, 0x3c020400,
+0xafa20020, 0x934205c6, 0x10400089, 0x1821,
+0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002,
+0xafaa002c, 0x27c30001, 0x8c020228, 0x609021,
+0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
+0x2484619c, 0x3c050009, 0xafa00014, 0xafa20010,
+0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021,
+0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
-0x2c4203e9, 0x10400016, 0x9821, 0x3c150020,
-0x24110010, 0x8f42000c, 0x8f440150, 0x8f450154,
-0x8f860120, 0xafb10010, 0xafb20014, 0x551025,
+0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
+0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
+0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c,
+0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
+0x24070008, 0xa32821, 0xa3482b, 0x822021,
+0x100f809, 0x892021, 0x54400006, 0x24130001,
+0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
+0x0, 0x326200ff, 0x54400017, 0xaf520018,
+0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
+0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124,
+0x3c040001, 0x248461a8, 0x3c050009, 0xafa20014,
+0x8d460000, 0x10000033, 0x34a50600, 0x8f420308,
+0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
+0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054,
+0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014,
+0x9821, 0x24110010, 0x8f42000c, 0x8f440160,
+0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014,
0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
-0x24c6001c, 0x1440ffe3, 0x0, 0x8f820054,
-0x2021023, 0x2c4203e9, 0x1440ffee, 0x0,
-0x326200ff, 0x14400011, 0x0, 0x8f420368,
-0x24420001, 0xaf420368, 0x8f420368, 0x8f820120,
+0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054,
+0x2021023, 0x2c4203e9, 0x1440ffef, 0x0,
+0x326200ff, 0x54400012, 0x24020001, 0x8f420378,
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
0x8faa002c, 0xafa20010, 0x8f820124, 0x3c040001,
-0x248431a0, 0x3c050009, 0xafa20014, 0x8d460000,
-0x34a50700, 0xc0029bb, 0x3c03821, 0x8f4202dc,
-0x24420001, 0xaf4202dc, 0x8f4202dc, 0x8f420004,
-0x30420001, 0x10400033, 0x3c020400, 0x2c21024,
-0x10400017, 0x0, 0x934205b0, 0x8f440240,
-0x8f450244, 0x8f4301a4, 0x34420020, 0x14a30006,
-0xa34205b0, 0x8f420260, 0x8f430264, 0x8f4401a8,
-0x10640008, 0x0, 0x8f420240, 0x8f430244,
-0x934405b0, 0x8f460260, 0x8f470264, 0x10000016,
-0x38840040, 0x934205b0, 0x10000048, 0x304200bf,
-0x934205b0, 0x8f440240, 0x8f450244, 0x8f4301a4,
-0x304200bf, 0x14a30006, 0xa34205b0, 0x8f420260,
-0x8f430264, 0x8f4401a8, 0x1064000b, 0x0,
-0x8f420240, 0x8f430244, 0x934405b0, 0x8f460260,
-0x8f470264, 0x38840020, 0xaf4301a4, 0xaf4701a8,
-0x10000033, 0xa34405b0, 0x934205b0, 0x1000002f,
-0x34420020, 0x934205b0, 0x8f4300d4, 0x34420020,
-0xa34205b0, 0x24620001, 0x10000023, 0x28630033,
-0x8f4200e4, 0x8f4300e0, 0x24420001, 0xaf4200e4,
-0x43102a, 0x14400006, 0x24030001, 0x8f4200e8,
-0x14430002, 0xaf4000e4, 0x24030004, 0xaf4300e8,
-0x8f420004, 0x30420001, 0x1040000d, 0x3c020400,
-0x2c21024, 0x10400007, 0x0, 0x934205b0,
-0x34420040, 0xa34205b0, 0x934205b0, 0x1000000f,
-0x304200df, 0x934205b0, 0x1000000c, 0x34420060,
-0x934205b0, 0x8f4300d4, 0x34420020, 0xa34205b0,
-0x24620001, 0x286300fb, 0x14600005, 0xaf4200d4,
-0x934205b0, 0xaf4000d4, 0x38420040, 0xa34205b0,
-0x934205b0, 0x8f4300e8, 0x3042007f, 0xa34205b0,
-0x24020001, 0x14620005, 0x0, 0x934405b0,
-0x42102, 0x10000003, 0x348400f0, 0x934405b0,
-0x3484000f, 0xc004a60, 0x0, 0x2402ff7f,
-0x282a024, 0x8fbf0048, 0x8fbe0044, 0x8fb50040,
+0x248461b0, 0x3c050009, 0xafa20014, 0x8d460000,
+0x34a50700, 0xc002b17, 0x3c03821, 0x1021,
+0x1440005b, 0x24020001, 0x10000065, 0x0,
+0x8f510018, 0x240200ff, 0x12220002, 0x8021,
+0x26300001, 0x8c020228, 0x1602000e, 0x1130c0,
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
+0x8c020228, 0x3c040001, 0x24846184, 0x3c050009,
+0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f,
+0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024,
+0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178,
+0x8f45017c, 0x1021, 0x24070004, 0xafa70010,
+0xafb00014, 0x8f48000c, 0x24c604c0, 0x2e63021,
+0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
+0xa3482b, 0x822021, 0x100f809, 0x892021,
+0x1440000b, 0x24070008, 0x8f820120, 0xafa20010,
+0x8f820124, 0x3c040001, 0x2484618c, 0x3c050009,
+0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200,
+0x8f440160, 0x8f450164, 0x8f43000c, 0xaf500018,
+0x8f860120, 0x24020010, 0xafa20010, 0xafb00014,
+0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c,
+0x54400011, 0x24020001, 0x8f420340, 0x24420001,
+0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010,
+0x8f820124, 0x3c040001, 0x24846194, 0x3c050009,
+0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b17,
+0x2203821, 0x1021, 0x1040000d, 0x24020001,
+0x8f4202e8, 0xa34005c6, 0xaf4001b0, 0x24420001,
+0xaf4202e8, 0x8f4202e8, 0x8ee20150, 0x24420001,
+0xaee20150, 0x10000003, 0x8ee20150, 0x24020001,
+0xa34205c6, 0x8fbf0048, 0x8fbe0044, 0x8fb50040,
0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030,
-0x3e00008, 0x27bd0050, 0x3e00008, 0x0,
-0x27bdffb0, 0x274401b0, 0x26e30028, 0x24650400,
-0x65102b, 0xafbf0048, 0xafbe0044, 0xafb50040,
-0xafb3003c, 0xafb20038, 0xafb10034, 0x10400007,
-0xafb00030, 0x8c820000, 0xac620000, 0x24630004,
-0x65102b, 0x1440fffb, 0x24840004, 0x8c020080,
-0xaee20044, 0x8c0200c0, 0xaee20040, 0x8c020084,
-0xaee20030, 0x8c020084, 0xaee2023c, 0x8c020088,
-0xaee20240, 0x8c02008c, 0xaee20244, 0x8c020090,
-0xaee20248, 0x8c020094, 0xaee2024c, 0x8c020098,
-0xaee20250, 0x8c02009c, 0xaee20254, 0x8c0200a0,
-0xaee20258, 0x8c0200a4, 0xaee2025c, 0x8c0200a8,
-0xaee20260, 0x8c0200ac, 0xaee20264, 0x8c0200b0,
-0xaee20268, 0x8c0200b4, 0xaee2026c, 0x8c0200b8,
-0xaee20270, 0x8c0200bc, 0x24040001, 0xaee20274,
-0xaee00034, 0x41080, 0x571021, 0x8ee30034,
-0x8c42023c, 0x24840001, 0x621821, 0x2c82000f,
-0xaee30034, 0x1440fff8, 0x41080, 0x8c0200cc,
-0xaee20048, 0x8c0200d0, 0xaee2004c, 0x8c0200e0,
-0xaee201f8, 0x8c0200e4, 0xaee201fc, 0x8c0200e8,
-0xaee20200, 0x8c0200ec, 0xaee20204, 0x8c0200f0,
-0xaee20208, 0x8ee400c0, 0x8ee500c4, 0x8c0200fc,
-0x45102b, 0x1040000b, 0x0, 0x8ee200c0,
-0x8ee300c4, 0x24040001, 0x24050000, 0x651821,
-0x65302b, 0x441021, 0x461021, 0xaee200c0,
-0xaee300c4, 0x8c0200fc, 0x8ee400c0, 0x8ee500c4,
-0x2408ffff, 0x24090000, 0x401821, 0x1021,
-0x882024, 0xa92824, 0x822025, 0xa32825,
-0xaee400c0, 0xaee500c4, 0x8ee400d0, 0x8ee500d4,
-0x8c0200f4, 0x45102b, 0x1040000b, 0x0,
-0x8ee200d0, 0x8ee300d4, 0x24040001, 0x24050000,
-0x651821, 0x65302b, 0x441021, 0x461021,
-0xaee200d0, 0xaee300d4, 0x8c0200f4, 0x8ee400d0,
-0x8ee500d4, 0x401821, 0x1021, 0x882024,
-0xa92824, 0x822025, 0xa32825, 0xaee400d0,
-0xaee500d4, 0x8ee400c8, 0x8ee500cc, 0x8c0200f8,
-0x45102b, 0x1040000b, 0x0, 0x8ee200c8,
-0x8ee300cc, 0x24040001, 0x24050000, 0x651821,
-0x65302b, 0x441021, 0x461021, 0xaee200c8,
-0xaee300cc, 0x8c0200f8, 0x8ee400c8, 0x8ee500cc,
-0x401821, 0x1021, 0x882024, 0xa92824,
-0x822025, 0xa32825, 0x24020008, 0xaee400c8,
-0xaee500cc, 0xafa20010, 0xafa00014, 0x8f42000c,
+0x3e00008, 0x27bd0050, 0x27bdffd8, 0xafbf0020,
+0x8f8200b0, 0x30420004, 0x10400068, 0x0,
+0x8f430128, 0x8f820104, 0x14620005, 0x0,
+0x8f430130, 0x8f8200b4, 0x10620006, 0x0,
+0x8f820104, 0xaf420128, 0x8f8200b4, 0x1000005b,
+0xaf420130, 0x8f8200b0, 0x3c030080, 0x431024,
+0x1040000d, 0x0, 0x8f82011c, 0x34420002,
+0xaf82011c, 0x8f8200b0, 0x2403fffb, 0x431024,
+0xaf8200b0, 0x8f82011c, 0x2403fffd, 0x431024,
+0x1000004a, 0xaf82011c, 0x8f430128, 0x8f820104,
+0x14620005, 0x0, 0x8f430130, 0x8f8200b4,
+0x10620010, 0x0, 0x8f820104, 0xaf420128,
+0x8f8200b4, 0x8f430128, 0xaf420130, 0xafa30010,
+0x8f420130, 0x3c040001, 0x248461d4, 0xafa20014,
+0x8f86011c, 0x8f8700b0, 0x3c050005, 0x10000031,
+0x34a50900, 0x8f420128, 0xafa20010, 0x8f420130,
+0x3c040001, 0x248461e0, 0xafa20014, 0x8f86011c,
+0x8f8700b0, 0x3c050005, 0xc002b17, 0x34a51000,
+0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830104,
+0x8f8200b0, 0x34420001, 0xaf8200b0, 0x24020008,
+0xaf830104, 0xafa20010, 0xafa00014, 0x8f42000c,
0x8c040208, 0x8c05020c, 0xafa20018, 0x8f42010c,
-0x26e60028, 0x40f809, 0x24070400, 0x104000f0,
-0x3c020400, 0xafa20020, 0x934205b7, 0x10400089,
-0x1821, 0x8f5e0018, 0x27aa0020, 0x240200ff,
-0x13c20002, 0xafaa002c, 0x27c30001, 0x8c020228,
-0x609021, 0x1642000e, 0x1e38c0, 0x8f42032c,
-0x24420001, 0xaf42032c, 0x8f42032c, 0x8c020228,
-0x3c040001, 0x2484318c, 0x3c050009, 0xafa00014,
+0x26e60028, 0x40f809, 0x24070400, 0x8f82011c,
+0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201dc,
+0x24420001, 0xaee201dc, 0x8ee201dc, 0x8f420128,
+0xafa20010, 0x8f420130, 0x3c040001, 0x248461ec,
+0xafa20014, 0x8f86011c, 0x8f8700b0, 0x3c050005,
+0x34a51100, 0xc002b17, 0x0, 0x8f8200a0,
+0x30420004, 0x10400069, 0x0, 0x8f43012c,
+0x8f820124, 0x14620005, 0x0, 0x8f430134,
+0x8f8200a4, 0x10620006, 0x0, 0x8f820124,
+0xaf42012c, 0x8f8200a4, 0x1000005c, 0xaf420134,
+0x8f8200a0, 0x3c030080, 0x431024, 0x1040000d,
+0x0, 0x8f82011c, 0x34420002, 0xaf82011c,
+0x8f8200a0, 0x2403fffb, 0x431024, 0xaf8200a0,
+0x8f82011c, 0x2403fffd, 0x431024, 0x1000004b,
+0xaf82011c, 0x8f43012c, 0x8f820124, 0x14620005,
+0x0, 0x8f430134, 0x8f8200a4, 0x10620010,
+0x0, 0x8f820124, 0xaf42012c, 0x8f8200a4,
+0x8f43012c, 0xaf420134, 0xafa30010, 0x8f420134,
+0x3c040001, 0x248461f8, 0xafa20014, 0x8f86011c,
+0x8f8700a0, 0x3c050005, 0x10000032, 0x34a51200,
+0x8f42012c, 0xafa20010, 0x8f420134, 0x3c040001,
+0x24846204, 0xafa20014, 0x8f86011c, 0x8f8700a0,
+0x3c050005, 0xc002b17, 0x34a51300, 0x8f82011c,
+0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0,
+0x34420001, 0xaf8200a0, 0x24020080, 0xaf830124,
+0xafa20010, 0xafa00014, 0x8f420014, 0x8c040208,
+0x8c05020c, 0xafa20018, 0x8f420108, 0x3c060001,
+0x24c66f54, 0x40f809, 0x24070004, 0x8f82011c,
+0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201dc,
+0x24420001, 0xaee201dc, 0x8ee201dc, 0x8f42012c,
+0xafa20010, 0x8f420134, 0x3c040001, 0x24846210,
+0xafa20014, 0x8f86011c, 0x8f8700a0, 0x3c050005,
+0x34a51400, 0xc002b17, 0x0, 0x8fbf0020,
+0x3e00008, 0x27bd0028, 0x3c081000, 0x24070001,
+0x3c060080, 0x3c050100, 0x8f820070, 0x481024,
+0x1040fffd, 0x0, 0x8f820054, 0x24420005,
+0xaf820078, 0x8c040234, 0x10800016, 0x1821,
+0x3c020001, 0x571021, 0x8c4240e8, 0x24420005,
+0x3c010001, 0x370821, 0xac2240e8, 0x3c020001,
+0x571021, 0x8c4240e8, 0x44102b, 0x14400009,
+0x0, 0x3c030080, 0x3c010001, 0x370821,
+0xac2040e8, 0x3c010001, 0x370821, 0x1000000b,
+0xa02740f0, 0x3c020001, 0x571021, 0x904240f0,
+0x54400006, 0x661825, 0x3c020001, 0x571021,
+0x904240f1, 0x54400001, 0x661825, 0x8c040230,
+0x10800013, 0x0, 0x3c020001, 0x571021,
+0x8c4240ec, 0x24420005, 0x3c010001, 0x370821,
+0xac2240ec, 0x3c020001, 0x571021, 0x8c4240ec,
+0x44102b, 0x14400006, 0x0, 0x3c010001,
+0x370821, 0xac2040ec, 0x10000006, 0x651825,
+0x3c020001, 0x571021, 0x904240f2, 0x54400001,
+0x651825, 0x1060ffbc, 0x0, 0x8f420000,
+0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
+0x1040fffd, 0x0, 0x10000005, 0x0,
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
+0x8f820060, 0x431025, 0xaf820060, 0x8f420000,
+0x10400003, 0x0, 0x1000ffa7, 0xaf80004c,
+0x1000ffa5, 0xaf800048, 0x3e00008, 0x0,
+0x0, 0x0, 0x0, 0x27bdffe0,
+0xafbf0018, 0x8f860064, 0x30c20004, 0x10400025,
+0x24040004, 0x8c020114, 0xaf420020, 0xaf840064,
+0x8f4202fc, 0x24420001, 0xaf4202fc, 0x8f4202fc,
+0x8f820064, 0x30420004, 0x14400005, 0x0,
+0x8c030114, 0x8f420020, 0x1462fff2, 0x0,
+0x8f420000, 0x10400007, 0x8f43003c, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x431025, 0xaf820060,
+0x8f420000, 0x10400073, 0x0, 0x1000006f,
+0x0, 0x30c20008, 0x10400020, 0x24040008,
+0x8c02011c, 0xaf420048, 0xaf840064, 0x8f4202a8,
+0x24420001, 0xaf4202a8, 0x8f4202a8, 0x8f820064,
+0x30420008, 0x14400005, 0x0, 0x8c03011c,
+0x8f420048, 0x1462fff2, 0x0, 0x8f420000,
+0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
+0x1040fffd, 0x0, 0x10000005, 0x0,
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
+0x8f820060, 0x1000ffd9, 0x34420200, 0x30c20020,
+0x10400023, 0x24040020, 0x8c02012c, 0xaf420068,
+0xaf840064, 0x8f4202d8, 0x24420001, 0xaf4202d8,
+0x8f4202d8, 0x8f820064, 0x30420020, 0x14400005,
+0x32c24000, 0x8c03012c, 0x8f420068, 0x1462fff2,
+0x32c24000, 0x14400002, 0x3c020001, 0x2c2b025,
+0x8f420000, 0x10400007, 0x0, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x1000ffb4, 0x34420800,
+0x30c20010, 0x10400029, 0x24040010, 0x8c020124,
+0xaf420058, 0xaf840064, 0x8f4202d4, 0x24420001,
+0xaf4202d4, 0x8f4202d4, 0x8f820064, 0x30420010,
+0x14400005, 0x32c22000, 0x8c030124, 0x8f420058,
+0x1462fff2, 0x32c22000, 0x50400001, 0x36d68000,
+0x8f420000, 0x10400007, 0x0, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x34420100, 0xaf820060,
+0x8f420000, 0x10400003, 0x0, 0x1000006c,
+0xaf80004c, 0x1000006a, 0xaf800048, 0x30c20001,
+0x10400004, 0x24020001, 0xaf820064, 0x10000064,
+0x0, 0x30c20002, 0x1440000b, 0x3c050003,
+0x3c040001, 0x248462d4, 0x34a50500, 0x3821,
+0xafa00010, 0xc002b17, 0xafa00014, 0x2402ffc0,
+0x10000057, 0xaf820064, 0x8c05022c, 0x8c02010c,
+0x10a20048, 0x51080, 0x8c460300, 0x24a20001,
+0x3045003f, 0x24020003, 0xac05022c, 0x61e02,
+0x10620005, 0x24020010, 0x1062001d, 0x30c20fff,
+0x10000039, 0x0, 0x8f4302a8, 0x8f440000,
+0x30c20fff, 0xaf420048, 0x24630001, 0xaf4302a8,
+0x10800007, 0x8f4202a8, 0xaf80004c, 0x8f82004c,
+0x1040fffd, 0x0, 0x10000005, 0x0,
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
+0x8f820060, 0x34420200, 0xaf820060, 0x8f420000,
+0x1040001f, 0x0, 0x1000001b, 0x0,
+0xaf420058, 0x32c22000, 0x50400001, 0x36d68000,
+0x8f4202d4, 0x8f430000, 0x24420001, 0xaf4202d4,
+0x10600007, 0x8f4202d4, 0xaf80004c, 0x8f82004c,
+0x1040fffd, 0x0, 0x10000005, 0x0,
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
+0x8f820060, 0x34420100, 0xaf820060, 0x8f420000,
+0x10400003, 0x0, 0x10000006, 0xaf80004c,
+0x10000004, 0xaf800048, 0xc00217e, 0xc02021,
+0x402821, 0x8c02010c, 0x14a20002, 0x24020002,
+0xaf820064, 0x8f820064, 0x30420002, 0x14400004,
+0x0, 0x8c02010c, 0x14a2ffac, 0x0,
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x3e00008,
+0x0, 0x27bdffa0, 0xafb00040, 0x808021,
+0x101602, 0x2442ffff, 0x304300ff, 0x2c620013,
+0xafbf0058, 0xafbe0054, 0xafb50050, 0xafb3004c,
+0xafb20048, 0xafb10044, 0x104001ec, 0xafa50034,
+0x31080, 0x3c010001, 0x220821, 0x8c226318,
+0x400008, 0x0, 0x101302, 0x30440fff,
+0x24020001, 0x10820005, 0x24020002, 0x1082000a,
+0x2402fffe, 0x10000021, 0x3c050003, 0x8f430004,
+0x3c020001, 0x8c426f80, 0xaf440200, 0xaf440204,
+0x10000007, 0x34630001, 0x8f430004, 0xaf440200,
+0xaf440204, 0x621824, 0x3c020001, 0x2442c9c8,
+0x21100, 0x21182, 0xaf430004, 0x3c030800,
+0x431025, 0x3c010000, 0xac224138, 0x8f840054,
+0x41442, 0x41c82, 0x431021, 0x41cc2,
+0x431023, 0x41d02, 0x431021, 0x41d42,
+0x431023, 0x10000009, 0xaf420208, 0x3c040001,
+0x248462e0, 0x34a51000, 0x2003021, 0x3821,
+0xafa00010, 0xc002b17, 0xafa00014, 0x8f4202a0,
+0x24420001, 0xaf4202a0, 0x1000021b, 0x8f4202a0,
+0x27b00028, 0x2002021, 0x24050210, 0xc002b9b,
+0x24060008, 0xc0024f4, 0x2002021, 0x10000212,
+0x0, 0x8faa0034, 0x27a40028, 0xa1880,
+0x25420001, 0x3042003f, 0xafa20034, 0x8c650300,
+0x8faa0034, 0x21080, 0x8c430300, 0x25420001,
+0x3042003f, 0xafa20034, 0xac02022c, 0xafa50028,
+0xc0024f4, 0xafa3002c, 0x100001ff, 0x0,
+0x27b00028, 0x2002021, 0x24050210, 0xc002b9b,
+0x24060008, 0xc002633, 0x2002021, 0x100001f6,
+0x0, 0x8faa0034, 0x27a40028, 0xa1880,
+0x25420001, 0x3042003f, 0xafa20034, 0x8c650300,
+0x8faa0034, 0x21080, 0x8c430300, 0x25420001,
+0x3042003f, 0xafa20034, 0xac02022c, 0xafa50028,
+0xc002633, 0xafa3002c, 0x100001e3, 0x0,
+0x101302, 0x30430fff, 0x24020001, 0x10620005,
+0x24020002, 0x1062001e, 0x3c020002, 0x10000033,
+0x3c050003, 0x3c030002, 0x2c31024, 0x54400037,
+0x2c3b025, 0x8f820228, 0x3c010001, 0x370821,
+0xac2238d8, 0x8f82022c, 0x3c010001, 0x370821,
+0xac2238dc, 0x8f820230, 0x3c010001, 0x370821,
+0xac2238e0, 0x8f820234, 0x3c010001, 0x370821,
+0xac2238e4, 0x2402ffff, 0xaf820228, 0xaf82022c,
+0xaf820230, 0xaf820234, 0x10000020, 0x2c3b025,
+0x2c21024, 0x10400012, 0x3c02fffd, 0x3c020001,
+0x571021, 0x8c4238d8, 0xaf820228, 0x3c020001,
+0x571021, 0x8c4238dc, 0xaf82022c, 0x3c020001,
+0x571021, 0x8c4238e0, 0xaf820230, 0x3c020001,
+0x571021, 0x8c4238e4, 0xaf820234, 0x3c02fffd,
+0x3442ffff, 0x10000009, 0x2c2b024, 0x3c040001,
+0x248462ec, 0x34a51100, 0x2003021, 0x3821,
+0xafa00010, 0xc002b17, 0xafa00014, 0x8f4202cc,
+0x24420001, 0xaf4202cc, 0x1000019b, 0x8f4202cc,
+0x101302, 0x30450fff, 0x24020001, 0x10a20005,
+0x24020002, 0x10a2000d, 0x3c0408ff, 0x10000014,
+0x3c050003, 0x3c0208ff, 0x3442ffff, 0x8f830220,
+0x3c040004, 0x2c4b025, 0x621824, 0x34630008,
+0xaf830220, 0x10000012, 0xaf450298, 0x3484fff7,
+0x3c03fffb, 0x8f820220, 0x3463ffff, 0x2c3b024,
+0x441024, 0xaf820220, 0x10000009, 0xaf450298,
+0x3c040001, 0x248462f8, 0x34a51200, 0x2003021,
+0x3821, 0xafa00010, 0xc002b17, 0xafa00014,
+0x8f4202bc, 0x24420001, 0xaf4202bc, 0x10000172,
+0x8f4202bc, 0x27840208, 0x24050200, 0xc002b9b,
+0x24060008, 0x27440224, 0x24050200, 0xc002b9b,
+0x24060008, 0x8f4202c4, 0x24420001, 0xaf4202c4,
+0x10000165, 0x8f4202c4, 0x101302, 0x30430fff,
+0x24020001, 0x10620011, 0x28620002, 0x50400005,
+0x24020002, 0x10600007, 0x0, 0x10000017,
+0x0, 0x1062000f, 0x0, 0x10000013,
+0x0, 0x8c060248, 0x2021, 0xc005134,
+0x24050004, 0x10000007, 0x0, 0x8c060248,
+0x2021, 0xc005134, 0x24050004, 0x10000010,
+0x0, 0x8c06024c, 0x2021, 0xc005134,
+0x24050001, 0x1000000a, 0x0, 0x3c040001,
+0x24846304, 0x3c050003, 0x34a51300, 0x2003021,
+0x3821, 0xafa00010, 0xc002b17, 0xafa00014,
+0x8f4202c0, 0x24420001, 0xaf4202c0, 0x10000136,
+0x8f4202c0, 0xc002407, 0x0, 0x10000132,
+0x0, 0x24020001, 0xa34205c5, 0x24100100,
+0x8f4401a8, 0x8f4501ac, 0xafb00010, 0xafa00014,
+0x8f420014, 0xafa20018, 0x8f420108, 0x26e60028,
+0x40f809, 0x24070400, 0x1040fff5, 0x0,
+0x10000121, 0x0, 0x3c02ffff, 0x34427fff,
+0x2c2b024, 0x1821, 0x3c020900, 0xaf400058,
+0xaf40005c, 0xaf400060, 0xaf400064, 0xaf400360,
+0xafa20020, 0x8f5e0018, 0x27aa0020, 0x240200ff,
+0x13c20002, 0xafaa003c, 0x27c30001, 0x8c020228,
+0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c,
+0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228,
+0x3c040001, 0x2484629c, 0x3c050009, 0xafa00014,
0xafa20010, 0x8fa60020, 0x1000006b, 0x34a50500,
0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0,
0xac4404c4, 0x8f830054, 0x8f820054, 0x247003e8,
0x2021023, 0x2c4203e9, 0x1040001b, 0x9821,
-0xe08821, 0x263504c0, 0x8f440168, 0x8f45016c,
+0xe08821, 0x263504c0, 0x8f440178, 0x8f45017c,
0x2201821, 0x240a0004, 0xafaa0010, 0xafb20014,
0x8f48000c, 0x1021, 0x2f53021, 0xafa80018,
0x8f48010c, 0x24070008, 0xa32821, 0xa3482b,
0x822021, 0x100f809, 0x892021, 0x54400006,
0x24130001, 0x8f820054, 0x2021023, 0x2c4203e9,
0x1440ffe9, 0x0, 0x326200ff, 0x54400017,
-0xaf520018, 0x8f420368, 0x24420001, 0xaf420368,
-0x8f420368, 0x8f820120, 0x8faa002c, 0xafa20010,
-0x8f820124, 0x3c040001, 0x24843198, 0x3c050009,
+0xaf520018, 0x8f420378, 0x24420001, 0xaf420378,
+0x8f420378, 0x8f820120, 0x8faa003c, 0xafa20010,
+0x8f820124, 0x3c040001, 0x248462a8, 0x3c050009,
0xafa20014, 0x8d460000, 0x10000033, 0x34a50600,
-0x8f4202f8, 0x24130001, 0x24420001, 0xaf4202f8,
-0x8f4202f8, 0x1000001c, 0x326200ff, 0x8f830054,
+0x8f420308, 0x24130001, 0x24420001, 0xaf420308,
+0x8f420308, 0x1000001c, 0x326200ff, 0x8f830054,
0x8f820054, 0x247003e8, 0x2021023, 0x2c4203e9,
0x10400014, 0x9821, 0x24110010, 0x8f42000c,
-0x8f440150, 0x8f450154, 0x8f860120, 0xafb10010,
+0x8f440160, 0x8f450164, 0x8f860120, 0xafb10010,
0xafb20014, 0xafa20018, 0x8f42010c, 0x24070008,
0x40f809, 0x24c6001c, 0x1440ffe5, 0x0,
0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffef,
-0x0, 0x326200ff, 0x54400012, 0x24020001,
-0x8f420368, 0x24420001, 0xaf420368, 0x8f420368,
-0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124,
-0x3c040001, 0x248431a0, 0x3c050009, 0xafa20014,
-0x8d460000, 0x34a50700, 0xc0029bb, 0x3c03821,
-0x1021, 0x1440005b, 0x24020001, 0x10000065,
-0x0, 0x8f510018, 0x240200ff, 0x12220002,
+0x0, 0x326200ff, 0x14400011, 0x0,
+0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
+0x8f820120, 0x8faa003c, 0xafa20010, 0x8f820124,
+0x3c040001, 0x248462b0, 0x3c050009, 0xafa20014,
+0x8d460000, 0x34a50700, 0xc002b17, 0x3c03821,
+0x8f4202b0, 0x24420001, 0xaf4202b0, 0x8f4202b0,
+0x8f4202f8, 0x24420001, 0xaf4202f8, 0x1000008a,
+0x8f4202f8, 0x8c02025c, 0x27440224, 0xaf4201f0,
+0x8c020260, 0x24050200, 0x24060008, 0xc002b9b,
+0xaf4201f8, 0x8f820220, 0x30420008, 0x14400002,
+0x24020001, 0x24020002, 0xaf420298, 0x8f4202ac,
+0x24420001, 0xaf4202ac, 0x10000077, 0x8f4202ac,
+0x3c0200ff, 0x3442ffff, 0x2021824, 0x32c20180,
+0x14400006, 0x3402fffb, 0x43102b, 0x14400003,
+0x0, 0x1000006c, 0xaf4300bc, 0x3c040001,
+0x24846310, 0x3c050003, 0x34a51500, 0x2003021,
+0x3821, 0xafa00010, 0xc002b17, 0xafa00014,
+0x3c020700, 0x34421000, 0x101e02, 0x621825,
+0xafa30020, 0x8f510018, 0x240200ff, 0x12220002,
0x8021, 0x26300001, 0x8c020228, 0x1602000e,
-0x1130c0, 0x8f42032c, 0x24420001, 0xaf42032c,
-0x8f42032c, 0x8c020228, 0x3c040001, 0x24843174,
+0x1130c0, 0x8f42033c, 0x24420001, 0xaf42033c,
+0x8f42033c, 0x8c020228, 0x3c040001, 0x24846284,
0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020,
0x1000003f, 0x34a50100, 0xd71021, 0x8fa30020,
0x8fa40024, 0xac4304c0, 0xac4404c4, 0xc01821,
-0x8f440168, 0x8f45016c, 0x1021, 0x24070004,
+0x8f440178, 0x8f45017c, 0x1021, 0x24070004,
0xafa70010, 0xafb00014, 0x8f48000c, 0x24c604c0,
0x2e63021, 0xafa80018, 0x8f48010c, 0x24070008,
0xa32821, 0xa3482b, 0x822021, 0x100f809,
0x892021, 0x1440000b, 0x24070008, 0x8f820120,
-0xafa20010, 0x8f820124, 0x3c040001, 0x2484317c,
+0xafa20010, 0x8f820124, 0x3c040001, 0x2484628c,
0x3c050009, 0xafa20014, 0x8fa60020, 0x1000001c,
-0x34a50200, 0x8f440150, 0x8f450154, 0x8f43000c,
+0x34a50200, 0x8f440160, 0x8f450164, 0x8f43000c,
0xaf500018, 0x8f860120, 0x24020010, 0xafa20010,
0xafb00014, 0xafa30018, 0x8f42010c, 0x40f809,
-0x24c6001c, 0x54400011, 0x24020001, 0x8f420330,
-0x24420001, 0xaf420330, 0x8f420330, 0x8f820120,
-0xafa20010, 0x8f820124, 0x3c040001, 0x24843184,
+0x24c6001c, 0x14400010, 0x0, 0x8f420340,
+0x24420001, 0xaf420340, 0x8f420340, 0x8f820120,
+0xafa20010, 0x8f820124, 0x3c040001, 0x24846294,
0x3c050009, 0xafa20014, 0x8fa60020, 0x34a50300,
-0xc0029bb, 0x2203821, 0x1021, 0x1040000d,
-0x24020001, 0x8f4202d8, 0xa34005b7, 0xaf4001a0,
-0x24420001, 0xaf4202d8, 0x8f4202d8, 0x8ee20150,
-0x24420001, 0xaee20150, 0x10000003, 0x8ee20150,
-0x24020001, 0xa34205b7, 0x8fbf0048, 0x8fbe0044,
-0x8fb50040, 0x8fb3003c, 0x8fb20038, 0x8fb10034,
-0x8fb00030, 0x3e00008, 0x27bd0050, 0x27bdffd8,
-0xafbf0020, 0x8f8200b0, 0x30420004, 0x10400068,
-0x0, 0x8f43011c, 0x8f820104, 0x14620005,
-0x0, 0x8f430124, 0x8f8200b4, 0x10620006,
-0x0, 0x8f820104, 0xaf42011c, 0x8f8200b4,
-0x1000005b, 0xaf420124, 0x8f8200b0, 0x3c030080,
-0x431024, 0x1040000d, 0x0, 0x8f82011c,
-0x34420002, 0xaf82011c, 0x8f8200b0, 0x2403fffb,
-0x431024, 0xaf8200b0, 0x8f82011c, 0x2403fffd,
-0x431024, 0x1000004a, 0xaf82011c, 0x8f43011c,
-0x8f820104, 0x14620005, 0x0, 0x8f430124,
-0x8f8200b4, 0x10620010, 0x0, 0x8f820104,
-0xaf42011c, 0x8f8200b4, 0x8f43011c, 0xaf420124,
-0xafa30010, 0x8f420124, 0x3c040001, 0x248431c4,
-0xafa20014, 0x8f86011c, 0x8f8700b0, 0x3c050005,
-0x10000031, 0x34a50900, 0x8f42011c, 0xafa20010,
-0x8f420124, 0x3c040001, 0x248431d0, 0xafa20014,
-0x8f86011c, 0x8f8700b0, 0x3c050005, 0xc0029bb,
-0x34a51000, 0x8f82011c, 0x34420002, 0xaf82011c,
-0x8f830104, 0x8f8200b0, 0x34420001, 0xaf8200b0,
-0x24020008, 0xaf830104, 0xafa20010, 0xafa00014,
-0x8f42000c, 0x8c040208, 0x8c05020c, 0xafa20018,
-0x8f42010c, 0x26e60028, 0x40f809, 0x24070400,
-0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c,
-0x8ee201dc, 0x24420001, 0xaee201dc, 0x8ee201dc,
-0x8f42011c, 0xafa20010, 0x8f420124, 0x3c040001,
-0x248431dc, 0xafa20014, 0x8f86011c, 0x8f8700b0,
-0x3c050005, 0x34a51100, 0xc0029bb, 0x0,
-0x8f8200a0, 0x30420004, 0x10400069, 0x0,
-0x8f430120, 0x8f820124, 0x14620005, 0x0,
-0x8f430128, 0x8f8200a4, 0x10620006, 0x0,
-0x8f820124, 0xaf420120, 0x8f8200a4, 0x1000005c,
-0xaf420128, 0x8f8200a0, 0x3c030080, 0x431024,
-0x1040000d, 0x0, 0x8f82011c, 0x34420002,
-0xaf82011c, 0x8f8200a0, 0x2403fffb, 0x431024,
-0xaf8200a0, 0x8f82011c, 0x2403fffd, 0x431024,
-0x1000004b, 0xaf82011c, 0x8f430120, 0x8f820124,
-0x14620005, 0x0, 0x8f430128, 0x8f8200a4,
-0x10620010, 0x0, 0x8f820124, 0xaf420120,
-0x8f8200a4, 0x8f430120, 0xaf420128, 0xafa30010,
-0x8f420128, 0x3c040001, 0x248431e8, 0xafa20014,
-0x8f86011c, 0x8f8700a0, 0x3c050005, 0x10000032,
-0x34a51200, 0x8f420120, 0xafa20010, 0x8f420128,
-0x3c040001, 0x248431f4, 0xafa20014, 0x8f86011c,
-0x8f8700a0, 0x3c050005, 0xc0029bb, 0x34a51300,
-0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830124,
-0x8f8200a0, 0x34420001, 0xaf8200a0, 0x24020080,
-0xaf830124, 0xafa20010, 0xafa00014, 0x8f420014,
-0x8c040208, 0x8c05020c, 0xafa20018, 0x8f420108,
-0x3c060001, 0x24c63e84, 0x40f809, 0x24070004,
-0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c,
-0x8ee201dc, 0x24420001, 0xaee201dc, 0x8ee201dc,
-0x8f420120, 0xafa20010, 0x8f420128, 0x3c040001,
-0x24843200, 0xafa20014, 0x8f86011c, 0x8f8700a0,
-0x3c050005, 0x34a51400, 0xc0029bb, 0x0,
-0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3c081000,
-0x24070001, 0x3c060080, 0x3c050100, 0x8f820070,
-0x481024, 0x1040fffd, 0x0, 0x8f820054,
-0x24420005, 0xaf820078, 0x8c040234, 0x10800016,
-0x1821, 0x3c020001, 0x571021, 0x8c4240e8,
-0x24420005, 0x3c010001, 0x370821, 0xac2240e8,
-0x3c020001, 0x571021, 0x8c4240e8, 0x44102b,
-0x14400009, 0x0, 0x3c030080, 0x3c010001,
-0x370821, 0xac2040e8, 0x3c010001, 0x370821,
-0x1000000b, 0xa02740f0, 0x3c020001, 0x571021,
-0x904240f0, 0x54400006, 0x661825, 0x3c020001,
-0x571021, 0x904240f1, 0x54400001, 0x661825,
-0x8c040230, 0x10800013, 0x0, 0x3c020001,
-0x571021, 0x8c4240ec, 0x24420005, 0x3c010001,
-0x370821, 0xac2240ec, 0x3c020001, 0x571021,
-0x8c4240ec, 0x44102b, 0x14400006, 0x0,
-0x3c010001, 0x370821, 0xac2040ec, 0x10000006,
-0x651825, 0x3c020001, 0x571021, 0x904240f2,
-0x54400001, 0x651825, 0x1060ffbc, 0x0,
-0x8f420000, 0x10400007, 0x0, 0xaf80004c,
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x431025, 0xaf820060,
-0x8f420000, 0x10400003, 0x0, 0x1000ffa7,
-0xaf80004c, 0x1000ffa5, 0xaf800048, 0x3e00008,
-0x0, 0x0, 0x0, 0x27bdffe0,
-0xafbf001c, 0xafb00018, 0x8f860064, 0x30c20004,
-0x10400025, 0x24040004, 0x8c020114, 0xaf420020,
-0xaf840064, 0x8f4202ec, 0x24420001, 0xaf4202ec,
-0x8f4202ec, 0x8f820064, 0x30420004, 0x14400005,
-0x0, 0x8c030114, 0x8f420020, 0x1462fff2,
-0x0, 0x8f420000, 0x10400007, 0x8f43003c,
-0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
-0x10000005, 0x0, 0xaf800048, 0x8f820048,
-0x1040fffd, 0x0, 0x8f820060, 0x431025,
-0xaf820060, 0x8f420000, 0x10400073, 0x0,
-0x1000006f, 0x0, 0x30c20008, 0x10400020,
-0x24040008, 0x8c02011c, 0xaf420048, 0xaf840064,
-0x8f420298, 0x24420001, 0xaf420298, 0x8f420298,
-0x8f820064, 0x30420008, 0x14400005, 0x0,
-0x8c03011c, 0x8f420048, 0x1462fff2, 0x0,
-0x8f420000, 0x10400007, 0x0, 0xaf80004c,
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x1000ffd9, 0x34420200,
-0x30c20020, 0x10400023, 0x24040020, 0x8c02012c,
-0xaf420068, 0xaf840064, 0x8f4202c8, 0x24420001,
-0xaf4202c8, 0x8f4202c8, 0x8f820064, 0x30420020,
-0x14400005, 0x32c24000, 0x8c03012c, 0x8f420068,
-0x1462fff2, 0x32c24000, 0x14400002, 0x3c020001,
-0x2c2b025, 0x8f420000, 0x10400007, 0x0,
-0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
-0x10000005, 0x0, 0xaf800048, 0x8f820048,
-0x1040fffd, 0x0, 0x8f820060, 0x1000ffb4,
-0x34420800, 0x30c20010, 0x10400029, 0x24040010,
-0x8c020124, 0xaf420058, 0xaf840064, 0x8f4202c4,
-0x24420001, 0xaf4202c4, 0x8f4202c4, 0x8f820064,
-0x30420010, 0x14400005, 0x32c22000, 0x8c030124,
-0x8f420058, 0x1462fff2, 0x32c22000, 0x50400001,
-0x36d68000, 0x8f420000, 0x10400007, 0x0,
-0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
-0x10000005, 0x0, 0xaf800048, 0x8f820048,
-0x1040fffd, 0x0, 0x8f820060, 0x34420100,
-0xaf820060, 0x8f420000, 0x10400003, 0x0,
-0x1000006b, 0xaf80004c, 0x10000069, 0xaf800048,
-0x30c20001, 0x10400004, 0x24020001, 0xaf820064,
-0x10000063, 0x0, 0x30c20002, 0x1440000b,
-0x3c050003, 0x3c040001, 0x248432c4, 0x34a50500,
-0x3821, 0xafa00010, 0xc0029bb, 0xafa00014,
-0x2402ffc0, 0x10000056, 0xaf820064, 0x8c10022c,
-0x8c02010c, 0x12020047, 0x101080, 0x8c450300,
-0x26020001, 0x3050003f, 0x24020003, 0xac10022c,
-0x51e02, 0x10620005, 0x24020010, 0x1062001d,
-0x30a20fff, 0x10000039, 0x0, 0x8f430298,
-0x8f440000, 0x30a20fff, 0xaf420048, 0x24630001,
-0xaf430298, 0x10800007, 0x8f420298, 0xaf80004c,
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x34420200, 0xaf820060,
-0x8f420000, 0x1040001f, 0x0, 0x1000001b,
-0x0, 0xaf420058, 0x32c22000, 0x50400001,
-0x36d68000, 0x8f4202c4, 0x8f430000, 0x24420001,
-0xaf4202c4, 0x10600007, 0x8f4202c4, 0xaf80004c,
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x34420100, 0xaf820060,
-0x8f420000, 0x10400003, 0x0, 0x10000005,
-0xaf80004c, 0x10000003, 0xaf800048, 0xc00202b,
-0xa02021, 0x8c02010c, 0x16020002, 0x24020002,
-0xaf820064, 0x8f820064, 0x30420002, 0x14400004,
-0x0, 0x8c02010c, 0x1602ffad, 0x0,
-0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020,
-0x3e00008, 0x0, 0x27bdffa8, 0xafb00038,
-0x808021, 0x101602, 0x2442ffff, 0x304300ff,
-0x2c620013, 0xafbf0050, 0xafbe004c, 0xafb50048,
-0xafb30044, 0xafb20040, 0x104001e6, 0xafb1003c,
-0x31080, 0x3c010001, 0x220821, 0x8c223308,
-0x400008, 0x0, 0x101302, 0x30440fff,
-0x24020001, 0x10820005, 0x24020002, 0x1082000a,
-0x2402fffe, 0x10000021, 0x3c050003, 0x8f430004,
-0x3c020001, 0x8c423eb0, 0xaf4401f0, 0xaf4401f4,
-0x10000007, 0x34630001, 0x8f430004, 0xaf4401f0,
-0xaf4401f4, 0x621824, 0x3c020001, 0x2442c1b0,
-0x21100, 0x21182, 0xaf430004, 0x3c030800,
-0x431025, 0x3c010000, 0xac224138, 0x8f840054,
-0x41442, 0x41c82, 0x431021, 0x41cc2,
-0x431023, 0x41d02, 0x431021, 0x41d42,
-0x431023, 0x10000009, 0xaf4201f8, 0x3c040001,
-0x248432d0, 0x34a51000, 0x2003021, 0x3821,
-0xafa00010, 0xc0029bb, 0xafa00014, 0x8f420290,
-0x24420001, 0xaf420290, 0x10000215, 0x8f420290,
-0x27b00028, 0x2002021, 0x24050210, 0xc002a3f,
-0x24060008, 0xc002398, 0x2002021, 0x1000020c,
-0x0, 0x8c06022c, 0x27a40028, 0x61880,
-0x24c20001, 0x3046003f, 0x8c650300, 0x61080,
-0x8c430300, 0x24c20001, 0x3042003f, 0xac02022c,
-0xafa50028, 0xc002398, 0xafa3002c, 0x100001fc,
-0x0, 0x27b00028, 0x2002021, 0x24050210,
-0xc002a3f, 0x24060008, 0xc0024d7, 0x2002021,
-0x100001f3, 0x0, 0x8c06022c, 0x27a40028,
-0x61880, 0x24c20001, 0x3046003f, 0x8c650300,
-0x61080, 0x8c430300, 0x24c20001, 0x3042003f,
-0xac02022c, 0xafa50028, 0xc0024d7, 0xafa3002c,
-0x100001e3, 0x0, 0x101302, 0x30430fff,
-0x24020001, 0x10620005, 0x24020002, 0x1062001e,
-0x3c020002, 0x10000033, 0x3c050003, 0x3c030002,
-0x2c31024, 0x54400037, 0x2c3b025, 0x8f820228,
-0x3c010001, 0x370821, 0xac2238d8, 0x8f82022c,
-0x3c010001, 0x370821, 0xac2238dc, 0x8f820230,
-0x3c010001, 0x370821, 0xac2238e0, 0x8f820234,
-0x3c010001, 0x370821, 0xac2238e4, 0x2402ffff,
-0xaf820228, 0xaf82022c, 0xaf820230, 0xaf820234,
-0x10000020, 0x2c3b025, 0x2c21024, 0x10400012,
-0x3c02fffd, 0x3c020001, 0x571021, 0x8c4238d8,
-0xaf820228, 0x3c020001, 0x571021, 0x8c4238dc,
-0xaf82022c, 0x3c020001, 0x571021, 0x8c4238e0,
-0xaf820230, 0x3c020001, 0x571021, 0x8c4238e4,
-0xaf820234, 0x3c02fffd, 0x3442ffff, 0x10000009,
-0x2c2b024, 0x3c040001, 0x248432dc, 0x34a51100,
-0x2003021, 0x3821, 0xafa00010, 0xc0029bb,
-0xafa00014, 0x8f4202bc, 0x24420001, 0xaf4202bc,
-0x1000019b, 0x8f4202bc, 0x101302, 0x30450fff,
-0x24020001, 0x10a20005, 0x24020002, 0x10a2000d,
-0x3c0408ff, 0x10000014, 0x3c050003, 0x3c0208ff,
-0x3442ffff, 0x8f830220, 0x3c040004, 0x2c4b025,
-0x621824, 0x34630008, 0xaf830220, 0x10000012,
-0xaf450288, 0x3484fff7, 0x3c03fffb, 0x8f820220,
-0x3463ffff, 0x2c3b024, 0x441024, 0xaf820220,
-0x10000009, 0xaf450288, 0x3c040001, 0x248432e8,
-0x34a51200, 0x2003021, 0x3821, 0xafa00010,
-0xc0029bb, 0xafa00014, 0x8f4202ac, 0x24420001,
-0xaf4202ac, 0x10000172, 0x8f4202ac, 0x27840208,
-0x24050200, 0xc002a3f, 0x24060008, 0x27440214,
-0x24050200, 0xc002a3f, 0x24060008, 0x8f4202b4,
-0x24420001, 0xaf4202b4, 0x10000165, 0x8f4202b4,
-0x101302, 0x30430fff, 0x24020001, 0x10620011,
-0x28620002, 0x50400005, 0x24020002, 0x10600007,
-0x0, 0x10000017, 0x0, 0x1062000f,
-0x0, 0x10000013, 0x0, 0x8c060248,
-0x2021, 0xc0047d4, 0x24050004, 0x10000007,
-0x0, 0x8c060248, 0x2021, 0xc0047d4,
-0x24050004, 0x10000010, 0x0, 0x8c06024c,
-0x2021, 0xc0047d4, 0x24050001, 0x1000000a,
-0x0, 0x3c040001, 0x248432f4, 0x3c050003,
-0x34a51300, 0x2003021, 0x3821, 0xafa00010,
-0xc0029bb, 0xafa00014, 0x8f4202b0, 0x24420001,
-0xaf4202b0, 0x10000136, 0x8f4202b0, 0xc0022ac,
-0x0, 0x10000132, 0x0, 0x24020001,
-0xa34205b6, 0x24100100, 0x8f440198, 0x8f45019c,
-0xafb00010, 0xafa00014, 0x8f420014, 0xafa20018,
-0x8f420108, 0x26e60028, 0x40f809, 0x24070400,
-0x1040fff5, 0x0, 0x10000121, 0x0,
-0x3c02ffff, 0x34427fff, 0x2c2b024, 0x1821,
-0x3c020900, 0xaf400058, 0xaf40005c, 0xaf400060,
-0xaf400064, 0xaf400350, 0xafa20020, 0x8f5e0018,
-0x27aa0020, 0x240200ff, 0x13c20002, 0xafaa0034,
-0x27c30001, 0x8c020228, 0x609021, 0x1642000e,
-0x1e38c0, 0x8f42032c, 0x24420001, 0xaf42032c,
-0x8f42032c, 0x8c020228, 0x3c040001, 0x2484328c,
-0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020,
-0x1000006b, 0x34a50500, 0xf71021, 0x8fa30020,
-0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054,
-0x8f820054, 0x247003e8, 0x2021023, 0x2c4203e9,
-0x1040001b, 0x9821, 0xe08821, 0x263504c0,
-0x8f440168, 0x8f45016c, 0x2201821, 0x240a0004,
-0xafaa0010, 0xafb20014, 0x8f48000c, 0x1021,
-0x2f53021, 0xafa80018, 0x8f48010c, 0x24070008,
-0xa32821, 0xa3482b, 0x822021, 0x100f809,
-0x892021, 0x54400006, 0x24130001, 0x8f820054,
-0x2021023, 0x2c4203e9, 0x1440ffe9, 0x0,
-0x326200ff, 0x54400017, 0xaf520018, 0x8f420368,
-0x24420001, 0xaf420368, 0x8f420368, 0x8f820120,
-0x8faa0034, 0xafa20010, 0x8f820124, 0x3c040001,
-0x24843298, 0x3c050009, 0xafa20014, 0x8d460000,
-0x10000033, 0x34a50600, 0x8f4202f8, 0x24130001,
-0x24420001, 0xaf4202f8, 0x8f4202f8, 0x1000001c,
-0x326200ff, 0x8f830054, 0x8f820054, 0x247003e8,
-0x2021023, 0x2c4203e9, 0x10400014, 0x9821,
-0x24110010, 0x8f42000c, 0x8f440150, 0x8f450154,
-0x8f860120, 0xafb10010, 0xafb20014, 0xafa20018,
-0x8f42010c, 0x24070008, 0x40f809, 0x24c6001c,
-0x1440ffe5, 0x0, 0x8f820054, 0x2021023,
-0x2c4203e9, 0x1440ffef, 0x0, 0x326200ff,
-0x14400011, 0x0, 0x8f420368, 0x24420001,
-0xaf420368, 0x8f420368, 0x8f820120, 0x8faa0034,
-0xafa20010, 0x8f820124, 0x3c040001, 0x248432a0,
-0x3c050009, 0xafa20014, 0x8d460000, 0x34a50700,
-0xc0029bb, 0x3c03821, 0x8f4202a0, 0x24420001,
-0xaf4202a0, 0x8f4202a0, 0x8f4202e8, 0x24420001,
-0xaf4202e8, 0x1000008a, 0x8f4202e8, 0x8c02025c,
-0x27440214, 0xaf4201e0, 0x8c020260, 0x24050200,
-0x24060008, 0xc002a3f, 0xaf4201e8, 0x8f820220,
-0x30420008, 0x14400002, 0x24020001, 0x24020002,
-0xaf420288, 0x8f42029c, 0x24420001, 0xaf42029c,
-0x10000077, 0x8f42029c, 0x3c0200ff, 0x3442ffff,
-0x2021824, 0x32c20180, 0x14400006, 0x3402fffb,
-0x43102b, 0x14400003, 0x0, 0x1000006c,
-0xaf4300bc, 0x3c040001, 0x24843300, 0x3c050003,
-0x34a51500, 0x2003021, 0x3821, 0xafa00010,
-0xc0029bb, 0xafa00014, 0x3c020700, 0x34421000,
-0x101e02, 0x621825, 0xafa30020, 0x8f510018,
-0x240200ff, 0x12220002, 0x8021, 0x26300001,
-0x8c020228, 0x1602000e, 0x1130c0, 0x8f42032c,
-0x24420001, 0xaf42032c, 0x8f42032c, 0x8c020228,
-0x3c040001, 0x24843274, 0x3c050009, 0xafa00014,
-0xafa20010, 0x8fa60020, 0x1000003f, 0x34a50100,
-0xd71021, 0x8fa30020, 0x8fa40024, 0xac4304c0,
-0xac4404c4, 0xc01821, 0x8f440168, 0x8f45016c,
-0x1021, 0x24070004, 0xafa70010, 0xafb00014,
-0x8f48000c, 0x24c604c0, 0x2e63021, 0xafa80018,
-0x8f48010c, 0x24070008, 0xa32821, 0xa3482b,
-0x822021, 0x100f809, 0x892021, 0x1440000b,
-0x24070008, 0x8f820120, 0xafa20010, 0x8f820124,
-0x3c040001, 0x2484327c, 0x3c050009, 0xafa20014,
-0x8fa60020, 0x1000001c, 0x34a50200, 0x8f440150,
-0x8f450154, 0x8f43000c, 0xaf500018, 0x8f860120,
-0x24020010, 0xafa20010, 0xafb00014, 0xafa30018,
-0x8f42010c, 0x40f809, 0x24c6001c, 0x14400010,
-0x0, 0x8f420330, 0x24420001, 0xaf420330,
-0x8f420330, 0x8f820120, 0xafa20010, 0x8f820124,
-0x3c040001, 0x24843284, 0x3c050009, 0xafa20014,
-0x8fa60020, 0x34a50300, 0xc0029bb, 0x2203821,
-0x8f4202d0, 0x24420001, 0xaf4202d0, 0x8f4202d0,
-0x8f4202e0, 0x24420001, 0xaf4202e0, 0x8f4202e0,
-0x8fbf0050, 0x8fbe004c, 0x8fb50048, 0x8fb30044,
-0x8fb20040, 0x8fb1003c, 0x8fb00038, 0x3e00008,
-0x27bd0058, 0x27bdfff8, 0x2408ffff, 0x10a00014,
-0x4821, 0x3c0aedb8, 0x354a8320, 0x90870000,
-0x24840001, 0x3021, 0x1071026, 0x30420001,
-0x10400002, 0x81842, 0x6a1826, 0x604021,
-0x24c60001, 0x2cc20008, 0x1440fff7, 0x73842,
-0x25290001, 0x125102b, 0x1440fff0, 0x0,
-0x1001021, 0x3e00008, 0x27bd0008, 0x27bdffb8,
-0xafbf0040, 0xafbe003c, 0xafb50038, 0xafb30034,
-0xafb20030, 0xafb1002c, 0xafb00028, 0x8f870220,
-0xafa7001c, 0x8f870200, 0xafa70024, 0x8f820220,
-0x3c0308ff, 0x3463ffff, 0x431024, 0x34420004,
-0xaf820220, 0x8f820200, 0x3c03c0ff, 0x3463ffff,
-0x431024, 0x34420004, 0xaf820200, 0x8f53034c,
-0x8f550350, 0x8f5e0354, 0x8f470358, 0xafa70014,
-0x8f4202c0, 0x274401b0, 0x24420001, 0xaf4202c0,
-0x8f5002c0, 0x8f5101f4, 0x8f5201f0, 0xc002a28,
-0x24050400, 0xaf53034c, 0xaf550350, 0xaf5e0354,
-0x8fa70014, 0xaf470358, 0xaf5002c0, 0xaf5101f4,
-0xaf5201f0, 0x8c02025c, 0x27440214, 0xaf4201e0,
-0x8c020260, 0x24050200, 0x24060008, 0xaf4201e8,
-0x24020006, 0xc002a3f, 0xaf4201e4, 0x3c023b9a,
-0x3442ca00, 0xaf4201ec, 0x240203e8, 0x24040002,
-0x24030001, 0xaf420284, 0xaf440280, 0xaf43028c,
-0x8f820220, 0x30420008, 0x10400004, 0x0,
-0xaf430288, 0x10000003, 0x3021, 0xaf440288,
-0x3021, 0x3c030001, 0x661821, 0x90633cf0,
-0x3461021, 0x24c60001, 0xa043021c, 0x2cc2000f,
-0x1440fff8, 0x3461821, 0x24c60001, 0x8f820040,
-0x24040080, 0x24050080, 0x21702, 0x24420030,
-0xa062021c, 0x3461021, 0xc002a28, 0xa040021c,
-0x8fa7001c, 0x30e20004, 0x14400006, 0x0,
-0x8f820220, 0x3c0308ff, 0x3463fffb, 0x431024,
-0xaf820220, 0x8fa70024, 0x30e20004, 0x14400006,
-0x0, 0x8f820200, 0x3c03c0ff, 0x3463fffb,
-0x431024, 0xaf820200, 0x8fbf0040, 0x8fbe003c,
-0x8fb50038, 0x8fb30034, 0x8fb20030, 0x8fb1002c,
-0x8fb00028, 0x3e00008, 0x27bd0048, 0xaf400104,
+0xc002b17, 0x2203821, 0x8f4202e0, 0x24420001,
+0xaf4202e0, 0x8f4202e0, 0x8f4202f0, 0x24420001,
+0xaf4202f0, 0x8f4202f0, 0x8fa20034, 0x8fbf0058,
+0x8fbe0054, 0x8fb50050, 0x8fb3004c, 0x8fb20048,
+0x8fb10044, 0x8fb00040, 0x3e00008, 0x27bd0060,
+0x27bdfff8, 0x2408ffff, 0x10a00014, 0x4821,
+0x3c0aedb8, 0x354a8320, 0x90870000, 0x24840001,
+0x3021, 0x1071026, 0x30420001, 0x10400002,
+0x81842, 0x6a1826, 0x604021, 0x24c60001,
+0x2cc20008, 0x1440fff7, 0x73842, 0x25290001,
+0x125102b, 0x1440fff0, 0x0, 0x1001021,
+0x3e00008, 0x27bd0008, 0x27bdffb8, 0xafbf0040,
+0xafbe003c, 0xafb50038, 0xafb30034, 0xafb20030,
+0xafb1002c, 0xafb00028, 0x8f870220, 0xafa7001c,
+0x8f870200, 0xafa70024, 0x8f820220, 0x3c0308ff,
+0x3463ffff, 0x431024, 0x34420004, 0xaf820220,
+0x8f820200, 0x3c03c0ff, 0x3463ffff, 0x431024,
+0x34420004, 0xaf820200, 0x8f53035c, 0x8f550360,
+0x8f5e0364, 0x8f470368, 0xafa70014, 0x8f4202d0,
+0x274401c0, 0x24420001, 0xaf4202d0, 0x8f5002d0,
+0x8f510204, 0x8f520200, 0xc002b84, 0x24050400,
+0xaf53035c, 0xaf550360, 0xaf5e0364, 0x8fa70014,
+0xaf470368, 0xaf5002d0, 0xaf510204, 0xaf520200,
+0x8c02025c, 0x27440224, 0xaf4201f0, 0x8c020260,
+0x24050200, 0x24060008, 0xaf4201f8, 0x24020006,
+0xc002b9b, 0xaf4201f4, 0x3c023b9a, 0x3442ca00,
+0xaf4201fc, 0x240203e8, 0x24040002, 0x24030001,
+0xaf420294, 0xaf440290, 0xaf43029c, 0x8f820220,
+0x30420008, 0x10400004, 0x0, 0xaf430298,
+0x10000003, 0x3021, 0xaf440298, 0x3021,
+0x3c030001, 0x661821, 0x90636d80, 0x3461021,
+0x24c60001, 0xa043022c, 0x2cc2000f, 0x1440fff8,
+0x3461821, 0x24c60001, 0x8f820040, 0x24040080,
+0x24050080, 0x21702, 0x24420030, 0xa062022c,
+0x3461021, 0xc002b84, 0xa040022c, 0x8fa7001c,
+0x30e20004, 0x14400006, 0x0, 0x8f820220,
+0x3c0308ff, 0x3463fffb, 0x431024, 0xaf820220,
+0x8fa70024, 0x30e20004, 0x14400006, 0x0,
+0x8f820200, 0x3c03c0ff, 0x3463fffb, 0x431024,
+0xaf820200, 0x8fbf0040, 0x8fbe003c, 0x8fb50038,
+0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028,
+0x3e00008, 0x27bd0048, 0x0, 0xaf400104,
0x24040001, 0x410c0, 0x2e21821, 0x24820001,
0x3c010001, 0x230821, 0xa42234d0, 0x402021,
0x2c820080, 0x1440fff8, 0x410c0, 0x24020001,
@@ -5721,7 +5946,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x2c450001, 0xa01021, 0x14400009, 0x24840008,
0x86102b, 0x1440fff0, 0x1021, 0x304200ff,
0x14400030, 0x24020001, 0x1000002e, 0x1021,
-0x1000fffa, 0x24020001, 0x2002021, 0xc002292,
+0x1000fffa, 0x24020001, 0x2002021, 0xc0023ed,
0x24050006, 0x3042007f, 0x218c0, 0x2e31021,
0x3c010001, 0x220821, 0x942230d0, 0x1040fff2,
0x2e31021, 0x3c060001, 0xc23021, 0x94c630d0,
@@ -5736,7 +5961,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x27bd0018, 0x3e00008, 0x0, 0x27bdffb0,
0x801021, 0xafb00030, 0x24500002, 0x2002021,
0x24050006, 0xafb10034, 0x408821, 0xafbf0048,
-0xafbe0044, 0xafb50040, 0xafb3003c, 0xc002292,
+0xafbe0044, 0xafb50040, 0xafb3003c, 0xc0023ed,
0xafb20038, 0x3047007f, 0x710c0, 0x2e21021,
0x3c050001, 0xa22821, 0x94a530d0, 0x50a0001c,
0xa03021, 0x3c090001, 0x352934d2, 0x96280002,
@@ -5749,15 +5974,15 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x10c00014, 0x610c0, 0x571821, 0x3c010001,
0x230821, 0x8c2334d0, 0x571021, 0xafa30010,
0x3c010001, 0x220821, 0x8c2234d4, 0x3c040001,
-0x24843414, 0xafa20014, 0x8e260000, 0x8e270004,
-0x3c050004, 0xc0029bb, 0x34a50400, 0x10000063,
+0x24846424, 0xafa20014, 0x8e260000, 0x8e270004,
+0x3c050004, 0xc002b17, 0x34a50400, 0x10000063,
0x3c020800, 0x8f450100, 0x10a00006, 0x510c0,
0x2e21021, 0x3c010001, 0x220821, 0x942234d0,
0xaf420100, 0xa03021, 0x14c00011, 0x628c0,
0x710c0, 0x2e21021, 0xafa70010, 0x3c010001,
-0x220821, 0x942230d0, 0x3c040001, 0x24843420,
+0x220821, 0x942230d0, 0x3c040001, 0x24846430,
0xafa20014, 0x8e260000, 0x8e270004, 0x3c050004,
-0xc0029bb, 0x34a50500, 0x10000048, 0x3c020800,
+0xc002b17, 0x34a50500, 0x10000048, 0x3c020800,
0xb71821, 0x3c020001, 0x96040000, 0x344234d2,
0x621821, 0xa4640000, 0x8e020002, 0x720c0,
0xac620002, 0x2e41021, 0x3c030001, 0x621821,
@@ -5779,44 +6004,44 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x1821, 0xafa20020, 0x8f5e0018, 0x27aa0020,
0x240200ff, 0x13c20002, 0xafaa002c, 0x27c30001,
0x8c020228, 0x609021, 0x1642000e, 0x1e38c0,
-0x8f42032c, 0x24420001, 0xaf42032c, 0x8f42032c,
-0x8c020228, 0x3c040001, 0x248433dc, 0x3c050009,
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
+0x8c020228, 0x3c040001, 0x248463ec, 0x3c050009,
0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006b,
0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024,
0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054,
0x247003e8, 0x2021023, 0x2c4203e9, 0x1040001b,
-0x9821, 0xe08821, 0x263504c0, 0x8f440168,
-0x8f45016c, 0x2201821, 0x240a0004, 0xafaa0010,
+0x9821, 0xe08821, 0x263504c0, 0x8f440178,
+0x8f45017c, 0x2201821, 0x240a0004, 0xafaa0010,
0xafb20014, 0x8f48000c, 0x1021, 0x2f53021,
0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
0xa3482b, 0x822021, 0x100f809, 0x892021,
0x54400006, 0x24130001, 0x8f820054, 0x2021023,
0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff,
-0x54400017, 0xaf520018, 0x8f420368, 0x24420001,
-0xaf420368, 0x8f420368, 0x8f820120, 0x8faa002c,
-0xafa20010, 0x8f820124, 0x3c040001, 0x248433e8,
+0x54400017, 0xaf520018, 0x8f420378, 0x24420001,
+0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c,
+0xafa20010, 0x8f820124, 0x3c040001, 0x248463f8,
0x3c050009, 0xafa20014, 0x8d460000, 0x10000033,
-0x34a50600, 0x8f4202f8, 0x24130001, 0x24420001,
-0xaf4202f8, 0x8f4202f8, 0x1000001c, 0x326200ff,
+0x34a50600, 0x8f420308, 0x24130001, 0x24420001,
+0xaf420308, 0x8f420308, 0x1000001c, 0x326200ff,
0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
0x2c4203e9, 0x10400014, 0x9821, 0x24110010,
-0x8f42000c, 0x8f440150, 0x8f450154, 0x8f860120,
+0x8f42000c, 0x8f440160, 0x8f450164, 0x8f860120,
0xafb10010, 0xafb20014, 0xafa20018, 0x8f42010c,
0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe5,
0x0, 0x8f820054, 0x2021023, 0x2c4203e9,
0x1440ffef, 0x0, 0x326200ff, 0x14400011,
-0x0, 0x8f420368, 0x24420001, 0xaf420368,
-0x8f420368, 0x8f820120, 0x8faa002c, 0xafa20010,
-0x8f820124, 0x3c040001, 0x248433f0, 0x3c050009,
-0xafa20014, 0x8d460000, 0x34a50700, 0xc0029bb,
-0x3c03821, 0x8f4202a4, 0x24420001, 0xaf4202a4,
-0x8f4202a4, 0x8f4202e4, 0x24420001, 0xaf4202e4,
-0x8f4202e4, 0x8fbf0048, 0x8fbe0044, 0x8fb50040,
+0x0, 0x8f420378, 0x24420001, 0xaf420378,
+0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010,
+0x8f820124, 0x3c040001, 0x24846400, 0x3c050009,
+0xafa20014, 0x8d460000, 0x34a50700, 0xc002b17,
+0x3c03821, 0x8f4202b4, 0x24420001, 0xaf4202b4,
+0x8f4202b4, 0x8f4202f4, 0x24420001, 0xaf4202f4,
+0x8f4202f4, 0x8fbf0048, 0x8fbe0044, 0x8fb50040,
0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030,
0x3e00008, 0x27bd0050, 0x27bdffa0, 0x801021,
0xafb00040, 0x24500002, 0x2002021, 0x24050006,
0xafb10044, 0x408821, 0xafbf0058, 0xafbe0054,
-0xafb50050, 0xafb3004c, 0xc002292, 0xafb20048,
+0xafb50050, 0xafb3004c, 0xc0023ed, 0xafb20048,
0x3048007f, 0x810c0, 0x2e21021, 0x3c060001,
0xc23021, 0x94c630d0, 0x10c0001c, 0x3821,
0x3c0a0001, 0x354a34d2, 0x96290002, 0x610c0,
@@ -5828,8 +6053,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x94c634d0, 0x14c0ffea, 0x610c0, 0x14c00011,
0xafa70028, 0x810c0, 0x2e21021, 0xafa80010,
0x3c010001, 0x220821, 0x942230d0, 0x3c040001,
-0x2484342c, 0xafa20014, 0x8e260000, 0x8e270004,
-0x3c050004, 0xc0029bb, 0x34a50900, 0x10000075,
+0x2484643c, 0xafa20014, 0x8e260000, 0x8e270004,
+0x3c050004, 0xc002b17, 0x34a50900, 0x10000075,
0x3c020800, 0x10e0000c, 0x610c0, 0x2e21021,
0x3c030001, 0x621821, 0x946334d0, 0x710c0,
0x2e21021, 0x3c010001, 0x220821, 0xa42334d0,
@@ -5862,43 +6087,43 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x3c020800, 0x34422000, 0x1821, 0xafa20020,
0x8f5e0018, 0x27ab0020, 0x240200ff, 0x13c20002,
0xafab0034, 0x27c30001, 0x8c020228, 0x609021,
-0x1642000e, 0x1e38c0, 0x8f42032c, 0x24420001,
-0xaf42032c, 0x8f42032c, 0x8c020228, 0x3c040001,
-0x248433dc, 0x3c050009, 0xafa00014, 0xafa20010,
+0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
+0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
+0x248463ec, 0x3c050009, 0xafa00014, 0xafa20010,
0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021,
0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
-0x263504c0, 0x8f440168, 0x8f45016c, 0x2201821,
+0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
0x240b0004, 0xafab0010, 0xafb20014, 0x8f48000c,
0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
0x24070008, 0xa32821, 0xa3482b, 0x822021,
0x100f809, 0x892021, 0x54400006, 0x24130001,
0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
0x0, 0x326200ff, 0x54400017, 0xaf520018,
-0x8f420368, 0x24420001, 0xaf420368, 0x8f420368,
+0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
0x8f820120, 0x8fab0034, 0xafa20010, 0x8f820124,
-0x3c040001, 0x248433e8, 0x3c050009, 0xafa20014,
-0x8d660000, 0x10000033, 0x34a50600, 0x8f4202f8,
-0x24130001, 0x24420001, 0xaf4202f8, 0x8f4202f8,
+0x3c040001, 0x248463f8, 0x3c050009, 0xafa20014,
+0x8d660000, 0x10000033, 0x34a50600, 0x8f420308,
+0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054,
0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014,
-0x9821, 0x24110010, 0x8f42000c, 0x8f440150,
-0x8f450154, 0x8f860120, 0xafb10010, 0xafb20014,
+0x9821, 0x24110010, 0x8f42000c, 0x8f440160,
+0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014,
0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054,
0x2021023, 0x2c4203e9, 0x1440ffef, 0x0,
-0x326200ff, 0x14400011, 0x0, 0x8f420368,
-0x24420001, 0xaf420368, 0x8f420368, 0x8f820120,
+0x326200ff, 0x14400011, 0x0, 0x8f420378,
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
0x8fab0034, 0xafa20010, 0x8f820124, 0x3c040001,
-0x248433f0, 0x3c050009, 0xafa20014, 0x8d660000,
-0x34a50700, 0xc0029bb, 0x3c03821, 0x8f4202a8,
-0x24420001, 0xaf4202a8, 0x8f4202a8, 0x8f4202e4,
-0x24420001, 0xaf4202e4, 0x8f4202e4, 0x8fbf0058,
+0x24846400, 0x3c050009, 0xafa20014, 0x8d660000,
+0x34a50700, 0xc002b17, 0x3c03821, 0x8f4202b8,
+0x24420001, 0xaf4202b8, 0x8f4202b8, 0x8f4202f4,
+0x24420001, 0xaf4202f4, 0x8f4202f4, 0x8fbf0058,
0x8fbe0054, 0x8fb50050, 0x8fb3004c, 0x8fb20048,
0x8fb10044, 0x8fb00040, 0x3e00008, 0x27bd0060,
0x0, 0x0, 0x0, 0x27bdffe0,
-0x27644000, 0xafbf0018, 0xc002a28, 0x24051000,
+0x27644000, 0xafbf0018, 0xc002b84, 0x24051000,
0x3c030001, 0x34632cc0, 0x3c040001, 0x34842ec8,
0x24020020, 0xaf82011c, 0x2e31021, 0xaf800100,
0xaf800104, 0xaf800108, 0xaf800110, 0xaf800114,
@@ -5907,21 +6132,21 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x2e31021, 0xaf4200f0, 0x2e41021, 0xaf4200f4,
0x2e41021, 0xaf4200f8, 0x3c020001, 0x571021,
0x904240f4, 0x1440001c, 0x3c050001, 0x8f82011c,
-0x3c040001, 0x248434f0, 0x3c050001, 0x34420001,
+0x3c040001, 0x24846500, 0x3c050001, 0x34420001,
0xaf82011c, 0xafa00010, 0xafa00014, 0x8f86011c,
-0x34a50100, 0xc0029bb, 0x3821, 0x8c020218,
+0x34a50100, 0xc002b17, 0x3821, 0x8c020218,
0x30420040, 0x10400014, 0x0, 0x8f82011c,
-0x3c040001, 0x248434fc, 0x3c050001, 0x34420004,
+0x3c040001, 0x2484650c, 0x3c050001, 0x34420004,
0xaf82011c, 0xafa00010, 0xafa00014, 0x8f86011c,
-0x10000007, 0x34a50200, 0x3c040001, 0x24843504,
+0x10000007, 0x34a50200, 0x3c040001, 0x24846514,
0xafa00010, 0xafa00014, 0x8f86011c, 0x34a50300,
-0xc0029bb, 0x3821, 0x8fbf0018, 0x3e00008,
+0xc002b17, 0x3821, 0x8fbf0018, 0x3e00008,
0x27bd0020, 0x8fa90010, 0x8f83012c, 0x8faa0014,
0x8fab0018, 0x1060000a, 0x27624fe0, 0x14620002,
0x24680020, 0x27684800, 0x8f820128, 0x11020004,
0x0, 0x8f820124, 0x15020007, 0x0,
-0x8f430324, 0x1021, 0x24630001, 0xaf430324,
-0x10000039, 0x8f430324, 0xac640000, 0xac650004,
+0x8f430334, 0x1021, 0x24630001, 0xaf430334,
+0x10000039, 0x8f430334, 0xac640000, 0xac650004,
0xac660008, 0xa467000e, 0xac690018, 0xac6a001c,
0xac6b0010, 0xac620014, 0xaf880120, 0x8f4200fc,
0x8f4400f4, 0x2442ffff, 0xaf4200fc, 0x8c820000,
@@ -5940,8 +6165,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8faa0014, 0x8fab0018, 0x1060000a, 0x276247e0,
0x14620002, 0x24680020, 0x27684000, 0x8f820108,
0x11020004, 0x0, 0x8f820104, 0x15020007,
-0x0, 0x8f430328, 0x1021, 0x24630001,
-0xaf430328, 0x10000035, 0x8f430328, 0xac640000,
+0x0, 0x8f430338, 0x1021, 0x24630001,
+0xaf430338, 0x10000035, 0x8f430338, 0xac640000,
0xac650004, 0xac660008, 0xa467000e, 0xac690018,
0xac6a001c, 0xac6b0010, 0xac620014, 0xaf880100,
0x8f4400ec, 0x8c820000, 0x30420006, 0x10400019,
@@ -5956,55 +6181,55 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x2e21021, 0x402021, 0x24020001, 0xaf4400ec,
0xac890000, 0xac820004, 0x24020001, 0x3e00008,
0x0, 0x3e00008, 0x0, 0x27bdffd8,
-0x3c040001, 0x2484350c, 0x3c050001, 0xafbf0024,
+0x3c040001, 0x2484651c, 0x3c050001, 0xafbf0024,
0xafb20020, 0xafb1001c, 0xafb00018, 0x8f900104,
0x8f9100b0, 0x8f92011c, 0x34a52500, 0x8f820100,
-0x2403021, 0x2203821, 0xafa20010, 0xc0029bb,
+0x2403021, 0x2203821, 0xafa20010, 0xc002b17,
0xafb00014, 0x8e020008, 0xafa20010, 0x8e02000c,
-0x3c040001, 0x24843518, 0xafa20014, 0x8e060000,
-0x8e070004, 0x3c050001, 0xc0029bb, 0x34a52510,
+0x3c040001, 0x24846528, 0xafa20014, 0x8e060000,
+0x8e070004, 0x3c050001, 0xc002b17, 0x34a52510,
0x8e020018, 0xafa20010, 0x8e02001c, 0x3c040001,
-0x24843524, 0xafa20014, 0x8e060010, 0x8e070014,
-0x3c050001, 0xc0029bb, 0x34a52520, 0x3c027f00,
+0x24846534, 0xafa20014, 0x8e060010, 0x8e070014,
+0x3c050001, 0xc002b17, 0x34a52520, 0x3c027f00,
0x2221024, 0x3c030800, 0x54430016, 0x3c030200,
0x8f82009c, 0x3042ffff, 0x14400012, 0x3c030200,
-0x3c040001, 0x24843530, 0x3c050002, 0x34a5f030,
+0x3c040001, 0x24846540, 0x3c050002, 0x34a5f030,
0x3021, 0x3821, 0x36420002, 0xaf82011c,
0x36220001, 0xaf8200b0, 0xaf900104, 0xaf92011c,
-0xafa00010, 0xc0029bb, 0xafa00014, 0x10000024,
+0xafa00010, 0xc002b17, 0xafa00014, 0x10000024,
0x0, 0x2c31024, 0x1040000d, 0x2231024,
0x1040000b, 0x36420002, 0xaf82011c, 0x36220001,
-0xaf8200b0, 0xaf900104, 0xaf92011c, 0x8f420320,
-0x24420001, 0xaf420320, 0x10000015, 0x8f420320,
-0x3c040001, 0x24843538, 0x240202a9, 0xafa20010,
-0xafa00014, 0x8f860144, 0x3c070001, 0x24e73540,
-0xc0029bb, 0x3405dead, 0x8f82011c, 0x34420002,
+0xaf8200b0, 0xaf900104, 0xaf92011c, 0x8f420330,
+0x24420001, 0xaf420330, 0x10000015, 0x8f420330,
+0x3c040001, 0x24846548, 0x240202a9, 0xafa20010,
+0xafa00014, 0x8f860144, 0x3c070001, 0x24e76550,
+0xc002b17, 0x3405dead, 0x8f82011c, 0x34420002,
0xaf82011c, 0x8f820220, 0x34420004, 0xaf820220,
0x8f820140, 0x3c030001, 0x431025, 0xaf820140,
0x8fbf0024, 0x8fb20020, 0x8fb1001c, 0x8fb00018,
0x3e00008, 0x27bd0028, 0x27bdffd8, 0x3c040001,
-0x24843568, 0x3c050001, 0xafbf0024, 0xafb20020,
+0x24846578, 0x3c050001, 0xafbf0024, 0xafb20020,
0xafb1001c, 0xafb00018, 0x8f900124, 0x8f9100a0,
0x8f92011c, 0x34a52600, 0x8f820120, 0x2403021,
-0x2203821, 0xafa20010, 0xc0029bb, 0xafb00014,
+0x2203821, 0xafa20010, 0xc002b17, 0xafb00014,
0x8e020008, 0xafa20010, 0x8e02000c, 0x3c040001,
-0x24843574, 0xafa20014, 0x8e060000, 0x8e070004,
-0x3c050001, 0xc0029bb, 0x34a52610, 0x8e020018,
-0xafa20010, 0x8e02001c, 0x3c040001, 0x24843580,
+0x24846584, 0xafa20014, 0x8e060000, 0x8e070004,
+0x3c050001, 0xc002b17, 0x34a52610, 0x8e020018,
+0xafa20010, 0x8e02001c, 0x3c040001, 0x24846590,
0xafa20014, 0x8e060010, 0x8e070014, 0x3c050001,
-0xc0029bb, 0x34a52620, 0x3c027f00, 0x2221024,
+0xc002b17, 0x34a52620, 0x3c027f00, 0x2221024,
0x3c030800, 0x54430016, 0x3c030200, 0x8f8200ac,
0x3042ffff, 0x14400012, 0x3c030200, 0x3c040001,
-0x2484358c, 0x3c050001, 0x34a5f030, 0x3021,
+0x2484659c, 0x3c050001, 0x34a5f030, 0x3021,
0x3821, 0x36420002, 0xaf82011c, 0x36220001,
0xaf8200a0, 0xaf900124, 0xaf92011c, 0xafa00010,
-0xc0029bb, 0xafa00014, 0x10000024, 0x0,
+0xc002b17, 0xafa00014, 0x10000024, 0x0,
0x2c31024, 0x1040000d, 0x2231024, 0x1040000b,
0x36420002, 0xaf82011c, 0x36220001, 0xaf8200a0,
-0xaf900124, 0xaf92011c, 0x8f42031c, 0x24420001,
-0xaf42031c, 0x10000015, 0x8f42031c, 0x3c040001,
-0x24843538, 0x240202e2, 0xafa20010, 0xafa00014,
-0x8f860144, 0x3c070001, 0x24e73540, 0xc0029bb,
+0xaf900124, 0xaf92011c, 0x8f42032c, 0x24420001,
+0xaf42032c, 0x10000015, 0x8f42032c, 0x3c040001,
+0x24846548, 0x240202e2, 0xafa20010, 0xafa00014,
+0x8f860144, 0x3c070001, 0x24e76550, 0xc002b17,
0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c,
0x8f820220, 0x34420004, 0xaf820220, 0x8f820140,
0x3c030001, 0x431025, 0xaf820140, 0x8fbf0024,
@@ -6013,24 +6238,24 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x2821, 0x6821, 0x4821, 0x7821,
0x7021, 0x8f880124, 0x8f870104, 0x1580002e,
0x8f8b011c, 0x11a00014, 0x31620800, 0x8f820120,
-0x10460029, 0x0, 0x3c040001, 0x8c843e90,
+0x10460029, 0x0, 0x3c040001, 0x8c846f60,
0x8cc20000, 0x8cc30004, 0xac820000, 0xac830004,
0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e,
0x8cc20010, 0x240c0001, 0xac820010, 0x8cc20014,
0x10000012, 0x24c60020, 0x10400017, 0x0,
-0x3c040001, 0x8c843e90, 0x8d020000, 0x8d030004,
+0x3c040001, 0x8c846f60, 0x8d020000, 0x8d030004,
0xac820000, 0xac830004, 0x8d020008, 0xac820008,
0x9502000e, 0xa482000e, 0x8d020010, 0x25060020,
0xac820010, 0x8d020014, 0x240c0001, 0xc01821,
0xac820014, 0x27624fe0, 0x43102b, 0x54400001,
0x27634800, 0x603021, 0x1540002f, 0x31620100,
0x11200014, 0x31628000, 0x8f820100, 0x1045002a,
-0x31620100, 0x3c040001, 0x8c843e8c, 0x8ca20000,
+0x31620100, 0x3c040001, 0x8c846f5c, 0x8ca20000,
0x8ca30004, 0xac820000, 0xac830004, 0x8ca20008,
0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010,
0x240a0001, 0xac820010, 0x8ca20014, 0x10000012,
0x24a50020, 0x10400018, 0x31620100, 0x3c040001,
-0x8c843e8c, 0x8ce20000, 0x8ce30004, 0xac820000,
+0x8c846f5c, 0x8ce20000, 0x8ce30004, 0xac820000,
0xac830004, 0x8ce20008, 0xac820008, 0x94e2000e,
0xa482000e, 0x8ce20010, 0x24e50020, 0xac820010,
0x8ce20014, 0x240a0001, 0xa01821, 0xac820014,
@@ -6039,7 +6264,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x11a00009, 0x31a20800, 0x10400004, 0x25020020,
0x8f8200a8, 0xa5e20000, 0x25020020, 0xaf820124,
0x8f880124, 0x6821, 0x11800011, 0x31621000,
-0x3c040001, 0x8c843e90, 0x8c820000, 0x8c830004,
+0x3c040001, 0x8c846f60, 0x8c820000, 0x8c830004,
0xaf820080, 0xaf830084, 0x8c820008, 0xaf8200a4,
0x9482000e, 0xaf8200ac, 0x8c820010, 0x6021,
0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31621000,
@@ -6048,7 +6273,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x3c020002, 0x1221024, 0x10400004, 0x24e20020,
0x8f8200b4, 0xaf8200d4, 0x24e20020, 0xaf820104,
0x8f870104, 0x4821, 0x1140ff70, 0x0,
-0x3c040001, 0x8c843e8c, 0x8c820000, 0x8c830004,
+0x3c040001, 0x8c846f5c, 0x8c820000, 0x8c830004,
0xaf820090, 0xaf830094, 0x8c820008, 0xaf8200b4,
0x9482000e, 0xaf82009c, 0x8c820010, 0x5021,
0xaf8200b0, 0x8c890010, 0x1000ff60, 0x8c8e0014,
@@ -6057,11 +6282,11 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x7821, 0x7021, 0x8f880124, 0x8f870104,
0x3c180100, 0x1580002e, 0x8f89011c, 0x11a00014,
0x31220800, 0x8f820120, 0x10460029, 0x0,
-0x3c040001, 0x8c843e90, 0x8cc20000, 0x8cc30004,
+0x3c040001, 0x8c846f60, 0x8cc20000, 0x8cc30004,
0xac820000, 0xac830004, 0x8cc20008, 0xac820008,
0x94c2000e, 0xa482000e, 0x8cc20010, 0x240c0001,
0xac820010, 0x8cc20014, 0x10000012, 0x24c60020,
-0x10400017, 0x0, 0x3c040001, 0x8c843e90,
+0x10400017, 0x0, 0x3c040001, 0x8c846f60,
0x8d020000, 0x8d030004, 0xac820000, 0xac830004,
0x8d020008, 0xac820008, 0x9502000e, 0xa482000e,
0x8d020010, 0x25060020, 0xac820010, 0x8d020014,
@@ -6069,11 +6294,11 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x43102b, 0x54400001, 0x27634800, 0x603021,
0x1560002f, 0x31220100, 0x11400014, 0x31228000,
0x8f820100, 0x1045002a, 0x31220100, 0x3c040001,
-0x8c843e8c, 0x8ca20000, 0x8ca30004, 0xac820000,
+0x8c846f5c, 0x8ca20000, 0x8ca30004, 0xac820000,
0xac830004, 0x8ca20008, 0xac820008, 0x94a2000e,
0xa482000e, 0x8ca20010, 0x240b0001, 0xac820010,
0x8ca20014, 0x10000012, 0x24a50020, 0x10400018,
-0x31220100, 0x3c040001, 0x8c843e8c, 0x8ce20000,
+0x31220100, 0x3c040001, 0x8c846f5c, 0x8ce20000,
0x8ce30004, 0xac820000, 0xac830004, 0x8ce20008,
0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010,
0x24e50020, 0xac820010, 0x8ce20014, 0x240b0001,
@@ -6082,7 +6307,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x5440001d, 0x31221000, 0x11a00009, 0x31a20800,
0x10400004, 0x25020020, 0x8f8200a8, 0xa5e20000,
0x25020020, 0xaf820124, 0x8f880124, 0x6821,
-0x11800011, 0x31221000, 0x3c040001, 0x8c843e90,
+0x11800011, 0x31221000, 0x3c040001, 0x8c846f60,
0x8c820000, 0x8c830004, 0xaf820080, 0xaf830084,
0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac,
0x8c820010, 0x6021, 0xaf8200a0, 0x8c8d0010,
@@ -6091,7 +6316,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8f8200b8, 0xa5c20000, 0x3c020002, 0x1421024,
0x10400004, 0x24e20020, 0x8f8200b4, 0xaf8200d4,
0x24e20020, 0xaf820104, 0x8f870104, 0x5021,
-0x11600010, 0x0, 0x3c040001, 0x8c843e8c,
+0x11600010, 0x0, 0x3c040001, 0x8c846f5c,
0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094,
0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c,
0x8c820010, 0x5821, 0xaf8200b0, 0x8c8a0010,
@@ -6120,37 +6345,37 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8f420000, 0x10400003, 0x0, 0x1000ff05,
0xaf80004c, 0x1000ff03, 0xaf800048, 0x3e00008,
0x0, 0x0, 0x0, 0x3c020001,
-0x8c423d18, 0x27bdffe8, 0xafbf0014, 0x14400012,
-0xafb00010, 0x3c100001, 0x26103f30, 0x2002021,
-0xc002a28, 0x24052000, 0x26021fe0, 0x3c010001,
-0xac223e98, 0x3c010001, 0xac223e94, 0xac020250,
+0x8c426da8, 0x27bdffe8, 0xafbf0014, 0x14400012,
+0xafb00010, 0x3c100001, 0x26107010, 0x2002021,
+0xc002b84, 0x24052000, 0x26021fe0, 0x3c010001,
+0xac226f68, 0x3c010001, 0xac226f64, 0xac020250,
0x24022000, 0xac100254, 0xac020258, 0x24020001,
-0x3c010001, 0xac223d18, 0x8fbf0014, 0x8fb00010,
-0x3e00008, 0x27bd0018, 0x3c090001, 0x8d293e98,
+0x3c010001, 0xac226da8, 0x8fbf0014, 0x8fb00010,
+0x3e00008, 0x27bd0018, 0x3c090001, 0x8d296f68,
0x8c820000, 0x8fa30010, 0x8fa80014, 0xad220000,
0x8c820004, 0xad250008, 0xad220004, 0x8f820054,
0xad260010, 0xad270014, 0xad230018, 0xad28001c,
-0xad22000c, 0x2529ffe0, 0x3c020001, 0x24423f30,
+0xad22000c, 0x2529ffe0, 0x3c020001, 0x24427010,
0x122102b, 0x10400003, 0x0, 0x3c090001,
-0x8d293e94, 0x3c020001, 0x8c423d00, 0xad220000,
-0x3c020001, 0x8c423d00, 0x3c010001, 0xac293e98,
+0x8d296f64, 0x3c020001, 0x8c426d90, 0xad220000,
+0x3c020001, 0x8c426d90, 0x3c010001, 0xac296f68,
0xad220004, 0xac090250, 0x3e00008, 0x0,
-0x27bdffd0, 0xafb00010, 0x3c100001, 0x8e103e98,
-0x3c020001, 0x8c423d00, 0xafb10014, 0x808821,
+0x27bdffd0, 0xafb00010, 0x3c100001, 0x8e106f68,
+0x3c020001, 0x8c426d90, 0xafb10014, 0x808821,
0xafbe0024, 0x8fbe0040, 0x8fa40048, 0xafb20018,
0xa09021, 0xafbf0028, 0xafb50020, 0xafb3001c,
-0xae020000, 0x3c020001, 0x8c423d00, 0xc09821,
+0xae020000, 0x3c020001, 0x8c426d90, 0xc09821,
0xe0a821, 0x10800006, 0xae020004, 0x26050008,
-0xc002a33, 0x24060018, 0x10000005, 0x2610ffe0,
-0x26040008, 0xc002a28, 0x24050018, 0x2610ffe0,
-0x3c030001, 0x24633f30, 0x203102b, 0x10400003,
-0x0, 0x3c100001, 0x8e103e94, 0x8e220000,
+0xc002b8f, 0x24060018, 0x10000005, 0x2610ffe0,
+0x26040008, 0xc002b84, 0x24050018, 0x2610ffe0,
+0x3c030001, 0x24637010, 0x203102b, 0x10400003,
+0x0, 0x3c100001, 0x8e106f64, 0x8e220000,
0xae020000, 0x8e220004, 0xae120008, 0xae020004,
0x8f820054, 0xae130010, 0xae150014, 0xae1e0018,
0x8fa80044, 0xae08001c, 0xae02000c, 0x2610ffe0,
0x203102b, 0x10400003, 0x0, 0x3c100001,
-0x8e103e94, 0x3c020001, 0x8c423d00, 0xae020000,
-0x3c020001, 0x8c423d00, 0x3c010001, 0xac303e98,
+0x8e106f64, 0x3c020001, 0x8c426d90, 0xae020000,
+0x3c020001, 0x8c426d90, 0x3c010001, 0xac306f68,
0xae020004, 0xac100250, 0x8fbf0028, 0x8fbe0024,
0x8fb50020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
0x8fb00010, 0x3e00008, 0x27bd0030, 0x851821,
@@ -6165,924 +6390,989 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x3e00008, 0x0, 0x63080, 0x861821,
0x83102b, 0x10400006, 0x0, 0xac850000,
0x24840004, 0x83102b, 0x5440fffd, 0xac850000,
-0x3e00008, 0x0, 0x0, 0x27bdffd8,
-0xafbf0024, 0xafb00020, 0x8f430024, 0x8f420020,
-0x10620038, 0x0, 0x8f430020, 0x8f420024,
-0x622023, 0x4810003, 0x0, 0x8f420040,
-0x822021, 0x8f430030, 0x8f420024, 0x43102b,
-0x14400005, 0x0, 0x8f430040, 0x8f420024,
-0x10000005, 0x621023, 0x8f420030, 0x8f430024,
-0x431023, 0x2442ffff, 0x406021, 0x8c102a,
-0x54400001, 0x806021, 0x8f4a0024, 0x8f490040,
-0x8f480024, 0x8f440170, 0x8f450174, 0x8f460024,
-0x8f4b001c, 0x24070001, 0xafa70010, 0x84100,
-0x1001821, 0x14c5021, 0x2529ffff, 0x1498024,
-0xafb00014, 0x8f470014, 0x1021, 0x63100,
-0xafa70018, 0xa32821, 0xa3382b, 0x822021,
-0x872021, 0x8f420108, 0x1663021, 0x40f809,
-0xc3900, 0x54400001, 0xaf500024, 0x8f430024,
-0x8f420020, 0x14620018, 0x0, 0x8f420000,
-0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
-0x1040fffd, 0x0, 0x10000005, 0x0,
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
-0x8f820060, 0x2403ffef, 0x431024, 0xaf820060,
-0x8f420000, 0x10400003, 0x0, 0x10000002,
-0xaf80004c, 0xaf800048, 0x8fbf0024, 0x8fb00020,
-0x3e00008, 0x27bd0028, 0x3e00008, 0x0,
-0x27bdffc0, 0x32c20020, 0xafbf0038, 0xafb30034,
-0xafb20030, 0xafb1002c, 0x10400004, 0xafb00028,
-0x8f530028, 0x10000002, 0x0, 0x8f530020,
-0x8f420030, 0x105300eb, 0x21100, 0x8f43001c,
-0x628021, 0x8e040000, 0x8e050004, 0x96120008,
-0x8f420090, 0x9611000a, 0x3246ffff, 0x46102a,
-0x10400017, 0x0, 0x8f8200d8, 0x8f430098,
-0x431023, 0x2442fff8, 0xaf420090, 0x8f420090,
-0x2842fff9, 0x10400005, 0x0, 0x8f420090,
-0x8f430138, 0x431021, 0xaf420090, 0x8f420090,
-0x46102a, 0x10400006, 0x0, 0x8f420338,
-0x24420001, 0xaf420338, 0x100000e1, 0x8f420338,
-0x8f8200fc, 0x14400006, 0x32c20008, 0x8f420334,
-0x24420001, 0xaf420334, 0x100000d9, 0x8f420334,
-0x5040000c, 0xaf4000ac, 0x934205b3, 0x10400008,
-0x32220200, 0x10400006, 0x3c034000, 0x9602000e,
-0xaf4300ac, 0x21400, 0x10000002, 0xaf4200b0,
-0xaf4000ac, 0x32220004, 0x1040007f, 0x32220800,
-0x10400003, 0x3247ffff, 0x10000002, 0x24020020,
-0x24020004, 0xafa20010, 0x8f420030, 0xafa20014,
-0x8f420010, 0x3c030002, 0x431025, 0xafa20018,
+0x3e00008, 0x0, 0x0, 0x3c0208ff,
+0x3442ffff, 0x3c03c0ff, 0x8f850220, 0x3463ffff,
+0x8f860200, 0xa21024, 0x34420004, 0xc31824,
+0x34630004, 0xaf820220, 0xaf830200, 0x8c820214,
+0xac020084, 0x8c820218, 0xac020088, 0x8c82021c,
+0xac02008c, 0x8c820220, 0xac020090, 0x8c820224,
+0xac020094, 0x8c820228, 0xac020098, 0x8c82022c,
+0xac02009c, 0x8c820230, 0xac0200a0, 0x8c820234,
+0xac0200a4, 0x8c820238, 0xac0200a8, 0x8c82023c,
+0xac0200ac, 0x8c820240, 0xac0200b0, 0x8c820244,
+0xac0200b4, 0x8c820248, 0xac0200b8, 0x8c82024c,
+0xac0200bc, 0x8c82001c, 0xac020080, 0x8c820018,
+0xac0200c0, 0x8c820020, 0xac0200cc, 0x8c820024,
+0xac0200d0, 0x8c8201d0, 0xac0200e0, 0x8c8201d4,
+0xac0200e4, 0x8c8201d8, 0xac0200e8, 0x8c8201dc,
+0xac0200ec, 0x8c8201e0, 0xac0200f0, 0x8c820098,
+0x8c83009c, 0xac0300fc, 0x8c8200a8, 0x8c8300ac,
+0xac0300f4, 0x8c8200a0, 0x8c8300a4, 0x30a50004,
+0xac0300f8, 0x14a00007, 0x30c20004, 0x8f820220,
+0x3c0308ff, 0x3463fffb, 0x431024, 0xaf820220,
+0x30c20004, 0x14400006, 0x0, 0x8f820200,
+0x3c03c0ff, 0x3463fffb, 0x431024, 0xaf820200,
+0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024,
+0xafb00020, 0x8f430024, 0x8f420020, 0x10620038,
+0x0, 0x8f430020, 0x8f420024, 0x622023,
+0x4810003, 0x0, 0x8f420040, 0x822021,
+0x8f430030, 0x8f420024, 0x43102b, 0x14400005,
+0x0, 0x8f430040, 0x8f420024, 0x10000005,
+0x621023, 0x8f420030, 0x8f430024, 0x431023,
+0x2442ffff, 0x406021, 0x8c102a, 0x54400001,
+0x806021, 0x8f4a0024, 0x8f490040, 0x8f480024,
+0x8f440180, 0x8f450184, 0x8f460024, 0x8f4b001c,
+0x24070001, 0xafa70010, 0x84100, 0x1001821,
+0x14c5021, 0x2529ffff, 0x1498024, 0xafb00014,
+0x8f470014, 0x1021, 0x63100, 0xafa70018,
+0xa32821, 0xa3382b, 0x822021, 0x872021,
+0x8f420108, 0x1663021, 0x40f809, 0xc3900,
+0x54400001, 0xaf500024, 0x8f430024, 0x8f420020,
+0x14620018, 0x0, 0x8f420000, 0x10400007,
+0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd,
+0x0, 0x10000005, 0x0, 0xaf800048,
+0x8f820048, 0x1040fffd, 0x0, 0x8f820060,
+0x2403ffef, 0x431024, 0xaf820060, 0x8f420000,
+0x10400003, 0x0, 0x10000002, 0xaf80004c,
+0xaf800048, 0x8fbf0024, 0x8fb00020, 0x3e00008,
+0x27bd0028, 0x3e00008, 0x0, 0x27bdffc0,
+0x32c20020, 0xafbf0038, 0xafb30034, 0xafb20030,
+0xafb1002c, 0x10400004, 0xafb00028, 0x8f530028,
+0x10000002, 0x0, 0x8f530020, 0x8f420030,
+0x105300eb, 0x21100, 0x8f43001c, 0x628021,
+0x8e040000, 0x8e050004, 0x96120008, 0x8f420090,
+0x9611000a, 0x3246ffff, 0x46102a, 0x10400017,
+0x0, 0x8f8200d8, 0x8f430098, 0x431023,
+0x2442fff8, 0xaf420090, 0x8f420090, 0x2842fff9,
+0x10400005, 0x0, 0x8f420090, 0x8f430144,
+0x431021, 0xaf420090, 0x8f420090, 0x46102a,
+0x10400006, 0x0, 0x8f420348, 0x24420001,
+0xaf420348, 0x100000e1, 0x8f420348, 0x8f8200fc,
+0x14400006, 0x0, 0x8f420344, 0x24420001,
+0xaf420344, 0x100000d9, 0x8f420344, 0x934205c2,
+0x1040000b, 0x32c20008, 0x10400008, 0x32220200,
+0x10400006, 0x3c034000, 0x9602000e, 0xaf4300ac,
+0x21400, 0x10000002, 0xaf4200b0, 0xaf4000ac,
+0x32220004, 0x1040007f, 0x32220800, 0x10400003,
+0x3247ffff, 0x10000002, 0x24020020, 0x24020004,
+0xafa20010, 0x8f420030, 0xafa20014, 0x8f420010,
+0x3c030002, 0x431025, 0xafa20018, 0x8f460098,
+0x8f420108, 0x40f809, 0x0, 0x104000b7,
+0x0, 0x8f42009c, 0x8f430094, 0x2421021,
+0xaf42009c, 0xae03000c, 0x8f4200ac, 0x10400008,
+0x3c034000, 0x8f420094, 0x431025, 0xafa20020,
+0x8f42009c, 0x8f4300b0, 0x10000004, 0x431025,
+0x8f420094, 0xafa20020, 0x8f42009c, 0xafa20024,
+0x8f8200fc, 0x8fa30020, 0x8fa40024, 0xac430000,
+0xac440004, 0x24420008, 0xaf8200f0, 0x8f42009c,
+0x8f440270, 0x8f450274, 0x401821, 0x1021,
+0xa32821, 0xa3302b, 0x822021, 0x862021,
+0x32230060, 0x24020040, 0xaf440270, 0xaf450274,
+0x10620017, 0x2c620041, 0x10400005, 0x24020020,
+0x10620008, 0x24020001, 0x10000026, 0x0,
+0x24020060, 0x10620019, 0x24020001, 0x10000021,
+0x0, 0x8f420278, 0x8f43027c, 0x24630001,
+0x2c640001, 0x441021, 0xaf420278, 0xaf43027c,
+0x8f420278, 0x8f43027c, 0x10000016, 0x24020001,
+0x8f420280, 0x8f430284, 0x24630001, 0x2c640001,
+0x441021, 0xaf420280, 0xaf430284, 0x8f420280,
+0x8f430284, 0x1000000b, 0x24020001, 0x8f420288,
+0x8f43028c, 0x24630001, 0x2c640001, 0x441021,
+0xaf420288, 0xaf43028c, 0x8f420288, 0x8f43028c,
+0x24020001, 0xa34205c2, 0x8f420098, 0x3244ffff,
+0x2406fff8, 0x8f45013c, 0x441021, 0x24420007,
+0x461024, 0x24840007, 0xaf420094, 0x8f420090,
+0x8f430094, 0x862024, 0x441023, 0x65182b,
+0x14600005, 0xaf420090, 0x8f420094, 0x8f430144,
+0x431023, 0xaf420094, 0x8f420094, 0x10000023,
+0xaf40009c, 0x3247ffff, 0x50e00022, 0x32c20020,
+0x14400002, 0x24020010, 0x24020002, 0xafa20010,
+0x8f420030, 0xafa20014, 0x8f420010, 0xafa20018,
0x8f460098, 0x8f420108, 0x40f809, 0x0,
-0x104000b7, 0x0, 0x8f42009c, 0x8f430094,
-0x2421021, 0xaf42009c, 0xae03000c, 0x8f4200ac,
-0x10400008, 0x3c034000, 0x8f420094, 0x431025,
-0xafa20020, 0x8f42009c, 0x8f4300b0, 0x10000004,
-0x431025, 0x8f420094, 0xafa20020, 0x8f42009c,
-0xafa20024, 0x8f8200fc, 0x8fa30020, 0x8fa40024,
-0xac430000, 0xac440004, 0x24420008, 0xaf8200f0,
-0x8f42009c, 0x8f440260, 0x8f450264, 0x401821,
-0x1021, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0x32230060, 0x24020040, 0xaf440260,
-0xaf450264, 0x10620017, 0x2c620041, 0x10400005,
-0x24020020, 0x10620008, 0x24020001, 0x10000026,
-0x0, 0x24020060, 0x10620019, 0x24020001,
-0x10000021, 0x0, 0x8f420268, 0x8f43026c,
-0x24630001, 0x2c640001, 0x441021, 0xaf420268,
-0xaf43026c, 0x8f420268, 0x8f43026c, 0x10000016,
-0x24020001, 0x8f420270, 0x8f430274, 0x24630001,
-0x2c640001, 0x441021, 0xaf420270, 0xaf430274,
-0x8f420270, 0x8f430274, 0x1000000b, 0x24020001,
-0x8f420278, 0x8f43027c, 0x24630001, 0x2c640001,
-0x441021, 0xaf420278, 0xaf43027c, 0x8f420278,
-0x8f43027c, 0x24020001, 0xa34205b3, 0x8f420098,
-0x3244ffff, 0x2406fff8, 0x8f450130, 0x441021,
+0x1040003a, 0x3245ffff, 0x8f420098, 0x8f430090,
+0x8f46013c, 0x451021, 0xaf420098, 0x8f42009c,
+0x8f440098, 0xa34005c2, 0x651823, 0xaf430090,
+0x451021, 0x86202b, 0x14800005, 0xaf42009c,
+0x8f420098, 0x8f430144, 0x431023, 0xaf420098,
+0x32c20020, 0x10400005, 0x0, 0x8f420358,
+0x2442ffff, 0xaf420358, 0x8f420358, 0x8f420030,
+0x8f430040, 0x24420001, 0x2463ffff, 0x431024,
+0xaf420030, 0x8f420030, 0x14530018, 0x0,
+0x8f420000, 0x10400007, 0x0, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x2403fff7, 0x431024,
+0xaf820060, 0x8f420000, 0x10400003, 0x0,
+0x10000002, 0xaf80004c, 0xaf800048, 0x8fbf0038,
+0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028,
+0x3e00008, 0x27bd0040, 0x3e00008, 0x0,
+0x27bdffd0, 0x32c20020, 0xafbf002c, 0xafb20028,
+0xafb10024, 0x10400004, 0xafb00020, 0x8f520028,
+0x10000002, 0x0, 0x8f520020, 0x8f420030,
+0x105200b5, 0x21100, 0x8f43001c, 0x628021,
+0x8e040000, 0x8e050004, 0x96110008, 0x8f420090,
+0x9607000a, 0x3226ffff, 0x46102a, 0x10400017,
+0x0, 0x8f8200d8, 0x8f430098, 0x431023,
+0x2442ff80, 0xaf420090, 0x8f420090, 0x2842ff81,
+0x10400005, 0x0, 0x8f420090, 0x8f430144,
+0x431021, 0xaf420090, 0x8f420090, 0x46102a,
+0x10400006, 0x0, 0x8f420348, 0x24420001,
+0xaf420348, 0x100000ab, 0x8f420348, 0x8f8600fc,
+0x10c0000c, 0x0, 0x8f8200f4, 0x2403fff8,
+0x431024, 0x461023, 0x218c3, 0x58600001,
+0x24630100, 0x8f42008c, 0x43102b, 0x14400006,
+0x712c2, 0x8f420344, 0x24420001, 0xaf420344,
+0x10000098, 0x8f420344, 0x934305c2, 0x1060000f,
+0x30460001, 0x8f420010, 0x34480400, 0x32c20008,
+0x10400008, 0x30e20200, 0x10400006, 0x3c034000,
+0x9602000e, 0xaf4300ac, 0x21400, 0x10000004,
+0xaf4200b0, 0x10000002, 0xaf4000ac, 0x8f480010,
+0x30e20004, 0x10400045, 0x3227ffff, 0x8f4900ac,
+0x11200005, 0x30c200ff, 0x14400006, 0x24020040,
+0x10000004, 0x24020008, 0x14400002, 0x24020020,
+0x24020004, 0xafa20010, 0x8f430030, 0x11200004,
+0xafa30014, 0x8f4200b0, 0x621025, 0xafa20014,
+0x3c020002, 0x1021025, 0xafa20018, 0x8f460098,
+0x8f420108, 0x40f809, 0x0, 0x10400069,
+0x3224ffff, 0x8f42008c, 0x8f430094, 0x24420001,
+0xaf42008c, 0x24020001, 0xae03000c, 0xa34205c2,
+0x8f420098, 0x2406fff8, 0x8f45013c, 0x441021,
0x24420007, 0x461024, 0x24840007, 0xaf420094,
0x8f420090, 0x8f430094, 0x862024, 0x441023,
0x65182b, 0x14600005, 0xaf420090, 0x8f420094,
-0x8f430138, 0x431023, 0xaf420094, 0x8f420094,
-0x10000023, 0xaf40009c, 0x3247ffff, 0x50e00022,
-0x32c20020, 0x14400002, 0x24020010, 0x24020002,
-0xafa20010, 0x8f420030, 0xafa20014, 0x8f420010,
-0xafa20018, 0x8f460098, 0x8f420108, 0x40f809,
-0x0, 0x1040003a, 0x3245ffff, 0x8f420098,
-0x8f430090, 0x8f460130, 0x451021, 0xaf420098,
-0x8f42009c, 0x8f440098, 0xa34005b3, 0x651823,
-0xaf430090, 0x451021, 0x86202b, 0x14800005,
-0xaf42009c, 0x8f420098, 0x8f430138, 0x431023,
-0xaf420098, 0x32c20020, 0x10400005, 0x0,
-0x8f420348, 0x2442ffff, 0xaf420348, 0x8f420348,
-0x8f420030, 0x8f430040, 0x24420001, 0x2463ffff,
-0x431024, 0xaf420030, 0x8f420030, 0x14530018,
-0x0, 0x8f420000, 0x10400007, 0x0,
-0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
-0x10000005, 0x0, 0xaf800048, 0x8f820048,
-0x1040fffd, 0x0, 0x8f820060, 0x2403fff7,
-0x431024, 0xaf820060, 0x8f420000, 0x10400003,
-0x0, 0x10000002, 0xaf80004c, 0xaf800048,
-0x8fbf0038, 0x8fb30034, 0x8fb20030, 0x8fb1002c,
-0x8fb00028, 0x3e00008, 0x27bd0040, 0x3e00008,
-0x0, 0x27bdffd0, 0x32c20020, 0xafbf002c,
-0xafb20028, 0xafb10024, 0x10400004, 0xafb00020,
-0x8f520028, 0x10000002, 0x0, 0x8f520020,
-0x8f420030, 0x105200b5, 0x21100, 0x8f43001c,
-0x628021, 0x8e040000, 0x8e050004, 0x96110008,
-0x8f420090, 0x9607000a, 0x3226ffff, 0x46102a,
-0x10400017, 0x0, 0x8f8200d8, 0x8f430098,
-0x431023, 0x2442ff80, 0xaf420090, 0x8f420090,
-0x2842ff81, 0x10400005, 0x0, 0x8f420090,
-0x8f430138, 0x431021, 0xaf420090, 0x8f420090,
-0x46102a, 0x10400006, 0x0, 0x8f420338,
-0x24420001, 0xaf420338, 0x100000ab, 0x8f420338,
-0x8f8600fc, 0x10c0000c, 0x0, 0x8f8200f4,
-0x2403fff8, 0x431024, 0x461023, 0x218c3,
-0x50600001, 0x24030100, 0x8f42008c, 0x43102b,
-0x14400006, 0x712c2, 0x8f420334, 0x24420001,
-0xaf420334, 0x10000098, 0x8f420334, 0x934305b3,
-0x1060000f, 0x30460001, 0x8f420010, 0x34480400,
-0x32c20008, 0x10400008, 0x30e20200, 0x10400006,
-0x3c034000, 0x9602000e, 0xaf4300ac, 0x21400,
-0x10000004, 0xaf4200b0, 0x10000002, 0xaf4000ac,
-0x8f480010, 0x30e20004, 0x10400045, 0x3227ffff,
-0x8f4900ac, 0x11200005, 0x30c200ff, 0x14400006,
-0x24020040, 0x10000004, 0x24020008, 0x14400002,
-0x24020020, 0x24020004, 0xafa20010, 0x8f430030,
-0x11200004, 0xafa30014, 0x8f4200b0, 0x621025,
-0xafa20014, 0x3c020002, 0x1021025, 0xafa20018,
+0x8f430144, 0x431023, 0xaf420094, 0x8f430094,
+0x8f420140, 0x43102b, 0x10400009, 0x0,
+0x8f43013c, 0x8f440094, 0x8f420090, 0x8f450138,
+0x641823, 0x431023, 0xaf420090, 0xaf450094,
+0x8f420094, 0x1000001f, 0xaf420098, 0x10e0001d,
+0x30c200ff, 0x14400002, 0x24020010, 0x24020002,
+0xafa20010, 0x8f420030, 0xafa80018, 0xafa20014,
0x8f460098, 0x8f420108, 0x40f809, 0x0,
-0x10400069, 0x3224ffff, 0x8f42008c, 0x8f430094,
-0x24420001, 0xaf42008c, 0x24020001, 0xae03000c,
-0xa34205b3, 0x8f420098, 0x2406fff8, 0x8f450130,
-0x441021, 0x24420007, 0x461024, 0x24840007,
-0xaf420094, 0x8f420090, 0x8f430094, 0x862024,
-0x441023, 0x65182b, 0x14600005, 0xaf420090,
-0x8f420094, 0x8f430138, 0x431023, 0xaf420094,
-0x8f430094, 0x8f420134, 0x43102b, 0x10400009,
-0x0, 0x8f430130, 0x8f440094, 0x8f420090,
-0x8f45012c, 0x641823, 0x431023, 0xaf420090,
-0xaf450094, 0x8f420094, 0x1000001f, 0xaf420098,
-0x10e0001d, 0x30c200ff, 0x14400002, 0x24020010,
-0x24020002, 0xafa20010, 0x8f420030, 0xafa80018,
-0xafa20014, 0x8f460098, 0x8f420108, 0x40f809,
-0x0, 0x10400030, 0x3225ffff, 0x8f420098,
-0x8f440130, 0x451021, 0xaf420098, 0x8f420090,
-0x8f430098, 0xa34005b3, 0x451023, 0x64182b,
-0x14600005, 0xaf420090, 0x8f420098, 0x8f430138,
-0x431023, 0xaf420098, 0x8f420030, 0x8f430040,
-0x24420001, 0x2463ffff, 0x431024, 0xaf420030,
-0x8f420030, 0x14520018, 0x0, 0x8f420000,
-0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
-0x1040fffd, 0x0, 0x10000005, 0x0,
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
-0x8f820060, 0x2403fff7, 0x431024, 0xaf820060,
-0x8f420000, 0x10400003, 0x0, 0x10000002,
-0xaf80004c, 0xaf800048, 0x8fbf002c, 0x8fb20028,
-0x8fb10024, 0x8fb00020, 0x3e00008, 0x27bd0030,
-0x3e00008, 0x0, 0x27bdffd8, 0x3c020001,
-0x34422ec0, 0xafbf0020, 0x8f4300f0, 0x8f840108,
-0x2e21021, 0x54620004, 0x24620008, 0x3c020001,
-0x34422cc0, 0x2e21021, 0x401821, 0xaf4300f0,
-0xac600000, 0x8f4200ec, 0x8c660004, 0x14620004,
-0x3c020001, 0x24820020, 0x1000000f, 0xaf820108,
-0x8f4300f0, 0x34422ec0, 0x2e21021, 0x54620004,
-0x24620008, 0x3c020001, 0x34422cc0, 0x2e21021,
-0x401821, 0x8c620004, 0x21140, 0x821021,
-0xaf820108, 0xac600000, 0x8c850018, 0x30a20036,
-0x1040006c, 0x30a20001, 0x8c82001c, 0x8f430040,
-0x8f440034, 0x24420001, 0x2463ffff, 0x431024,
-0x862021, 0xaf42002c, 0x30a20030, 0x14400006,
-0xaf440034, 0x8f420034, 0x8c03023c, 0x43102b,
-0x144000c6, 0x0, 0x32c20010, 0x10400028,
-0x24070008, 0x8f440160, 0x8f450164, 0x8f43002c,
-0x8f48000c, 0x8f860120, 0x24020080, 0xafa20010,
-0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809,
-0x24c6001c, 0x14400011, 0x24020001, 0x3c010001,
-0x370821, 0xa02240f1, 0x8f820124, 0xafa20010,
-0x8f820128, 0x3c040001, 0x24843844, 0xafa20014,
-0x8f46002c, 0x8f870120, 0x3c050009, 0xc0029bb,
-0x34a51100, 0x10000036, 0x0, 0x8f4202f0,
-0x8f43002c, 0x24420001, 0xaf4202f0, 0x8f4202f0,
-0x24020001, 0xa34205b2, 0x10000026, 0xaf430038,
-0x8f440160, 0x8f450164, 0x8f43002c, 0x8f48000c,
-0x8f860120, 0x24020020, 0xafa20010, 0xafa30014,
+0x10400030, 0x3225ffff, 0x8f420098, 0x8f44013c,
+0x451021, 0xaf420098, 0x8f420090, 0x8f430098,
+0xa34005c2, 0x451023, 0x64182b, 0x14600005,
+0xaf420090, 0x8f420098, 0x8f430144, 0x431023,
+0xaf420098, 0x8f420030, 0x8f430040, 0x24420001,
+0x2463ffff, 0x431024, 0xaf420030, 0x8f420030,
+0x14520018, 0x0, 0x8f420000, 0x10400007,
+0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd,
+0x0, 0x10000005, 0x0, 0xaf800048,
+0x8f820048, 0x1040fffd, 0x0, 0x8f820060,
+0x2403fff7, 0x431024, 0xaf820060, 0x8f420000,
+0x10400003, 0x0, 0x10000002, 0xaf80004c,
+0xaf800048, 0x8fbf002c, 0x8fb20028, 0x8fb10024,
+0x8fb00020, 0x3e00008, 0x27bd0030, 0x3e00008,
+0x0, 0x27bdffd8, 0x3c020001, 0x34422ec0,
+0xafbf0020, 0x8f4300f0, 0x8f840108, 0x2e21021,
+0x54620004, 0x24620008, 0x3c020001, 0x34422cc0,
+0x2e21021, 0x401821, 0xaf4300f0, 0xac600000,
+0x8f4200ec, 0x8c660004, 0x14620004, 0x3c020001,
+0x24820020, 0x1000000f, 0xaf820108, 0x8f4300f0,
+0x34422ec0, 0x2e21021, 0x54620004, 0x24620008,
+0x3c020001, 0x34422cc0, 0x2e21021, 0x401821,
+0x8c620004, 0x21140, 0x821021, 0xaf820108,
+0xac600000, 0x8c850018, 0x30a20036, 0x1040006c,
+0x30a20001, 0x8c82001c, 0x8f430040, 0x8f440034,
+0x24420001, 0x2463ffff, 0x431024, 0x862021,
+0xaf42002c, 0x30a20030, 0x14400006, 0xaf440034,
+0x8f420034, 0x8c03023c, 0x43102b, 0x144000ca,
+0x0, 0x32c20010, 0x10400028, 0x24070008,
+0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c,
+0x8f860120, 0x24020080, 0xafa20010, 0xafa30014,
0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c,
0x14400011, 0x24020001, 0x3c010001, 0x370821,
-0xa02240f0, 0x8f820124, 0xafa20010, 0x8f820128,
-0x3c040001, 0x24843838, 0xafa20014, 0x8f46002c,
-0x8f870120, 0x3c050009, 0xc0029bb, 0x34a50900,
-0x1000000f, 0x0, 0x8f4202f0, 0x24420001,
-0xaf4202f0, 0x8f4202f0, 0x8f42002c, 0xa34005b2,
-0xaf420038, 0x3c010001, 0x370821, 0xa02040f1,
-0x3c010001, 0x370821, 0xa02040f0, 0xaf400034,
-0x8f420304, 0x24420001, 0xaf420304, 0x1000006b,
-0x8f420304, 0x10400022, 0x30a27000, 0x8c85001c,
-0x8f420028, 0xa22023, 0x4810003, 0x0,
-0x8f420040, 0x822021, 0x8f420348, 0x8f430000,
-0xaf450028, 0x441021, 0x10600007, 0xaf420348,
-0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
-0x10000005, 0x0, 0xaf800048, 0x8f820048,
-0x1040fffd, 0x0, 0x8f820060, 0x34420008,
-0xaf820060, 0x8f420000, 0x10400003, 0x0,
-0x1000004a, 0xaf80004c, 0x10000048, 0xaf800048,
-0x1040002f, 0x30a21000, 0x1040000c, 0x30a24000,
-0x8c83001c, 0x8f420050, 0x622023, 0x4820001,
-0x24840200, 0x8f42034c, 0x441021, 0xaf42034c,
-0x8f420358, 0x1000001a, 0xaf430050, 0x1040000c,
-0x32c28000, 0x8c83001c, 0x8f420070, 0x622023,
-0x4820001, 0x24840400, 0x8f420354, 0x441021,
-0xaf420354, 0x8f420358, 0x1000000d, 0xaf430070,
-0x1040000e, 0x3c020800, 0x8c83001c, 0x8f420060,
-0x622023, 0x4820001, 0x24840100, 0x8f420350,
-0x441021, 0xaf420350, 0x8f420358, 0xaf430060,
-0x441021, 0xaf420358, 0x3c020800, 0x2c21024,
-0x5040001a, 0x36940040, 0x10000018, 0x0,
-0x30a20100, 0x10400015, 0x0, 0x3c020001,
-0x8c423cc4, 0x1040000c, 0x0, 0x274301b0,
-0x24650400, 0x65102b, 0x10400007, 0x26e40028,
-0x8c820000, 0xac620000, 0x24630004, 0x65102b,
-0x1440fffb, 0x24840004, 0x8f4202cc, 0xa34005b6,
-0x24420001, 0xaf4202cc, 0x8f4202cc, 0x8fbf0020,
-0x3e00008, 0x27bd0028, 0x3e00008, 0x0,
-0x27bdffa8, 0xafbf0050, 0xafbe004c, 0xafb50048,
-0xafb30044, 0xafb20040, 0xafb1003c, 0xafb00038,
-0x8f910108, 0x26220020, 0xaf820108, 0x8e320018,
-0xa821, 0x32420024, 0x104001b7, 0xf021,
-0x8e26001c, 0x8f42001c, 0x61900, 0x431021,
-0x8c50000c, 0x9603000c, 0x962d0016, 0x9453000a,
-0x2c6205dd, 0x10400015, 0x2821, 0x32c20040,
-0x10400015, 0x24020800, 0x96030014, 0x14620012,
-0x3402aaaa, 0x9603000e, 0x14620007, 0x2021,
-0x96030010, 0x24020300, 0x14620004, 0x801021,
-0x96020012, 0x2c440001, 0x801021, 0x54400006,
-0x24050016, 0x10000004, 0x0, 0x24020800,
-0x50620001, 0x2405000e, 0x934205b4, 0x14400008,
-0x5821, 0x240b0001, 0x32620180, 0xaf4500a8,
-0xaf5000a0, 0x10400002, 0xaf4600a4, 0xa34b05b4,
-0x10a00085, 0x2054021, 0x91020000, 0x3821,
-0x3042000f, 0x25080, 0x32c20002, 0x10400012,
-0x10a1821, 0x32620002, 0x10400010, 0x32c20001,
-0x1002021, 0x94820000, 0x24840002, 0xe23821,
-0x83102b, 0x1440fffb, 0x30e2ffff, 0x71c02,
+0xa02240f1, 0x8f820124, 0xafa20010, 0x8f820128,
+0x3c040001, 0x24846854, 0xafa20014, 0x8f46002c,
+0x8f870120, 0x3c050009, 0xc002b17, 0x34a51100,
+0x10000036, 0x0, 0x8f420300, 0x8f43002c,
+0x24420001, 0xaf420300, 0x8f420300, 0x24020001,
+0xa34205c1, 0x10000026, 0xaf430038, 0x8f440170,
+0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120,
+0x24020020, 0xafa20010, 0xafa30014, 0xafa80018,
+0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011,
+0x24020001, 0x3c010001, 0x370821, 0xa02240f0,
+0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001,
+0x24846848, 0xafa20014, 0x8f46002c, 0x8f870120,
+0x3c050009, 0xc002b17, 0x34a50900, 0x1000000f,
+0x0, 0x8f420300, 0x24420001, 0xaf420300,
+0x8f420300, 0x8f42002c, 0xa34005c1, 0xaf420038,
+0x3c010001, 0x370821, 0xa02040f1, 0x3c010001,
+0x370821, 0xa02040f0, 0xaf400034, 0x8f420314,
+0x24420001, 0xaf420314, 0x1000006f, 0x8f420314,
+0x10400022, 0x30a27000, 0x8c85001c, 0x8f420028,
+0xa22023, 0x4810003, 0x0, 0x8f420040,
+0x822021, 0x8f420358, 0x8f430000, 0xaf450028,
+0x441021, 0x10600007, 0xaf420358, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
+0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
+0x0, 0x8f820060, 0x34420008, 0xaf820060,
+0x8f420000, 0x10400003, 0x0, 0x1000004e,
+0xaf80004c, 0x1000004c, 0xaf800048, 0x1040002f,
+0x30a21000, 0x1040000c, 0x30a24000, 0x8c83001c,
+0x8f420050, 0x622023, 0x4820001, 0x24840200,
+0x8f42035c, 0x441021, 0xaf42035c, 0x8f420368,
+0x1000001a, 0xaf430050, 0x1040000c, 0x32c28000,
+0x8c83001c, 0x8f420070, 0x622023, 0x4820001,
+0x24840400, 0x8f420364, 0x441021, 0xaf420364,
+0x8f420368, 0x1000000d, 0xaf430070, 0x1040000e,
+0x3c020800, 0x8c83001c, 0x8f420060, 0x622023,
+0x4820001, 0x24840100, 0x8f420360, 0x441021,
+0xaf420360, 0x8f420368, 0xaf430060, 0x441021,
+0xaf420368, 0x3c020800, 0x2c21024, 0x5040001e,
+0x36940040, 0x1000001c, 0x0, 0x30a20100,
+0x10400019, 0x0, 0x3c020001, 0x8c426d44,
+0x1040000d, 0x274301c0, 0x24650400, 0x65102b,
+0x10400007, 0x26e40028, 0x8c820000, 0xac620000,
+0x24630004, 0x65102b, 0x1440fffb, 0x24840004,
+0x10000002, 0x274401c0, 0x26e40028, 0xc002bb4,
+0x0, 0x8f4202dc, 0xa34005c5, 0x24420001,
+0xaf4202dc, 0x8f4202dc, 0x8fbf0020, 0x3e00008,
+0x27bd0028, 0x3e00008, 0x0, 0x27bdffa8,
+0xafbf0050, 0xafbe004c, 0xafb50048, 0xafb30044,
+0xafb20040, 0xafb1003c, 0xafb00038, 0x8f910108,
+0x26220020, 0xaf820108, 0x8e320018, 0xa821,
+0x32420024, 0x104001ba, 0xf021, 0x8e26001c,
+0x8f43001c, 0x61100, 0x621821, 0x8c70000c,
+0x9604000c, 0x962d0016, 0x9473000a, 0x2c8305dd,
+0x38828870, 0x2c420001, 0x621825, 0x10600015,
+0x2821, 0x32c20040, 0x10400015, 0x24020800,
+0x96030014, 0x14620012, 0x3402aaaa, 0x9603000e,
+0x14620007, 0x2021, 0x96030010, 0x24020300,
+0x14620004, 0x801021, 0x96020012, 0x2c440001,
+0x801021, 0x54400006, 0x24050016, 0x10000004,
+0x0, 0x24020800, 0x50820001, 0x2405000e,
+0x934205c3, 0x14400008, 0x5821, 0x240b0001,
+0x32620180, 0xaf4500a8, 0xaf5000a0, 0x10400002,
+0xaf4600a4, 0xa34b05c3, 0x10a00085, 0x2054021,
+0x91020000, 0x3821, 0x3042000f, 0x25080,
+0x32c20002, 0x10400012, 0x10a1821, 0x32620002,
+0x10400010, 0x32c20001, 0x1002021, 0x94820000,
+0x24840002, 0xe23821, 0x83102b, 0x1440fffb,
+0x30e2ffff, 0x71c02, 0x623821, 0x71c02,
+0x30e2ffff, 0x623821, 0x71027, 0xa502000a,
+0x32c20001, 0x1040006a, 0x32620001, 0x10400068,
+0x0, 0x8f4200a8, 0x10400065, 0x0,
+0x8f4200a0, 0x8f4300a8, 0x431021, 0x904c0009,
+0x318900ff, 0x39230006, 0x3182b, 0x39220011,
+0x2102b, 0x621824, 0x1060000c, 0x3c050006,
+0x8f4200a4, 0x3c040001, 0x24846864, 0xafa20010,
+0x8f4200a0, 0x34a54600, 0x1203821, 0xc002b17,
+0xafa20014, 0x1000004e, 0x0, 0x32c20004,
+0x14400013, 0x2821, 0x316200ff, 0x14400004,
+0x0, 0x95020002, 0x1000000d, 0x4a2823,
+0x9505000c, 0x9502000e, 0x95030010, 0xa22821,
+0xa32821, 0x95030012, 0x91040009, 0x95020002,
+0xa32821, 0xa42821, 0x4a1023, 0xa22821,
+0x2002021, 0x94820000, 0x24840002, 0xe23821,
+0x88102b, 0x1440fffb, 0x71c02, 0x30e2ffff,
0x623821, 0x71c02, 0x30e2ffff, 0x623821,
-0x71027, 0xa502000a, 0x32c20001, 0x1040006a,
-0x32620001, 0x10400068, 0x0, 0x8f4200a8,
-0x10400065, 0x0, 0x8f4200a0, 0x8f4300a8,
-0x431021, 0x904c0009, 0x318900ff, 0x39230006,
-0x3182b, 0x39220011, 0x2102b, 0x621824,
-0x1060000c, 0x3c050006, 0x8f4200a4, 0x3c040001,
-0x24843854, 0xafa20010, 0x8f4200a0, 0x34a54600,
-0x1203821, 0xc0029bb, 0xafa20014, 0x1000004e,
-0x0, 0x32c20004, 0x14400013, 0x2821,
-0x316200ff, 0x14400004, 0x0, 0x95020002,
-0x1000000d, 0x4a2823, 0x9505000c, 0x9502000e,
-0x95030010, 0xa22821, 0xa32821, 0x95030012,
-0x91040009, 0x95020002, 0xa32821, 0xa42821,
-0x4a1023, 0xa22821, 0x2002021, 0x94820000,
-0x24840002, 0xe23821, 0x88102b, 0x1440fffb,
-0x71c02, 0x30e2ffff, 0x623821, 0x71c02,
-0x30e2ffff, 0x623821, 0x1a52821, 0x51c02,
-0x30a2ffff, 0x622821, 0x51c02, 0x30a2ffff,
-0x622821, 0xa72823, 0x51402, 0xa22821,
-0x30a5ffff, 0x50a00001, 0x3405ffff, 0x316200ff,
-0x14400008, 0x318300ff, 0x8f4300a0, 0x8f4200a8,
-0x624021, 0x91020000, 0x3042000f, 0x25080,
-0x318300ff, 0x24020006, 0x14620003, 0x10a1021,
-0x10000002, 0x24440010, 0x24440006, 0x316200ff,
-0x14400006, 0x0, 0x94820000, 0xa22821,
-0x51c02, 0x30a2ffff, 0x622821, 0x934205b4,
-0x10400003, 0x32620100, 0x50400003, 0xa4850000,
-0x52827, 0xa4850000, 0x9622000e, 0x8f43009c,
-0x621821, 0x32a200ff, 0x10400007, 0xaf43009c,
-0x3c024000, 0x2021025, 0xafa20020, 0x8f42009c,
-0x10000003, 0x5e1025, 0xafb00020, 0x8f42009c,
-0xafa20024, 0x32620080, 0x10400010, 0x32620100,
-0x8f4200b4, 0x24430001, 0x210c0, 0x571021,
-0xaf4300b4, 0x8fa30020, 0x8fa40024, 0x3c010001,
-0x220821, 0xac2338e8, 0x3c010001, 0x220821,
-0xac2438ec, 0x100000a5, 0x32c20020, 0x10400064,
-0x0, 0x8f4200b4, 0x24430001, 0x210c0,
-0x571021, 0xaf4300b4, 0x8fa30020, 0x8fa40024,
-0x3c010001, 0x220821, 0xac2338e8, 0x3c010001,
-0x220821, 0xac2438ec, 0x8f4200b4, 0x10400051,
-0x3821, 0x3c090001, 0x352938e8, 0x3c08001f,
-0x3508ffff, 0x240bffff, 0x340affff, 0x710c0,
-0x571021, 0x491021, 0x8c430000, 0x8c440004,
-0xafa30028, 0xafa4002c, 0x8f8200fc, 0x8fa30028,
-0x8fa4002c, 0xac430000, 0xac440004, 0x24420008,
-0xaf8200f0, 0x8f42008c, 0x2442ffff, 0xaf42008c,
-0x97a2002e, 0x8f440260, 0x8f450264, 0x401821,
-0x1021, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xaf440260, 0xaf450264, 0x8fa20028,
-0x481024, 0x90430000, 0x30630001, 0x1460000b,
-0x402021, 0x8f420268, 0x8f43026c, 0x24630001,
-0x2c640001, 0x441021, 0xaf420268, 0xaf43026c,
-0x8f420268, 0x1000001a, 0x8f43026c, 0x8c820000,
-0x144b000e, 0x0, 0x94820004, 0x144a000b,
-0x0, 0x8f420278, 0x8f43027c, 0x24630001,
-0x2c640001, 0x441021, 0xaf420278, 0xaf43027c,
-0x8f420278, 0x1000000a, 0x8f43027c, 0x8f420270,
-0x8f430274, 0x24630001, 0x2c640001, 0x441021,
-0xaf420270, 0xaf430274, 0x8f420270, 0x8f430274,
-0x8f4200b4, 0x24e70001, 0xe2102b, 0x1440ffb8,
-0x710c0, 0xa34005b4, 0x1000003f, 0xaf4000b4,
-0x8f8200fc, 0x8fa30020, 0x8fa40024, 0xac430000,
-0xac440004, 0x24420008, 0xaf8200f0, 0x8f42009c,
-0x8f46008c, 0x8f440260, 0x8f450264, 0x401821,
-0x1021, 0x24c6ffff, 0xaf46008c, 0xa32821,
-0xa3302b, 0x822021, 0x862021, 0xaf440260,
-0xaf450264, 0x92020000, 0x30420001, 0x1440000c,
-0x2402ffff, 0x8f420268, 0x8f43026c, 0x24630001,
-0x2c640001, 0x441021, 0xaf420268, 0xaf43026c,
-0x8f420268, 0x8f43026c, 0x1000001c, 0x32c20020,
-0x8e030000, 0x1462000f, 0x3402ffff, 0x96030004,
-0x1462000c, 0x0, 0x8f420278, 0x8f43027c,
-0x24630001, 0x2c640001, 0x441021, 0xaf420278,
-0xaf43027c, 0x8f420278, 0x8f43027c, 0x1000000b,
-0x32c20020, 0x8f420270, 0x8f430274, 0x24630001,
-0x2c640001, 0x441021, 0xaf420270, 0xaf430274,
-0x8f420270, 0x8f430274, 0x32c20020, 0x10400005,
-0xaf40009c, 0x8f420348, 0x2442ffff, 0xaf420348,
-0x8f420348, 0x8e22001c, 0x8f430040, 0x24420001,
-0x2463ffff, 0x431024, 0xaf42002c, 0x32420060,
-0x14400008, 0x32c20010, 0x8f420034, 0x24420001,
-0xaf420034, 0x8c03023c, 0x43102b, 0x14400114,
-0x32c20010, 0x10400018, 0x24070008, 0x8f440160,
-0x8f450164, 0x8f43002c, 0x8f48000c, 0x8f860120,
-0x24020080, 0xafa20010, 0xafa30014, 0xafa80018,
-0x8f42010c, 0x40f809, 0x24c6001c, 0x10400047,
-0x24020001, 0x8f4202f0, 0x8f43002c, 0x24420001,
-0xaf4202f0, 0x8f4202f0, 0x24020001, 0xa34205b2,
-0x1000007c, 0xaf430038, 0x8f440160, 0x8f450164,
-0x8f43002c, 0x8f48000c, 0x8f860120, 0x24020020,
-0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c,
-0x40f809, 0x24c6001c, 0x10400057, 0x24020001,
-0x10000065, 0x0, 0x32420012, 0x10400075,
-0x32420001, 0x9622000e, 0x8f43009c, 0x621821,
-0x32c20020, 0x10400005, 0xaf43009c, 0x8f420348,
-0x2442ffff, 0xaf420348, 0x8f420348, 0x8e22001c,
+0x1a52821, 0x51c02, 0x30a2ffff, 0x622821,
+0x51c02, 0x30a2ffff, 0x622821, 0xa72823,
+0x51402, 0xa22821, 0x30a5ffff, 0x50a00001,
+0x3405ffff, 0x316200ff, 0x14400008, 0x318300ff,
+0x8f4300a0, 0x8f4200a8, 0x624021, 0x91020000,
+0x3042000f, 0x25080, 0x318300ff, 0x24020006,
+0x14620003, 0x10a1021, 0x10000002, 0x24440010,
+0x24440006, 0x316200ff, 0x14400006, 0x0,
+0x94820000, 0xa22821, 0x51c02, 0x30a2ffff,
+0x622821, 0x934205c3, 0x10400003, 0x32620100,
+0x50400003, 0xa4850000, 0x52827, 0xa4850000,
+0x9622000e, 0x8f43009c, 0x621821, 0x32a200ff,
+0x10400007, 0xaf43009c, 0x3c024000, 0x2021025,
+0xafa20020, 0x8f42009c, 0x10000003, 0x5e1025,
+0xafb00020, 0x8f42009c, 0xafa20024, 0x32620080,
+0x10400010, 0x32620100, 0x8f4200b4, 0x24430001,
+0x210c0, 0x571021, 0xaf4300b4, 0x8fa30020,
+0x8fa40024, 0x3c010001, 0x220821, 0xac2338e8,
+0x3c010001, 0x220821, 0xac2438ec, 0x100000a5,
+0x32c20020, 0x10400064, 0x0, 0x8f4200b4,
+0x24430001, 0x210c0, 0x571021, 0xaf4300b4,
+0x8fa30020, 0x8fa40024, 0x3c010001, 0x220821,
+0xac2338e8, 0x3c010001, 0x220821, 0xac2438ec,
+0x8f4200b4, 0x10400051, 0x3821, 0x3c090001,
+0x352938e8, 0x3c08001f, 0x3508ffff, 0x240bffff,
+0x340affff, 0x710c0, 0x571021, 0x491021,
+0x8c430000, 0x8c440004, 0xafa30028, 0xafa4002c,
+0x8f8200fc, 0x8fa30028, 0x8fa4002c, 0xac430000,
+0xac440004, 0x24420008, 0xaf8200f0, 0x8f42008c,
+0x2442ffff, 0xaf42008c, 0x97a2002e, 0x8f440270,
+0x8f450274, 0x401821, 0x1021, 0xa32821,
+0xa3302b, 0x822021, 0x862021, 0xaf440270,
+0xaf450274, 0x8fa20028, 0x481024, 0x90430000,
+0x30630001, 0x1460000b, 0x402021, 0x8f420278,
+0x8f43027c, 0x24630001, 0x2c640001, 0x441021,
+0xaf420278, 0xaf43027c, 0x8f420278, 0x1000001a,
+0x8f43027c, 0x8c820000, 0x144b000e, 0x0,
+0x94820004, 0x144a000b, 0x0, 0x8f420288,
+0x8f43028c, 0x24630001, 0x2c640001, 0x441021,
+0xaf420288, 0xaf43028c, 0x8f420288, 0x1000000a,
+0x8f43028c, 0x8f420280, 0x8f430284, 0x24630001,
+0x2c640001, 0x441021, 0xaf420280, 0xaf430284,
+0x8f420280, 0x8f430284, 0x8f4200b4, 0x24e70001,
+0xe2102b, 0x1440ffb8, 0x710c0, 0xa34005c3,
+0x1000003f, 0xaf4000b4, 0x8f8200fc, 0x8fa30020,
+0x8fa40024, 0xac430000, 0xac440004, 0x24420008,
+0xaf8200f0, 0x8f42009c, 0x8f46008c, 0x8f440270,
+0x8f450274, 0x401821, 0x1021, 0x24c6ffff,
+0xaf46008c, 0xa32821, 0xa3302b, 0x822021,
+0x862021, 0xaf440270, 0xaf450274, 0x92020000,
+0x30420001, 0x1440000c, 0x2402ffff, 0x8f420278,
+0x8f43027c, 0x24630001, 0x2c640001, 0x441021,
+0xaf420278, 0xaf43027c, 0x8f420278, 0x8f43027c,
+0x1000001c, 0x32c20020, 0x8e030000, 0x1462000f,
+0x3402ffff, 0x96030004, 0x1462000c, 0x0,
+0x8f420288, 0x8f43028c, 0x24630001, 0x2c640001,
+0x441021, 0xaf420288, 0xaf43028c, 0x8f420288,
+0x8f43028c, 0x1000000b, 0x32c20020, 0x8f420280,
+0x8f430284, 0x24630001, 0x2c640001, 0x441021,
+0xaf420280, 0xaf430284, 0x8f420280, 0x8f430284,
+0x32c20020, 0x10400005, 0xaf40009c, 0x8f420358,
+0x2442ffff, 0xaf420358, 0x8f420358, 0x8e22001c,
0x8f430040, 0x24420001, 0x2463ffff, 0x431024,
-0xaf42002c, 0x32420010, 0x14400008, 0x32c20010,
+0xaf42002c, 0x32420060, 0x14400008, 0x32c20010,
0x8f420034, 0x24420001, 0xaf420034, 0x8c03023c,
-0x43102b, 0x144000ce, 0x32c20010, 0x10400028,
-0x24070008, 0x8f440160, 0x8f450164, 0x8f43002c,
+0x43102b, 0x14400118, 0x32c20010, 0x10400018,
+0x24070008, 0x8f440170, 0x8f450174, 0x8f43002c,
0x8f48000c, 0x8f860120, 0x24020080, 0xafa20010,
0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809,
-0x24c6001c, 0x14400011, 0x24020001, 0x3c010001,
-0x370821, 0xa02240f1, 0x8f820124, 0xafa20010,
-0x8f820128, 0x3c040001, 0x24843844, 0xafa20014,
-0x8f46002c, 0x8f870120, 0x3c050009, 0xc0029bb,
-0x34a51100, 0x10000036, 0x0, 0x8f4202f0,
-0x8f43002c, 0x24420001, 0xaf4202f0, 0x8f4202f0,
-0x24020001, 0xa34205b2, 0x10000026, 0xaf430038,
-0x8f440160, 0x8f450164, 0x8f43002c, 0x8f48000c,
+0x24c6001c, 0x10400047, 0x24020001, 0x8f420300,
+0x8f43002c, 0x24420001, 0xaf420300, 0x8f420300,
+0x24020001, 0xa34205c1, 0x1000007c, 0xaf430038,
+0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c,
0x8f860120, 0x24020020, 0xafa20010, 0xafa30014,
0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c,
-0x14400011, 0x24020001, 0x3c010001, 0x370821,
-0xa02240f0, 0x8f820124, 0xafa20010, 0x8f820128,
-0x3c040001, 0x24843838, 0xafa20014, 0x8f46002c,
-0x8f870120, 0x3c050009, 0xc0029bb, 0x34a50900,
-0x1000000f, 0x0, 0x8f4202f0, 0x24420001,
-0xaf4202f0, 0x8f4202f0, 0x8f42002c, 0xa34005b2,
-0xaf420038, 0x3c010001, 0x370821, 0xa02040f1,
-0x3c010001, 0x370821, 0xa02040f0, 0xaf400034,
-0x8f420304, 0x24420001, 0xaf420304, 0x10000074,
-0x8f420304, 0x10400022, 0x32427000, 0x8e25001c,
-0x8f420028, 0xa22023, 0x4810003, 0x0,
-0x8f420040, 0x822021, 0x8f420348, 0x8f430000,
-0xaf450028, 0x441021, 0x10600007, 0xaf420348,
-0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
-0x10000005, 0x0, 0xaf800048, 0x8f820048,
-0x1040fffd, 0x0, 0x8f820060, 0x34420008,
-0xaf820060, 0x8f420000, 0x10400003, 0x0,
-0x10000053, 0xaf80004c, 0x10000051, 0xaf800048,
-0x1040002f, 0x32421000, 0x1040000c, 0x32424000,
-0x8e23001c, 0x8f420050, 0x622023, 0x4820001,
-0x24840200, 0x8f42034c, 0x441021, 0xaf42034c,
-0x8f420358, 0x1000001a, 0xaf430050, 0x1040000c,
-0x32c28000, 0x8e23001c, 0x8f420070, 0x622023,
-0x4820001, 0x24840400, 0x8f420354, 0x441021,
-0xaf420354, 0x8f420358, 0x1000000d, 0xaf430070,
-0x1040000e, 0x3c020800, 0x8e23001c, 0x8f420060,
-0x622023, 0x4820001, 0x24840100, 0x8f420350,
-0x441021, 0xaf420350, 0x8f420358, 0xaf430060,
-0x441021, 0xaf420358, 0x3c020800, 0x2c21024,
-0x50400023, 0x36940040, 0x10000021, 0x0,
-0x32420048, 0x10400007, 0x24150001, 0x8e22001c,
-0x3c03ffff, 0x43f024, 0x3042ffff, 0x1000fd78,
-0xae22001c, 0x32420100, 0x10400015, 0x0,
-0x3c020001, 0x8c423cc4, 0x1040000c, 0x0,
-0x274301b0, 0x24650400, 0x65102b, 0x10400007,
-0x26e40028, 0x8c820000, 0xac620000, 0x24630004,
-0x65102b, 0x1440fffb, 0x24840004, 0x8f4202cc,
-0xa34005b6, 0x24420001, 0xaf4202cc, 0x8f4202cc,
-0x8fbf0050, 0x8fbe004c, 0x8fb50048, 0x8fb30044,
-0x8fb20040, 0x8fb1003c, 0x8fb00038, 0x3e00008,
-0x27bd0058, 0x3e00008, 0x0, 0x8f8400e0,
-0x8f8800c4, 0x8f8300e8, 0x2402fff8, 0x823824,
-0xe32023, 0x2c821000, 0x50400001, 0x24841000,
-0x420c2, 0x801821, 0x8f440248, 0x8f45024c,
+0x10400057, 0x24020001, 0x10000065, 0x0,
+0x32420012, 0x10400075, 0x32420001, 0x9622000e,
+0x8f43009c, 0x621821, 0x32c20020, 0x10400005,
+0xaf43009c, 0x8f420358, 0x2442ffff, 0xaf420358,
+0x8f420358, 0x8e22001c, 0x8f430040, 0x24420001,
+0x2463ffff, 0x431024, 0xaf42002c, 0x32420010,
+0x14400008, 0x32c20010, 0x8f420034, 0x24420001,
+0xaf420034, 0x8c03023c, 0x43102b, 0x144000d2,
+0x32c20010, 0x10400028, 0x24070008, 0x8f440170,
+0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120,
+0x24020080, 0xafa20010, 0xafa30014, 0xafa80018,
+0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011,
+0x24020001, 0x3c010001, 0x370821, 0xa02240f1,
+0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001,
+0x24846854, 0xafa20014, 0x8f46002c, 0x8f870120,
+0x3c050009, 0xc002b17, 0x34a51100, 0x10000036,
+0x0, 0x8f420300, 0x8f43002c, 0x24420001,
+0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1,
+0x10000026, 0xaf430038, 0x8f440170, 0x8f450174,
+0x8f43002c, 0x8f48000c, 0x8f860120, 0x24020020,
+0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c,
+0x40f809, 0x24c6001c, 0x14400011, 0x24020001,
+0x3c010001, 0x370821, 0xa02240f0, 0x8f820124,
+0xafa20010, 0x8f820128, 0x3c040001, 0x24846848,
+0xafa20014, 0x8f46002c, 0x8f870120, 0x3c050009,
+0xc002b17, 0x34a50900, 0x1000000f, 0x0,
+0x8f420300, 0x24420001, 0xaf420300, 0x8f420300,
+0x8f42002c, 0xa34005c1, 0xaf420038, 0x3c010001,
+0x370821, 0xa02040f1, 0x3c010001, 0x370821,
+0xa02040f0, 0xaf400034, 0x8f420314, 0x24420001,
+0xaf420314, 0x10000078, 0x8f420314, 0x10400022,
+0x32427000, 0x8e25001c, 0x8f420028, 0xa22023,
+0x4810003, 0x0, 0x8f420040, 0x822021,
+0x8f420358, 0x8f430000, 0xaf450028, 0x441021,
+0x10600007, 0xaf420358, 0xaf80004c, 0x8f82004c,
+0x1040fffd, 0x0, 0x10000005, 0x0,
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
+0x8f820060, 0x34420008, 0xaf820060, 0x8f420000,
+0x10400003, 0x0, 0x10000057, 0xaf80004c,
+0x10000055, 0xaf800048, 0x1040002f, 0x32421000,
+0x1040000c, 0x32424000, 0x8e23001c, 0x8f420050,
+0x622023, 0x4820001, 0x24840200, 0x8f42035c,
+0x441021, 0xaf42035c, 0x8f420368, 0x1000001a,
+0xaf430050, 0x1040000c, 0x32c28000, 0x8e23001c,
+0x8f420070, 0x622023, 0x4820001, 0x24840400,
+0x8f420364, 0x441021, 0xaf420364, 0x8f420368,
+0x1000000d, 0xaf430070, 0x1040000e, 0x3c020800,
+0x8e23001c, 0x8f420060, 0x622023, 0x4820001,
+0x24840100, 0x8f420360, 0x441021, 0xaf420360,
+0x8f420368, 0xaf430060, 0x441021, 0xaf420368,
+0x3c020800, 0x2c21024, 0x50400027, 0x36940040,
+0x10000025, 0x0, 0x32420048, 0x10400007,
+0x24150001, 0x8e22001c, 0x3c03ffff, 0x43f024,
+0x3042ffff, 0x1000fd75, 0xae22001c, 0x32420100,
+0x10400019, 0x0, 0x3c020001, 0x8c426d44,
+0x1040000d, 0x274301c0, 0x24650400, 0x65102b,
+0x10400007, 0x26e40028, 0x8c820000, 0xac620000,
+0x24630004, 0x65102b, 0x1440fffb, 0x24840004,
+0x10000002, 0x274401c0, 0x26e40028, 0xc002bb4,
+0x0, 0x8f4202dc, 0xa34005c5, 0x24420001,
+0xaf4202dc, 0x8f4202dc, 0x8fbf0050, 0x8fbe004c,
+0x8fb50048, 0x8fb30044, 0x8fb20040, 0x8fb1003c,
+0x8fb00038, 0x3e00008, 0x27bd0058, 0x3e00008,
+0x0, 0x0, 0x0, 0x8f8300e4,
+0x8f8200e0, 0x2404fff8, 0x441024, 0x621026,
+0x2102b, 0x21023, 0x3e00008, 0x621024,
+0x3e00008, 0x0, 0x27bdffe0, 0xafbf001c,
+0xafb00018, 0x8f8600c4, 0x8f8400e0, 0x8f8500e4,
+0x2402fff8, 0x821824, 0x10a30009, 0x27623ff8,
+0x14a20002, 0x24a20008, 0x27623000, 0x408021,
+0x16030005, 0x30820004, 0x10400004, 0xc02021,
+0x10000022, 0x1021, 0x8e040000, 0x8f42011c,
+0x14a20003, 0x0, 0x8f420120, 0xaf420114,
+0x8ca30000, 0x8f420148, 0x831823, 0x43102b,
+0x10400003, 0x0, 0x8f420148, 0x621821,
+0x94a20006, 0x24420050, 0x62102b, 0x1440000f,
+0xa01021, 0xafa40010, 0xafa30014, 0x8ca60000,
+0x8ca70004, 0x3c040001, 0xc002b17, 0x24846924,
+0x8f42020c, 0x24420001, 0xaf42020c, 0x8f42020c,
+0x1021, 0xaf9000e8, 0xaf9000e4, 0x8fbf001c,
+0x8fb00018, 0x3e00008, 0x27bd0020, 0x3e00008,
+0x0, 0x8f8400e0, 0x8f8800c4, 0x8f8300e8,
+0x2402fff8, 0x823824, 0xe32023, 0x2c821000,
+0x50400001, 0x24841000, 0x420c2, 0x801821,
+0x8f440258, 0x8f45025c, 0x1021, 0xa32821,
+0xa3302b, 0x822021, 0x862021, 0xaf440258,
+0xaf45025c, 0x8f8300c8, 0x8f420148, 0x1032023,
+0x82102b, 0x14400004, 0x801821, 0x8f420148,
+0x822021, 0x801821, 0x8f440250, 0x8f450254,
0x1021, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xaf440248, 0xaf45024c, 0x8f8300c8,
-0x8f42013c, 0x1032023, 0x82102b, 0x14400004,
-0x801821, 0x8f42013c, 0x822021, 0x801821,
-0x8f440240, 0x8f450244, 0x1021, 0xa32821,
-0xa3302b, 0x822021, 0x862021, 0xaf440240,
-0xaf450244, 0xaf8800c8, 0xaf8700e4, 0xaf8700e8,
-0x3e00008, 0x0, 0x27bdff30, 0x240a0001,
-0xafbf00c8, 0xafbe00c4, 0xafb500c0, 0xafb300bc,
-0xafb200b8, 0xafb100b4, 0xafb000b0, 0xa3a00097,
-0xafa00044, 0xafaa005c, 0x934205b5, 0xa7a0008e,
-0x1040000a, 0xa7a00086, 0x8f4b00c4, 0xafab0064,
-0x8f4a00c0, 0xafaa006c, 0x8f4b00cc, 0xafab0074,
-0x8f4a00c8, 0x10000129, 0xafaa007c, 0x8f420114,
-0x40f809, 0x0, 0x403021, 0x10c0033f,
-0x0, 0x8cc20000, 0x8cc30004, 0xafa20020,
-0xafa30024, 0x8fab0024, 0x8faa0020, 0x3162ffff,
-0x2442fffc, 0xafa2006c, 0x3c020006, 0x2c21024,
-0xafab007c, 0x14400015, 0xafaa0064, 0x91420000,
-0x30420001, 0x10400011, 0x2402ffff, 0x8d430000,
-0x14620004, 0x3402ffff, 0x95430004, 0x1062000b,
-0x0, 0xc00233b, 0x8fa40064, 0x304200ff,
-0x14400006, 0x0, 0x8f420118, 0x40f809,
-0x0, 0x1000031d, 0x0, 0x8fa20024,
-0x3c03ffbf, 0x3463ffff, 0x431024, 0x3c03ffff,
-0x431824, 0x14600003, 0xafa20024, 0x10000040,
-0x1821, 0x3c020080, 0x621024, 0x10400007,
-0x0, 0x8f42037c, 0x24420001, 0xaf42037c,
-0x8f42037c, 0x10000036, 0x24030001, 0x8f420200,
-0x24420001, 0xaf420200, 0x8f420200, 0x3c020001,
-0x621024, 0x10400006, 0x3c020002, 0x8f4201b4,
-0x24420001, 0xaf4201b4, 0x8f4201b4, 0x3c020002,
-0x621024, 0x10400006, 0x3c020004, 0x8f42036c,
-0x24420001, 0xaf42036c, 0x8f42036c, 0x3c020004,
-0x621024, 0x10400006, 0x3c020008, 0x8f420370,
-0x24420001, 0xaf420370, 0x8f420370, 0x3c020008,
-0x621024, 0x10400006, 0x3c020010, 0x8f420374,
-0x24420001, 0xaf420374, 0x8f420374, 0x3c020010,
-0x621024, 0x10400006, 0x3c020020, 0x8f4201b0,
-0x24420001, 0xaf4201b0, 0x8f4201b0, 0x3c020020,
-0x621024, 0x10400006, 0x24030001, 0x8f420378,
-0x24420001, 0xaf420378, 0x8f420378, 0x24030001,
-0x8c020260, 0x8fab006c, 0x4b102b, 0x10400014,
-0x307000ff, 0x8f4201d8, 0x24420001, 0xaf4201d8,
-0x8f4201d8, 0x8faa007c, 0x8f8200e0, 0x354a0100,
-0xafaa007c, 0xafa20010, 0x8f8200e4, 0x24100001,
-0x3c040001, 0x24843914, 0xafa20014, 0x8fa60020,
-0x8fa70024, 0x3c050007, 0xc0029bb, 0x34a50800,
-0x12000010, 0x3c020080, 0x2c21024, 0x1440000e,
-0x32c20400, 0x8fab007c, 0x3c020080, 0x34420100,
-0x1621024, 0x10400005, 0x0, 0x8f4201fc,
-0x24420001, 0xaf4201fc, 0x8f4201fc, 0x100002a0,
-0x8fa3006c, 0x32c20400, 0x10400015, 0x34028100,
-0x8faa0064, 0x9543000c, 0x14620012, 0x3c020100,
-0x240b0200, 0xa7ab008e, 0x9542000e, 0x8d430008,
-0x8d440004, 0x8d450000, 0x8faa006c, 0x8fab0064,
-0x254afffc, 0xafaa006c, 0xa7a20086, 0xad63000c,
-0xad640008, 0xad650004, 0x256b0004, 0xafab0064,
-0x3c020100, 0x2c21024, 0x10400004, 0x0,
-0x8faa006c, 0x254a0004, 0xafaa006c, 0x8f4200bc,
-0x5040000a, 0xafa00074, 0x8fab006c, 0x4b102b,
-0x50400006, 0xafa00074, 0x8f4200bc, 0x1621023,
-0xafa20074, 0x8f4a00bc, 0xafaa006c, 0x8f420080,
-0x8fab006c, 0x4b102b, 0x10400056, 0x32c28000,
-0x1040005e, 0x240a0003, 0x32c21000, 0x1040005b,
-0xafaa005c, 0x10000058, 0x240b0004, 0x8f420340,
-0x2403ffbf, 0x283a024, 0x24420001, 0xaf420340,
-0x1000023f, 0x8f420340, 0x2c2b025, 0x2402ffbf,
-0x282a024, 0x8f830128, 0x3c040001, 0x24843944,
-0x26620001, 0xafa20014, 0xafa30010, 0x8f860120,
-0x8f870124, 0x3c050007, 0xc0029bb, 0x34a52250,
-0x1000022f, 0x0, 0x2c2b025, 0x2402ffbf,
-0x282a024, 0x8f830128, 0x3c040001, 0x24843944,
-0x24020002, 0xafa20014, 0xafa30010, 0x8f860120,
-0x8f870124, 0x3c050007, 0xc0029bb, 0x34a52450,
-0x1000021f, 0x0, 0x8ea20000, 0x8ea30004,
-0x3c040001, 0x2484395c, 0xafb00010, 0xafbe0014,
-0x8ea70018, 0x34a52800, 0xc0029bb, 0x603021,
-0x10000213, 0x0, 0xa6b1000a, 0x8f820124,
-0x3c040001, 0x24843964, 0xafbe0014, 0xafa20010,
-0x8f460044, 0x8f870120, 0x3c050007, 0xc0029bb,
-0x34a53000, 0x10000206, 0x0, 0xa6b1000a,
-0xa6b2000e, 0x8f820124, 0x3c040001, 0x24843970,
+0x862021, 0xaf440250, 0xaf450254, 0xaf8800c8,
+0xaf8700e4, 0xaf8700e8, 0x3e00008, 0x0,
+0x27bdff30, 0x240a0001, 0xafbf00c8, 0xafbe00c4,
+0xafb500c0, 0xafb300bc, 0xafb200b8, 0xafb100b4,
+0xafb000b0, 0xa3a00097, 0xafa00044, 0xafaa005c,
+0x934205c4, 0xa7a0008e, 0x1040000a, 0xa7a00086,
+0x8f4b00c4, 0xafab0064, 0x8f4a00c0, 0xafaa006c,
+0x8f4b00cc, 0xafab0074, 0x8f4a00c8, 0x10000129,
+0xafaa007c, 0x8f420114, 0x40f809, 0x0,
+0x403021, 0x10c0033f, 0x0, 0x8cc20000,
+0x8cc30004, 0xafa20020, 0xafa30024, 0x8fab0024,
+0x8faa0020, 0x3162ffff, 0x2442fffc, 0xafa2006c,
+0x3c020006, 0x2c21024, 0xafab007c, 0x14400015,
+0xafaa0064, 0x91420000, 0x30420001, 0x10400011,
+0x2402ffff, 0x8d430000, 0x14620004, 0x3402ffff,
+0x95430004, 0x1062000b, 0x0, 0xc002497,
+0x8fa40064, 0x304200ff, 0x14400006, 0x0,
+0x8f420118, 0x40f809, 0x0, 0x1000031d,
+0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff,
+0x431024, 0x3c03ffff, 0x431824, 0x14600003,
+0xafa20024, 0x10000040, 0x1821, 0x3c020080,
+0x621024, 0x10400007, 0x0, 0x8f42038c,
+0x24420001, 0xaf42038c, 0x8f42038c, 0x10000036,
+0x24030001, 0x8f420210, 0x24420001, 0xaf420210,
+0x8f420210, 0x3c020001, 0x621024, 0x10400006,
+0x3c020002, 0x8f4201c4, 0x24420001, 0xaf4201c4,
+0x8f4201c4, 0x3c020002, 0x621024, 0x10400006,
+0x3c020004, 0x8f42037c, 0x24420001, 0xaf42037c,
+0x8f42037c, 0x3c020004, 0x621024, 0x10400006,
+0x3c020008, 0x8f420380, 0x24420001, 0xaf420380,
+0x8f420380, 0x3c020008, 0x621024, 0x10400006,
+0x3c020010, 0x8f420384, 0x24420001, 0xaf420384,
+0x8f420384, 0x3c020010, 0x621024, 0x10400006,
+0x3c020020, 0x8f4201c0, 0x24420001, 0xaf4201c0,
+0x8f4201c0, 0x3c020020, 0x621024, 0x10400006,
+0x24030001, 0x8f420388, 0x24420001, 0xaf420388,
+0x8f420388, 0x24030001, 0x8c020260, 0x8fab006c,
+0x4b102b, 0x10400014, 0x307000ff, 0x8f4201e8,
+0x24420001, 0xaf4201e8, 0x8f4201e8, 0x8faa007c,
+0x8f8200e0, 0x354a0100, 0xafaa007c, 0xafa20010,
+0x8f8200e4, 0x24100001, 0x3c040001, 0x24846930,
+0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050007,
+0xc002b17, 0x34a50800, 0x12000010, 0x3c020080,
+0x2c21024, 0x1440000e, 0x32c20400, 0x8fab007c,
+0x3c020080, 0x34420100, 0x1621024, 0x10400005,
+0x0, 0x8f42020c, 0x24420001, 0xaf42020c,
+0x8f42020c, 0x100002a0, 0x8fa3006c, 0x32c20400,
+0x10400015, 0x34028100, 0x8faa0064, 0x9543000c,
+0x14620012, 0x3c020100, 0x240b0200, 0xa7ab008e,
+0x9542000e, 0x8d430008, 0x8d440004, 0x8d450000,
+0x8faa006c, 0x8fab0064, 0x254afffc, 0xafaa006c,
+0xa7a20086, 0xad63000c, 0xad640008, 0xad650004,
+0x256b0004, 0xafab0064, 0x3c020100, 0x2c21024,
+0x10400004, 0x0, 0x8faa006c, 0x254a0004,
+0xafaa006c, 0x8f4200bc, 0x5040000a, 0xafa00074,
+0x8fab006c, 0x4b102b, 0x50400006, 0xafa00074,
+0x8f4200bc, 0x1621023, 0xafa20074, 0x8f4a00bc,
+0xafaa006c, 0x8f420080, 0x8fab006c, 0x4b102b,
+0x10400056, 0x32c28000, 0x1040005e, 0x240a0003,
+0x32c21000, 0x1040005b, 0xafaa005c, 0x10000058,
+0x240b0004, 0x8f420350, 0x2403ffbf, 0x283a024,
+0x24420001, 0xaf420350, 0x1000023f, 0x8f420350,
+0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128,
+0x3c040001, 0x24846960, 0x26620001, 0xafa20014,
+0xafa30010, 0x8f860120, 0x8f870124, 0x3c050007,
+0xc002b17, 0x34a52250, 0x1000022f, 0x0,
+0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128,
+0x3c040001, 0x24846960, 0x24020002, 0xafa20014,
+0xafa30010, 0x8f860120, 0x8f870124, 0x3c050007,
+0xc002b17, 0x34a52450, 0x1000021f, 0x0,
+0x8ea20000, 0x8ea30004, 0x3c040001, 0x24846978,
+0xafb00010, 0xafbe0014, 0x8ea70018, 0x34a52800,
+0xc002b17, 0x603021, 0x10000213, 0x0,
+0xa6b1000a, 0x8f820124, 0x3c040001, 0x24846980,
0xafbe0014, 0xafa20010, 0x8f460044, 0x8f870120,
-0x3c050007, 0xc0029bb, 0x34a53200, 0x100001f8,
-0x0, 0x8f420084, 0x8faa006c, 0x4a102b,
-0x14400007, 0x3c020001, 0x2c21024, 0x10400004,
-0x0, 0x240b0002, 0xafab005c, 0x8faa006c,
-0x1140020b, 0x27ab0020, 0xafab00a4, 0x3c0a001f,
-0x354affff, 0xafaa009c, 0x8fab005c, 0x240a0001,
-0x156a0021, 0x24020002, 0x8f430054, 0x8f420050,
-0x1062000b, 0x274b0054, 0x8f5e0054, 0x3403ecc0,
-0xafab004c, 0x27c20001, 0x304201ff, 0xafa20054,
-0x1e1140, 0x431021, 0x1000006b, 0x2e2a821,
-0x8f420044, 0x8faa006c, 0x3c040001, 0x24843920,
-0xafaa0014, 0xafa20010, 0x8f460054, 0x8f470050,
-0x3c050007, 0xc0029bb, 0x34a51300, 0x8f430340,
-0x2402ffbf, 0x282a024, 0x24630001, 0xaf430340,
-0x100001c3, 0x8f420340, 0x1562001d, 0x0,
-0x8f430074, 0x8f420070, 0x1062000a, 0x274a0074,
-0x8f5e0074, 0xafaa004c, 0x27c20001, 0x304203ff,
-0xafa20054, 0x1e1140, 0x24426cc0, 0x1000004a,
-0x2e2a821, 0x8f420044, 0x8fab006c, 0x3c040001,
-0x2484392c, 0x3c050007, 0xafab0014, 0xafa20010,
-0x8f460074, 0x8f470070, 0x34a51500, 0x240a0001,
-0xc0029bb, 0xafaa005c, 0x1000ffc3, 0x0,
-0x8f430064, 0x8f420060, 0x1062001a, 0x274b0064,
-0x8f5e0064, 0x8faa005c, 0xafab004c, 0x27c20001,
-0x304200ff, 0xafa20054, 0x24020004, 0x1542000e,
-0x1e1140, 0x1e1180, 0x24420cc0, 0x2e21021,
-0xafa20044, 0x9442002a, 0x8fab0044, 0x8faa006c,
-0x4a102b, 0x10400024, 0x25750020, 0x240b0001,
-0x10000021, 0xa3ab0097, 0x24424cc0, 0x1000001e,
-0x2e2a821, 0x8f420044, 0x8faa006c, 0x3c040001,
-0x24843938, 0xafaa0014, 0xafa20010, 0x8f460064,
-0x8f470060, 0x3c050007, 0xc0029bb, 0x34a51800,
-0x3c020008, 0x2c21024, 0x1440ff34, 0x0,
-0x8f420360, 0x240b0001, 0xafab005c, 0x24420001,
-0xaf420360, 0x1000ff90, 0x8f420360, 0x27a30036,
-0x131040, 0x621821, 0x94620000, 0x441021,
-0x10000020, 0xa4620000, 0x8faa0064, 0xaeaa0018,
-0x93a20097, 0x10400072, 0x9821, 0x8fab0044,
-0x8fa4006c, 0x8fa300a4, 0x25620020, 0xafa20028,
-0x25620008, 0xafa20030, 0x25620010, 0xafab002c,
-0xafa20034, 0x9562002a, 0xa7a20038, 0x95620018,
-0xa7a2003a, 0x9562001a, 0xa7a2003c, 0x9562001c,
-0xa7a2003e, 0x94620018, 0x24630002, 0x822023,
-0x1880ffde, 0x26730001, 0x2e620004, 0x1440fff9,
-0x0, 0x8f4200fc, 0x26650001, 0xa2102a,
-0x1440002b, 0x24030001, 0x8f83012c, 0x10600023,
-0x0, 0x8f820124, 0x431023, 0x22143,
-0x58800001, 0x24840040, 0x8f820128, 0x431023,
-0x21943, 0x58600001, 0x24630040, 0x64102a,
-0x54400001, 0x602021, 0xaf4400fc, 0x8f4200fc,
-0xa2102a, 0x10400011, 0x24030001, 0x10000015,
-0x306200ff, 0x8faa0064, 0x96070018, 0xafaa0010,
-0x8e220008, 0x3c040001, 0x24843950, 0x8c430004,
-0x8c420000, 0x34a52400, 0x2403021, 0xc0029bb,
-0xafa30014, 0x1000002b, 0x0, 0x8f420324,
-0x1821, 0x24420001, 0xaf420324, 0x8f420324,
-0x306200ff, 0x5040fedc, 0x3c020800, 0x12600021,
-0x9021, 0x8fb100a4, 0x2208021, 0x8e220008,
-0x96070018, 0x8fa60064, 0x8c440000, 0x8c450004,
-0x240b0001, 0xafab0010, 0xafbe0014, 0x8f420008,
-0xafa20018, 0x8f42010c, 0x40f809, 0x0,
-0x1040ffd8, 0x3c050007, 0x96020018, 0x8faa0064,
-0x8fab009c, 0x1425021, 0x16a102b, 0x10400004,
-0xafaa0064, 0x8f42013c, 0x1425023, 0xafaa0064,
-0x26100002, 0x26520001, 0x253102b, 0x1440ffe3,
-0x26310004, 0x8fb0006c, 0x10000036, 0x97b10038,
-0x8f4200fc, 0x24050002, 0xa2102a, 0x1440001b,
-0x24030001, 0x8f83012c, 0x10600013, 0x0,
-0x8f820124, 0x431023, 0x22143, 0x58800001,
-0x24840040, 0x8f820128, 0x431023, 0x21943,
-0x58600001, 0x24630040, 0x64102a, 0x54400001,
-0x602021, 0xaf4400fc, 0x8f4200fc, 0xa2102a,
-0x14400006, 0x24030001, 0x8f420324, 0x1821,
-0x24420001, 0xaf420324, 0x8f420324, 0x306200ff,
-0x1040fea5, 0x3c020800, 0x96b1000a, 0x8fb0006c,
-0x3223ffff, 0x70102b, 0x54400001, 0x608021,
-0x8ea40000, 0x8ea50004, 0x240a0001, 0xafaa0010,
-0xafbe0014, 0x8f420008, 0x8fa60064, 0xafa20018,
-0x8f42010c, 0x40f809, 0x2003821, 0x1040fea2,
-0x3c050007, 0x96a3000e, 0x97ab008e, 0x11600007,
-0x609021, 0x934205b5, 0x14400004, 0x0,
-0x97aa0086, 0x6b1825, 0xa6aa0016, 0x8fab007c,
-0x3c02ffff, 0x1621024, 0x10400003, 0xb1402,
-0x34630400, 0xa6a20014, 0x8faa006c, 0x560a0072,
-0xa6a3000e, 0x34620004, 0xa6a2000e, 0x8fab0074,
-0x14b1021, 0xa6a2000a, 0x8f430044, 0x8f440190,
-0x8f450194, 0x34028000, 0xafa20010, 0x8f420044,
-0x2a03021, 0x24070020, 0xafa20014, 0x8f42000c,
-0x31940, 0x604821, 0xafa20018, 0x8f42010c,
-0x4021, 0xa92821, 0xa9182b, 0x882021,
-0x40f809, 0x832021, 0x5040fe7f, 0xa6b2000e,
-0x8f420358, 0xafa0006c, 0xa34005b5, 0x2442ffff,
-0xaf420358, 0x8faa005c, 0x240b0001, 0x8f420358,
-0x154b0006, 0x24020002, 0x8f42034c, 0x2442ffff,
-0xaf42034c, 0x1000000c, 0x8f42034c, 0x15420006,
-0x0, 0x8f420354, 0x2442ffff, 0xaf420354,
-0x10000005, 0x8f420354, 0x8f420350, 0x2442ffff,
-0xaf420350, 0x8f420350, 0x8faa0054, 0x8fab004c,
-0xad6a0000, 0x8f420044, 0x8f440088, 0x8f430078,
-0x24420001, 0x441024, 0x24630001, 0xaf420044,
-0xaf430078, 0x8c020240, 0x62182b, 0x14600065,
-0x24070008, 0x8f440158, 0x8f45015c, 0x8f430044,
-0x8f48000c, 0x8f860120, 0x24020040, 0xafa20010,
-0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809,
-0x24c6001c, 0x14400011, 0x240b0001, 0x3c010001,
-0x370821, 0xa02b40f2, 0x8f820124, 0xafa20010,
-0x8f820128, 0x3c040001, 0x2484390c, 0xafa20014,
-0x8f460044, 0x8f870120, 0x3c050009, 0xc0029bb,
-0x34a51300, 0x1000000b, 0x0, 0x8f4202f4,
-0x24420001, 0xaf4202f4, 0x8f4202f4, 0x8f420044,
-0xaf42007c, 0x3c010001, 0x370821, 0xa02040f2,
-0xaf400078, 0x8f420308, 0x24420001, 0xaf420308,
-0x10000038, 0x8f420308, 0xa6b0000a, 0x8f430044,
-0x8f440190, 0x8f450194, 0x34028000, 0xafa20010,
-0x8f420044, 0x2a03021, 0x24070020, 0xafa20014,
-0x8f42000c, 0x31940, 0x604821, 0xafa20018,
-0x8f42010c, 0x4021, 0xa92821, 0xa9182b,
-0x882021, 0x40f809, 0x832021, 0x1040fe1f,
-0x240a0001, 0xa34a05b5, 0x8fab006c, 0x8faa0064,
-0x1705823, 0xafab006c, 0x8fab009c, 0x1505021,
-0x16a102b, 0x10400004, 0xafaa0064, 0x8f42013c,
-0x1425023, 0xafaa0064, 0x8f420358, 0x2442ffff,
-0xaf420358, 0x8f420358, 0x8f42034c, 0x2442ffff,
-0xaf42034c, 0x8fab0054, 0x8faa004c, 0x8f42034c,
-0xad4b0000, 0x8f420044, 0x8f440088, 0x8f430078,
-0x24420001, 0x441024, 0x24630001, 0xaf420044,
-0xaf430078, 0x8faa006c, 0x1540fe1b, 0x0,
-0x8fab006c, 0x1160001e, 0x0, 0x934205b5,
-0x10400009, 0x0, 0x8faa0064, 0xaf4a00c4,
-0xaf4b00c0, 0x8fab007c, 0xaf4b00c8, 0x8faa0074,
-0x1000000e, 0xaf4a00cc, 0x97ab008e, 0x1160000b,
-0x34038100, 0x8fa20020, 0x8c46000c, 0xa443000c,
-0x97aa0086, 0x8c440004, 0x8c450008, 0xa44a000e,
-0xac440000, 0xac450004, 0xac460008, 0x8f42033c,
-0x24420001, 0xaf42033c, 0x10000010, 0x8f42033c,
-0x8fab007c, 0x3164ffff, 0x2484fffc, 0x801821,
-0x8f440240, 0x8f450244, 0x8f460118, 0x1021,
-0xa32821, 0xa3382b, 0x822021, 0x872021,
-0xaf440240, 0xc0f809, 0xaf450244, 0x8fbf00c8,
-0x8fbe00c4, 0x8fb500c0, 0x8fb300bc, 0x8fb200b8,
-0x8fb100b4, 0x8fb000b0, 0x3e00008, 0x27bd00d0,
-0x3e00008, 0x0, 0x27bdff38, 0x240b0001,
-0xafbf00c0, 0xafbe00bc, 0xafb500b8, 0xafb300b4,
-0xafb200b0, 0xafb100ac, 0xafb000a8, 0xa3a00087,
-0xafa00044, 0xafab005c, 0x934205b5, 0xa7a00076,
-0x10400007, 0xa7a0007e, 0x8f4c00c0, 0xafac0064,
-0x8f4b00c8, 0x8f5e00c4, 0x1000012d, 0xafab006c,
-0x8f420114, 0x40f809, 0x0, 0x403021,
-0x10c0029e, 0x0, 0x8cc20000, 0x8cc30004,
-0xafa20020, 0xafa30024, 0x8fac0024, 0x8fbe0020,
-0x3182ffff, 0x2442fffc, 0xafa20064, 0x3c020006,
-0x2c21024, 0x14400015, 0xafac006c, 0x93c20000,
-0x30420001, 0x10400011, 0x2402ffff, 0x8fc30000,
-0x14620004, 0x3402ffff, 0x97c30004, 0x1062000b,
-0x0, 0xc00233b, 0x3c02021, 0x304200ff,
-0x14400006, 0x0, 0x8f420118, 0x40f809,
-0x0, 0x1000027d, 0x0, 0x8fa20024,
-0x3c03ffbf, 0x3463ffff, 0x431024, 0x3c03ffff,
-0x431824, 0x14600003, 0xafa20024, 0x10000040,
-0x8021, 0x3c020080, 0x621024, 0x10400007,
-0x0, 0x8f42037c, 0x24420001, 0xaf42037c,
-0x8f42037c, 0x10000036, 0x24100001, 0x8f420200,
-0x24420001, 0xaf420200, 0x8f420200, 0x3c020001,
-0x621024, 0x10400006, 0x3c020002, 0x8f4201b4,
-0x24420001, 0xaf4201b4, 0x8f4201b4, 0x3c020002,
-0x621024, 0x10400006, 0x3c020004, 0x8f42036c,
-0x24420001, 0xaf42036c, 0x8f42036c, 0x3c020004,
-0x621024, 0x10400006, 0x3c020008, 0x8f420370,
-0x24420001, 0xaf420370, 0x8f420370, 0x3c020008,
-0x621024, 0x10400006, 0x3c020010, 0x8f420374,
-0x24420001, 0xaf420374, 0x8f420374, 0x3c020010,
-0x621024, 0x10400006, 0x3c020020, 0x8f4201b0,
-0x24420001, 0xaf4201b0, 0x8f4201b0, 0x3c020020,
-0x621024, 0x10400006, 0x24100001, 0x8f420378,
-0x24420001, 0xaf420378, 0x8f420378, 0x24100001,
-0x8c020260, 0x8fab0064, 0x4b102b, 0x10400015,
-0x320200ff, 0x8f4201d8, 0x24420001, 0xaf4201d8,
-0x8f4201d8, 0x8fac006c, 0x8f8200e0, 0x358c0100,
-0xafac006c, 0xafa20010, 0x8f8200e4, 0x24100001,
-0x3c040001, 0x24843914, 0xafa20014, 0x8fa60020,
-0x8fa70024, 0x3c050007, 0xc0029bb, 0x34a53600,
-0x320200ff, 0x10400010, 0x3c020080, 0x2c21024,
-0x1440000e, 0x32c20400, 0x8fab006c, 0x3c020080,
-0x34420100, 0x1621024, 0x10400005, 0x0,
-0x8f4201fc, 0x24420001, 0xaf4201fc, 0x8f4201fc,
-0x100001ff, 0x8fa30064, 0x32c20400, 0x10400012,
-0x34028100, 0x97c3000c, 0x1462000f, 0x0,
-0x240c0200, 0xa7ac0076, 0x97c2000e, 0x8fc30008,
-0x8fc40004, 0x8fab0064, 0x8fc50000, 0x256bfffc,
-0xafab0064, 0xa7a2007e, 0xafc3000c, 0xafc40008,
-0xafc50004, 0x27de0004, 0x8fa70064, 0x320200ff,
-0x14400031, 0x3c020100, 0x97c3000c, 0x2c6205dd,
-0x10400015, 0x2821, 0x32c20800, 0x10400015,
-0x24020800, 0x97c30014, 0x14620012, 0x3402aaaa,
-0x97c3000e, 0x14620007, 0x2021, 0x97c30010,
-0x24020300, 0x14620004, 0x801021, 0x97c20012,
-0x2c440001, 0x801021, 0x54400006, 0x24050016,
-0x10000004, 0x0, 0x24020800, 0x50620001,
-0x2405000e, 0x10a00013, 0x3c52021, 0x24830009,
-0x3c02001f, 0x3442ffff, 0x43102b, 0x10400003,
-0x0, 0x8f42013c, 0x621823, 0x90620000,
-0x38430006, 0x2c630001, 0x38420011, 0x2c420001,
-0x621825, 0x10600004, 0x3c020100, 0x94820002,
-0x453821, 0x3c020100, 0x2c21024, 0x5040000e,
-0xafa70064, 0x8fac0064, 0x10ec0008, 0x3c050007,
-0x3c040001, 0x2484397c, 0x8fa60064, 0x34a54000,
-0xafa00010, 0xc0029bb, 0xafa00014, 0x8fab0064,
-0x256b0004, 0xafab0064, 0x8f420080, 0x8fac0064,
-0x4c102b, 0x1040002c, 0x32c28000, 0x10400034,
-0x240b0003, 0x32c21000, 0x10400031, 0xafab005c,
-0x1000002e, 0x240c0004, 0x8f420340, 0x2403ffbf,
-0x283a024, 0x24420001, 0xaf420340, 0x10000173,
-0x8f420340, 0x3c020800, 0x2c2b025, 0x2402ffbf,
-0x282a024, 0x8f830128, 0x3c040001, 0x24843944,
-0x26620001, 0xafa20014, 0xafa30010, 0x8f860120,
-0x8f870124, 0x3c050007, 0xc0029bb, 0x34a55300,
-0x10000162, 0x0, 0x8ea20000, 0x8ea30004,
-0x3c040001, 0x2484395c, 0xafb00010, 0xafb10014,
-0x8ea70018, 0x34a55900, 0xc0029bb, 0x603021,
-0x10000156, 0x0, 0x8f420084, 0x8fab0064,
-0x4b102b, 0x14400007, 0x3c020001, 0x2c21024,
-0x10400004, 0x0, 0x240c0002, 0xafac005c,
-0x8fab0064, 0x11600166, 0x27ac0020, 0xafac008c,
-0x8fab005c, 0x240c0001, 0x556c0021, 0x240c0002,
+0x3c050007, 0xc002b17, 0x34a53000, 0x10000206,
+0x0, 0xa6b1000a, 0xa6b2000e, 0x8f820124,
+0x3c040001, 0x2484698c, 0xafbe0014, 0xafa20010,
+0x8f460044, 0x8f870120, 0x3c050007, 0xc002b17,
+0x34a53200, 0x100001f8, 0x0, 0x8f420084,
+0x8faa006c, 0x4a102b, 0x14400007, 0x3c020001,
+0x2c21024, 0x10400004, 0x0, 0x240b0002,
+0xafab005c, 0x8faa006c, 0x1140020b, 0x27ab0020,
+0xafab00a4, 0x3c0a001f, 0x354affff, 0xafaa009c,
+0x8fab005c, 0x240a0001, 0x156a0021, 0x24020002,
0x8f430054, 0x8f420050, 0x1062000b, 0x274b0054,
-0x8f510054, 0x3403ecc0, 0xafab004c, 0x26220001,
-0x304201ff, 0xafa20054, 0x111140, 0x431021,
-0x1000006b, 0x2e2a821, 0x8f420044, 0x8fac0064,
-0x3c040001, 0x24843920, 0xafac0014, 0xafa20010,
-0x8f460054, 0x8f470050, 0x3c050007, 0xc0029bb,
-0x34a54300, 0x8f430340, 0x2402ffbf, 0x282a024,
-0x24630001, 0xaf430340, 0x10000124, 0x8f420340,
-0x156c001d, 0x0, 0x8f430074, 0x8f420070,
-0x1062000a, 0x274b0074, 0x8f510074, 0xafab004c,
-0x26220001, 0x304203ff, 0xafa20054, 0x111140,
+0x8f5e0054, 0x3403ecc0, 0xafab004c, 0x27c20001,
+0x304201ff, 0xafa20054, 0x1e1140, 0x431021,
+0x1000006b, 0x2e2a821, 0x8f420044, 0x8faa006c,
+0x3c040001, 0x2484693c, 0xafaa0014, 0xafa20010,
+0x8f460054, 0x8f470050, 0x3c050007, 0xc002b17,
+0x34a51300, 0x8f430350, 0x2402ffbf, 0x282a024,
+0x24630001, 0xaf430350, 0x100001c3, 0x8f420350,
+0x1562001d, 0x0, 0x8f430074, 0x8f420070,
+0x1062000a, 0x274a0074, 0x8f5e0074, 0xafaa004c,
+0x27c20001, 0x304203ff, 0xafa20054, 0x1e1140,
0x24426cc0, 0x1000004a, 0x2e2a821, 0x8f420044,
-0x8fac0064, 0x3c040001, 0x2484392c, 0x3c050007,
-0xafac0014, 0xafa20010, 0x8f460074, 0x8f470070,
-0x34a54500, 0x240b0001, 0xc0029bb, 0xafab005c,
+0x8fab006c, 0x3c040001, 0x24846948, 0x3c050007,
+0xafab0014, 0xafa20010, 0x8f460074, 0x8f470070,
+0x34a51500, 0x240a0001, 0xc002b17, 0xafaa005c,
0x1000ffc3, 0x0, 0x8f430064, 0x8f420060,
-0x1062001a, 0x274c0064, 0x8f510064, 0x8fab005c,
-0xafac004c, 0x26220001, 0x304200ff, 0xafa20054,
-0x24020004, 0x1562000e, 0x111140, 0x111180,
+0x1062001a, 0x274b0064, 0x8f5e0064, 0x8faa005c,
+0xafab004c, 0x27c20001, 0x304200ff, 0xafa20054,
+0x24020004, 0x1542000e, 0x1e1140, 0x1e1180,
0x24420cc0, 0x2e21021, 0xafa20044, 0x9442002a,
-0x8fac0044, 0x8fab0064, 0x4b102b, 0x10400024,
-0x25950020, 0x240c0001, 0x10000021, 0xa3ac0087,
+0x8fab0044, 0x8faa006c, 0x4a102b, 0x10400024,
+0x25750020, 0x240b0001, 0x10000021, 0xa3ab0097,
0x24424cc0, 0x1000001e, 0x2e2a821, 0x8f420044,
-0x8fab0064, 0x3c040001, 0x24843938, 0xafab0014,
+0x8faa006c, 0x3c040001, 0x24846954, 0xafaa0014,
0xafa20010, 0x8f460064, 0x8f470060, 0x3c050007,
-0xc0029bb, 0x34a54800, 0x3c020008, 0x2c21024,
-0x1440ff61, 0x0, 0x8f420360, 0x240c0001,
-0xafac005c, 0x24420001, 0xaf420360, 0x1000ff90,
-0x8f420360, 0x27a30036, 0x131040, 0x621821,
-0x94620000, 0x441021, 0x1000001f, 0xa4620000,
-0xaebe0018, 0x93a20087, 0x10400084, 0x9821,
-0x8fab0044, 0x8fa40064, 0x8fa3008c, 0x25620020,
-0xafa20028, 0x25620008, 0xafa20030, 0x25620010,
-0xafab002c, 0xafa20034, 0x9562002a, 0xa7a20038,
-0x95620018, 0xa7a2003a, 0x9562001a, 0xa7a2003c,
-0x9562001c, 0xa7a2003e, 0x94620018, 0x24630002,
-0x822023, 0x1880ffdf, 0x26730001, 0x2e620004,
-0x1440fff9, 0x0, 0x8f4200fc, 0x262102a,
-0x14400030, 0x24030001, 0x8f83012c, 0x10600028,
-0x0, 0x8f820124, 0x431023, 0x22143,
-0x58800001, 0x24840040, 0x8f820128, 0x431023,
-0x21943, 0x58600001, 0x24630040, 0x64102a,
-0x54400001, 0x602021, 0xaf4400fc, 0x8f4200fc,
-0x262102a, 0x10400016, 0x24030001, 0x1000001a,
-0x306200ff, 0x8fac008c, 0x101040, 0x4c1021,
-0x94470018, 0x101080, 0x4c1021, 0xafbe0010,
-0x8c420008, 0x3c040001, 0x24843950, 0x3c050007,
-0x8c430004, 0x8c420000, 0x34a55500, 0x2003021,
-0xc0029bb, 0xafa30014, 0x10000039, 0x0,
-0x8f420324, 0x1821, 0x24420001, 0xaf420324,
-0x8f420324, 0x306200ff, 0x1040ff06, 0x8021,
-0x8f430008, 0x2402fbff, 0x1260002d, 0x625024,
-0x3c0b4000, 0x22b4025, 0x8fb1008c, 0x2669ffff,
-0x2209021, 0x8e420008, 0x96270018, 0x8c440000,
-0x8c450004, 0x56090004, 0x240b0001, 0x240c0002,
-0x10000002, 0xafac0010, 0xafab0010, 0x16000004,
-0xafa80014, 0x8f420008, 0x10000002, 0xafa20018,
-0xafaa0018, 0x8f42010c, 0x3c03021, 0xafa80098,
-0xafa9009c, 0x40f809, 0xafaa00a0, 0x8fa80098,
-0x8fa9009c, 0x8faa00a0, 0x1040ffc2, 0x3c02001f,
-0x96230018, 0x3442ffff, 0x3c3f021, 0x5e102b,
-0x10400003, 0x26310002, 0x8f42013c, 0x3c2f023,
-0x26100001, 0x213102b, 0x1440ffda, 0x26520004,
-0x8fb00064, 0x1000001a, 0x0, 0x96a3000a,
-0x8fb00064, 0x70102b, 0x54400001, 0x608021,
-0x8ea40000, 0x8ea50004, 0x8fab005c, 0x240c0002,
-0xafac0010, 0x934305b5, 0xb1700, 0x10600003,
-0x2223025, 0x3c020800, 0xc23025, 0xafa60014,
-0x8f420008, 0xafa20018, 0x8f42010c, 0x3c03021,
-0x40f809, 0x2003821, 0x1040fecb, 0x3c050007,
-0x97ac0076, 0x11800007, 0x96a3000e, 0x934205b5,
-0x14400004, 0x0, 0x97ab007e, 0x6c1825,
-0xa6ab0016, 0x8fac006c, 0x3c02ffff, 0x1821024,
-0x10400003, 0xc1402, 0x34630400, 0xa6a20014,
-0xa6b0000a, 0x8fab0064, 0x560b0006, 0x3d0f021,
-0x34620004, 0xafa00064, 0xa6a2000e, 0x1000000d,
-0xa34005b5, 0x8fac0064, 0x3c02001f, 0x3442ffff,
-0x5e102b, 0x1906023, 0xafac0064, 0xa6a3000e,
-0x240b0001, 0x10400003, 0xa34b05b5, 0x8f42013c,
-0x3c2f023, 0x8fab0054, 0x8fac004c, 0xad8b0000,
-0x8fac0064, 0x1580feba, 0x0, 0x8fab0064,
-0x1160001b, 0x0, 0x934205b5, 0x10400006,
-0x0, 0xaf5e00c4, 0xaf4b00c0, 0x8fac006c,
-0x1000000e, 0xaf4c00c8, 0x97ab0076, 0x1160000b,
-0x34038100, 0x8fa20020, 0x8c46000c, 0xa443000c,
-0x97ac007e, 0x8c440004, 0x8c450008, 0xa44c000e,
-0xac440000, 0xac450004, 0xac460008, 0x8f42033c,
-0x24420001, 0xaf42033c, 0x10000010, 0x8f42033c,
-0x8fab006c, 0x3164ffff, 0x2484fffc, 0x801821,
-0x8f440240, 0x8f450244, 0x8f460118, 0x1021,
-0xa32821, 0xa3382b, 0x822021, 0x872021,
-0xaf440240, 0xc0f809, 0xaf450244, 0x8fbf00c0,
-0x8fbe00bc, 0x8fb500b8, 0x8fb300b4, 0x8fb200b0,
-0x8fb100ac, 0x8fb000a8, 0x3e00008, 0x27bd00c8,
-0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024,
-0xafb00020, 0x8f43005c, 0x8f420058, 0x10620049,
-0x0, 0x8f430058, 0x8f42005c, 0x622023,
-0x4820001, 0x24840100, 0x8f430064, 0x8f42005c,
-0x43102b, 0x14400004, 0x24020100, 0x8f43005c,
-0x10000005, 0x431023, 0x8f420064, 0x8f43005c,
-0x431023, 0x2442ffff, 0x403821, 0x87102a,
-0x54400001, 0x803821, 0x8f42005c, 0x471021,
-0x305000ff, 0x32c21000, 0x10400015, 0x24082000,
-0x8f49005c, 0x8f440180, 0x8f450184, 0x8f46005c,
-0x73980, 0xafa80010, 0xafb00014, 0x8f480014,
-0x94980, 0x1201821, 0x1021, 0xa32821,
-0xa3482b, 0x822021, 0x892021, 0x63180,
-0xafa80018, 0x8f420108, 0x10000014, 0x24c60cc0,
-0x8f49005c, 0x8f440180, 0x8f450184, 0x8f46005c,
-0x73940, 0xafa80010, 0xafb00014, 0x8f480014,
-0x94940, 0x1201821, 0x1021, 0xa32821,
-0xa3482b, 0x822021, 0x892021, 0x63140,
-0xafa80018, 0x8f420108, 0x24c64cc0, 0x40f809,
-0x2e63021, 0x54400001, 0xaf50005c, 0x8f43005c,
-0x8f420058, 0x14620018, 0x0, 0x8f420000,
-0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
-0x1040fffd, 0x0, 0x10000005, 0x0,
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
-0x8f820060, 0x2403feff, 0x431024, 0xaf820060,
-0x8f420000, 0x10400003, 0x0, 0x10000002,
-0xaf80004c, 0xaf800048, 0x8fbf0024, 0x8fb00020,
-0x3e00008, 0x27bd0028, 0x3e00008, 0x0,
-0x27bdffd8, 0xafbf0024, 0xafb00020, 0x8f43006c,
-0x8f420068, 0x10620033, 0x0, 0x8f430068,
-0x8f42006c, 0x622023, 0x4820001, 0x24840400,
-0x8f430074, 0x8f42006c, 0x43102b, 0x14400004,
-0x24020400, 0x8f43006c, 0x10000005, 0x431023,
-0x8f420074, 0x8f43006c, 0x431023, 0x2442ffff,
-0x405021, 0x8a102a, 0x54400001, 0x805021,
-0x8f49006c, 0x8f48006c, 0x8f440188, 0x8f45018c,
-0x8f46006c, 0x24074000, 0xafa70010, 0x84140,
-0x1001821, 0x12a4821, 0x313003ff, 0xafb00014,
-0x8f470014, 0x1021, 0x63140, 0x24c66cc0,
-0xafa70018, 0xa32821, 0xa3382b, 0x822021,
-0x872021, 0x8f420108, 0x2e63021, 0x40f809,
-0xa3940, 0x54400001, 0xaf50006c, 0x8f43006c,
-0x8f420068, 0x14620018, 0x0, 0x8f420000,
+0xc002b17, 0x34a51800, 0x3c020008, 0x2c21024,
+0x1440ff34, 0x0, 0x8f420370, 0x240b0001,
+0xafab005c, 0x24420001, 0xaf420370, 0x1000ff90,
+0x8f420370, 0x27a30036, 0x131040, 0x621821,
+0x94620000, 0x441021, 0x10000020, 0xa4620000,
+0x8faa0064, 0xaeaa0018, 0x93a20097, 0x10400072,
+0x9821, 0x8fab0044, 0x8fa4006c, 0x8fa300a4,
+0x25620020, 0xafa20028, 0x25620008, 0xafa20030,
+0x25620010, 0xafab002c, 0xafa20034, 0x9562002a,
+0xa7a20038, 0x95620018, 0xa7a2003a, 0x9562001a,
+0xa7a2003c, 0x9562001c, 0xa7a2003e, 0x94620018,
+0x24630002, 0x822023, 0x1880ffde, 0x26730001,
+0x2e620004, 0x1440fff9, 0x0, 0x8f4200fc,
+0x26650001, 0xa2102a, 0x1440002b, 0x24030001,
+0x8f83012c, 0x10600023, 0x0, 0x8f820124,
+0x431023, 0x22143, 0x58800001, 0x24840040,
+0x8f820128, 0x431023, 0x21943, 0x58600001,
+0x24630040, 0x64102a, 0x54400001, 0x602021,
+0xaf4400fc, 0x8f4200fc, 0xa2102a, 0x10400011,
+0x24030001, 0x10000015, 0x306200ff, 0x8faa0064,
+0x96070018, 0xafaa0010, 0x8e220008, 0x3c040001,
+0x2484696c, 0x8c430004, 0x8c420000, 0x34a52400,
+0x2403021, 0xc002b17, 0xafa30014, 0x1000002b,
+0x0, 0x8f420334, 0x1821, 0x24420001,
+0xaf420334, 0x8f420334, 0x306200ff, 0x5040fedc,
+0x3c020800, 0x12600021, 0x9021, 0x8fb100a4,
+0x2208021, 0x8e220008, 0x96070018, 0x8fa60064,
+0x8c440000, 0x8c450004, 0x240b0001, 0xafab0010,
+0xafbe0014, 0x8f420008, 0xafa20018, 0x8f42010c,
+0x40f809, 0x0, 0x1040ffd8, 0x3c050007,
+0x96020018, 0x8faa0064, 0x8fab009c, 0x1425021,
+0x16a102b, 0x10400004, 0xafaa0064, 0x8f420148,
+0x1425023, 0xafaa0064, 0x26100002, 0x26520001,
+0x253102b, 0x1440ffe3, 0x26310004, 0x8fb0006c,
+0x10000036, 0x97b10038, 0x8f4200fc, 0x24050002,
+0xa2102a, 0x1440001b, 0x24030001, 0x8f83012c,
+0x10600013, 0x0, 0x8f820124, 0x431023,
+0x22143, 0x58800001, 0x24840040, 0x8f820128,
+0x431023, 0x21943, 0x58600001, 0x24630040,
+0x64102a, 0x54400001, 0x602021, 0xaf4400fc,
+0x8f4200fc, 0xa2102a, 0x14400006, 0x24030001,
+0x8f420334, 0x1821, 0x24420001, 0xaf420334,
+0x8f420334, 0x306200ff, 0x1040fea5, 0x3c020800,
+0x96b1000a, 0x8fb0006c, 0x3223ffff, 0x70102b,
+0x54400001, 0x608021, 0x8ea40000, 0x8ea50004,
+0x240a0001, 0xafaa0010, 0xafbe0014, 0x8f420008,
+0x8fa60064, 0xafa20018, 0x8f42010c, 0x40f809,
+0x2003821, 0x1040fea2, 0x3c050007, 0x96a3000e,
+0x97ab008e, 0x11600007, 0x609021, 0x934205c4,
+0x14400004, 0x0, 0x97aa0086, 0x6b1825,
+0xa6aa0016, 0x8fab007c, 0x3c02ffff, 0x1621024,
+0x10400003, 0xb1402, 0x34630400, 0xa6a20014,
+0x8faa006c, 0x560a0072, 0xa6a3000e, 0x34620004,
+0xa6a2000e, 0x8fab0074, 0x14b1021, 0xa6a2000a,
+0x8f430044, 0x8f4401a0, 0x8f4501a4, 0x34028000,
+0xafa20010, 0x8f420044, 0x2a03021, 0x24070020,
+0xafa20014, 0x8f42000c, 0x31940, 0x604821,
+0xafa20018, 0x8f42010c, 0x4021, 0xa92821,
+0xa9182b, 0x882021, 0x40f809, 0x832021,
+0x5040fe7f, 0xa6b2000e, 0x8f420368, 0xafa0006c,
+0xa34005c4, 0x2442ffff, 0xaf420368, 0x8faa005c,
+0x240b0001, 0x8f420368, 0x154b0006, 0x24020002,
+0x8f42035c, 0x2442ffff, 0xaf42035c, 0x1000000c,
+0x8f42035c, 0x15420006, 0x0, 0x8f420364,
+0x2442ffff, 0xaf420364, 0x10000005, 0x8f420364,
+0x8f420360, 0x2442ffff, 0xaf420360, 0x8f420360,
+0x8faa0054, 0x8fab004c, 0xad6a0000, 0x8f420044,
+0x8f440088, 0x8f430078, 0x24420001, 0x441024,
+0x24630001, 0xaf420044, 0xaf430078, 0x8c020240,
+0x62182b, 0x14600065, 0x24070008, 0x8f440168,
+0x8f45016c, 0x8f430044, 0x8f48000c, 0x8f860120,
+0x24020040, 0xafa20010, 0xafa30014, 0xafa80018,
+0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011,
+0x240b0001, 0x3c010001, 0x370821, 0xa02b40f2,
+0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001,
+0x2484691c, 0xafa20014, 0x8f460044, 0x8f870120,
+0x3c050009, 0xc002b17, 0x34a51300, 0x1000000b,
+0x0, 0x8f420304, 0x24420001, 0xaf420304,
+0x8f420304, 0x8f420044, 0xaf42007c, 0x3c010001,
+0x370821, 0xa02040f2, 0xaf400078, 0x8f420318,
+0x24420001, 0xaf420318, 0x10000038, 0x8f420318,
+0xa6b0000a, 0x8f430044, 0x8f4401a0, 0x8f4501a4,
+0x34028000, 0xafa20010, 0x8f420044, 0x2a03021,
+0x24070020, 0xafa20014, 0x8f42000c, 0x31940,
+0x604821, 0xafa20018, 0x8f42010c, 0x4021,
+0xa92821, 0xa9182b, 0x882021, 0x40f809,
+0x832021, 0x1040fe1f, 0x240a0001, 0xa34a05c4,
+0x8fab006c, 0x8faa0064, 0x1705823, 0xafab006c,
+0x8fab009c, 0x1505021, 0x16a102b, 0x10400004,
+0xafaa0064, 0x8f420148, 0x1425023, 0xafaa0064,
+0x8f420368, 0x2442ffff, 0xaf420368, 0x8f420368,
+0x8f42035c, 0x2442ffff, 0xaf42035c, 0x8fab0054,
+0x8faa004c, 0x8f42035c, 0xad4b0000, 0x8f420044,
+0x8f440088, 0x8f430078, 0x24420001, 0x441024,
+0x24630001, 0xaf420044, 0xaf430078, 0x8faa006c,
+0x1540fe1b, 0x0, 0x8fab006c, 0x1160001e,
+0x0, 0x934205c4, 0x10400009, 0x0,
+0x8faa0064, 0xaf4a00c4, 0xaf4b00c0, 0x8fab007c,
+0xaf4b00c8, 0x8faa0074, 0x1000000e, 0xaf4a00cc,
+0x97ab008e, 0x1160000b, 0x34038100, 0x8fa20020,
+0x8c46000c, 0xa443000c, 0x97aa0086, 0x8c440004,
+0x8c450008, 0xa44a000e, 0xac440000, 0xac450004,
+0xac460008, 0x8f42034c, 0x24420001, 0xaf42034c,
+0x10000010, 0x8f42034c, 0x8fab007c, 0x3164ffff,
+0x2484fffc, 0x801821, 0x8f440250, 0x8f450254,
+0x8f460118, 0x1021, 0xa32821, 0xa3382b,
+0x822021, 0x872021, 0xaf440250, 0xc0f809,
+0xaf450254, 0x8fbf00c8, 0x8fbe00c4, 0x8fb500c0,
+0x8fb300bc, 0x8fb200b8, 0x8fb100b4, 0x8fb000b0,
+0x3e00008, 0x27bd00d0, 0x3e00008, 0x0,
+0x27bdff38, 0x240b0001, 0xafbf00c0, 0xafbe00bc,
+0xafb500b8, 0xafb300b4, 0xafb200b0, 0xafb100ac,
+0xafb000a8, 0xa3a00087, 0xafa00044, 0xafab005c,
+0x934205c4, 0xa7a00076, 0x10400007, 0xa7a0007e,
+0x8f4c00c0, 0xafac0064, 0x8f4b00c8, 0x8f5e00c4,
+0x10000130, 0xafab006c, 0x8f420114, 0x40f809,
+0x0, 0x403021, 0x10c002a1, 0x0,
+0x8cc20000, 0x8cc30004, 0xafa20020, 0xafa30024,
+0x8fac0024, 0x8fbe0020, 0x3182ffff, 0x2442fffc,
+0xafa20064, 0x3c020006, 0x2c21024, 0x14400015,
+0xafac006c, 0x93c20000, 0x30420001, 0x10400011,
+0x2402ffff, 0x8fc30000, 0x14620004, 0x3402ffff,
+0x97c30004, 0x1062000b, 0x0, 0xc002497,
+0x3c02021, 0x304200ff, 0x14400006, 0x0,
+0x8f420118, 0x40f809, 0x0, 0x10000280,
+0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff,
+0x431024, 0x3c03ffff, 0x431824, 0x14600003,
+0xafa20024, 0x10000040, 0x8021, 0x3c020080,
+0x621024, 0x10400007, 0x0, 0x8f42038c,
+0x24420001, 0xaf42038c, 0x8f42038c, 0x10000036,
+0x24100001, 0x8f420210, 0x24420001, 0xaf420210,
+0x8f420210, 0x3c020001, 0x621024, 0x10400006,
+0x3c020002, 0x8f4201c4, 0x24420001, 0xaf4201c4,
+0x8f4201c4, 0x3c020002, 0x621024, 0x10400006,
+0x3c020004, 0x8f42037c, 0x24420001, 0xaf42037c,
+0x8f42037c, 0x3c020004, 0x621024, 0x10400006,
+0x3c020008, 0x8f420380, 0x24420001, 0xaf420380,
+0x8f420380, 0x3c020008, 0x621024, 0x10400006,
+0x3c020010, 0x8f420384, 0x24420001, 0xaf420384,
+0x8f420384, 0x3c020010, 0x621024, 0x10400006,
+0x3c020020, 0x8f4201c0, 0x24420001, 0xaf4201c0,
+0x8f4201c0, 0x3c020020, 0x621024, 0x10400006,
+0x24100001, 0x8f420388, 0x24420001, 0xaf420388,
+0x8f420388, 0x24100001, 0x8c020260, 0x8fab0064,
+0x4b102b, 0x10400015, 0x320200ff, 0x8f4201e8,
+0x24420001, 0xaf4201e8, 0x8f4201e8, 0x8fac006c,
+0x8f8200e0, 0x358c0100, 0xafac006c, 0xafa20010,
+0x8f8200e4, 0x24100001, 0x3c040001, 0x24846930,
+0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050007,
+0xc002b17, 0x34a53600, 0x320200ff, 0x10400010,
+0x3c020080, 0x2c21024, 0x1440000e, 0x32c20400,
+0x8fab006c, 0x3c020080, 0x34420100, 0x1621024,
+0x10400005, 0x0, 0x8f42020c, 0x24420001,
+0xaf42020c, 0x8f42020c, 0x10000202, 0x8fa30064,
+0x32c20400, 0x10400012, 0x34028100, 0x97c3000c,
+0x1462000f, 0x0, 0x240c0200, 0xa7ac0076,
+0x97c2000e, 0x8fc30008, 0x8fc40004, 0x8fab0064,
+0x8fc50000, 0x256bfffc, 0xafab0064, 0xa7a2007e,
+0xafc3000c, 0xafc40008, 0xafc50004, 0x27de0004,
+0x8fa70064, 0x320200ff, 0x14400034, 0x3c020100,
+0x97c4000c, 0x2c8305dd, 0x38828870, 0x2c420001,
+0x621825, 0x10600015, 0x2821, 0x32c20800,
+0x10400015, 0x24020800, 0x97c30014, 0x14620012,
+0x3402aaaa, 0x97c3000e, 0x14620007, 0x2021,
+0x97c30010, 0x24020300, 0x14620004, 0x801021,
+0x97c20012, 0x2c440001, 0x801021, 0x54400006,
+0x24050016, 0x10000004, 0x0, 0x24020800,
+0x50820001, 0x2405000e, 0x10a00013, 0x3c52021,
+0x24830009, 0x3c02001f, 0x3442ffff, 0x43102b,
+0x10400003, 0x0, 0x8f420148, 0x621823,
+0x90620000, 0x38430006, 0x2c630001, 0x38420011,
+0x2c420001, 0x621825, 0x10600004, 0x3c020100,
+0x94820002, 0x453821, 0x3c020100, 0x2c21024,
+0x5040000e, 0xafa70064, 0x8fac0064, 0x10ec0008,
+0x3c050007, 0x3c040001, 0x24846998, 0x8fa60064,
+0x34a54000, 0xafa00010, 0xc002b17, 0xafa00014,
+0x8fab0064, 0x256b0004, 0xafab0064, 0x8f420080,
+0x8fac0064, 0x4c102b, 0x1040002c, 0x32c28000,
+0x10400034, 0x240b0003, 0x32c21000, 0x10400031,
+0xafab005c, 0x1000002e, 0x240c0004, 0x8f420350,
+0x2403ffbf, 0x283a024, 0x24420001, 0xaf420350,
+0x10000173, 0x8f420350, 0x3c020800, 0x2c2b025,
+0x2402ffbf, 0x282a024, 0x8f830128, 0x3c040001,
+0x24846960, 0x26620001, 0xafa20014, 0xafa30010,
+0x8f860120, 0x8f870124, 0x3c050007, 0xc002b17,
+0x34a55300, 0x10000162, 0x0, 0x8ea20000,
+0x8ea30004, 0x3c040001, 0x24846978, 0xafb00010,
+0xafb10014, 0x8ea70018, 0x34a55900, 0xc002b17,
+0x603021, 0x10000156, 0x0, 0x8f420084,
+0x8fab0064, 0x4b102b, 0x14400007, 0x3c020001,
+0x2c21024, 0x10400004, 0x0, 0x240c0002,
+0xafac005c, 0x8fab0064, 0x11600166, 0x27ac0020,
+0xafac008c, 0x8fab005c, 0x240c0001, 0x556c0021,
+0x240c0002, 0x8f430054, 0x8f420050, 0x1062000b,
+0x274b0054, 0x8f510054, 0x3403ecc0, 0xafab004c,
+0x26220001, 0x304201ff, 0xafa20054, 0x111140,
+0x431021, 0x1000006b, 0x2e2a821, 0x8f420044,
+0x8fac0064, 0x3c040001, 0x2484693c, 0xafac0014,
+0xafa20010, 0x8f460054, 0x8f470050, 0x3c050007,
+0xc002b17, 0x34a54300, 0x8f430350, 0x2402ffbf,
+0x282a024, 0x24630001, 0xaf430350, 0x10000124,
+0x8f420350, 0x156c001d, 0x0, 0x8f430074,
+0x8f420070, 0x1062000a, 0x274b0074, 0x8f510074,
+0xafab004c, 0x26220001, 0x304203ff, 0xafa20054,
+0x111140, 0x24426cc0, 0x1000004a, 0x2e2a821,
+0x8f420044, 0x8fac0064, 0x3c040001, 0x24846948,
+0x3c050007, 0xafac0014, 0xafa20010, 0x8f460074,
+0x8f470070, 0x34a54500, 0x240b0001, 0xc002b17,
+0xafab005c, 0x1000ffc3, 0x0, 0x8f430064,
+0x8f420060, 0x1062001a, 0x274c0064, 0x8f510064,
+0x8fab005c, 0xafac004c, 0x26220001, 0x304200ff,
+0xafa20054, 0x24020004, 0x1562000e, 0x111140,
+0x111180, 0x24420cc0, 0x2e21021, 0xafa20044,
+0x9442002a, 0x8fac0044, 0x8fab0064, 0x4b102b,
+0x10400024, 0x25950020, 0x240c0001, 0x10000021,
+0xa3ac0087, 0x24424cc0, 0x1000001e, 0x2e2a821,
+0x8f420044, 0x8fab0064, 0x3c040001, 0x24846954,
+0xafab0014, 0xafa20010, 0x8f460064, 0x8f470060,
+0x3c050007, 0xc002b17, 0x34a54800, 0x3c020008,
+0x2c21024, 0x1440ff61, 0x0, 0x8f420370,
+0x240c0001, 0xafac005c, 0x24420001, 0xaf420370,
+0x1000ff90, 0x8f420370, 0x27a30036, 0x131040,
+0x621821, 0x94620000, 0x441021, 0x1000001f,
+0xa4620000, 0xaebe0018, 0x93a20087, 0x10400084,
+0x9821, 0x8fab0044, 0x8fa40064, 0x8fa3008c,
+0x25620020, 0xafa20028, 0x25620008, 0xafa20030,
+0x25620010, 0xafab002c, 0xafa20034, 0x9562002a,
+0xa7a20038, 0x95620018, 0xa7a2003a, 0x9562001a,
+0xa7a2003c, 0x9562001c, 0xa7a2003e, 0x94620018,
+0x24630002, 0x822023, 0x1880ffdf, 0x26730001,
+0x2e620004, 0x1440fff9, 0x0, 0x8f4200fc,
+0x262102a, 0x14400030, 0x24030001, 0x8f83012c,
+0x10600028, 0x0, 0x8f820124, 0x431023,
+0x22143, 0x58800001, 0x24840040, 0x8f820128,
+0x431023, 0x21943, 0x58600001, 0x24630040,
+0x64102a, 0x54400001, 0x602021, 0xaf4400fc,
+0x8f4200fc, 0x262102a, 0x10400016, 0x24030001,
+0x1000001a, 0x306200ff, 0x8fac008c, 0x101040,
+0x4c1021, 0x94470018, 0x101080, 0x4c1021,
+0xafbe0010, 0x8c420008, 0x3c040001, 0x2484696c,
+0x3c050007, 0x8c430004, 0x8c420000, 0x34a55500,
+0x2003021, 0xc002b17, 0xafa30014, 0x10000039,
+0x0, 0x8f420334, 0x1821, 0x24420001,
+0xaf420334, 0x8f420334, 0x306200ff, 0x1040ff06,
+0x8021, 0x8f430008, 0x2402fbff, 0x1260002d,
+0x625024, 0x3c0b4000, 0x22b4025, 0x8fb1008c,
+0x2669ffff, 0x2209021, 0x8e420008, 0x96270018,
+0x8c440000, 0x8c450004, 0x56090004, 0x240b0001,
+0x240c0002, 0x10000002, 0xafac0010, 0xafab0010,
+0x16000004, 0xafa80014, 0x8f420008, 0x10000002,
+0xafa20018, 0xafaa0018, 0x8f42010c, 0x3c03021,
+0xafa80098, 0xafa9009c, 0x40f809, 0xafaa00a0,
+0x8fa80098, 0x8fa9009c, 0x8faa00a0, 0x1040ffc2,
+0x3c02001f, 0x96230018, 0x3442ffff, 0x3c3f021,
+0x5e102b, 0x10400003, 0x26310002, 0x8f420148,
+0x3c2f023, 0x26100001, 0x213102b, 0x1440ffda,
+0x26520004, 0x8fb00064, 0x1000001a, 0x0,
+0x96a3000a, 0x8fb00064, 0x70102b, 0x54400001,
+0x608021, 0x8ea40000, 0x8ea50004, 0x8fab005c,
+0x240c0002, 0xafac0010, 0x934305c4, 0xb1700,
+0x10600003, 0x2223025, 0x3c020800, 0xc23025,
+0xafa60014, 0x8f420008, 0xafa20018, 0x8f42010c,
+0x3c03021, 0x40f809, 0x2003821, 0x1040fecb,
+0x3c050007, 0x97ac0076, 0x11800007, 0x96a3000e,
+0x934205c4, 0x14400004, 0x0, 0x97ab007e,
+0x6c1825, 0xa6ab0016, 0x8fac006c, 0x3c02ffff,
+0x1821024, 0x10400003, 0xc1402, 0x34630400,
+0xa6a20014, 0xa6b0000a, 0x8fab0064, 0x560b0006,
+0x3d0f021, 0x34620004, 0xafa00064, 0xa6a2000e,
+0x1000000d, 0xa34005c4, 0x8fac0064, 0x3c02001f,
+0x3442ffff, 0x5e102b, 0x1906023, 0xafac0064,
+0xa6a3000e, 0x240b0001, 0x10400003, 0xa34b05c4,
+0x8f420148, 0x3c2f023, 0x8fab0054, 0x8fac004c,
+0xad8b0000, 0x8fac0064, 0x1580feba, 0x0,
+0x8fab0064, 0x1160001b, 0x0, 0x934205c4,
+0x10400006, 0x0, 0xaf5e00c4, 0xaf4b00c0,
+0x8fac006c, 0x1000000e, 0xaf4c00c8, 0x97ab0076,
+0x1160000b, 0x34038100, 0x8fa20020, 0x8c46000c,
+0xa443000c, 0x97ac007e, 0x8c440004, 0x8c450008,
+0xa44c000e, 0xac440000, 0xac450004, 0xac460008,
+0x8f42034c, 0x24420001, 0xaf42034c, 0x10000010,
+0x8f42034c, 0x8fab006c, 0x3164ffff, 0x2484fffc,
+0x801821, 0x8f440250, 0x8f450254, 0x8f460118,
+0x1021, 0xa32821, 0xa3382b, 0x822021,
+0x872021, 0xaf440250, 0xc0f809, 0xaf450254,
+0x8fbf00c0, 0x8fbe00bc, 0x8fb500b8, 0x8fb300b4,
+0x8fb200b0, 0x8fb100ac, 0x8fb000a8, 0x3e00008,
+0x27bd00c8, 0x3e00008, 0x0, 0x27bdffd8,
+0xafbf0024, 0xafb00020, 0x8f43004c, 0x8f420048,
+0x10620034, 0x0, 0x8f430048, 0x8f42004c,
+0x622023, 0x4820001, 0x24840200, 0x8f430054,
+0x8f42004c, 0x43102b, 0x14400004, 0x24020200,
+0x8f43004c, 0x10000005, 0x431023, 0x8f420054,
+0x8f43004c, 0x431023, 0x2442ffff, 0x405021,
+0x8a102a, 0x54400001, 0x805021, 0x8f49004c,
+0x8f48004c, 0x8f440188, 0x8f45018c, 0x8f46004c,
+0x24071000, 0xafa70010, 0x84140, 0x1001821,
+0x12a4821, 0x313001ff, 0xafb00014, 0x8f470014,
+0x1021, 0x63140, 0xafa70018, 0xa32821,
+0xa3382b, 0x822021, 0x872021, 0x3402ecc0,
+0xc23021, 0x8f420108, 0x2e63021, 0x40f809,
+0xa3940, 0x54400001, 0xaf50004c, 0x8f43004c,
+0x8f420048, 0x14620018, 0x0, 0x8f420000,
0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
0x1040fffd, 0x0, 0x10000005, 0x0,
0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
-0x8f820060, 0x2403f7ff, 0x431024, 0xaf820060,
+0x8f820060, 0x2403fdff, 0x431024, 0xaf820060,
0x8f420000, 0x10400003, 0x0, 0x10000002,
0xaf80004c, 0xaf800048, 0x8fbf0024, 0x8fb00020,
0x3e00008, 0x27bd0028, 0x3e00008, 0x0,
-0x8f4200fc, 0x3c030001, 0x8f4400f8, 0x346330c8,
-0x24420001, 0xaf4200fc, 0x8f850128, 0x2e31021,
-0x54820004, 0x24820008, 0x3c020001, 0x34422ec8,
-0x2e21021, 0x401821, 0xaf4300f8, 0xac600000,
-0x8f4200f4, 0x14620004, 0x3c020001, 0x24a20020,
-0x1000000f, 0xaf820128, 0x8f4300f8, 0x344230c8,
-0x2e21021, 0x54620004, 0x24620008, 0x3c020001,
-0x34422ec8, 0x2e21021, 0x401821, 0x8c620004,
-0x21140, 0xa21021, 0xaf820128, 0xac600000,
-0x8ca30018, 0x30620070, 0x1040002d, 0x30620020,
+0x27bdffd8, 0xafbf0024, 0xafb00020, 0x8f43005c,
+0x8f420058, 0x10620049, 0x0, 0x8f430058,
+0x8f42005c, 0x622023, 0x4820001, 0x24840100,
+0x8f430064, 0x8f42005c, 0x43102b, 0x14400004,
+0x24020100, 0x8f43005c, 0x10000005, 0x431023,
+0x8f420064, 0x8f43005c, 0x431023, 0x2442ffff,
+0x403821, 0x87102a, 0x54400001, 0x803821,
+0x8f42005c, 0x471021, 0x305000ff, 0x32c21000,
+0x10400015, 0x24082000, 0x8f49005c, 0x8f440190,
+0x8f450194, 0x8f46005c, 0x73980, 0xafa80010,
+0xafb00014, 0x8f480014, 0x94980, 0x1201821,
+0x1021, 0xa32821, 0xa3482b, 0x822021,
+0x892021, 0x63180, 0xafa80018, 0x8f420108,
+0x10000014, 0x24c60cc0, 0x8f49005c, 0x8f440190,
+0x8f450194, 0x8f46005c, 0x73940, 0xafa80010,
+0xafb00014, 0x8f480014, 0x94940, 0x1201821,
+0x1021, 0xa32821, 0xa3482b, 0x822021,
+0x892021, 0x63140, 0xafa80018, 0x8f420108,
+0x24c64cc0, 0x40f809, 0x2e63021, 0x54400001,
+0xaf50005c, 0x8f43005c, 0x8f420058, 0x14620018,
+0x0, 0x8f420000, 0x10400007, 0x0,
+0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
+0x10000005, 0x0, 0xaf800048, 0x8f820048,
+0x1040fffd, 0x0, 0x8f820060, 0x2403feff,
+0x431024, 0xaf820060, 0x8f420000, 0x10400003,
+0x0, 0x10000002, 0xaf80004c, 0xaf800048,
+0x8fbf0024, 0x8fb00020, 0x3e00008, 0x27bd0028,
+0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024,
+0xafb00020, 0x8f43006c, 0x8f420068, 0x10620033,
+0x0, 0x8f430068, 0x8f42006c, 0x622023,
+0x4820001, 0x24840400, 0x8f430074, 0x8f42006c,
+0x43102b, 0x14400004, 0x24020400, 0x8f43006c,
+0x10000005, 0x431023, 0x8f420074, 0x8f43006c,
+0x431023, 0x2442ffff, 0x405021, 0x8a102a,
+0x54400001, 0x805021, 0x8f49006c, 0x8f48006c,
+0x8f440198, 0x8f45019c, 0x8f46006c, 0x24074000,
+0xafa70010, 0x84140, 0x1001821, 0x12a4821,
+0x313003ff, 0xafb00014, 0x8f470014, 0x1021,
+0x63140, 0x24c66cc0, 0xafa70018, 0xa32821,
+0xa3382b, 0x822021, 0x872021, 0x8f420108,
+0x2e63021, 0x40f809, 0xa3940, 0x54400001,
+0xaf50006c, 0x8f43006c, 0x8f420068, 0x14620018,
+0x0, 0x8f420000, 0x10400007, 0x0,
+0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
+0x10000005, 0x0, 0xaf800048, 0x8f820048,
+0x1040fffd, 0x0, 0x8f820060, 0x2403f7ff,
+0x431024, 0xaf820060, 0x8f420000, 0x10400003,
+0x0, 0x10000002, 0xaf80004c, 0xaf800048,
+0x8fbf0024, 0x8fb00020, 0x3e00008, 0x27bd0028,
+0x3e00008, 0x0, 0x8f4200fc, 0x3c030001,
+0x8f4400f8, 0x346330c8, 0x24420001, 0xaf4200fc,
+0x8f850128, 0x2e31021, 0x54820004, 0x24820008,
+0x3c020001, 0x34422ec8, 0x2e21021, 0x401821,
+0xaf4300f8, 0xac600000, 0x8f4200f4, 0x14620004,
+0x3c020001, 0x24a20020, 0x1000000f, 0xaf820128,
+0x8f4300f8, 0x344230c8, 0x2e21021, 0x54620004,
+0x24620008, 0x3c020001, 0x34422ec8, 0x2e21021,
+0x401821, 0x8c620004, 0x21140, 0xa21021,
+0xaf820128, 0xac600000, 0x8ca30018, 0x30620070,
+0x1040002d, 0x30620020, 0x10400004, 0x3c020010,
+0x2c21024, 0x1040000d, 0x0, 0x30620040,
+0x10400004, 0x3c020020, 0x2c21024, 0x10400007,
+0x0, 0x30620010, 0x1040001f, 0x3c020040,
+0x2c21024, 0x1440001c, 0x0, 0x8f820040,
+0x30420001, 0x14400008, 0x2021, 0x8c030104,
+0x24020001, 0x50620005, 0x24040001, 0x8c020264,
+0x10400003, 0x801021, 0x24040001, 0x801021,
+0x10400006, 0x0, 0x8f42030c, 0x24420001,
+0xaf42030c, 0x10000008, 0x8f42030c, 0x8f820044,
+0x34420004, 0xaf820044, 0x8f420308, 0x24420001,
+0xaf420308, 0x8f420308, 0x3e00008, 0x0,
+0x3e00008, 0x0, 0x27bdff98, 0xafbf0060,
+0xafbe005c, 0xafb50058, 0xafb30054, 0xafb20050,
+0xafb1004c, 0xafb00048, 0x8f4200fc, 0x24420001,
+0xaf4200fc, 0x8f880128, 0x25020020, 0xaf820128,
+0x8d030018, 0x30620070, 0x1040002e, 0x30620020,
0x10400004, 0x3c020010, 0x2c21024, 0x1040000d,
0x0, 0x30620040, 0x10400004, 0x3c020020,
0x2c21024, 0x10400007, 0x0, 0x30620010,
-0x1040001f, 0x3c020040, 0x2c21024, 0x1440001c,
+0x104001a9, 0x3c020040, 0x2c21024, 0x144001a6,
0x0, 0x8f820040, 0x30420001, 0x14400008,
0x2021, 0x8c030104, 0x24020001, 0x50620005,
0x24040001, 0x8c020264, 0x10400003, 0x801021,
0x24040001, 0x801021, 0x10400006, 0x0,
-0x8f4202fc, 0x24420001, 0xaf4202fc, 0x10000008,
-0x8f4202fc, 0x8f820044, 0x34420004, 0xaf820044,
-0x8f4202f8, 0x24420001, 0xaf4202f8, 0x8f4202f8,
-0x3e00008, 0x0, 0x3e00008, 0x0,
-0x27bdff98, 0xafbf0060, 0xafbe005c, 0xafb50058,
-0xafb30054, 0xafb20050, 0xafb1004c, 0xafb00048,
-0x8f4200fc, 0x24420001, 0xaf4200fc, 0x8f880128,
-0x25020020, 0xaf820128, 0x8d030018, 0x30620070,
-0x1040002e, 0x30620020, 0x10400004, 0x3c020010,
-0x2c21024, 0x1040000d, 0x0, 0x30620040,
-0x10400004, 0x3c020020, 0x2c21024, 0x10400007,
-0x0, 0x30620010, 0x104001a6, 0x3c020040,
-0x2c21024, 0x144001a3, 0x0, 0x8f820040,
-0x30420001, 0x14400008, 0x2021, 0x8c030104,
-0x24020001, 0x50620005, 0x24040001, 0x8c020264,
-0x10400003, 0x801021, 0x24040001, 0x801021,
-0x10400006, 0x0, 0x8f4202fc, 0x24420001,
-0xaf4202fc, 0x1000018f, 0x8f4202fc, 0x8f820044,
-0x34420004, 0xaf820044, 0x8f4202f8, 0x24420001,
-0xaf4202f8, 0x10000187, 0x8f4202f8, 0x30620002,
-0x10400148, 0x3c020800, 0x8d0a001c, 0x1422024,
-0xafaa0024, 0xa5702, 0xafaa0034, 0x8faa0024,
-0x314affff, 0xafaa0024, 0x950a0016, 0xafaa002c,
-0x8faa0034, 0x24020001, 0x15420007, 0x24020002,
-0x8faa0024, 0xa1140, 0x3403ecc0, 0x431021,
-0x10000014, 0x2e2a821, 0x15420006, 0x24020003,
-0x8faa0024, 0xa1140, 0x24426cc0, 0x1000000d,
-0x2e2a821, 0x8faa0034, 0x15420006, 0x0,
-0x8faa0024, 0xa1140, 0x24424cc0, 0x10000005,
-0x2e2a821, 0x8faa0024, 0xa1180, 0x571021,
-0x24550ce0, 0x96a2000e, 0x305efffc, 0x30420400,
-0x144000d8, 0x8821, 0x10800004, 0x24091000,
-0x97b1002e, 0x100000d4, 0x0, 0x8eb30018,
-0x966a000c, 0xa7aa003e, 0x97a3003e, 0x2c6205dd,
-0x10400015, 0x2021, 0x32c20800, 0x10400015,
-0x24020800, 0x96630014, 0x14620012, 0x3402aaaa,
-0x9663000e, 0x14620007, 0x2821, 0x96630010,
-0x24020300, 0x14620004, 0xa01021, 0x96620012,
-0x2c450001, 0xa01021, 0x54400006, 0x24040016,
-0x10000004, 0x0, 0x24020800, 0x50620001,
-0x2404000e, 0x108000b3, 0x2649021, 0x92420000,
-0x3042000f, 0x28080, 0x32c20100, 0x1040001e,
-0x2501821, 0x3c020020, 0x43102b, 0x1440000e,
-0x2402021, 0x2821, 0x94820000, 0x24840002,
-0xa22821, 0x83102b, 0x1440fffb, 0x30a2ffff,
-0x51c02, 0x622821, 0x51c02, 0x30a2ffff,
-0x10000009, 0x622821, 0x8f47013c, 0x8f420110,
-0x102842, 0x3c060020, 0x40f809, 0xafa80040,
-0x3045ffff, 0x8fa80040, 0x50a00001, 0x3405ffff,
-0x10000002, 0x37de0002, 0x2821, 0x32c20080,
-0x1040008c, 0xa6a50010, 0x26430009, 0x3c02001f,
+0x8f42030c, 0x24420001, 0xaf42030c, 0x10000192,
+0x8f42030c, 0x8f820044, 0x34420004, 0xaf820044,
+0x8f420308, 0x24420001, 0xaf420308, 0x1000018a,
+0x8f420308, 0x30620002, 0x1040014b, 0x3c020800,
+0x8d1e001c, 0x1e5702, 0xafaa0034, 0x950a0016,
+0x3c22024, 0xafaa0024, 0x8faa0034, 0x24020001,
+0x15420006, 0x33deffff, 0x1e1140, 0x3403ecc0,
+0x431021, 0x10000010, 0x2e2a821, 0x24020002,
+0x15420005, 0x24020003, 0x1e1140, 0x24426cc0,
+0x10000009, 0x2e2a821, 0x15420005, 0x1e1180,
+0x1e1140, 0x24424cc0, 0x10000003, 0x2e2a821,
+0x571021, 0x24550ce0, 0x96a2000e, 0x304afffc,
+0x30420400, 0x10400003, 0xafaa002c, 0x100000e1,
+0x8821, 0x10800004, 0x8821, 0x97b10026,
+0x100000dd, 0xa6b10012, 0x8eb30018, 0x966a000c,
+0xa7aa003e, 0x97a5003e, 0x2ca305dd, 0x38a28870,
+0x2c420001, 0x621825, 0x10600015, 0x2021,
+0x32c20800, 0x10400015, 0x24020800, 0x96630014,
+0x14620012, 0x3402aaaa, 0x9663000e, 0x14620007,
+0x2821, 0x96630010, 0x24020300, 0x14620004,
+0xa01021, 0x96620012, 0x2c450001, 0xa01021,
+0x54400006, 0x24040016, 0x10000004, 0x0,
+0x24020800, 0x50a20001, 0x2404000e, 0x108000b9,
+0x2649021, 0x92420000, 0x3042000f, 0x28080,
+0x32c20100, 0x10400020, 0x2501821, 0x3c020020,
+0x43102b, 0x1440000e, 0x2402021, 0x2821,
+0x94820000, 0x24840002, 0xa22821, 0x83102b,
+0x1440fffb, 0x30a2ffff, 0x51c02, 0x622821,
+0x51c02, 0x30a2ffff, 0x10000009, 0x622821,
+0x8f470148, 0x8f420110, 0x102842, 0x3c060020,
+0x40f809, 0xafa80040, 0x3045ffff, 0x8fa80040,
+0x50a00001, 0x3405ffff, 0x8faa002c, 0x354a0002,
+0x10000002, 0xafaa002c, 0x2821, 0x32c20080,
+0x10400090, 0xa6a50010, 0x26430009, 0x3c02001f,
0x3442ffff, 0x43102b, 0x10400003, 0x0,
-0x8f42013c, 0x621823, 0x90660000, 0x30c200ff,
+0x8f420148, 0x621823, 0x90660000, 0x30c200ff,
0x38430006, 0x2c630001, 0x38420011, 0x2c420001,
-0x621825, 0x1060007b, 0x24020800, 0x8821,
+0x621825, 0x1060007f, 0x24020800, 0x8821,
0x97a3003e, 0x1462000f, 0x2602021, 0x96710000,
0x96620002, 0x96630004, 0x96640006, 0x2228821,
0x2238821, 0x2248821, 0x96620008, 0x9663000a,
@@ -7092,155 +7382,162 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x3222ffff, 0x628821, 0x111c02, 0x3222ffff,
0x628821, 0x32c20200, 0x10400003, 0x26440006,
0x1000003e, 0x8021, 0x3c05001f, 0x34a5ffff,
-0xa4102b, 0x10400003, 0x0, 0x8f42013c,
+0xa4102b, 0x10400003, 0x0, 0x8f420148,
0x822023, 0x94820000, 0x30421fff, 0x10400004,
0x2644000c, 0x96420002, 0x10000030, 0x508023,
0x96420002, 0x26430014, 0x508023, 0x3c020020,
0x43102b, 0x1440000a, 0xd08021, 0x9642000c,
0x2028021, 0x9642000e, 0x96430010, 0x96440012,
0x2028021, 0x2038021, 0x10000020, 0x2048021,
-0xa4102b, 0x10400003, 0x0, 0x8f42013c,
+0xa4102b, 0x10400003, 0x0, 0x8f420148,
0x822023, 0x94820000, 0x24840002, 0x2028021,
-0xa4102b, 0x10400003, 0x0, 0x8f42013c,
+0xa4102b, 0x10400003, 0x0, 0x8f420148,
0x822023, 0x94820000, 0x24840002, 0x2028021,
-0xa4102b, 0x10400003, 0x0, 0x8f42013c,
+0xa4102b, 0x10400003, 0x0, 0x8f420148,
0x822023, 0x94820000, 0x24840002, 0x2028021,
-0xa4102b, 0x10400003, 0x0, 0x8f42013c,
+0xa4102b, 0x10400003, 0x0, 0x8f420148,
0x822023, 0x94820000, 0x2028021, 0x3c020100,
-0x2c21024, 0x1040000c, 0x33c20004, 0x1040000a,
-0x0, 0x9504000e, 0x2642021, 0xc003c24,
-0x2484fffc, 0x3042ffff, 0x2228821, 0x111c02,
-0x3222ffff, 0x628821, 0x8faa002c, 0x1518823,
-0x111402, 0x2228821, 0x2308821, 0x111402,
-0x2228821, 0x3231ffff, 0x52200001, 0x3411ffff,
-0x37de0001, 0x24091000, 0x33c20004, 0xa6b10012,
-0x10400002, 0xa6be000e, 0x34098000, 0x8f480044,
-0x8f440190, 0x8f450194, 0xafa90010, 0x8f490044,
-0x84140, 0x1001821, 0xafa90014, 0x8f48000c,
-0x2a03021, 0x24070020, 0xafa80018, 0x8f48010c,
-0x1021, 0xa32821, 0xa3482b, 0x822021,
-0x100f809, 0x892021, 0x1440000c, 0x0,
-0x8f820128, 0x8faa0024, 0x3c040001, 0x24843988,
-0xafaa0014, 0xafa20010, 0x8f860124, 0x8f870120,
-0x3c050007, 0xc0029bb, 0x34a59920, 0x8f420358,
-0x2442ffff, 0xaf420358, 0x8f420044, 0x8f430088,
-0x24420001, 0x431024, 0xaf420044, 0x8faa0034,
-0x8f440358, 0x24020001, 0x15420006, 0x24020002,
-0x8f42034c, 0x2442ffff, 0xaf42034c, 0x10000049,
-0x8f42034c, 0x15420006, 0x0, 0x8f420354,
-0x2442ffff, 0xaf420354, 0x10000042, 0x8f420354,
-0x8f420350, 0x2442ffff, 0xaf420350, 0x1000003d,
-0x8f420350, 0x30621000, 0x10400005, 0x30628000,
-0x8f420078, 0x24420001, 0x10000036, 0xaf420078,
-0x10400034, 0x0, 0x8f420078, 0x24420001,
-0xaf420078, 0x8c030240, 0x43102b, 0x1440002d,
-0x24070008, 0x8f440158, 0x8f45015c, 0x8f430044,
-0x8f48000c, 0x8f860120, 0x24020040, 0xafa20010,
-0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809,
-0x24c6001c, 0x14400011, 0x24020001, 0x3c010001,
-0x370821, 0xa02240f2, 0x8f820124, 0xafa20010,
-0x8f820128, 0x3c040001, 0x2484390c, 0xafa20014,
-0x8f460044, 0x8f870120, 0x3c050009, 0xc0029bb,
-0x34a51300, 0x1000000b, 0x0, 0x8f4202f4,
-0x24420001, 0xaf4202f4, 0x8f4202f4, 0x8f420044,
-0xaf42007c, 0x3c010001, 0x370821, 0xa02040f2,
-0xaf400078, 0x8f420308, 0x24420001, 0xaf420308,
-0x8f420308, 0x8fbf0060, 0x8fbe005c, 0x8fb50058,
-0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048,
-0x3e00008, 0x27bd0068, 0x3e00008, 0x0,
-0x0, 0x0, 0x0, 0x8f420130,
-0xaf8200c0, 0x8f420130, 0xaf8200c4, 0x8f420130,
-0xaf8200c8, 0x8f42012c, 0xaf8200d0, 0x8f42012c,
-0xaf8200d4, 0x8f42012c, 0x3e00008, 0xaf8200d8,
+0x2c21024, 0x1040000e, 0x0, 0x8faa002c,
+0x31420004, 0x1040000a, 0x0, 0x9504000e,
+0x2642021, 0xc003ec4, 0x2484fffc, 0x3042ffff,
+0x2228821, 0x111c02, 0x3222ffff, 0x628821,
+0x8faa0024, 0x1518823, 0x111402, 0x2228821,
+0x2308821, 0x111402, 0x2228821, 0x3231ffff,
+0x52200001, 0x3411ffff, 0x8faa002c, 0x354a0001,
+0xafaa002c, 0xa6b10012, 0x97aa002e, 0xa6aa000e,
+0x8faa002c, 0x31420004, 0x10400002, 0x24091000,
+0x34098000, 0x8f480044, 0x8f4401a0, 0x8f4501a4,
+0xafa90010, 0x8f490044, 0x84140, 0x1001821,
+0xafa90014, 0x8f48000c, 0x2a03021, 0x24070020,
+0xafa80018, 0x8f48010c, 0x1021, 0xa32821,
+0xa3482b, 0x822021, 0x100f809, 0x892021,
+0x1440000b, 0x0, 0x8f820128, 0x3c040001,
+0x248469a4, 0xafbe0014, 0xafa20010, 0x8f860124,
+0x8f870120, 0x3c050007, 0xc002b17, 0x34a59920,
+0x8f420368, 0x2442ffff, 0xaf420368, 0x8f420044,
+0x8f430088, 0x24420001, 0x431024, 0xaf420044,
+0x8faa0034, 0x8f440368, 0x24020001, 0x15420006,
+0x24020002, 0x8f42035c, 0x2442ffff, 0xaf42035c,
+0x10000049, 0x8f42035c, 0x15420006, 0x0,
+0x8f420364, 0x2442ffff, 0xaf420364, 0x10000042,
+0x8f420364, 0x8f420360, 0x2442ffff, 0xaf420360,
+0x1000003d, 0x8f420360, 0x30621000, 0x10400005,
+0x30628000, 0x8f420078, 0x24420001, 0x10000036,
+0xaf420078, 0x10400034, 0x0, 0x8f420078,
+0x24420001, 0xaf420078, 0x8c030240, 0x43102b,
+0x1440002d, 0x24070008, 0x8f440168, 0x8f45016c,
+0x8f430044, 0x8f48000c, 0x8f860120, 0x24020040,
+0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c,
+0x40f809, 0x24c6001c, 0x14400011, 0x24020001,
+0x3c010001, 0x370821, 0xa02240f2, 0x8f820124,
+0xafa20010, 0x8f820128, 0x3c040001, 0x2484691c,
+0xafa20014, 0x8f460044, 0x8f870120, 0x3c050009,
+0xc002b17, 0x34a51300, 0x1000000b, 0x0,
+0x8f420304, 0x24420001, 0xaf420304, 0x8f420304,
+0x8f420044, 0xaf42007c, 0x3c010001, 0x370821,
+0xa02040f2, 0xaf400078, 0x8f420318, 0x24420001,
+0xaf420318, 0x8f420318, 0x8fbf0060, 0x8fbe005c,
+0x8fb50058, 0x8fb30054, 0x8fb20050, 0x8fb1004c,
+0x8fb00048, 0x3e00008, 0x27bd0068, 0x3e00008,
+0x0, 0x0, 0x0, 0x8f42013c,
+0xaf8200c0, 0x8f42013c, 0xaf8200c4, 0x8f42013c,
+0xaf8200c8, 0x8f420138, 0xaf8200d0, 0x8f420138,
+0xaf8200d4, 0x8f420138, 0x3e00008, 0xaf8200d8,
0x27bdffe0, 0x27840208, 0x24050200, 0xafbf0018,
-0xc002a3f, 0x24060008, 0x8c020204, 0xc003d4a,
-0xaf820210, 0x2021, 0x8c060248, 0x24020004,
-0x3c010001, 0xac223d88, 0xc0047d4, 0x24050004,
-0x3c020001, 0x8c423d84, 0x30420001, 0x10400007,
-0x24020001, 0x3c010001, 0xac223d88, 0x2021,
-0x24050001, 0xc0047d4, 0x3c06601b, 0x3c040001,
-0x24843a50, 0x8f420144, 0x8f430148, 0x3c050008,
-0x8f46014c, 0x21640, 0x31940, 0x34630403,
-0x431025, 0x633c0, 0x461025, 0xaf82021c,
-0xafa00010, 0xafa00014, 0x8f86021c, 0x34a50200,
-0xc0029bb, 0x3821, 0x3c010001, 0xac203d80,
-0x3c010001, 0xac203d98, 0x8fbf0018, 0x3e00008,
-0x27bd0020, 0x27bdffe0, 0x3c050008, 0x34a50300,
-0xafbf0018, 0xafa00010, 0xafa00014, 0x8f860200,
-0x3c040001, 0x24843a5c, 0xc0029bb, 0x3821,
-0x8f420400, 0x24420001, 0xaf420400, 0x8f420400,
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffd8,
-0xafbf0020, 0xafb1001c, 0xafb00018, 0x8f420394,
-0x24420001, 0xaf420394, 0x8f420394, 0x8f900220,
-0x8f8200e0, 0xafa20010, 0x8f8200e4, 0xafa20014,
-0x8f8600c4, 0x8f8700c8, 0x3c040001, 0x24843a68,
-0xc0029bb, 0x2002821, 0x3c044000, 0x2041024,
-0x504000ae, 0x3c040100, 0x8f4203ac, 0x24420001,
-0xaf4203ac, 0x8f4203ac, 0x8f8700c4, 0x8f8300c8,
-0x8f42013c, 0x671823, 0x43102b, 0x10400003,
-0x0, 0x8f42013c, 0x621821, 0x10600005,
-0x0, 0x8f420140, 0x43102b, 0x10400007,
-0x0, 0x8f820220, 0x3c0308ff, 0x3463fffb,
-0x431024, 0x100000cc, 0x441025, 0x8f820220,
-0x3c0308ff, 0x3463ffff, 0x431024, 0x34420004,
-0xaf820220, 0x8f8600c8, 0x8f840120, 0x8f830124,
-0x10000005, 0x2821, 0x14620002, 0x24620020,
-0x27624800, 0x401821, 0x1064000c, 0x30a200ff,
-0x8c620018, 0x30420003, 0x1040fff7, 0x27624fe0,
-0x8f4203c0, 0x24050001, 0x24420001, 0xaf4203c0,
-0x8f4203c0, 0x8c660008, 0x30a200ff, 0x14400058,
-0x0, 0x934205b5, 0x14400055, 0x0,
-0x8f8700c4, 0x8f8800e0, 0x8f8400e4, 0x2402fff8,
-0x1024024, 0x1041023, 0x218c3, 0x4620001,
-0x24630200, 0x10600005, 0x24020001, 0x10620009,
-0x0, 0x1000001f, 0x0, 0x8f4203b0,
-0xe03021, 0x24420001, 0xaf4203b0, 0x10000040,
-0x8f4203b0, 0x8f4203b4, 0x24420001, 0xaf4203b4,
-0x8c860000, 0x8f42013c, 0x8f4303b4, 0xe61823,
-0x43102b, 0x10400004, 0x2c62233f, 0x8f42013c,
-0x621821, 0x2c62233f, 0x14400031, 0x0,
-0x8f4201fc, 0x24420001, 0xaf4201fc, 0x8f4201fc,
-0xe03021, 0x24820008, 0xaf8200e4, 0x10000028,
-0xaf8200e8, 0x8f4203b8, 0x24420001, 0xaf4203b8,
-0x8f4203b8, 0x8c850000, 0x8f42013c, 0xa71823,
-0x43102b, 0x10400003, 0x0, 0x8f42013c,
-0x621821, 0x8f420140, 0x43102b, 0x5440000a,
-0xa03021, 0x8f4201fc, 0x24420001, 0xaf4201fc,
-0x8f4201fc, 0x24820008, 0xaf8200e4, 0x8f8400e4,
-0x1488ffec, 0xaf8400e8, 0x1488000d, 0x27623000,
-0x14820002, 0x2482fff8, 0x27623ff8, 0x94430006,
-0x3c02001f, 0x3442ffff, 0xc33021, 0x46102b,
-0x10400003, 0x0, 0x8f42013c, 0xc23023,
-0xaf8600c8, 0x8f8300c4, 0x8f42013c, 0xc31823,
-0x43102b, 0x10400003, 0x0, 0x8f42013c,
-0x621821, 0x10600005, 0x0, 0x8f420140,
-0x43102b, 0x50400008, 0x3c02fdff, 0x8f820220,
-0x3c0308ff, 0x3463fffb, 0x431024, 0x3c034000,
-0x10000041, 0x431025, 0x3442ffff, 0x8f4303bc,
-0x282a024, 0x24020001, 0xa34205b1, 0x24630001,
-0xaf4303bc, 0x10000039, 0x8f4203bc, 0x2041024,
-0x1040000e, 0x3c110200, 0x8f420398, 0x24420001,
-0xaf420398, 0x8f420398, 0x8f820220, 0x3c0308ff,
-0x3463ffff, 0x431024, 0x441025, 0xc003b0b,
+0xc002b9b, 0x24060008, 0x8c020204, 0xc003fea,
+0xaf820210, 0x3c020001, 0x8c426e14, 0x30420002,
+0x1040000e, 0x2021, 0x8c060248, 0x24020002,
+0x3c010001, 0xac226e18, 0xc005134, 0x24050002,
+0x2021, 0x8c060248, 0x24020001, 0x3c010001,
+0xac226e18, 0x10000011, 0x24050001, 0x8c060248,
+0x24020004, 0x3c010001, 0xac226e18, 0xc005134,
+0x24050004, 0x3c020001, 0x8c426e14, 0x30420001,
+0x10400008, 0x24020001, 0x3c010001, 0xac226e18,
+0x2021, 0x24050001, 0x3c06601b, 0xc005134,
+0x0, 0x3c040001, 0x24846a60, 0x8f420150,
+0x8f430154, 0x3c050008, 0x8f460158, 0x21640,
+0x31940, 0x34630403, 0x431025, 0x633c0,
+0x461025, 0xaf82021c, 0xafa00010, 0xafa00014,
+0x8f86021c, 0x34a50200, 0xc002b17, 0x3821,
+0x3c010001, 0xac206e10, 0x3c010001, 0xac206e28,
+0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0,
+0x3c050008, 0x34a50300, 0xafbf0018, 0xafa00010,
+0xafa00014, 0x8f860200, 0x3c040001, 0x24846a6c,
+0xc002b17, 0x3821, 0x8f420410, 0x24420001,
+0xaf420410, 0x8f420410, 0x8fbf0018, 0x3e00008,
+0x27bd0020, 0x27bdffd8, 0xafbf0020, 0xafb1001c,
+0xafb00018, 0x8f4203a4, 0x24420001, 0xaf4203a4,
+0x8f4203a4, 0x8f900220, 0x8f8200e0, 0xafa20010,
+0x8f8200e4, 0xafa20014, 0x8f8600c4, 0x8f8700c8,
+0x3c040001, 0x24846a78, 0xc002b17, 0x2002821,
+0x3c044000, 0x2041024, 0x504000b4, 0x3c040100,
+0x8f4203bc, 0x24420001, 0xaf4203bc, 0x8f4203bc,
+0x8f8700c4, 0x8f8300c8, 0x8f420148, 0x671823,
+0x43102b, 0x10400003, 0x0, 0x8f420148,
+0x621821, 0x10600005, 0x0, 0x8f42014c,
+0x43102b, 0x1040000b, 0x0, 0x8f8200e0,
+0x8f430124, 0xaf42011c, 0xaf430114, 0x8f820220,
+0x3c0308ff, 0x3463fffb, 0x431024, 0x100000ce,
+0x441025, 0x8f820220, 0x3c0308ff, 0x3463ffff,
+0x431024, 0x34420004, 0xaf820220, 0x8f8200e0,
+0x8f430124, 0xaf42011c, 0xaf430114, 0x8f8600c8,
+0x8f840120, 0x8f830124, 0x10000005, 0x2821,
+0x14620002, 0x24620020, 0x27624800, 0x401821,
+0x1064000c, 0x30a200ff, 0x8c620018, 0x30420003,
+0x1040fff7, 0x27624fe0, 0x8f4203d0, 0x24050001,
+0x24420001, 0xaf4203d0, 0x8f4203d0, 0x8c660008,
+0x30a200ff, 0x14400058, 0x0, 0x934205c4,
+0x14400055, 0x0, 0x8f8700c4, 0x8f8800e0,
+0x8f8400e4, 0x2402fff8, 0x1024024, 0x1041023,
+0x218c3, 0x4620001, 0x24630200, 0x10600005,
+0x24020001, 0x10620009, 0x0, 0x1000001f,
+0x0, 0x8f4203c0, 0xe03021, 0x24420001,
+0xaf4203c0, 0x10000040, 0x8f4203c0, 0x8f4203c4,
+0x24420001, 0xaf4203c4, 0x8c860000, 0x8f420148,
+0x8f4303c4, 0xe61823, 0x43102b, 0x10400004,
+0x2c62233f, 0x8f420148, 0x621821, 0x2c62233f,
+0x14400031, 0x0, 0x8f42020c, 0x24420001,
+0xaf42020c, 0x8f42020c, 0xe03021, 0x24820008,
+0xaf8200e4, 0x10000028, 0xaf8200e8, 0x8f4203c8,
+0x24420001, 0xaf4203c8, 0x8f4203c8, 0x8c850000,
+0x8f420148, 0xa71823, 0x43102b, 0x10400003,
+0x0, 0x8f420148, 0x621821, 0x8f42014c,
+0x43102b, 0x5440000a, 0xa03021, 0x8f42020c,
+0x24420001, 0xaf42020c, 0x8f42020c, 0x24820008,
+0xaf8200e4, 0x8f8400e4, 0x1488ffec, 0xaf8400e8,
+0x1488000d, 0x27623000, 0x14820002, 0x2482fff8,
+0x27623ff8, 0x94430006, 0x3c02001f, 0x3442ffff,
+0xc33021, 0x46102b, 0x10400003, 0x0,
+0x8f420148, 0xc23023, 0xaf8600c8, 0x8f8300c4,
+0x8f420148, 0xc31823, 0x43102b, 0x10400003,
+0x0, 0x8f420148, 0x621821, 0x10600005,
+0x0, 0x8f42014c, 0x43102b, 0x50400008,
+0x3c02fdff, 0x8f820220, 0x3c0308ff, 0x3463fffb,
+0x431024, 0x3c034000, 0x1000003f, 0x431025,
+0x8f4303cc, 0x3442ffff, 0x282a024, 0x24630001,
+0xaf4303cc, 0x10000039, 0x8f4203cc, 0x2041024,
+0x1040000e, 0x3c110200, 0x8f4203a8, 0x24420001,
+0xaf4203a8, 0x8f4203a8, 0x8f820220, 0x3c0308ff,
+0x3463ffff, 0x431024, 0x441025, 0xc003d87,
0xaf820220, 0x10000029, 0x0, 0x2111024,
-0x50400008, 0x3c110400, 0x8f42039c, 0x24420001,
-0xaf42039c, 0xc003b0b, 0x8f42039c, 0x10000019,
+0x50400008, 0x3c110400, 0x8f4203ac, 0x24420001,
+0xaf4203ac, 0xc003d87, 0x8f4203ac, 0x10000019,
0x0, 0x2111024, 0x1040001c, 0x0,
0x8f830224, 0x24021402, 0x14620009, 0x3c050008,
-0x3c040001, 0x24843a74, 0xafa00010, 0xafa00014,
-0x8f860224, 0x34a50500, 0xc0029bb, 0x3821,
-0x8f4203a0, 0x24420001, 0xaf4203a0, 0x8f4203a0,
-0x8f820220, 0x2002021, 0x34420002, 0xc00456c,
+0x3c040001, 0x24846a84, 0xafa00010, 0xafa00014,
+0x8f860224, 0x34a50500, 0xc002b17, 0x3821,
+0x8f4203b0, 0x24420001, 0xaf4203b0, 0x8f4203b0,
+0x8f820220, 0x2002021, 0x34420002, 0xc004ecc,
0xaf820220, 0x8f820220, 0x3c0308ff, 0x3463ffff,
0x431024, 0x511025, 0xaf820220, 0x8fbf0020,
0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0028,
-0x3e00008, 0x0, 0x3c020001, 0x8c423d98,
+0x3e00008, 0x0, 0x3c020001, 0x8c426e28,
0x27bdffb0, 0xafbf0048, 0xafbe0044, 0xafb50040,
0xafb3003c, 0xafb20038, 0xafb10034, 0x1040000f,
-0xafb00030, 0x3c040001, 0x24843a80, 0x3c050008,
+0xafb00030, 0x3c040001, 0x24846a90, 0x3c050008,
0xafa00010, 0xafa00014, 0x8f860220, 0x34a50600,
-0x24020001, 0x3c010001, 0xac203d98, 0x3c010001,
-0xac223d8c, 0xc0029bb, 0x3821, 0x3c037fff,
+0x24020001, 0x3c010001, 0xac206e28, 0x3c010001,
+0xac226e1c, 0xc002b17, 0x3821, 0x3c037fff,
0x8c020268, 0x3463ffff, 0x3c04fdff, 0x431024,
0xac020268, 0x8f420004, 0x3484ffff, 0x30420002,
0x10400092, 0x284a024, 0x3c040600, 0x34842000,
@@ -7248,49 +7545,58 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0xaf420004, 0xafa40020, 0x8f5e0018, 0x27aa0020,
0x240200ff, 0x13c20002, 0xafaa002c, 0x27c50001,
0x8c020228, 0xa09021, 0x1642000e, 0x1e38c0,
-0x8f42032c, 0x24420001, 0xaf42032c, 0x8f42032c,
-0x8c020228, 0x3c040001, 0x24843a18, 0x3c050009,
+0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
+0x8c020228, 0x3c040001, 0x24846a28, 0x3c050009,
0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006d,
0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024,
0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054,
0x247003e8, 0x2021023, 0x2c4203e9, 0x1040001b,
-0x9821, 0xe08821, 0x263504c0, 0x8f440168,
-0x8f45016c, 0x2201821, 0x240a0004, 0xafaa0010,
+0x9821, 0xe08821, 0x263504c0, 0x8f440178,
+0x8f45017c, 0x2201821, 0x240a0004, 0xafaa0010,
0xafb20014, 0x8f48000c, 0x1021, 0x2f53021,
0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
0xa3482b, 0x822021, 0x100f809, 0x892021,
0x54400006, 0x24130001, 0x8f820054, 0x2021023,
0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff,
-0x54400017, 0xaf520018, 0x8f420368, 0x24420001,
-0xaf420368, 0x8f420368, 0x8f820120, 0x8faa002c,
-0xafa20010, 0x8f820124, 0x3c040001, 0x24843a24,
+0x54400017, 0xaf520018, 0x8f420378, 0x24420001,
+0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c,
+0xafa20010, 0x8f820124, 0x3c040001, 0x24846a34,
0x3c050009, 0xafa20014, 0x8d460000, 0x10000035,
-0x34a50600, 0x8f4202f8, 0x24130001, 0x24420001,
-0xaf4202f8, 0x8f4202f8, 0x1000001e, 0x326200ff,
+0x34a50600, 0x8f420308, 0x24130001, 0x24420001,
+0xaf420308, 0x8f420308, 0x1000001e, 0x326200ff,
0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
0x2c4203e9, 0x10400016, 0x9821, 0x3c150020,
-0x24110010, 0x8f42000c, 0x8f440150, 0x8f450154,
+0x24110010, 0x8f42000c, 0x8f440160, 0x8f450164,
0x8f860120, 0xafb10010, 0xafb20014, 0x551025,
0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
0x24c6001c, 0x1440ffe3, 0x0, 0x8f820054,
0x2021023, 0x2c4203e9, 0x1440ffee, 0x0,
-0x326200ff, 0x14400011, 0x0, 0x8f420368,
-0x24420001, 0xaf420368, 0x8f420368, 0x8f820120,
+0x326200ff, 0x14400011, 0x0, 0x8f420378,
+0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
0x8faa002c, 0xafa20010, 0x8f820124, 0x3c040001,
-0x24843a2c, 0x3c050009, 0xafa20014, 0x8d460000,
-0x34a50700, 0xc0029bb, 0x3c03821, 0x8f4202dc,
-0x24420001, 0xaf4202dc, 0x8f4202dc, 0x8fbf0048,
+0x24846a3c, 0x3c050009, 0xafa20014, 0x8d460000,
+0x34a50700, 0xc002b17, 0x3c03821, 0x8f4202ec,
+0x24420001, 0xaf4202ec, 0x8f4202ec, 0x8fbf0048,
0x8fbe0044, 0x8fb50040, 0x8fb3003c, 0x8fb20038,
0x8fb10034, 0x8fb00030, 0x3e00008, 0x27bd0050,
-0x3c020001, 0x8c423d98, 0x27bdffe0, 0x1440000d,
-0xafbf0018, 0x3c040001, 0x24843a8c, 0x3c050008,
+0x3c020001, 0x8c426e28, 0x27bdffe0, 0x1440000d,
+0xafbf0018, 0x3c040001, 0x24846a9c, 0x3c050008,
0xafa00010, 0xafa00014, 0x8f860220, 0x34a50700,
-0x24020001, 0x3c010001, 0xac223d98, 0xc0029bb,
-0x3821, 0x3c020004, 0x2c21024, 0x10400008,
-0x2021, 0x8f820220, 0x3c0308ff, 0x3463ffff,
-0x431024, 0x34420008, 0xaf820220, 0x2021,
-0xc0048dd, 0x24050004, 0xac020268, 0x8fbf0018,
-0x3e00008, 0x27bd0020, 0x0, 0x86102b,
+0x24020001, 0x3c010001, 0xac226e28, 0xc002b17,
+0x3821, 0x3c020004, 0x2c21024, 0x10400007,
+0x0, 0x8f820220, 0x3c0308ff, 0x3463ffff,
+0x431024, 0x34420008, 0xaf820220, 0x3c050001,
+0x8ca56e18, 0x24020001, 0x14a20007, 0x2021,
+0xc0052c7, 0x24050001, 0xac02026c, 0x8c03026c,
+0x10000006, 0x3c020007, 0xc0052c7, 0x2021,
+0xac020268, 0x8c030268, 0x3c020007, 0x621824,
+0x3c020002, 0x5062000d, 0x3c0205f5, 0x43102b,
+0x14400006, 0x3c020004, 0x3c020001, 0x10620009,
+0x3c020098, 0x1000000b, 0x0, 0x14620009,
+0x3c023b9a, 0x10000004, 0x3442ca00, 0x10000002,
+0x3442e100, 0x34429680, 0xaf4201fc, 0x8f4201fc,
+0xaee20064, 0x8fbf0018, 0x3e00008, 0x27bd0020,
+0x0, 0x0, 0x0, 0x86102b,
0x50400001, 0x872023, 0xc41023, 0x24843,
0x125102b, 0x1040001b, 0x91040, 0x824021,
0x88102b, 0x10400007, 0x1821, 0x94820000,
@@ -7309,28 +7615,28 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x24a20004, 0x62102b, 0x54400007, 0x65102b,
0x90a20001, 0x90a40003, 0x90a30000, 0x90a50002,
0x1000002a, 0x441021, 0x10400003, 0x0,
-0x8f42013c, 0xa22823, 0x90a40000, 0x24a50001,
-0x65102b, 0x10400003, 0x0, 0x8f42013c,
+0x8f420148, 0xa22823, 0x90a40000, 0x24a50001,
+0x65102b, 0x10400003, 0x0, 0x8f420148,
0xa22823, 0x90a20000, 0x24a50001, 0x21200,
0x822021, 0x65102b, 0x10400003, 0x0,
-0x8f42013c, 0xa22823, 0x90a20000, 0x24a50001,
+0x8f420148, 0xa22823, 0x90a20000, 0x24a50001,
0x822021, 0x65102b, 0x10400003, 0x0,
-0x8f42013c, 0xa22823, 0x90a20000, 0x1000002d,
+0x8f420148, 0xa22823, 0x90a20000, 0x1000002d,
0x21200, 0x3463ffff, 0x24a20004, 0x62102b,
0x5440000a, 0x65102b, 0x90a20000, 0x90a40002,
0x90a30001, 0x90a50003, 0x441021, 0x21200,
0x651821, 0x10000020, 0x432021, 0x10400003,
-0x0, 0x8f42013c, 0xa22823, 0x90a20000,
+0x0, 0x8f420148, 0xa22823, 0x90a20000,
0x24a50001, 0x22200, 0x65102b, 0x10400003,
-0x0, 0x8f42013c, 0xa22823, 0x90a20000,
+0x0, 0x8f420148, 0xa22823, 0x90a20000,
0x24a50001, 0x822021, 0x65102b, 0x10400003,
-0x0, 0x8f42013c, 0xa22823, 0x90a20000,
+0x0, 0x8f420148, 0xa22823, 0x90a20000,
0x24a50001, 0x21200, 0x822021, 0x65102b,
-0x10400003, 0x0, 0x8f42013c, 0xa22823,
+0x10400003, 0x0, 0x8f420148, 0xa22823,
0x90a20000, 0x822021, 0x41c02, 0x3082ffff,
0x622021, 0x41c02, 0x3082ffff, 0x622021,
0x3e00008, 0x3082ffff, 0x0, 0x8f820220,
-0x34420002, 0xaf820220, 0x3c020001, 0x8c425f98,
+0x34420002, 0xaf820220, 0x3c020002, 0x8c429078,
0x30424000, 0x10400054, 0x24040001, 0x8f820200,
0x24067fff, 0x8f830200, 0x30450002, 0x2402fffd,
0x621824, 0xaf830200, 0xaf840204, 0x8f830054,
@@ -7377,502 +7683,880 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x43102b, 0x14400006, 0x3c026000, 0x3c024000,
0x10620008, 0x24020800, 0x10000008, 0x0,
0x10620004, 0x24020800, 0x10000004, 0x0,
-0x24020700, 0x3c010001, 0xac223d9c, 0x3e00008,
-0x0, 0x27bdffc8, 0xafbf0034, 0xafb20030,
-0xafb1002c, 0xafb00028, 0x3c010001, 0xc004549,
-0xac203d84, 0x24040001, 0x2821, 0x27a60020,
-0x34028000, 0xc004166, 0xa7a20020, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630064, 0x8f820054,
-0x621023, 0x2c420065, 0x1440fffc, 0x24040001,
-0x24050001, 0xc004124, 0x27a60020, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630064, 0x8f820054,
-0x621023, 0x2c420065, 0x1440fffc, 0x24040001,
-0x24050001, 0xc004124, 0x27a60020, 0x8f830054,
+0x24020700, 0x3c010001, 0xac226e2c, 0x3e00008,
+0x0, 0x3c020001, 0x8c426e3c, 0x27bdffc8,
+0xafbf0034, 0xafb20030, 0xafb1002c, 0xafb00028,
+0x3c010001, 0x10400005, 0xac206e14, 0xc004dd1,
+0x0, 0x3c010001, 0xac206e3c, 0x8f830054,
0x8f820054, 0x10000002, 0x24630064, 0x8f820054,
-0x621023, 0x2c420065, 0x1440fffc, 0x24040001,
-0x24050002, 0xc004124, 0x27a60018, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630064, 0x8f820054,
-0x621023, 0x2c420065, 0x1440fffc, 0x24040001,
-0x24050003, 0xc004124, 0x27a6001a, 0x97a20020,
-0x1040002a, 0x24020001, 0x3c020001, 0x8c423d84,
-0x97a30018, 0x34420001, 0x3c010001, 0xac223d84,
-0x24020015, 0x1462000a, 0x0, 0x97a2001a,
-0x3042fff0, 0x3843f420, 0x2c630001, 0x3842f430,
-0x2c420001, 0x621825, 0x14600018, 0x24020003,
-0x97a30018, 0x24027810, 0x14620014, 0x24020002,
-0x97a2001a, 0x3042fff0, 0x14400010, 0x24020002,
-0x1000000e, 0x24020004, 0x3c020001, 0x8c423d84,
-0x34420008, 0x3c010001, 0xac223d84, 0x10000058,
-0x24020004, 0x3c020001, 0x8c423d84, 0x34420004,
-0x3c010001, 0x100000a9, 0xac223d84, 0x3c010001,
-0xac223ee0, 0x24020e00, 0xaf820238, 0x8f840054,
-0x8f820054, 0x24030008, 0x3c010001, 0xac233d88,
-0x10000002, 0x248401f4, 0x8f820054, 0x821023,
-0x2c4201f5, 0x1440fffc, 0x3c0200c8, 0x344201fb,
+0x621023, 0x2c420065, 0x1440fffc, 0x0,
+0xc004dec, 0x0, 0x24040001, 0x2821,
+0x27a60020, 0x34028000, 0xc00450e, 0xa7a20020,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
+0x24040001, 0x24050001, 0xc0044cc, 0x27a60020,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
+0x24040001, 0x24050001, 0xc0044cc, 0x27a60020,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
+0x24040001, 0x24050002, 0xc0044cc, 0x27a60018,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
+0x24040001, 0x24050003, 0xc0044cc, 0x27a6001a,
+0x3c040001, 0x24846b70, 0x97a60020, 0x97a70018,
+0x97a2001a, 0x3c05000d, 0x34a50100, 0xafa00014,
+0xc002b17, 0xafa20010, 0x97a20020, 0x10400046,
+0x24036040, 0x97a2001a, 0x3042fff0, 0x1443000b,
+0x24020020, 0x97a30018, 0x1462000a, 0x24027830,
+0x24020003, 0x3c010001, 0xac226e14, 0x24020005,
+0x3c010001, 0x10000039, 0xac226fac, 0x97a30018,
+0x24027830, 0x1462000b, 0x24030010, 0x97a2001a,
+0x3042fff0, 0x14430007, 0x24020003, 0x3c010001,
+0xac226e14, 0x24020006, 0x3c010001, 0x1000002b,
+0xac226fac, 0x3c020001, 0x8c426e14, 0x97a30018,
+0x34420001, 0x3c010001, 0xac226e14, 0x24020015,
+0x1462000a, 0x0, 0x97a2001a, 0x3042fff0,
+0x3843f420, 0x2c630001, 0x3842f430, 0x2c420001,
+0x621825, 0x14600019, 0x24020003, 0x97a30018,
+0x24027810, 0x14620015, 0x24020002, 0x97a2001a,
+0x3042fff0, 0x14400011, 0x24020002, 0x1000000f,
+0x24020004, 0x3c020001, 0x8c426e14, 0x34420008,
+0x3c010001, 0xac226e14, 0x1000005e, 0x24020004,
+0x3c020001, 0x8c426e14, 0x34420004, 0x3c010001,
+0x100000af, 0xac226e14, 0x24020001, 0x3c010001,
+0xac226fb8, 0x3c020001, 0x8c426e14, 0x30420002,
+0x144000b2, 0x3c09fff0, 0x24020e00, 0xaf820238,
+0x8f840054, 0x8f820054, 0x24030008, 0x3c010001,
+0xac236e18, 0x10000002, 0x248401f4, 0x8f820054,
+0x821023, 0x2c4201f5, 0x1440fffc, 0x3c0200c8,
+0x344201fb, 0xaf820238, 0x8f830054, 0x8f820054,
+0x10000002, 0x246301f4, 0x8f820054, 0x621023,
+0x2c4201f5, 0x1440fffc, 0x8021, 0x24120001,
+0x24110009, 0xc0043d3, 0x0, 0x3c010001,
+0xac326e34, 0xc004498, 0x0, 0x3c020001,
+0x8c426e34, 0x1451fffb, 0x3c0200c8, 0x344201f6,
0xaf820238, 0x8f830054, 0x8f820054, 0x10000002,
-0x246301f4, 0x8f820054, 0x621023, 0x2c4201f5,
-0x1440fffc, 0x8021, 0x24120001, 0x24110009,
-0xc004045, 0x0, 0x3c010001, 0xac323da0,
-0xc0040f2, 0x0, 0x3c020001, 0x8c423da0,
-0x1451fffb, 0x3c0200c8, 0x344201f6, 0xaf820238,
-0x8f830054, 0x8f820054, 0x10000002, 0x2463000a,
-0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc,
+0x2463000a, 0x8f820054, 0x621023, 0x2c42000b,
+0x1440fffc, 0x0, 0x8f820220, 0x24040001,
+0x34420002, 0xaf820220, 0x8f830200, 0x24057fff,
+0x2402fffd, 0x621824, 0xaf830200, 0xaf840204,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
+0x0, 0x8f820224, 0x14440005, 0x34028000,
+0x42040, 0xa4102b, 0x1040fff0, 0x34028000,
+0x1082ffa0, 0x26100001, 0x2e020014, 0x1440ffcd,
+0x24020004, 0x3c010001, 0xac226e18, 0x8021,
+0x24120009, 0x3c11ffff, 0x36313f7f, 0xc0043d3,
+0x0, 0x24020001, 0x3c010001, 0xac226e34,
+0xc004498, 0x0, 0x3c020001, 0x8c426e34,
+0x1452fffb, 0x0, 0x8f820044, 0x511024,
+0x34425080, 0xaf820044, 0x8f830054, 0x8f820054,
+0x10000002, 0x2463000a, 0x8f820054, 0x621023,
+0x2c42000b, 0x1440fffc, 0x0, 0x8f820044,
+0x511024, 0x3442f080, 0xaf820044, 0x8f830054,
+0x8f820054, 0x10000002, 0x2463000a, 0x8f820054,
+0x621023, 0x2c42000b, 0x1440fffc, 0x0,
+0x8f820220, 0x3c03f700, 0x431025, 0xaf820220,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
0x0, 0x8f820220, 0x24040001, 0x34420002,
0xaf820220, 0x8f830200, 0x24057fff, 0x2402fffd,
0x621824, 0xaf830200, 0xaf840204, 0x8f830054,
0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
0x621023, 0x2c420002, 0x1440fffc, 0x0,
0x8f820224, 0x14440005, 0x34028000, 0x42040,
-0xa4102b, 0x1040fff0, 0x34028000, 0x1082ffa6,
-0x26100001, 0x2e020014, 0x1440ffcd, 0x24020004,
-0x3c010001, 0xac223d88, 0x8021, 0x24120009,
-0x3c11ffff, 0x36313f7f, 0xc004045, 0x0,
-0x24020001, 0x3c010001, 0xac223da0, 0xc0040f2,
-0x0, 0x3c020001, 0x8c423da0, 0x1452fffb,
-0x0, 0x8f820044, 0x511024, 0x34425080,
-0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
-0x2463000a, 0x8f820054, 0x621023, 0x2c42000b,
-0x1440fffc, 0x0, 0x8f820044, 0x511024,
-0x3442f080, 0xaf820044, 0x8f830054, 0x8f820054,
-0x10000002, 0x2463000a, 0x8f820054, 0x621023,
-0x2c42000b, 0x1440fffc, 0x0, 0x8f820220,
-0x3c03f700, 0x431025, 0xaf820220, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630064, 0x8f820054,
-0x621023, 0x2c420065, 0x1440fffc, 0x0,
-0x8f820220, 0x24040001, 0x34420002, 0xaf820220,
-0x8f830200, 0x24057fff, 0x2402fffd, 0x621824,
-0xaf830200, 0xaf840204, 0x8f830054, 0x8f820054,
-0x10000002, 0x24630001, 0x8f820054, 0x621023,
-0x2c420002, 0x1440fffc, 0x0, 0x8f820224,
-0x14440005, 0x34028000, 0x42040, 0xa4102b,
-0x1040fff0, 0x34028000, 0x1082ff56, 0x26100001,
-0x2e020064, 0x1440ffb0, 0x0, 0x3c020001,
-0x8c423d84, 0x30420004, 0x14400007, 0x3c08fff0,
-0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024,
-0xaf820044, 0x3c08fff0, 0x3508bdc0, 0x8f830054,
-0x97a60018, 0x3c070001, 0x8ce73ee0, 0x3c040001,
-0x24843b60, 0x24020001, 0x3c010001, 0xac223d8c,
-0xafa60010, 0x3c060001, 0x8cc63d84, 0x97a2001a,
-0x3c05000d, 0x34a50100, 0x3c010001, 0xac203d88,
-0x681821, 0x3c010001, 0xac233ed8, 0xc0029bb,
-0xafa20014, 0x8fbf0034, 0x8fb20030, 0x8fb1002c,
-0x8fb00028, 0x3e00008, 0x27bd0038, 0x27bdffe8,
-0x24070004, 0x3c040001, 0x8c843d88, 0x3021,
-0x24020001, 0x1482000a, 0xafbf0010, 0x3c020001,
-0x8c425f9c, 0x3c050004, 0x30428000, 0x1040000c,
-0x34a593e0, 0x3c05000f, 0x10000009, 0x34a54240,
-0x3c020001, 0x8c425f9c, 0x3c05000f, 0x30428000,
-0x10400003, 0x34a54240, 0x3c05001e, 0x34a58480,
-0x3c020001, 0x8c423ed8, 0x8f830054, 0x451021,
-0x431023, 0x45102b, 0x1440002e, 0x0,
-0x3c020001, 0x8c423d90, 0x1440002a, 0x2cc20001,
-0x7182b, 0x431024, 0x1040001d, 0x0,
-0x3c090001, 0x8d293d84, 0x240b0001, 0x3c054000,
-0x3c080001, 0x25085f9c, 0x250afffc, 0x42042,
-0x14800002, 0x24e7ffff, 0x24040008, 0x891024,
-0x5040000b, 0x2cc20001, 0x148b0004, 0x0,
-0x8d020000, 0x10000003, 0x451024, 0x8d420000,
-0x451024, 0x54400001, 0x24060001, 0x2cc20001,
-0x7182b, 0x431024, 0x5440ffed, 0x42042,
-0x3c010001, 0x10c00020, 0xac243d88, 0x8f830054,
-0x24020001, 0x3c010001, 0xac223d8c, 0x3c010001,
-0xac233ed8, 0x3c020001, 0x8c423d8c, 0x10400004,
-0x24020001, 0x3c010001, 0xac203d8c, 0xaee204b8,
-0x8ee304b8, 0x24020008, 0x10620005, 0x24020001,
-0xc003eee, 0x0, 0x1000000b, 0x0,
-0x3c030001, 0x8c633d88, 0x10620007, 0x2402000e,
-0x3c030001, 0x8c635f30, 0x10620003, 0x0,
-0xc00456c, 0x8f840220, 0x8fbf0010, 0x3e00008,
-0x27bd0018, 0x27bdffe0, 0x3c03fdff, 0x3c040001,
-0x8c843d88, 0x3c020001, 0x8c423da8, 0x3463ffff,
-0x283a024, 0x14820006, 0xafbf0018, 0x8ee304b8,
-0x3c020001, 0x8c423dac, 0x10620006, 0x0,
-0x8ee204b8, 0x3c010001, 0xac243da8, 0x3c010001,
-0xac223dac, 0x3c030001, 0x8c633d88, 0x24020002,
-0x1062013c, 0x2c620003, 0x10400005, 0x24020001,
-0x1062000a, 0x0, 0x10000134, 0x0,
-0x24020004, 0x1062006d, 0x24020008, 0x1062009f,
-0x24020001, 0x1000012d, 0x0, 0x8ee204b8,
-0x2443ffff, 0x2c620008, 0x1040012a, 0x31080,
-0x3c010001, 0x220821, 0x8c223b78, 0x400008,
-0x0, 0xc004045, 0x0, 0x3c020001,
-0x8c423d94, 0x3c010001, 0xac203d20, 0x104000d7,
-0x24020002, 0xaee204b8, 0x3c010001, 0x10000119,
-0xac203d94, 0xc0041a7, 0x0, 0x3c030001,
-0x8c633db0, 0x1000009e, 0x24020011, 0x3c050001,
-0x8ca53d88, 0x3c060001, 0x8cc65f9c, 0xc0047d4,
-0x2021, 0x24020005, 0x3c010001, 0xac203d94,
-0x10000108, 0xaee204b8, 0x3c040001, 0x24843b6c,
-0x3c05000f, 0x34a50100, 0x3021, 0x3821,
-0xafa00010, 0xc0029bb, 0xafa00014, 0x100000fd,
-0x0, 0x8f820220, 0x3c03f700, 0x431025,
-0x100000a4, 0xaf820220, 0x8f820220, 0x3c030004,
-0x431024, 0x144000ae, 0x24020007, 0x8f830054,
-0x3c020001, 0x8c423ed0, 0x2463d8f0, 0x431023,
-0x2c422710, 0x144000eb, 0x24020001, 0x100000e7,
-0x0, 0x3c050001, 0x8ca53d88, 0xc0048dd,
-0x2021, 0xc0049a8, 0x2021, 0x3c030001,
-0x8c635f94, 0x46100dd, 0x24020001, 0x3c020008,
-0x621024, 0x10400006, 0x0, 0x8f820214,
-0x3c03ffff, 0x431024, 0x10000005, 0x3442251f,
-0x8f820214, 0x3c03ffff, 0x431024, 0x3442241f,
-0xaf820214, 0x8f820220, 0x3c030200, 0x283a025,
-0x34420002, 0xaf820220, 0x24020008, 0xc003bc9,
-0xaee204b8, 0x100000c7, 0x0, 0x8ee204b8,
-0x2443ffff, 0x2c620008, 0x104000c2, 0x31080,
-0x3c010001, 0x220821, 0x8c223b98, 0x400008,
-0x0, 0x3c020001, 0x8c425f98, 0x30424000,
+0xa4102b, 0x1040fff0, 0x34028000, 0x1082ff50,
+0x26100001, 0x2e020064, 0x1440ffb0, 0x0,
+0x3c020001, 0x8c426e14, 0x30420004, 0x14400007,
+0x3c09fff0, 0x8f820044, 0x3c03ffff, 0x34633f7f,
+0x431024, 0xaf820044, 0x3c09fff0, 0x3529bdc0,
+0x8f830054, 0x3c060001, 0x8cc66e14, 0x3c070001,
+0x8ce76fb8, 0x97a80018, 0x3c040001, 0x24846b70,
+0x24020001, 0x3c010001, 0xac226e1c, 0xafa80010,
+0x97a2001a, 0x3c05000d, 0x34a50100, 0x3c010001,
+0xac206e18, 0x691821, 0x3c010001, 0xac236fa8,
+0xc002b17, 0xafa20014, 0x8fbf0034, 0x8fb20030,
+0x8fb1002c, 0x8fb00028, 0x3e00008, 0x27bd0038,
+0x27bdffe8, 0x3c050001, 0x8ca56e18, 0x24060004,
+0x24020001, 0x14a20014, 0xafbf0010, 0x3c020002,
+0x8c42907c, 0x30428000, 0x10400005, 0x3c04000f,
+0x3c030001, 0x8c636fb8, 0x10000005, 0x34844240,
+0x3c040004, 0x3c030001, 0x8c636fb8, 0x348493e0,
+0x24020005, 0x14620016, 0x0, 0x3c04003d,
+0x10000013, 0x34840900, 0x3c020002, 0x8c429078,
+0x30428000, 0x10400005, 0x3c04001e, 0x3c030001,
+0x8c636fb8, 0x10000005, 0x34848480, 0x3c04000f,
+0x3c030001, 0x8c636fb8, 0x34844240, 0x24020005,
+0x14620003, 0x0, 0x3c04007a, 0x34841200,
+0x3c020001, 0x8c426fa8, 0x8f830054, 0x441021,
+0x431023, 0x44102b, 0x1440004b, 0x0,
+0x3c020001, 0x8c426e20, 0x14400047, 0x0,
+0x3c010001, 0x10c00025, 0xac206e30, 0x3c090001,
+0x8d296e14, 0x24070001, 0x3c044000, 0x3c080002,
+0x2508907c, 0x250afffc, 0x52842, 0x14a00002,
+0x24c6ffff, 0x24050008, 0xa91024, 0x10400010,
+0x0, 0x14a70008, 0x0, 0x8d020000,
+0x441024, 0x1040000a, 0x0, 0x3c010001,
+0x10000007, 0xac256e30, 0x8d420000, 0x441024,
+0x10400003, 0x0, 0x3c010001, 0xac276e30,
+0x3c020001, 0x8c426e30, 0x6182b, 0x2c420001,
+0x431024, 0x5440ffe5, 0x52842, 0x8f820054,
+0x3c030001, 0x8c636e30, 0x3c010001, 0xac226fa8,
+0x1060003a, 0x24020005, 0x3c030001, 0x8c636fb8,
+0x3c010001, 0xac256e18, 0x14620011, 0x24020001,
+0x3c020002, 0x8c429078, 0x3c032000, 0x431024,
+0x14400006, 0x24020001, 0x3c010001, 0xac206f98,
+0x3c010001, 0xac226e18, 0x24020001, 0x3c010001,
+0xac226ea4, 0x3c010001, 0xac226e24, 0x24020001,
+0x3c010001, 0xac226e1c, 0x3c020001, 0x8c426e30,
+0x1040001e, 0x0, 0x3c020001, 0x8c426e1c,
+0x10400008, 0x24020001, 0x3c010001, 0xac206e1c,
+0xaee204b8, 0x3c010001, 0xac206e9c, 0x3c010001,
+0xac226e54, 0x8ee304b8, 0x24020008, 0x10620005,
+0x24020001, 0xc004203, 0x0, 0x1000000b,
+0x0, 0x3c030001, 0x8c636e18, 0x10620007,
+0x2402000e, 0x3c030002, 0x8c639010, 0x10620003,
+0x0, 0xc004ecc, 0x8f840220, 0x8fbf0010,
+0x3e00008, 0x27bd0018, 0x27bdffe0, 0x3c03fdff,
+0x3c040001, 0x8c846e18, 0x3c020001, 0x8c426e40,
+0x3463ffff, 0x283a024, 0xafbf001c, 0x14820006,
+0xafb00018, 0x8ee304b8, 0x3c020001, 0x8c426e44,
+0x10620006, 0x0, 0x8ee204b8, 0x3c010001,
+0xac246e40, 0x3c010001, 0xac226e44, 0x3c030001,
+0x8c636e18, 0x24020002, 0x10620167, 0x2c620003,
+0x10400005, 0x24020001, 0x1062000a, 0x0,
+0x100001ab, 0x0, 0x24020004, 0x10620081,
+0x24020008, 0x106200d5, 0x24020001, 0x100001a4,
+0x0, 0x8ee204b8, 0x2443ffff, 0x2c620008,
+0x104001a1, 0x31080, 0x3c010001, 0x220821,
+0x8c226b88, 0x400008, 0x0, 0x3c030001,
+0x8c636fb8, 0x24020005, 0x14620010, 0x0,
+0x3c020001, 0x8c426e24, 0x10400008, 0x24020003,
+0xc0043d3, 0x0, 0x24020002, 0xaee204b8,
+0x3c010001, 0x10000002, 0xac206e24, 0xaee204b8,
+0x3c010001, 0x10000188, 0xac206db0, 0xc0043d3,
+0x0, 0x3c020001, 0x8c426e24, 0x3c010001,
+0xac206db0, 0x14400145, 0x24020002, 0x10000163,
+0x24020007, 0x24020001, 0x3c010001, 0xc00454f,
+0xac226e50, 0x3c030001, 0x8c636e50, 0x10000144,
+0x24020011, 0x3c020001, 0x8c426fb8, 0x24100005,
+0x10500007, 0x0, 0x3c050001, 0x8ca56e18,
+0x3c060002, 0x8cc6907c, 0xc005134, 0x2021,
+0x3c010001, 0xac206e24, 0x10000167, 0xaef004b8,
+0x3c040001, 0x24846b7c, 0x3c05000f, 0x34a50100,
+0x3021, 0x3821, 0xafa00010, 0xc002b17,
+0xafa00014, 0x1000015c, 0x0, 0x8f820220,
+0x3c030004, 0x431024, 0x1440013c, 0x24020007,
+0x8f830054, 0x3c020001, 0x8c426fa0, 0x2463d8f0,
+0x431023, 0x2c422710, 0x1440014f, 0x24020001,
+0x1000014b, 0x0, 0x3c050001, 0x8ca56e18,
+0xc0052c7, 0x2021, 0xc00553d, 0x2021,
+0x3c030002, 0x8c639074, 0x4610141, 0x24020001,
+0x3c020008, 0x621024, 0x10400006, 0x0,
+0x8f820214, 0x3c03ffff, 0x431024, 0x10000005,
+0x3442251f, 0x8f820214, 0x3c03ffff, 0x431024,
+0x3442241f, 0xaf820214, 0x8f820220, 0x3c030200,
+0x283a025, 0x34420002, 0xaf820220, 0x24020008,
+0xc003e45, 0xaee204b8, 0x3c010001, 0x1000012a,
+0xac206ea0, 0x8ee204b8, 0x2443ffff, 0x2c620008,
+0x10400125, 0x31080, 0x3c010001, 0x220821,
+0x8c226ba8, 0x400008, 0x0, 0xc004498,
+0x0, 0x3c030001, 0x8c636e34, 0x100000e8,
+0x24020009, 0x3c020002, 0x8c429078, 0x30424000,
0x10400004, 0x0, 0x8f820044, 0x10000006,
0x3442f080, 0x8f820044, 0x3c03ffff, 0x34633f7f,
0x431024, 0x3442a080, 0xaf820044, 0x8f830054,
-0x1000005a, 0x24020004, 0xc003c88, 0x0,
-0x104000a6, 0x24020001, 0x8f820214, 0x3c03ffff,
-0x3c040001, 0x8c843ec8, 0x431024, 0x3442251f,
+0x100000ea, 0x24020004, 0x8f830054, 0x3c020001,
+0x8c426fa0, 0x2463d8f0, 0x431023, 0x2c422710,
+0x14400101, 0x24020005, 0x100000d8, 0x0,
+0x8f820220, 0x3c03f700, 0x431025, 0xaf820220,
+0xaf800204, 0x3c010002, 0x100000d6, 0xac209060,
+0x8f830054, 0x3c020001, 0x8c426fa0, 0x2463fff6,
+0x431023, 0x2c42000a, 0x144000ef, 0x24020007,
+0x100000d2, 0x0, 0xc003f28, 0x0,
+0x104000e7, 0x24020001, 0x8f820214, 0x3c03ffff,
+0x3c040001, 0x8c846f98, 0x431024, 0x3442251f,
0xaf820214, 0x24020008, 0x10800005, 0xaee204b8,
-0x3c020001, 0x8c423e14, 0x1040006d, 0x24020001,
-0x8f820220, 0x3c030008, 0x431024, 0x10400073,
-0x3c020200, 0x10000081, 0x0, 0x8ee204b8,
-0x2443ffff, 0x2c620007, 0x1040008e, 0x31080,
-0x3c010001, 0x220821, 0x8c223bb8, 0x400008,
-0x0, 0xc003b0b, 0x0, 0x3c010001,
-0xac203d8c, 0xaf800204, 0x3c010001, 0xc004045,
-0xac205f80, 0x24020001, 0x3c010001, 0xac223da0,
-0x24020002, 0x1000007b, 0xaee204b8, 0xc0040f2,
-0x0, 0x3c030001, 0x8c633da0, 0x24020009,
-0x14620074, 0x24020003, 0x10000072, 0xaee204b8,
-0x3c020001, 0x8c425f98, 0x30424000, 0x10400003,
-0x3c0200c8, 0x10000002, 0x344201f6, 0x344201fe,
-0xaf820238, 0x8f830054, 0x10000014, 0x24020004,
-0x8f830054, 0x3c020001, 0x8c423ed0, 0x2463d8f0,
-0x431023, 0x2c422710, 0x1440005e, 0x24020005,
-0x1000005c, 0xaee204b8, 0x8f820220, 0x3c03f700,
-0x431025, 0xaf820220, 0xaf800204, 0x3c010001,
-0xac205f80, 0x8f830054, 0x24020006, 0xaee204b8,
-0x3c010001, 0x1000004f, 0xac233ed0, 0x8f830054,
-0x3c020001, 0x8c423ed0, 0x2463fff6, 0x431023,
-0x2c42000a, 0x14400047, 0x0, 0x24020007,
-0x10000044, 0xaee204b8, 0xc003c88, 0x0,
-0x1040003e, 0x24020001, 0x8f820214, 0x3c03ffff,
-0x3c040001, 0x8c843ec8, 0x431024, 0x3442251f,
-0xaf820214, 0x24020008, 0x1080000f, 0xaee204b8,
-0x3c020001, 0x8c423e14, 0x1440000b, 0x0,
-0x8f820220, 0x34420002, 0xaf820220, 0x24020001,
-0x3c010001, 0xac225f30, 0xc00456c, 0x8f840220,
-0x10000016, 0x0, 0x8f820220, 0x3c030008,
-0x431024, 0x14400011, 0x3c020200, 0x282a025,
-0x2402000e, 0x3c010001, 0xac225f30, 0xc0049a8,
-0x2021, 0x8f820220, 0x34420002, 0xc003bc9,
-0xaf820220, 0x3c050001, 0x8ca53d88, 0xc0048dd,
-0x2021, 0x10000013, 0x0, 0x3c020001,
-0x8c423e14, 0x1040000f, 0x0, 0x3c020001,
-0x8c423e10, 0x2442ffff, 0x3c010001, 0xac223e10,
-0x14400008, 0x24020002, 0x3c010001, 0xac203e14,
-0x3c010001, 0x10000003, 0xac223e10, 0x3c010001,
-0xac223d8c, 0x8fbf0018, 0x3e00008, 0x27bd0020,
-0x8f820200, 0x8f820220, 0x8f820220, 0x34420004,
-0xaf820220, 0x8f820200, 0x3c060001, 0x8cc63d88,
-0x34420004, 0xaf820200, 0x24020002, 0x10c2003b,
-0x2cc20003, 0x10400005, 0x24020001, 0x10c2000a,
-0x3c03f0ff, 0x10000099, 0x0, 0x24020004,
-0x10c2005a, 0x24020008, 0x10c2006d, 0x3c02f0ff,
-0x10000092, 0x0, 0x8f820050, 0x3463ffff,
-0x3c05ffff, 0x3c040001, 0x8c843ee0, 0x431024,
-0x3c030700, 0x431025, 0xaf820050, 0x24020e00,
-0xaf860200, 0xaf860220, 0xaf820238, 0x8f820044,
-0x3c030001, 0x8c633d78, 0x34a53f7f, 0x451024,
-0x34630022, 0xaf820044, 0x24020004, 0xaf860238,
-0x1082000c, 0xaf830200, 0x3c020001, 0x8c423d9c,
-0x3c030001, 0x8c633d80, 0x3c040001, 0x8c843d7c,
-0x34428000, 0x621825, 0x641825, 0x1000006e,
-0x34620002, 0x3c020001, 0x8c423d80, 0x3c030001,
-0x8c633d9c, 0x3c040001, 0x8c843d7c, 0x431025,
-0x441025, 0x10000064, 0x34420002, 0x8f830050,
-0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c843ec8,
+0x3c020001, 0x8c426ec4, 0x10400064, 0x24020001,
+0x8f820220, 0x3c030008, 0x431024, 0x1040006a,
+0x3c020200, 0x10000078, 0x0, 0x8ee204b8,
+0x2443ffff, 0x2c620007, 0x104000cf, 0x31080,
+0x3c010001, 0x220821, 0x8c226bc8, 0x400008,
+0x0, 0xc003d87, 0x0, 0x3c010001,
+0xac206e1c, 0xaf800204, 0x3c010002, 0xc0043d3,
+0xac209060, 0x24020001, 0x3c010001, 0xac226e34,
+0x24020002, 0x100000bc, 0xaee204b8, 0xc004498,
+0x0, 0x3c030001, 0x8c636e34, 0x10000084,
+0x24020009, 0x3c020002, 0x8c429078, 0x30424000,
+0x10400003, 0x3c0200c8, 0x10000002, 0x344201f6,
+0x344201fe, 0xaf820238, 0x8f830054, 0x1000008b,
+0x24020004, 0x8f830054, 0x3c020001, 0x8c426fa0,
+0x2463d8f0, 0x431023, 0x2c422710, 0x144000a2,
+0x24020005, 0x10000079, 0x0, 0x8f820220,
+0x3c03f700, 0x431025, 0xaf820220, 0xaf800204,
+0x3c010002, 0x10000077, 0xac209060, 0x8f830054,
+0x3c020001, 0x8c426fa0, 0x2463fff6, 0x431023,
+0x2c42000a, 0x14400090, 0x24020007, 0x10000073,
+0x0, 0xc003f28, 0x0, 0x10400088,
+0x24020001, 0x8f820214, 0x3c03ffff, 0x3c040001,
+0x8c846f98, 0x431024, 0x3442251f, 0xaf820214,
+0x24020008, 0x1080000f, 0xaee204b8, 0x3c020001,
+0x8c426ec4, 0x1440000b, 0x0, 0x8f820220,
+0x34420002, 0xaf820220, 0x24020001, 0x3c010002,
+0xac229010, 0xc004ecc, 0x8f840220, 0x10000016,
+0x0, 0x8f820220, 0x3c030008, 0x431024,
+0x14400011, 0x3c020200, 0x282a025, 0x2402000e,
+0x3c010002, 0xac229010, 0xc00553d, 0x2021,
+0x8f820220, 0x34420002, 0xc003e45, 0xaf820220,
+0x3c050001, 0x8ca56e18, 0xc0052c7, 0x2021,
+0x1000005d, 0x0, 0x3c020001, 0x8c426ec4,
+0x10400059, 0x0, 0x3c020001, 0x8c426ec0,
+0x2442ffff, 0x3c010001, 0xac226ec0, 0x14400052,
+0x24020002, 0x3c010001, 0xac206ec4, 0x3c010001,
+0x1000004d, 0xac226ec0, 0x8ee204b8, 0x2443ffff,
+0x2c620007, 0x10400048, 0x31080, 0x3c010001,
+0x220821, 0x8c226be8, 0x400008, 0x0,
+0x3c020001, 0x8c426e24, 0x10400024, 0x24020007,
+0xc0043d3, 0x0, 0x24020002, 0xaee204b8,
+0x3c010001, 0x10000038, 0xac206e24, 0xc0048b3,
+0x0, 0x3c030001, 0x8c636e54, 0x24020006,
+0x14620031, 0x24020003, 0x1000002f, 0xaee204b8,
+0x3c050001, 0x8ca56e18, 0x3c060002, 0x8cc69078,
+0xc005134, 0x2021, 0x24020005, 0x10000026,
+0xaee204b8, 0x8f820220, 0x3c03f700, 0x431025,
+0xaf820220, 0x8f830054, 0x24020006, 0xaee204b8,
+0x3c010001, 0x1000001c, 0xac236fa0, 0x1000001a,
+0xaee204b8, 0x3c050001, 0x8ca56e18, 0xc0052c7,
+0x2021, 0xc00553d, 0x2021, 0x3c020002,
+0x8c429070, 0x441000e, 0x24020001, 0x8f820214,
+0x3c03ffff, 0x431024, 0x3442251f, 0xaf820214,
+0x24020008, 0xaee204b8, 0x8f820220, 0x34420002,
+0xc003e45, 0xaf820220, 0x10000003, 0x0,
+0x3c010001, 0xac226e1c, 0x8fbf001c, 0x8fb00018,
+0x3e00008, 0x27bd0020, 0x8f820200, 0x8f820220,
+0x8f820220, 0x34420004, 0xaf820220, 0x8f820200,
+0x3c050001, 0x8ca56e18, 0x34420004, 0xaf820200,
+0x24020002, 0x10a2004b, 0x2ca20003, 0x10400005,
+0x24020001, 0x10a2000a, 0x0, 0x100000b1,
+0x0, 0x24020004, 0x10a20072, 0x24020008,
+0x10a20085, 0x3c02f0ff, 0x100000aa, 0x0,
+0x8f830050, 0x3c02f0ff, 0x3442ffff, 0x3c040001,
+0x8c846fb8, 0x621824, 0x3c020700, 0x621825,
+0x24020e00, 0x2484fffb, 0x2c840002, 0xaf830050,
+0xaf850200, 0xaf850220, 0x14800006, 0xaf820238,
+0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024,
+0xaf820044, 0x3c030001, 0x8c636fb8, 0x24020005,
+0x14620004, 0x0, 0x8f820044, 0x34425000,
+0xaf820044, 0x3c020001, 0x8c426e08, 0x3c030001,
+0x8c636fb8, 0x34420022, 0x2463fffc, 0x2c630002,
+0x1460000c, 0xaf820200, 0x3c020001, 0x8c426e2c,
+0x3c030001, 0x8c636e10, 0x3c040001, 0x8c846e0c,
+0x34428000, 0x621825, 0x641825, 0x1000000a,
+0x34620002, 0x3c020001, 0x8c426e10, 0x3c030001,
+0x8c636e2c, 0x3c040001, 0x8c846e0c, 0x431025,
+0x441025, 0x34420002, 0xaf820220, 0x1000002f,
+0x24020001, 0x24020e01, 0xaf820238, 0x8f830050,
+0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c846f98,
0x621824, 0x3c020d00, 0x621825, 0x24020001,
-0xaf830050, 0xaf820200, 0xaf820220, 0x24020e00,
-0x10800009, 0xaf820238, 0x3c020001, 0x8c423e14,
-0x14400005, 0x3c033f00, 0x3c020001, 0x8c423d70,
-0x10000005, 0x34630070, 0x3c020001, 0x8c423d70,
-0x3c033f00, 0x34630072, 0x431025, 0xaf820200,
-0x3c030001, 0x8c633d74, 0x3c04f700, 0x3c020001,
-0x8c423d80, 0x3c050001, 0x8ca53d9c, 0x641825,
-0x431025, 0x1000003c, 0x451025, 0x8f830050,
-0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c843ec8,
-0x621824, 0x3c020a00, 0x621825, 0x24020001,
-0xaf830050, 0xaf820200, 0x1080001e, 0xaf820220,
-0x3c020001, 0x8c423e14, 0x1440001a, 0x3c033f00,
-0x3c020001, 0x8c423d70, 0x1000001a, 0x346300e0,
-0x8f830050, 0x3c040001, 0x8c843ec8, 0x3442ffff,
-0x621824, 0x1080000f, 0xaf830050, 0x3c020001,
-0x8c423e14, 0x1440000b, 0x3c043f00, 0x3c030001,
-0x8c633d70, 0x348400e0, 0x24020001, 0xaf820200,
-0xaf820220, 0x641825, 0xaf830200, 0x10000008,
-0x3c05f700, 0x3c020001, 0x8c423d70, 0x3c033f00,
-0x346300e2, 0x431025, 0xaf820200, 0x3c05f700,
-0x34a58000, 0x3c030001, 0x8c633d74, 0x3c020001,
-0x8c423d80, 0x3c040001, 0x8c843d9c, 0x651825,
-0x431025, 0x441025, 0xaf820220, 0x3e00008,
-0x0, 0x3c030001, 0x8c633da0, 0x3c020001,
-0x8c423da4, 0x10620003, 0x24020002, 0x3c010001,
-0xac233da4, 0x1062001d, 0x2c620003, 0x10400025,
-0x24020001, 0x14620023, 0x24020004, 0x3c030001,
-0x8c633d88, 0x10620006, 0x24020008, 0x1462000c,
-0x3c0200c8, 0x344201fb, 0x10000009, 0xaf820238,
-0x24020e01, 0xaf820238, 0x8f820044, 0x3c03ffff,
-0x34633f7f, 0x431024, 0x34420080, 0xaf820044,
-0x8f830054, 0x24020002, 0x3c010001, 0xac223da0,
-0x3c010001, 0x1000000b, 0xac233ed4, 0x8f830054,
-0x3c020001, 0x8c423ed4, 0x2463d8f0, 0x431023,
-0x2c422710, 0x14400003, 0x24020009, 0x3c010001,
-0xac223da0, 0x3e00008, 0x0, 0x27bdffd8,
+0xaf830050, 0xaf820200, 0xaf820220, 0x10800005,
+0x3c033f00, 0x3c020001, 0x8c426e00, 0x10000004,
+0x34630070, 0x3c020001, 0x8c426e00, 0x34630072,
+0x431025, 0xaf820200, 0x3c030001, 0x8c636e04,
+0x3c02f700, 0x621825, 0x3c020001, 0x8c426e10,
+0x3c040001, 0x8c846e2c, 0x3c050001, 0x8ca56fb8,
+0x431025, 0x441025, 0xaf820220, 0x24020005,
+0x14a20006, 0x24020001, 0x8f820044, 0x2403afff,
+0x431024, 0xaf820044, 0x24020001, 0x1000003d,
+0xaf820238, 0x8f830050, 0x3c02f0ff, 0x3442ffff,
+0x3c040001, 0x8c846f98, 0x621824, 0x3c020a00,
+0x621825, 0x24020001, 0xaf830050, 0xaf820200,
+0x1080001e, 0xaf820220, 0x3c020001, 0x8c426ec4,
+0x1440001a, 0x3c033f00, 0x3c020001, 0x8c426e00,
+0x1000001a, 0x346300e0, 0x8f830050, 0x3c040001,
+0x8c846f98, 0x3442ffff, 0x621824, 0x1080000f,
+0xaf830050, 0x3c020001, 0x8c426ec4, 0x1440000b,
+0x3c043f00, 0x3c030001, 0x8c636e00, 0x348400e0,
+0x24020001, 0xaf820200, 0xaf820220, 0x641825,
+0xaf830200, 0x10000008, 0x3c05f700, 0x3c020001,
+0x8c426e00, 0x3c033f00, 0x346300e2, 0x431025,
+0xaf820200, 0x3c05f700, 0x34a58000, 0x3c030001,
+0x8c636e04, 0x3c020001, 0x8c426e10, 0x3c040001,
+0x8c846e2c, 0x651825, 0x431025, 0x441025,
+0xaf820220, 0x3e00008, 0x0, 0x3c030001,
+0x8c636e34, 0x3c020001, 0x8c426e38, 0x10620003,
+0x24020002, 0x3c010001, 0xac236e38, 0x1062001d,
+0x2c620003, 0x10400025, 0x24020001, 0x14620023,
+0x24020004, 0x3c030001, 0x8c636e18, 0x10620006,
+0x24020008, 0x1462000c, 0x3c0200c8, 0x344201fb,
+0x10000009, 0xaf820238, 0x24020e01, 0xaf820238,
+0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024,
+0x34420080, 0xaf820044, 0x8f830054, 0x24020002,
+0x3c010001, 0xac226e34, 0x3c010001, 0x1000000b,
+0xac236fa4, 0x8f830054, 0x3c020001, 0x8c426fa4,
+0x2463d8f0, 0x431023, 0x2c422710, 0x14400003,
+0x24020009, 0x3c010001, 0xac226e34, 0x3e00008,
+0x0, 0x0, 0x0, 0x27bdffd8,
0xafb20018, 0x809021, 0xafb3001c, 0xa09821,
0xafb10014, 0xc08821, 0xafb00010, 0x8021,
-0xafbf0020, 0xa6200000, 0xc004523, 0x24040001,
+0xafbf0020, 0xa6200000, 0xc004dab, 0x24040001,
0x26100001, 0x2e020020, 0x1440fffb, 0x0,
-0xc004523, 0x2021, 0xc004523, 0x24040001,
-0xc004523, 0x24040001, 0xc004523, 0x2021,
+0xc004dab, 0x2021, 0xc004dab, 0x24040001,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
0x24100010, 0x2501024, 0x10400002, 0x2021,
-0x24040001, 0xc004523, 0x108042, 0x1600fffa,
+0x24040001, 0xc004dab, 0x108042, 0x1600fffa,
0x2501024, 0x24100010, 0x2701024, 0x10400002,
-0x2021, 0x24040001, 0xc004523, 0x108042,
-0x1600fffa, 0x2701024, 0xc004549, 0x34108000,
-0xc004549, 0x0, 0xc004503, 0x0,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fffa, 0x2701024, 0xc004dec, 0x34108000,
+0xc004dec, 0x0, 0xc004d8b, 0x0,
0x50400005, 0x108042, 0x96220000, 0x501025,
0xa6220000, 0x108042, 0x1600fff7, 0x0,
-0xc004549, 0x0, 0x8fbf0020, 0x8fb3001c,
+0xc004dec, 0x0, 0x8fbf0020, 0x8fb3001c,
0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
0x27bd0028, 0x27bdffd8, 0xafb10014, 0x808821,
0xafb20018, 0xa09021, 0xafb3001c, 0xc09821,
-0xafb00010, 0x8021, 0xafbf0020, 0xc004523,
+0xafb00010, 0x8021, 0xafbf0020, 0xc004dab,
0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004523, 0x2021, 0xc004523,
-0x24040001, 0xc004523, 0x2021, 0xc004523,
+0x0, 0xc004dab, 0x2021, 0xc004dab,
+0x24040001, 0xc004dab, 0x2021, 0xc004dab,
0x24040001, 0x24100010, 0x2301024, 0x10400002,
-0x2021, 0x24040001, 0xc004523, 0x108042,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
0x1600fffa, 0x2301024, 0x24100010, 0x2501024,
-0x10400002, 0x2021, 0x24040001, 0xc004523,
-0x108042, 0x1600fffa, 0x2501024, 0xc004523,
-0x24040001, 0xc004523, 0x2021, 0x34108000,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
+0x108042, 0x1600fffa, 0x2501024, 0xc004dab,
+0x24040001, 0xc004dab, 0x2021, 0x34108000,
0x96620000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004523, 0x108042, 0x1600fff8,
-0x0, 0xc004549, 0x0, 0x8fbf0020,
+0x24040001, 0xc004dab, 0x108042, 0x1600fff8,
+0x0, 0xc004dec, 0x0, 0x8fbf0020,
0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0028, 0x3c030001, 0x8c633db0,
-0x3c020001, 0x8c423df4, 0x27bdffd8, 0xafbf0020,
-0xafb1001c, 0x10620003, 0xafb00018, 0x3c010001,
-0xac233df4, 0x2463ffff, 0x2c620013, 0x10400349,
-0x31080, 0x3c010001, 0x220821, 0x8c223be0,
-0x400008, 0x0, 0xc004549, 0x8021,
-0x34028000, 0xa7a20010, 0x27b10010, 0xc004523,
+0x3e00008, 0x27bd0028, 0x3c040001, 0x8c846e50,
+0x3c020001, 0x8c426e98, 0x27bdffd8, 0xafbf0020,
+0xafb1001c, 0x10820003, 0xafb00018, 0x3c010001,
+0xac246e98, 0x3c030001, 0x8c636fb8, 0x24020005,
+0x14620005, 0x2483ffff, 0xc0048b3, 0x0,
+0x1000034c, 0x0, 0x2c620013, 0x10400349,
+0x31080, 0x3c010001, 0x220821, 0x8c226c10,
+0x400008, 0x0, 0xc004dec, 0x8021,
+0x34028000, 0xa7a20010, 0x27b10010, 0xc004dab,
0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004523, 0x2021, 0xc004523,
-0x24040001, 0xc004523, 0x2021, 0xc004523,
+0x0, 0xc004dab, 0x2021, 0xc004dab,
+0x24040001, 0xc004dab, 0x2021, 0xc004dab,
0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004523, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0xc004523,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0xc004dab,
0x2021, 0x108042, 0x1600fffc, 0x0,
-0xc004523, 0x24040001, 0xc004523, 0x2021,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004523, 0x108042,
-0x1600fff8, 0x0, 0xc004549, 0x0,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fff8, 0x0, 0xc004dec, 0x0,
0x1000030e, 0x24020002, 0x27b10010, 0xa7a00010,
-0x8021, 0xc004523, 0x24040001, 0x26100001,
-0x2e020020, 0x1440fffb, 0x0, 0xc004523,
-0x2021, 0xc004523, 0x24040001, 0xc004523,
-0x24040001, 0xc004523, 0x2021, 0x24100010,
+0x8021, 0xc004dab, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004dab,
+0x2021, 0xc004dab, 0x24040001, 0xc004dab,
+0x24040001, 0xc004dab, 0x2021, 0x24100010,
0x32020001, 0x10400002, 0x2021, 0x24040001,
-0xc004523, 0x108042, 0x1600fffa, 0x32020001,
-0x24100010, 0xc004523, 0x2021, 0x108042,
-0x1600fffc, 0x0, 0xc004549, 0x34108000,
-0xc004549, 0x0, 0xc004503, 0x0,
+0xc004dab, 0x108042, 0x1600fffa, 0x32020001,
+0x24100010, 0xc004dab, 0x2021, 0x108042,
+0x1600fffc, 0x0, 0xc004dec, 0x34108000,
+0xc004dec, 0x0, 0xc004d8b, 0x0,
0x50400005, 0x108042, 0x96220000, 0x501025,
0xa6220000, 0x108042, 0x1600fff7, 0x0,
-0xc004549, 0x0, 0x97a20010, 0x30428000,
+0xc004dec, 0x0, 0x97a20010, 0x30428000,
0x144002dc, 0x24020003, 0x100002d8, 0x0,
0x24021200, 0xa7a20010, 0x27b10010, 0x8021,
-0xc004523, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004523, 0x2021,
-0xc004523, 0x24040001, 0xc004523, 0x2021,
-0xc004523, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004523,
+0xc004dab, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0xc004523, 0x2021, 0x108042, 0x1600fffc,
-0x0, 0xc004523, 0x24040001, 0xc004523,
+0xc004dab, 0x2021, 0x108042, 0x1600fffc,
+0x0, 0xc004dab, 0x24040001, 0xc004dab,
0x2021, 0x34108000, 0x96220000, 0x501024,
-0x10400002, 0x2021, 0x24040001, 0xc004523,
-0x108042, 0x1600fff8, 0x0, 0xc004549,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
+0x108042, 0x1600fff8, 0x0, 0xc004dec,
0x0, 0x8f830054, 0x10000296, 0x24020004,
-0x8f830054, 0x3c020001, 0x8c423edc, 0x2463ff9c,
+0x8f830054, 0x3c020001, 0x8c426fb4, 0x2463ff9c,
0x431023, 0x2c420064, 0x1440029e, 0x24020002,
-0x3c030001, 0x8c633ee0, 0x10620297, 0x2c620003,
+0x3c030001, 0x8c636fb8, 0x10620297, 0x2c620003,
0x14400296, 0x24020011, 0x24020003, 0x10620005,
0x24020004, 0x10620291, 0x2402000f, 0x1000028f,
0x24020011, 0x1000028d, 0x24020005, 0x24020014,
-0xa7a20010, 0x27b10010, 0x8021, 0xc004523,
+0xa7a20010, 0x27b10010, 0x8021, 0xc004dab,
0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004523, 0x2021, 0xc004523,
-0x24040001, 0xc004523, 0x2021, 0xc004523,
+0x0, 0xc004dab, 0x2021, 0xc004dab,
+0x24040001, 0xc004dab, 0x2021, 0xc004dab,
0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004523, 0x108042,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
0x1600fffa, 0x32020001, 0x24100010, 0x32020012,
-0x10400002, 0x2021, 0x24040001, 0xc004523,
-0x108042, 0x1600fffa, 0x32020012, 0xc004523,
-0x24040001, 0xc004523, 0x2021, 0x34108000,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
+0x108042, 0x1600fffa, 0x32020012, 0xc004dab,
+0x24040001, 0xc004dab, 0x2021, 0x34108000,
0x96220000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004523, 0x108042, 0x1600fff8,
-0x0, 0xc004549, 0x0, 0x8f830054,
+0x24040001, 0xc004dab, 0x108042, 0x1600fff8,
+0x0, 0xc004dec, 0x0, 0x8f830054,
0x10000248, 0x24020006, 0x8f830054, 0x3c020001,
-0x8c423edc, 0x2463ff9c, 0x431023, 0x2c420064,
+0x8c426fb4, 0x2463ff9c, 0x431023, 0x2c420064,
0x14400250, 0x24020007, 0x1000024c, 0x0,
0x24020006, 0xa7a20010, 0x27b10010, 0x8021,
-0xc004523, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004523, 0x2021,
-0xc004523, 0x24040001, 0xc004523, 0x2021,
-0xc004523, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004523,
+0xc004dab, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
0x32020013, 0x10400002, 0x2021, 0x24040001,
-0xc004523, 0x108042, 0x1600fffa, 0x32020013,
-0xc004523, 0x24040001, 0xc004523, 0x2021,
+0xc004dab, 0x108042, 0x1600fffa, 0x32020013,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004523, 0x108042,
-0x1600fff8, 0x0, 0xc004549, 0x0,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fff8, 0x0, 0xc004dec, 0x0,
0x8f830054, 0x10000207, 0x24020008, 0x8f830054,
-0x3c020001, 0x8c423edc, 0x2463ff9c, 0x431023,
+0x3c020001, 0x8c426fb4, 0x2463ff9c, 0x431023,
0x2c420064, 0x1440020f, 0x24020009, 0x1000020b,
0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004523, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004523, 0x2021,
-0xc004523, 0x24040001, 0xc004523, 0x24040001,
-0xc004523, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004523,
+0xc004dab, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0xc004dab, 0x24040001,
+0xc004dab, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004523, 0x108042, 0x1600fffa, 0x32020018,
-0xc004549, 0x34108000, 0xc004549, 0x0,
-0xc004503, 0x0, 0x50400005, 0x108042,
+0xc004dab, 0x108042, 0x1600fffa, 0x32020018,
+0xc004dec, 0x34108000, 0xc004dec, 0x0,
+0xc004d8b, 0x0, 0x50400005, 0x108042,
0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004549, 0x8021,
+0x1600fff7, 0x0, 0xc004dec, 0x8021,
0x97a20010, 0x27b10010, 0x34420001, 0xa7a20010,
-0xc004523, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004523, 0x2021,
-0xc004523, 0x24040001, 0xc004523, 0x2021,
-0xc004523, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004523,
+0xc004dab, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004523, 0x108042, 0x1600fffa, 0x32020018,
-0xc004523, 0x24040001, 0xc004523, 0x2021,
+0xc004dab, 0x108042, 0x1600fffa, 0x32020018,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004523, 0x108042,
-0x1600fff8, 0x0, 0xc004549, 0x0,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fff8, 0x0, 0xc004dec, 0x0,
0x8f830054, 0x10000193, 0x2402000a, 0x8f830054,
-0x3c020001, 0x8c423edc, 0x2463ff9c, 0x431023,
+0x3c020001, 0x8c426fb4, 0x2463ff9c, 0x431023,
0x2c420064, 0x1440019b, 0x2402000b, 0x10000197,
0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004523, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004523, 0x2021,
-0xc004523, 0x24040001, 0xc004523, 0x24040001,
-0xc004523, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004523,
+0xc004dab, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0xc004dab, 0x24040001,
+0xc004dab, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
0x32020017, 0x10400002, 0x2021, 0x24040001,
-0xc004523, 0x108042, 0x1600fffa, 0x32020017,
-0xc004549, 0x34108000, 0xc004549, 0x0,
-0xc004503, 0x0, 0x50400005, 0x108042,
+0xc004dab, 0x108042, 0x1600fffa, 0x32020017,
+0xc004dec, 0x34108000, 0xc004dec, 0x0,
+0xc004d8b, 0x0, 0x50400005, 0x108042,
0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004549, 0x8021,
+0x1600fff7, 0x0, 0xc004dec, 0x8021,
0x97a20010, 0x27b10010, 0x34420700, 0xa7a20010,
-0xc004523, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004523, 0x2021,
-0xc004523, 0x24040001, 0xc004523, 0x2021,
-0xc004523, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004523,
+0xc004dab, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
0x32020017, 0x10400002, 0x2021, 0x24040001,
-0xc004523, 0x108042, 0x1600fffa, 0x32020017,
-0xc004523, 0x24040001, 0xc004523, 0x2021,
+0xc004dab, 0x108042, 0x1600fffa, 0x32020017,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004523, 0x108042,
-0x1600fff8, 0x0, 0xc004549, 0x0,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fff8, 0x0, 0xc004dec, 0x0,
0x8f830054, 0x1000011f, 0x2402000c, 0x8f830054,
-0x3c020001, 0x8c423edc, 0x2463ff9c, 0x431023,
+0x3c020001, 0x8c426fb4, 0x2463ff9c, 0x431023,
0x2c420064, 0x14400127, 0x24020012, 0x10000123,
0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004523, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004523, 0x2021,
-0xc004523, 0x24040001, 0xc004523, 0x24040001,
-0xc004523, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004523,
+0xc004dab, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0xc004dab, 0x24040001,
+0xc004dab, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
0x32020014, 0x10400002, 0x2021, 0x24040001,
-0xc004523, 0x108042, 0x1600fffa, 0x32020014,
-0xc004549, 0x34108000, 0xc004549, 0x0,
-0xc004503, 0x0, 0x50400005, 0x108042,
+0xc004dab, 0x108042, 0x1600fffa, 0x32020014,
+0xc004dec, 0x34108000, 0xc004dec, 0x0,
+0xc004d8b, 0x0, 0x50400005, 0x108042,
0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004549, 0x8021,
+0x1600fff7, 0x0, 0xc004dec, 0x8021,
0x97a20010, 0x27b10010, 0x34420010, 0xa7a20010,
-0xc004523, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004523, 0x2021,
-0xc004523, 0x24040001, 0xc004523, 0x2021,
-0xc004523, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004523,
+0xc004dab, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
0x32020014, 0x10400002, 0x2021, 0x24040001,
-0xc004523, 0x108042, 0x1600fffa, 0x32020014,
-0xc004523, 0x24040001, 0xc004523, 0x2021,
+0xc004dab, 0x108042, 0x1600fffa, 0x32020014,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004523, 0x108042,
-0x1600fff8, 0x0, 0xc004549, 0x0,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fff8, 0x0, 0xc004dec, 0x0,
0x8f830054, 0x100000ab, 0x24020013, 0x8f830054,
-0x3c020001, 0x8c423edc, 0x2463ff9c, 0x431023,
+0x3c020001, 0x8c426fb4, 0x2463ff9c, 0x431023,
0x2c420064, 0x144000b3, 0x2402000d, 0x100000af,
0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004523, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004523, 0x2021,
-0xc004523, 0x24040001, 0xc004523, 0x24040001,
-0xc004523, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004523,
+0xc004dab, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0xc004dab, 0x24040001,
+0xc004dab, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004523, 0x108042, 0x1600fffa, 0x32020018,
-0xc004549, 0x34108000, 0xc004549, 0x0,
-0xc004503, 0x0, 0x50400005, 0x108042,
+0xc004dab, 0x108042, 0x1600fffa, 0x32020018,
+0xc004dec, 0x34108000, 0xc004dec, 0x0,
+0xc004d8b, 0x0, 0x50400005, 0x108042,
0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004549, 0x8021,
+0x1600fff7, 0x0, 0xc004dec, 0x8021,
0x97a20010, 0x27b10010, 0x3042fffe, 0xa7a20010,
-0xc004523, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004523, 0x2021,
-0xc004523, 0x24040001, 0xc004523, 0x2021,
-0xc004523, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004523,
+0xc004dab, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
0x108042, 0x1600fffa, 0x32020001, 0x24100010,
0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004523, 0x108042, 0x1600fffa, 0x32020018,
-0xc004523, 0x24040001, 0xc004523, 0x2021,
+0xc004dab, 0x108042, 0x1600fffa, 0x32020018,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004523, 0x108042,
-0x1600fff8, 0x0, 0xc004549, 0x0,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fff8, 0x0, 0xc004dec, 0x0,
0x8f830054, 0x10000037, 0x2402000e, 0x24020840,
-0xa7a20010, 0x27b10010, 0x8021, 0xc004523,
+0xa7a20010, 0x27b10010, 0x8021, 0xc004dab,
0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004523, 0x2021, 0xc004523,
-0x24040001, 0xc004523, 0x2021, 0xc004523,
+0x0, 0xc004dab, 0x2021, 0xc004dab,
+0x24040001, 0xc004dab, 0x2021, 0xc004dab,
0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004523, 0x108042,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
0x1600fffa, 0x32020001, 0x24100010, 0x32020013,
-0x10400002, 0x2021, 0x24040001, 0xc004523,
-0x108042, 0x1600fffa, 0x32020013, 0xc004523,
-0x24040001, 0xc004523, 0x2021, 0x34108000,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
+0x108042, 0x1600fffa, 0x32020013, 0xc004dab,
+0x24040001, 0xc004dab, 0x2021, 0x34108000,
0x96220000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004523, 0x108042, 0x1600fff8,
-0x0, 0xc004549, 0x0, 0x8f830054,
-0x24020010, 0x3c010001, 0xac223db0, 0x3c010001,
-0x1000000c, 0xac233edc, 0x8f830054, 0x3c020001,
-0x8c423edc, 0x2463ff9c, 0x431023, 0x2c420064,
+0x24040001, 0xc004dab, 0x108042, 0x1600fff8,
+0x0, 0xc004dec, 0x0, 0x8f830054,
+0x24020010, 0x3c010001, 0xac226e50, 0x3c010001,
+0x1000000c, 0xac236fb4, 0x8f830054, 0x3c020001,
+0x8c426fb4, 0x2463ff9c, 0x431023, 0x2c420064,
0x14400004, 0x0, 0x24020011, 0x3c010001,
-0xac223db0, 0x8fbf0020, 0x8fb1001c, 0x8fb00018,
-0x3e00008, 0x27bd0028, 0x8f850044, 0x8f820044,
+0xac226e50, 0x8fbf0020, 0x8fb1001c, 0x8fb00018,
+0x3e00008, 0x27bd0028, 0x3c030001, 0x8c636e18,
+0x27bdffc8, 0x24020002, 0xafbf0034, 0xafb20030,
+0xafb1002c, 0x14620004, 0xafb00028, 0x3c120002,
+0x10000003, 0x8e529078, 0x3c120002, 0x8e52907c,
+0x3c030001, 0x8c636e54, 0x3c020001, 0x8c426e9c,
+0x50620004, 0x2463ffff, 0x3c010001, 0xac236e9c,
+0x2463ffff, 0x2c620006, 0x104004b9, 0x31080,
+0x3c010001, 0x220821, 0x8c226c68, 0x400008,
+0x0, 0x2021, 0x2821, 0xc004e0e,
+0x34068000, 0x24040010, 0x24050002, 0x24060002,
+0x24020002, 0xc004e0e, 0xa7a20018, 0x24020002,
+0x3c010001, 0x100004a6, 0xac226e54, 0x27b10018,
+0xa7a00018, 0x8021, 0xc004dab, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004dab, 0x2021, 0xc004dab, 0x24040001,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
+0x24100010, 0x32020001, 0x10400002, 0x2021,
+0x24040001, 0xc004dab, 0x108042, 0x1600fffa,
+0x32020001, 0x24100010, 0xc004dab, 0x2021,
+0x108042, 0x1600fffc, 0x0, 0xc004dec,
+0x34108000, 0xc004dec, 0x0, 0xc004d8b,
+0x0, 0x50400005, 0x108042, 0x96220000,
+0x501025, 0xa6220000, 0x108042, 0x1600fff7,
+0x0, 0xc004dec, 0x0, 0x97a20018,
+0x30428000, 0x14400004, 0x24020003, 0x3c010001,
+0xac226e54, 0x24020003, 0x3c010001, 0x1000046c,
+0xac226e54, 0x24040010, 0x24050002, 0x24060002,
+0x24020002, 0xc004e0e, 0xa7a20018, 0x3c030001,
+0x8c636ea0, 0x24020001, 0x146201e2, 0x0,
+0x27b10018, 0xa7a00018, 0x8021, 0xc004dab,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004dab, 0x2021, 0xc004dab,
+0x24040001, 0xc004dab, 0x24040001, 0xc004dab,
+0x2021, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x32020018,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
+0x108042, 0x1600fffa, 0x32020018, 0xc004dec,
+0x34108000, 0xc004dec, 0x0, 0xc004d8b,
+0x0, 0x50400005, 0x108042, 0x96220000,
+0x501025, 0xa6220000, 0x108042, 0x1600fff7,
+0x0, 0xc004dec, 0x8021, 0x27b10018,
+0xa7a00018, 0xc004dab, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004dab,
+0x2021, 0xc004dab, 0x24040001, 0xc004dab,
+0x24040001, 0xc004dab, 0x2021, 0x24100010,
+0x32020001, 0x10400002, 0x2021, 0x24040001,
+0xc004dab, 0x108042, 0x1600fffa, 0x32020001,
+0x24100010, 0x32020018, 0x10400002, 0x2021,
+0x24040001, 0xc004dab, 0x108042, 0x1600fffa,
+0x32020018, 0xc004dec, 0x34108000, 0xc004dec,
+0x0, 0xc004d8b, 0x0, 0x50400005,
+0x108042, 0x96220000, 0x501025, 0xa6220000,
+0x108042, 0x1600fff7, 0x0, 0xc004dec,
+0x8021, 0x24040018, 0x2821, 0xc004e0e,
+0x24060404, 0xa7a0001a, 0xc004dab, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004dab, 0x2021, 0xc004dab, 0x24040001,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
+0x24100010, 0x32020001, 0x10400002, 0x2021,
+0x24040001, 0xc004dab, 0x108042, 0x1600fffa,
+0x32020001, 0x24100010, 0x32020018, 0x10400002,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fffa, 0x32020018, 0xc004dec, 0x34108000,
+0xc004dec, 0x0, 0xc004d8b, 0x0,
+0x50400005, 0x108042, 0x97a2001a, 0x501025,
+0xa7a2001a, 0x108042, 0x1600fff7, 0x0,
+0xc004dec, 0x8021, 0xa7a0001a, 0xc004dab,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004dab, 0x2021, 0xc004dab,
+0x24040001, 0xc004dab, 0x24040001, 0xc004dab,
+0x2021, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x32020018,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
+0x108042, 0x1600fffa, 0x32020018, 0xc004dec,
+0x34108000, 0xc004dec, 0x0, 0xc004d8b,
+0x0, 0x50400005, 0x108042, 0x97a2001a,
+0x501025, 0xa7a2001a, 0x108042, 0x1600fff7,
+0x0, 0xc004dec, 0x8021, 0xa7a0001c,
+0xc004dab, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0xc004dab, 0x24040001,
+0xc004dab, 0x2021, 0x24100010, 0xc004dab,
+0x2021, 0x108042, 0x1600fffc, 0x0,
+0x24100010, 0x3202001e, 0x10400002, 0x2021,
+0x24040001, 0xc004dab, 0x108042, 0x1600fffa,
+0x3202001e, 0xc004dec, 0x34108000, 0xc004dec,
+0x0, 0xc004d8b, 0x0, 0x50400005,
+0x108042, 0x97a2001c, 0x501025, 0xa7a2001c,
+0x108042, 0x1600fff7, 0x0, 0xc004dec,
+0x8021, 0xa7a0001c, 0xc004dab, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004dab, 0x2021, 0xc004dab, 0x24040001,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
+0x24100010, 0xc004dab, 0x2021, 0x108042,
+0x1600fffc, 0x0, 0x24100010, 0x3202001e,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
+0x108042, 0x1600fffa, 0x3202001e, 0xc004dec,
+0x34108000, 0xc004dec, 0x0, 0xc004d8b,
+0x0, 0x50400005, 0x108042, 0x97a2001c,
+0x501025, 0xa7a2001c, 0x108042, 0x1600fff7,
+0x0, 0xc004dec, 0x8021, 0x24020002,
+0xa7a2001e, 0xc004dab, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004dab,
+0x2021, 0xc004dab, 0x24040001, 0xc004dab,
+0x2021, 0xc004dab, 0x24040001, 0x24100010,
+0xc004dab, 0x2021, 0x108042, 0x1600fffc,
+0x0, 0x24100010, 0x3202001e, 0x10400002,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fffa, 0x3202001e, 0xc004dab, 0x24040001,
+0xc004dab, 0x2021, 0x34108000, 0x97a2001e,
+0x501024, 0x10400002, 0x2021, 0x24040001,
+0xc004dab, 0x108042, 0x1600fff8, 0x0,
+0xc004dec, 0x8021, 0xa7a00020, 0xc004dab,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004dab, 0x2021, 0xc004dab,
+0x24040001, 0xc004dab, 0x24040001, 0xc004dab,
+0x2021, 0x24100010, 0xc004dab, 0x2021,
+0x108042, 0x1600fffc, 0x0, 0x24100010,
+0x3202001e, 0x10400002, 0x2021, 0x24040001,
+0xc004dab, 0x108042, 0x1600fffa, 0x3202001e,
+0xc004dec, 0x34108000, 0xc004dec, 0x0,
+0xc004d8b, 0x0, 0x50400005, 0x108042,
+0x97a20020, 0x501025, 0xa7a20020, 0x108042,
+0x1600fff7, 0x0, 0xc004dec, 0x8021,
+0xa7a00020, 0xc004dab, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004dab,
+0x2021, 0xc004dab, 0x24040001, 0xc004dab,
+0x24040001, 0xc004dab, 0x2021, 0x24100010,
+0xc004dab, 0x2021, 0x108042, 0x1600fffc,
+0x0, 0x24100010, 0x3202001e, 0x10400002,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fffa, 0x3202001e, 0xc004dec, 0x34108000,
+0xc004dec, 0x0, 0xc004d8b, 0x0,
+0x50400005, 0x108042, 0x97a20020, 0x501025,
+0xa7a20020, 0x108042, 0x1600fff7, 0x0,
+0xc004dec, 0x8021, 0xa7a00022, 0xc004dab,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004dab, 0x2021, 0xc004dab,
+0x24040001, 0xc004dab, 0x2021, 0xc004dab,
+0x24040001, 0x24100010, 0xc004dab, 0x2021,
+0x108042, 0x1600fffc, 0x0, 0x24100010,
+0xc004dab, 0x2021, 0x108042, 0x1600fffc,
+0x0, 0xc004dab, 0x24040001, 0xc004dab,
+0x2021, 0x34108000, 0x97a20022, 0x501024,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
+0x108042, 0x1600fff8, 0x0, 0xc004dec,
+0x0, 0x24040018, 0x24050002, 0xc004e0e,
+0x24060004, 0x3c030001, 0x8c636ea4, 0x24020001,
+0x146200fc, 0x3c024000, 0x3c010001, 0xac206ea4,
+0x2421024, 0x10400276, 0x3c022000, 0x2421024,
+0x10400004, 0x0, 0x3c010001, 0x10000003,
+0xac236f98, 0x3c010001, 0xac206f98, 0x3c030001,
+0x8c636fac, 0x24020005, 0x146200ea, 0x0,
+0x3c020001, 0x8c426f98, 0x1040005f, 0x3c020004,
+0x2421024, 0x10400011, 0xa7a00018, 0x3c020008,
+0x2421024, 0x10400002, 0x24020200, 0xa7a20018,
+0x3c020010, 0x2421024, 0x10400004, 0x0,
+0x97a20018, 0x34420100, 0xa7a20018, 0x97a60018,
+0x24040009, 0x10000004, 0x2821, 0x24040009,
+0x2821, 0x3021, 0xc004e0e, 0x0,
+0x24020001, 0xa7a2001a, 0x3c020008, 0x2421024,
+0x1040000c, 0x3c020002, 0x2421024, 0x10400002,
+0x24020101, 0xa7a2001a, 0x3c020001, 0x2421024,
+0x10400005, 0x3c020010, 0x97a2001a, 0x34420040,
+0xa7a2001a, 0x3c020010, 0x2421024, 0x1040000e,
+0x3c020002, 0x2421024, 0x10400005, 0x3c020001,
+0x97a2001a, 0x34420080, 0xa7a2001a, 0x3c020001,
+0x2421024, 0x10400005, 0x3c0300a0, 0x97a2001a,
+0x34420020, 0xa7a2001a, 0x3c0300a0, 0x2431024,
+0x54430004, 0x3c020020, 0x97a2001a, 0x1000000c,
+0x34420400, 0x2421024, 0x50400004, 0x3c020080,
+0x97a2001a, 0x10000006, 0x34420800, 0x2421024,
+0x10400004, 0x0, 0x97a2001a, 0x34420c00,
+0xa7a2001a, 0x97a6001a, 0x24040004, 0xc004e0e,
+0x2821, 0x32424000, 0x10400003, 0xa7a0001c,
+0x24024000, 0xa7a2001c, 0x97a6001c, 0x2021,
+0x2821, 0x34c61200, 0xc004e0e, 0xa7a6001c,
+0x10000088, 0x0, 0x32424000, 0x10400003,
+0xa7a00018, 0x24024000, 0xa7a20018, 0x3c020010,
+0x2421024, 0x10400004, 0x0, 0x97a20018,
+0x10000004, 0xa7a20018, 0x97a20018, 0x34420100,
+0xa7a20018, 0x3c020001, 0x2421024, 0x10400004,
+0x0, 0x97a20018, 0x10000004, 0xa7a20018,
+0x97a20018, 0x34422000, 0xa7a20018, 0x2021,
+0x97a60018, 0x2821, 0xc004e0e, 0x8021,
+0xa7a0001a, 0xc004dab, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004dab,
+0x2021, 0xc004dab, 0x24040001, 0xc004dab,
+0x24040001, 0xc004dab, 0x2021, 0x24100010,
+0x32020001, 0x10400002, 0x2021, 0x24040001,
+0xc004dab, 0x108042, 0x1600fffa, 0x32020001,
+0x24100010, 0xc004dab, 0x2021, 0x108042,
+0x1600fffc, 0x0, 0xc004dec, 0x34108000,
+0xc004dec, 0x0, 0xc004d8b, 0x0,
+0x50400005, 0x108042, 0x97a2001a, 0x501025,
+0xa7a2001a, 0x108042, 0x1600fff7, 0x0,
+0xc004dec, 0x8021, 0xa7a0001a, 0xc004dab,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004dab, 0x2021, 0xc004dab,
+0x24040001, 0xc004dab, 0x24040001, 0xc004dab,
+0x2021, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0xc004dab,
+0x2021, 0x108042, 0x1600fffc, 0x0,
+0xc004dec, 0x34108000, 0xc004dec, 0x0,
+0xc004d8b, 0x0, 0x50400005, 0x108042,
+0x97a2001a, 0x501025, 0xa7a2001a, 0x108042,
+0x1600fff7, 0x0, 0xc004dec, 0x0,
+0x3c040001, 0x24846c5c, 0x97a60018, 0x97a7001a,
+0x3c020001, 0x8c426e18, 0x3c030001, 0x8c636f98,
+0x3c05000d, 0x34a50205, 0xafa20010, 0xc002b17,
+0xafa30014, 0x8f830054, 0x24020004, 0x3c010001,
+0xac226e54, 0x3c010001, 0x10000179, 0xac236fb0,
+0x8f830054, 0x3c020001, 0x8c426fb0, 0x2463ff9c,
+0x431023, 0x2c420064, 0x14400009, 0x27b10018,
+0x8f820220, 0x24030005, 0x3c010001, 0xac236e54,
+0x3c03f700, 0x431025, 0xaf820220, 0x27b10018,
+0xa7a00018, 0x8021, 0xc004dab, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004dab, 0x2021, 0xc004dab, 0x24040001,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
+0x24100010, 0x32020001, 0x10400002, 0x2021,
+0x24040001, 0xc004dab, 0x108042, 0x1600fffa,
+0x32020001, 0x24100010, 0xc004dab, 0x2021,
+0x108042, 0x1600fffc, 0x0, 0xc004dec,
+0x34108000, 0xc004dec, 0x0, 0xc004d8b,
+0x0, 0x50400005, 0x108042, 0x96220000,
+0x501025, 0xa6220000, 0x108042, 0x1600fff7,
+0x0, 0xc004dec, 0x8021, 0xa7a0001a,
+0xc004dab, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0xc004dab, 0x24040001,
+0xc004dab, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020001, 0x10400002, 0x2021, 0x24040001,
+0xc004dab, 0x108042, 0x1600fffa, 0x32020001,
+0xc004dec, 0x34108000, 0xc004dec, 0x0,
+0xc004d8b, 0x0, 0x50400005, 0x108042,
+0x97a2001a, 0x501025, 0xa7a2001a, 0x108042,
+0x1600fff7, 0x0, 0xc004dec, 0x8021,
+0xa7a0001a, 0xc004dab, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004dab,
+0x2021, 0xc004dab, 0x24040001, 0xc004dab,
+0x24040001, 0xc004dab, 0x2021, 0x24100010,
+0x32020001, 0x10400002, 0x2021, 0x24040001,
+0xc004dab, 0x108042, 0x1600fffa, 0x32020001,
+0x24100010, 0x32020001, 0x10400002, 0x2021,
+0x24040001, 0xc004dab, 0x108042, 0x1600fffa,
+0x32020001, 0xc004dec, 0x34108000, 0xc004dec,
+0x0, 0xc004d8b, 0x0, 0x50400005,
+0x108042, 0x97a2001a, 0x501025, 0xa7a2001a,
+0x108042, 0x1600fff7, 0x0, 0xc004dec,
+0x8021, 0xa7a0001c, 0xc004dab, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004dab, 0x2021, 0xc004dab, 0x24040001,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
+0x24100010, 0x32020001, 0x10400002, 0x2021,
+0x24040001, 0xc004dab, 0x108042, 0x1600fffa,
+0x32020001, 0x24100010, 0x32020004, 0x10400002,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fffa, 0x32020004, 0xc004dec, 0x34108000,
+0xc004dec, 0x0, 0xc004d8b, 0x0,
+0x50400005, 0x108042, 0x97a2001c, 0x501025,
+0xa7a2001c, 0x108042, 0x1600fff7, 0x0,
+0xc004dec, 0x8021, 0xa7a0001c, 0xc004dab,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004dab, 0x2021, 0xc004dab,
+0x24040001, 0xc004dab, 0x24040001, 0xc004dab,
+0x2021, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x32020004,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
+0x108042, 0x1600fffa, 0x32020004, 0xc004dec,
+0x34108000, 0xc004dec, 0x0, 0xc004d8b,
+0x0, 0x50400005, 0x108042, 0x97a2001c,
+0x501025, 0xa7a2001c, 0x108042, 0x1600fff7,
+0x0, 0xc004dec, 0x8021, 0xa7a00020,
+0xc004dab, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004dab, 0x2021,
+0xc004dab, 0x24040001, 0xc004dab, 0x24040001,
+0xc004dab, 0x2021, 0x24100010, 0x32020001,
+0x10400002, 0x2021, 0x24040001, 0xc004dab,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020019, 0x10400002, 0x2021, 0x24040001,
+0xc004dab, 0x108042, 0x1600fffa, 0x32020019,
+0xc004dec, 0x34108000, 0xc004dec, 0x0,
+0xc004d8b, 0x0, 0x50400005, 0x108042,
+0x97a20020, 0x501025, 0xa7a20020, 0x108042,
+0x1600fff7, 0x0, 0xc004dec, 0x8021,
+0xa7a00020, 0xc004dab, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004dab,
+0x2021, 0xc004dab, 0x24040001, 0xc004dab,
+0x24040001, 0xc004dab, 0x2021, 0x24100010,
+0x32020001, 0x10400002, 0x2021, 0x24040001,
+0xc004dab, 0x108042, 0x1600fffa, 0x32020001,
+0x24100010, 0x32020019, 0x10400002, 0x2021,
+0x24040001, 0xc004dab, 0x108042, 0x1600fffa,
+0x32020019, 0xc004dec, 0x34108000, 0xc004dec,
+0x0, 0xc004d8b, 0x0, 0x50400005,
+0x108042, 0x97a20020, 0x501025, 0xa7a20020,
+0x108042, 0x1600fff7, 0x0, 0xc004dec,
+0x0, 0x97a60018, 0x97a7001a, 0x97a2001c,
+0x3c040001, 0x24846c5c, 0xafa20010, 0x97a20020,
+0x3c05000d, 0x34a50204, 0xc002b17, 0xafa20014,
+0x10000007, 0x0, 0x24020006, 0x3c010001,
+0xac226e54, 0x24020011, 0x3c010001, 0xac226e50,
+0x8fbf0034, 0x8fb20030, 0x8fb1002c, 0x8fb00028,
+0x3e00008, 0x27bd0038, 0x8f850044, 0x8f820044,
0x3c030001, 0x431025, 0x3c030008, 0xaf820044,
0x8f840054, 0x8f820054, 0xa32824, 0x10000002,
0x24840001, 0x8f820054, 0x821023, 0x2c420002,
@@ -7883,153 +8567,207 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x3e00008, 0xa01021, 0x8f830044, 0x3c02fff0,
0x3442ffff, 0x42480, 0x621824, 0x3c020002,
0x822025, 0x641825, 0xaf830044, 0x8f820044,
-0x3c030001, 0x431025, 0xaf820044, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
-0x621023, 0x2c420002, 0x1440fffc, 0x0,
-0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024,
+0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
+0x0, 0x8f820044, 0x3c030001, 0x431025,
0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
0x24630001, 0x8f820054, 0x621023, 0x2c420002,
0x1440fffc, 0x0, 0x3e00008, 0x0,
-0x8f820044, 0x3c03fff0, 0x3463ffff, 0x431024,
-0xaf820044, 0x8f820044, 0x3c030001, 0x431025,
-0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
-0x24630001, 0x8f820054, 0x621023, 0x2c420002,
-0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe,
-0x3463ffff, 0x431024, 0xaf820044, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
-0x621023, 0x2c420002, 0x1440fffc, 0x0,
-0x3e00008, 0x0, 0x0, 0x27bdffe8,
+0x8f820044, 0x2403ff7f, 0x431024, 0xaf820044,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
+0x0, 0x8f820044, 0x34420080, 0xaf820044,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
+0x0, 0x3e00008, 0x0, 0x8f820044,
+0x3c03fff0, 0x3463ffff, 0x431024, 0xaf820044,
+0x8f820044, 0x3c030001, 0x431025, 0xaf820044,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
+0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff,
+0x431024, 0xaf820044, 0x8f830054, 0x8f820054,
+0x10000002, 0x24630001, 0x8f820054, 0x621023,
+0x2c420002, 0x1440fffc, 0x0, 0x3e00008,
+0x0, 0x27bdffc8, 0xafb30024, 0x809821,
+0xafbe002c, 0xa0f021, 0xafb20020, 0xc09021,
+0x33c2ffff, 0xafbf0030, 0xafb50028, 0xafb1001c,
+0xafb00018, 0x14400034, 0xa7b20010, 0x3271ffff,
+0x27b20010, 0x8021, 0xc004dab, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004dab, 0x2021, 0xc004dab, 0x24040001,
+0xc004dab, 0x2021, 0xc004dab, 0x24040001,
+0x24100010, 0x32020001, 0x10400002, 0x2021,
+0x24040001, 0xc004dab, 0x108042, 0x1600fffa,
+0x32020001, 0x24100010, 0x2301024, 0x10400002,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fffa, 0x2301024, 0xc004dab, 0x24040001,
+0xc004dab, 0x2021, 0x34108000, 0x96420000,
+0x501024, 0x10400002, 0x2021, 0x24040001,
+0xc004dab, 0x108042, 0x12000075, 0x0,
+0x1000fff6, 0x0, 0x3275ffff, 0x27b10010,
+0xa7a00010, 0x8021, 0xc004dab, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004dab, 0x2021, 0xc004dab, 0x24040001,
+0xc004dab, 0x24040001, 0xc004dab, 0x2021,
+0x24100010, 0x32020001, 0x10400002, 0x2021,
+0x24040001, 0xc004dab, 0x108042, 0x1600fffa,
+0x32020001, 0x24100010, 0x2b01024, 0x10400002,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fffa, 0x2b01024, 0xc004dec, 0x34108000,
+0xc004dec, 0x0, 0xc004d8b, 0x0,
+0x50400005, 0x108042, 0x96220000, 0x501025,
+0xa6220000, 0x108042, 0x1600fff7, 0x0,
+0xc004dec, 0x0, 0x33c5ffff, 0x24020001,
+0x54a20004, 0x24020002, 0x97a20010, 0x10000006,
+0x521025, 0x14a20006, 0x3271ffff, 0x97a20010,
+0x121827, 0x431024, 0xa7a20010, 0x3271ffff,
+0x27b20010, 0x8021, 0xc004dab, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004dab, 0x2021, 0xc004dab, 0x24040001,
+0xc004dab, 0x2021, 0xc004dab, 0x24040001,
+0x24100010, 0x32020001, 0x10400002, 0x2021,
+0x24040001, 0xc004dab, 0x108042, 0x1600fffa,
+0x32020001, 0x24100010, 0x2301024, 0x10400002,
+0x2021, 0x24040001, 0xc004dab, 0x108042,
+0x1600fffa, 0x2301024, 0xc004dab, 0x24040001,
+0xc004dab, 0x2021, 0x34108000, 0x96420000,
+0x501024, 0x10400002, 0x2021, 0x24040001,
+0xc004dab, 0x108042, 0x1600fff8, 0x0,
+0xc004dec, 0x0, 0x8fbf0030, 0x8fbe002c,
+0x8fb50028, 0x8fb30024, 0x8fb20020, 0x8fb1001c,
+0x8fb00018, 0x3e00008, 0x27bd0038, 0x27bdffe8,
0xafbf0010, 0x8ee304b8, 0x24020008, 0x146201e0,
-0x0, 0x3c020001, 0x8c423ec8, 0x14400005,
-0x0, 0xc003b0b, 0x8f840224, 0x100001d8,
+0x0, 0x3c020001, 0x8c426f98, 0x14400005,
+0x0, 0xc003d87, 0x8f840224, 0x100001d8,
0x0, 0x8f820220, 0x3c030008, 0x431024,
0x10400026, 0x24020001, 0x8f840224, 0x8f820220,
0x3c030400, 0x431024, 0x10400006, 0x0,
-0x3c010001, 0xac205f40, 0x3c010001, 0x1000000b,
-0xac205f60, 0x3c030001, 0x24635f40, 0x8c620000,
+0x3c010002, 0xac209020, 0x3c010002, 0x1000000b,
+0xac209040, 0x3c030002, 0x24639020, 0x8c620000,
0x24420001, 0xac620000, 0x2c420002, 0x14400003,
-0x24020001, 0x3c010001, 0xac225f60, 0x3c020001,
-0x8c425f60, 0x10400006, 0x30820040, 0x10400004,
-0x24020001, 0x3c010001, 0x10000003, 0xac225f64,
-0x3c010001, 0xac205f64, 0x3c010001, 0xac245f3c,
-0x3c010001, 0x1000000b, 0xac205f70, 0x3c010001,
-0xac225f70, 0x3c010001, 0xac205f60, 0x3c010001,
-0xac205f40, 0x3c010001, 0xac205f64, 0x3c010001,
-0xac205f3c, 0x3c030001, 0x8c635f30, 0x3c020001,
-0x8c425f34, 0x50620004, 0x2463ffff, 0x3c010001,
-0xac235f34, 0x2463ffff, 0x2c62000e, 0x10400194,
-0x31080, 0x3c010001, 0x220821, 0x8c223c30,
-0x400008, 0x0, 0x24020002, 0x3c010001,
-0xac205f60, 0x3c010001, 0xac205f40, 0x3c010001,
-0xac205f3c, 0x3c010001, 0xac205f64, 0x3c010001,
-0xac205f58, 0x3c010001, 0xac205f50, 0xaf800224,
-0x3c010001, 0xac225f30, 0x3c020001, 0x8c425f70,
-0x1440004f, 0x3c02fdff, 0x3442ffff, 0xc003b0b,
+0x24020001, 0x3c010002, 0xac229040, 0x3c020002,
+0x8c429040, 0x10400006, 0x30820040, 0x10400004,
+0x24020001, 0x3c010002, 0x10000003, 0xac229044,
+0x3c010002, 0xac209044, 0x3c010002, 0xac24901c,
+0x3c010002, 0x1000000b, 0xac209050, 0x3c010002,
+0xac229050, 0x3c010002, 0xac209040, 0x3c010002,
+0xac209020, 0x3c010002, 0xac209044, 0x3c010002,
+0xac20901c, 0x3c030002, 0x8c639010, 0x3c020002,
+0x8c429014, 0x50620004, 0x2463ffff, 0x3c010002,
+0xac239014, 0x2463ffff, 0x2c62000e, 0x10400194,
+0x31080, 0x3c010001, 0x220821, 0x8c226c80,
+0x400008, 0x0, 0x24020002, 0x3c010002,
+0xac209040, 0x3c010002, 0xac209020, 0x3c010002,
+0xac20901c, 0x3c010002, 0xac209044, 0x3c010002,
+0xac209038, 0x3c010002, 0xac209030, 0xaf800224,
+0x3c010002, 0xac229010, 0x3c020002, 0x8c429050,
+0x1440004f, 0x3c02fdff, 0x3442ffff, 0xc003d87,
0x282a024, 0xaf800204, 0x8f820200, 0x2403fffd,
-0x431024, 0xaf820200, 0x3c010001, 0xac205f80,
-0x8f830054, 0x3c020001, 0x8c425f58, 0x24040001,
-0x3c010001, 0xac245f6c, 0x24420001, 0x3c010001,
-0xac225f58, 0x2c420004, 0x3c010001, 0xac235f54,
-0x14400006, 0x24020003, 0x3c010001, 0xac243d8c,
-0x3c010001, 0x1000015e, 0xac205f58, 0x3c010001,
-0x1000015b, 0xac225f30, 0x8f830054, 0x3c020001,
-0x8c425f54, 0x2463d8f0, 0x431023, 0x2c422710,
-0x14400003, 0x24020004, 0x3c010001, 0xac225f30,
-0x3c020001, 0x8c425f70, 0x14400021, 0x3c02fdff,
+0x431024, 0xaf820200, 0x3c010002, 0xac209060,
+0x8f830054, 0x3c020002, 0x8c429038, 0x24040001,
+0x3c010002, 0xac24904c, 0x24420001, 0x3c010002,
+0xac229038, 0x2c420004, 0x3c010002, 0xac239034,
+0x14400006, 0x24020003, 0x3c010001, 0xac246e1c,
+0x3c010002, 0x1000015e, 0xac209038, 0x3c010002,
+0x1000015b, 0xac229010, 0x8f830054, 0x3c020002,
+0x8c429034, 0x2463d8f0, 0x431023, 0x2c422710,
+0x14400003, 0x24020004, 0x3c010002, 0xac229010,
+0x3c020002, 0x8c429050, 0x14400021, 0x3c02fdff,
0x3442ffff, 0x1000014a, 0x282a024, 0x3c040001,
-0x8c843ecc, 0x3c010001, 0xc004754, 0xac205f48,
-0x3c020001, 0x8c425f7c, 0xaf820204, 0x3c020001,
-0x8c425f70, 0x14400012, 0x3c03fdff, 0x8f820204,
+0x8c846f9c, 0x3c010002, 0xc0050b4, 0xac209028,
+0x3c020002, 0x8c42905c, 0xaf820204, 0x3c020002,
+0x8c429050, 0x14400012, 0x3c03fdff, 0x8f820204,
0x3463ffff, 0x30420030, 0x1440012f, 0x283a024,
-0x3c030001, 0x8c635f7c, 0x24020005, 0x3c010001,
-0xac225f30, 0x3c010001, 0x10000131, 0xac235f80,
-0x3c020001, 0x8c425f70, 0x10400010, 0x3c02fdff,
-0x3c020001, 0x8c423e0c, 0x24420001, 0x3c010001,
-0xac223e0c, 0x2c420002, 0x14400125, 0x24020001,
-0x3c010001, 0xac223e14, 0x3c010001, 0xac203e0c,
-0x3c010001, 0x1000011e, 0xac223d8c, 0x3c030001,
-0x8c635f60, 0x3442ffff, 0x10600119, 0x282a024,
-0x3c020001, 0x8c425f3c, 0x10400115, 0x0,
-0x3c010001, 0xac225f68, 0x24020003, 0x3c010001,
-0xac225f40, 0x100000b8, 0x24020006, 0x3c010001,
-0xac205f48, 0x8f820204, 0x34420040, 0xaf820204,
-0x3c020001, 0x8c425f80, 0x24030007, 0x3c010001,
-0xac235f30, 0x34420040, 0x3c010001, 0xac225f80,
-0x3c020001, 0x8c425f60, 0x10400005, 0x0,
-0x3c020001, 0x8c425f3c, 0x104000f0, 0x24020002,
-0x3c050001, 0x24a55f40, 0x8ca20000, 0x2c424e21,
-0x104000ea, 0x24020002, 0x3c020001, 0x8c425f64,
-0x104000ef, 0x2404ffbf, 0x3c020001, 0x8c425f3c,
-0x3c030001, 0x8c635f68, 0x441024, 0x641824,
-0x10430004, 0x24020001, 0x3c010001, 0x100000e4,
-0xac225f30, 0x24020003, 0xaca20000, 0x24020008,
-0x3c010001, 0xac225f30, 0x3c020001, 0x8c425f6c,
-0x1040000c, 0x24020001, 0x3c040001, 0xc004761,
-0x8c845f3c, 0x3c020001, 0x8c425f88, 0x14400005,
-0x24020001, 0x3c020001, 0x8c425f84, 0x10400006,
-0x24020001, 0x3c010001, 0xac223d8c, 0x3c010001,
-0x100000cb, 0xac205f58, 0x3c020001, 0x8c425f50,
-0x3c030001, 0x8c635f3c, 0x2c420001, 0x210c0,
-0x30630008, 0x3c010001, 0xac225f50, 0x3c010001,
-0xac235f4c, 0x8f830054, 0x24020009, 0x3c010001,
-0xac225f30, 0x3c010001, 0x100000b9, 0xac235f54,
-0x8f830054, 0x3c020001, 0x8c425f54, 0x2463d8f0,
+0x3c030002, 0x8c63905c, 0x24020005, 0x3c010002,
+0xac229010, 0x3c010002, 0x10000131, 0xac239060,
+0x3c020002, 0x8c429050, 0x10400010, 0x3c02fdff,
+0x3c020001, 0x8c426ebc, 0x24420001, 0x3c010001,
+0xac226ebc, 0x2c420002, 0x14400125, 0x24020001,
+0x3c010001, 0xac226ec4, 0x3c010001, 0xac206ebc,
+0x3c010001, 0x1000011e, 0xac226e1c, 0x3c030002,
+0x8c639040, 0x3442ffff, 0x10600119, 0x282a024,
+0x3c020002, 0x8c42901c, 0x10400115, 0x0,
+0x3c010002, 0xac229048, 0x24020003, 0x3c010002,
+0xac229020, 0x100000b8, 0x24020006, 0x3c010002,
+0xac209028, 0x8f820204, 0x34420040, 0xaf820204,
+0x3c020002, 0x8c429060, 0x24030007, 0x3c010002,
+0xac239010, 0x34420040, 0x3c010002, 0xac229060,
+0x3c020002, 0x8c429040, 0x10400005, 0x0,
+0x3c020002, 0x8c42901c, 0x104000f0, 0x24020002,
+0x3c050002, 0x24a59020, 0x8ca20000, 0x2c424e21,
+0x104000ea, 0x24020002, 0x3c020002, 0x8c429044,
+0x104000ef, 0x2404ffbf, 0x3c020002, 0x8c42901c,
+0x3c030002, 0x8c639048, 0x441024, 0x641824,
+0x10430004, 0x24020001, 0x3c010002, 0x100000e4,
+0xac229010, 0x24020003, 0xaca20000, 0x24020008,
+0x3c010002, 0xac229010, 0x3c020002, 0x8c42904c,
+0x1040000c, 0x24020001, 0x3c040002, 0xc0050c1,
+0x8c84901c, 0x3c020002, 0x8c429068, 0x14400005,
+0x24020001, 0x3c020002, 0x8c429064, 0x10400006,
+0x24020001, 0x3c010001, 0xac226e1c, 0x3c010002,
+0x100000cb, 0xac209038, 0x3c020002, 0x8c429030,
+0x3c030002, 0x8c63901c, 0x2c420001, 0x210c0,
+0x30630008, 0x3c010002, 0xac229030, 0x3c010002,
+0xac23902c, 0x8f830054, 0x24020009, 0x3c010002,
+0xac229010, 0x3c010002, 0x100000b9, 0xac239034,
+0x8f830054, 0x3c020002, 0x8c429034, 0x2463d8f0,
0x431023, 0x2c422710, 0x1440009f, 0x0,
-0x3c020001, 0x8c425f60, 0x10400005, 0x0,
-0x3c020001, 0x8c425f3c, 0x104000a0, 0x24020002,
-0x3c030001, 0x24635f40, 0x8c620000, 0x2c424e21,
-0x1040009a, 0x24020002, 0x3c020001, 0x8c425f6c,
-0x1040000e, 0x0, 0x3c020001, 0x8c425f3c,
-0x3c010001, 0xac205f6c, 0x30420080, 0x1040002f,
+0x3c020002, 0x8c429040, 0x10400005, 0x0,
+0x3c020002, 0x8c42901c, 0x104000a0, 0x24020002,
+0x3c030002, 0x24639020, 0x8c620000, 0x2c424e21,
+0x1040009a, 0x24020002, 0x3c020002, 0x8c42904c,
+0x1040000e, 0x0, 0x3c020002, 0x8c42901c,
+0x3c010002, 0xac20904c, 0x30420080, 0x1040002f,
0x2402000c, 0x8f820204, 0x30420080, 0x1440000c,
-0x24020003, 0x10000029, 0x2402000c, 0x3c020001,
-0x8c425f3c, 0x30420080, 0x14400005, 0x24020003,
+0x24020003, 0x10000029, 0x2402000c, 0x3c020002,
+0x8c42901c, 0x30420080, 0x14400005, 0x24020003,
0x8f820204, 0x30420080, 0x1040001f, 0x24020003,
-0xac620000, 0x2402000a, 0x3c010001, 0xac225f30,
-0x3c040001, 0x24845f78, 0x8c820000, 0x3c030001,
-0x8c635f50, 0x431025, 0xaf820204, 0x8c830000,
-0x3c040001, 0x8c845f50, 0x2402000b, 0x3c010001,
-0xac225f30, 0x641825, 0x3c010001, 0xac235f80,
-0x3c050001, 0x24a55f40, 0x8ca20000, 0x2c424e21,
-0x10400066, 0x24020002, 0x3c020001, 0x8c425f70,
-0x10400005, 0x0, 0x2402000c, 0x3c010001,
-0x10000067, 0xac225f30, 0x3c020001, 0x8c425f60,
-0x10400063, 0x0, 0x3c040001, 0x8c845f3c,
-0x10800055, 0x30820008, 0x3c030001, 0x8c635f4c,
-0x1062005b, 0x24020003, 0x3c010001, 0xac245f68,
-0xaca20000, 0x24020006, 0x3c010001, 0x10000054,
-0xac225f30, 0x8f820200, 0x34420002, 0xaf820200,
-0x8f830054, 0x2402000d, 0x3c010001, 0xac225f30,
-0x3c010001, 0xac235f54, 0x8f830054, 0x3c020001,
-0x8c425f54, 0x2463d8f0, 0x431023, 0x2c422710,
-0x14400031, 0x0, 0x3c020001, 0x8c425f70,
-0x10400020, 0x2402000e, 0x3c030001, 0x8c635f84,
-0x3c010001, 0x14600015, 0xac225f30, 0xc003bc9,
-0x0, 0x3c050001, 0x8ca53d88, 0xc0048dd,
-0x2021, 0x3c030001, 0x8c633d88, 0x24020004,
-0x14620005, 0x2403fffb, 0x3c020001, 0x8c423d84,
-0x10000003, 0x2403fff7, 0x3c020001, 0x8c423d84,
-0x431024, 0x3c010001, 0xac223d84, 0x8f830224,
-0x3c020200, 0x3c010001, 0xac235f8c, 0x10000020,
-0x282a025, 0x3c020001, 0x8c425f60, 0x10400005,
-0x0, 0x3c020001, 0x8c425f3c, 0x1040000f,
-0x24020002, 0x3c020001, 0x8c425f40, 0x2c424e21,
-0x1040000a, 0x24020002, 0x3c020001, 0x8c425f60,
-0x1040000f, 0x0, 0x3c020001, 0x8c425f3c,
-0x1440000b, 0x0, 0x24020002, 0x3c010001,
-0x10000007, 0xac225f30, 0x3c020001, 0x8c425f60,
-0x10400003, 0x0, 0xc003b0b, 0x0,
+0xac620000, 0x2402000a, 0x3c010002, 0xac229010,
+0x3c040002, 0x24849058, 0x8c820000, 0x3c030002,
+0x8c639030, 0x431025, 0xaf820204, 0x8c830000,
+0x3c040002, 0x8c849030, 0x2402000b, 0x3c010002,
+0xac229010, 0x641825, 0x3c010002, 0xac239060,
+0x3c050002, 0x24a59020, 0x8ca20000, 0x2c424e21,
+0x10400066, 0x24020002, 0x3c020002, 0x8c429050,
+0x10400005, 0x0, 0x2402000c, 0x3c010002,
+0x10000067, 0xac229010, 0x3c020002, 0x8c429040,
+0x10400063, 0x0, 0x3c040002, 0x8c84901c,
+0x10800055, 0x30820008, 0x3c030002, 0x8c63902c,
+0x1062005b, 0x24020003, 0x3c010002, 0xac249048,
+0xaca20000, 0x24020006, 0x3c010002, 0x10000054,
+0xac229010, 0x8f820200, 0x34420002, 0xaf820200,
+0x8f830054, 0x2402000d, 0x3c010002, 0xac229010,
+0x3c010002, 0xac239034, 0x8f830054, 0x3c020002,
+0x8c429034, 0x2463d8f0, 0x431023, 0x2c422710,
+0x14400031, 0x0, 0x3c020002, 0x8c429050,
+0x10400020, 0x2402000e, 0x3c030002, 0x8c639064,
+0x3c010002, 0x14600015, 0xac229010, 0xc003e45,
+0x0, 0x3c050001, 0x8ca56e18, 0xc0052c7,
+0x2021, 0x3c030001, 0x8c636e18, 0x24020004,
+0x14620005, 0x2403fffb, 0x3c020001, 0x8c426e14,
+0x10000003, 0x2403fff7, 0x3c020001, 0x8c426e14,
+0x431024, 0x3c010001, 0xac226e14, 0x8f830224,
+0x3c020200, 0x3c010002, 0xac23906c, 0x10000020,
+0x282a025, 0x3c020002, 0x8c429040, 0x10400005,
+0x0, 0x3c020002, 0x8c42901c, 0x1040000f,
+0x24020002, 0x3c020002, 0x8c429020, 0x2c424e21,
+0x1040000a, 0x24020002, 0x3c020002, 0x8c429040,
+0x1040000f, 0x0, 0x3c020002, 0x8c42901c,
+0x1440000b, 0x0, 0x24020002, 0x3c010002,
+0x10000007, 0xac229010, 0x3c020002, 0x8c429040,
+0x10400003, 0x0, 0xc003d87, 0x0,
0x8f820220, 0x3c03f700, 0x431025, 0xaf820220,
-0x8fbf0010, 0x3e00008, 0x27bd0018, 0x3c030001,
-0x24635f88, 0x8c620000, 0x10400005, 0x34422000,
-0x3c010001, 0xac225f7c, 0x10000003, 0xac600000,
-0x3c010001, 0xac245f7c, 0x3e00008, 0x0,
-0x27bdffe0, 0x30820030, 0xafbf0018, 0x3c010001,
-0xac225f84, 0x14400067, 0x3c02ffff, 0x34421f0e,
+0x8fbf0010, 0x3e00008, 0x27bd0018, 0x3c030002,
+0x24639068, 0x8c620000, 0x10400005, 0x34422000,
+0x3c010002, 0xac22905c, 0x10000003, 0xac600000,
+0x3c010002, 0xac24905c, 0x3e00008, 0x0,
+0x27bdffe0, 0x30820030, 0xafbf0018, 0x3c010002,
+0xac229064, 0x14400067, 0x3c02ffff, 0x34421f0e,
0x821024, 0x14400061, 0x24020030, 0x30822000,
0x1040005d, 0x30838000, 0x31a02, 0x30820001,
-0x21200, 0x3c040001, 0x8c843ecc, 0x621825,
-0x331c2, 0x3c030001, 0x24633e18, 0x30828000,
+0x21200, 0x3c040001, 0x8c846f9c, 0x621825,
+0x331c2, 0x3c030001, 0x24636ec8, 0x30828000,
0x21202, 0x30840001, 0x42200, 0x441025,
0x239c2, 0x61080, 0x431021, 0x471021,
0x90430000, 0x24020001, 0x10620025, 0x0,
@@ -8037,191 +8775,368 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x1062002c, 0x3c05000f, 0x10000037, 0x0,
0x8f820200, 0x2403feff, 0x431024, 0xaf820200,
0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024,
-0xaf820220, 0x3c010001, 0xac205fa4, 0x3c010001,
-0x10000034, 0xac205fac, 0x8f820200, 0x34420100,
+0xaf820220, 0x3c010002, 0xac209084, 0x3c010002,
+0x10000034, 0xac20908c, 0x8f820200, 0x34420100,
0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff,
-0x431024, 0xaf820220, 0x24020100, 0x3c010001,
-0xac225fa4, 0x3c010001, 0x10000026, 0xac205fac,
+0x431024, 0xaf820220, 0x24020100, 0x3c010002,
+0xac229084, 0x3c010002, 0x10000026, 0xac20908c,
0x8f820200, 0x2403feff, 0x431024, 0xaf820200,
0x8f820220, 0x3c030001, 0x431025, 0xaf820220,
-0x3c010001, 0xac205fa4, 0x3c010001, 0x10000019,
-0xac235fac, 0x8f820200, 0x34420100, 0xaf820200,
+0x3c010002, 0xac209084, 0x3c010002, 0x10000019,
+0xac23908c, 0x8f820200, 0x34420100, 0xaf820200,
0x8f820220, 0x3c030001, 0x431025, 0xaf820220,
-0x24020100, 0x3c010001, 0xac225fa4, 0x3c010001,
-0x1000000c, 0xac235fac, 0x34a5ffff, 0x3c040001,
-0x24843c68, 0xafa30010, 0xc0029bb, 0xafa00014,
-0x10000004, 0x0, 0x24020030, 0x3c010001,
-0xac225f88, 0x8fbf0018, 0x3e00008, 0x27bd0020,
+0x24020100, 0x3c010002, 0xac229084, 0x3c010002,
+0x1000000c, 0xac23908c, 0x34a5ffff, 0x3c040001,
+0x24846cb8, 0xafa30010, 0xc002b17, 0xafa00014,
+0x10000004, 0x0, 0x24020030, 0x3c010002,
+0xac229068, 0x8fbf0018, 0x3e00008, 0x27bd0020,
0x0, 0x0, 0x0, 0x27bdffc8,
-0xafb10024, 0x808821, 0xafb3002c, 0xa09821,
-0xafb00020, 0xc08021, 0x3c040001, 0x24843c80,
-0x3c050009, 0x3c020001, 0x8c423d88, 0x34a59001,
-0x2203021, 0x2603821, 0xafbf0030, 0xafb20028,
-0xa7a0001a, 0xafb00014, 0xc0029bb, 0xafa20010,
-0x24020002, 0x126200eb, 0x2e620003, 0x10400005,
-0x24020001, 0x1262000a, 0x3c02fffb, 0x100000e5,
-0x0, 0x24020004, 0x1262006d, 0x24020008,
-0x1262006c, 0x3c02ffec, 0x100000de, 0x0,
-0x3442ffff, 0x2028024, 0x119140, 0x3c010001,
-0x320821, 0xac305f9c, 0x3c024000, 0x2021024,
-0x10400046, 0x1023c2, 0x30840030, 0x101382,
-0x3042000c, 0x3c030001, 0x24633db4, 0x431021,
-0x823821, 0x3c020020, 0x2021024, 0x10400006,
-0x24020100, 0x3c010001, 0x320821, 0xac225fa0,
-0x10000005, 0x3c020080, 0x3c010001, 0x320821,
-0xac205fa0, 0x3c020080, 0x2021024, 0x10400006,
-0x111940, 0x3c020001, 0x3c010001, 0x230821,
-0x10000005, 0xac225fa8, 0x111140, 0x3c010001,
-0x220821, 0xac205fa8, 0x94e30000, 0x32024000,
-0x10400003, 0xa7a30018, 0x34624000, 0xa7a20018,
-0x24040001, 0x94e20002, 0x24050004, 0x24e60002,
-0x34420001, 0xc004166, 0xa4e20002, 0x24040001,
-0x2821, 0xc004166, 0x27a60018, 0x3c020001,
-0x8c423d88, 0x24110001, 0x3c010001, 0xac313d94,
-0x14530004, 0x32028000, 0xc003b0b, 0x0,
-0x32028000, 0x10400097, 0x0, 0xc003b0b,
-0x0, 0x24020002, 0x3c010001, 0xac313d8c,
-0x3c010001, 0x1000008f, 0xac223d88, 0x24040001,
-0x24050004, 0x27b0001a, 0xc004166, 0x2003021,
-0x24040001, 0x2821, 0xc004166, 0x2003021,
-0x3c020001, 0x521021, 0x8c425f94, 0x3c040001,
-0x8c843d88, 0x3c03bfff, 0x3463ffff, 0x3c010001,
-0xac333d94, 0x431024, 0x3c010001, 0x320821,
-0x10930076, 0xac225f94, 0x10000076, 0x0,
-0x3c02ffec, 0x3442ffff, 0x2028024, 0x3c020008,
-0x2028025, 0x111140, 0x3c010001, 0x220821,
-0xac305f98, 0x3c022000, 0x2021024, 0x10400009,
-0x0, 0x3c020001, 0x8c423e14, 0x14400005,
-0x24020001, 0x3c010001, 0xac223ec8, 0x10000004,
-0x3c024000, 0x3c010001, 0xac203ec8, 0x3c024000,
-0x2021024, 0x1440001a, 0x0, 0x3c020001,
-0x8c423ec8, 0x10400005, 0x24022020, 0x3c010001,
-0xac223ecc, 0x24020001, 0xaee204b8, 0x3c04bfff,
-0x111940, 0x3c020001, 0x431021, 0x8c425f90,
-0x3c050001, 0x8ca53d88, 0x3484ffff, 0x441024,
-0x3c010001, 0x230821, 0xac225f90, 0x24020001,
-0x10a20044, 0x0, 0x10000040, 0x0,
-0x3c020001, 0x8c423ec8, 0x1040001c, 0x24022000,
-0x3c010001, 0xac223ecc, 0x3c0300a0, 0x2031024,
-0x14430005, 0x111140, 0x3402a000, 0x3c010001,
-0x1000002d, 0xac223ecc, 0x3c030001, 0x621821,
-0x8c635f98, 0x3c020020, 0x621024, 0x10400004,
-0x24022001, 0x3c010001, 0x10000023, 0xac223ecc,
-0x3c020080, 0x621024, 0x1040001f, 0x3402a001,
-0x3c010001, 0x1000001c, 0xac223ecc, 0x3c020020,
-0x2021024, 0x10400007, 0x111940, 0x24020100,
-0x3c010001, 0x230821, 0xac225fa4, 0x10000006,
-0x3c020080, 0x111140, 0x3c010001, 0x220821,
-0xac205fa4, 0x3c020080, 0x2021024, 0x10400006,
-0x111940, 0x3c020001, 0x3c010001, 0x230821,
-0x10000005, 0xac225fac, 0x111140, 0x3c010001,
-0x220821, 0xac205fac, 0x3c030001, 0x8c633d88,
-0x24020001, 0x10620003, 0x0, 0xc003b0b,
-0x0, 0x8fbf0030, 0x8fb3002c, 0x8fb20028,
-0x8fb10024, 0x8fb00020, 0x3e00008, 0x27bd0038,
-0x27bdffd0, 0xafb50028, 0x80a821, 0xafb20020,
-0x9021, 0xafb30024, 0x9821, 0xafb1001c,
-0x8821, 0x24020002, 0xafbf002c, 0xafb00018,
-0xa7a00012, 0x10a20068, 0xa7a00010, 0x2ca20003,
-0x10400005, 0x24020001, 0x10a2000a, 0x158140,
-0x100000ae, 0x2201021, 0x24020004, 0x10a2005e,
-0x24020008, 0x10a2005d, 0x152940, 0x100000a7,
-0x2201021, 0x3c030001, 0x701821, 0x8c635f9c,
-0x3c024000, 0x621024, 0x14400009, 0x24040001,
-0x3c027fff, 0x3442ffff, 0x628824, 0x3c010001,
-0x300821, 0xac315f94, 0x10000098, 0x2201021,
-0x24050001, 0xc004124, 0x27a60010, 0x24040001,
-0x24050001, 0xc004124, 0x27a60010, 0x97a20010,
-0x30420004, 0x10400034, 0x3c114000, 0x3c030001,
-0x8c633ee0, 0x24020003, 0x10620008, 0x2c620004,
-0x14400029, 0x3c028000, 0x24020004, 0x10620014,
-0x24040001, 0x10000024, 0x3c028000, 0x24040001,
-0x24050011, 0x27b00012, 0xc004124, 0x2003021,
-0x24040001, 0x24050011, 0xc004124, 0x2003021,
-0x97a30012, 0x30624000, 0x10400002, 0x3c130010,
-0x3c130008, 0x3c120001, 0x10000010, 0x30628000,
-0x24050014, 0x27b00012, 0xc004124, 0x2003021,
-0x24040001, 0x24050014, 0xc004124, 0x2003021,
-0x97a30012, 0x30621000, 0x10400002, 0x3c130010,
-0x3c130008, 0x3c120001, 0x30620800, 0x54400001,
-0x3c120002, 0x3c028000, 0x2221025, 0x2531825,
-0x10000007, 0x438825, 0x3c110001, 0x2308821,
-0x8e315f9c, 0x3c027fff, 0x3442ffff, 0x2228824,
-0x151140, 0x3c010001, 0x220821, 0xac315f94,
-0x1000004e, 0x2201021, 0x152940, 0x3c030001,
-0x651821, 0x8c635f98, 0x3c024000, 0x621024,
+0xafb20028, 0x809021, 0xafb3002c, 0xa09821,
+0xafb00020, 0xc08021, 0x3c040001, 0x24846cd0,
+0x3c050009, 0x3c020001, 0x8c426e18, 0x34a59001,
+0x2403021, 0x2603821, 0xafbf0030, 0xafb10024,
+0xa7a0001a, 0xafb00014, 0xc002b17, 0xafa20010,
+0x24020002, 0x1262007f, 0x2e620003, 0x10400005,
+0x24020001, 0x1262000a, 0x0, 0x1000016f,
+0x0, 0x24020004, 0x126200f4, 0x24020008,
+0x126200f3, 0x3c02ffec, 0x10000168, 0x0,
+0x3c020001, 0x8c426e14, 0x30420002, 0x14400004,
+0x128940, 0x3c02fffb, 0x3442ffff, 0x2028024,
+0x3c010002, 0x310821, 0xac30907c, 0x3c024000,
+0x2021024, 0x1040004a, 0x1023c2, 0x30840030,
+0x101382, 0x3042001c, 0x3c030001, 0x24636e58,
+0x431021, 0x823821, 0x3c020020, 0x2021024,
+0x10400006, 0x24020100, 0x3c010002, 0x310821,
+0xac229080, 0x10000005, 0x3c020080, 0x3c010002,
+0x310821, 0xac209080, 0x3c020080, 0x2021024,
+0x10400006, 0x121940, 0x3c020001, 0x3c010002,
+0x230821, 0x10000005, 0xac229088, 0x121140,
+0x3c010002, 0x220821, 0xac209088, 0x94e30000,
+0x32024000, 0x10400003, 0xa7a30018, 0x34624000,
+0xa7a20018, 0x24040001, 0x94e20002, 0x24050004,
+0x24e60002, 0x34420001, 0xc00450e, 0xa4e20002,
+0x24040001, 0x2821, 0xc00450e, 0x27a60018,
+0x3c020001, 0x8c426e18, 0x24110001, 0x3c010001,
+0xac316e24, 0x14530004, 0x32028000, 0xc003d87,
+0x0, 0x32028000, 0x1040011c, 0x0,
+0xc003d87, 0x0, 0x3c030001, 0x8c636fb8,
+0x24020005, 0x10620115, 0x24020002, 0x3c010001,
+0xac316e1c, 0x3c010001, 0x10000110, 0xac226e18,
+0x24040001, 0x24050004, 0x27b0001a, 0xc00450e,
+0x2003021, 0x24040001, 0x2821, 0xc00450e,
+0x2003021, 0x3c020002, 0x511021, 0x8c429074,
+0x3c040001, 0x8c846e18, 0x3c03bfff, 0x3463ffff,
+0x3c010001, 0xac336e24, 0x431024, 0x3c010002,
+0x310821, 0x109300f7, 0xac229074, 0x100000f7,
+0x0, 0x3c022000, 0x2021024, 0x10400005,
+0x24020001, 0x3c010001, 0xac226f98, 0x10000004,
+0x128940, 0x3c010001, 0xac206f98, 0x128940,
+0x3c010002, 0x310821, 0xac309078, 0x3c024000,
+0x2021024, 0x14400014, 0x0, 0x3c020001,
+0x8c426f98, 0x10400006, 0x24040004, 0x24050001,
+0xc004e0e, 0x24062000, 0x24020001, 0xaee204b8,
+0x3c020002, 0x511021, 0x8c429070, 0x3c03bfff,
+0x3463ffff, 0x431024, 0x3c010002, 0x310821,
+0x100000d0, 0xac229070, 0x3c020001, 0x8c426f98,
+0x10400028, 0x3c0300a0, 0x2031024, 0x5443000d,
+0x3c020020, 0x3c020001, 0x8c426f9c, 0x24030100,
+0x3c010002, 0x310821, 0xac239084, 0x3c030001,
+0x3c010002, 0x310821, 0xac23908c, 0x10000015,
+0x34420400, 0x2021024, 0x10400008, 0x24030100,
+0x3c020001, 0x8c426f9c, 0x3c010002, 0x310821,
+0xac239084, 0x1000000b, 0x34420800, 0x3c020080,
+0x2021024, 0x1040002e, 0x3c030001, 0x3c020001,
+0x8c426f9c, 0x3c010002, 0x310821, 0xac23908c,
+0x34420c00, 0x3c010001, 0xac226f9c, 0x10000025,
+0x24040001, 0x3c020020, 0x2021024, 0x10400006,
+0x24020100, 0x3c010002, 0x310821, 0xac229084,
+0x10000005, 0x3c020080, 0x3c010002, 0x310821,
+0xac209084, 0x3c020080, 0x2021024, 0x10400007,
+0x121940, 0x3c020001, 0x3c010002, 0x230821,
+0xac22908c, 0x10000006, 0x24040001, 0x121140,
+0x3c010002, 0x220821, 0xac20908c, 0x24040001,
+0x2821, 0x27b0001e, 0xc0044cc, 0x2003021,
+0x24040001, 0x2821, 0xc0044cc, 0x2003021,
+0x24040001, 0x24050001, 0x27b0001c, 0xc0044cc,
+0x2003021, 0x24040001, 0x24050001, 0xc0044cc,
+0x2003021, 0x10000077, 0x0, 0x3c02ffec,
+0x3442ffff, 0x2028024, 0x3c020008, 0x2028025,
+0x121140, 0x3c010002, 0x220821, 0xac309078,
+0x3c022000, 0x2021024, 0x10400009, 0x0,
+0x3c020001, 0x8c426ec4, 0x14400005, 0x24020001,
+0x3c010001, 0xac226f98, 0x10000004, 0x3c024000,
+0x3c010001, 0xac206f98, 0x3c024000, 0x2021024,
+0x1440001d, 0x24020e01, 0x3c030001, 0x8c636f98,
+0xaf820238, 0x3c010001, 0xac206e30, 0x10600005,
+0x24022020, 0x3c010001, 0xac226f9c, 0x24020001,
+0xaee204b8, 0x3c04bfff, 0x121940, 0x3c020002,
+0x431021, 0x8c429070, 0x3c050001, 0x8ca56e18,
+0x3484ffff, 0x441024, 0x3c010002, 0x230821,
+0xac229070, 0x24020001, 0x10a20044, 0x0,
+0x10000040, 0x0, 0x3c020001, 0x8c426f98,
+0x1040001c, 0x24022000, 0x3c010001, 0xac226f9c,
+0x3c0300a0, 0x2031024, 0x14430005, 0x121140,
+0x3402a000, 0x3c010001, 0x1000002d, 0xac226f9c,
+0x3c030002, 0x621821, 0x8c639078, 0x3c020020,
+0x621024, 0x10400004, 0x24022001, 0x3c010001,
+0x10000023, 0xac226f9c, 0x3c020080, 0x621024,
+0x1040001f, 0x3402a001, 0x3c010001, 0x1000001c,
+0xac226f9c, 0x3c020020, 0x2021024, 0x10400007,
+0x121940, 0x24020100, 0x3c010002, 0x230821,
+0xac229084, 0x10000006, 0x3c020080, 0x121140,
+0x3c010002, 0x220821, 0xac209084, 0x3c020080,
+0x2021024, 0x10400006, 0x121940, 0x3c020001,
+0x3c010002, 0x230821, 0x10000005, 0xac22908c,
+0x121140, 0x3c010002, 0x220821, 0xac20908c,
+0x3c030001, 0x8c636e18, 0x24020001, 0x10620003,
+0x0, 0xc003d87, 0x0, 0x8fbf0030,
+0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
+0x3e00008, 0x27bd0038, 0x27bdffb8, 0xafbe003c,
+0x80f021, 0xafb30034, 0x9821, 0xafb20030,
+0x9021, 0xafb1002c, 0x8821, 0x24020002,
+0xafbf0040, 0xafb50038, 0xafb00028, 0xa7a00020,
+0xa7a00018, 0xa7a0001a, 0xa7a0001c, 0xa7a0001e,
+0x10a20142, 0xa7a00022, 0x2ca20003, 0x10400005,
+0x24020001, 0x10a2000a, 0x1ea940, 0x10000253,
+0x2201021, 0x24020004, 0x10a20203, 0x24020008,
+0x10a20202, 0x1e2940, 0x1000024c, 0x2201021,
+0x3c030002, 0x751821, 0x8c63907c, 0x3c024000,
+0x621024, 0x14400009, 0x24040001, 0x3c027fff,
+0x3442ffff, 0x628824, 0x3c010002, 0x350821,
+0xac319074, 0x1000023d, 0x2201021, 0x2821,
+0xc0044cc, 0x27a60018, 0x24040001, 0x2821,
+0xc0044cc, 0x27a60018, 0x24040001, 0x24050001,
+0x27b0001a, 0xc0044cc, 0x2003021, 0x24040001,
+0x24050001, 0xc0044cc, 0x2003021, 0x24040001,
+0x24050004, 0x27b0001c, 0xc0044cc, 0x2003021,
+0x24040001, 0x24050004, 0xc0044cc, 0x2003021,
+0x24040001, 0x24050005, 0x27b0001e, 0xc0044cc,
+0x2003021, 0x24040001, 0x24050005, 0xc0044cc,
+0x2003021, 0x24040001, 0x24050009, 0xc0044cc,
+0x2003021, 0x24040001, 0x24050009, 0xc0044cc,
+0x2003021, 0x24040001, 0x24050001, 0xc0044cc,
+0x27a60018, 0x24040001, 0x24050001, 0xc0044cc,
+0x27a60018, 0x97a20018, 0x30420004, 0x104000ba,
+0x3c114000, 0x3c020001, 0x8c426fb8, 0x2443ffff,
+0x2c620006, 0x104000ba, 0x31080, 0x3c010001,
+0x220821, 0x8c226ce8, 0x400008, 0x0,
+0x24040001, 0x24050011, 0x27b00020, 0xc0044cc,
+0x2003021, 0x24040001, 0x24050011, 0xc0044cc,
+0x2003021, 0x97a30020, 0x30624000, 0x10400002,
+0x3c120010, 0x3c120008, 0x3c130001, 0x30628000,
+0x54400098, 0x3c130002, 0x10000097, 0x3c028000,
+0x24040001, 0x24050014, 0x27b00020, 0xc0044cc,
+0x2003021, 0x24040001, 0x24050014, 0xc0044cc,
+0x2003021, 0x97a30020, 0x30621000, 0x10400002,
+0x3c120010, 0x3c120008, 0x3c130001, 0x1000ffec,
+0x30620800, 0x24040001, 0x24050019, 0x27b00022,
+0xc0044cc, 0x2003021, 0x24040001, 0x24050019,
+0xc0044cc, 0x2003021, 0x97a20022, 0x30430700,
+0x24020400, 0x10620027, 0x28620401, 0x1040000e,
+0x24020200, 0x1062001f, 0x28620201, 0x10400005,
+0x24020100, 0x5062001e, 0x3c130001, 0x1000001e,
+0x24040001, 0x24020300, 0x50620019, 0x3c130002,
+0x10000019, 0x24040001, 0x24020600, 0x1062000d,
+0x28620601, 0x10400005, 0x24020500, 0x5062000b,
+0x3c130002, 0x10000010, 0x24040001, 0x24020700,
+0x1462000d, 0x24040001, 0x3c130004, 0x1000000a,
+0x3c120008, 0x10000006, 0x3c130004, 0x10000005,
+0x3c120008, 0x3c130001, 0x10000002, 0x3c120008,
+0x3c120010, 0x24040001, 0x24050010, 0x27b0001c,
+0xc0044cc, 0x2003021, 0x24040001, 0x24050010,
+0xc0044cc, 0x2003021, 0x3c020004, 0x16620010,
+0x3c020001, 0x8f840054, 0x24030001, 0x24020002,
+0x3c010001, 0xac236e1c, 0x3c010001, 0xac226e18,
+0x3c010001, 0xac236e24, 0x3c010001, 0xac236ea4,
+0x3c010001, 0xac246fa8, 0x10000041, 0x2538825,
+0x16620035, 0x3c028000, 0x3c020001, 0x8c426ea0,
+0x1440001e, 0x24040018, 0x2021, 0x2821,
+0xc004e0e, 0x34068000, 0x8f830054, 0x8f820054,
+0x2538825, 0x10000002, 0x24630032, 0x8f820054,
+0x621023, 0x2c420033, 0x1440fffc, 0x0,
+0x8f830054, 0x24020001, 0x3c010001, 0xac226ea0,
+0x3c010001, 0xac226e1c, 0x3c010001, 0xac226e18,
+0x3c010001, 0xac226e24, 0x3c010001, 0xac226ea4,
+0x3c010001, 0x1000001e, 0xac236fa8, 0x2821,
+0xc004e0e, 0x24060404, 0x2021, 0x2405001e,
+0x27a60018, 0x24020002, 0xc00450e, 0xa7a20018,
+0x2021, 0x2821, 0x27a60018, 0xc00450e,
+0xa7a00018, 0x24040018, 0x24050002, 0xc004e0e,
+0x24060004, 0x3c028000, 0x2221025, 0x2721825,
+0x10000007, 0x438825, 0x3c110002, 0x2358821,
+0x8e31907c, 0x3c027fff, 0x3442ffff, 0x2228824,
+0x3c020001, 0x8c426e28, 0x1040001c, 0x0,
+0x3c020001, 0x8c426f98, 0x10400002, 0x3c022000,
+0x2228825, 0x1e1140, 0x3c010002, 0x220821,
+0x8c229080, 0x10400003, 0x3c020020, 0x10000004,
+0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824,
+0x1e1140, 0x3c010002, 0x220821, 0x8c229088,
+0x10400003, 0x3c020080, 0x10000004, 0x2228825,
+0x3c02ff7f, 0x3442ffff, 0x2228824, 0x3c040001,
+0x24846cdc, 0x3c05000c, 0x97a60022, 0x3c070001,
+0x8ce76e18, 0x34a50326, 0x1e1140, 0x3c010002,
+0x220821, 0xac319074, 0xafb30010, 0xc002b17,
+0xafb10014, 0x10000119, 0x2201021, 0x1ea940,
+0x3c030002, 0x751821, 0x8c639078, 0x3c024000,
+0x621024, 0x14400009, 0x24040001, 0x3c027fff,
+0x3442ffff, 0x628824, 0x3c010002, 0x350821,
+0xac319070, 0x10000109, 0x2201021, 0x2821,
+0xc0044cc, 0x27a60018, 0x24040001, 0x2821,
+0xc0044cc, 0x27a60018, 0x24040001, 0x24050001,
+0x27b1001a, 0xc0044cc, 0x2203021, 0x24040001,
+0x24050001, 0xc0044cc, 0x2203021, 0x24040001,
+0x24050004, 0x27b0001c, 0xc0044cc, 0x2003021,
+0x24040001, 0x24050004, 0xc0044cc, 0x2003021,
+0x24040001, 0x24050005, 0x27b0001e, 0xc0044cc,
+0x2003021, 0x24040001, 0x24050005, 0xc0044cc,
+0x2003021, 0x24040001, 0x24050010, 0xc0044cc,
+0x27a60018, 0x24040001, 0x24050010, 0xc0044cc,
+0x27a60018, 0x24040001, 0x2405000a, 0xc0044cc,
+0x2203021, 0x24040001, 0x2405000a, 0xc0044cc,
+0x2203021, 0x24040001, 0x24050001, 0xc0044cc,
+0x27a60018, 0x24040001, 0x24050001, 0xc0044cc,
+0x27a60018, 0x97a20018, 0x30420004, 0x10400058,
+0x3c114000, 0x3c030001, 0x8c636fac, 0x24020005,
+0x14620059, 0x24040001, 0x24050019, 0x27b00022,
+0xc0044cc, 0x2003021, 0x24040001, 0x24050019,
+0xc0044cc, 0x2003021, 0x97a20022, 0x30430700,
+0x24020400, 0x10620027, 0x28620401, 0x1040000e,
+0x24020200, 0x1062001f, 0x28620201, 0x10400005,
+0x24020100, 0x5062001e, 0x3c130001, 0x1000001e,
+0x3c020004, 0x24020300, 0x50620019, 0x3c130002,
+0x10000019, 0x3c020004, 0x24020600, 0x1062000d,
+0x28620601, 0x10400005, 0x24020500, 0x5062000b,
+0x3c130002, 0x10000010, 0x3c020004, 0x24020700,
+0x1462000d, 0x3c020004, 0x3c130004, 0x1000000a,
+0x3c120008, 0x10000006, 0x3c130004, 0x10000005,
+0x3c120008, 0x3c130001, 0x10000002, 0x3c120008,
+0x3c120010, 0x3c020004, 0x12620017, 0x3c028000,
+0x8f820054, 0x24100001, 0x3c010001, 0xac306e1c,
+0x3c010001, 0xac306e18, 0x3c010001, 0xac306e24,
+0x3c010001, 0xac306ea4, 0x3c010001, 0xac226fa8,
+0x3c020001, 0x16620014, 0x2728825, 0x2021,
+0x2821, 0xc004e0e, 0x34068000, 0x3c010001,
+0x1000000d, 0xac306ea0, 0x2221025, 0x2531825,
+0x3c010001, 0xac206ea0, 0x10000007, 0x438825,
+0x3c110002, 0x2358821, 0x8e319070, 0x3c027fff,
+0x3442ffff, 0x2228824, 0x3c020001, 0x8c426e28,
+0x10400066, 0x1e1140, 0x3c020001, 0x8c426f98,
+0x10400002, 0x3c022000, 0x2228825, 0x1e1140,
+0x3c010002, 0x220821, 0x8c229084, 0x10400003,
+0x3c020020, 0x10000004, 0x2228825, 0x3c02ffdf,
+0x3442ffff, 0x2228824, 0x1e1140, 0x3c010002,
+0x220821, 0x8c22908c, 0x10400003, 0x3c020080,
+0x1000004d, 0x2228825, 0x3c02ff7f, 0x3442ffff,
+0x10000049, 0x2228824, 0x1e2940, 0x3c030002,
+0x651821, 0x8c639078, 0x3c024000, 0x621024,
0x14400008, 0x3c027fff, 0x3442ffff, 0x628824,
-0x3c010001, 0x250821, 0xac315f90, 0x1000003f,
-0x2201021, 0x3c020001, 0x8c423d98, 0x10400033,
-0x3c11c00c, 0x3c020001, 0x8c423e14, 0x3c04c00c,
-0x34842000, 0x3c030001, 0x8c633ec8, 0x2102b,
+0x3c010002, 0x250821, 0xac319070, 0x1000003f,
+0x2201021, 0x3c020001, 0x8c426e28, 0x10400033,
+0x3c11c00c, 0x3c020001, 0x8c426ec4, 0x3c04c00c,
+0x34842000, 0x3c030001, 0x8c636f98, 0x2102b,
0x21023, 0x441024, 0x10600003, 0x518825,
-0x3c022000, 0x2228825, 0x3c020001, 0x451021,
-0x8c425fa4, 0x10400003, 0x3c020020, 0x10000004,
+0x3c022000, 0x2228825, 0x3c020002, 0x451021,
+0x8c429084, 0x10400003, 0x3c020020, 0x10000004,
0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824,
-0x151140, 0x3c010001, 0x220821, 0x8c225fac,
+0x1e1140, 0x3c010002, 0x220821, 0x8c22908c,
0x10400003, 0x3c020080, 0x10000004, 0x2228825,
0x3c02ff7f, 0x3442ffff, 0x2228824, 0x3c020001,
-0x8c423e00, 0x10400002, 0x3c020800, 0x2228825,
-0x3c020001, 0x8c423e04, 0x10400002, 0x3c020400,
-0x2228825, 0x3c020001, 0x8c423e08, 0x10400006,
+0x8c426eb0, 0x10400002, 0x3c020800, 0x2228825,
+0x3c020001, 0x8c426eb4, 0x10400002, 0x3c020400,
+0x2228825, 0x3c020001, 0x8c426eb8, 0x10400006,
0x3c020100, 0x10000004, 0x2228825, 0x3c027fff,
-0x3442ffff, 0x628824, 0x151140, 0x3c010001,
-0x220821, 0xac315f90, 0x2201021, 0x8fbf002c,
-0x8fb50028, 0x8fb30024, 0x8fb20020, 0x8fb1001c,
-0x8fb00018, 0x3e00008, 0x27bd0030, 0x27bdffe0,
-0xafb20018, 0x809021, 0xafbf001c, 0xafb10014,
-0xafb00010, 0x8f840200, 0x3c030001, 0x8c633d88,
-0x8f860220, 0x24020002, 0x106200a6, 0x2c620003,
-0x10400005, 0x24020001, 0x1062000a, 0x121940,
-0x100000a0, 0x0, 0x24020004, 0x10620053,
-0x24020008, 0x10620052, 0x128940, 0x10000099,
-0x0, 0x3c050001, 0xa32821, 0x8ca55f9c,
-0x3c100001, 0x2038021, 0x8e105f94, 0x3c024000,
-0xa21024, 0x10400038, 0x3c020008, 0x2021024,
-0x10400020, 0x34840002, 0x3c020001, 0x431021,
-0x8c425fa0, 0x10400005, 0x34840020, 0x34840100,
-0x3c020020, 0x10000006, 0x2028025, 0x2402feff,
-0x822024, 0x3c02ffdf, 0x3442ffff, 0x2028024,
-0x121140, 0x3c010001, 0x220821, 0x8c225fa8,
-0x10400005, 0x3c020001, 0xc23025, 0x3c020080,
-0x10000016, 0x2028025, 0x3c02fffe, 0x3442ffff,
-0xc23024, 0x3c02ff7f, 0x3442ffff, 0x1000000f,
-0x2028024, 0x2402fedf, 0x822024, 0x3c02fffe,
-0x3442ffff, 0xc23024, 0x3c02ff5f, 0x3442ffff,
-0x2028024, 0x3c010001, 0x230821, 0xac205fa0,
-0x3c010001, 0x230821, 0xac205fa8, 0xaf840200,
-0xaf860220, 0x8f820220, 0x34420002, 0xaf820220,
-0x1000000a, 0x121140, 0x3c02bfff, 0x3442ffff,
-0x8f830200, 0x2028024, 0x2402fffd, 0x621824,
-0xc003b0b, 0xaf830200, 0x121140, 0x3c010001,
-0x220821, 0x1000004b, 0xac305f94, 0x128940,
-0x3c050001, 0xb12821, 0x8ca55f98, 0x3c100001,
-0x2118021, 0x8e105f90, 0x3c024000, 0xa21024,
-0x14400010, 0x0, 0x3c020001, 0x8c423ec8,
-0x14400005, 0x3c02bfff, 0x8f820200, 0x34420002,
-0xaf820200, 0x3c02bfff, 0x3442ffff, 0xc003b0b,
-0x2028024, 0x3c010001, 0x310821, 0x10000031,
-0xac305f90, 0x3c020001, 0x8c423ec8, 0x10400005,
-0x3c020020, 0x3c020001, 0x8c423e14, 0x10400025,
-0x3c020020, 0xa21024, 0x10400007, 0x34840020,
-0x24020100, 0x3c010001, 0x310821, 0xac225fa4,
-0x10000006, 0x34840100, 0x3c010001, 0x310821,
-0xac205fa4, 0x2402feff, 0x822024, 0x3c020080,
-0xa21024, 0x10400007, 0x121940, 0x3c020001,
-0x3c010001, 0x230821, 0xac225fac, 0x10000008,
-0xc23025, 0x121140, 0x3c010001, 0x220821,
-0xac205fac, 0x3c02fffe, 0x3442ffff, 0xc23024,
+0x3442ffff, 0x628824, 0x1e1140, 0x3c010002,
+0x220821, 0xac319070, 0x2201021, 0x8fbf0040,
+0x8fbe003c, 0x8fb50038, 0x8fb30034, 0x8fb20030,
+0x8fb1002c, 0x8fb00028, 0x3e00008, 0x27bd0048,
+0x27bdffd0, 0xafb20028, 0x809021, 0xafbf002c,
+0xafb10024, 0xafb00020, 0x8f840200, 0x3c100001,
+0x8e106e18, 0x8f860220, 0x24020002, 0x1202005c,
+0x2e020003, 0x10400005, 0x24020001, 0x1202000a,
+0x121940, 0x1000010c, 0x0, 0x24020004,
+0x120200bf, 0x24020008, 0x120200be, 0x128940,
+0x10000105, 0x0, 0x3c050002, 0xa32821,
+0x8ca5907c, 0x3c100002, 0x2038021, 0x8e109074,
+0x3c024000, 0xa21024, 0x10400038, 0x3c020008,
+0x2021024, 0x10400020, 0x34840002, 0x3c020002,
+0x431021, 0x8c429080, 0x10400005, 0x34840020,
+0x34840100, 0x3c020020, 0x10000006, 0x2028025,
+0x2402feff, 0x822024, 0x3c02ffdf, 0x3442ffff,
+0x2028024, 0x121140, 0x3c010002, 0x220821,
+0x8c229088, 0x10400005, 0x3c020001, 0xc23025,
+0x3c020080, 0x10000016, 0x2028025, 0x3c02fffe,
+0x3442ffff, 0xc23024, 0x3c02ff7f, 0x3442ffff,
+0x1000000f, 0x2028024, 0x2402fedf, 0x822024,
+0x3c02fffe, 0x3442ffff, 0xc23024, 0x3c02ff5f,
+0x3442ffff, 0x2028024, 0x3c010002, 0x230821,
+0xac209080, 0x3c010002, 0x230821, 0xac209088,
0xaf840200, 0xaf860220, 0x8f820220, 0x34420002,
-0xaf820220, 0x121140, 0x3c010001, 0x220821,
-0xac305f90, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0x3e00008, 0x27bd0020, 0x1821,
+0xaf820220, 0x1000000a, 0x121140, 0x3c02bfff,
+0x3442ffff, 0x8f830200, 0x2028024, 0x2402fffd,
+0x621824, 0xc003d87, 0xaf830200, 0x121140,
+0x3c010002, 0x220821, 0x100000b7, 0xac309074,
+0x3c020001, 0x8c426f98, 0x10400069, 0x24050004,
+0x24040001, 0xc0044cc, 0x27a60018, 0x24040001,
+0x24050005, 0xc0044cc, 0x27a6001a, 0x97a30018,
+0x97a2001a, 0x3c040001, 0x24846ec8, 0x30630c00,
+0x31a82, 0x30420c00, 0x21282, 0xa7a2001a,
+0x21080, 0x441021, 0x431021, 0xa7a30018,
+0x90480000, 0x24020001, 0x3103ffff, 0x10620029,
+0x28620002, 0x10400005, 0x0, 0x10600009,
+0x0, 0x1000003d, 0x0, 0x10700013,
+0x24020003, 0x1062002c, 0x0, 0x10000037,
+0x0, 0x8f820200, 0x2403feff, 0x431024,
+0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff,
+0x431024, 0xaf820220, 0x3c010002, 0xac209084,
+0x3c010002, 0x10000032, 0xac20908c, 0x8f820200,
+0x34420100, 0xaf820200, 0x8f820220, 0x3c03fffe,
+0x3463ffff, 0x431024, 0xaf820220, 0x24020100,
+0x3c010002, 0xac229084, 0x3c010002, 0x10000024,
+0xac20908c, 0x8f820200, 0x2403feff, 0x431024,
+0xaf820200, 0x8f820220, 0x3c030001, 0x431025,
+0xaf820220, 0x3c010002, 0xac209084, 0x3c010002,
+0x10000017, 0xac23908c, 0x8f820200, 0x34420100,
+0xaf820200, 0x8f820220, 0x3c030001, 0x431025,
+0xaf820220, 0x24020100, 0x3c010002, 0xac229084,
+0x3c010002, 0x1000000a, 0xac23908c, 0x3c040001,
+0x24846d00, 0x97a6001a, 0x97a70018, 0x3c050001,
+0x34a5ffff, 0xafa80010, 0xc002b17, 0xafa00014,
+0x8f820200, 0x34420002, 0x1000004b, 0xaf820200,
+0x128940, 0x3c050002, 0xb12821, 0x8ca59078,
+0x3c100002, 0x2118021, 0x8e109070, 0x3c024000,
+0xa21024, 0x14400010, 0x0, 0x3c020001,
+0x8c426f98, 0x14400005, 0x3c02bfff, 0x8f820200,
+0x34420002, 0xaf820200, 0x3c02bfff, 0x3442ffff,
+0xc003d87, 0x2028024, 0x3c010002, 0x310821,
+0x10000031, 0xac309070, 0x3c020001, 0x8c426f98,
+0x10400005, 0x3c020020, 0x3c020001, 0x8c426ec4,
+0x10400025, 0x3c020020, 0xa21024, 0x10400007,
+0x34840020, 0x24020100, 0x3c010002, 0x310821,
+0xac229084, 0x10000006, 0x34840100, 0x3c010002,
+0x310821, 0xac209084, 0x2402feff, 0x822024,
+0x3c020080, 0xa21024, 0x10400007, 0x121940,
+0x3c020001, 0x3c010002, 0x230821, 0xac22908c,
+0x10000008, 0xc23025, 0x121140, 0x3c010002,
+0x220821, 0xac20908c, 0x3c02fffe, 0x3442ffff,
+0xc23024, 0xaf840200, 0xaf860220, 0x8f820220,
+0x34420002, 0xaf820220, 0x121140, 0x3c010002,
+0x220821, 0xac309070, 0x8fbf002c, 0x8fb20028,
+0x8fb10024, 0x8fb00020, 0x3e00008, 0x27bd0030,
+0x0, 0x0, 0x0, 0x1821,
0x308400ff, 0x2405ffdf, 0x2406ffbf, 0x641007,
0x30420001, 0x10400004, 0x0, 0x8f820044,
0x10000003, 0x34420040, 0x8f820044, 0x461024,
0xaf820044, 0x8f820044, 0x34420020, 0xaf820044,
0x8f820044, 0x451024, 0xaf820044, 0x24630001,
0x28620008, 0x5440ffee, 0x641007, 0x3e00008,
+0x0, 0x2c820008, 0x1040001b, 0x0,
+0x2405ffdf, 0x2406ffbf, 0x41880, 0x3c020001,
+0x24426ee0, 0x621821, 0x24640004, 0x90620000,
+0x10400004, 0x0, 0x8f820044, 0x10000003,
+0x34420040, 0x8f820044, 0x461024, 0xaf820044,
+0x8f820044, 0x34420020, 0xaf820044, 0x8f820044,
+0x451024, 0xaf820044, 0x24630001, 0x64102b,
+0x1440ffee, 0x0, 0x3e00008, 0x0,
0x0, 0x0, 0x0, 0x8f8400c4,
0x8f8600e0, 0x8f8700e4, 0x2402fff8, 0xc22824,
0x10e5001a, 0x27623ff8, 0x14e20002, 0x24e80008,
@@ -8232,23 +9147,9 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x8f4201fc, 0x3e00008, 0xe01021, 0xaf8800e8,
0x24420001, 0xaf4201fc, 0xaf8800e4, 0x3e00008,
0x1021, 0x3e00008, 0x0, 0x8f8300e4,
-0x27623ff8, 0x10620004, 0x24620008, 0xaf8200e4,
-0x3e00008, 0xaf8200e8, 0x27623000, 0xaf8200e4,
-0x3e00008, 0xaf8200e8, 0x3e00008, 0x0,
-0x27bdffd0, 0xafbf0028, 0x8f4c004c, 0x8f4d0048,
-0xafb00024, 0x118d0026, 0x1ac4023, 0x8f490054,
-0x5020001, 0x25080200, 0x189102b, 0x14400003,
-0x24020200, 0x8004abe, 0x4c5023, 0x12c5023,
-0x254affff, 0x10a102a, 0x54400001, 0x1005021,
-0x14c8021, 0x321001ff, 0x8f45017c, 0x8f440178,
-0xc1140, 0xa22821, 0x3406ecc0, 0xc23021,
-0x2e63021, 0xa3940, 0x24031000, 0xafa30010,
-0x8f430108, 0xafb00014, 0x8f420014, 0x60f809,
-0xafa20018, 0x10400002, 0x8fbf0028, 0xaf50004c,
-0x120d0003, 0x8fb00024, 0x3e00008, 0x27bd0030,
-0xaf800048, 0x8f820048, 0x0, 0x1040fffc,
-0x8f820060, 0x2403fdff, 0x431024, 0xaf820060,
-0xaf800048, 0x3e00008, 0x27bd0030, 0x3e00008,
+0x27623ff8, 0x10620004, 0x24620008, 0xaf8200e8,
+0x3e00008, 0xaf8200e4, 0x27623000, 0xaf8200e8,
+0x3e00008, 0xaf8200e4, 0x3e00008, 0x0,
0x0, 0x0, 0x0, 0x8f880120,
0x27624fe0, 0x8f830128, 0x15020002, 0x25090020,
0x27694800, 0x11230012, 0x8fa20010, 0xad040000,
@@ -8284,7 +9185,11 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
0x0, 0x74785278, 0x4266537a, 0x0,
0x62664174, 0x6e4d726b, 0x0, 0x7265645a,
0x6f6e6531, 0x0, 0x70636943, 0x6f6e6600,
-0x67656e43, 0x6f6e6600, 0x72636246, 0x6c616773,
+0x67656e43, 0x6f6e6600, 0x2a646d61, 0x5244666c,
+0x0, 0x2a50414e, 0x49432a00, 0x2e2e2f2e,
+0x2e2f2e2e, 0x2f2e2e2f, 0x2e2e2f73, 0x72632f6e,
+0x69632f66, 0x77322f63, 0x6f6d6d6f, 0x6e2f6677,
+0x6d61696e, 0x2e630000, 0x72636246, 0x6c616773,
0x0, 0x62616452, 0x78526362, 0x0,
0x676c6f62, 0x466c6773, 0x0, 0x2b5f6469,
0x73705f6c, 0x6f6f7000, 0x2b65765f, 0x68616e64,
@@ -8321,12 +9226,14 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
0x5f74785f, 0x636f6e73, 0x0, 0x2b685f64,
0x6f5f7570, 0x64617465, 0x5f72785f, 0x70726f64,
0x0, 0x2b636b73, 0x756d3136, 0x0,
+0x2b706565, 0x6b5f6d61, 0x635f7278, 0x5f776100,
0x2b706565, 0x6b5f6d61, 0x635f7278, 0x0,
0x2b646571, 0x5f6d6163, 0x5f727800, 0x2b685f6d,
0x61635f72, 0x785f6174, 0x746e0000, 0x62616452,
0x6574537a, 0x0, 0x72784264, 0x4266537a,
0x0, 0x2b6e756c, 0x6c5f6861, 0x6e646c65,
0x72000000, 0x66774f70, 0x4661696c, 0x0,
+0x2b685f75, 0x70646174, 0x655f6c65, 0x64340000,
0x2b685f75, 0x70646174, 0x655f6c65, 0x64360000,
0x2b685f75, 0x70646174, 0x655f6c65, 0x64320000,
0x696e7453, 0x74617465, 0x0, 0x2a2a696e,
@@ -8369,12 +9276,12 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
0x0, 0x3f636d64, 0x48737453, 0x0,
0x3f636d64, 0x4d634d64, 0x0, 0x3f636d64,
0x50726f6d, 0x0, 0x3f636d64, 0x4c696e6b,
-0x0, 0x3f636d64, 0x45727200, 0x80fc,
-0x8878, 0x8878, 0x8800, 0x85a4,
-0x884c, 0x8878, 0x81d4, 0x8238,
-0x83bc, 0x8494, 0x8460, 0x8878,
-0x829c, 0x8550, 0x8878, 0x8560,
-0x81f8, 0x825c, 0x0, 0x0,
+0x0, 0x3f636d64, 0x45727200, 0x864c,
+0x8de0, 0x8de0, 0x8d68, 0x8b0c,
+0x8db4, 0x8de0, 0x8724, 0x8794,
+0x8924, 0x89fc, 0x89c8, 0x8de0,
+0x8804, 0x8ab8, 0x8de0, 0x8ac8,
+0x8748, 0x87b8, 0x0, 0x0,
0x0, 0x24486561, 0x6465723a, 0x202f7072,
0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
@@ -8425,10 +9332,10 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
0x2e313220, 0x31393939, 0x2f30312f, 0x32302031,
0x393a3439, 0x3a353120, 0x73687561, 0x6e672045,
0x78702024, 0x0, 0x46575f56, 0x45525349,
-0x4f4e3a20, 0x23312054, 0x68752041, 0x75672031,
-0x32203135, 0x3a35323a, 0x32392050, 0x44542031,
+0x4f4e3a20, 0x23312053, 0x61742044, 0x65632031,
+0x31203136, 0x3a30353a, 0x30332050, 0x53542031,
0x39393900, 0x46575f43, 0x4f4d5049, 0x4c455f54,
-0x494d453a, 0x2031353a, 0x35323a32, 0x39000000,
+0x494d453a, 0x2031363a, 0x30353a30, 0x33000000,
0x46575f43, 0x4f4d5049, 0x4c455f42, 0x593a2064,
0x65767263, 0x73000000, 0x46575f43, 0x4f4d5049,
0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465,
@@ -8436,7 +9343,7 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
0x4f4d4149, 0x4e3a2065, 0x6e672e61, 0x6374656f,
0x6e2e636f, 0x6d000000, 0x46575f43, 0x4f4d5049,
0x4c45523a, 0x20676363, 0x20766572, 0x73696f6e,
-0x20322e37, 0x2e320000, 0x0, 0x12030303,
+0x20322e37, 0x2e320000, 0x0, 0x12040100,
0x0, 0x24486561, 0x6465723a, 0x202f7072,
0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
@@ -8466,15 +9373,15 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
0x4d657674, 0x526e6746, 0x0, 0x4d516576,
0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
-0x51725072, 0x6f644600, 0x72784672, 0x6d324c67,
-0x0, 0x72784e6f, 0x53744264, 0x0,
-0x72784e6f, 0x4d694264, 0x0, 0x72784e6f,
-0x4a6d4264, 0x0, 0x7278436b, 0x446d6146,
-0x0, 0x72785144, 0x6d457846, 0x0,
-0x72785144, 0x6d614600, 0x72785144, 0x4c426446,
-0x0, 0x72785144, 0x6d426446, 0x0,
-0x72784372, 0x63506164, 0x0, 0x72536d51,
-0x446d6146, 0x0, 0x0, 0x0,
+0x51725072, 0x6f644600, 0x724d6163, 0x43686b30,
+0x0, 0x72784672, 0x6d324c67, 0x0,
+0x72784e6f, 0x53744264, 0x0, 0x72784e6f,
+0x4d694264, 0x0, 0x72784e6f, 0x4a6d4264,
+0x0, 0x7278436b, 0x446d6146, 0x0,
+0x72785144, 0x6d457846, 0x0, 0x72785144,
+0x6d614600, 0x72785144, 0x4c426446, 0x0,
+0x72785144, 0x6d426446, 0x0, 0x72784372,
+0x63506164, 0x0, 0x72536d51, 0x446d6146,
0x0, 0x24486561, 0x6465723a, 0x202f7072,
0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
@@ -8504,30 +9411,38 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
0x51725072, 0x6f644600, 0x0, 0x0,
0x0, 0x50726f62, 0x65506879, 0x0,
-0x6c6e6b41, 0x53535254, 0x0, 0xfc78,
-0xfca8, 0xfcc0, 0xfcec, 0xfd18,
-0xfd2c, 0xfd68, 0x10108, 0xfee8,
-0xff20, 0xfe18, 0xff74, 0xff9c,
-0xffd0, 0xfe5c, 0x10108, 0xfee8,
-0xff20, 0xff44, 0xff74, 0xff9c,
-0xffd0, 0xfffc, 0x0, 0x0,
-0x0, 0x106ec, 0x107bc, 0x10894,
-0x10964, 0x109c0, 0x10a9c, 0x10ac4,
-0x10ba0, 0x10bc8, 0x10d70, 0x10d98,
-0x10f40, 0x11138, 0x113cc, 0x112e0,
-0x113cc, 0x113f8, 0x10f68, 0x11110,
-0x0, 0x116fc, 0x1173c, 0x117cc,
-0x11810, 0x11874, 0x11900, 0x11934,
-0x119bc, 0x11a54, 0x11b24, 0x11b64,
-0x11be8, 0x11c0c, 0x11d1c, 0x646f4261,
+0x6c6e6b41, 0x53535254, 0x0, 0x108d0,
+0x10948, 0x10968, 0x109a4, 0x10ea8,
+0x109d0, 0x10a0c, 0x10f3c, 0x10c18,
+0x10ac0, 0x10ad8, 0x10b1c, 0x10b44,
+0x10b64, 0x10b8c, 0x10f3c, 0x10c18,
+0x10c50, 0x10c68, 0x10c98, 0x10cc0,
+0x10ce0, 0x10d08, 0x0, 0x10e34,
+0x10e60, 0x10e84, 0x10f3c, 0x10ea8,
+0x109d0, 0x10ed8, 0x0, 0x0,
+0x0, 0x115ac, 0x1167c, 0x11754,
+0x11824, 0x11880, 0x1195c, 0x11984,
+0x11a60, 0x11a88, 0x11c30, 0x11c58,
+0x11e00, 0x11ff8, 0x1228c, 0x121a0,
+0x1228c, 0x122b8, 0x11e28, 0x11fd0,
+0x7273745f, 0x676d6969, 0x0, 0x12348,
+0x12380, 0x12468, 0x13034, 0x135fc,
+0x13614, 0x13c7c, 0x13cbc, 0x13d4c,
+0x13d90, 0x13df4, 0x13e80, 0x13eb4,
+0x13f3c, 0x13fd4, 0x140a4, 0x140e4,
+0x14168, 0x1418c, 0x1429c, 0x646f4261,
0x73655067, 0x0, 0x0, 0x0,
0x0, 0x73746d61, 0x634c4e4b, 0x0,
+0x6765746d, 0x636c6e6b, 0x0, 0x14fb4,
+0x14fb4, 0x14ce4, 0x14d34, 0x14d78,
+0x14fb4, 0x7365746d, 0x61636163, 0x74000000,
0x0, 0x0 };
u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __initdata = {
0x1,
0x1, 0x1, 0xc001fc, 0x3ffc,
0xc00000, 0x416c7465, 0x6f6e2041, 0x63654e49,
-0x43205600, 0x0, 0x0, 0x416c7465,
+0x43205600, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x416c7465,
0x6f6e2041, 0x63654e49, 0x43205600, 0x42424242,
0x0, 0x0, 0x0, 0x1ffffc,
0x1fff7c, 0x0, 0x0, 0x0,
@@ -8538,13 +9453,17 @@ u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __initdata = {
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x3, 0x0,
-0x1, 0x0, 0x0, 0x1,
+0x1, 0x0, 0x0, 0x0,
+0x1, 0x0, 0x1, 0x0,
0x0, 0x0, 0x0, 0x1,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x1000000, 0x21000000, 0x12000140,
-0x0, 0x0, 0x20000000, 0x120000a0,
-0x0, 0x12000060, 0x12000180, 0x120001e0,
-0x0, 0x0, 0x0, 0x0,
+0x1, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x1000000, 0x21000000,
+0x12000140, 0x0, 0x0, 0x20000000,
+0x120000a0, 0x0, 0x12000060, 0x12000180,
+0x120001e0, 0x0, 0x0, 0x0,
+0x1, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x2,
0x0, 0x0, 0x30001, 0x1,
-0x30201, 0x0, 0x0, 0x0 };
+0x30201, 0x0, 0x0, 0x1010101,
+0x1010100, 0x10100, 0x1010001, 0x10001,
+0x1000101, 0x101, 0x0, 0x0 };
diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c
index 1fc708ee1..0829bd82e 100644
--- a/drivers/net/arcnet/arc-rimi.c
+++ b/drivers/net/arcnet/arc-rimi.c
@@ -2,7 +2,7 @@
* Linux ARCnet driver - "RIM I" (entirely mem-mapped) cards
*
* Written 1994-1999 by Avery Pennarun.
- * Written 1999 by Martin Mares <mj@suse.cz>.
+ * Written 1999-2000 by Martin Mares <mj@suse.cz>.
* Derived from skeleton.c by Donald Becker.
*
* Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
@@ -325,20 +325,11 @@ void cleanup_module(void)
{
struct net_device *dev = my_dev;
struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
- void *ioaddr = lp->mem_start + 0x800;
-
- if (dev->start)
- dev->stop(dev);
-
- /* Flush TX and disable RX */
- AINTMASK(0); /* disable IRQ's */
- ACOMMAND(NOTXcmd); /* stop transmit */
- ACOMMAND(NORXcmd); /* disable receive */
+ unregister_netdev(dev);
free_irq(dev->irq, dev);
iounmap(lp->mem_start);
release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
- unregister_netdev(dev);
kfree(dev->priv);
kfree(dev);
}
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 98b2ac4da..1608b8bdd 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -3,7 +3,7 @@
*
* Written 1997 by David Woodhouse.
* Written 1994-1999 by Avery Pennarun.
- * Written 1999 by Martin Mares <mj@suse.cz>.
+ * Written 1999-2000 by Martin Mares <mj@suse.cz>.
* Derived from skeleton.c by Donald Becker.
*
* Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
@@ -41,7 +41,7 @@
* <jojo@repas.de>
*/
-#define VERSION "arcnet: v3.91 BETA 99/12/18 - by Avery Pennarun et al.\n"
+#define VERSION "arcnet: v3.92 BETA 2000/02/13 - by Avery Pennarun et al.\n"
#include <linux/module.h>
#include <linux/config.h>
@@ -97,6 +97,7 @@ EXPORT_SYMBOL(arcnet_interrupt);
static int arcnet_open(struct net_device *dev);
static int arcnet_close(struct net_device *dev);
static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev);
+static void arcnet_timeout(struct net_device *dev);
static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, void *daddr, void *saddr,
unsigned len);
@@ -347,6 +348,7 @@ void arcdev_setup(struct net_device *dev)
dev->addr_len = 1;
dev->tx_queue_len = 30;
dev->broadcast[0] = 0x00; /* for us, broadcasts are address 0 */
+ dev->watchdog_timeo = TX_TIMEOUT;
/* New-style flags. */
dev->flags = IFF_BROADCAST;
@@ -358,6 +360,7 @@ void arcdev_setup(struct net_device *dev)
dev->open = arcnet_open;
dev->stop = arcnet_close;
dev->hard_start_xmit = arcnet_send_packet;
+ dev->tx_timeout = arcnet_timeout;
dev->get_stats = arcnet_get_stats;
dev->hard_header = arcnet_header;
dev->rebuild_header = arcnet_rebuild_header;
@@ -397,10 +400,6 @@ static int arcnet_open(struct net_device *dev)
if (ARCRESET(0) && ARCRESET(1))
return -ENODEV;
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 0;
-
newmtu = choose_mtu();
if (newmtu < dev->mtu)
dev->mtu = newmtu;
@@ -441,9 +440,6 @@ static int arcnet_open(struct net_device *dev)
if (ASTATUS() & RESETflag)
ACOMMAND(CFLAGScmd | RESETclear);
- /* we're started */
- dev->start = 1;
-
/* make sure we're ready to receive IRQ's. */
AINTMASK(0);
udelay(1); /* give it time to set the mask before
@@ -453,6 +449,8 @@ static int arcnet_open(struct net_device *dev)
lp->intmask = NORXflag | RECONflag;
AINTMASK(lp->intmask);
+ netif_start_queue(dev);
+
return 0;
}
@@ -462,16 +460,14 @@ static int arcnet_close(struct net_device *dev)
{
struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ netif_stop_queue(dev);
+
/* flush TX and disable RX */
AINTMASK(0);
ACOMMAND(NOTXcmd); /* stop transmit */
ACOMMAND(NORXcmd); /* disable receive */
mdelay(1);
- dev->tbusy = 1;
- dev->start = 0;
- dev->interrupt = 0;
-
/* shut down the card */
ARCOPEN(0);
@@ -584,48 +580,6 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
"transmit requested (status=%Xh, txbufs=%d/%d, len=%d)\n",
ASTATUS(), lp->cur_tx, lp->next_tx, skb->len);
- if (dev->tbusy) {
- /*
- * If we get here, some higher level has decided we are broken.
- * There should really be a "kick me" function call instead.
- */
- unsigned long flags;
- int tickssofar = jiffies - dev->trans_start, status = ASTATUS();
-
- if (tickssofar < TX_TIMEOUT) {
- BUGMSG(D_DURING, "premature kickme! (status=%Xh ticks=%d)\n",
- status, tickssofar);
- return 1; /* means "try again" */
- }
- save_flags(flags);
- cli();
-
- if (status & TXFREEflag) { /* transmit _DID_ finish */
- BUGMSG(D_NORMAL, "tx timeout - missed IRQ? (status=%Xh, ticks=%d, mask=%Xh, dest=%02Xh)\n",
- status, tickssofar, lp->intmask, lp->lasttrans_dest);
- lp->stats.tx_errors++;
- } else {
- BUGMSG(D_EXTRA, "tx timed out (status=%Xh, tickssofar=%d, intmask=%Xh, dest=%02Xh)\n",
- status, tickssofar, lp->intmask, lp->lasttrans_dest);
- lp->stats.tx_errors++;
- lp->stats.tx_aborted_errors++;
-
- ACOMMAND(NOTXcmd | (lp->cur_tx << 3));
- }
-
- /*
- * interrupt handler will set dev->tbusy = 0 when it notices the
- * transmit has been canceled.
- */
-
- /* make sure we didn't miss a TX IRQ */
- AINTMASK(0);
- lp->intmask |= TXFREEflag;
- AINTMASK(lp->intmask);
-
- restore_flags(flags);
- return 1;
- }
pkt = (struct archdr *) skb->data;
soft = &pkt->soft.rfc1201;
proto = arc_proto_map[soft->proto];
@@ -638,18 +592,10 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb(skb);
return 0; /* don't try again */
}
- /*
- * Block a timer-based transmit from overlapping. This could better be
- * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
- */
- if (test_and_set_bit(0, (int *) &dev->tbusy)) {
- BUGMSG(D_NORMAL, "transmitter called with busy bit set! "
- "(status=%Xh, tickssofar=%ld)\n",
- ASTATUS(), jiffies - dev->trans_start);
- lp->stats.tx_errors++;
- lp->stats.tx_fifo_errors++;
- return 0; /* don't try again */
- }
+
+ /* We're busy transmitting a packet... */
+ netif_stop_queue(dev);
+
AINTMASK(0);
txbuf = get_arcbuf(dev);
@@ -718,6 +664,37 @@ static int go_tx(struct net_device *dev)
}
+/* Called by the kernel when transmit times out */
+static void arcnet_timeout(struct net_device *dev)
+{
+ unsigned long flags;
+ struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ int status = ASTATUS();
+
+ save_flags(flags);
+ cli();
+
+ if (status & TXFREEflag) { /* transmit _DID_ finish */
+ BUGMSG(D_NORMAL, "tx timeout - missed IRQ? (status=%Xh, mask=%Xh, dest=%02Xh)\n",
+ status, lp->intmask, lp->lasttrans_dest);
+ lp->stats.tx_errors++;
+ } else {
+ BUGMSG(D_EXTRA, "tx timed out (status=%Xh, intmask=%Xh, dest=%02Xh)\n",
+ status, lp->intmask, lp->lasttrans_dest);
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
+ ACOMMAND(NOTXcmd | (lp->cur_tx << 3));
+ }
+
+ /* make sure we didn't miss a TX IRQ */
+ AINTMASK(0);
+ lp->intmask |= TXFREEflag;
+ AINTMASK(lp->intmask);
+
+ restore_flags(flags);
+}
+
+
/*
* The typical workload of the driver: Handle the network interface
* interrupts. Establish which device needs attention, and call the correct
@@ -743,25 +720,20 @@ void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
return;
}
/*
- * RESET flag was enabled - if !dev->start, we must clear it right
+ * RESET flag was enabled - if device is not running, we must clear it right
* away (but nothing else).
*/
- if (!dev->start) {
+ if (!netif_running(dev)) {
if (ASTATUS() & RESETflag)
ACOMMAND(CFLAGScmd | RESETclear);
AINTMASK(0);
return;
}
- if (dev->interrupt) {
- BUGMSG(D_NORMAL, "DRIVER PROBLEM! Nested arcnet interrupts!\n");
- return; /* don't even try. */
- }
- dev->interrupt = 1;
BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n",
ASTATUS(), lp->intmask);
- boguscount = 3;
+ boguscount = 5;
do {
status = ASTATUS();
didsomething = 0;
@@ -839,17 +811,15 @@ void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (lp->outgoing.proto->continue_tx(dev, txbuf)) {
/* that was the last segment */
lp->stats.tx_bytes += lp->outgoing.skb->len;
- dev_kfree_skb(lp->outgoing.skb);
+ dev_kfree_skb_irq(lp->outgoing.skb);
lp->outgoing.proto = NULL;
}
lp->next_tx = txbuf;
}
}
/* inform upper layers of idleness, if necessary */
- if (lp->cur_tx == -1) {
- dev->tbusy = 0;
- mark_bh(NET_BH);
- }
+ if (lp->cur_tx == -1)
+ netif_wake_queue(dev);
}
/* now process the received packet, if any */
if (recbuf != -1) {
@@ -922,8 +892,6 @@ void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
AINTMASK(0);
udelay(1);
AINTMASK(lp->intmask);
-
- dev->interrupt = 0;
}
@@ -987,11 +955,6 @@ void arcnet_rx(struct net_device *dev, int bufnum)
}
/* call the protocol-specific receiver. */
arc_proto_map[soft->proto]->rx(dev, bufnum, &pkt, length);
-
- /*
- * If any worthwhile packets have been received, a mark_bh(NET_BH) has
- * been done by netif_rx and Linux will handle them after we return.
- */
}
diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c
index 94c68901b..7bd06e2e4 100644
--- a/drivers/net/arcnet/com20020-isa.c
+++ b/drivers/net/arcnet/com20020-isa.c
@@ -3,7 +3,7 @@
*
* Written 1997 by David Woodhouse.
* Written 1994-1999 by Avery Pennarun.
- * Written 1999 by Martin Mares <mj@suse.cz>.
+ * Written 1999-2000 by Martin Mares <mj@suse.cz>.
* Derived from skeleton.c by Donald Becker.
*
* Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
@@ -176,12 +176,9 @@ void cleanup_module(void)
{
struct net_device *dev = my_dev;
- if (dev->start)
- dev->stop(dev);
-
+ unregister_netdev(dev);
free_irq(dev->irq, dev);
release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
- unregister_netdev(dev);
kfree(dev->priv);
kfree(dev);
}
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
index 585308c27..b88203f54 100644
--- a/drivers/net/arcnet/com20020-pci.c
+++ b/drivers/net/arcnet/com20020-pci.c
@@ -3,7 +3,7 @@
*
* Written 1994-1999 by Avery Pennarun,
* based on an ISA version by David Woodhouse.
- * Written 1999 by Martin Mares <mj@suse.cz>.
+ * Written 1999-2000 by Martin Mares <mj@suse.cz>.
* Derived from skeleton.c by Donald Becker.
*
* Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
@@ -148,13 +148,9 @@ void cleanup_module(void)
for (count = 0; count < numcards; count++) {
dev = cards[count];
-
- if (dev->start)
- dev->stop(dev);
-
+ unregister_netdev(dev);
free_irq(dev->irq, dev);
release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
- unregister_netdev(dev);
kfree(dev->priv);
kfree(dev);
}
diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c
index edd92ff25..79800883f 100644
--- a/drivers/net/arcnet/com90io.c
+++ b/drivers/net/arcnet/com90io.c
@@ -3,7 +3,7 @@
*
* Written 1997 by David Woodhouse.
* Written 1994-1999 by Avery Pennarun.
- * Written 1999 by Martin Mares <mj@suse.cz>.
+ * Written 1999-2000 by Martin Mares <mj@suse.cz>.
* Derived from skeleton.c by Donald Becker.
*
* Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
@@ -406,20 +406,13 @@ void cleanup_module(void)
struct net_device *dev = my_dev;
int ioaddr = dev->base_addr;
- if (dev->start)
- dev->stop(dev);
-
- /* Flush TX and disable RX */
- AINTMASK(0); /* disable IRQ's */
- ACOMMAND(NOTXcmd); /* stop transmit */
- ACOMMAND(NORXcmd); /* disable receive */
+ unregister_netdev(dev);
/* Set the thing back to MMAP mode, in case the old driver is loaded later */
outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG);
free_irq(dev->irq, dev);
release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
- unregister_netdev(dev);
kfree(dev->priv);
kfree(dev);
}
diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c
index 843115609..ac8790ef0 100644
--- a/drivers/net/arcnet/com90xx.c
+++ b/drivers/net/arcnet/com90xx.c
@@ -143,7 +143,7 @@ int __init com90xx_probe(struct net_device *dev)
numprint %= 8;
if (!numprint) {
BUGMSG2(D_INIT, "\n");
- BUGMSG(D_INIT, "S1: ");
+ BUGMSG2(D_INIT, "S1: ");
}
BUGMSG2(D_INIT, "%Xh ", *port);
@@ -151,7 +151,7 @@ int __init com90xx_probe(struct net_device *dev)
if (check_region(*port, ARCNET_TOTAL_SIZE)) {
BUGMSG2(D_INIT_REASONS, "(check_region)\n");
- BUGMSG(D_INIT_REASONS, "S1: ");
+ BUGMSG2(D_INIT_REASONS, "S1: ");
BUGLVL(D_INIT_REASONS) numprint = 0;
*port = ports[numports - 1];
numports--;
@@ -160,7 +160,7 @@ int __init com90xx_probe(struct net_device *dev)
}
if (ASTATUS() == 0xFF) {
BUGMSG2(D_INIT_REASONS, "(empty)\n");
- BUGMSG(D_INIT_REASONS, "S1: ");
+ BUGMSG2(D_INIT_REASONS, "S1: ");
BUGLVL(D_INIT_REASONS) numprint = 0;
*port = ports[numports - 1];
numports--;
@@ -170,13 +170,13 @@ int __init com90xx_probe(struct net_device *dev)
inb(_RESET); /* begin resetting card */
BUGMSG2(D_INIT_REASONS, "\n");
- BUGMSG(D_INIT_REASONS, "S1: ");
+ BUGMSG2(D_INIT_REASONS, "S1: ");
BUGLVL(D_INIT_REASONS) numprint = 0;
}
BUGMSG2(D_INIT, "\n");
if (!numports) {
- BUGMSG(D_NORMAL, "S1: No ARCnet cards found.\n");
+ BUGMSG2(D_NORMAL, "S1: No ARCnet cards found.\n");
return -ENODEV;
}
/* Stage 2: we have now reset any possible ARCnet cards, so we can't
@@ -189,7 +189,7 @@ int __init com90xx_probe(struct net_device *dev)
numprint %= 8;
if (!numprint) {
BUGMSG2(D_INIT, "\n");
- BUGMSG(D_INIT, "S2: ");
+ BUGMSG2(D_INIT, "S2: ");
}
BUGMSG2(D_INIT, "%Xh ", *port);
}
@@ -207,13 +207,13 @@ int __init com90xx_probe(struct net_device *dev)
numprint %= 8;
if (!numprint) {
BUGMSG2(D_INIT, "\n");
- BUGMSG(D_INIT, "S3: ");
+ BUGMSG2(D_INIT, "S3: ");
}
BUGMSG2(D_INIT, "%lXh ", *shmem);
if (check_mem_region(*shmem, BUFFER_SIZE)) {
BUGMSG2(D_INIT_REASONS, "(check_mem_region)\n");
- BUGMSG(D_INIT_REASONS, "Stage 3: ");
+ BUGMSG2(D_INIT_REASONS, "Stage 3: ");
BUGLVL(D_INIT_REASONS) numprint = 0;
*shmem = shmems[numshmems - 1];
numshmems--;
@@ -223,7 +223,7 @@ int __init com90xx_probe(struct net_device *dev)
if (isa_readb(ptr) != TESTvalue) {
BUGMSG2(D_INIT_REASONS, "(%02Xh != %02Xh)\n",
isa_readb(ptr), TESTvalue);
- BUGMSG(D_INIT_REASONS, "S3: ");
+ BUGMSG2(D_INIT_REASONS, "S3: ");
BUGLVL(D_INIT_REASONS) numprint = 0;
*shmem = shmems[numshmems - 1];
numshmems--;
@@ -238,20 +238,20 @@ int __init com90xx_probe(struct net_device *dev)
isa_writeb(0x42, ptr);
if (isa_readb(ptr) != 0x42) {
BUGMSG2(D_INIT_REASONS, "(read only)\n");
- BUGMSG(D_INIT_REASONS, "S3: ");
+ BUGMSG2(D_INIT_REASONS, "S3: ");
*shmem = shmems[numshmems - 1];
numshmems--;
shmem--;
continue;
}
BUGMSG2(D_INIT_REASONS, "\n");
- BUGMSG(D_INIT_REASONS, "S3: ");
+ BUGMSG2(D_INIT_REASONS, "S3: ");
BUGLVL(D_INIT_REASONS) numprint = 0;
}
BUGMSG2(D_INIT, "\n");
if (!numshmems) {
- BUGMSG(D_NORMAL, "S3: No ARCnet cards found.\n");
+ BUGMSG2(D_NORMAL, "S3: No ARCnet cards found.\n");
return -ENODEV;
}
/* Stage 4: something of a dummy, to report the shmems that are
@@ -263,7 +263,7 @@ int __init com90xx_probe(struct net_device *dev)
numprint %= 8;
if (!numprint) {
BUGMSG2(D_INIT, "\n");
- BUGMSG(D_INIT, "S4: ");
+ BUGMSG2(D_INIT, "S4: ");
}
BUGMSG2(D_INIT, "%lXh ", *shmem);
}
@@ -282,7 +282,7 @@ int __init com90xx_probe(struct net_device *dev)
numprint %= 8;
if (!numprint) {
BUGMSG2(D_INIT, "\n");
- BUGMSG(D_INIT, "S5: ");
+ BUGMSG2(D_INIT, "S5: ");
}
BUGMSG2(D_INIT, "%Xh ", *port);
@@ -292,7 +292,7 @@ int __init com90xx_probe(struct net_device *dev)
if ((status & 0x9D)
!= (NORXflag | RECONflag | TXFREEflag | RESETflag)) {
BUGMSG2(D_INIT_REASONS, "(status=%Xh)\n", status);
- BUGMSG(D_INIT_REASONS, "S5: ");
+ BUGMSG2(D_INIT_REASONS, "S5: ");
BUGLVL(D_INIT_REASONS) numprint = 0;
*port = ports[numports - 1];
numports--;
@@ -304,7 +304,7 @@ int __init com90xx_probe(struct net_device *dev)
if (status & RESETflag) {
BUGMSG2(D_INIT_REASONS, " (eternal reset, status=%Xh)\n",
status);
- BUGMSG(D_INIT_REASONS, "S5: ");
+ BUGMSG2(D_INIT_REASONS, "S5: ");
BUGLVL(D_INIT_REASONS) numprint = 0;
*port = ports[numports - 1];
numports--;
@@ -327,7 +327,7 @@ int __init com90xx_probe(struct net_device *dev)
if (airq <= 0) {
BUGMSG2(D_INIT_REASONS, "(airq=%d)\n", airq);
- BUGMSG(D_INIT_REASONS, "S5: ");
+ BUGMSG2(D_INIT_REASONS, "S5: ");
BUGLVL(D_INIT_REASONS) numprint = 0;
*port = ports[numports - 1];
numports--;
@@ -398,7 +398,7 @@ int __init com90xx_probe(struct net_device *dev)
isa_writeb(TESTvalue, *shmem);
if (retval && dev && !numcards)
- BUGMSG(D_NORMAL, "S5: No ARCnet cards found.\n");
+ BUGMSG2(D_NORMAL, "S5: No ARCnet cards found.\n");
return retval;
}
@@ -416,7 +416,7 @@ static int __init com90xx_found(struct net_device *dev0, int ioaddr, int airq,
/* allocate struct net_device if we don't have one yet */
if (!dev && !(dev = dev_alloc("arc%d", &err))) {
- BUGMSG(D_NORMAL, "Can't allocate device!\n");
+ BUGMSG2(D_NORMAL, "com90xx: Can't allocate device!\n");
return err;
}
lp = dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
@@ -546,8 +546,7 @@ int com90xx_reset(struct net_device *dev, int really_reset)
struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
short ioaddr = dev->base_addr;
- BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n",
- dev->name, ASTATUS());
+ BUGMSG(D_INIT, "Resetting (status=%02Xh)\n", ASTATUS());
if (really_reset) {
/* reset the card */
@@ -653,13 +652,11 @@ void cleanup_module(void)
dev = cards[count];
lp = (struct arcnet_local *) dev->priv;
- if (dev->start)
- dev->stop(dev);
+ unregister_netdev(dev);
free_irq(dev->irq, dev);
iounmap(lp->mem_start);
release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
- unregister_netdev(dev);
kfree(dev->priv);
kfree(dev);
}
diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c
index 759263ca0..92d026ec8 100644
--- a/drivers/net/arcnet/rfc1201.c
+++ b/drivers/net/arcnet/rfc1201.c
@@ -171,7 +171,7 @@ static void rx(struct net_device *dev, int bufnum,
BUGMSG(D_EXTRA, "aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
in->sequence, soft->split_flag, soft->sequence);
lp->rfc1201.aborted_seq = soft->sequence;
- kfree_skb(in->skb);
+ dev_kfree_skb_irq(in->skb);
lp->stats.rx_errors++;
lp->stats.rx_missed_errors++;
in->skb = NULL;
@@ -255,7 +255,7 @@ static void rx(struct net_device *dev, int bufnum,
BUGMSG(D_EXTRA, "wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
saddr, in->sequence, soft->sequence,
soft->split_flag);
- kfree_skb(in->skb);
+ dev_kfree_skb_irq(in->skb);
in->skb = NULL;
lp->stats.rx_errors++;
lp->stats.rx_missed_errors++;
@@ -271,7 +271,7 @@ static void rx(struct net_device *dev, int bufnum,
soft->sequence);
lp->stats.rx_errors++;
lp->stats.rx_missed_errors++;
- kfree_skb(in->skb);
+ dev_kfree_skb_irq(in->skb);
}
in->sequence = soft->sequence;
in->numpackets = ((unsigned) soft->split_flag >> 1) + 2;
@@ -332,7 +332,7 @@ static void rx(struct net_device *dev, int bufnum,
"(seq=%d) aborted (splitflag=%d, seq=%d)\n",
in->sequence, soft->split_flag, soft->sequence);
lp->rfc1201.aborted_seq = soft->sequence;
- kfree_skb(in->skb);
+ dev_kfree_skb_irq(in->skb);
in->skb = NULL;
lp->stats.rx_errors++;
lp->stats.rx_missed_errors++;
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index 099bd1300..89d5fd599 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -160,6 +160,16 @@ int __init ariadne_probe(struct net_device *dev)
continue;
}
strcpy(z->name, "Ariadne Ethernet Card and Parallel Ports");
+
+ dev = init_etherdev(NULL, sizeof(struct ariadne_private));
+
+ if (dev == NULL) {
+ release_mem_region(base_addr, sizeof(struct Am79C960));
+ release_mem_region(ram_start, ARIADNE_RAM_SIZE);
+ return -ENOMEM;
+ }
+ memset(dev->priv, 0, sizeof(struct ariadne_private));
+
dev->dev_addr[0] = 0x00;
dev->dev_addr[1] = 0x60;
dev->dev_addr[2] = 0x30;
@@ -171,16 +181,6 @@ int __init ariadne_probe(struct net_device *dev)
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
- init_etherdev(dev, 0);
-
- dev->priv = kmalloc(sizeof(struct ariadne_private), GFP_KERNEL);
- if (dev->priv == NULL) {
- release_mem_region(base_addr, sizeof(struct Am79C960));
- release_mem_region(ram_start, ARIADNE_RAM_SIZE);
- return -ENOMEM;
- }
- memset(dev->priv, 0, sizeof(struct ariadne_private));
-
dev->base_addr = ZTWO_VADDR(base_addr);
dev->mem_start = ZTWO_VADDR(ram_start);
dev->mem_end = dev->mem_start+ARIADNE_RAM_SIZE;
diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
index a028b159e..4c8723efa 100644
--- a/drivers/net/at1700.c
+++ b/drivers/net/at1700.c
@@ -111,6 +111,7 @@ typedef unsigned char uchar;
/* Information that need to be kept for each board. */
struct net_local {
struct enet_statistics stats;
+ spinlock_t lock;
unsigned char mc_filter[8];
uint jumpered:1; /* Set iff the board has jumper config. */
uint tx_started:1; /* Packets are on the Tx queue. */
@@ -148,6 +149,10 @@ struct net_local {
#define SAPROM 20 /* The station address PROM, if no EEPROM. */
#define RESET 31 /* Write to reset some parts of the chip. */
#define AT1700_IO_EXTENT 32
+
+#define TX_TIMEOUT 10
+
+
/* Index to functions, as function prototypes. */
extern int at1700_probe(struct net_device *dev);
@@ -161,6 +166,7 @@ static void net_rx(struct net_device *dev);
static int net_close(struct net_device *dev);
static struct enet_statistics *net_get_stats(struct net_device *dev);
static void set_rx_mode(struct net_device *dev);
+static void net_tx_timeout (struct net_device *dev);
#ifdef CONFIG_MCA
@@ -228,6 +234,7 @@ int at1700_probe1(struct net_device *dev, int ioaddr)
char at1700_irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15};
unsigned int i, irq, is_fmv18x = 0, is_at1700 = 0;
int slot;
+ struct net_local *lp;
/* Resetting the chip doesn't reset the ISA interface, so don't bother.
That means we have to be careful with the register values we probe for.
@@ -427,21 +434,23 @@ found:
dev->hard_start_xmit = net_send_packet;
dev->get_stats = net_get_stats;
dev->set_multicast_list = &set_rx_mode;
+ dev->tx_timeout = net_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
+ lp = (struct net_local *)dev->priv;
+ lp->lock = SPIN_LOCK_UNLOCKED;
/* Fill in the fields of 'dev' with ethernet-generic values. */
ether_setup(dev);
- {
- struct net_local *lp = (struct net_local *)dev->priv;
- lp->jumpered = is_fmv18x;
- lp->mca_slot = slot;
- /* Snarf the interrupt vector now. */
- if (request_irq(irq, &net_interrupt, 0, dev->name, dev)) {
- printk (" AT1700 at %#3x is unusable due to a conflict on"
- "IRQ %d.\n", ioaddr, irq);
- lp->invalid_irq = 1;
- return 0;
- }
+ lp->jumpered = is_fmv18x;
+ lp->mca_slot = slot;
+ /* Snarf the interrupt vector now. */
+ if (request_irq(irq, &net_interrupt, 0, dev->name, dev)) {
+ printk (" AT1700 at %#3x is unusable due to a conflict on"
+ "IRQ %d.\n", ioaddr, irq);
+ lp->invalid_irq = 1;
+ return 0;
}
return 0;
@@ -525,86 +534,81 @@ static int net_open(struct net_device *dev)
outb(0x80, ioaddr + IOCONFIG1);
}
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue(dev);
MOD_INC_USE_COUNT;
return 0;
}
-static int
-net_send_packet(struct sk_buff *skb, struct net_device *dev)
+static void net_tx_timeout (struct net_device *dev)
{
struct net_local *lp = (struct net_local *)dev->priv;
int ioaddr = dev->base_addr;
- if (dev->tbusy) {
- /* If we get here, some higher level has decided we are broken.
- There should really be a "kick me" function call instead. */
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 10)
- return 1;
- printk("%s: transmit timed out with status %04x, %s?\n", dev->name,
- inw(ioaddr + STATUS), inb(ioaddr + TX_STATUS) & 0x80
- ? "IRQ conflict" : "network cable problem");
- printk("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
- dev->name, inw(ioaddr + 0), inw(ioaddr + 2), inw(ioaddr + 4),
- inw(ioaddr + 6), inw(ioaddr + 8), inw(ioaddr + 10),
- inw(ioaddr + 12), inw(ioaddr + 14));
- lp->stats.tx_errors++;
- /* ToDo: We should try to restart the adaptor... */
- outw(0xffff, ioaddr + 24);
- outw(0xffff, ioaddr + TX_STATUS);
- outw(0xe85a, ioaddr + CONFIG_0);
- outw(0x8182, ioaddr + TX_INTR);
- outb(0x00, ioaddr + TX_START);
- outb(0x03, ioaddr + COL16CNTL);
- dev->tbusy=0;
- dev->trans_start = jiffies;
- lp->tx_started = 0;
- lp->tx_queue_ready = 1;
- lp->rx_started = 0;
- lp->tx_queue = 0;
- lp->tx_queue_len = 0;
- }
+ printk ("%s: transmit timed out with status %04x, %s?\n", dev->name,
+ inw (ioaddr + STATUS), inb (ioaddr + TX_STATUS) & 0x80
+ ? "IRQ conflict" : "network cable problem");
+ printk ("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
+ dev->name, inw (ioaddr + 0), inw (ioaddr + 2), inw (ioaddr + 4),
+ inw (ioaddr + 6), inw (ioaddr + 8), inw (ioaddr + 10),
+ inw (ioaddr + 12), inw (ioaddr + 14));
+ lp->stats.tx_errors++;
+ /* ToDo: We should try to restart the adaptor... */
+ outw (0xffff, ioaddr + 24);
+ outw (0xffff, ioaddr + TX_STATUS);
+ outw (0xe85a, ioaddr + CONFIG_0);
+ outw (0x8182, ioaddr + TX_INTR);
+ outb (0x00, ioaddr + TX_START);
+ outb (0x03, ioaddr + COL16CNTL);
+
+ dev->trans_start = jiffies;
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk("%s: Transmitter access conflict.\n", dev->name);
- else {
- short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned char *buf = skb->data;
-
- /* We may not start transmitting unless we finish transferring
- a packet into the Tx queue. During executing the following
- codes we possibly catch a Tx interrupt. Thus we flag off
- tx_queue_ready, so that we prevent the interrupt routine
- (net_interrupt) to start transmitting. */
- lp->tx_queue_ready = 0;
- {
- outw(length, ioaddr + DATAPORT);
- outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
-
- lp->tx_queue++;
- lp->tx_queue_len += length + 2;
- }
- lp->tx_queue_ready = 1;
-
- if (lp->tx_started == 0) {
- /* If the Tx is idle, always trigger a transmit. */
- outb(0x80 | lp->tx_queue, ioaddr + TX_START);
- lp->tx_queue = 0;
- lp->tx_queue_len = 0;
- dev->trans_start = jiffies;
- lp->tx_started = 1;
- dev->tbusy = 0;
- } else if (lp->tx_queue_len < 4096 - 1502)
- /* Yes, there is room for one more packet. */
- dev->tbusy = 0;
+ lp->tx_started = 0;
+ lp->tx_queue_ready = 1;
+ lp->rx_started = 0;
+ lp->tx_queue = 0;
+ lp->tx_queue_len = 0;
+
+ netif_wake_queue(dev);
+}
+
+
+static int net_send_packet (struct sk_buff *skb, struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *) dev->priv;
+ int ioaddr = dev->base_addr;
+ short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+ unsigned char *buf = skb->data;
+
+ netif_stop_queue (dev);
+
+ /* We may not start transmitting unless we finish transferring
+ a packet into the Tx queue. During executing the following
+ codes we possibly catch a Tx interrupt. Thus we flag off
+ tx_queue_ready, so that we prevent the interrupt routine
+ (net_interrupt) to start transmitting. */
+ lp->tx_queue_ready = 0;
+ {
+ outw (length, ioaddr + DATAPORT);
+ outsw (ioaddr + DATAPORT, buf, (length + 1) >> 1);
+
+ lp->tx_queue++;
+ lp->tx_queue_len += length + 2;
}
+ lp->tx_queue_ready = 1;
+
+ if (lp->tx_started == 0) {
+ /* If the Tx is idle, always trigger a transmit. */
+ outb (0x80 | lp->tx_queue, ioaddr + TX_START);
+ lp->tx_queue = 0;
+ lp->tx_queue_len = 0;
+ dev->trans_start = jiffies;
+ lp->tx_started = 1;
+ netif_start_queue (dev);
+ } else if (lp->tx_queue_len < 4096 - 1502)
+ /* Yes, there is room for one more packet. */
+ netif_start_queue (dev);
dev_kfree_skb (skb);
return 0;
@@ -623,10 +627,12 @@ net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
printk ("at1700_interrupt(): irq %d for unknown device.\n", irq);
return;
}
- dev->interrupt = 1;
ioaddr = dev->base_addr;
lp = (struct net_local *)dev->priv;
+
+ spin_lock (&lp->lock);
+
status = inw(ioaddr + TX_STATUS);
outw(status, ioaddr + TX_STATUS);
@@ -665,17 +671,15 @@ net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
lp->tx_queue = 0;
lp->tx_queue_len = 0;
dev->trans_start = jiffies;
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_wake_queue (dev);
} else {
lp->tx_started = 0;
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_wake_queue (dev);
}
}
}
- dev->interrupt = 0;
+ spin_unlock (&lp->lock);
return;
}
@@ -767,8 +771,7 @@ static int net_close(struct net_device *dev)
struct net_local *lp = (struct net_local *)dev->priv;
int ioaddr = dev->base_addr;
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue(dev);
/* Set configuration register 0 to disable Tx and Rx. */
outb(0xda, ioaddr + CONFIG_0);
diff --git a/drivers/net/atp.c b/drivers/net/atp.c
index 45da37261..1f58b30c4 100644
--- a/drivers/net/atp.c
+++ b/drivers/net/atp.c
@@ -16,6 +16,8 @@
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
The timer-based reset code was written by Bill Carlson, wwc@super.org.
+
+ Modular support/softnet added by Alan Cox.
*/
static const char *version =
@@ -82,6 +84,7 @@ static const char *version =
*/
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/fcntl.h>
@@ -101,6 +104,7 @@ static const char *version =
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+#include <linux/spinlock.h>
#include "atp.h"
@@ -133,9 +137,10 @@ static void get_node_ID(struct net_device *dev);
static unsigned short eeprom_op(short ioaddr, unsigned int cmd);
static int net_open(struct net_device *dev);
static void hardware_init(struct net_device *dev);
+static void tx_timeout(struct net_device *dev);
static void write_packet(short ioaddr, int length, unsigned char *packet, int mode);
static void trigger_send(short ioaddr, int length);
-static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
+static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void net_rx(struct net_device *dev);
static void read_block(short ioaddr, int length, unsigned char *buffer, int data_mode);
@@ -150,8 +155,8 @@ static void set_multicast_list(struct net_device *dev);
If dev->base_addr == 2, allocate space for the device and return success
(detachable devices only).
*/
-int __init
-atp_init(struct net_device *dev)
+
+int __init atp_init(struct net_device *dev)
{
int *port, ports[] = {0x378, 0x278, 0x3bc, 0};
int base_addr = dev->base_addr;
@@ -220,7 +225,7 @@ static int __init atp_probe1(struct net_device *dev, short ioaddr)
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
/* Leave the hardware in a reset state. */
- write_reg_high(ioaddr, CMR1, CMR1h_RESET);
+ write_reg_high(ioaddr, CMR1, CMR1h_RESET);
if (net_debug)
printk(version);
@@ -231,11 +236,10 @@ static int __init atp_probe1(struct net_device *dev, short ioaddr)
if (dev->priv == NULL)
return -ENOMEM;
memset(dev->priv, 0, sizeof(struct net_local));
-
-
{
struct net_local *lp = (struct net_local *)dev->priv;
lp->addr_mode = CMR2h_Normal;
+ spin_lock_init(&lp->lock);
}
/* For the ATP adapter the "if_port" is really the data transfer mode. */
@@ -245,9 +249,11 @@ static int __init atp_probe1(struct net_device *dev, short ioaddr)
dev->open = net_open;
dev->stop = net_close;
- dev->hard_start_xmit = net_send_packet;
- dev->get_stats = net_get_stats;
- dev->set_multicast_list = &set_multicast_list;
+ dev->hard_start_xmit = net_send_packet;
+ dev->get_stats = net_get_stats;
+ dev->set_multicast_list = set_multicast_list;
+ dev->tx_timeout = tx_timeout;
+ dev->watchdog_timeo = HZ/20;
#ifdef TIMED_CHECKER
del_timer(&atp_timer);
@@ -327,12 +333,12 @@ static int net_open(struct net_device *dev)
/* The interrupt line is turned off (tri-stated) when the device isn't in
use. That's especially important for "attached" interfaces where the
port or interrupt may be shared. */
+
if (request_irq(dev->irq, &net_interrupt, 0, "ATP", dev)) {
return -EAGAIN;
}
-
hardware_init(dev);
- dev->start = 1;
+ netif_start_queue(dev);
return 0;
}
@@ -342,11 +348,11 @@ static void hardware_init(struct net_device *dev)
{
struct net_local *lp = (struct net_local *)dev->priv;
int ioaddr = dev->base_addr;
- int i;
+ int i;
write_reg_high(ioaddr, CMR1, CMR1h_RESET);
- for (i = 0; i < 6; i++)
+ for (i = 0; i < 6; i++)
write_reg_byte(ioaddr, PAR0 + i, dev->dev_addr[i]);
write_reg_high(ioaddr, CMR2, lp->addr_mode);
@@ -356,22 +362,19 @@ static void hardware_init(struct net_device *dev)
(read_nibble(ioaddr, CMR2_h) >> 3) & 0x0f);
}
- write_reg(ioaddr, CMR2, CMR2_IRQOUT);
- write_reg_high(ioaddr, CMR1, CMR1h_RxENABLE | CMR1h_TxENABLE);
+ write_reg(ioaddr, CMR2, CMR2_IRQOUT);
+ write_reg_high(ioaddr, CMR1, CMR1h_RxENABLE | CMR1h_TxENABLE);
/* Enable the interrupt line from the serial port. */
outb(Ctrl_SelData + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
/* Unmask the interesting interrupts. */
- write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
- write_reg_high(ioaddr, IMR, ISRh_RxErr);
+ write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
+ write_reg_high(ioaddr, IMR, ISRh_RxErr);
lp->tx_unit_busy = 0;
- lp->pac_cnt_in_tx_buf = 0;
+ lp->pac_cnt_in_tx_buf = 0;
lp->saved_tx_size = 0;
-
- dev->tbusy = 0;
- dev->interrupt = 0;
}
static void trigger_send(short ioaddr, int length)
@@ -383,15 +386,15 @@ static void trigger_send(short ioaddr, int length)
static void write_packet(short ioaddr, int length, unsigned char *packet, int data_mode)
{
- length = (length + 1) & ~1; /* Round up to word length. */
- outb(EOC+MAR, ioaddr + PAR_DATA);
- if ((data_mode & 1) == 0) {
+ length = (length + 1) & ~1; /* Round up to word length. */
+ outb(EOC+MAR, ioaddr + PAR_DATA);
+ if ((data_mode & 1) == 0) {
/* Write the packet out, starting with the write addr. */
outb(WrAddr+MAR, ioaddr + PAR_DATA);
do {
write_byte_mode0(ioaddr, *packet++);
} while (--length > 0) ;
- } else {
+ } else {
/* Write the packet out in slow mode. */
unsigned char outbyte = *packet++;
@@ -405,70 +408,61 @@ static void write_packet(short ioaddr, int length, unsigned char *packet, int da
outb(Ctrl_HNibWrite + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
while (--length > 0)
write_byte_mode1(ioaddr, *packet++);
- }
- /* Terminate the Tx frame. End of write: ECB. */
- outb(0xff, ioaddr + PAR_DATA);
- outb(Ctrl_HNibWrite | Ctrl_SelData | Ctrl_IRQEN, ioaddr + PAR_CONTROL);
+ }
+ /* Terminate the Tx frame. End of write: ECB. */
+ outb(0xff, ioaddr + PAR_DATA);
+ outb(Ctrl_HNibWrite | Ctrl_SelData | Ctrl_IRQEN, ioaddr + PAR_CONTROL);
}
-static int
-net_send_packet(struct sk_buff *skb, struct net_device *dev)
+static void tx_timeout(struct net_device *dev)
{
struct net_local *lp = (struct net_local *)dev->priv;
int ioaddr = dev->base_addr;
+ /* If we get here, some higher level has decided we are broken. */
+ printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
+ inb(ioaddr + PAR_CONTROL) & 0x10 ? "network cable problem"
+ : "IRQ conflict");
+ lp->stats.tx_errors++;
+ /* Try to restart the adapter. */
+ hardware_init(dev);
+ dev->trans_start = jiffies;
+ netif_wake_queue(dev);
+}
- if (dev->tbusy) {
- /* If we get here, some higher level has decided we are broken.
- There should really be a "kick me" function call instead. */
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 5)
- return 1;
- printk("%s: transmit timed out, %s?\n", dev->name,
- inb(ioaddr + PAR_CONTROL) & 0x10 ? "network cable problem"
- : "IRQ conflict");
- lp->stats.tx_errors++;
- /* Try to restart the adapter. */
- hardware_init(dev);
- dev->tbusy=0;
- dev->trans_start = jiffies;
- }
+static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+ short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+ unsigned char *buf = skb->data;
+ unsigned long flags;
+
+ netif_stop_queue(dev);
+
+ /* Disable interrupts by writing 0x00 to the Interrupt Mask Register.
+ This sequence must not be interrupted by an incoming packet. */
+
+ spin_lock_irqsave(&lp->lock, flags);
+ write_reg(ioaddr, IMR, 0);
+ write_reg_high(ioaddr, IMR, 0);
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ write_packet(ioaddr, length, buf, dev->if_port);
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk("%s: Transmitter access conflict.\n", dev->name);
- else {
- short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned char *buf = skb->data;
- int flags;
-
- /* Disable interrupts by writing 0x00 to the Interrupt Mask Register.
- This sequence must not be interrupted by an incoming packet. */
- save_flags(flags);
- cli();
- write_reg(ioaddr, IMR, 0);
- write_reg_high(ioaddr, IMR, 0);
- restore_flags(flags);
-
- write_packet(ioaddr, length, buf, dev->if_port);
-
- lp->pac_cnt_in_tx_buf++;
- if (lp->tx_unit_busy == 0) {
- trigger_send(ioaddr, length);
- lp->saved_tx_size = 0; /* Redundant */
- lp->re_tx = 0;
+ lp->pac_cnt_in_tx_buf++;
+ if (lp->tx_unit_busy == 0) {
+ trigger_send(ioaddr, length);
+ lp->saved_tx_size = 0; /* Redundant */
+ lp->re_tx = 0;
lp->tx_unit_busy = 1;
- } else
- lp->saved_tx_size = length;
-
- dev->trans_start = jiffies;
- /* Re-enable the LPT interrupts. */
- write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
- write_reg_high(ioaddr, IMR, ISRh_RxErr);
- }
+ } else
+ lp->saved_tx_size = length;
+ dev->trans_start = jiffies;
+ /* Re-enable the LPT interrupts. */
+ write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
+ write_reg_high(ioaddr, IMR, ISRh_RxErr);
dev_kfree_skb (skb);
-
return 0;
}
@@ -482,14 +476,10 @@ net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
int ioaddr, status, boguscount = 20;
static int num_tx_since_rx = 0;
- if (dev == NULL) {
- printk ("ATP_interrupt(): irq %d for unknown device.\n", irq);
- return;
- }
- dev->interrupt = 1;
-
ioaddr = dev->base_addr;
lp = (struct net_local *)dev->priv;
+
+ spin_lock(&lp->lock);
/* Disable additional spurious interrupts. */
outb(Ctrl_SelData, ioaddr + PAR_CONTROL);
@@ -498,10 +488,14 @@ net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
write_reg(ioaddr, CMR2, CMR2_NULL);
write_reg(ioaddr, IMR, 0);
- if (net_debug > 5) printk("%s: In interrupt ", dev->name);
- while (--boguscount > 0) {
+ if (net_debug > 5)
+ printk("%s: In interrupt ", dev->name);
+
+ while (--boguscount > 0)
+ {
status = read_nibble(ioaddr, ISR);
- if (net_debug > 5) printk("loop status %02x..", status);
+ if (net_debug > 5)
+ printk("loop status %02x..", status);
if (status & (ISR_RxOK<<3)) {
write_reg(ioaddr, ISR, ISR_RxOK); /* Clear the Rx interrupt. */
@@ -539,7 +533,8 @@ net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
break;
}
/* Attempt to retransmit. */
- if (net_debug > 6) printk("attempting to ReTx");
+ if (net_debug > 6)
+ printk("attempting to ReTx");
write_reg(ioaddr, CMR1, CMR1_ReXmit + CMR1_Xmit);
} else {
/* Finish up the transmit. */
@@ -551,8 +546,7 @@ net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
lp->re_tx = 0;
} else
lp->tx_unit_busy = 0;
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_wake_queue(dev); /* Inform upper layers. */
}
num_tx_since_rx++;
} else if (num_tx_since_rx > 8
@@ -568,7 +562,7 @@ net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
break;
} else
break;
- }
+ }
/* This following code fixes a rare (and very difficult to track down)
problem where the adapter forgets its ethernet address. */
@@ -584,17 +578,17 @@ net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
}
/* Tell the adapter that it can go back to using the output line as IRQ. */
- write_reg(ioaddr, CMR2, CMR2_IRQOUT);
+ write_reg(ioaddr, CMR2, CMR2_IRQOUT);
/* Enable the physical interrupt line, which is sure to be low until.. */
outb(Ctrl_SelData + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
/* .. we enable the interrupt sources. */
write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
write_reg_high(ioaddr, IMR, ISRh_RxErr); /* Hmmm, really needed? */
- if (net_debug > 5) printk("exiting interrupt.\n");
-
- dev->interrupt = 0;
-
+ if (net_debug > 5)
+ printk("exiting interrupt.\n");
+
+ spin_unlock(&lp->lock);
return;
}
@@ -603,33 +597,17 @@ net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
problem where the adapter forgets its ethernet address. */
static void atp_timed_checker(unsigned long ignored)
{
- int i;
- int ioaddr = atp_timed_dev->base_addr;
+ int i;
+ struct net_local *lp = (struct net_local *)atp_timed_dev->priv;
+ int ioaddr = atp_timed_dev->base_addr;
- if (!atp_timed_dev->interrupt)
- {
- for (i = 0; i < 6; i++)
-#if 0
- if (read_cmd_byte(ioaddr, PAR0 + i) != atp_timed_dev->dev_addr[i])
- {
- struct net_local *lp = (struct net_local *)atp_timed_dev->priv;
- write_reg_byte(ioaddr, PAR0 + i, atp_timed_dev->dev_addr[i]);
- if (i == 2)
- lp->stats.tx_errors++;
- else if (i == 3)
- lp->stats.tx_dropped++;
- else if (i == 4)
- lp->stats.collisions++;
- else
- lp->stats.rx_errors++;
- }
-#else
- write_reg_byte(ioaddr, PAR0 + i, atp_timed_dev->dev_addr[i]);
-#endif
- }
- del_timer(&atp_timer);
- atp_timer.expires = jiffies + TIMED_CHECKER;
- add_timer(&atp_timer);
+ spin_lock(&lp->lock);
+ for (i = 0; i < 6; i++)
+ write_reg_byte(ioaddr, PAR0 + i, atp_timed_dev->dev_addr[i]);
+ spin_unlock(&lp->lock);
+ del_timer(&atp_timer);
+ atp_timer.expires = jiffies + TIMED_CHECKER;
+ add_timer(&atp_timer);
}
#endif
@@ -707,19 +685,17 @@ static void read_block(short ioaddr, int length, unsigned char *p, int data_mode
else
do *p++ = read_byte_mode6(ioaddr); while (--length > 0);
- outb(EOC+HNib+MAR, ioaddr + PAR_DATA);
+ outb(EOC+HNib+MAR, ioaddr + PAR_DATA);
outb(Ctrl_SelData, ioaddr + PAR_CONTROL);
}
/* The inverse routine to net_open(). */
-static int
-net_close(struct net_device *dev)
+static int net_close(struct net_device *dev)
{
struct net_local *lp = (struct net_local *)dev->priv;
int ioaddr = dev->base_addr;
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue(dev);
/* Flush the Tx and disable Rx here. */
lp->addr_mode = CMR2h_OFF;
@@ -730,7 +706,7 @@ net_close(struct net_device *dev)
free_irq(dev->irq, dev);
/* Leave the hardware in a reset state. */
- write_reg_high(ioaddr, CMR1, CMR1h_RESET);
+ write_reg_high(ioaddr, CMR1, CMR1h_RESET);
return 0;
}
@@ -774,3 +750,27 @@ static void set_multicast_list(struct net_device *dev)
* tab-width: 4
* End:
*/
+
+#ifdef MODULE
+
+static int io = 0;
+static char nullname[8] = "";
+static struct net_device atp_dev = {
+ nullname, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, atp_probe };
+
+MODULE_PARM(io, "I/O port of the pocket adapter");
+
+int init_module(void)
+{
+ atp_dev.base_addr = io;
+ if (register_netdev(&atp_dev) != 0)
+ return -EIO;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ unregister_netdev(&atp_dev);
+}
+
+#endif
diff --git a/drivers/net/atp.h b/drivers/net/atp.h
index 8a74d4451..46801e401 100644
--- a/drivers/net/atp.h
+++ b/drivers/net/atp.h
@@ -4,15 +4,14 @@
struct net_local
{
-#ifdef __KERNEL__
struct net_device_stats stats;
-#endif
ushort saved_tx_size;
unsigned char
re_tx, /* Number of packet retransmissions. */
tx_unit_busy,
addr_mode, /* Current Rx filter e.g. promiscuous, etc. */
pac_cnt_in_tx_buf;
+ spinlock_t lock; /* Safety lock */
};
struct rx_header {
@@ -52,8 +51,7 @@ enum page0_regs
CMR2_h = 0x1d,
};
-enum eepage_regs
-{ PROM_CMD = 6, PROM_DATA = 7 }; /* Note that PROM_CMD is in the "high" bits. */
+enum eepage_regs { PROM_CMD = 6, PROM_DATA = 7 }; /* Note that PROM_CMD is in the "high" bits. */
#define ISR_TxOK 0x01
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index 30aa851b8..1c297dbec 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -65,6 +65,7 @@ struct bmac_data {
volatile struct dbdma_cmd *tx_cmds; /* xmit dma command list */
volatile struct dbdma_cmd *rx_cmds; /* recv dma command list */
struct device_node *node;
+ int is_bmac_plus;
struct sk_buff *rx_bufs[N_RX_RING];
int rx_fill;
int rx_empty;
@@ -80,6 +81,7 @@ struct bmac_data {
int tx_allocated;
unsigned short hash_use_count[64];
unsigned short hash_table_mask[4];
+ struct net_device *next_bmac;
};
typedef struct bmac_reg_entry {
@@ -124,7 +126,6 @@ bmac_reg_entry_t reg_entries[N_REG_ENTRIES] = {
};
struct net_device *bmac_devs = NULL;
-static int is_bmac_plus;
#ifdef CONFIG_PMAC_PBOOK
int bmac_sleep_notify(struct pmu_sleep_notifier *self, int when);
@@ -133,13 +134,6 @@ static struct pmu_sleep_notifier bmac_sleep_notifier = {
};
#endif
-#if 0
-/*
- * If we can't get a skbuff when we need it, we use this area for DMA.
- */
-static unsigned char dummy_buf[RX_BUFLEN];
-#endif
-
/*
* Number of bytes of private data per BMAC: allow enough for
* the rx and tx dma commands plus a branch dma command each,
@@ -151,6 +145,7 @@ static unsigned char dummy_buf[RX_BUFLEN];
+ sizeof(struct sk_buff_head))
static unsigned char bitrev(unsigned char b);
+static void bmac_probe1(struct device_node *bmac, int is_bmac_plus);
static int bmac_open(struct net_device *dev);
static int bmac_close(struct net_device *dev);
static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev);
@@ -192,9 +187,10 @@ dbdma_ld32(volatile unsigned long *a)
void
dbdma_stop(volatile struct dbdma_regs *dmap)
{
- dbdma_st32((volatile unsigned long *)&dmap->control, DBDMA_CLEAR(RUN) | DBDMA_SET(FLUSH));
+ dbdma_st32((volatile unsigned long *)&dmap->control,
+ DBDMA_CLEAR(RUN) | DBDMA_SET(FLUSH));
eieio();
-
+
while (dbdma_ld32((volatile unsigned long *)&dmap->status) & (ACTIVE|FLUSH))
eieio();
}
@@ -210,10 +206,11 @@ dbdma_continue(volatile struct dbdma_regs *dmap)
static void
dbdma_reset(volatile struct dbdma_regs *dmap)
{
- dbdma_st32((volatile unsigned long *)&dmap->control,
- DBDMA_CLEAR(ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN));
+ dbdma_st32((volatile unsigned long *)&dmap->control,
+ DBDMA_CLEAR(ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN));
eieio();
- while (dbdma_ld32((volatile unsigned long *)&dmap->status) & RUN) eieio();
+ while (dbdma_ld32((volatile unsigned long *)&dmap->status) & RUN)
+ eieio();
}
static void
@@ -239,7 +236,7 @@ void bmwrite(struct net_device *dev, unsigned long reg_offset, unsigned data )
static __inline__
volatile unsigned short bmread(struct net_device *dev, unsigned long reg_offset )
{
- return in_le16((void *)dev->base_addr + reg_offset);
+ return in_le16((void *)dev->base_addr + reg_offset);
}
static void
@@ -248,7 +245,7 @@ bmac_reset_chip(struct net_device *dev)
struct bmac_data *bp = (struct bmac_data *) dev->priv;
volatile struct dbdma_regs *rd = bp->rx_dma;
volatile struct dbdma_regs *td = bp->tx_dma;
-
+
dbdma_reset(rd);
dbdma_reset(td);
@@ -349,7 +346,7 @@ bmac_init_registers(struct net_device *dev)
regValue = bmread(dev, TXRST); /* wait for reset to clear..acknowledge */
} while ((regValue & TxResetBit) && i > 0);
- if (!is_bmac_plus) {
+ if (!bp->is_bmac_plus) {
regValue = bmread(dev, XCVRIF);
regValue |= ClkBit | SerialMode | COLActiveLow;
bmwrite(dev, XCVRIF, regValue);
@@ -385,7 +382,7 @@ bmac_init_registers(struct net_device *dev)
/* set rx fifo information */
bmwrite(dev, RXFIFOCSR, 0); /* first disable rxFIFO */
- bmwrite(dev, RXFIFOCSR, RxFIFOEnable );
+ bmwrite(dev, RXFIFOCSR, RxFIFOEnable );
//bmwrite(dev, TXCFG, TxMACEnable); /* TxNeverGiveUp maybe later */
bmread(dev, STATUS); /* read it just to clear it */
@@ -433,13 +430,13 @@ bmac_start_chip(struct net_device *dev)
/* enable rx dma channel */
dbdma_continue(rd);
-
+
oldConfig = bmread(dev, TXCFG);
- bmwrite(dev, TXCFG, oldConfig | TxMACEnable );
-
+ bmwrite(dev, TXCFG, oldConfig | TxMACEnable );
+
/* turn on rx plus any other bits already on (promiscuous possibly) */
oldConfig = bmread(dev, RXCFG);
- bmwrite(dev, RXCFG, oldConfig | RxMACEnable );
+ bmwrite(dev, RXCFG, oldConfig | RxMACEnable );
udelay(20000);
}
@@ -447,6 +444,7 @@ static void
bmac_init_phy(struct net_device *dev)
{
unsigned int addr;
+ struct bmac_data *bp = (struct bmac_data *) dev->priv;
printk(KERN_DEBUG "phy registers:");
for (addr = 0; addr < 32; ++addr) {
@@ -455,7 +453,7 @@ bmac_init_phy(struct net_device *dev)
printk(" %.4x", bmac_mif_read(dev, addr));
}
printk("\n");
- if (is_bmac_plus) {
+ if (bp->is_bmac_plus) {
unsigned int capable, ctrl;
ctrl = bmac_mif_read(dev, 0);
@@ -622,7 +620,8 @@ bmac_init_rx_ring(struct bmac_data *bp)
if (!bp->rx_allocated) {
for (i = 0; i < N_RX_RING; i++) {
bp->rx_bufs[i] = dev_alloc_skb(RX_BUFLEN+2);
- if (bp->rx_bufs[i] == NULL) return 0;
+ if (bp->rx_bufs[i] == NULL)
+ return 0;
skb_reserve(bp->rx_bufs[i], 2);
}
bp->rx_allocated = 1;
@@ -657,9 +656,10 @@ static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev)
/* XXDEBUG(("bmac_xmit_start: empty=%d fill=%d\n", */
/* bp->tx_empty, bp->tx_fill)); */
i = bp->tx_fill + 1;
- if (i >= N_TX_RING) i = 0;
+ if (i >= N_TX_RING)
+ i = 0;
if (i == bp->tx_empty) {
- dev->tbusy = 1;
+ netif_stop_queue(dev);
bp->tx_fullup = 1;
XXDEBUG(("bmac_transmit_packet: tx ring full\n"));
return -1; /* can't take it at the moment */
@@ -776,16 +776,15 @@ static void bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs)
if (bp->tx_bufs[bp->tx_empty]) {
++bp->stats.tx_packets;
- dev_kfree_skb(bp->tx_bufs[bp->tx_empty]);
+ dev_kfree_skb_irq(bp->tx_bufs[bp->tx_empty]);
}
bp->tx_bufs[bp->tx_empty] = NULL;
bp->tx_fullup = 0;
- dev->tbusy = 0;
- /* XXDEBUG(("bmac_intr: cleared tbusy, empty=%d fill=%d\n", */
- /* i, bp->tx_fill)); */
- mark_bh(NET_BH);
- if (++bp->tx_empty >= N_TX_RING) bp->tx_empty = 0;
- if (bp->tx_empty == bp->tx_fill) break;
+ netif_wake_queue(dev);
+ if (++bp->tx_empty >= N_TX_RING)
+ bp->tx_empty = 0;
+ if (bp->tx_empty == bp->tx_fill)
+ break;
}
restore_flags(flags);
@@ -831,7 +830,7 @@ crc416(unsigned int curval, unsigned short nxtval)
/* is high CRC bit set? */
if ((cur & 0x80000000) == 0) high_crc_set = 0;
else high_crc_set = 1;
-
+
cur = cur << 1;
if ((next & 0x0001) == 0) low_data_set = 0;
@@ -859,8 +858,8 @@ bmac_crc(unsigned short *address)
}
/*
- * Add requested mcast addr to BMac's hash table filter.
- *
+ * Add requested mcast addr to BMac's hash table filter.
+ *
*/
static void
@@ -925,7 +924,7 @@ bmac_rx_on(struct net_device *dev, int hash_enable, int promisc_enable)
else rx_cfg &= ~RxPromiscEnable;
bmwrite(dev, RXRST, RxResetValue);
bmwrite(dev, RXFIFOCSR, 0); /* first disable rxFIFO */
- bmwrite(dev, RXFIFOCSR, RxFIFOEnable );
+ bmwrite(dev, RXFIFOCSR, RxFIFOEnable );
bmwrite(dev, RXCFG, rx_cfg );
return rx_cfg;
}
@@ -1020,13 +1019,7 @@ static void bmac_set_multicast(struct net_device *dev)
int i, j, bit, byte;
unsigned short rx_cfg;
u32 crc, poly = CRC_POLYNOMIAL_LE;
-
- /* Let the transmits drain. */
- /* while(dev->tbusy) schedule(); */
-
- /* Lock out others. */
- /* set_bit(0, (void *) &dev->tbusy); */
-
+
if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
bmwrite(dev, BHASH0, 0xffff);
bmwrite(dev, BHASH1, 0xffff);
@@ -1048,15 +1041,15 @@ static void bmac_set_multicast(struct net_device *dev)
for(i = 0; i < dev->mc_count; i++) {
addrs = dmi->dmi_addr;
dmi = dmi->next;
-
+
if(!(*addrs & 1))
continue;
-
+
crc = 0xffffffffU;
for(byte = 0; byte < 6; byte++) {
for(bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {
int test;
-
+
test = ((bit ^ crc) & 0x01);
crc >>= 1;
if(test)
@@ -1071,9 +1064,6 @@ static void bmac_set_multicast(struct net_device *dev)
bmwrite(dev, BHASH2, hash_table[2]);
bmwrite(dev, BHASH3, hash_table[3]);
}
-
- /* Let us get going again. */
- /* dev->tbusy = 0; */
}
#endif /* SUNHME_MULTICAST */
@@ -1103,7 +1093,7 @@ static void bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs)
}
/*
- * Procedure for reading EEPROM
+ * Procedure for reading EEPROM
*/
#define SROMAddressLength 5
#define DataInOn 0x0008
@@ -1126,28 +1116,28 @@ bmac_clock_out_bit(struct net_device *dev)
bmwrite(dev, SROMCSR, ChipSelect | Clk);
udelay(DelayValue);
-
+
data = bmread(dev, SROMCSR);
udelay(DelayValue);
val = (data >> SD0ShiftCount) & 1;
bmwrite(dev, SROMCSR, ChipSelect);
udelay(DelayValue);
-
+
return val;
}
static void
bmac_clock_in_bit(struct net_device *dev, unsigned int val)
{
- unsigned short data;
+ unsigned short data;
if (val != 0 && val != 1) return;
-
+
data = (val << SDIShiftCount);
bmwrite(dev, SROMCSR, data | ChipSelect );
udelay(DelayValue);
-
+
bmwrite(dev, SROMCSR, data | ChipSelect | Clk );
udelay(DelayValue);
@@ -1161,7 +1151,7 @@ reset_and_select_srom(struct net_device *dev)
/* first reset */
bmwrite(dev, SROMCSR, 0);
udelay(DelayValue);
-
+
/* send it the read command (110) */
bmac_clock_in_bit(dev, 1);
bmac_clock_in_bit(dev, 1);
@@ -1173,13 +1163,13 @@ read_srom(struct net_device *dev, unsigned int addr, unsigned int addr_len)
{
unsigned short data, val;
int i;
-
+
/* send out the address we want to read from */
for (i = 0; i < addr_len; i++) {
val = addr >> (addr_len-i-1);
bmac_clock_in_bit(dev, val & 1);
}
-
+
/* Now read in the 16-bit data */
data = 0;
for (i = 0; i < 16; i++) {
@@ -1188,24 +1178,24 @@ read_srom(struct net_device *dev, unsigned int addr, unsigned int addr_len)
data |= val;
}
bmwrite(dev, SROMCSR, 0);
-
+
return data;
}
/*
* It looks like Cogent and SMC use different methods for calculating
- * checksums. What a pain..
+ * checksums. What a pain..
*/
static int
bmac_verify_checksum(struct net_device *dev)
{
unsigned short data, storedCS;
-
+
reset_and_select_srom(dev);
data = read_srom(dev, 3, SROMAddressBits);
storedCS = ((data >> 8) & 0x0ff) | ((data << 8) & 0xff00);
-
+
return 0;
}
@@ -1236,8 +1226,10 @@ static int bmac_reset_and_enable(struct net_device *dev, int enable)
bp->reset_and_enabled = 0;
bmac_reset_chip(dev);
if (enable) {
- if (!bmac_init_tx_ring(bp) || !bmac_init_rx_ring(bp)) return 0;
- if (!bmac_init_chip(dev)) return 0;
+ if (!bmac_init_tx_ring(bp) || !bmac_init_rx_ring(bp))
+ return 0;
+ if (!bmac_init_chip(dev))
+ return 0;
bmac_start_chip(dev);
bmwrite(dev, INTDISABLE, EnableNormal);
bp->reset_and_enabled = 1;
@@ -1257,70 +1249,55 @@ static int bmac_reset_and_enable(struct net_device *dev, int enable)
return 1;
}
-static int __init bmac_probe (void)
+static int __init bmac_probe(void)
{
- int j, rev;
- struct bmac_data *bp;
- struct device_node *bmacs;
- unsigned char *addr;
- static struct device_node *all_bmacs = NULL, *next_bmac;
- struct net_device *dev = NULL;
+ struct device_node *bmac;
-#ifdef MODULE
- if(bmac_devs != NULL)
- return -EBUSY;
-#endif
-
- if (all_bmacs == NULL) {
- all_bmacs = find_devices("bmac");
- is_bmac_plus = 0;
- if (all_bmacs == NULL) {
- all_bmacs = find_compatible_devices("network", "bmac+");
- if (all_bmacs)
- is_bmac_plus = 1;
- }
- next_bmac = all_bmacs;
- }
- bmacs = next_bmac;
- if (bmacs == NULL) return -ENODEV;
- next_bmac = bmacs->next;
+ for (bmac = find_devices("bmac"); bmac != 0; bmac = bmac->next)
+ bmac_probe1(bmac, 0);
+ for (bmac = find_compatible_devices("network", "bmac+"); bmac != 0;
+ bmac = bmac->next)
+ bmac_probe1(bmac, 1);
- if (bmac_devs == 0) {
- bmac_devs = dev; /* KLUDGE!! */
+ if (bmac_devs != 0) {
+ proc_net_create ("bmac", 0, bmac_proc_info);
#ifdef CONFIG_PMAC_PBOOK
pmu_register_sleep_notifier(&bmac_sleep_notifier);
#endif
}
+ return 0;
+}
- if (bmacs->n_addrs != 3 || bmacs->n_intrs != 3) {
- printk(KERN_ERR "can't use BMAC %s: expect 3 addrs and 3 intrs\n",
- bmacs->full_name);
- return -EINVAL;
+static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus)
+{
+ int j, rev;
+ struct bmac_data *bp;
+ unsigned char *addr;
+ struct net_device *dev;
+
+ if (bmac->n_addrs != 3 || bmac->n_intrs != 3) {
+ printk(KERN_ERR "can't use BMAC %s: need 3 addrs and 3 intrs\n",
+ bmac->full_name);
+ return;
+ }
+ addr = get_property(bmac, "mac-address", NULL);
+ if (addr == NULL) {
+ addr = get_property(bmac, "local-mac-address", NULL);
+ if (addr == NULL) {
+ printk(KERN_ERR "Can't get mac-address for BMAC %s\n",
+ bmac->full_name);
+ return;
+ }
}
dev = init_etherdev(NULL, PRIV_BYTES);
- bmac_devs = dev; /*KLUDGE!!*/
-#ifdef MODULE
- bmac_devs = dev;
-#endif
-
dev->base_addr = (unsigned long)
- ioremap(bmacs->addrs[0].address, bmacs->addrs[0].size);
- dev->irq = bmacs->intrs[0].line;
+ ioremap(bmac->addrs[0].address, bmac->addrs[0].size);
+ dev->irq = bmac->intrs[0].line;
bmwrite(dev, INTDISABLE, DisableAll);
-
- addr = get_property(bmacs, "mac-address", NULL);
- if (addr == NULL) {
- addr = get_property(bmacs, "local-mac-address", NULL);
- if (addr == NULL) {
- printk(KERN_ERR "Can't get mac-address for BMAC at %lx\n",
- dev->base_addr);
- return -EAGAIN;
- }
- }
-
+
printk(KERN_INFO "%s: BMAC%s at", dev->name, (is_bmac_plus? "+": ""));
rev = addr[0] == 0 && addr[1] == 0xA0;
for (j = 0; j < 6; ++j) {
@@ -1329,7 +1306,7 @@ static int __init bmac_probe (void)
}
XXDEBUG((", base_addr=%#0lx", dev->base_addr));
printk("\n");
-
+
dev->open = bmac_open;
dev->stop = bmac_close;
dev->hard_start_xmit = bmac_output;
@@ -1338,61 +1315,55 @@ static int __init bmac_probe (void)
dev->set_mac_address = bmac_set_address;
bmac_get_station_address(dev, addr);
- if (bmac_verify_checksum(dev) != 0) return -EINVAL;
-
+ if (bmac_verify_checksum(dev) != 0)
+ return;
+
ether_setup(dev);
-
+
bp = (struct bmac_data *) dev->priv;
memset(bp, 0, sizeof(struct bmac_data));
+ bp->is_bmac_plus = is_bmac_plus;
bp->tx_dma = (volatile struct dbdma_regs *)
- ioremap(bmacs->addrs[1].address, bmacs->addrs[1].size);
- bp->tx_dma_intr = bmacs->intrs[1].line;
+ ioremap(bmac->addrs[1].address, bmac->addrs[1].size);
+ bp->tx_dma_intr = bmac->intrs[1].line;
bp->rx_dma = (volatile struct dbdma_regs *)
- ioremap(bmacs->addrs[2].address, bmacs->addrs[2].size);
- bp->rx_dma_intr = bmacs->intrs[2].line;
-
+ ioremap(bmac->addrs[2].address, bmac->addrs[2].size);
+ bp->rx_dma_intr = bmac->intrs[2].line;
+
bp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(bp + 1);
bp->rx_cmds = bp->tx_cmds + N_TX_RING + 1;
bp->queue = (struct sk_buff_head *)(bp->rx_cmds + N_RX_RING + 1);
skb_queue_head_init(bp->queue);
-
- bp->node = bmacs;
+
+ bp->node = bmac;
memset(&bp->stats, 0, sizeof(bp->stats));
memset((char *) bp->tx_cmds, 0,
(N_TX_RING + N_RX_RING + 2) * sizeof(struct dbdma_cmd));
/* init_timer(&bp->tx_timeout); */
/* bp->timeout_active = 0; */
- if (request_irq(dev->irq, bmac_misc_intr, 0, "BMAC-misc", dev)) {
+ if (request_irq(dev->irq, bmac_misc_intr, 0, "BMAC-misc", dev))
printk(KERN_ERR "BMAC: can't get irq %d\n", dev->irq);
- return -EAGAIN;
- }
- if (request_irq(bmacs->intrs[1].line, bmac_txdma_intr, 0, "BMAC-txdma",
- dev)) {
- printk(KERN_ERR "BMAC: can't get irq %d\n", bmacs->intrs[1].line);
- return -EAGAIN;
- }
- if (request_irq(bmacs->intrs[2].line, bmac_rxdma_intr, 0, "BMAC-rxdma",
- dev)) {
- printk(KERN_ERR "BMAC: can't get irq %d\n", bmacs->intrs[2].line);
- return -EAGAIN;
- }
-
- if (!bmac_reset_and_enable(dev, 0)) return -ENOMEM;
-
- proc_net_create ("bmac", 0, bmac_proc_info);
-
- return 0;
+ if (request_irq(bmac->intrs[1].line, bmac_txdma_intr, 0, "BMAC-txdma",
+ dev))
+ printk(KERN_ERR "BMAC: can't get irq %d\n", bmac->intrs[1].line);
+ if (request_irq(bmac->intrs[2].line, bmac_rxdma_intr, 0, "BMAC-rxdma",
+ dev))
+ printk(KERN_ERR "BMAC: can't get irq %d\n", bmac->intrs[2].line);
+
+ bp->next_bmac = bmac_devs;
+ bmac_devs = dev;
}
static int bmac_open(struct net_device *dev)
{
/* XXDEBUG(("bmac: enter open\n")); */
/* reset the chip */
- bmac_reset_and_enable(dev, 1);
+ if (!bmac_reset_and_enable(dev, 1))
+ return -ENOMEM;
- dev->flags |= IFF_UP | IFF_RUNNING;
+ dev->flags |= IFF_RUNNING;
MOD_INC_USE_COUNT;
return 0;
@@ -1452,14 +1423,17 @@ bmac_start(struct net_device *dev)
int i;
struct sk_buff *skb;
unsigned long flags;
-
+
save_flags(flags); cli();
while (1) {
i = bp->tx_fill + 1;
- if (i >= N_TX_RING) i = 0;
- if (i == bp->tx_empty) break;
+ if (i >= N_TX_RING)
+ i = 0;
+ if (i == bp->tx_empty)
+ break;
skb = skb_dequeue(bp->queue);
- if (skb == NULL) break;
+ if (skb == NULL)
+ break;
bmac_transmit_packet(skb, dev);
}
restore_flags(flags);
@@ -1525,9 +1499,7 @@ static void bmac_tx_timeout(unsigned long data)
bp->tx_empty = i;
}
bp->tx_fullup = 0;
- dev->tbusy = 0;
- mark_bh(NET_BH);
- XXDEBUG((KERN_DEBUG "bmac: clearing tbusy\n"));
+ netif_wake_queue(dev);
if (i != bp->tx_fill) {
cp = &bp->tx_cmds[i];
out_le16(&cp->xfer_status, 0);
@@ -1540,9 +1512,9 @@ static void bmac_tx_timeout(unsigned long data)
/* turn it back on */
oldConfig = bmread(dev, RXCFG);
- bmwrite(dev, RXCFG, oldConfig | RxMACEnable );
+ bmwrite(dev, RXCFG, oldConfig | RxMACEnable );
oldConfig = bmread(dev, TXCFG);
- bmwrite(dev, TXCFG, oldConfig | TxMACEnable );
+ bmwrite(dev, TXCFG, oldConfig | TxMACEnable );
restore_flags(flags);
}
@@ -1573,7 +1545,8 @@ bmac_proc_info(char *buffer, char **start, off_t offset, int length)
off_t begin = 0;
int i;
- if (bmac_devs == NULL) return (-ENOSYS);
+ if (bmac_devs == NULL)
+ return (-ENOSYS);
len += sprintf(buffer, "BMAC counters & registers\n");
@@ -1582,20 +1555,20 @@ bmac_proc_info(char *buffer, char **start, off_t offset, int length)
reg_entries[i].name,
bmread(bmac_devs, reg_entries[i].reg_offset));
pos = begin + len;
-
+
if (pos < offset) {
len = 0;
begin = pos;
}
-
+
if (pos > offset+length) break;
}
-
+
*start = buffer + (offset - begin);
len -= (offset - begin);
-
+
if (len > length) len = length;
-
+
return len;
}
@@ -1606,26 +1579,28 @@ MODULE_DESCRIPTION("PowerMac BMAC ethernet driver.");
static void __exit bmac_cleanup (void)
{
-#ifdef MODULE
- struct bmac_data *bp;
+ struct bmac_data *bp;
+ struct net_device *dev;
- if (bmac_devs == 0)
- return;
+ if (bmac_devs == 0)
+ return;
+#ifdef CONFIG_PMAC_PBOOK
+ pmu_unregister_sleep_notifier(&bmac_sleep_notifier);
+#endif
+ proc_net_remove("bmac");
- bp = (struct bmac_data *) bmac_devs->priv;
- unregister_netdev(bmac_devs);
- proc_net_remove("bmac");
+ do {
+ dev = bmac_devs;
+ bp = (struct bmac_data *) dev->priv;
+ bmac_devs = bp->next_bmac;
- free_irq(bmac_devs->irq, bmac_misc_intr);
- free_irq(bp->tx_dma_intr, bmac_txdma_intr);
- free_irq(bp->rx_dma_intr, bmac_rxdma_intr);
+ free_irq(dev->irq, dev);
+ free_irq(bp->tx_dma_intr, dev);
+ free_irq(bp->rx_dma_intr, dev);
-#ifdef CONFIG_PMAC_PBOOK
- pmu_unregister_sleep_notifier(&bmac_sleep_notifier);
-#endif
- kfree(bmac_devs);
- bmac_devs = NULL;
-#endif
+ unregister_netdev(dev);
+ kfree(dev);
+ } while (bmac_devs != NULL);
}
module_init(bmac_probe);
diff --git a/drivers/net/cops.c b/drivers/net/cops.c
index c15a1937c..466705f9e 100644
--- a/drivers/net/cops.c
+++ b/drivers/net/cops.c
@@ -30,6 +30,7 @@
* cleanup of formatting and program
* logic. Added emacs 'local-vars'
* setup for Jay's brace style.
+ * 20000211 Alan Cox Cleaned up for softnet
*/
static const char *version =
@@ -48,10 +49,8 @@ static const char *version =
*/
#include <linux/config.h>
-#ifdef MODULE
#include <linux/module.h>
#include <linux/version.h>
-#endif
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -180,7 +179,7 @@ static unsigned int cops_debug = COPS_DEBUG;
struct cops_local
{
- struct enet_statistics stats;
+ struct net_device_stats stats;
int board; /* Holds what board type is. */
int nodeid; /* Set to 1 once have nodeid. */
unsigned char node_acquire; /* Node ID when acquired. */
@@ -200,6 +199,7 @@ static int cops_nodeid (struct net_device *dev, int nodeid);
static void cops_interrupt (int irq, void *dev_id, struct pt_regs *regs);
static void cops_poll (unsigned long ltdev);
+static void cops_timeout(struct net_device *dev);
static void cops_rx (struct net_device *dev);
static int cops_send_packet (struct sk_buff *skb, struct net_device *dev);
static void set_multicast_list (struct net_device *dev);
@@ -209,7 +209,7 @@ static int cops_hard_header (struct sk_buff *skb, struct net_device *dev,
static int cops_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
static int cops_close (struct net_device *dev);
-static struct enet_statistics *cops_get_stats (struct net_device *dev);
+static struct net_device_stats *cops_get_stats (struct net_device *dev);
/*
@@ -323,13 +323,15 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
/* Fill in the fields of the device structure with LocalTalk values. */
ltalk_setup(dev);
- dev->hard_start_xmit = &cops_send_packet;
+ dev->hard_start_xmit = cops_send_packet;
+ dev->tx_timeout = cops_timeout;
+ dev->watchdog_timeo = HZ * 2;
dev->hard_header = cops_hard_header;
dev->get_stats = cops_get_stats;
dev->open = cops_open;
dev->stop = cops_close;
- dev->do_ioctl = &cops_ioctl;
- dev->set_multicast_list = &set_multicast_list;
+ dev->do_ioctl = cops_ioctl;
+ dev->set_multicast_list = set_multicast_list;
dev->mc_list = NULL;
/* Tell the user where the card is and what mode we're in. */
@@ -424,10 +426,7 @@ static int cops_open(struct net_device *dev)
cops_jumpstart(dev); /* Start the card up. */
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
-
+ netif_start_queue(dev);
#ifdef MODULE
MOD_INC_USE_COUNT;
#endif
@@ -501,8 +500,7 @@ static void cops_reset(struct net_device *dev, int sleep)
else
udelay(333333);
}
- dev->tbusy=0;
-
+ netif_wake_queue(dev);
return;
}
@@ -673,6 +671,7 @@ static int cops_nodeid (struct net_device *dev, int nodeid)
/*
* Poll the Tangent type cards to see if we have work.
*/
+
static void cops_poll(unsigned long ltdev)
{
int ioaddr, status;
@@ -691,7 +690,7 @@ static void cops_poll(unsigned long ltdev)
if(status & TANG_RX_READY)
cops_rx(dev);
if(status & TANG_TX_READY)
- dev->tbusy = 0;
+ netif_wake_queue(dev);
status = inb(ioaddr+TANG_CARD_STATUS);
} while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY)));
@@ -712,14 +711,6 @@ static void cops_interrupt(int irq, void *dev_id, struct pt_regs * regs)
int ioaddr, status;
int boguscount = 0;
- if(dev == NULL)
- {
- printk(KERN_WARNING "%s: irq %d for unknown device.\n",
- cardname, irq);
- return;
- }
- dev->interrupt = 1;
-
ioaddr = dev->base_addr;
lp = (struct cops_local *)dev->priv;
@@ -730,8 +721,7 @@ static void cops_interrupt(int irq, void *dev_id, struct pt_regs * regs)
status=inb(ioaddr+DAYNA_CARD_STATUS);
if((status&0x03)==DAYNA_RX_REQUEST)
cops_rx(dev);
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
} while(++boguscount < 20);
}
else
@@ -741,13 +731,11 @@ static void cops_interrupt(int irq, void *dev_id, struct pt_regs * regs)
if(status & TANG_RX_READY)
cops_rx(dev);
if(status & TANG_TX_READY)
- dev->tbusy = 0;
+ netif_wake_queue(dev);
status=inb(ioaddr+TANG_CARD_STATUS);
- } while((++boguscount < 20) &&
- (status&(TANG_RX_READY|TANG_TX_READY)));
+ } while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY)));
}
- dev->interrupt = 0;
return;
}
@@ -762,7 +750,10 @@ static void cops_rx(struct net_device *dev)
struct cops_local *lp = (struct cops_local *)dev->priv;
int ioaddr = dev->base_addr;
int boguscount = 0;
+ unsigned long flags;
+
+ save_flags(flags);
cli(); /* Disable interrupts. */
if(lp->board==DAYNA)
@@ -798,7 +789,7 @@ static void cops_rx(struct net_device *dev)
skb = dev_alloc_skb(pkt_len);
if(skb == NULL)
{
- printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
+ printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n",
dev->name);
lp->stats.rx_dropped++;
while(pkt_len--) /* Discard packet */
@@ -814,12 +805,12 @@ static void cops_rx(struct net_device *dev)
if(lp->board==DAYNA)
outb(1, ioaddr+DAYNA_INT_CARD); /* Interrupt the card */
- sti(); /* Restore interrupts. */
+ restore_flags(flags); /* Restore interrupts. */
/* Check for bad response length */
if(pkt_len < 0 || pkt_len > MAX_LLAP_SIZE)
{
- printk(KERN_NOTICE "%s: Bad packet length of %d bytes.\n",
+ printk(KERN_WARNING "%s: Bad packet length of %d bytes.\n",
dev->name, pkt_len);
lp->stats.tx_errors++;
kfree_skb(skb);
@@ -837,7 +828,7 @@ static void cops_rx(struct net_device *dev)
/* One last check to make sure we have a good packet. */
if(rsp_type != LAP_RESPONSE)
{
- printk("%s: Bad packet type %d.\n", dev->name, rsp_type);
+ printk(KERN_WARNING "%s: Bad packet type %d.\n", dev->name, rsp_type);
lp->stats.tx_errors++;
kfree_skb(skb);
return;
@@ -857,79 +848,72 @@ static void cops_rx(struct net_device *dev)
return;
}
+static void cops_timeout(struct net_device *dev)
+{
+ struct cops_local *lp = (struct cops_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+
+ lp->stats.tx_errors++;
+ if(lp->board==TANGENT)
+ {
+ if((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0)
+ printk(KERN_WARNING "%s: No TX complete interrupt.\n", dev->name);
+ }
+ printk(KERN_WARNING "%s: Transmit timed out.\n", dev->name);
+ cops_jumpstart(dev); /* Restart the card. */
+ dev->trans_start = jiffies;
+ netif_wake_queue(dev);
+}
+
+
/*
* Make the card transmit a LocalTalk packet.
*/
+
static int cops_send_packet(struct sk_buff *skb, struct net_device *dev)
{
struct cops_local *lp = (struct cops_local *)dev->priv;
int ioaddr = dev->base_addr;
-
- if(dev->tbusy)
- {
- /*
- * If we get here, some higher level has decided we are broken.
- * There should really be a "kick me" function call instead.
- */
- int tickssofar = jiffies - dev->trans_start;
- if(tickssofar < 5)
- return 1;
- lp->stats.tx_errors++;
- if(lp->board==TANGENT)
- {
- if((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0)
- printk(KERN_WARNING "%s: No TX complete interrupt.\n", dev->name);
- }
- printk(KERN_WARNING "%s: Transmit timed out.\n", dev->name);
- cops_jumpstart(dev); /* Restart the card. */
- dev->tbusy=0;
- dev->trans_start = jiffies;
- }
+ unsigned long flags;
/*
- * Block a timer-based transmit from overlapping. This could better be
- * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
+ * Block a timer-based transmit from overlapping.
*/
- if(test_and_set_bit(0, (void*) &dev->tbusy) != 0)
- printk(KERN_WARNING "%s: Transmitter access conflict.\n",
- dev->name);
- else
- {
- cli(); /* Disable interrupts. */
- if(lp->board == DAYNA) /* Wait for adapter transmit buffer. */
- while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0);
- if(lp->board == TANGENT) /* Wait for adapter transmit buffer. */
- while((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0);
-
- /* Output IO length. */
- outb(skb->len, ioaddr);
- if(lp->board == DAYNA)
- outb(skb->len >> 8, ioaddr);
- else
- outb((skb->len >> 8)&0x0FF, ioaddr);
-
- /* Output IO code. */
- outb(LAP_WRITE, ioaddr);
+
+ netif_stop_queue(dev);
+
+ save_flags(flags);
+ cli(); /* Disable interrupts. */
+ if(lp->board == DAYNA) /* Wait for adapter transmit buffer. */
+ while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0);
+ if(lp->board == TANGENT) /* Wait for adapter transmit buffer. */
+ while((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0);
+
+ /* Output IO length. */
+ outb(skb->len, ioaddr);
+ if(lp->board == DAYNA)
+ outb(skb->len >> 8, ioaddr);
+ else
+ outb((skb->len >> 8)&0x0FF, ioaddr);
- if(lp->board == DAYNA) /* Check the transmit buffer again. */
- while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0);
+ /* Output IO code. */
+ outb(LAP_WRITE, ioaddr);
- outsb(ioaddr, skb->data, skb->len); /* Send out the data. */
+ if(lp->board == DAYNA) /* Check the transmit buffer again. */
+ while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0);
- if(lp->board==DAYNA) /* Dayna requires you kick the card */
- outb(1, ioaddr+DAYNA_INT_CARD);
+ outsb(ioaddr, skb->data, skb->len); /* Send out the data. */
- sti(); /* Restore interrupts. */
+ if(lp->board==DAYNA) /* Dayna requires you kick the card */
+ outb(1, ioaddr+DAYNA_INT_CARD);
- /* Done sending packet, update counters and cleanup. */
- lp->stats.tx_packets++;
- lp->stats.tx_bytes += skb->len;
- dev->trans_start = jiffies;
- }
+ restore_flags(flags); /* Restore interrupts. */
+ /* Done sending packet, update counters and cleanup. */
+ lp->stats.tx_packets++;
+ lp->stats.tx_bytes += skb->len;
+ dev->trans_start = jiffies;
dev_kfree_skb (skb);
- dev->tbusy = 0;
-
return 0;
}
@@ -1005,9 +989,7 @@ static int cops_close(struct net_device *dev)
if(lp->board==TANGENT && dev->irq==0)
del_timer(&cops_timer);
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
#ifdef MODULE
MOD_DEC_USE_COUNT;
#endif
@@ -1019,7 +1001,7 @@ static int cops_close(struct net_device *dev)
* Get the current statistics.
* This may be called with the card open or closed.
*/
-static struct enet_statistics *cops_get_stats(struct net_device *dev)
+static struct net_device_stats *cops_get_stats(struct net_device *dev)
{
struct cops_local *lp = (struct cops_local *)dev->priv;
return &lp->stats;
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index ac6ff986c..01dd799b3 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -120,6 +120,7 @@ static int net_open(struct net_device *dev);
static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void set_multicast_list(struct net_device *dev);
+static void net_timeout(struct net_device *dev);
static void net_rx(struct net_device *dev);
static int net_close(struct net_device *dev);
static struct net_device_stats *net_get_stats(struct net_device *dev);
@@ -139,14 +140,8 @@ static int set_mac_address(struct net_device *dev, void *addr);
If dev->base_addr == 2, allocate space for the device and return success
(detachable devices only).
*/
-#ifdef HAVE_DEVLIST
-/* Support for a alternate probe manager, which will eliminate the
- boilerplate below. */
-struct netdev_entry netcard_drv =
-{"netcard", cs89x0_probe1, NETCARD_IO_EXTENT, netcard_portlist};
-#else
-int __init
-cs89x0_probe(struct net_device *dev)
+
+int __init cs89x0_probe(struct net_device *dev)
{
int i;
int base_addr = dev ? dev->base_addr : 0;
@@ -166,37 +161,31 @@ cs89x0_probe(struct net_device *dev)
printk("cs89x0: no cs8900 or cs8920 detected. Be sure to disable PnP with SETUP\n");
return ENODEV;
}
-#endif
-static int inline
-readreg(struct net_device *dev, int portno)
+extern int inline readreg(struct net_device *dev, int portno)
{
outw(portno, dev->base_addr + ADD_PORT);
return inw(dev->base_addr + DATA_PORT);
}
-static void inline
-writereg(struct net_device *dev, int portno, int value)
+extern void inline writereg(struct net_device *dev, int portno, int value)
{
outw(portno, dev->base_addr + ADD_PORT);
outw(value, dev->base_addr + DATA_PORT);
}
-static int inline
-readword(struct net_device *dev, int portno)
+extern int inline readword(struct net_device *dev, int portno)
{
return inw(dev->base_addr + portno);
}
-static void inline
-writeword(struct net_device *dev, int portno, int value)
+extern void inline writeword(struct net_device *dev, int portno, int value)
{
outw(value, dev->base_addr + portno);
}
-static int __init
-wait_eeprom_ready(struct net_device *dev)
+static int __init wait_eeprom_ready(struct net_device *dev)
{
int timeout = jiffies;
/* check to see if the EEPROM is ready, a timeout is used -
@@ -208,8 +197,7 @@ wait_eeprom_ready(struct net_device *dev)
return 0;
}
-static int __init
-get_eeprom_data(struct net_device *dev, int off, int len, int *buffer)
+static int __init get_eeprom_data(struct net_device *dev, int off, int len, int *buffer)
{
int i;
@@ -226,8 +214,7 @@ get_eeprom_data(struct net_device *dev, int off, int len, int *buffer)
return 0;
}
-static int __init
-get_eeprom_cksum(int off, int len, int *buffer)
+static int __init get_eeprom_cksum(int off, int len, int *buffer)
{
int i, cksum;
@@ -378,10 +365,12 @@ static int __init cs89x0_probe1(struct net_device *dev, int ioaddr)
dev->open = net_open;
dev->stop = net_close;
- dev->hard_start_xmit = net_send_packet;
- dev->get_stats = net_get_stats;
- dev->set_multicast_list = &set_multicast_list;
- dev->set_mac_address = &set_mac_address;
+ dev->tx_timeout = net_timeout;
+ dev->watchdog_timeo = HZ;
+ dev->hard_start_xmit = net_send_packet;
+ dev->get_stats = net_get_stats;
+ dev->set_multicast_list = set_multicast_list;
+ dev->set_mac_address = set_mac_address;
/* Fill in the fields of the device structure with ethernet values. */
ether_setup(dev);
@@ -720,85 +709,69 @@ net_open(struct net_device *dev)
/* now that we've got our act together, enable everything */
writereg(dev, PP_BusCTL, ENABLE_IRQ
);
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
MOD_INC_USE_COUNT;
+ netif_start_queue(dev);
return 0;
}
-static int
-net_send_packet(struct sk_buff *skb, struct net_device *dev)
+static void net_timeout(struct net_device *dev)
{
- if (dev->tbusy) {
- /* If we get here, some higher level has decided we are broken.
- There should really be a "kick me" function call instead. */
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 5)
- return 1;
- if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
- tx_done(dev) ? "IRQ conflict ?" : "network cable problem");
- /* Try to restart the adaptor. */
- dev->tbusy=0;
- dev->trans_start = jiffies;
- }
+ /* If we get here, some higher level has decided we are broken.
+ There should really be a "kick me" function call instead. */
+ if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
+ tx_done(dev) ? "IRQ conflict ?" : "network cable problem");
+ /* Try to restart the adaptor. */
+ netif_wake_queue(dev);
+}
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk("%s: Transmitter access conflict.\n", dev->name);
- else {
- struct net_local *lp = (struct net_local *)dev->priv;
- short ioaddr = dev->base_addr;
- unsigned long flags;
-
- if (net_debug > 3)printk("%s: sent %d byte packet of type %x\n", dev->name, skb->len, (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);
-
- /* keep the upload from being interrupted, since we
- ask the chip to start transmitting before the
- whole packet has been completely uploaded. */
- save_flags(flags);
- cli();
-
- /* initiate a transmit sequence */
- outw(lp->send_cmd, ioaddr + TX_CMD_PORT);
- outw(skb->len, ioaddr + TX_LEN_PORT);
-
- /* Test to see if the chip has allocated memory for the packet */
- if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
- /* Gasp! It hasn't. But that shouldn't happen since
- we're waiting for TxOk, so return 1 and requeue this packet. */
- restore_flags(flags);
- return 1;
- }
+static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+ short ioaddr = dev->base_addr;
+ unsigned long flags;
+
+ if (net_debug > 3)
+ printk("%s: sent %d byte packet of type %x\n", dev->name, skb->len, (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);
+
+ /* keep the upload from being interrupted, since we
+ ask the chip to start transmitting before the
+ whole packet has been completely uploaded. */
- /* Write the contents of the packet */
- outsw(ioaddr + TX_FRAME_PORT,skb->data,(skb->len+1) >>1);
+ save_flags(flags);
+ cli();
+ netif_stop_queue(dev);
+
+ /* initiate a transmit sequence */
+ outw(lp->send_cmd, ioaddr + TX_CMD_PORT);
+ outw(skb->len, ioaddr + TX_LEN_PORT);
+ /* Test to see if the chip has allocated memory for the packet */
+ if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
+ /* Gasp! It hasn't. But that shouldn't happen since
+ we're waiting for TxOk, so return 1 and requeue this packet. */
restore_flags(flags);
- dev->trans_start = jiffies;
+ return 1;
}
- dev_kfree_skb (skb);
+ /* Write the contents of the packet */
+ outsw(ioaddr + TX_FRAME_PORT,skb->data,(skb->len+1) >>1);
+ restore_flags(flags);
+ dev->trans_start = jiffies;
+ dev_kfree_skb (skb);
+ netif_wake_queue(dev);
+
return 0;
}
/* The typical workload of the driver:
Handle the network interface interrupts. */
+
static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct net_device *dev = dev_id;
struct net_local *lp;
int ioaddr, status;
- if (dev == NULL) {
- printk ("net_interrupt(): irq %d for unknown device.\n", irq);
- return;
- }
- if (dev->interrupt)
- printk("%s: Re-entering the interrupt handler.\n", dev->name);
- dev->interrupt = 1;
-
ioaddr = dev->base_addr;
lp = (struct net_local *)dev->priv;
@@ -818,8 +791,7 @@ static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
break;
case ISQ_TRANSMITTER_EVENT:
lp->stats.tx_packets++;
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_wake_queue(dev); /* Inform upper layers. */
if ((status & TX_OK) == 0) lp->stats.tx_errors++;
if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++;
if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++;
@@ -833,8 +805,7 @@ static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
That shouldn't happen since we only ever
load one packet. Shrug. Do the right
thing anyway. */
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_wake_queue(dev); /* Inform upper layers. */
}
if (status & TX_UNDERRUN) {
if (net_debug > 0) printk("%s: transmit underrun\n", dev->name);
@@ -846,8 +817,7 @@ static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
avoids having to wait for the upper
layers to timeout on us, in the
event of a tx underrun */
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_wake_queue(dev); /* Inform upper layers. */
}
break;
case ISQ_RX_MISS_EVENT:
@@ -858,8 +828,6 @@ static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
break;
}
}
- dev->interrupt = 0;
- return;
}
/* We have a good packet(s), get it/them out of the buffers. */
@@ -913,14 +881,13 @@ net_rx(struct net_device *dev)
static int
net_close(struct net_device *dev)
{
-
+ netif_stop_queue(dev);
+
writereg(dev, PP_RxCFG, 0);
writereg(dev, PP_TxCFG, 0);
writereg(dev, PP_BufCFG, 0);
writereg(dev, PP_BusCTL, 0);
- dev->start = 0;
-
free_irq(dev->irq, dev);
/* Update the statistics here. */
@@ -974,7 +941,7 @@ static void set_multicast_list(struct net_device *dev)
static int set_mac_address(struct net_device *dev, void *addr)
{
int i;
- if (dev->start)
+ if (netif_running(dev))
return -EBUSY;
printk("%s: Setting MAC address to ", dev->name);
for (i = 0; i < 6; i++)
diff --git a/drivers/net/de4x5.c b/drivers/net/de4x5.c
index 7bb5b9796..81e0dbdae 100644
--- a/drivers/net/de4x5.c
+++ b/drivers/net/de4x5.c
@@ -458,6 +458,9 @@ static const char *version = "de4x5.c:V0.545 1999/11/28 davies@maniac.ultranet.c
#include <asm/byteorder.h>
#include <asm/unaligned.h>
#include <asm/uaccess.h>
+#ifdef CONFIG_PPC
+#include <asm/machdep.h>
+#endif /* CONFIG_PPC */
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -1558,15 +1561,14 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev)
return -1;
/* Transmit descriptor ring full or stale skb */
- if (test_bit(LINK_STATE_XOFF, &dev->state) ||
- (u_long) lp->tx_skb[lp->tx_new] > 1) {
+ if (netif_queue_stopped(dev) || (u_long) lp->tx_skb[lp->tx_new] > 1) {
if (lp->interrupt) {
de4x5_putb_cache(dev, skb); /* Requeue the buffer */
} else {
de4x5_put_cache(dev, skb);
}
if (de4x5_debug & DEBUG_TX) {
- printk("%s: transmit busy, lost media or stale skb found:\n STS:%08x\n tbusy:%d\n IMR:%08x\n OMR:%08x\n Stale skb: %s\n",dev->name, inl(DE4X5_STS), test_bit(LINK_STATE_XOFF, &dev->state), inl(DE4X5_IMR), inl(DE4X5_OMR), ((u_long) lp->tx_skb[lp->tx_new] > 1) ? "YES" : "NO");
+ printk("%s: transmit busy, lost media or stale skb found:\n STS:%08x\n tbusy:%d\n IMR:%08x\n OMR:%08x\n Stale skb: %s\n",dev->name, inl(DE4X5_STS), netif_queue_stopped(dev), inl(DE4X5_IMR), inl(DE4X5_OMR), ((u_long) lp->tx_skb[lp->tx_new] > 1) ? "YES" : "NO");
}
} else if (skb->len > 0) {
/* If we already have stuff queued locally, use that first */
@@ -1575,7 +1577,8 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev)
skb = de4x5_get_cache(dev);
}
- while (skb && !test_bit(LINK_STATE_XOFF, &dev->state) && (u_long) lp->tx_skb[lp->tx_new] <= 1) {
+ while (skb && !netif_queue_stopped(dev) &&
+ (u_long) lp->tx_skb[lp->tx_new] <= 1) {
spin_lock_irqsave(&lp->lock, flags);
netif_stop_queue(dev);
load_packet(dev, skb->data, TD_IC | TD_LS | TD_FS | skb->len, skb);
@@ -1663,7 +1666,7 @@ de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* Load the TX ring with any locally stored packets */
if (!test_and_set_bit(0, (void *)&lp->cache.lock)) {
- while (lp->cache.skb && !test_bit(LINK_STATE_XOFF, &dev->state) && lp->tx_enable) {
+ while (lp->cache.skb && !netif_queue_stopped(dev) && lp->tx_enable) {
de4x5_queue_pkt(de4x5_get_cache(dev), dev);
}
lp->cache.lock = 0;
@@ -1756,9 +1759,10 @@ static inline void
de4x5_free_tx_buff(struct de4x5_private *lp, int entry)
{
pci_unmap_single(lp->pdev, le32_to_cpu(lp->tx_ring[entry].buf),
- le32_to_cpu(lp->tx_ring[entry].des1) & TD_TBS1);
+ le32_to_cpu(lp->tx_ring[entry].des1) & TD_TBS1,
+ PCI_DMA_TODEVICE);
if ((u_long) lp->tx_skb[entry] > 1)
- dev_kfree_skb(lp->tx_skb[entry]);
+ dev_kfree_skb_irq(lp->tx_skb[entry]);
lp->tx_skb[entry] = NULL;
}
@@ -1807,7 +1811,7 @@ de4x5_tx(struct net_device *dev)
}
/* Any resources available? */
- if (TX_BUFFS_AVAIL && test_bit(LINK_STATE_XOFF, &dev->state)) {
+ if (TX_BUFFS_AVAIL && netif_queue_stopped(dev)) {
if (lp->interrupt)
netif_wake_queue(dev);
else
@@ -1977,7 +1981,7 @@ load_packet(struct net_device *dev, char *buf, u32 flags, struct sk_buff *skb)
{
struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
int entry = (lp->tx_new ? lp->tx_new-1 : lp->txRingSize-1);
- dma_addr_t buf_dma = pci_map_single(lp->pdev, buf, flags & TD_TBS1);
+ dma_addr_t buf_dma = pci_map_single(lp->pdev, buf, flags & TD_TBS1, PCI_DMA_TODEVICE);
lp->tx_ring[lp->tx_new].buf = cpu_to_le32(buf_dma);
lp->tx_ring[lp->tx_new].des1 &= cpu_to_le32(TD_TER);
@@ -4186,20 +4190,24 @@ get_hw_addr(struct net_device *dev)
/* If possible, try to fix a broken card - SMC only so far */
srom_repair(dev, broken);
-#ifdef CONFIG_PMAC
+#ifdef CONFIG_PPC
/*
** If the address starts with 00 a0, we have to bit-reverse
** each byte of the address.
*/
- if (dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0xa0) {
- for (i = 0; i < ETH_ALEN; ++i) {
- int x = dev->dev_addr[i];
- x = ((x & 0xf) << 4) + ((x & 0xf0) >> 4);
- x = ((x & 0x33) << 2) + ((x & 0xcc) >> 2);
- dev->dev_addr[i] = ((x & 0x55) << 1) + ((x & 0xaa) >> 1);
- }
+ if ( (ppc_md.ppc_machine & _MACH_Pmac) &&
+ (dev->dev_addr[0] == 0) &&
+ (dev->dev_addr[1] == 0xa0) )
+ {
+ for (i = 0; i < ETH_ALEN; ++i)
+ {
+ int x = dev->dev_addr[i];
+ x = ((x & 0xf) << 4) + ((x & 0xf0) >> 4);
+ x = ((x & 0x33) << 2) + ((x & 0xcc) >> 2);
+ dev->dev_addr[i] = ((x & 0x55) << 1) + ((x & 0xaa) >> 1);
+ }
}
-#endif /* CONFIG_PMAC */
+#endif /* CONFIG_PPC */
/* Test for a bad enet address */
status = test_bad_enet(dev, status);
@@ -5599,18 +5607,19 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
case DE4X5_SET_HWADDR: /* Set the hardware address */
if (!capable(CAP_NET_ADMIN)) return -EPERM;
if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN)) return -EFAULT;
+ if (netif_queue_stopped(dev))
+ return -EBUSY;
+ netif_stop_queue(dev);
for (i=0; i<ETH_ALEN; i++) {
dev->dev_addr[i] = tmp.addr[i];
}
build_setup_frame(dev, PHYS_ADDR_ONLY);
/* Set up the descriptor and give ownership to the card */
- while (test_and_set_bit(LINK_STATE_XOFF, &dev->state) != 0)
- barrier();
load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET |
SETUP_FRAME_LEN, (struct sk_buff *)1);
lp->tx_new = (++lp->tx_new) % lp->txRingSize;
outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */
- netif_start_queue(dev); /* Unlock the TX ring */
+ netif_wake_queue(dev); /* Unlock the TX ring */
break;
case DE4X5_SET_PROM: /* Set Promiscuous Mode */
@@ -5762,7 +5771,7 @@ de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
tmp.addr[j++] = lp->txRingSize;
- tmp.addr[j++] = test_bit(LINK_STATE_XOFF, &dev->state);
+ tmp.addr[j++] = netif_queue_stopped(dev);
ioc->len = j;
if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
diff --git a/drivers/net/de600.c b/drivers/net/de600.c
index 1805ae5f3..075f19cb8 100644
--- a/drivers/net/de600.c
+++ b/drivers/net/de600.c
@@ -348,7 +348,6 @@ de600_open(struct net_device *dev)
}
MOD_INC_USE_COUNT;
- dev->start = 1;
if (adapter_init(dev)) {
return 1;
}
@@ -369,9 +368,8 @@ de600_close(struct net_device *dev)
de600_put_command(0);
select_prn();
- if (dev->start) {
+ if (netif_running(dev)) { /* perhaps not needed? */
free_irq(DE600_IRQ, dev);
- dev->start = 0;
MOD_DEC_USE_COUNT;
}
return 0;
@@ -400,6 +398,7 @@ trigger_interrupt(struct net_device *dev)
static int
de600_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
+ unsigned long flags;
int transmit_from;
int len;
int tickssofar;
@@ -429,6 +428,7 @@ de600_start_xmit(struct sk_buff *skb, struct net_device *dev)
if ((len = skb->len) < RUNT)
len = RUNT;
+ save_flags(flags);
cli();
select_nic();
tx_fifo[tx_fifo_in] = transmit_from = tx_page_adr(tx_fifo_in) - len;
@@ -440,7 +440,7 @@ de600_start_xmit(struct sk_buff *skb, struct net_device *dev)
de600_read_byte(READ_DATA, dev);
if (was_down || (de600_read_byte(READ_DATA, dev) != 0xde)) {
if (adapter_init(dev)) {
- sti();
+ restore_flags(flags);
return 1;
}
}
@@ -452,17 +452,20 @@ de600_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (free_tx_pages-- == TX_PAGES) { /* No transmission going on */
dev->trans_start = jiffies;
- dev->tbusy = 0; /* allow more packets into adapter */
+ netif_start_queue(dev); /* allow more packets into adapter */
/* Send page and generate a faked interrupt */
de600_setup_address(transmit_from, TX_ADDR);
de600_put_command(TX_ENABLE);
}
else {
- dev->tbusy = !free_tx_pages;
+ if (free_tx_pages)
+ netif_start_queue(dev);
+ else
+ netif_stop_queue(dev);
select_prn();
}
- sti(); /* interrupts back on */
+ restore_flags(flags);
#ifdef FAKE_SMALL_MAX
/* This will "patch" the socket TCP proto at an early moment */
@@ -489,12 +492,11 @@ de600_interrupt(int irq, void *dev_id, struct pt_regs * regs)
int boguscount = 0;
/* This might just as well be deleted now, no crummy drivers present :-) */
- if ((dev == NULL) || (dev->start == 0) || (DE600_IRQ != irq)) {
+ if ((dev == NULL) || (DE600_IRQ != irq)) {
printk("%s: bogus interrupt %d\n", dev?dev->name:"DE-600", irq);
return;
}
- dev->interrupt = 1;
select_nic();
irq_status = de600_read_status(dev);
@@ -521,13 +523,11 @@ de600_interrupt(int irq, void *dev_id, struct pt_regs * regs)
*/
/* Enable adapter interrupts */
- dev->interrupt = 0;
select_prn();
if (retrig)
trigger_interrupt(dev);
- sti();
return;
}
@@ -538,7 +538,6 @@ de600_tx_intr(struct net_device *dev, int irq_status)
* Returns 1 if tx still not done
*/
- mark_bh(NET_BH);
/* Check if current transmission is done yet */
if (irq_status & TX_BUSY)
return 1; /* tx not done, try again */
@@ -549,7 +548,7 @@ de600_tx_intr(struct net_device *dev, int irq_status)
tx_fifo_out = (tx_fifo_out + 1) % TX_PAGES;
++free_tx_pages;
((struct net_device_stats *)(dev->priv))->tx_packets++;
- dev->tbusy = 0;
+ netif_wake_queue(dev);
}
/* More to send, or resend last packet? */
@@ -571,12 +570,15 @@ static void
de600_rx_intr(struct net_device *dev)
{
struct sk_buff *skb;
+ unsigned long flags;
int i;
int read_from;
int size;
register unsigned char *buffer;
+ save_flags(flags);
cli();
+
/* Get size of received packet */
size = de600_read_byte(RX_LEN, dev); /* low byte */
size += (de600_read_byte(RX_LEN, dev) << 8); /* high byte */
@@ -586,7 +588,8 @@ de600_rx_intr(struct net_device *dev)
read_from = rx_page_adr();
next_rx_page();
de600_put_command(RX_ENABLE);
- sti();
+
+ restore_flags(flags);
if ((size < 32) || (size > 1535)) {
printk("%s: Bogus packet size %d.\n", dev->name, size);
@@ -596,7 +599,7 @@ de600_rx_intr(struct net_device *dev)
}
skb = dev_alloc_skb(size+2);
- sti();
+ restore_flags(flags);
if (skb == NULL) {
printk("%s: Couldn't allocate a sk_buff of size %d.\n",
dev->name, size);
@@ -738,7 +741,7 @@ adapter_init(struct net_device *dev)
de600_close(dev);
#endif /* SHUTDOWN_WHEN_LOST */
was_down = 1;
- dev->tbusy = 1; /* Transmit busy... */
+ netif_stop_queue(dev); /* Transmit busy... */
restore_flags(flags);
return 1; /* failed */
}
@@ -748,8 +751,7 @@ adapter_init(struct net_device *dev)
was_down = 0;
}
- dev->tbusy = 0; /* Transmit busy... */
- dev->interrupt = 0;
+ netif_start_queue(dev);
tx_fifo_in = 0;
tx_fifo_out = 0;
free_tx_pages = TX_PAGES;
diff --git a/drivers/net/de620.c b/drivers/net/de620.c
index 3f138239f..440ac9951 100644
--- a/drivers/net/de620.c
+++ b/drivers/net/de620.c
@@ -435,19 +435,18 @@ de620_get_register(struct net_device *dev, byte reg)
* there is a non-reboot way to recover if something goes wrong.
*
*/
-static int
-de620_open(struct net_device *dev)
+static int de620_open(struct net_device *dev)
{
if (request_irq(dev->irq, de620_interrupt, 0, "de620", dev)) {
- printk ("%s: unable to get IRQ %d\n", dev->name, dev->irq);
+ printk (KERN_ERR "%s: unable to get IRQ %d\n", dev->name, dev->irq);
return 1;
}
- MOD_INC_USE_COUNT;
- if (adapter_init(dev)) {
+ if (adapter_init(dev))
return 1;
- }
- dev->start = 1;
+
+ MOD_INC_USE_COUNT;
+ netif_start_queue(dev);
return 0;
}
@@ -456,15 +455,13 @@ de620_open(struct net_device *dev)
* The inverse routine to de620_open().
*
*/
-static int
-de620_close(struct net_device *dev)
+
+static int de620_close(struct net_device *dev)
{
+ netif_stop_queue(dev);
/* disable recv */
de620_set_register(dev, W_TCR, RXOFF);
-
free_irq(dev->irq, dev);
-
- dev->start = 0;
MOD_DEC_USE_COUNT;
return 0;
}
@@ -506,38 +503,37 @@ static void de620_set_multicast_list(struct net_device *dev)
}
/*******************************************************
+ *
+ * Handle timeouts on transmit
+ */
+
+static void de620_timeout(struct net_device *dev)
+{
+ printk("%s: transmit timed out, %s?\n",
+ dev->name,
+ "network cable problem"
+ );
+ /* Restart the adapter. */
+ if (!adapter_init(dev)) /* maybe close it */
+ netif_wake_queue(dev);
+}
+
+/*******************************************************
*
* Copy a buffer to the adapter transmit page memory.
* Start sending.
*/
-static int
-de620_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int de620_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned long flags;
int len;
- int tickssofar;
byte *buffer = skb->data;
byte using_txbuf;
using_txbuf = de620_tx_buffs(dev); /* Peek at the adapter */
- dev->tbusy = (using_txbuf == (TXBF0 | TXBF1)); /* Boolean! */
-
- if (dev->tbusy) { /* Do timeouts, to avoid hangs. */
- tickssofar = jiffies - dev->trans_start;
-
- if (tickssofar < 5)
- return 1;
-
- /* else */
- printk("%s: transmit timed out (%d), %s?\n",
- dev->name,
- tickssofar,
- "network cable problem"
- );
- /* Restart the adapter. */
- if (adapter_init(dev)) /* maybe close it */
- return 1;
- }
+
+ netif_stop_queue(dev);
+
if ((len = skb->len) < RUNT)
len = RUNT;
@@ -565,7 +561,7 @@ de620_start_xmit(struct sk_buff *skb, struct net_device *dev)
break;
case (TXBF0 | TXBF1): /* NONE!!! */
- printk("de620: Ouch! No tx-buffer available!\n");
+ printk(KERN_WARNING "%s: No tx-buffer available!\n", dev->name);
restore_flags(flags);
return 1;
break;
@@ -573,14 +569,12 @@ de620_start_xmit(struct sk_buff *skb, struct net_device *dev)
de620_write_block(dev, buffer, len);
dev->trans_start = jiffies;
- dev->tbusy = (using_txbuf == (TXBF0 | TXBF1)); /* Boolean! */
+ if(!(using_txbuf == (TXBF0 | TXBF1)))
+ netif_wake_queue(dev);
((struct net_device_stats *)(dev->priv))->tx_packets++;
-
restore_flags(flags); /* interrupts maybe back on */
-
dev_kfree_skb (skb);
-
return 0;
}
@@ -589,8 +583,7 @@ de620_start_xmit(struct sk_buff *skb, struct net_device *dev)
* Handle the network interface interrupts.
*
*/
-static void
-de620_interrupt(int irq_in, void *dev_id, struct pt_regs *regs)
+static void de620_interrupt(int irq_in, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
byte irq_status;
@@ -603,9 +596,6 @@ de620_interrupt(int irq_in, void *dev_id, struct pt_regs *regs)
return;
}
- cli();
- dev->interrupt = 1;
-
/* Read the status register (_not_ the status port) */
irq_status = de620_get_register(dev, R_STS);
@@ -619,11 +609,8 @@ de620_interrupt(int irq_in, void *dev_id, struct pt_regs *regs)
while (again && (++bogus_count < 100));
}
- dev->tbusy = (de620_tx_buffs(dev) == (TXBF0 | TXBF1)); /* Boolean! */
-
- dev->interrupt = 0;
- sti();
- return;
+ if(de620_tx_buffs(dev) != (TXBF0 | TXBF1))
+ netif_wake_queue(dev);
}
/**************************************
@@ -633,8 +620,7 @@ de620_interrupt(int irq_in, void *dev_id, struct pt_regs *regs)
* Send it "upstairs"
*
*/
-static int
-de620_rx_intr(struct net_device *dev)
+static int de620_rx_intr(struct net_device *dev)
{
struct header_buf {
byte status;
@@ -663,9 +649,10 @@ de620_rx_intr(struct net_device *dev)
pagelink = header_buf.Rx_NextPage;
if ((pagelink < first_rx_page) || (last_rx_page < pagelink)) {
/* Ouch... Forget it! Skip all and start afresh... */
- printk("%s: Ring overrun? Restoring...\n", dev->name);
+ printk(KERN_WARNING "%s: Ring overrun? Restoring...\n", dev->name);
/* You win some, you lose some. And sometimes plenty... */
adapter_init(dev);
+ netif_wake_queue(dev);
((struct net_device_stats *)(dev->priv))->rx_over_errors++;
return 0;
}
@@ -682,7 +669,7 @@ de620_rx_intr(struct net_device *dev)
/* Is the _computed_ next page number equal to what the adapter says? */
if (pagelink != header_buf.Rx_NextPage) {
/* Naah, we'll skip this packet. Probably bogus data as well */
- printk("%s: Page link out of sync! Restoring...\n", dev->name);
+ printk(KERN_WARNING "%s: Page link out of sync! Restoring...\n", dev->name);
next_rx_page = header_buf.Rx_NextPage; /* at least a try... */
de620_send_command(dev, W_DUMMY);
de620_set_register(dev, W_NPRF, next_rx_page);
@@ -693,12 +680,12 @@ de620_rx_intr(struct net_device *dev)
size = header_buf.Rx_ByteCount - 4;
if ((size < RUNT) || (GIANT < size)) {
- printk("%s: Illegal packet size: %d!\n", dev->name, size);
+ printk(KERN_WARNING "%s: Illegal packet size: %d!\n", dev->name, size);
}
else { /* Good packet? */
skb = dev_alloc_skb(size+2);
if (skb == NULL) { /* Yeah, but no place to put it... */
- printk("%s: Couldn't allocate a sk_buff of size %d.\n",
+ printk(KERN_WARNING "%s: Couldn't allocate a sk_buff of size %d.\n",
dev->name, size);
((struct net_device_stats *)(dev->priv))->rx_dropped++;
}
@@ -732,8 +719,7 @@ de620_rx_intr(struct net_device *dev)
* Reset the adapter to a known state
*
*/
-static int
-adapter_init(struct net_device *dev)
+static int adapter_init(struct net_device *dev)
{
int i;
static int was_down = 0;
@@ -787,11 +773,11 @@ adapter_init(struct net_device *dev)
/* ignore: EEDI RXGOOD COLS LNKS*/
if (((i = de620_get_register(dev, R_STS)) & CHECK_MASK) != CHECK_OK) {
- printk("Something has happened to the DE-620! Please check it"
+ printk(KERN_ERR "%s: Something has happened to the DE-620! Please check it"
#ifdef SHUTDOWN_WHEN_LOST
" and do a new ifconfig"
#endif
- "! (%02x)\n", i);
+ "! (%02x)\n", dev->name, i);
#ifdef SHUTDOWN_WHEN_LOST
/* Goodbye, cruel world... */
dev->flags &= ~IFF_UP;
@@ -801,7 +787,7 @@ adapter_init(struct net_device *dev)
return 1; /* failed */
}
if (was_down) {
- printk("Thanks, I feel much better now!\n");
+ printk(KERN_WARNING "%s: Thanks, I feel much better now!\n", dev->name);
was_down = 0;
}
@@ -820,8 +806,7 @@ adapter_init(struct net_device *dev)
*
* Check if there is a DE-620 connected
*/
-int __init
-de620_probe(struct net_device *dev)
+int __init de620_probe(struct net_device *dev)
{
static struct net_device_stats de620_netstats;
int i;
@@ -837,7 +822,7 @@ de620_probe(struct net_device *dev)
if (de620_debug)
printk(version);
- printk("D-Link DE-620 pocket adapter");
+ printk(KERN_INFO "D-Link DE-620 pocket adapter");
/* Initially, configure basic nibble mode, so we can read the EEPROM */
NIC_Cmd = DEF_NIC_CMD;
@@ -880,11 +865,14 @@ de620_probe(struct net_device *dev)
dev->priv = &de620_netstats;
memset(dev->priv, 0, sizeof(struct net_device_stats));
- dev->get_stats = get_stats;
- dev->open = de620_open;
- dev->stop = de620_close;
- dev->hard_start_xmit = &de620_start_xmit;
- dev->set_multicast_list = &de620_set_multicast_list;
+ dev->get_stats = get_stats;
+ dev->open = de620_open;
+ dev->stop = de620_close;
+ dev->hard_start_xmit = de620_start_xmit;
+ dev->tx_timeout = de620_timeout;
+ dev->watchdog_timeo = HZ*2;
+ dev->set_multicast_list = de620_set_multicast_list;
+
/* base_addr and irq are already set, see above! */
ether_setup(dev);
@@ -913,8 +901,7 @@ de620_probe(struct net_device *dev)
*/
#define sendit(dev,data) de620_set_register(dev, W_EIP, data | EIPRegister);
-static unsigned short __init
-ReadAWord(struct net_device *dev, int from)
+static unsigned short __init ReadAWord(struct net_device *dev, int from)
{
unsigned short data;
int nbits;
@@ -956,8 +943,7 @@ ReadAWord(struct net_device *dev, int from)
return data;
}
-static int __init
-read_eeprom(struct net_device *dev)
+static int __init read_eeprom(struct net_device *dev)
{
unsigned short wrd;
@@ -1003,16 +989,14 @@ static char nullname[8] = "";
static struct net_device de620_dev = {
nullname, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, de620_probe };
-int
-init_module(void)
+int init_module(void)
{
if (register_netdev(&de620_dev) != 0)
return -EIO;
return 0;
}
-void
-cleanup_module(void)
+void cleanup_module(void)
{
unregister_netdev(&de620_dev);
release_region(de620_dev.base_addr, 3);
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index be62ef741..b3851ef09 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -253,7 +253,7 @@ static int dfx_close(struct net_device *dev);
static void dfx_int_pr_halt_id(DFX_board_t *bp);
static void dfx_int_type_0_process(DFX_board_t *bp);
-static void dfx_int_common(DFX_board_t *bp);
+static void dfx_int_common(struct net_device *dev);
static void dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static struct net_device_stats *dfx_ctl_get_stats(struct net_device *dev);
@@ -272,7 +272,7 @@ static void dfx_rcv_init(DFX_board_t *bp);
static void dfx_rcv_queue_process(DFX_board_t *bp);
static int dfx_xmt_queue_pkt(struct sk_buff *skb, struct net_device *dev);
-static void dfx_xmt_done(DFX_board_t *bp);
+static int dfx_xmt_done(DFX_board_t *bp);
static void dfx_xmt_flush(DFX_board_t *bp);
/* Define module-wide (static) variables */
@@ -1423,9 +1423,7 @@ int dfx_open(
/* Set device structure info */
- dev->tbusy = 0;
- dev->interrupt = DFX_UNMASK_INTERRUPTS;
- dev->start = 1;
+ netif_start_queue(dev);
return(0);
}
@@ -1511,9 +1509,8 @@ int dfx_close(
/* Clear device structure flags */
- dev->start = 0;
- dev->tbusy = 1;
-
+ netif_stop_queue(dev);
+
/* Deregister (free) IRQ */
free_irq(dev->irq, dev);
@@ -1804,16 +1801,15 @@ void dfx_int_type_0_process(
* or updating completion indices.
*/
-void dfx_int_common(
- DFX_board_t *bp
- )
-
- {
+void dfx_int_common(struct net_device *dev)
+{
+ DFX_board_t *bp = (DFX_board_t *) dev->priv;
PI_UINT32 port_status; /* Port Status register */
/* Process xmt interrupts - frequent case, so always call this routine */
- dfx_xmt_done(bp); /* free consumed xmt packets */
+ if(dfx_xmt_done(bp)) /* free consumed xmt packets */
+ netif_wake_queue(dev);
/* Process rcv interrupts - frequent case, so always call this routine */
@@ -1889,21 +1885,12 @@ void dfx_interrupt(
/* Get board pointer only if device structure is valid */
- if (dev == NULL)
- {
- printk("dfx_interrupt(): irq %d for unknown device!\n", irq);
- return;
- }
bp = (DFX_board_t *) dev->priv;
spin_lock(&bp->lock);
/* See if we're already servicing an interrupt */
- if (dev->interrupt)
- printk("%s: Re-entering the interrupt handler!\n", dev->name);
- dev->interrupt = DFX_MASK_INTERRUPTS; /* ensure non reentrancy */
-
/* Service adapter interrupts */
if (bp->bus_type == DFX_BUS_TYPE_PCI)
@@ -1914,7 +1901,7 @@ void dfx_interrupt(
/* Call interrupt service routine for this adapter */
- dfx_int_common(bp);
+ dfx_int_common(dev);
/* Clear PDQ interrupt status bit and reenable interrupts */
@@ -1932,7 +1919,7 @@ void dfx_interrupt(
/* Call interrupt service routine for this adapter */
- dfx_int_common(bp);
+ dfx_int_common(dev);
/* Reenable interrupts at the ESIC */
@@ -1941,7 +1928,6 @@ void dfx_interrupt(
dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, tmp);
}
- dev->interrupt = DFX_UNMASK_INTERRUPTS;
spin_unlock(&bp->lock);
return;
}
@@ -3199,6 +3185,8 @@ int dfx_xmt_queue_pkt(
XMT_DRIVER_DESCR *p_xmt_drv_descr; /* ptr to transmit driver descriptor */
unsigned long flags;
+ netif_stop_queue(dev);
+
/*
* Verify that incoming transmit request is OK
*
@@ -3213,7 +3201,7 @@ int dfx_xmt_queue_pkt(
printk("%s: Invalid packet length - %u bytes\n",
dev->name, skb->len);
bp->xmt_length_errors++; /* bump error counter */
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
dev_kfree_skb(skb);
return(0); /* return "success" */
}
@@ -3237,6 +3225,7 @@ int dfx_xmt_queue_pkt(
{
bp->xmt_discards++; /* bump error counter */
dev_kfree_skb(skb); /* free sk_buff now */
+ netif_wake_queue(dev);
return(0); /* return "success" */
}
}
@@ -3339,6 +3328,7 @@ int dfx_xmt_queue_pkt(
bp->rcv_xmt_reg.index.xmt_prod = prod;
dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_2_PROD, bp->rcv_xmt_reg.lword);
spin_unlock_irqrestore(&bp->lock, flags);
+ netif_wake_queue(dev);
return(0); /* packet queued to adapter */
}
@@ -3375,13 +3365,14 @@ int dfx_xmt_queue_pkt(
* None
*/
-void dfx_xmt_done(
+int dfx_xmt_done(
DFX_board_t *bp
)
{
XMT_DRIVER_DESCR *p_xmt_drv_descr; /* ptr to transmit driver descriptor */
PI_TYPE_2_CONSUMER *p_type_2_cons; /* ptr to rcv/xmt consumer block register */
+ int freed = 0; /* buffers freed */
/* Service all consumed transmit frames */
@@ -3413,8 +3404,9 @@ void dfx_xmt_done(
*/
bp->rcv_xmt_reg.index.xmt_comp += 1;
+ freed++;
}
- return;
+ return freed;
}
diff --git a/drivers/net/depca.c b/drivers/net/depca.c
index bfcc78744..06d9e6171 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/depca.c
@@ -270,6 +270,8 @@ static int depca_debug = 1;
#define DEPCA_NDA 0xffe0 /* No Device Address */
+#define TX_TIMEOUT (1*HZ)
+
/*
** Ethernet PROM defines
*/
@@ -387,6 +389,7 @@ struct depca_private {
int rx_new, tx_new; /* The next free ring entry */
int rx_old, tx_old; /* The ring entries to be free()ed. */
struct net_device_stats stats;
+ spinlock_t lock;
struct { /* Private stats counters */
u32 bins[DEPCA_PKT_STAT_SZ];
u32 unicast;
@@ -421,6 +424,7 @@ static int depca_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void depca_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int depca_close(struct net_device *dev);
static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static void depca_tx_timeout (struct net_device *dev);
static struct net_device_stats *depca_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
@@ -584,6 +588,7 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
memset((char *)dev->priv, 0, sizeof(struct depca_private));
lp->adapter = adapter;
lp->mca_slot = mca_slot;
+ lp->lock = SPIN_LOCK_UNLOCKED;
sprintf(lp->adapter_name,"%s (%s)", name, dev->name);
request_region(ioaddr, DEPCA_TOTAL_SIZE, lp->adapter_name);
@@ -703,6 +708,8 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
dev->get_stats = &depca_get_stats;
dev->set_multicast_list = &set_multicast_list;
dev->do_ioctl = &depca_ioctl;
+ dev->tx_timeout = depca_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
dev->mem_start = 0;
@@ -755,9 +762,7 @@ depca_open(struct net_device *dev)
outb(nicsr, DEPCA_NICSR);
outw(CSR0,DEPCA_ADDR);
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue(dev);
status = InitRestartDepca(dev);
@@ -781,7 +786,7 @@ depca_init_ring(struct net_device *dev)
u_long p;
/* Lock out other processes whilst setting up the hardware */
- test_and_set_bit(0, (void *)&dev->tbusy);
+ netif_stop_queue(dev);
lp->rx_new = lp->tx_new = 0;
lp->rx_old = lp->tx_old = 0;
@@ -809,122 +814,110 @@ depca_init_ring(struct net_device *dev)
}
lp->init_block.mode = 0x0000; /* Enable the Tx and Rx */
+}
- return;
+
+static void depca_tx_timeout (struct net_device *dev)
+{
+ u_long ioaddr = dev->base_addr;
+
+ printk ("%s: transmit timed out, status %04x, resetting.\n",
+ dev->name, inw (DEPCA_DATA));
+
+ STOP_DEPCA;
+ depca_init_ring (dev);
+ LoadCSRs (dev);
+ dev->trans_start = jiffies;
+ netif_wake_queue (dev);
+ InitRestartDepca (dev);
}
+
/*
** Writes a socket buffer to TX descriptor ring and starts transmission
*/
-static int
-depca_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int depca_start_xmit (struct sk_buff *skb, struct net_device *dev)
{
- struct depca_private *lp = (struct depca_private *)dev->priv;
- u_long ioaddr = dev->base_addr;
- int status = 0;
+ struct depca_private *lp = (struct depca_private *) dev->priv;
+ u_long ioaddr = dev->base_addr;
+ int status = 0;
- /* Transmitter timeout, serious problems. */
- if (dev->tbusy) {
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 1*HZ) {
- status = -1;
- } else {
- printk("%s: transmit timed out, status %04x, resetting.\n",
- dev->name, inw(DEPCA_DATA));
-
- STOP_DEPCA;
- depca_init_ring(dev);
- LoadCSRs(dev);
- dev->interrupt = UNMASK_INTERRUPTS;
- dev->start = 1;
- dev->tbusy=0;
- dev->trans_start = jiffies;
- InitRestartDepca(dev);
- }
- return status;
- } else if (skb->len > 0) {
- /* Enforce 1 process per h/w access */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
- printk("%s: Transmitter access conflict.\n", dev->name);
- status = -1;
- } else {
- if (TX_BUFFS_AVAIL) { /* Fill in a Tx ring entry */
- status = load_packet(dev, skb);
+ /* Transmitter timeout, serious problems. */
+ if (skb->len < 1)
+ goto out;
- if (!status) {
- /* Trigger an immediate send demand. */
- outw(CSR0, DEPCA_ADDR);
- outw(INEA | TDMD, DEPCA_DATA);
-
- dev->trans_start = jiffies;
- dev_kfree_skb(skb);
- }
- if (TX_BUFFS_AVAIL) {
- dev->tbusy=0;
- }
- } else {
- status = -1;
- }
- }
- }
-
- return status;
+ netif_stop_queue (dev);
+
+ if (TX_BUFFS_AVAIL) { /* Fill in a Tx ring entry */
+ status = load_packet (dev, skb);
+
+ if (!status) {
+ /* Trigger an immediate send demand. */
+ outw (CSR0, DEPCA_ADDR);
+ outw (INEA | TDMD, DEPCA_DATA);
+
+ dev->trans_start = jiffies;
+ dev_kfree_skb (skb);
+ }
+ if (TX_BUFFS_AVAIL)
+ netif_start_queue (dev);
+ } else
+ status = -1;
+
+out:
+ return status;
}
/*
** The DEPCA interrupt handler.
*/
-static void
-depca_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void depca_interrupt (int irq, void *dev_id, struct pt_regs *regs)
{
- struct net_device *dev = dev_id;
- struct depca_private *lp;
- s16 csr0, nicsr;
- u_long ioaddr;
+ struct net_device *dev = dev_id;
+ struct depca_private *lp;
+ s16 csr0, nicsr;
+ u_long ioaddr;
- if (dev == NULL) {
- printk ("depca_interrupt(): irq %d for unknown device.\n", irq);
- } else {
- lp = (struct depca_private *)dev->priv;
- ioaddr = dev->base_addr;
-
- if (dev->interrupt)
- printk("%s: Re-entering the interrupt handler.\n", dev->name);
+ if (dev == NULL) {
+ printk ("depca_interrupt(): irq %d for unknown device.\n", irq);
+ return;
+ }
- dev->interrupt = MASK_INTERRUPTS;
+ lp = (struct depca_private *) dev->priv;
+ ioaddr = dev->base_addr;
- /* mask the DEPCA board interrupts and turn on the LED */
- nicsr = inb(DEPCA_NICSR);
- nicsr |= (IM|LED);
- outb(nicsr, DEPCA_NICSR);
+ spin_lock (&lp->lock);
- outw(CSR0, DEPCA_ADDR);
- csr0 = inw(DEPCA_DATA);
+ /* mask the DEPCA board interrupts and turn on the LED */
+ nicsr = inb (DEPCA_NICSR);
+ nicsr |= (IM | LED);
+ outb (nicsr, DEPCA_NICSR);
- /* Acknowledge all of the current interrupt sources ASAP. */
- outw(csr0 & INTE, DEPCA_DATA);
+ outw (CSR0, DEPCA_ADDR);
+ csr0 = inw (DEPCA_DATA);
- if (csr0 & RINT) /* Rx interrupt (packet arrived) */
- depca_rx(dev);
+ /* Acknowledge all of the current interrupt sources ASAP. */
+ outw (csr0 & INTE, DEPCA_DATA);
- if (csr0 & TINT) /* Tx interrupt (packet sent) */
- depca_tx(dev);
+ if (csr0 & RINT) /* Rx interrupt (packet arrived) */
+ depca_rx (dev);
- if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) { /* any resources available? */
- dev->tbusy = 0; /* clear TX busy flag */
- mark_bh(NET_BH);
- }
+ if (csr0 & TINT) /* Tx interrupt (packet sent) */
+ depca_tx (dev);
- /* Unmask the DEPCA board interrupts and turn off the LED */
- nicsr = (nicsr & ~IM & ~LED);
- outb(nicsr, DEPCA_NICSR);
+ /* Any resources available? */
+ if ((TX_BUFFS_AVAIL >= 0) && netif_queue_stopped(dev)) {
+ netif_wake_queue (dev);
- dev->interrupt = UNMASK_INTERRUPTS;
- }
+ /* Unmask the DEPCA board interrupts and turn off the LED */
+ nicsr = (nicsr & ~IM & ~LED);
+ outb (nicsr, DEPCA_NICSR);
+ }
- return;
+ spin_unlock (&lp->lock);
}
+
static int
depca_rx(struct net_device *dev)
{
@@ -1070,8 +1063,7 @@ depca_close(struct net_device *dev)
s16 nicsr;
u_long ioaddr = dev->base_addr;
- dev->start = 0;
- dev->tbusy = 1;
+ netif_stop_queue(dev);
outw(CSR0, DEPCA_ADDR);
@@ -1173,8 +1165,7 @@ set_multicast_list(struct net_device *dev)
u_long ioaddr = dev->base_addr;
if (dev) {
- while(dev->tbusy) barrier(); /* Stop ring access */
- set_bit(0, (void*)&dev->tbusy);
+ netif_stop_queue(dev);
while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */
STOP_DEPCA; /* Temporarily stop the depca. */
@@ -1189,7 +1180,7 @@ set_multicast_list(struct net_device *dev)
LoadCSRs(dev); /* Reload CSR3 */
InitRestartDepca(dev); /* Resume normal operation. */
- dev->tbusy = 0; /* Unlock the TX ring */
+ netif_start_queue(dev); /* Unlock the TX ring */
}
}
@@ -1909,21 +1900,19 @@ static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
for (i=0; i<ETH_ALEN; i++) {
dev->dev_addr[i] = tmp.addr[i];
}
- while(dev->tbusy) barrier(); /* Stop ring access */
- test_and_set_bit(0, (void*)&dev->tbusy);
+ netif_stop_queue(dev);
while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */
STOP_DEPCA; /* Temporarily stop the depca. */
depca_init_ring(dev); /* Initialize the descriptor rings */
LoadCSRs(dev); /* Reload CSR3 */
InitRestartDepca(dev); /* Resume normal operation. */
- dev->tbusy = 0; /* Unlock the TX ring */
+ netif_start_queue(dev); /* Unlock the TX ring */
break;
case DEPCA_SET_PROM: /* Set Promiscuous Mode */
if (!capable(CAP_NET_ADMIN)) return -EPERM;
- while(dev->tbusy) barrier(); /* Stop ring access */
- test_and_set_bit(0, (void*)&dev->tbusy);
+ netif_stop_queue(dev);
while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */
STOP_DEPCA; /* Temporarily stop the depca. */
@@ -1932,13 +1921,12 @@ static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
LoadCSRs(dev); /* Reload CSR3 */
InitRestartDepca(dev); /* Resume normal operation. */
- dev->tbusy = 0; /* Unlock the TX ring */
+ netif_start_queue(dev); /* Unlock the TX ring */
break;
case DEPCA_CLR_PROM: /* Clear Promiscuous Mode */
if (!capable(CAP_NET_ADMIN)) return -EPERM;
- while(dev->tbusy) barrier(); /* Stop ring access */
- test_and_set_bit(0, (void*)&dev->tbusy);
+ netif_stop_queue(dev);
while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */
STOP_DEPCA; /* Temporarily stop the depca. */
@@ -1947,7 +1935,7 @@ static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
LoadCSRs(dev); /* Reload CSR3 */
InitRestartDepca(dev); /* Resume normal operation. */
- dev->tbusy = 0; /* Unlock the TX ring */
+ netif_start_queue(dev); /* Unlock the TX ring */
break;
case DEPCA_SAY_BOO: /* Say "Boo!" to the kernel log file */
diff --git a/drivers/net/dmfe.c b/drivers/net/dmfe.c
index e341ed226..01a32afd5 100644
--- a/drivers/net/dmfe.c
+++ b/drivers/net/dmfe.c
@@ -460,8 +460,6 @@ static int dmfe_open(struct net_device *dev)
dmfe_init_dm910x(dev);
/* Active System Interface */
- dev->tbusy = 0; /* Can transmit packet */
- dev->start = 1; /* interface ready */
MOD_INC_USE_COUNT;
/* set and active a timer process */
@@ -470,6 +468,8 @@ static int dmfe_open(struct net_device *dev)
db->timer.data = (unsigned long) dev;
db->timer.function = &dmfe_timer;
add_timer(&db->timer);
+
+ netif_wake_queue(dev);
return 0;
}
@@ -543,24 +543,18 @@ static int dmfe_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct tx_desc *txptr;
DMFE_DBUG(0, "dmfe_start_xmit", 0);
-
- if ((dev->tbusy == 1) && (db->tx_packet_cnt != 0))
- return 1;
- else
- dev->tbusy = 0;
-
+
+ netif_stop_queue(dev);
+
/* Too large packet check */
if (skb->len > MAX_PACKET_SIZE) {
- printk(KERN_ERR "%s: oversized frame (%d bytes) received.\n", dev->name, (u16) skb->len);
+ printk(KERN_ERR "%s: oversized frame (%d bytes) for transmit.\n", dev->name, (u16) skb->len);
dev_kfree_skb(skb);
return 0;
}
/* No Tx resource check, it never happen nromally */
if (db->tx_packet_cnt >= TX_FREE_DESC_CNT) {
- printk(KERN_WARNING "%s: No Tx resource, enter xmit() again \n", dev->name);
- dev_kfree_skb(skb);
- dev->tbusy = 1;
- return -EBUSY;
+ return 1;
}
/* transmit this packet */
@@ -580,8 +574,8 @@ static int dmfe_start_xmit(struct sk_buff *skb, struct net_device *dev)
outl(0x1, dev->base_addr + DCR1);
/* Tx resource check */
- if (db->tx_packet_cnt >= TX_FREE_DESC_CNT)
- dev->tbusy = 1;
+ if (db->tx_packet_cnt < TX_FREE_DESC_CNT)
+ netif_wake_queue(dev);
/* Set transmit time stamp */
dev->trans_start = jiffies; /* saved the time stamp */
@@ -603,9 +597,7 @@ static int dmfe_stop(struct net_device *dev)
DMFE_DBUG(0, "dmfe_stop", 0);
- /* disable system */
- dev->start = 0; /* interface disable */
- dev->tbusy = 1; /* can't transmit */
+ netif_stop_queue(dev);
/* Reset & stop DM910X board */
outl(DM910X_RESET, ioaddr + DCR0);
@@ -645,13 +637,8 @@ static void dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)
DMFE_DBUG(1, "dmfe_interrupt() without device arg", 0);
return;
}
- if (dev->interrupt) {
- DMFE_DBUG(1, "dmfe_interrupt() re-entry ", 0);
- return;
- }
/* A real interrupt coming */
- dev->interrupt = 1; /* Lock interrupt */
db = (struct dmfe_board_info *) dev->priv;
ioaddr = dev->base_addr;
@@ -669,10 +656,9 @@ static void dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (db->cr5_data & 0x2000) {
/* A system bus error occurred */
DMFE_DBUG(1, "A system bus error occurred. CR5=", db->cr5_data);
- dev->tbusy = 1;
+ netif_stop_queue(dev);
db->wait_reset = 1; /* Need to RESET */
outl(0, ioaddr + DCR7); /* disable all interrupt */
- dev->interrupt = 0; /* unlock interrupt */
return;
}
/* Free the transmitted descriptor */
@@ -690,10 +676,9 @@ static void dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
db->tx_remove_ptr = (struct tx_desc *) txptr;
- if (dev->tbusy && (db->tx_packet_cnt < TX_FREE_DESC_CNT)) {
- dev->tbusy = 0; /* free a resource */
- mark_bh(NET_BH); /* active bottom half */
- }
+ if (db->tx_packet_cnt < TX_FREE_DESC_CNT)
+ netif_wake_queue(dev);
+
/* Received the coming packet */
if (db->rx_avail_cnt)
dmfe_rx_packet(dev, db);
@@ -708,7 +693,6 @@ static void dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)
db->cr6_data |= 0x100;
update_cr6(db->cr6_data, db->ioaddr);
}
- dev->interrupt = 0; /* release interrupt lock */
/* Restore CR7 to enable interrupt mask */
@@ -935,9 +919,8 @@ static void dmfe_dynamic_reset(struct net_device *dev)
db->in_reset_state = 1;
/* Disable upper layer interface */
- dev->tbusy = 1; /* transmit packet disable */
- dev->start = 0; /* interface not ready */
-
+ netif_stop_queue(dev);
+
db->cr6_data &= ~(CR6_RXSC | CR6_TXSC); /* Disable Tx/Rx */
update_cr6(db->cr6_data, dev->base_addr);
@@ -954,12 +937,11 @@ static void dmfe_dynamic_reset(struct net_device *dev)
/* Re-initilize DM910X board */
dmfe_init_dm910x(dev);
- /* Restart upper layer interface */
- dev->tbusy = 0; /* Can transmit packet */
- dev->start = 1; /* interface ready */
-
/* Leave dynamic reser route */
db->in_reset_state = 0;
+
+ /* Restart upper layer interface */
+ netif_wake_queue(dev);
}
/*
@@ -1113,7 +1095,7 @@ static void send_filter_frame(struct net_device *dev, int mc_cnt)
/* prepare the setup frame */
db->tx_packet_cnt++;
- dev->tbusy = 1;
+ netif_stop_queue(dev);
txptr->tdes1 = 0x890000c0;
txptr->tdes0 = 0x80000000;
db->tx_insert_ptr = (struct tx_desc *) txptr->next_tx_desc;
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index 21236be77..c9e7beaca 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -987,7 +987,7 @@ static void eepro_tx_timeout (struct net_device *dev)
lp->tx_last = 0;
dev->trans_start = jiffies;
- netif_start_queue (dev);
+ netif_wake_queue (dev);
outb (RCV_ENABLE_CMD, ioaddr);
}
@@ -1001,6 +1001,8 @@ static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev)
if (net_debug > 5)
printk(KERN_DEBUG "%s: entering eepro_send_packet routine.\n", dev->name);
+ netif_stop_queue (dev);
+
spin_lock_irqsave(&lp->lock, flags);
{
@@ -1014,7 +1016,7 @@ static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev)
}
- compat_dev_kfree_skb (skb, FREE_WRITE);
+ dev_kfree_skb (skb);
/* You might need to clean up and record Tx statistics here. */
/* lp->stats.tx_aborted_errors++; */
@@ -1407,8 +1409,8 @@ hardware_send_packet(struct net_device *dev, void *buf, short length)
lp->tx_last = last;
lp->tx_end = end;
- if (test_bit(LINK_STATE_XOFF, &dev->flags))
- netif_start_queue(dev);
+ if (netif_queue_stopped(dev))
+ netif_wake_queue(dev);
/* Enable RX and TX interrupts */
outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index e651be8a8..8410c0cf8 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -1,7 +1,9 @@
-/* drivers/net/eepro100.c: An Intel i82557-559 Ethernet driver for Linux. */
/*
- NOTICE: this version tested with kernels 1.3.72 and later only!
+
+ drivers/net/eepro100.c: An Intel i82557-559 Ethernet driver for Linux
+
Written 1996-1999 by Donald Becker.
+ Modified 2000 by Linux Kernel Team
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
@@ -20,132 +22,15 @@
http://cesdis.gsfc.nasa.gov/linux/misc/modules.html
There is a Majordomo mailing list based at
linux-eepro100@cesdis.gsfc.nasa.gov
-*/
-
-static const char *version =
-"eepro100.c:v1.09j 7/27/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n";
-
-/* A few user-configurable values that apply to all boards.
- First set is undocumented and spelled per Intel recommendations. */
-
-static int congenb = 0; /* Enable congestion control in the DP83840. */
-static int txfifo = 8; /* Tx FIFO threshold in 4 byte units, 0-15 */
-static int rxfifo = 8; /* Rx FIFO threshold, default 32 bytes. */
-/* Tx/Rx DMA burst length, 0-127, 0 == no preemption, tx==128 -> disabled. */
-static int txdmacount = 128;
-static int rxdmacount = 0;
-
-/* Set the copy breakpoint for the copy-only-tiny-buffer Rx method.
- Lower values use more memory, but are faster. */
-static int rx_copybreak = 200;
-
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 20;
-
-/* Maximum number of multicast addresses to filter (vs. rx-all-multicast) */
-static int multicast_filter_limit = 64;
-
-/* 'options' is used to pass a transceiver override or full-duplex flag
- e.g. "options=16" for FD, "options=32" for 100mbps-only. */
-static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int debug = -1; /* The debug level */
-
-/* A few values that may be tweaked. */
-/* The ring sizes should be a power of two for efficiency. */
-#define TX_RING_SIZE 32 /* Effectively 2 entries fewer. */
-#define RX_RING_SIZE 32
-/* Actual number of TX packets queued, must be <= TX_RING_SIZE-2. */
-#define TX_QUEUE_LIMIT 12
-
-/* Operational parameters that usually are not changed. */
-
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT (2*HZ)
-/* Size of an pre-allocated Rx buffer: <Ethernet MTU> + slack.*/
-#define PKT_BUF_SZ 1536
-
-#if !defined(__OPTIMIZE__) || !defined(__KERNEL__)
-#warning You must compile this file with the correct options!
-#warning See the last lines of the source file.
-#error You must compile this driver with "-O".
-#endif
-
-#include <linux/version.h>
-#include <linux/module.h>
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/malloc.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#ifdef HAS_PCI_NETIF
-#include "pci-netif.h"
-#else
-#include <linux/pci.h>
-#if LINUX_VERSION_CODE < 0x20155
-#include <linux/bios32.h> /* Ignore the bogus warning in 2.1.100+ */
-#endif
-#endif
-#include <linux/spinlock.h>
-#include <linux/init.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/delay.h>
-
-MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
-MODULE_DESCRIPTION("Intel i82557/i82558 PCI EtherExpressPro driver");
-MODULE_PARM(debug, "i");
-MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(congenb, "i");
-MODULE_PARM(txfifo, "i");
-MODULE_PARM(rxfifo, "i");
-MODULE_PARM(txdmacount, "i");
-MODULE_PARM(rxdmacount, "i");
-MODULE_PARM(rx_copybreak, "i");
-MODULE_PARM(max_interrupt_work, "i");
-MODULE_PARM(multicast_filter_limit, "i");
-#define RUN_AT(x) (jiffies + (x))
-#if (LINUX_VERSION_CODE < 0x20123)
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#define le16_to_cpu(val) (val)
-#define cpu_to_le16(val) (val)
-#define le32_to_cpu(val) (val)
-#define cpu_to_le32(val) (val)
-#define spin_lock_irqsave(&sp->lock, flags) save_flags(flags); cli();
-#define spin_unlock_irqrestore(&sp->lock, flags); restore_flags(flags);
-#endif
-#if LINUX_VERSION_CODE < 0x20159
-#define dev_free_skb(skb) dev_kfree_skb(skb, FREE_WRITE);
-#else
-#define dev_free_skb(skb) dev_kfree_skb(skb);
-#endif
-#if ! defined(CAP_NET_ADMIN)
-#define capable(CAP_XXX) (suser())
-#endif
-#if ! defined(HAS_NETIF_QUEUE)
-#define netif_wake_queue(dev) mark_bh(NET_BH);
-#endif
+ Version history:
+ v1.09j+LK1.0 - Jeff Garzik <jgarzik@mandrakesoft.com>
+ Convert to new PCI driver interface
-/* The total I/O port extent of the board.
- The registers beyond 0x18 only exist on the i82558. */
-#define SPEEDO3_TOTAL_SIZE 0x20
-int speedo_debug = 1;
-/*
Theory of Operation
I. Board Compatibility
@@ -277,40 +162,118 @@ having to sign an Intel NDA when I'm helping Intel sell their own product!
*/
-/* This table drives the PCI probe routines. */
-static struct net_device *speedo_found1(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
-#ifdef USE_IO
-#define SPEEDO_IOTYPE PCI_USES_MASTER|PCI_USES_IO|PCI_ADDR1
-#define SPEEDO_SIZE 32
-#else
-#define SPEEDO_IOTYPE PCI_USES_MASTER|PCI_USES_MEM|PCI_ADDR0
-#define SPEEDO_SIZE 0x1000
+static const char *version =
+"eepro100.c:v1.09j+LK1.0 Feb 13, 2000 Linux Kernel Team http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n";
+
+/* A few user-configurable values that apply to all boards.
+ First set is undocumented and spelled per Intel recommendations. */
+
+static int congenb = 0; /* Enable congestion control in the DP83840. */
+static int txfifo = 8; /* Tx FIFO threshold in 4 byte units, 0-15 */
+static int rxfifo = 8; /* Rx FIFO threshold, default 32 bytes. */
+/* Tx/Rx DMA burst length, 0-127, 0 == no preemption, tx==128 -> disabled. */
+static int txdmacount = 128;
+static int rxdmacount = 0;
+
+/* Set the copy breakpoint for the copy-only-tiny-buffer Rx method.
+ Lower values use more memory, but are faster. */
+static int rx_copybreak = 200;
+
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static int max_interrupt_work = 20;
+
+/* Maximum number of multicast addresses to filter (vs. rx-all-multicast) */
+static int multicast_filter_limit = 64;
+
+/* 'options' is used to pass a transceiver override or full-duplex flag
+ e.g. "options=16" for FD, "options=32" for 100mbps-only. */
+static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int debug = -1; /* The debug level */
+
+/* A few values that may be tweaked. */
+/* The ring sizes should be a power of two for efficiency. */
+#define TX_RING_SIZE 32 /* Effectively 2 entries fewer. */
+#define RX_RING_SIZE 32
+/* Actual number of TX packets queued, must be <= TX_RING_SIZE-2. */
+#define TX_QUEUE_LIMIT 12
+
+/* Operational parameters that usually are not changed. */
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT (2*HZ)
+/* Size of an pre-allocated Rx buffer: <Ethernet MTU> + slack.*/
+#define PKT_BUF_SZ 1536
+
+#if !defined(__OPTIMIZE__) || !defined(__KERNEL__)
+#warning You must compile this file with the correct options!
+#warning See the last lines of the source file.
+#error You must compile this driver with "-O".
#endif
-#if defined(HAS_PCI_NETIF)
-struct pci_id_info static pci_tbl[] = {
- { "Intel PCI EtherExpress Pro100",
- { 0x12298086, 0xffffffff,}, SPEEDO_IOTYPE, SPEEDO_SIZE,
- 0, speedo_found1 },
- {0,}, /* 0 terminated list. */
-};
-#else
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+
+MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
+MODULE_DESCRIPTION("Intel i82557/i82558 PCI EtherExpressPro driver");
+MODULE_PARM(debug, "i");
+MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(congenb, "i");
+MODULE_PARM(txfifo, "i");
+MODULE_PARM(rxfifo, "i");
+MODULE_PARM(txdmacount, "i");
+MODULE_PARM(rxdmacount, "i");
+MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(max_interrupt_work, "i");
+MODULE_PARM(multicast_filter_limit, "i");
+
+#define EEPRO100_MODULE_NAME "eepro100"
+#define PFX EEPRO100_MODULE_NAME ": "
+
+#define RUN_AT(x) (jiffies + (x))
+
+/* ACPI power states don't universally work (yet) */
+#ifndef CONFIG_EEPRO100_PM
+#undef pci_set_power_state
+#define pci_set_power_state null_set_power_state
+static inline int null_set_power_state(struct pci_dev *dev, int state)
+{
+ return 0;
+}
+#endif /* CONFIG_EEPRO100_PM */
+
+
+/* compile-time switch to en/disable slow PIO */
+#undef USE_IO
+
+
+int speedo_debug = 1;
+
+
enum pci_flags_bit {
PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
};
-struct pci_id_info {
- const char *name;
- u16 vendor_id, device_id, device_id_mask, flags;
- int io_size;
- struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
-} static pci_tbl[] = {
- { "Intel PCI EtherExpress Pro100",
- 0x8086, 0x1229, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 32, speedo_found1 },
- {0,}, /* 0 terminated list. */
-};
-#endif
#ifndef USE_IO
#define inb readb
@@ -321,34 +284,45 @@ struct pci_id_info {
#define outl writel
#endif
+
/* How to wait for the command unit to accept a command.
Typically this takes 0 ticks. */
-static inline void wait_for_cmd_done(long cmd_ioaddr)
+static inline void wait_for_cmd_done (long cmd_ioaddr)
{
int wait = 100;
- do ;
- while(inb(cmd_ioaddr) && --wait >= 0);
+ do;
+ while (inb (cmd_ioaddr) && --wait >= 0);
}
+
/* Offsets to the various registers.
All accesses need not be longword aligned. */
enum speedo_offsets {
SCBStatus = 0, SCBCmd = 2, /* Rx/Command Unit command and status. */
- SCBPointer = 4, /* General purpose pointer. */
- SCBPort = 8, /* Misc. commands and operands. */
- SCBflash = 12, SCBeeprom = 14, /* EEPROM and flash memory control. */
- SCBCtrlMDI = 16, /* MDI interface control. */
- SCBEarlyRx = 20, /* Early receive byte count. */
+ SCBPointer = 4, /* General purpose pointer. */
+ SCBPort = 8, /* Misc. commands and operands. */
+ SCBflash = 12, SCBeeprom = 14, /* EEPROM and flash memory control. */
+ SCBCtrlMDI = 16, /* MDI interface control. */
+ SCBEarlyRx = 20, /* Early receive byte count. */
};
+
+
/* Commands that can be put in a command list entry. */
enum commands {
- CmdNOp = 0, CmdIASetup = 0x10000, CmdConfigure = 0x20000,
- CmdMulticastList = 0x30000, CmdTx = 0x40000, CmdTDR = 0x50000,
- CmdDump = 0x60000, CmdDiagnose = 0x70000,
+ CmdNOp = 0,
+ CmdIASetup = 0x10000,
+ CmdConfigure = 0x20000,
+ CmdMulticastList = 0x30000,
+ CmdTx = 0x40000,
+ CmdTDR = 0x50000,
+ CmdDump = 0x60000,
+ CmdDiagnose = 0x70000,
CmdSuspend = 0x40000000, /* Suspend after completion. */
CmdIntr = 0x20000000, /* Interrupt after completion. */
CmdTxFlex = 0x00080000, /* Use "Flexible mode" for CmdTx command. */
};
+
+
/* Do atomically if possible. */
#if defined(__i386__) || defined(__alpha__) || defined(__ia64__)
#define clear_suspend(cmd) clear_bit(30, &(cmd)->cmd_status)
@@ -362,54 +336,75 @@ enum commands {
#endif
enum SCBCmdBits {
- SCBMaskCmdDone=0x8000, SCBMaskRxDone=0x4000, SCBMaskCmdIdle=0x2000,
- SCBMaskRxSuspend=0x1000, SCBMaskEarlyRx=0x0800, SCBMaskFlowCtl=0x0400,
- SCBTriggerIntr=0x0200, SCBMaskAll=0x0100,
- /* The rest are Rx and Tx commands. */
- CUStart=0x0010, CUResume=0x0020, CUStatsAddr=0x0040, CUShowStats=0x0050,
- CUCmdBase=0x0060, /* CU Base address (set to zero) . */
- CUDumpStats=0x0070, /* Dump then reset stats counters. */
- RxStart=0x0001, RxResume=0x0002, RxAbort=0x0004, RxAddrLoad=0x0006,
- RxResumeNoResources=0x0007,
+ SCBMaskCmdDone = 0x8000,
+ SCBMaskRxDone = 0x4000,
+ SCBMaskCmdIdle = 0x2000,
+ SCBMaskRxSuspend = 0x1000,
+ SCBMaskEarlyRx = 0x0800,
+ SCBMaskFlowCtl = 0x0400,
+ SCBTriggerIntr = 0x0200,
+ SCBMaskAll = 0x0100,
+ /* The rest are Rx and Tx commands. */
+ CUStart = 0x0010,
+ CUResume = 0x0020,
+ CUStatsAddr = 0x0040,
+ CUShowStats = 0x0050,
+ CUCmdBase = 0x0060, /* CU Base address (set to zero) . */
+ CUDumpStats = 0x0070, /* Dump then reset stats counters. */
+ RxStart = 0x0001,
+ RxResume = 0x0002,
+ RxAbort = 0x0004,
+ RxAddrLoad = 0x0006,
+ RxResumeNoResources = 0x0007,
};
enum SCBPort_cmds {
- PortReset=0, PortSelfTest=1, PortPartialReset=2, PortDump=3,
+ PortReset = 0,
+ PortSelfTest = 1,
+ PortPartialReset = 2,
+ PortDump = 3,
};
/* The Speedo3 Rx and Tx frame/buffer descriptors. */
-struct descriptor { /* A generic descriptor. */
- s32 cmd_status; /* All command and status fields. */
- u32 link; /* struct descriptor * */
+struct descriptor { /* A generic descriptor. */
+ s32 cmd_status; /* All command and status fields. */
+ u32 link; /* struct descriptor * */
unsigned char params[0];
};
/* The Speedo3 Rx and Tx buffer descriptors. */
-struct RxFD { /* Receive frame descriptor. */
+struct RxFD { /* Receive frame descriptor. */
s32 status;
- u32 link; /* struct RxFD * */
- u32 rx_buf_addr; /* void * */
+ u32 link; /* struct RxFD * */
+ u32 rx_buf_addr; /* void * */
u32 count;
};
/* Selected elements of the Tx/RxFD.status word. */
enum RxFD_bits {
- RxComplete=0x8000, RxOK=0x2000,
- RxErrCRC=0x0800, RxErrAlign=0x0400, RxErrTooBig=0x0200, RxErrSymbol=0x0010,
- RxEth2Type=0x0020, RxNoMatch=0x0004, RxNoIAMatch=0x0002,
- TxUnderrun=0x1000, StatusComplete=0x8000,
+ RxComplete = 0x8000,
+ RxOK = 0x2000,
+ RxErrCRC = 0x0800,
+ RxErrAlign = 0x0400,
+ RxErrTooBig = 0x0200,
+ RxErrSymbol = 0x0010,
+ RxEth2Type = 0x0020,
+ RxNoMatch = 0x0004,
+ RxNoIAMatch = 0x0002,
+ TxUnderrun = 0x1000,
+ StatusComplete = 0x8000,
};
-struct TxFD { /* Transmit frame descriptor set. */
+struct TxFD { /* Transmit frame descriptor set. */
s32 status;
- u32 link; /* void * */
- u32 tx_desc_addr; /* Always points to the tx_buf_addr element. */
- s32 count; /* # of TBD (=1), Tx start thresh., etc. */
+ u32 link; /* void * */
+ u32 tx_desc_addr; /* Always points to the tx_buf_addr element. */
+ s32 count; /* # of TBD (=1), Tx start thresh., etc. */
/* This constitutes two "TBD" entries -- we only use one. */
- u32 tx_buf_addr0; /* void *, frame to be transmitted. */
- s32 tx_buf_size0; /* Length of Tx frame. */
- u32 tx_buf_addr1; /* void *, frame to be transmitted. */
- s32 tx_buf_size1; /* Length of Tx frame. */
+ u32 tx_buf_addr0; /* void *, frame to be transmitted. */
+ s32 tx_buf_size0; /* Length of Tx frame. */
+ u32 tx_buf_addr1; /* void *, frame to be transmitted. */
+ s32 tx_buf_size1; /* Length of Tx frame. */
};
/* Elements of the dump_statistics block. This block must be lword aligned. */
@@ -436,46 +431,43 @@ struct speedo_stats {
/* Do not change the position (alignment) of the first few elements!
The later elements are grouped for cache locality. */
struct speedo_private {
- struct TxFD *tx_ring; /* Commands (usually CmdTxPacket). */
- struct RxFD *rx_ringp[RX_RING_SIZE]; /* Rx descriptor, used as ring. */
+ struct TxFD *tx_ring; /* Commands (usually CmdTxPacket). */
+ struct RxFD *rx_ringp[RX_RING_SIZE];/* Rx descriptor, used as ring. */
/* The addresses of a Tx/Rx-in-place packets/buffers. */
- struct sk_buff* tx_skbuff[TX_RING_SIZE];
- struct sk_buff* rx_skbuff[RX_RING_SIZE];
- dma_addr_t rx_ring_dma[RX_RING_SIZE];
- dma_addr_t tx_ring_dma;
- struct descriptor *last_cmd; /* Last command sent. */
+ struct sk_buff *tx_skbuff[TX_RING_SIZE];
+ struct sk_buff *rx_skbuff[RX_RING_SIZE];
+ dma_addr_t rx_ring_dma[RX_RING_SIZE];
+ dma_addr_t tx_ring_dma;
+ struct descriptor *last_cmd; /* Last command sent. */
unsigned int cur_tx, dirty_tx; /* The ring entries to be free()ed. */
- spinlock_t lock; /* Group with Tx control cache line. */
- u32 tx_threshold; /* The value for txdesc.count. */
- struct RxFD *last_rxf; /* Last command sent. */
- unsigned int cur_rx, dirty_rx; /* The next free ring entry */
- long last_rx_time; /* Last Rx, in jiffies, to handle Rx hang. */
+ spinlock_t lock; /* Group with Tx control cache line. */
+ u32 tx_threshold; /* The value for txdesc.count. */
+ struct RxFD *last_rxf; /* Last command sent. */
+ unsigned int cur_rx, dirty_rx; /* The next free ring entry */
+ long last_rx_time; /* Last Rx, in jiffies, to handle Rx hang. */
const char *product_name;
- struct net_device *next_module;
- void *priv_addr; /* Unaligned address for kfree */
struct enet_statistics stats;
struct speedo_stats *lstats;
int chip_id;
- unsigned char pci_bus, pci_devfn, acpi_pwr;
+ unsigned char acpi_pwr;
struct pci_dev *pdev;
struct timer_list timer; /* Media selection timer. */
- int mc_setup_frm_len; /* The length of an allocated.. */
- struct descriptor *mc_setup_frm; /* ..multicast setup frame. */
- int mc_setup_busy; /* Avoid double-use of setup frame. */
+ int mc_setup_frm_len; /* The length of an allocated.. */
+ struct descriptor *mc_setup_frm;/* ..multicast setup frame. */
+ int mc_setup_busy; /* Avoid double-use of setup frame. */
dma_addr_t mc_setup_dma;
- char rx_mode; /* Current PROMISC/ALLMULTI setting. */
- unsigned int tx_full:1; /* The Tx queue is full. */
- unsigned int full_duplex:1; /* Full-duplex operation requested. */
- unsigned int flow_ctrl:1; /* Use 802.3x flow control. */
- unsigned int rx_bug:1; /* Work around receiver hang errata. */
- unsigned int rx_bug10:1; /* Receiver might hang at 10mbps. */
- unsigned int rx_bug100:1; /* Receiver might hang at 100mbps. */
- unsigned char default_port:8; /* Last dev->if_port value. */
- unsigned short phy[2]; /* PHY media interfaces available. */
- unsigned short advertising; /* Current PHY advertised caps. */
- unsigned short partner; /* Link partner caps. */
+ char rx_mode; /* Current PROMISC/ALLMULTI setting. */
+ unsigned int tx_full:1; /* The Tx queue is full. */
+ unsigned int full_duplex:1; /* Full-duplex operation requested. */
+ unsigned int flow_ctrl:1; /* Use 802.3x flow control. */
+ unsigned int rx_bug:1; /* Work around receiver hang errata. */
+ unsigned int rx_bug10:1; /* Receiver might hang at 10mbps. */
+ unsigned int rx_bug100:1; /* Receiver might hang at 100mbps. */
+ unsigned char default_port:8; /* Last dev->if_port value. */
+ unsigned short phy[2]; /* PHY media interfaces available. */
+ unsigned short advertising; /* Current PHY advertised caps. */
+ unsigned short partner; /* Link partner caps. */
};
-
/* The parameters for a CmdConfigure operation.
There are so many options that it would be difficult to document each bit.
We mostly use the default or recommended settings. */
@@ -526,139 +518,75 @@ static int mii_ctrl[8] = { 0x3300, 0x3100, 0x0000, 0x0100,
0x2000, 0x2100, 0x0400, 0x3100};
#endif
-/* A list of all installed Speedo devices, for removing the driver module. */
-static struct net_device *root_speedo_dev = NULL;
-
-#if ! defined(HAS_PCI_NETIF)
-int eepro100_init(void)
-{
- int cards_found = 0;
- static int pci_index = 0;
-
- if (! pcibios_present())
- return cards_found;
-
- for (; pci_index < 8; pci_index++) {
- unsigned char pci_bus, pci_device_fn, pci_latency;
- long ioaddr;
- int irq;
-
- u16 pci_command, new_command;
-
- if (pcibios_find_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82557,
- pci_index, &pci_bus,
- &pci_device_fn))
- break;
-#if LINUX_VERSION_CODE >= 0x20155 || PCI_SUPPORT_1
- {
- struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
-#ifdef USE_IO
- ioaddr = pdev->resource[1].start;
-#else
- ioaddr = pdev->resource[0].start;
-#endif
- irq = pdev->irq;
- }
-#else
- {
- u32 pciaddr;
- u8 pci_irq_line;
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_INTERRUPT_LINE, &pci_irq_line);
- /* Note: BASE_ADDRESS_0 is for memory-mapping the registers. */
-#ifdef USE_IO
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_1, &pciaddr);
- pciaddr &= ~3UL;
-#else
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_0, &pciaddr);
-#endif
- ioaddr = pciaddr;
- irq = pci_irq_line;
- }
-#endif
- /* Remove I/O space marker in bit 0. */
-#ifdef USE_IO
- if (check_region(ioaddr, 32))
- continue;
-#else
- {
- unsigned long orig_ioaddr = ioaddr;
-
- if ((ioaddr = (long)ioremap(ioaddr & ~0xfUL, 0x1000)) == 0) {
- printk(KERN_INFO "Failed to map PCI address %#lx.\n",
- orig_ioaddr);
- continue;
- }
- }
-#endif
- if (speedo_debug > 2)
- printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n",
- ioaddr, irq);
-
- /* Get and check the bus-master and latency values. */
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, &pci_command);
- new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
- if (pci_command != new_command) {
- printk(KERN_INFO " The PCI BIOS has not enabled this"
- " device! Updating PCI command %4.4x->%4.4x.\n",
- pci_command, new_command);
- pcibios_write_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, new_command);
- }
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, &pci_latency);
- if (pci_latency < 32) {
- printk(" PCI latency timer (CFLT) is unreasonably low at %d."
- " Setting to 32 clocks.\n", pci_latency);
- pcibios_write_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, 32);
- } else if (speedo_debug > 1)
- printk(" PCI latency timer (CFLT) is %#x.\n", pci_latency);
-
- if(speedo_found1(pci_bus, pci_device_fn, ioaddr, irq, 0,cards_found))
- cards_found++;
- }
- return cards_found;
-}
-#endif
-static struct net_device *speedo_found1(int pci_bus, int pci_devfn,
- long ioaddr, int irq, int chip_idx, int card_idx)
+static int __devinit eepro100_init_one (struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct net_device *dev;
struct speedo_private *sp;
- struct pci_dev *pdev;
unsigned char *tx_ring;
dma_addr_t tx_ring_dma;
const char *product;
int i, option;
u16 eeprom[0x100];
- int acpi_idle_state = 0;
+ int acpi_idle_state = 0, pm, irq;
+ unsigned long ioaddr;
+ static int card_idx = -1;
static int did_version = 0; /* Already printed version info. */
+
+#ifdef USE_IO
+ ioaddr = pci_resource_start (pdev, 0);
+#else
+ ioaddr = pci_resource_start (pdev, 1);
+#endif
+ irq = pdev->irq;
+
+ card_idx++;
+
+ if (!request_region (pci_resource_start (pdev, 1),
+ pci_resource_len (pdev, 1),
+ EEPRO100_MODULE_NAME)) {
+ printk (KERN_ERR PFX "cannot reserve I/O ports\n");
+ goto err_out_none;
+ }
+ if (!request_mem_region (pci_resource_start (pdev, 0),
+ pci_resource_len (pdev, 0),
+ EEPRO100_MODULE_NAME)) {
+ printk (KERN_ERR PFX "cannot reserve MMIO region\n");
+ goto err_out_free_pio_region;
+ }
+
+#ifndef USE_IO
+ ioaddr = (unsigned long) ioremap (pci_resource_start (pdev, 0),
+ pci_resource_len (pdev, 0));
+ if (!ioaddr) {
+ printk (KERN_ERR PFX "cannot remap MMIO region %lx @ %lx\n",
+ pci_resource_len (pdev, 0),
+ pci_resource_start (pdev, 0));
+ goto err_out_free_mmio_region;
+ }
+#endif
+
if (speedo_debug > 0 && did_version++ == 0)
printk(version);
- pdev = pci_find_slot(pci_bus, pci_devfn);
-
tx_ring = pci_alloc_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD)
+ sizeof(struct speedo_stats), &tx_ring_dma);
if (!tx_ring) {
- printk(KERN_ERR "Could not allocate DMA memory.\n");
- return NULL;
+ printk(KERN_ERR PFX "Could not allocate DMA memory.\n");
+ goto err_out_iounmap;
}
dev = init_etherdev(NULL, sizeof(struct speedo_private));
if (dev == NULL) {
- pci_free_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD)
- + sizeof(struct speedo_stats),
- tx_ring, tx_ring_dma);
- return NULL;
+ printk(KERN_ERR PFX "Could not allocate ethernet device.\n");
+ goto err_out_free_tx_ring;
+ }
+ if (dev->priv == NULL) {
+ printk(KERN_ERR PFX "Could not allocate ethernet device private info.\n");
+ goto err_out_free_netdev;
}
if (dev->mem_start > 0)
@@ -668,9 +596,16 @@ static struct net_device *speedo_found1(int pci_bus, int pci_devfn,
else
option = 0;
-#if defined(HAS_PCI_NETIF)
- acpi_idle_state = acpi_set_pwr_state(pci_bus, pci_devfn, ACPI_D0);
-#endif
+ /* save power state b4 pci_enable_device overwrites it */
+ pm = pci_find_capability(pdev, PCI_CAP_ID_PM);
+ if (pm) {
+ u16 pwr_command;
+ pci_read_config_word(pdev, pm + PCI_PM_CTRL, &pwr_command);
+ acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
+ }
+
+ pci_enable_device (pdev);
+ pci_set_master (pdev);
/* Read the station address EEPROM before doing the reset.
Nominally his should even be done before accepting the device, but
@@ -716,7 +651,7 @@ static struct net_device *speedo_found1(int pci_bus, int pci_devfn,
if (eeprom[3] & 0x0100)
product = "OEM i82557/i82558 10/100 Ethernet";
else
- product = pci_tbl[chip_idx].name;
+ product = "Intel PCI EtherExpress Pro100";
printk(KERN_INFO "%s: %s at %#3lx, ", dev->name, product, ioaddr);
@@ -724,7 +659,7 @@ static struct net_device *speedo_found1(int pci_bus, int pci_devfn,
printk("%2.2X:", dev->dev_addr[i]);
printk("%2.2X, IRQ %d.\n", dev->dev_addr[i], irq);
-#ifndef kernel_bloat
+#if 1
/* OK, this is pure kernel bloat. I don't like it when other drivers
waste non-pageable kernel space to emit similar messages, but I need
them for bug reports. */
@@ -793,41 +728,29 @@ static struct net_device *speedo_found1(int pci_bus, int pci_devfn,
#endif /* kernel_bloat */
outl(PortReset, ioaddr + SCBPort);
-#if defined(HAS_PCI_NETIF)
- /* Return the chip to its original power state. */
- acpi_set_pwr_state(pci_bus, pci_devfn, acpi_idle_state);
-#endif
- /* We do a request_region() only to register /proc/ioports info. */
- request_region(ioaddr, SPEEDO3_TOTAL_SIZE, "Intel Speedo3 Ethernet");
+ /* Return the chip to its original power state. */
+ pci_set_power_state (pdev, acpi_idle_state);
dev->base_addr = ioaddr;
dev->irq = irq;
sp = dev->priv;
- if (dev->priv == NULL) {
- void *mem = kmalloc(sizeof(*sp), GFP_KERNEL);
- dev->priv = sp = mem; /* Cache align here if kmalloc does not. */
- sp->priv_addr = mem;
- }
memset(sp, 0, sizeof(*sp));
- sp->next_module = root_speedo_dev;
- root_speedo_dev = dev;
- sp->pci_bus = pci_bus;
- sp->pci_devfn = pci_devfn;
sp->pdev = pdev;
- sp->chip_id = chip_idx;
sp->acpi_pwr = acpi_idle_state;
sp->tx_ring = (struct TxFD *)tx_ring;
sp->tx_ring_dma = tx_ring_dma;
sp->lstats = (struct speedo_stats *)(sp->tx_ring + TX_RING_SIZE);
sp->full_duplex = option >= 0 && (option & 0x10) ? 1 : 0;
+
if (card_idx >= 0) {
if (full_duplex[card_idx] >= 0)
sp->full_duplex = full_duplex[card_idx];
}
+
sp->default_port = option >= 0 ? (option & 0x0f) : 0;
sp->phy[0] = eeprom[6];
@@ -847,9 +770,30 @@ static struct net_device *speedo_found1(int pci_bus, int pci_devfn,
dev->set_multicast_list = &set_rx_mode;
dev->do_ioctl = &speedo_ioctl;
- return dev;
+ return 0;
+
+err_out_free_netdev:
+ unregister_netdevice (dev);
+ kfree (dev);
+err_out_free_tx_ring:
+ pci_free_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD)
+ + sizeof(struct speedo_stats),
+ tx_ring, tx_ring_dma);
+err_out_iounmap:
+#ifndef USE_IO
+ iounmap ((void *)ioaddr);
+err_out_free_mmio_region:
+#endif
+ release_mem_region (pci_resource_start (pdev, 0),
+ pci_resource_len (pdev, 0));
+err_out_free_pio_region:
+ release_region (pci_resource_start (pdev, 1),
+ pci_resource_len (pdev, 1));
+err_out_none:
+ return -ENODEV;
}
-
+
+
/* Serial EEPROM section.
A "bit" grungy, but we work our way through bit-by-bit :->. */
/* EEPROM_Ctrl bits. */
@@ -925,13 +869,11 @@ speedo_open(struct net_device *dev)
struct speedo_private *sp = (struct speedo_private *)dev->priv;
long ioaddr = dev->base_addr;
-#if defined(HAS_PCI_NETIF)
- acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0);
-#endif
-
if (speedo_debug > 1)
printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq);
+ pci_set_power_state(sp->pdev, 0);
+
/* Set up the Tx queue early.. */
sp->cur_tx = 0;
sp->dirty_tx = 0;
@@ -940,9 +882,9 @@ speedo_open(struct net_device *dev)
spin_lock_init(&sp->lock);
/* .. we can safely take handler calls during init. */
- if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev)) {
- return -EAGAIN;
- }
+ if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev))
+ return -EBUSY;
+
MOD_INC_USE_COUNT;
dev->if_port = sp->default_port;
@@ -970,7 +912,6 @@ speedo_open(struct net_device *dev)
/* Fire up the hardware. */
speedo_resume(dev);
- clear_bit(LINK_STATE_RXSEM, &dev->state);
netif_start_queue(dev);
/* Setup the chip and configure the multicast list. */
@@ -1059,6 +1000,8 @@ static void speedo_resume(struct net_device *dev)
+ (sp->dirty_tx % TX_RING_SIZE) * sizeof(struct TxFD),
ioaddr + SCBPointer);
outw(CUStart, ioaddr + SCBCmd);
+
+ netif_start_queue (dev);
}
/* Media monitoring and control. */
@@ -1158,7 +1101,7 @@ speedo_init_rx_ring(struct net_device *dev)
rxf = (struct RxFD *)skb->tail;
sp->rx_ringp[i] = rxf;
sp->rx_ring_dma[i] =
- pci_map_single(sp->pdev, rxf, PKT_BUF_SZ + sizeof(struct RxFD));
+ pci_map_single(sp->pdev, rxf, PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
skb_reserve(skb, sizeof(struct RxFD));
if (last_rxf)
last_rxf->link = cpu_to_le32(sp->rx_ring_dma[i]);
@@ -1220,9 +1163,10 @@ static void speedo_tx_timeout(struct net_device *dev)
}
sp->stats.tx_errors++;
dev->trans_start = jiffies;
- return;
+ netif_start_queue (dev);
}
+
static int
speedo_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
@@ -1230,6 +1174,8 @@ speedo_start_xmit(struct sk_buff *skb, struct net_device *dev)
long ioaddr = dev->base_addr;
int entry;
+ netif_stop_queue (dev);
+
/* Caution: the write order is important here, set the base address
with the "ownership" bits last. */
@@ -1256,7 +1202,7 @@ speedo_start_xmit(struct sk_buff *skb, struct net_device *dev)
sp->tx_ring[entry].count = cpu_to_le32(sp->tx_threshold);
sp->tx_ring[entry].tx_buf_addr0 =
cpu_to_le32(pci_map_single(sp->pdev, skb->data,
- skb->len));
+ skb->len, PCI_DMA_TODEVICE));
sp->tx_ring[entry].tx_buf_size0 = cpu_to_le32(skb->len);
/* Todo: perhaps leave the interrupt bit set if the Tx queue is more
than half full. Argument against: we should be receiving packets
@@ -1270,13 +1216,15 @@ speedo_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
if (sp->cur_tx - sp->dirty_tx >= TX_QUEUE_LIMIT) {
sp->tx_full = 1;
- netif_stop_queue(dev);
}
spin_unlock_irqrestore(&sp->lock, flags);
}
wait_for_cmd_done(ioaddr + SCBCmd);
outw(CUResume, ioaddr + SCBCmd);
dev->trans_start = jiffies;
+
+ if (! sp->tx_full)
+ netif_start_queue (dev);
return 0;
}
@@ -1300,6 +1248,8 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
ioaddr = dev->base_addr;
sp = (struct speedo_private *)dev->priv;
+ spin_lock (&sp->lock);
+
do {
status = inw(ioaddr + SCBStatus);
/* Acknowledge all of the current interrupt sources ASAP. */
@@ -1330,7 +1280,6 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
/* User interrupt, Command/Tx unit interrupt or CU not active. */
if (status & 0xA400) {
unsigned int dirty_tx;
- spin_lock(&sp->lock);
dirty_tx = sp->dirty_tx;
while (sp->cur_tx - dirty_tx > 0) {
@@ -1348,19 +1297,18 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
/* Free the original skb. */
if (sp->tx_skbuff[entry]) {
sp->stats.tx_packets++; /* Count only user packets. */
-#if LINUX_VERSION_CODE > 0x20127
sp->stats.tx_bytes += sp->tx_skbuff[entry]->len;
-#endif
pci_unmap_single(sp->pdev,
le32_to_cpu(sp->tx_ring[entry].tx_buf_addr0),
- sp->tx_skbuff[entry]->len);
+ sp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE);
dev_kfree_skb_irq(sp->tx_skbuff[entry]);
sp->tx_skbuff[entry] = 0;
} else if ((status & 0x70000) == CmdNOp) {
if (sp->mc_setup_busy)
pci_unmap_single(sp->pdev,
sp->mc_setup_dma,
- sp->mc_setup_frm_len);
+ sp->mc_setup_frm_len,
+ PCI_DMA_TODEVICE);
sp->mc_setup_busy = 0;
}
dirty_tx++;
@@ -1380,10 +1328,12 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
&& sp->cur_tx - dirty_tx < TX_QUEUE_LIMIT - 1) {
/* The ring is no longer full, clear tbusy. */
sp->tx_full = 0;
- spin_unlock(&sp->lock);
- netif_wake_queue(dev);
- } else
- spin_unlock(&sp->lock);
+ }
+
+ if (sp->tx_full)
+ netif_stop_queue (dev);
+ else
+ netif_wake_queue (dev);
}
if (--boguscnt < 0) {
@@ -1399,7 +1349,7 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
dev->name, inw(ioaddr + SCBStatus));
- return;
+ spin_unlock (&sp->lock);
}
static int
@@ -1443,7 +1393,7 @@ speedo_rx(struct net_device *dev)
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
/* 'skb_put()' points to the start of sk_buff data area. */
pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry],
- PKT_BUF_SZ + sizeof(struct RxFD));
+ PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
#if 1 || USE_IP_CSUM
/* Packet is in one chunk -- we can copy + cksum. */
eth_copy_and_sum(skb, sp->rx_skbuff[entry]->tail, pkt_len, 0);
@@ -1465,14 +1415,12 @@ speedo_rx(struct net_device *dev)
temp = skb_put(skb, pkt_len);
sp->rx_ringp[entry] = NULL;
pci_unmap_single(sp->pdev, sp->rx_ring_dma[entry],
- PKT_BUF_SZ + sizeof(struct RxFD));
+ PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
}
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
sp->stats.rx_packets++;
-#if LINUX_VERSION_CODE > 0x20127
sp->stats.rx_bytes += pkt_len;
-#endif
}
entry = (++sp->cur_rx) % RX_RING_SIZE;
}
@@ -1493,7 +1441,7 @@ speedo_rx(struct net_device *dev)
rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail;
sp->rx_ring_dma[entry] =
pci_map_single(sp->pdev, rxf, PKT_BUF_SZ
- + sizeof(struct RxFD));
+ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
skb->dev = dev;
skb_reserve(skb, sizeof(struct RxFD));
rxf->rx_buf_addr = 0xffffffff;
@@ -1542,11 +1490,8 @@ speedo_close(struct net_device *dev)
if (skb) {
pci_unmap_single(sp->pdev,
sp->rx_ring_dma[i],
- PKT_BUF_SZ + sizeof(struct RxFD));
-#if LINUX_VERSION_CODE < 0x20100
- skb->free = 1;
-#endif
- dev_free_skb(skb);
+ PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(skb);
}
}
@@ -1558,8 +1503,8 @@ speedo_close(struct net_device *dev)
if (skb) {
pci_unmap_single(sp->pdev,
le32_to_cpu(sp->tx_ring[i].tx_buf_addr0),
- skb->len);
- dev_free_skb(skb);
+ skb->len, PCI_DMA_TODEVICE);
+ dev_kfree_skb(skb);
}
}
if (sp->mc_setup_frm) {
@@ -1571,10 +1516,9 @@ speedo_close(struct net_device *dev)
if (speedo_debug > 3)
speedo_show_state(dev);
-#if defined(HAS_PCI_NETIF)
/* Alt: acpi_set_pwr_state(pci_bus, pci_devfn, sp->acpi_pwr); */
- acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D2);
-#endif
+ pci_set_power_state (sp->pdev, 2);
+
MOD_DEC_USE_COUNT;
return 0;
@@ -1612,7 +1556,7 @@ speedo_get_stats(struct net_device *dev)
sp->stats.rx_fifo_errors += le32_to_cpu(sp->lstats->rx_overrun_errs);
sp->stats.rx_length_errors += le32_to_cpu(sp->lstats->rx_runt_errs);
sp->lstats->done_marker = 0x0000;
- if (test_bit(LINK_STATE_START, &dev->state)) {
+ if (netif_running(dev)) {
wait_for_cmd_done(ioaddr + SCBCmd);
outw(CUDumpStats, ioaddr + SCBCmd);
}
@@ -1626,32 +1570,22 @@ static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
long ioaddr = dev->base_addr;
u16 *data = (u16 *)&rq->ifr_data;
int phy = sp->phy[0] & 0x1f;
-#if defined(HAS_PCI_NETIF)
int saved_acpi;
-#endif
switch(cmd) {
case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
data[0] = phy;
case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
-#if defined(HAS_PCI_NETIF)
- saved_acpi = acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0);
- data[3] = mdio_read(ioaddr, data[0], data[1]);
- acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, saved_acpi);
-#else
- data[3] = mdio_read(ioaddr, data[0], data[1]);
-#endif
+ saved_acpi = pci_set_power_state (sp->pdev, 0);
+ data[3] = mdio_read (ioaddr, data[0], data[1]);
+ pci_set_power_state (sp->pdev, saved_acpi);
return 0;
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
if (!capable(CAP_NET_ADMIN))
return -EPERM;
-#if defined(HAS_PCI_NETIF)
- saved_acpi = acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, ACPI_D0);
- mdio_write(ioaddr, data[0], data[1], data[2]);
- acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, saved_acpi);
-#else
+ saved_acpi = pci_set_power_state(sp->pdev, 0);
mdio_write(ioaddr, data[0], data[1], data[2]);
-#endif
+ pci_set_power_state(sp->pdev, saved_acpi);
return 0;
default:
return -EOPNOTSUPP;
@@ -1814,7 +1748,7 @@ static void set_rx_mode(struct net_device *dev)
/* Change the command to a NoOp, pointing to the CmdMulti command. */
sp->tx_skbuff[entry] = 0;
sp->tx_ring[entry].status = cpu_to_le32(CmdNOp);
- sp->mc_setup_dma = pci_map_single(sp->pdev, mc_setup_frm, sp->mc_setup_frm_len);
+ sp->mc_setup_dma = pci_map_single(sp->pdev, mc_setup_frm, sp->mc_setup_frm_len, PCI_DMA_TODEVICE);
sp->tx_ring[entry].link = cpu_to_le32(sp->mc_setup_dma);
/* Set the link in the setup frame. */
@@ -1836,55 +1770,103 @@ static void set_rx_mode(struct net_device *dev)
}
+static void eepro100_suspend (struct pci_dev *pdev)
+{
+ struct net_device *dev = pdev->driver_data;
+ long ioaddr = dev->base_addr;
+
+ netif_device_detach(dev);
+ outl(PortPartialReset, ioaddr + SCBPort);
+
+ /* XXX call pci_set_power_state ()? */
+}
+
+
+static void eepro100_resume (struct pci_dev *pdev)
+{
+ struct net_device *dev = pdev->driver_data;
+ struct speedo_private *np = (struct speedo_private *)dev->priv;
+
+ netif_device_attach(dev);
+ speedo_resume(dev);
+ np->rx_mode = -1;
+ np->flow_ctrl = np->partner = 0;
+ set_rx_mode(dev);
+}
+
+
+static void __devexit eepro100_remove_one (struct pci_dev *pdev)
+{
+ struct net_device *dev = pdev->driver_data;
+ struct speedo_private *sp = (struct speedo_private *)dev->priv;
+
+ unregister_netdev (dev);
+
+ release_region (pci_resource_start (pdev, 1),
+ pci_resource_len (pdev, 1));
+ release_mem_region (pci_resource_start (pdev, 0),
+ pci_resource_len (pdev, 0));
+
+#ifndef USE_IO
+ iounmap ((char *) dev->base_addr);
+#endif
+
+ pci_set_power_state (pdev, sp->acpi_pwr);
+
+ pci_free_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD)
+ + sizeof(struct speedo_stats),
+ sp->tx_ring, sp->tx_ring_dma);
+
+ kfree (dev);
+}
+
+
+static struct pci_device_id eepro100_pci_tbl[] __devinitdata = {
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ { 0,},
+};
+MODULE_DEVICE_TABLE (pci, eepro100_pci_tbl);
+
+
+static struct pci_driver eepro100_driver = {
+ name: EEPRO100_MODULE_NAME,
+ id_table: eepro100_pci_tbl,
+ probe: eepro100_init_one,
+ remove: eepro100_remove_one,
+ suspend: eepro100_suspend,
+ resume: eepro100_resume,
+};
+
+
static int __init eepro100_init_module(void)
{
int cards_found;
if (debug >= 0)
speedo_debug = debug;
+
/* Always emit the version message. */
if (speedo_debug)
printk(KERN_INFO "%s", version);
-#if defined(HAS_PCI_NETIF)
- cards_found = netif_pci_probe(pci_tbl);
- if (cards_found < 0)
- printk(KERN_INFO "eepro100: No cards found, driver not installed.\n");
- return cards_found;
-#else
- cards_found = eepro100_init();
+ cards_found = pci_register_driver (&eepro100_driver);
if (cards_found <= 0) {
- printk(KERN_INFO "eepro100: No cards found, driver not installed.\n");
+ printk(KERN_INFO PFX "No cards found, driver not installed.\n");
+ pci_unregister_driver (&eepro100_driver);
return -ENODEV;
}
-#endif
+
return 0;
}
+
static void __exit eepro100_cleanup_module(void)
{
- struct net_device *next_dev;
-
- /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
- while (root_speedo_dev) {
- struct speedo_private *sp = (void *)root_speedo_dev->priv;
- unregister_netdev(root_speedo_dev);
-#ifdef USE_IO
- release_region(root_speedo_dev->base_addr, SPEEDO3_TOTAL_SIZE);
-#else
- iounmap((char *)root_speedo_dev->base_addr);
-#endif
-#if defined(HAS_PCI_NETIF)
- acpi_set_pwr_state(sp->pci_bus, sp->pci_devfn, sp->acpi_pwr);
-#endif
- next_dev = sp->next_module;
- if (sp->priv_addr)
- kfree(sp->priv_addr);
- kfree(root_speedo_dev);
- root_speedo_dev = next_dev;
- }
+ pci_unregister_driver (&eepro100_driver);
}
+
module_init(eepro100_init_module);
module_exit(eepro100_cleanup_module);
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index 0b04615ef..03c69417a 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -251,6 +251,7 @@ static char mca_irqmap[] = { 12, 9, 3, 4, 5, 10, 11, 15 };
extern int express_probe(struct net_device *dev);
static int eexp_open(struct net_device *dev);
static int eexp_close(struct net_device *dev);
+static void eexp_timeout(struct net_device *dev);
static struct net_device_stats *eexp_stats(struct net_device *dev);
static int eexp_xmit(struct sk_buff *buf, struct net_device *dev);
@@ -437,8 +438,6 @@ static int eexp_open(struct net_device *dev)
request_region(ioaddr+0x4000, 16, "EtherExpress shadow");
request_region(ioaddr+0x8000, 16, "EtherExpress shadow");
request_region(ioaddr+0xc000, 16, "EtherExpress shadow");
- dev->tbusy = 0;
- dev->interrupt = 0;
if (lp->width) {
printk("%s: forcing ASIC to 8-bit mode\n", dev->name);
@@ -446,8 +445,8 @@ static int eexp_open(struct net_device *dev)
}
eexp_hw_init586(dev);
- dev->start = 1;
MOD_INC_USE_COUNT;
+ netif_start_queue(dev);
#if NET_DEBUG > 6
printk(KERN_DEBUG "%s: leaving eexp_open()\n", dev->name);
#endif
@@ -465,9 +464,8 @@ static int eexp_close(struct net_device *dev)
int irq = dev->irq;
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
+
outb(SIRQ_dis|irqrmap[irq],ioaddr+SET_IRQ);
lp->started = 0;
scb_command(dev, SCB_CUsuspend|SCB_RUsuspend);
@@ -530,8 +528,7 @@ static void unstick_cu(struct net_device *dev)
outb(0,ioaddr+SIGNAL_CA);
}
}
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
}
else
{
@@ -546,13 +543,12 @@ static void unstick_cu(struct net_device *dev)
else
{
unsigned short txstatus = eexp_hw_lasttxstat(dev);
- if (dev->tbusy && !txstatus)
+ if (netif_queue_stopped(dev) && !txstatus)
{
printk(KERN_WARNING "%s: CU wedged, status %04x %04x, resetting...\n",
dev->name,status,txstatus);
eexp_hw_init586(dev);
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
}
else
{
@@ -570,12 +566,47 @@ static void unstick_cu(struct net_device *dev)
printk(KERN_WARNING "%s: i82586 startup timed out, status %04x, resetting...\n",
dev->name, status);
eexp_hw_init586(dev);
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
}
}
}
+static void eexp_timeout(struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+#ifdef CONFIG_SMP
+ unsigned long flags;
+#endif
+ int status;
+
+ disable_irq(dev->irq);
+
+ /*
+ * Best would be to use synchronize_irq(); spin_lock() here
+ * lets make it work first..
+ */
+
+#ifdef CONFIG_SMP
+ spin_lock_irqsave(&lp->lock, flags);
+#endif
+
+ status = scb_status(dev);
+ unstick_cu(dev);
+ printk(KERN_INFO "%s: transmit timed out, %s?", dev->name,
+ (SCB_complete(status)?"lost interrupt":
+ "board on fire"));
+ lp->stats.tx_errors++;
+ lp->last_tx = jiffies;
+ if (!SCB_complete(status)) {
+ scb_command(dev, SCB_CUabort);
+ outb(0,dev->base_addr+SIGNAL_CA);
+ }
+ netif_wake_queue(dev);
+#ifdef CONFIG_SMP
+ spin_unlock_irqrestore(&lp->lock, flags);
+#endif
+}
+
/*
* Called to transmit a packet, or to allow us to right ourselves
* if the kernel thinks we've died.
@@ -601,38 +632,7 @@ static int eexp_xmit(struct sk_buff *buf, struct net_device *dev)
#ifdef CONFIG_SMP
spin_lock_irqsave(&lp->lock, flags);
#endif
-
- /* If dev->tbusy is set, all our tx buffers are full but the kernel
- * is calling us anyway. Check that nothing bad is happening.
- */
- if (dev->tbusy) {
- int status = scb_status(dev);
- unstick_cu(dev);
- if ((jiffies - lp->last_tx) < HZ)
- {
-#ifdef CONFIG_SMP
- spin_unlock_irqrestore(&lp->lock, flags);
-#endif
-
- return 1;
- }
- printk(KERN_INFO "%s: transmit timed out, %s?", dev->name,
- (SCB_complete(status)?"lost interrupt":
- "board on fire"));
- lp->stats.tx_errors++;
- dev->tbusy = 0;
- lp->last_tx = jiffies;
- if (!SCB_complete(status)) {
- scb_command(dev, SCB_CUabort);
- outb(0,dev->base_addr+SIGNAL_CA);
- }
- }
- if (test_and_set_bit(0,(void *)&dev->tbusy))
- {
- lp->stats.tx_dropped++;
- }
- else
{
unsigned short length = (ETH_ZLEN < buf->len) ? buf->len :
ETH_ZLEN;
@@ -756,8 +756,6 @@ static void eexp_irq(int irq, void *dev_info, struct pt_regs *regs)
outb(SIRQ_dis|irqrmap[irq],ioaddr+SET_IRQ);
- dev->interrupt = 1;
-
status = scb_status(dev);
#if NET_DEBUG > 4
@@ -825,7 +823,6 @@ static void eexp_irq(int irq, void *dev_info, struct pt_regs *regs)
outb(SIRQ_en|irqrmap[irq],ioaddr+SET_IRQ);
- dev->interrupt = 0;
#if NET_DEBUG > 6
printk("%s: leaving eexp_irq()\n", dev->name);
#endif
@@ -1004,8 +1001,8 @@ static void eexp_hw_tx_pio(struct net_device *dev, unsigned short *buf,
else
lp->tx_head += TX_BUF_SIZE;
if (lp->tx_head != lp->tx_reap)
- dev->tbusy = 0;
-
+ netif_wake_queue(dev);
+
if (LOCKUP16 || lp->width) {
/* Restart the CU so that the packet can actually
be transmitted. (Zoltan Szilagyi 10-12-96) */
@@ -1141,6 +1138,8 @@ static int __init eexp_hw_probe(struct net_device *dev, unsigned short ioaddr)
dev->hard_start_xmit = eexp_xmit;
dev->get_stats = eexp_stats;
dev->set_multicast_list = &eexp_set_multicast;
+ dev->tx_timeout = eexp_timeout;
+ dev->watchdog_timeo = 2*HZ;
ether_setup(dev);
return 0;
}
@@ -1205,7 +1204,7 @@ static unsigned short eexp_hw_lasttxstat(struct net_device *dev)
unsigned short tx_block = lp->tx_reap;
unsigned short status;
- if ((!dev->tbusy) && lp->tx_head==lp->tx_reap)
+ if (!netif_queue_stopped(dev) && lp->tx_head==lp->tx_reap)
return 0x0000;
do
@@ -1254,8 +1253,7 @@ static unsigned short eexp_hw_lasttxstat(struct net_device *dev)
lp->tx_reap = tx_block = TX_BUF_START;
else
lp->tx_reap = tx_block += TX_BUF_SIZE;
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
}
while (lp->tx_reap != lp->tx_head);
@@ -1298,8 +1296,7 @@ static void eexp_hw_txrestart(struct net_device *dev)
{
printk(KERN_WARNING "%s: Failed to restart CU, resetting board...\n",dev->name);
eexp_hw_init586(dev);
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
return;
}
}
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index c7dfb7a65..1c546b4d1 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -15,8 +15,42 @@
Information and updates available at
http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html
+
+
+
+ Theory of Operation
+
+I. Board Compatibility
+
+This device driver is designed for the SMC "EPIC/100", the SMC
+single-chip Ethernet controllers for PCI. This chip is used on
+the SMC EtherPower II boards.
+
+II. Board-specific settings
+
+PCI bus devices are configured by the system at boot time, so no jumpers
+need to be set on the board. The system BIOS will assign the
+PCI INTA signal to a (preferably otherwise unused) system IRQ line.
+Note: Kernel versions earlier than 1.3.73 do not support shared PCI
+interrupt lines.
+
+III. Driver operation
+
+IIIa. Ring buffers
+
+IVb. References
+
+http://www.smsc.com/main/datasheets/83c171.pdf
+http://www.smsc.com/main/datasheets/83c175.pdf
+http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
+http://www.national.com/pf/DP/DP83840A.html
+
+IVc. Errata
+
*/
+
+
static const char *version =
"epic100.c:v1.04 8/23/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html\n";
@@ -56,7 +90,6 @@ static int max_interrupt_work = 10;
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
-#define PCI_SUPPORT_VER2
#include <linux/delay.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
@@ -72,6 +105,9 @@ static int max_interrupt_work = 10;
#define RUN_AT(x) (jiffies + (x))
+#define EPIC100_MODULE_NAME "epic100"
+#define PFX EPIC100_MODULE_NAME ": "
+
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_DESCRIPTION("SMC 83c170 EPIC series Ethernet driver");
MODULE_PARM(debug, "i");
@@ -79,7 +115,6 @@ MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
MODULE_PARM(rx_copybreak, "i");
MODULE_PARM(max_interrupt_work, "i");
-#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
/* The I/O extent. */
#define EPIC_TOTAL_SIZE 0x100
@@ -87,82 +122,88 @@ MODULE_PARM(max_interrupt_work, "i");
#define epic_debug debug
static int epic_debug = 1;
-/*
- Theory of Operation
-
-I. Board Compatibility
-
-This device driver is designed for the SMC "EPIC/100", the SMC
-single-chip Ethernet controllers for PCI. This chip is used on
-the SMC EtherPower II boards.
-
-II. Board-specific settings
-
-PCI bus devices are configured by the system at boot time, so no jumpers
-need to be set on the board. The system BIOS will assign the
-PCI INTA signal to a (preferably otherwise unused) system IRQ line.
-Note: Kernel versions earlier than 1.3.73 do not support shared PCI
-interrupt lines.
-
-III. Driver operation
+/* The rest of these values should never change. */
-IIIa. Ring buffers
-IVb. References
+enum pci_flags_bit {
+ PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
+ PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
+};
-http://www.smsc.com/main/datasheets/83c171.pdf
-http://www.smsc.com/main/datasheets/83c175.pdf
-http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
-http://www.national.com/pf/DP/DP83840A.html
-IVc. Errata
+typedef enum {
+ SMSC_83C170,
+ SMSC_83C175,
+} chip_t;
-*/
-/* The rest of these values should never change. */
+struct epic100_chip_info {
+ const char *name;
+};
-static struct net_device *epic_probe1(struct pci_dev *pdev, long ioaddr, int irq,
- int chip_id, int card_idx);
-enum pci_flags_bit {
- PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
- PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
+/* indexed by chip_t */
+static struct epic100_chip_info epic100_chip_info[] __devinitdata = {
+ { "SMSC EPIC/100 83c170" },
+ { "SMSC EPIC/C 83c175" },
};
-struct chip_info {
- const char *name;
- u16 vendor_id, device_id, device_id_mask, pci_flags;
- int io_size, min_latency;
- struct net_device *(*probe1)(struct pci_dev *pdev,
- long ioaddr, int irq, int chip_idx,
- int fnd_cnt);
-} chip_tbl[] = {
- {"SMSC EPIC/100 83c170", 0x10B8, 0x0005, 0x7fff,
- PCI_USES_IO|PCI_USES_MASTER|PCI_ADDR0, EPIC_TOTAL_SIZE, 32, epic_probe1},
- {"SMSC EPIC/C 83c175", 0x10B8, 0x0006, 0x7fff,
- PCI_USES_IO|PCI_USES_MASTER|PCI_ADDR0, EPIC_TOTAL_SIZE, 32, epic_probe1},
- {0,},
+
+static struct pci_device_id epic100_pci_tbl[] __devinitdata = {
+ { 0x10B8, 0x0005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMSC_83C170, },
+ { 0x10B8, 0x0006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMSC_83C175, },
+ { 0,},
};
+MODULE_DEVICE_TABLE (pci, epic100_pci_tbl);
+
/* Offsets to registers, using the (ugh) SMC names. */
enum epic_registers {
- COMMAND=0, INTSTAT=4, INTMASK=8, GENCTL=0x0C, NVCTL=0x10, EECTL=0x14,
- PCIBurstCnt=0x18,
- TEST1=0x1C, CRCCNT=0x20, ALICNT=0x24, MPCNT=0x28, /* Rx error counters. */
- MIICtrl=0x30, MIIData=0x34, MIICfg=0x38,
- LAN0=64, /* MAC address. */
- MC0=80, /* Multicast filter table. */
- RxCtrl=96, TxCtrl=112, TxSTAT=0x74,
- PRxCDAR=0x84, RxSTAT=0xA4, EarlyRx=0xB0, PTxCDAR=0xC4, TxThresh=0xDC,
+ COMMAND = 0,
+ INTSTAT = 4,
+ INTMASK = 8,
+ GENCTL = 0x0C,
+ NVCTL = 0x10,
+ EECTL = 0x14,
+ PCIBurstCnt = 0x18,
+ TEST1 = 0x1C,
+ CRCCNT = 0x20,
+ ALICNT = 0x24,
+ MPCNT = 0x28, /* Rx error counters. */
+ MIICtrl = 0x30,
+ MIIData = 0x34,
+ MIICfg = 0x38,
+ LAN0 = 64, /* MAC address. */
+ MC0 = 80, /* Multicast filter table. */
+ RxCtrl = 96,
+ TxCtrl = 112,
+ TxSTAT = 0x74,
+ PRxCDAR = 0x84,
+ RxSTAT = 0xA4,
+ EarlyRx = 0xB0,
+ PTxCDAR = 0xC4,
+ TxThresh = 0xDC,
};
+
/* Interrupt register bits, using my own meaningful names. */
enum IntrStatus {
- TxIdle=0x40000, RxIdle=0x20000, IntrSummary=0x010000,
- PCIBusErr170=0x7000, PCIBusErr175=0x1000, PhyEvent175=0x8000,
- RxStarted=0x0800, RxEarlyWarn=0x0400, CntFull=0x0200, TxUnderrun=0x0100,
- TxEmpty=0x0080, TxDone=0x0020, RxError=0x0010,
- RxOverflow=0x0008, RxFull=0x0004, RxHeader=0x0002, RxDone=0x0001,
+ TxIdle = 0x40000,
+ RxIdle = 0x20000,
+ IntrSummary = 0x010000,
+ PCIBusErr170 = 0x7000,
+ PCIBusErr175 = 0x1000,
+ PhyEvent175 = 0x8000,
+ RxStarted = 0x0800,
+ RxEarlyWarn = 0x0400,
+ CntFull = 0x0200,
+ TxUnderrun = 0x0100,
+ TxEmpty = 0x0080,
+ TxDone = 0x0020, RxError = 0x0010,
+ RxOverflow = 0x0008,
+ RxFull = 0x0004,
+ RxHeader = 0x0002,
+ RxDone = 0x0001,
};
/* The EPIC100 Rx and Tx buffer descriptors. */
@@ -203,7 +244,7 @@ struct epic_private {
unsigned int cur_rx, cur_tx; /* The next free ring entry */
unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
- u8 pci_bus, pci_dev_fn; /* PCI bus location. */
+ struct pci_dev *pdev;
u16 chip_id;
struct net_device_stats stats;
@@ -241,194 +282,9 @@ static int epic_close(struct net_device *dev);
static struct net_device_stats *epic_get_stats(struct net_device *dev);
static void set_rx_mode(struct net_device *dev);
-
-/* A list of all installed EPIC devices, for removing the driver module. */
-static struct net_device *root_epic_dev = NULL;
-
-#ifndef CARDBUS
-static int __init epic100_probe(void)
-{
- int cards_found = 0;
- int chip_idx, irq;
- u16 pci_command, new_command;
- unsigned char pci_bus, pci_device_fn;
- struct net_device *dev;
-
- struct pci_dev *pcidev = NULL;
- while ((pcidev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pcidev))
- != NULL) {
- long pci_ioaddr = pcidev->resource[0].start;
- int vendor = pcidev->vendor;
- int device = pcidev->device;
-
- for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++)
- if (vendor == chip_tbl[chip_idx].vendor_id
- && (device & chip_tbl[chip_idx].device_id_mask) ==
- chip_tbl[chip_idx].device_id)
- break;
- if (chip_tbl[chip_idx].vendor_id == 0 /* Compiled out! */
- || check_region(pci_ioaddr, chip_tbl[chip_idx].io_size))
- continue;
- pci_bus = pcidev->bus->number;
- pci_device_fn = pcidev->devfn;
- irq = pcidev->irq;
-
- /* EPIC-specific code: Soft-reset the chip ere setting as master. */
- outl(0x0001, pci_ioaddr + GENCTL);
-
- /* Activate the card: fix for brain-damaged Win98 BIOSes. */
- pci_read_config_word(pcidev, PCI_COMMAND, &pci_command);
- new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
- if (pci_command != new_command) {
- printk(KERN_INFO " The PCI BIOS has not enabled Ethernet"
- " device %4.4x-%4.4x."
- " Updating PCI command %4.4x->%4.4x.\n",
- vendor, device, pci_command, new_command);
- pci_write_config_word(pcidev, PCI_COMMAND, new_command);
- }
-
- dev = chip_tbl[chip_idx].probe1(pcidev, pci_ioaddr, irq,
- chip_idx, cards_found);
-
- /* Check the latency timer. */
- if (dev) {
- u8 pci_latency;
- pci_read_config_byte(pcidev, PCI_LATENCY_TIMER, &pci_latency);
- if (pci_latency < chip_tbl[chip_idx].min_latency) {
- printk(KERN_INFO " PCI latency timer (CFLT) value of %d is "
- "unreasonably low, setting to %d.\n", pci_latency,
- chip_tbl[chip_idx].min_latency);
- pci_write_config_byte(pcidev, PCI_LATENCY_TIMER,
- chip_tbl[chip_idx].min_latency);
- }
- dev = 0;
- cards_found++;
- }
- }
-
- return cards_found ? 0 : -ENODEV;
-}
-#endif /* not CARDBUS */
-
-static struct net_device *epic_probe1(struct pci_dev *pdev, long ioaddr, int irq,
- int chip_idx, int card_idx)
-{
- struct epic_private *ep;
- int i, option = 0, duplex = 0;
- struct net_device *dev;
-
-// FIXME if (dev && dev->mem_start) {
-// option = dev->mem_start;
-// duplex = (dev->mem_start & 16) ? 1 : 0;
-// }
-// else
- if (card_idx >= 0 && card_idx < MAX_UNITS) {
- if (options[card_idx] >= 0)
- option = options[card_idx];
- if (full_duplex[card_idx] >= 0)
- duplex = full_duplex[card_idx];
- }
-
- dev = init_etherdev(NULL, 0);
-
- dev->base_addr = ioaddr;
- dev->irq = irq;
- printk(KERN_INFO "%s: SMC EPIC/100 at %#lx, IRQ %d, ",
- dev->name, ioaddr, dev->irq);
-
- /* Bring the chip out of low-power mode. */
- outl(0x4200, ioaddr + GENCTL);
- /* Magic?! If we don't set this bit the MII interface won't work. */
- outl(0x0008, ioaddr + TEST1);
-
- /* Turn on the MII transceiver. */
- outl(0x12, ioaddr + MIICfg);
- if (chip_idx == 1)
- outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
- outl(0x0200, ioaddr + GENCTL);
-
- /* This could also be read from the EEPROM. */
- for (i = 0; i < 3; i++)
- ((u16 *)dev->dev_addr)[i] = inw(ioaddr + LAN0 + i*4);
-
- for (i = 0; i < 5; i++)
- printk("%2.2x:", dev->dev_addr[i]);
- printk("%2.2x.\n", dev->dev_addr[i]);
-
- if (epic_debug > 1) {
- printk(KERN_DEBUG "%s: EEPROM contents\n", dev->name);
- for (i = 0; i < 64; i++)
- printk(" %4.4x%s", read_eeprom(ioaddr, i),
- i % 16 == 15 ? "\n" : "");
- }
-
- /* We do a request_region() to register /proc/ioports info. */
- request_region(ioaddr, EPIC_TOTAL_SIZE, dev->name);
-
- /* The data structures must be quadword aligned. */
- ep = kmalloc(sizeof(*ep), GFP_KERNEL | GFP_DMA);
- memset(ep, 0, sizeof(*ep));
- dev->priv = ep;
-
- ep->next_module = root_epic_dev;
- root_epic_dev = dev;
-
- ep->lock = SPIN_LOCK_UNLOCKED;
- ep->pci_bus = pdev->bus->number;
- ep->pci_dev_fn = pdev->devfn;
- ep->chip_id = pdev->device;
- /* Find the connected MII xcvrs.
- Doing this in open() would allow detecting external xcvrs later, but
- takes too much time. */
- {
- int phy, phy_idx;
- for (phy = 1, phy_idx = 0; phy < 32 && phy_idx < sizeof(ep->phys);
- phy++) {
- int mii_status = mdio_read(ioaddr, phy, 1);
- if (mii_status != 0xffff && mii_status != 0x0000) {
- ep->phys[phy_idx++] = phy;
- printk(KERN_INFO "%s: MII transceiver #%d control "
- "%4.4x status %4.4x.\n"
- KERN_INFO "%s: Autonegotiation advertising %4.4x "
- "link partner %4.4x.\n",
- dev->name, phy, mdio_read(ioaddr, phy, 0), mii_status,
- dev->name, mdio_read(ioaddr, phy, 4),
- mdio_read(ioaddr, phy, 5));
- }
- }
- if (phy_idx == 0) {
- printk(KERN_WARNING "%s: ***WARNING***: No MII transceiver found!\n",
- dev->name);
- /* Use the known PHY address of the EPII. */
- ep->phys[0] = 3;
- }
- }
- /* Turn off the MII xcvr (175 only!), leave the chip in low-power mode. */
- if (ep->chip_id == 6)
- outl(inl(ioaddr + NVCTL) & ~0x483C, ioaddr + NVCTL);
- outl(0x0008, ioaddr + GENCTL);
- /* The lower four bits are the media type. */
- ep->force_fd = duplex;
- ep->default_port = option;
- if (ep->default_port)
- ep->medialock = 1;
-
- /* The Epic-specific entries in the device structure. */
- dev->open = &epic_open;
- dev->hard_start_xmit = &epic_start_xmit;
- dev->stop = &epic_close;
- dev->get_stats = &epic_get_stats;
- dev->set_multicast_list = &set_rx_mode;
- dev->do_ioctl = &mii_ioctl;
- dev->tx_timeout = epic_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
-
- return dev;
-}
-
/* Serial EEPROM section. */
/* EEPROM_Ctrl bits. */
@@ -527,13 +383,15 @@ epic_open(struct net_device *dev)
int mii_reg5;
ep->full_duplex = ep->force_fd;
+ MOD_INC_USE_COUNT;
+
/* Soft reset the chip. */
outl(0x4001, ioaddr + GENCTL);
- if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, "SMC EPIC/100", dev))
- return -EAGAIN;
-
- MOD_INC_USE_COUNT;
+ if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, EPIC100_MODULE_NAME, dev)) {
+ MOD_DEC_USE_COUNT;
+ return -EBUSY;
+ }
epic_init_ring(dev);
@@ -581,8 +439,6 @@ epic_open(struct net_device *dev)
set_rx_mode(dev);
outl(0x000A, ioaddr + COMMAND);
- netif_start_queue(dev);
-
/* Enable interrupts by setting the interrupt mask. */
outl((ep->chip_id == 6 ? PCIBusErr175 : PCIBusErr170)
| CntFull | TxUnderrun | TxDone
@@ -595,10 +451,12 @@ epic_open(struct net_device *dev)
dev->name, ioaddr, dev->irq, inl(ioaddr + GENCTL),
ep->full_duplex ? "full" : "half");
+ netif_start_queue(dev);
+
/* Set the timer to switch to check for link beat and perhaps switch
to an alternate media type. */
init_timer(&ep->timer);
- ep->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */
+ ep->timer.expires = RUN_AT(3*HZ); /* 3 sec. */
ep->timer.data = (unsigned long)dev;
ep->timer.function = &epic_timer; /* timer handler */
add_timer(&ep->timer);
@@ -606,6 +464,7 @@ epic_open(struct net_device *dev)
return 0;
}
+
/* Reset the chip to recover from a PCI transaction error.
This may occur at interrupt time. */
static void epic_pause(struct net_device *dev)
@@ -613,6 +472,8 @@ static void epic_pause(struct net_device *dev)
long ioaddr = dev->base_addr;
struct epic_private *ep = (struct epic_private *)dev->priv;
+ netif_stop_queue (dev);
+
/* Disable interrupts by clearing the interrupt mask. */
outl(0x00000000, ioaddr + INTMASK);
/* Stop the chip's Tx and Rx DMA processes. */
@@ -671,11 +532,13 @@ static void epic_restart(struct net_device *dev)
| CntFull | TxUnderrun | TxDone
| RxError | RxOverflow | RxFull | RxHeader | RxDone,
ioaddr + INTMASK);
+
+ netif_start_queue (dev);
+
printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x"
" interrupt %4.4x.\n",
dev->name, inl(ioaddr + COMMAND), inl(ioaddr + GENCTL),
inl(ioaddr + INTSTAT));
- return;
}
static void epic_timer(unsigned long data)
@@ -738,7 +601,8 @@ static void epic_tx_timeout(struct net_device *dev)
dev->trans_start = jiffies;
ep->stats.tx_errors++;
- return;
+
+ netif_start_queue (dev);
}
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
@@ -790,6 +654,8 @@ epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
int entry;
u32 flag;
+ netif_stop_queue (dev);
+
/* Caution: the write order is important here, set the base address
with the "ownership" bits last. */
@@ -806,13 +672,10 @@ epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
flag = 0x10; /* No interrupt */
- netif_start_queue(dev);
} else if (ep->cur_tx - ep->dirty_tx == TX_RING_SIZE/2) {
flag = 0x14; /* Tx-done intr. */
- netif_start_queue(dev);
} else if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE - 2) {
flag = 0x10; /* No Tx-done intr. */
- netif_start_queue(dev);
} else {
/* Leave room for two additional entries. */
flag = 0x14; /* Tx-done intr. */
@@ -826,6 +689,10 @@ epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
outl(0x0004, dev->base_addr + COMMAND);
dev->trans_start = jiffies;
+
+ if (! ep->tx_full)
+ netif_start_queue (dev);
+
if (epic_debug > 4)
printk(KERN_DEBUG "%s: Queued Tx packet size %d to slot %d, "
"flag %2.2x Tx status %8.8x.\n",
@@ -895,7 +762,7 @@ static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
}
/* Free the original skb. */
- DEV_FREE_SKB(ep->tx_skbuff[entry]);
+ dev_kfree_skb_irq(ep->tx_skbuff[entry]);
ep->tx_skbuff[entry] = 0;
}
@@ -908,12 +775,16 @@ static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
#endif
if (ep->tx_full &&
- test_bit(LINK_STATE_XOFF, &dev->flags) &&
+ netif_queue_stopped(dev) &&
dirty_tx > ep->cur_tx - TX_RING_SIZE + 2) {
/* The ring is no longer full, clear tbusy. */
ep->tx_full = 0;
- netif_wake_queue (dev);
}
+
+ if (ep->tx_full)
+ netif_stop_queue (dev);
+ else
+ netif_wake_queue (dev);
ep->dirty_tx = dirty_tx;
}
@@ -963,6 +834,7 @@ static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
spin_unlock (&ep->lock);
}
+
static int epic_rx(struct net_device *dev)
{
struct epic_private *ep = (struct epic_private *)dev->priv;
@@ -1039,6 +911,7 @@ static int epic_rx(struct net_device *dev)
return work_done;
}
+
static int epic_close(struct net_device *dev)
{
long ioaddr = dev->base_addr;
@@ -1073,12 +946,12 @@ static int epic_close(struct net_device *dev)
ep->rx_ring[i].buflength = 0;
ep->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */
if (skb) {
- DEV_FREE_SKB(skb);
+ dev_kfree_skb(skb);
}
}
for (i = 0; i < TX_RING_SIZE; i++) {
if (ep->tx_skbuff[i])
- DEV_FREE_SKB(ep->tx_skbuff[i]);
+ dev_kfree_skb(ep->tx_skbuff[i]);
ep->tx_skbuff[i] = 0;
}
@@ -1091,12 +964,13 @@ static int epic_close(struct net_device *dev)
return 0;
}
+
static struct net_device_stats *epic_get_stats(struct net_device *dev)
{
struct epic_private *ep = (struct epic_private *)dev->priv;
long ioaddr = dev->base_addr;
- if (test_bit(LINK_STATE_START, &dev->state)) {
+ if (netif_running(dev)) {
/* Update the error counts. */
ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
@@ -1106,6 +980,7 @@ static struct net_device_stats *epic_get_stats(struct net_device *dev)
return &ep->stats;
}
+
/* Set or clear the multicast filter for this adaptor.
Note that we only use exclusion around actually queueing the
new frame, not around filling ep->setup_frame. This is non-deterministic
@@ -1172,6 +1047,7 @@ static void set_rx_mode(struct net_device *dev)
return;
}
+
static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
long ioaddr = dev->base_addr;
@@ -1182,12 +1058,12 @@ static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
data[0] = ((struct epic_private *)dev->priv)->phys[0] & 0x1f;
/* Fall Through */
case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
- if (! test_bit(LINK_STATE_START, &dev->state)) {
+ if (! netif_running(dev)) {
outl(0x0200, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
}
data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
- if (! test_bit(LINK_STATE_START, &dev->state)) {
+ if (! netif_running(dev)) {
#ifdef notdef
outl(0x0008, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
@@ -1197,12 +1073,12 @@ static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
if (!suser())
return -EPERM;
- if (! test_bit(LINK_STATE_START, &dev->state)) {
+ if (! netif_running(dev)) {
outl(0x0200, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
}
mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
- if (! test_bit(LINK_STATE_START, &dev->state)) {
+ if (! netif_running(dev)) {
#ifdef notdef
outl(0x0008, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
@@ -1214,131 +1090,214 @@ static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
}
-
-#ifdef CARDBUS
-
-#include <pcmcia/driver_ops.h>
-static dev_node_t *epic_attach(dev_locator_t *loc)
+static int __devinit epic100_init_one (struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
+ struct epic_private *ep;
+ int i, option = 0, duplex = 0, irq, chip_idx;
struct net_device *dev;
- u16 dev_id;
- u32 io;
- u8 bus, devfn, irq;
- struct pci_dev *pdev;
-
- if (loc->bus != LOC_PCI) return NULL;
- pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn);
- if (!pdev) return NULL;
- printk(KERN_DEBUG "epic_attach(bus %d, function %d)\n", bus, devfn);
- io = pdev->resource[0].start;
+ long ioaddr;
+ static int card_idx = -1;
+
+ chip_idx = ent->driver_data;
+
+ ioaddr = pci_resource_start (pdev, 0);
+ if (!ioaddr)
+ return -ENODEV;
+
irq = pdev->irq;
- dev_id = pdev->device;
- io &= ~3;
- if (io == 0 || irq == 0) {
- printk(KERN_ERR "The EPIC/C CardBus Ethernet interface was not "
- "assigned an %s.\n" KERN_ERR " It will not be activated.\n",
- io == 0 ? "I/O address" : "IRQ");
- return NULL;
- }
- dev = epic_probe1(bus, devfn, io, irq, 2, -1);
- if (dev) {
- dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
- strcpy(node->dev_name, dev->name);
- node->major = node->minor = 0;
- node->next = NULL;
- MOD_INC_USE_COUNT;
- return node;
- }
- return NULL;
-}
+ if (!irq)
+ return -ENODEV;
-static void epic_suspend(dev_node_t *node)
-{
- struct net_device **devp, **next;
- printk(KERN_INFO "epic_suspend(%s)\n", node->dev_name);
- for (devp = &root_epic_dev; *devp; devp = next) {
- next = &((struct epic_private *)(*devp)->priv)->next_module;
- if (strcmp((*devp)->name, node->dev_name) == 0) break;
- }
- if (*devp) {
- long ioaddr = (*devp)->base_addr;
- epic_pause(*devp);
- /* Put the chip into low-power mode. */
- outl(0x0008, ioaddr + GENCTL);
+ /* We do a request_region() to register /proc/ioports info. */
+ if (!request_region(ioaddr, EPIC_TOTAL_SIZE, EPIC100_MODULE_NAME))
+ return -EBUSY;
+
+ pci_enable_device (pdev);
+
+ /* EPIC-specific code: Soft-reset the chip ere setting as master. */
+ outl(0x0001, ioaddr + GENCTL);
+
+ pci_set_master (pdev);
+
+// FIXME if (dev && dev->mem_start) {
+// option = dev->mem_start;
+// duplex = (dev->mem_start & 16) ? 1 : 0;
+// }
+// else
+
+ card_idx++;
+ if (card_idx >= 0 && card_idx < MAX_UNITS) {
+ if (options[card_idx] >= 0)
+ option = options[card_idx];
+ if (full_duplex[card_idx] >= 0)
+ duplex = full_duplex[card_idx];
}
-}
-static void epic_resume(dev_node_t *node)
-{
- struct net_device **devp, **next;
- printk(KERN_INFO "epic_resume(%s)\n", node->dev_name);
- for (devp = &root_epic_dev; *devp; devp = next) {
- next = &((struct epic_private *)(*devp)->priv)->next_module;
- if (strcmp((*devp)->name, node->dev_name) == 0) break;
+
+ dev = init_etherdev(NULL, sizeof (*ep));
+ if (!dev)
+ goto err_out_free_region;
+
+ dev->base_addr = ioaddr;
+ dev->irq = irq;
+ printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ",
+ dev->name, epic100_chip_info[chip_idx].name,
+ ioaddr, dev->irq);
+
+ /* Bring the chip out of low-power mode. */
+ outl(0x4200, ioaddr + GENCTL);
+ /* Magic?! If we don't set this bit the MII interface won't work. */
+ outl(0x0008, ioaddr + TEST1);
+
+ /* Turn on the MII transceiver. */
+ outl(0x12, ioaddr + MIICfg);
+ if (chip_idx == 1)
+ outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+ outl(0x0200, ioaddr + GENCTL);
+
+ /* This could also be read from the EEPROM. */
+ for (i = 0; i < 3; i++)
+ ((u16 *)dev->dev_addr)[i] = inw(ioaddr + LAN0 + i*4);
+
+ for (i = 0; i < 5; i++)
+ printk("%2.2x:", dev->dev_addr[i]);
+ printk("%2.2x.\n", dev->dev_addr[i]);
+
+ if (epic_debug > 1) {
+ printk(KERN_DEBUG "%s: EEPROM contents\n", dev->name);
+ for (i = 0; i < 64; i++)
+ printk(" %4.4x%s", read_eeprom(ioaddr, i),
+ i % 16 == 15 ? "\n" : "");
}
- if (*devp) {
- epic_restart(*devp);
+
+ /* The data structures must be quadword aligned,
+ * init_etherdev ensures this */
+ ep = dev->priv;
+ memset(ep, 0, sizeof(*ep));
+
+ ep->lock = SPIN_LOCK_UNLOCKED;
+ ep->chip_id = pdev->device;
+ ep->pdev = pdev;
+ pdev->driver_data = dev;
+
+ /* Find the connected MII xcvrs.
+ Doing this in open() would allow detecting external xcvrs later, but
+ takes too much time. */
+ {
+ int phy, phy_idx;
+ for (phy = 1, phy_idx = 0; phy < 32 && phy_idx < sizeof(ep->phys);
+ phy++) {
+ int mii_status = mdio_read(ioaddr, phy, 1);
+ if (mii_status != 0xffff && mii_status != 0x0000) {
+ ep->phys[phy_idx++] = phy;
+ printk(KERN_INFO "%s: MII transceiver #%d control "
+ "%4.4x status %4.4x.\n"
+ KERN_INFO "%s: Autonegotiation advertising %4.4x "
+ "link partner %4.4x.\n",
+ dev->name, phy, mdio_read(ioaddr, phy, 0), mii_status,
+ dev->name, mdio_read(ioaddr, phy, 4),
+ mdio_read(ioaddr, phy, 5));
+ }
+ }
+ if (phy_idx == 0) {
+ printk(KERN_WARNING "%s: ***WARNING***: No MII transceiver found!\n",
+ dev->name);
+ /* Use the known PHY address of the EPII. */
+ ep->phys[0] = 3;
+ }
}
+
+ /* Turn off the MII xcvr (175 only!), leave the chip in low-power mode. */
+ if (ep->chip_id == 6)
+ outl(inl(ioaddr + NVCTL) & ~0x483C, ioaddr + NVCTL);
+ outl(0x0008, ioaddr + GENCTL);
+
+ /* The lower four bits are the media type. */
+ ep->force_fd = duplex;
+ ep->default_port = option;
+ if (ep->default_port)
+ ep->medialock = 1;
+
+ /* The Epic-specific entries in the device structure. */
+ dev->open = epic_open;
+ dev->hard_start_xmit = epic_start_xmit;
+ dev->stop = epic_close;
+ dev->get_stats = epic_get_stats;
+ dev->set_multicast_list = set_rx_mode;
+ dev->do_ioctl = mii_ioctl;
+ dev->tx_timeout = epic_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
+ netif_stop_queue (dev);
+
+ return 0;
+
+err_out_free_region:
+ release_region(ioaddr, EPIC_TOTAL_SIZE);
+ return -ENODEV;
}
-static void epic_detach(dev_node_t *node)
+
+
+static void __devexit epic100_remove_one (struct pci_dev *pdev)
{
- struct net_device **devp, **next;
- printk(KERN_INFO "epic_detach(%s)\n", node->dev_name);
- for (devp = &root_epic_dev; *devp; devp = next) {
- next = &((struct epic_private *)(*devp)->priv)->next_module;
- if (strcmp((*devp)->name, node->dev_name) == 0) break;
- }
- if (*devp) {
- unregister_netdev(*devp);
- kfree(*devp);
- *devp = *next;
- kfree(node);
- MOD_DEC_USE_COUNT;
- }
+ struct net_device *dev = pdev->driver_data;
+
+ unregister_netdev(dev);
+ release_region(dev->base_addr, EPIC_TOTAL_SIZE);
+ kfree(dev);
}
-struct driver_operations epic_ops = {
- "epic_cb", epic_attach, epic_suspend, epic_resume, epic_detach
-};
-#endif /* Cardbus support */
+static void epic100_suspend (struct pci_dev *pdev)
+{
+ struct net_device *dev = pdev->driver_data;
+ long ioaddr = dev->base_addr;
+
+ epic_pause(dev);
+ /* Put the chip into low-power mode. */
+ outl(0x0008, ioaddr + GENCTL);
+}
-static int __init epic100_init_module(void)
+static void epic100_resume (struct pci_dev *pdev)
{
- if (epic_debug)
- printk(KERN_INFO "%s", version);
+ struct net_device *dev = pdev->driver_data;
-#ifdef CARDBUS
- register_driver(&epic_ops);
- return 0;
-#else
- return epic100_probe();
-#endif
+ epic_restart (dev);
}
-static void __exit epic100_cleanup_module(void)
+
+static struct pci_driver epic100_driver = {
+ name: EPIC100_MODULE_NAME,
+ id_table: epic100_pci_tbl,
+ probe: epic100_init_one,
+ remove: epic100_remove_one,
+ suspend: epic100_suspend,
+ resume: epic100_resume,
+};
+
+
+static int __init epic100_init (void)
{
- struct net_device *next_dev;
+ printk (KERN_INFO "%s", version);
+
+ if (pci_register_driver (&epic100_driver) > 0)
+ return 0;
+
+ pci_unregister_driver (&epic100_driver);
+ return -ENODEV;
+}
-#ifdef CARDBUS
- unregister_driver(&epic_ops);
-#endif
- /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
- while (root_epic_dev) {
- struct epic_private *ep = (struct epic_private *)root_epic_dev->priv;
- next_dev = ep->next_module;
- unregister_netdev(root_epic_dev);
- release_region(root_epic_dev->base_addr, EPIC_TOTAL_SIZE);
- kfree(root_epic_dev);
- root_epic_dev = next_dev;
- kfree(ep);
- }
+static void __exit epic100_cleanup (void)
+{
+ pci_unregister_driver (&epic100_driver);
}
-module_init(epic100_init_module);
-module_exit(epic100_cleanup_module);
+
+module_init(epic100_init);
+module_exit(epic100_cleanup);
/*
diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c
index b1af7e5dc..502936cab 100644
--- a/drivers/net/eth16i.c
+++ b/drivers/net/eth16i.c
@@ -158,6 +158,8 @@ static char *version =
#include <linux/malloc.h>
#include <linux/string.h>
#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -168,26 +170,7 @@ static char *version =
#include <asm/io.h>
#include <asm/dma.h>
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-
-#if LINUX_VERSION_CODE >= 0x20123
-#include <linux/init.h>
-#else
-#define __init
-#define __initdata
-#endif
-#if LINUX_VERSION_CODE < 0x20138
-#define test_and_set_bit(val,addr) set_bit(val,addr)
-#endif
-
-#if LINUX_VERSION_CODE < 0x020100
-typedef struct enet_statistics eth16i_stats_type;
-#else
-typedef struct net_device_stats eth16i_stats_type;
-#endif
/* Few macros */
#define BIT(a) ( (1 << (a)) )
@@ -371,12 +354,14 @@ typedef struct net_device_stats eth16i_stats_type;
#define RESET ID_ROM_0
/* This is the I/O address list to be probed when seeking the card */
-static unsigned int eth16i_portlist[] =
- { 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300, 0 };
+static unsigned int eth16i_portlist[] = {
+ 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
+};
-static unsigned int eth32i_portlist[] =
- { 0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000,
- 0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0 };
+static unsigned int eth32i_portlist[] = {
+ 0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000,
+ 0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0
+};
/* This is the Interrupt lookup table for Eth16i card */
static unsigned int eth16i_irqmap[] = { 9, 10, 5, 15, 0 };
@@ -399,7 +384,7 @@ static unsigned int eth16i_debug = ETH16I_DEBUG;
/* Information for each board */
struct eth16i_local {
- eth16i_stats_type stats;
+ struct net_device_stats stats;
unsigned char tx_started;
unsigned char tx_buf_busy;
unsigned short tx_queue; /* Number of packets in transmit buffer */
@@ -409,6 +394,7 @@ struct eth16i_local {
unsigned long tx_buffered_packets;
unsigned long tx_buffered_bytes;
unsigned long col_16;
+ spinlock_t lock;
};
/* Function prototypes */
@@ -429,8 +415,10 @@ static int eth16i_open(struct net_device *dev);
static int eth16i_close(struct net_device *dev);
static int eth16i_tx(struct sk_buff *skb, struct net_device *dev);
static void eth16i_rx(struct net_device *dev);
+static void eth16i_timeout(struct net_device *dev);
static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void eth16i_reset(struct net_device *dev);
+static void eth16i_timeout(struct net_device *dev);
static void eth16i_skip_packet(struct net_device *dev);
static void eth16i_multicast(struct net_device *dev);
static void eth16i_select_regbank(unsigned char regbank, int ioaddr);
@@ -444,18 +432,10 @@ static int eth16i_set_irq(struct net_device *dev);
static ushort eth16i_parse_mediatype(const char* s);
#endif
-static struct enet_statistics *eth16i_get_stats(struct net_device *dev);
+static struct net_device_stats *eth16i_get_stats(struct net_device *dev);
static char *cardname = "ICL EtherTeam 16i/32";
-#ifdef HAVE_DEVLIST
-
-/* Support for alternate probe manager */
-/struct netdev_entry eth16i_drv =
- {"eth16i", eth16i_probe1, ETH16I_IO_EXTENT, eth16i_probe_list};
-
-#else /* Not HAVE_DEVLIST */
-
int __init eth16i_probe(struct net_device *dev)
{
int i;
@@ -488,10 +468,11 @@ int __init eth16i_probe(struct net_device *dev)
return ENODEV;
}
-#endif /* Not HAVE_DEVLIST */
static int __init eth16i_probe1(struct net_device *dev, int ioaddr)
{
+ struct eth16i_local *lp;
+
static unsigned version_printed = 0;
boot = 1; /* To inform initilization that we are in boot probe */
@@ -535,17 +516,6 @@ static int __init eth16i_probe1(struct net_device *dev, int ioaddr)
printk(KERN_INFO "%s", version);
dev->base_addr = ioaddr;
-
-#if 0
- if(dev->irq) {
- if(eth16i_set_irq(dev)) {
- dev->irq = eth16i_get_irq(ioaddr);
- }
-
- }
- else {
-#endif
-
dev->irq = eth16i_get_irq(ioaddr);
/* Try to obtain interrupt vector */
@@ -556,10 +526,6 @@ static int __init eth16i_probe1(struct net_device *dev, int ioaddr)
return -EAGAIN;
}
-#if 0
- irq2dev_map[dev->irq] = dev;
-#endif
-
printk(KERN_INFO "%s: %s at %#3x, IRQ %d, ",
dev->name, cardname, ioaddr, dev->irq);
@@ -583,12 +549,16 @@ static int __init eth16i_probe1(struct net_device *dev, int ioaddr)
}
memset(dev->priv, 0, sizeof(struct eth16i_local));
-
dev->open = eth16i_open;
dev->stop = eth16i_close;
dev->hard_start_xmit = eth16i_tx;
dev->get_stats = eth16i_get_stats;
- dev->set_multicast_list = &eth16i_multicast;
+ dev->set_multicast_list = eth16i_multicast;
+ dev->tx_timeout = eth16i_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
+ lp = (struct eth16i_local *)dev->priv;
+ spin_lock_init(&lp->lock);
/* Fill in the fields of the device structure with ethernet values. */
ether_setup(dev);
@@ -1004,10 +974,7 @@ static int eth16i_open(struct net_device *dev)
/* Turn on interrupts*/
outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
-
+ netif_start_queue(dev);
MOD_INC_USE_COUNT;
return 0;
@@ -1023,9 +990,8 @@ static int eth16i_close(struct net_device *dev)
/* Turn off interrupts*/
outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
- dev->start = 0;
- dev->tbusy = 1;
-
+ netif_stop_queue(dev);
+
lp->open_time = 0;
/* Disable transmit and receive */
@@ -1042,153 +1008,115 @@ static int eth16i_close(struct net_device *dev)
return 0;
}
-static int eth16i_tx(struct sk_buff *skb, struct net_device *dev)
+static void eth16i_timeout(struct net_device *dev)
{
struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
int ioaddr = dev->base_addr;
- int status = 0;
+ /*
+ If we get here, some higher level has decided that
+ we are broken. There should really be a "kick me"
+ function call instead.
+ */
- if(dev->tbusy) {
-
- /*
- If we get here, some higher level has decided that
- we are broken. There should really be a "kick me"
- function call instead.
- */
-
- int tickssofar = jiffies - dev->trans_start;
- if(tickssofar < TX_TIMEOUT)
- return 1;
-
- outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
-
- printk(KERN_WARNING "%s: transmit timed out with status %04x, %s ?\n",
- dev->name,
- inw(ioaddr + TX_STATUS_REG),
- (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ?
+ outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
+ printk(KERN_WARNING "%s: transmit timed out with status %04x, %s ?\n",
+ dev->name,
+ inw(ioaddr + TX_STATUS_REG), (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ?
"IRQ conflict" : "network cable problem");
- dev->trans_start = jiffies;
-
- /* Let's dump all registers */
- if(eth16i_debug > 0) {
- printk(KERN_DEBUG "%s: timeout: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
- dev->name, inb(ioaddr + 0),
- inb(ioaddr + 1), inb(ioaddr + 2),
- inb(ioaddr + 3), inb(ioaddr + 4),
- inb(ioaddr + 5),
- inb(ioaddr + 6), inb(ioaddr + 7));
+ dev->trans_start = jiffies;
- printk(KERN_DEBUG "%s: transmit start reg: %02x. collision reg %02x\n",
- dev->name, inb(ioaddr + TRANSMIT_START_REG),
- inb(ioaddr + COL_16_REG));
+ /* Let's dump all registers */
+ if(eth16i_debug > 0) {
+ printk(KERN_DEBUG "%s: timeout: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
+ dev->name, inb(ioaddr + 0),
+ inb(ioaddr + 1), inb(ioaddr + 2),
+ inb(ioaddr + 3), inb(ioaddr + 4),
+ inb(ioaddr + 5),
+ inb(ioaddr + 6), inb(ioaddr + 7));
+ printk(KERN_DEBUG "%s: transmit start reg: %02x. collision reg %02x\n",
+ dev->name, inb(ioaddr + TRANSMIT_START_REG),
+ inb(ioaddr + COL_16_REG));
printk(KERN_DEBUG "lp->tx_queue = %d\n", lp->tx_queue);
- printk(KERN_DEBUG "lp->tx_queue_len = %d\n", lp->tx_queue_len);
- printk(KERN_DEBUG "lp->tx_started = %d\n", lp->tx_started);
-
- }
-
- lp->stats.tx_errors++;
-
- eth16i_reset(dev);
-
- dev->trans_start = jiffies;
-
- outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-
+ printk(KERN_DEBUG "lp->tx_queue_len = %d\n", lp->tx_queue_len);
+ printk(KERN_DEBUG "lp->tx_started = %d\n", lp->tx_started);
}
+ lp->stats.tx_errors++;
+ eth16i_reset(dev);
+ dev->trans_start = jiffies;
+ outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+ netif_wake_queue(dev);
+}
- /*
- If some higher layer thinks we've missed an tx-done interrupt
- we are passed NULL. Caution: dev_tint() handles the cli()/sti()
- itself
- */
-
- if(skb == NULL) {
-#if LINUX_VERSION_CODE < 0x020100
- dev_tint(dev);
-#endif
- if(eth16i_debug > 0)
- printk(KERN_WARNING "%s: Missed tx-done interrupt.\n", dev->name);
- return 0;
- }
+static int eth16i_tx(struct sk_buff *skb, struct net_device *dev)
+{
+ struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+ int status = 0;
+ ushort length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+ unsigned char *buf = skb->data;
+ unsigned long flags;
- /* Block a timer based transmitter from overlapping.
- This could better be done with atomic_swap(1, dev->tbusy),
- but set_bit() works as well. */
- set_bit(0, (void *)&lp->tx_buf_busy);
-
+ netif_stop_queue(dev);
+
/* Turn off TX interrupts */
outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
+
+ /* We would be better doing the disable_irq tricks the 3c509 does,
+ that would make this suck a lot less */
+
+ spin_lock_irqsave(&lp->lock, flags);
- if(test_and_set_bit(0, (void *)&dev->tbusy) != 0) {
- printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
- status = -1;
- }
+ if( (length + 2) > (lp->tx_buf_size - lp->tx_queue_len)) {
+ if(eth16i_debug > 0)
+ printk(KERN_WARNING "%s: Transmit buffer full.\n", dev->name);
+ }
else {
- ushort length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned char *buf = skb->data;
+ outw(length, ioaddr + DATAPORT);
- if( (length + 2) > (lp->tx_buf_size - lp->tx_queue_len)) {
- if(eth16i_debug > 0)
- printk(KERN_WARNING "%s: Transmit buffer full.\n", dev->name);
- }
+ if( ioaddr < 0x1000 )
+ outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
else {
- outw(length, ioaddr + DATAPORT);
-
- if( ioaddr < 0x1000 )
- outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
- else {
- unsigned char frag = length % 4;
-
- outsl(ioaddr + DATAPORT, buf, length >> 2);
-
- if( frag != 0 ) {
- outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC)), 1);
- if( frag == 3 )
- outsw(ioaddr + DATAPORT,
- (buf + (length & 0xFFFC) + 2), 1);
- }
+ unsigned char frag = length % 4;
+ outsl(ioaddr + DATAPORT, buf, length >> 2);
+ if( frag != 0 ) {
+ outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC)), 1);
+ if( frag == 3 )
+ outsw(ioaddr + DATAPORT,
+ (buf + (length & 0xFFFC) + 2), 1);
}
-
- lp->tx_buffered_packets++;
- lp->tx_buffered_bytes = length;
- lp->tx_queue++;
- lp->tx_queue_len += length + 2;
- }
-
- lp->tx_buf_busy = 0;
-
- if(lp->tx_started == 0) {
- /* If the transmitter is idle..always trigger a transmit */
- outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
- lp->tx_queue = 0;
- lp->tx_queue_len = 0;
- dev->trans_start = jiffies;
- lp->tx_started = 1;
- dev->tbusy = 0;
- }
- else if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
- /* There is still more room for one more packet in tx buffer */
- dev->tbusy = 0;
}
-
- outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-
- /* Turn TX interrupts back on */
- /* outb(TX_INTR_DONE | TX_INTR_16_COL, ioaddr + TX_INTR_REG); */
- status = 0;
- }
+ lp->tx_buffered_packets++;
+ lp->tx_buffered_bytes = length;
+ lp->tx_queue++;
+ lp->tx_queue_len += length + 2;
+ }
+ lp->tx_buf_busy = 0;
-#if LINUX_VERSION_CODE >= 0x020100
+ if(lp->tx_started == 0) {
+ /* If the transmitter is idle..always trigger a transmit */
+ outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
+ lp->tx_queue = 0;
+ lp->tx_queue_len = 0;
+ dev->trans_start = jiffies;
+ lp->tx_started = 1;
+ netif_wake_queue(dev);
+ }
+ else if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
+ /* There is still more room for one more packet in tx buffer */
+ netif_wake_queue(dev);
+ }
+
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+ /* Turn TX interrupts back on */
+ /* outb(TX_INTR_DONE | TX_INTR_16_COL, ioaddr + TX_INTR_REG); */
+ status = 0;
dev_kfree_skb(skb);
-#else
- dev_kfree_skb(skb, FREE_WRITE);
-#endif
-
- return status;
+ return 0;
}
static void eth16i_rx(struct net_device *dev)
@@ -1284,51 +1212,23 @@ static void eth16i_rx(struct net_device *dev)
break;
} /* while */
-
-#if 0
- {
- int i;
-
- for(i = 0; i < 20; i++) {
- if( (inb(ioaddr+RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) ==
- RX_BUFFER_EMPTY)
- break;
- inw(ioaddr + DATAPORT);
- outb(SKIP_RX_PACKET, ioaddr + FILTER_SELF_RX_REG);
- }
-
- if(eth16i_debug > 1)
- printk(KERN_DEBUG "%s: Flushed receive buffer.\n", dev->name);
- }
-#endif
-
- return;
}
static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
struct eth16i_local *lp;
- int ioaddr = 0,
- status;
+ int ioaddr = 0, status;
- if(dev == NULL) {
- printk(KERN_WARNING "eth16i_interrupt(): irq %d for unknown device. \n", irq);
- return;
- }
+ ioaddr = dev->base_addr;
+ lp = (struct eth16i_local *)dev->priv;
/* Turn off all interrupts from adapter */
outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
- set_bit(0, (void *)&dev->tbusy); /* Set the device busy so that */
/* eth16i_tx wont be called */
+ spin_lock(&lp->lock);
- if(dev->interrupt)
- printk(KERN_WARNING "%s: Re-entering the interrupt handler.\n", dev->name);
- dev->interrupt = 1;
-
- ioaddr = dev->base_addr;
- lp = (struct eth16i_local *)dev->priv;
status = inw(ioaddr + TX_STATUS_REG); /* Get the status */
outw(status, ioaddr + TX_STATUS_REG); /* Clear status bits */
@@ -1386,13 +1286,11 @@ static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
lp->tx_queue = 0;
lp->tx_queue_len = 0;
lp->tx_started = 1;
- dev->trans_start = jiffies;
- mark_bh(NET_BH);
}
else {
lp->tx_started = 0;
- mark_bh(NET_BH);
}
+ netif_wake_queue(dev);
}
}
@@ -1401,16 +1299,16 @@ static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
eth16i_rx(dev); /* We have packet in receive buffer */
}
- dev->interrupt = 0;
-
/* Turn interrupts back on */
outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
/* There is still more room for one more packet in tx buffer */
- dev->tbusy = 0;
+ netif_wake_queue(dev);
}
+ spin_unlock(&lp->lock);
+
return;
}
@@ -1442,10 +1340,6 @@ static void eth16i_reset(struct net_device *dev)
lp->tx_buf_busy = 0;
lp->tx_queue = 0;
lp->tx_queue_len = 0;
-
- dev->interrupt = 0;
- dev->start = 1;
- dev->tbusy = 0;
BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
}
@@ -1462,10 +1356,9 @@ static void eth16i_multicast(struct net_device *dev)
}
}
-static struct enet_statistics *eth16i_get_stats(struct net_device *dev)
+static struct net_device_stats *eth16i_get_stats(struct net_device *dev)
{
struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
-
return &lp->stats;
}
diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
index eecbb9a56..90c82b341 100644
--- a/drivers/net/ewrk3.c
+++ b/drivers/net/ewrk3.c
@@ -138,6 +138,7 @@
static const char *version = "ewrk3.c:v0.43 96/8/16 davies@maniac.ultranet.com\n";
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -303,6 +304,7 @@ static int ewrk3_hw_init(struct net_device *dev, u_long iobase);
static void ewrk3_init(struct net_device *dev);
static int ewrk3_rx(struct net_device *dev);
static int ewrk3_tx(struct net_device *dev);
+static void ewrk3_timeout(struct net_device *dev);
static void EthwrkSignature(char *name, char *eeprom_image);
static int DevicePresent(u_long iobase);
@@ -601,12 +603,14 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
printk(version);
}
/* The EWRK3-specific entries in the device structure. */
- dev->open = &ewrk3_open;
- dev->hard_start_xmit = &ewrk3_queue_pkt;
- dev->stop = &ewrk3_close;
- dev->get_stats = &ewrk3_get_stats;
- dev->set_multicast_list = &set_multicast_list;
- dev->do_ioctl = &ewrk3_ioctl;
+ dev->open = ewrk3_open;
+ dev->hard_start_xmit = ewrk3_queue_pkt;
+ dev->stop = ewrk3_close;
+ dev->get_stats = ewrk3_get_stats;
+ dev->set_multicast_list = set_multicast_list;
+ dev->do_ioctl = ewrk3_ioctl;
+ dev->tx_timeout = ewrk3_timeout;
+ dev->watchdog_timeo = QUEUE_PKT_TIMEOUT;
dev->mem_start = 0;
@@ -616,7 +620,6 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
} else {
status = -ENXIO;
}
-
return status;
}
@@ -664,10 +667,7 @@ static int ewrk3_open(struct net_device *dev)
printk(" cmr: 0x%02x\n", inb(EWRK3_CMR));
printk(" fmqc: 0x%02x\n", inb(EWRK3_FMQC));
}
- dev->tbusy = 0;
- dev->start = 1;
- dev->interrupt = UNMASK_INTERRUPTS;
-
+ netif_start_queue(dev);
/*
** Unmask EWRK3 board interrupts
*/
@@ -676,10 +676,9 @@ static int ewrk3_open(struct net_device *dev)
}
} else {
- dev->start = 0;
- dev->tbusy = 1;
- printk("%s: ewrk3 available for hard strapped set up only.\n", dev->name);
- printk(" Run the 'ewrk3setup' utility or remove the hard straps.\n");
+ printk(KERN_ERR "%s: ewrk3 available for hard strapped set up only.\n", dev->name);
+ printk(KERN_ERR " Run the 'ewrk3setup' utility or remove the hard straps.\n");
+ return -EINVAL;
}
MOD_INC_USE_COUNT;
@@ -722,149 +721,148 @@ static void ewrk3_init(struct net_device *dev)
}
/*
- ** Writes a socket buffer to the free page queue
+ * Transmit timeout
*/
-static int ewrk3_queue_pkt(struct sk_buff *skb, struct net_device *dev)
+
+static void ewrk3_timeout(struct net_device *dev)
{
struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
- u_long iobase = dev->base_addr;
- int status = 0;
u_char icr, csr;
+ u_long iobase = dev->base_addr;
+
+ if (!lp->hard_strapped)
+ {
+ printk(KERN_WARNING"%s: transmit timed/locked out, status %04x, resetting.\n",
+ dev->name, inb(EWRK3_CSR));
- /* Transmitter timeout, serious problems. */
- if (dev->tbusy || lp->lock) {
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < QUEUE_PKT_TIMEOUT) {
- status = -1;
- } else if (!lp->hard_strapped) {
- printk("%s: transmit timed/locked out, status %04x, resetting.\n",
- dev->name, inb(EWRK3_CSR));
-
- /*
- ** Mask all board interrupts
- */
- DISABLE_IRQs;
-
- /*
- ** Stop the TX and RX...
- */
- STOP_EWRK3;
-
- ewrk3_init(dev);
-
- /*
- ** Unmask EWRK3 board interrupts
- */
- ENABLE_IRQs;
-
- dev->tbusy = 0;
- dev->trans_start = jiffies;
- }
- } else if (skb->len > 0) {
+ /*
+ ** Mask all board interrupts
+ */
+ DISABLE_IRQs;
/*
- ** Block a timer-based transmit from overlapping. This could better be
- ** done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
+ ** Stop the TX and RX...
*/
- if (test_and_set_bit(0, (void *) &dev->tbusy) != 0)
- printk("%s: Transmitter access conflict.\n", dev->name);
+ STOP_EWRK3;
- DISABLE_IRQs; /* So that the page # remains correct */
+ ewrk3_init(dev);
/*
- ** Get a free page from the FMQ when resources are available
+ ** Unmask EWRK3 board interrupts
*/
- if (inb(EWRK3_FMQC) > 0) {
- u_long buf = 0;
- u_char page;
+ ENABLE_IRQs;
- if ((page = inb(EWRK3_FMQ)) < lp->mPage) {
- /*
- ** Set up shared memory window and pointer into the window
- */
- while (test_and_set_bit(0, (void *) &lp->lock) != 0); /* Wait for lock to free */
- if (lp->shmem_length == IO_ONLY) {
- outb(page, EWRK3_IOPR);
- } else if (lp->shmem_length == SHMEM_2K) {
- buf = lp->shmem_base;
- outb(page, EWRK3_MPR);
- } else if (lp->shmem_length == SHMEM_32K) {
- buf = ((((short) page << 11) & 0x7800) + lp->shmem_base);
- outb((page >> 4), EWRK3_MPR);
- } else if (lp->shmem_length == SHMEM_64K) {
- buf = ((((short) page << 11) & 0xf800) + lp->shmem_base);
- outb((page >> 5), EWRK3_MPR);
- } else {
- status = -1;
- printk("%s: Oops - your private data area is hosed!\n", dev->name);
- }
+ dev->trans_start = jiffies;
+ netif_wake_queue(dev);
+ }
+}
- if (!status) {
+/*
+ ** Writes a socket buffer to the free page queue
+ */
+static int ewrk3_queue_pkt(struct sk_buff *skb, struct net_device *dev)
+{
+ struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+ u_long iobase = dev->base_addr;
+ int status = 0;
+ u_char icr;
- /*
- ** Set up the buffer control structures and copy the data from
- ** the socket buffer to the shared memory .
- */
+ netif_stop_queue(dev);
+#ifdef CONFIG_SMP
+#error "This needs spinlocks"
+#endif
+ DISABLE_IRQs; /* So that the page # remains correct */
- if (lp->shmem_length == IO_ONLY) {
- int i;
- u_char *p = skb->data;
+ /*
+ ** Get a free page from the FMQ when resources are available
+ */
+ if (inb(EWRK3_FMQC) > 0)
+ {
+ u_long buf = 0;
+ u_char page;
+ if ((page = inb(EWRK3_FMQ)) < lp->mPage) {
+ /*
+ ** Set up shared memory window and pointer into the window
+ */
+ while (test_and_set_bit(0, (void *) &lp->lock) != 0); /* Wait for lock to free */
+ if (lp->shmem_length == IO_ONLY) {
+ outb(page, EWRK3_IOPR);
+ } else if (lp->shmem_length == SHMEM_2K) {
+ buf = lp->shmem_base;
+ outb(page, EWRK3_MPR);
+ } else if (lp->shmem_length == SHMEM_32K) {
+ buf = ((((short) page << 11) & 0x7800) + lp->shmem_base);
+ outb((page >> 4), EWRK3_MPR);
+ } else if (lp->shmem_length == SHMEM_64K) {
+ buf = ((((short) page << 11) & 0xf800) + lp->shmem_base);
+ outb((page >> 5), EWRK3_MPR);
+ } else {
+ status = -1;
+ printk(KERN_ERR "%s: Oops - your private data area is hosed!\n", dev->name);
+ }
+
+ if (!status) {
+ /*
+ ** Set up the buffer control structures and copy the data from
+ ** the socket buffer to the shared memory .
+ */
+ if (lp->shmem_length == IO_ONLY) {
+ int i;
+ u_char *p = skb->data;
outb((char) (TCR_QMODE | TCR_PAD | TCR_IFC), EWRK3_DATA);
- outb((char) (skb->len & 0xff), EWRK3_DATA);
- outb((char) ((skb->len >> 8) & 0xff), EWRK3_DATA);
- outb((char) 0x04, EWRK3_DATA);
- for (i = 0; i < skb->len; i++) {
- outb(*p++, EWRK3_DATA);
- }
+ outb((char) (skb->len & 0xff), EWRK3_DATA);
+ outb((char) ((skb->len >> 8) & 0xff), EWRK3_DATA);
+ outb((char) 0x04, EWRK3_DATA);
+ for (i = 0; i < skb->len; i++) {
+ outb(*p++, EWRK3_DATA);
+ }
+ outb(page, EWRK3_TQ); /* Start sending pkt */
+ } else {
+ writeb((char) (TCR_QMODE | TCR_PAD | TCR_IFC), (char *) buf); /* ctrl byte */
+ buf += 1;
+ writeb((char) (skb->len & 0xff), (char *) buf); /* length (16 bit xfer) */
+ buf += 1;
+ if (lp->txc) {
+ writeb((char) (((skb->len >> 8) & 0xff) | XCT), (char *) buf);
+ buf += 1;
+ writeb(0x04, (char *) buf); /* index byte */
+ buf += 1;
+ writeb(0x00, (char *) (buf + skb->len)); /* Write the XCT flag */
+ isa_memcpy_toio(buf, skb->data, PRELOAD); /* Write PRELOAD bytes */
outb(page, EWRK3_TQ); /* Start sending pkt */
+ isa_memcpy_toio(buf + PRELOAD, skb->data + PRELOAD, skb->len - PRELOAD);
+ writeb(0xff, (char *) (buf + skb->len)); /* Write the XCT flag */
} else {
- writeb((char) (TCR_QMODE | TCR_PAD | TCR_IFC), (char *) buf); /* ctrl byte */
+ writeb((char) ((skb->len >> 8) & 0xff), (char *) buf);
buf += 1;
- writeb((char) (skb->len & 0xff), (char *) buf); /* length (16 bit xfer) */
+ writeb(0x04, (char *) buf); /* index byte */
buf += 1;
- if (lp->txc) {
- writeb((char) (((skb->len >> 8) & 0xff) | XCT), (char *) buf);
- buf += 1;
- writeb(0x04, (char *) buf); /* index byte */
- buf += 1;
- writeb(0x00, (char *) (buf + skb->len)); /* Write the XCT flag */
- isa_memcpy_toio(buf, skb->data, PRELOAD); /* Write PRELOAD bytes */
- outb(page, EWRK3_TQ); /* Start sending pkt */
- isa_memcpy_toio(buf + PRELOAD, skb->data + PRELOAD, skb->len - PRELOAD);
- writeb(0xff, (char *) (buf + skb->len)); /* Write the XCT flag */
- } else {
- writeb((char) ((skb->len >> 8) & 0xff), (char *) buf);
- buf += 1;
- writeb(0x04, (char *) buf); /* index byte */
- buf += 1;
- isa_memcpy_toio(buf, skb->data, skb->len); /* Write data bytes */
- outb(page, EWRK3_TQ); /* Start sending pkt */
- }
+ isa_memcpy_toio(buf, skb->data, skb->len); /* Write data bytes */
+ outb(page, EWRK3_TQ); /* Start sending pkt */
}
-
- dev->trans_start = jiffies;
- dev_kfree_skb(skb);
-
- } else { /* return unused page to the free memory queue */
- outb(page, EWRK3_FMQ);
}
- lp->lock = 0; /* unlock the page register */
- } else {
- printk("ewrk3_queue_pkt(): Invalid free memory page (%d).\n",
- (u_char) page);
+
+ dev->trans_start = jiffies;
+ dev_kfree_skb(skb);
+ } else { /* return unused page to the free memory queue */
+ outb(page, EWRK3_FMQ);
}
+ lp->lock = 0; /* unlock the page register */
} else {
- printk("ewrk3_queue_pkt(): No free resources...\n");
- printk("ewrk3_queue_pkt(): CSR: %02x ICR: %02x FMQC: %02x\n", inb(EWRK3_CSR), inb(EWRK3_ICR), inb(EWRK3_FMQC));
+ printk("ewrk3_queue_pkt(): Invalid free memory page (%d).\n",
+ (u_char) page);
}
+ } else {
+ printk(KERN_WARNING "%s: ewrk3_queue_pkt(): No free resources...\n", dev->name);
+ printk(KERN_WARNING "%s: ewrk3_queue_pkt(): CSR: %02x ICR: %02x FMQC: %02x\n", dev->name, inb(EWRK3_CSR), inb(EWRK3_ICR), inb(EWRK3_FMQC));
+ }
- /* Check for free resources: clear 'tbusy' if there are some */
- if (inb(EWRK3_FMQC) > 0) {
- dev->tbusy = 0;
- }
- ENABLE_IRQs;
+ /* Check for free resources: clear 'tbusy' if there are some */
+ if (inb(EWRK3_FMQC) > 0) {
+ netif_wake_queue(dev);
}
+ ENABLE_IRQs;
return status;
}
@@ -878,60 +876,46 @@ static void ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
u_long iobase;
u_char icr, cr, csr;
- if (dev == NULL) {
- printk("ewrk3_interrupt(): irq %d for unknown device.\n", irq);
- } else {
- lp = (struct ewrk3_private *) dev->priv;
- iobase = dev->base_addr;
-
- if (dev->interrupt)
- printk("%s: Re-entering the interrupt handler.\n", dev->name);
-
- dev->interrupt = MASK_INTERRUPTS;
+ lp = (struct ewrk3_private *) dev->priv;
+ iobase = dev->base_addr;
- /* get the interrupt information */
- csr = inb(EWRK3_CSR);
-
- /*
- ** Mask the EWRK3 board interrupts and turn on the LED
- */
- DISABLE_IRQs;
-
- cr = inb(EWRK3_CR);
- cr |= CR_LED;
- outb(cr, EWRK3_CR);
+ /* get the interrupt information */
+ csr = inb(EWRK3_CSR);
- if (csr & CSR_RNE) /* Rx interrupt (packet[s] arrived) */
- ewrk3_rx(dev);
+ /*
+ ** Mask the EWRK3 board interrupts and turn on the LED
+ */
+ DISABLE_IRQs;
- if (csr & CSR_TNE) /* Tx interrupt (packet sent) */
- ewrk3_tx(dev);
+ cr = inb(EWRK3_CR);
+ cr |= CR_LED;
+ outb(cr, EWRK3_CR);
- /*
- ** Now deal with the TX/RX disable flags. These are set when there
- ** are no more resources. If resources free up then enable these
- ** interrupts, otherwise mask them - failure to do this will result
- ** in the system hanging in an interrupt loop.
- */
- if (inb(EWRK3_FMQC)) { /* any resources available? */
- lp->irq_mask |= ICR_TXDM | ICR_RXDM; /* enable the interrupt source */
- csr &= ~(CSR_TXD | CSR_RXD); /* ensure restart of a stalled TX or RX */
- outb(csr, EWRK3_CSR);
- dev->tbusy = 0; /* clear TX busy flag */
- mark_bh(NET_BH);
- } else {
- lp->irq_mask &= ~(ICR_TXDM | ICR_RXDM); /* disable the interrupt source */
- }
+ if (csr & CSR_RNE) /* Rx interrupt (packet[s] arrived) */
+ ewrk3_rx(dev);
- /* Unmask the EWRK3 board interrupts and turn off the LED */
- cr &= ~CR_LED;
- outb(cr, EWRK3_CR);
+ if (csr & CSR_TNE) /* Tx interrupt (packet sent) */
+ ewrk3_tx(dev);
- dev->interrupt = UNMASK_INTERRUPTS;
- ENABLE_IRQs;
+ /*
+ ** Now deal with the TX/RX disable flags. These are set when there
+ ** are no more resources. If resources free up then enable these
+ ** interrupts, otherwise mask them - failure to do this will result
+ ** in the system hanging in an interrupt loop.
+ */
+ if (inb(EWRK3_FMQC)) { /* any resources available? */
+ lp->irq_mask |= ICR_TXDM | ICR_RXDM; /* enable the interrupt source */
+ csr &= ~(CSR_TXD | CSR_RXD); /* ensure restart of a stalled TX or RX */
+ outb(csr, EWRK3_CSR);
+ netif_wake_queue(dev);
+ } else {
+ lp->irq_mask &= ~(ICR_TXDM | ICR_RXDM); /* disable the interrupt source */
}
- return;
+ /* Unmask the EWRK3 board interrupts and turn off the LED */
+ cr &= ~CR_LED;
+ outb(cr, EWRK3_CR);
+ ENABLE_IRQs;
}
static int ewrk3_rx(struct net_device *dev)
@@ -1120,9 +1104,8 @@ static int ewrk3_close(struct net_device *dev)
u_long iobase = dev->base_addr;
u_char icr, csr;
- dev->start = 0;
- dev->tbusy = 1;
-
+ netif_stop_queue(dev);
+
if (ewrk3_debug > 1) {
printk("%s: Shutting down ethercard, status was %2.2x.\n",
dev->name, inb(EWRK3_CSR));
@@ -1369,8 +1352,7 @@ static void __init eisa_probe(struct net_device *dev, u_long ioaddr)
** are not available then insert a new device structure at the end of
** the current list.
*/
-static struct net_device * __init
-alloc_device(struct net_device *dev, u_long iobase)
+static struct net_device * __init alloc_device(struct net_device *dev, u_long iobase)
{
struct net_device *adev = NULL;
int fixed = 0, new_dev = 0;
diff --git a/drivers/net/fc/iph5526.c b/drivers/net/fc/iph5526.c
index c1c9fde27..785a3fafd 100644
--- a/drivers/net/fc/iph5526.c
+++ b/drivers/net/fc/iph5526.c
@@ -919,7 +919,8 @@ u_int tag;
/* An IP frame was transmitted to a Bad AL_PA. Free up
* the skb used.
*/
- dev_kfree_skb((struct sk_buff *)(bus_to_virt(transaction_id)));
+ dev_kfree_skb_irq((struct sk_buff *)(bus_to_virt(transaction_id)));
+ netif_wake_queue(fi->dev);
}
} /* End of IP frame timing out. */
} /* End of frame timing out. */
@@ -977,7 +978,8 @@ u_int tag;
* Free the skb that was used for this IP frame.
*/
if ((status == 0) && (seq_count > 1)) {
- dev_kfree_skb((struct sk_buff *)(bus_to_virt(transaction_id)));
+ dev_kfree_skb_irq((struct sk_buff *)(bus_to_virt(transaction_id)));
+ netif_wake_queue(fi->dev);
}
}
}
@@ -2914,65 +2916,59 @@ static void update_EDB_indx(struct fc_info *fi)
static int iph5526_open(struct net_device *dev)
{
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue(dev);
MOD_INC_USE_COUNT;
return 0;
}
static int iph5526_close(struct net_device *dev)
{
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue(dev);
MOD_DEC_USE_COUNT;
return 0;
}
+static void iph5526_timeout(struct net_device *dev)
+{
+ struct fc_info *fi = (struct fc_info*)dev->priv;
+ printk(KERN_WARNING "%s: timed out on send.\n", dev->name);
+ fi->fc_stats.rx_dropped++;
+ dev->trans_start = jiffies;
+ netif_wake_queue(dev);
+}
+
static int iph5526_send_packet(struct sk_buff *skb, struct net_device *dev)
{
-struct fc_info *fi = (struct fc_info*)dev->priv;
-int status = 0;
-short type = 0;
-u_long flags;
+ struct fc_info *fi = (struct fc_info*)dev->priv;
+ int status = 0;
+ short type = 0;
+ u_long flags;
+ struct fcllc *fcllc;
+
ENTER("iph5526_send_packet");
- if (dev->tbusy) {
- printk(KERN_WARNING "%s: DEVICE BUSY\n", dev->name);
- dev->tbusy = 0;
- fi->fc_stats.rx_dropped++;
- dev->trans_start = jiffies;
- return 0;
- }
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
- printk(KERN_WARNING "%s: Transmitter access conflict.\n",
-dev->name);
- fi->fc_stats.rx_dropped++;
- return 1;
- }
- else {
- struct fcllc *fcllc;
- /* Strip off the pseudo header.
- */
- skb->data = skb->data + 2*FC_ALEN;
- skb->len = skb->len - 2*FC_ALEN;
- fcllc = (struct fcllc *)skb->data;
- type = ntohs(fcllc->ethertype);
-
- spin_lock_irqsave(&fi->fc_lock, flags);
- switch(type) {
- case ETH_P_IP:
- status = tx_ip_packet(skb, skb->len, fi);
- break;
- case ETH_P_ARP:
- status = tx_arp_packet(skb->data, skb->len, fi);
- break;
- default:
- T_MSG("WARNING!!! Received Unknown Packet Type... Discarding...");
- fi->fc_stats.rx_dropped++;
- break;
- }
- spin_unlock_irqrestore(&fi->fc_lock, flags);
+
+ netif_stop_queue(dev);
+ /* Strip off the pseudo header.
+ */
+ skb->data = skb->data + 2*FC_ALEN;
+ skb->len = skb->len - 2*FC_ALEN;
+ fcllc = (struct fcllc *)skb->data;
+ type = ntohs(fcllc->ethertype);
+
+ spin_lock_irqsave(&fi->fc_lock, flags);
+ switch(type) {
+ case ETH_P_IP:
+ status = tx_ip_packet(skb, skb->len, fi);
+ break;
+ case ETH_P_ARP:
+ status = tx_arp_packet(skb->data, skb->len, fi);
+ break;
+ default:
+ T_MSG("WARNING!!! Received Unknown Packet Type... Discarding...");
+ fi->fc_stats.rx_dropped++;
+ break;
}
+ spin_unlock_irqrestore(&fi->fc_lock, flags);
if (status) {
fi->fc_stats.tx_bytes += skb->len;
@@ -2981,14 +2977,14 @@ dev->name);
else
fi->fc_stats.rx_dropped++;
dev->trans_start = jiffies;
- dev->tbusy = 0;
/* We free up the IP buffers in the OCI_interrupt handler.
* status == 0 implies that the frame was not transmitted. So the
* skb is freed here.
*/
if ((type == ETH_P_ARP) || (status == 0))
dev_kfree_skb(skb);
- mark_bh(NET_BH);
+ else
+ netif_wake_queue(dev);
LEAVE("iph5526_send_packet");
return 0;
}
diff --git a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c
index 10366f2f8..b26351886 100644
--- a/drivers/net/fmv18x.c
+++ b/drivers/net/fmv18x.c
@@ -58,8 +58,9 @@ static const char *version =
#include <linux/skbuff.h>
#include <linux/delay.h>
-static int fmv18x_probe_list[] __initdata =
-{0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0};
+static int fmv18x_probe_list[] __initdata = {
+ 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0
+};
/* use 0 for production, 1 for verification, >2 for debug */
#ifndef NET_DEBUG
@@ -112,9 +113,10 @@ extern int fmv18x_probe(struct net_device *dev);
static int fmv18x_probe1(struct net_device *dev, short ioaddr);
static int net_open(struct net_device *dev);
-static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
+static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void net_rx(struct net_device *dev);
+static void net_timeout(struct net_device *dev);
static int net_close(struct net_device *dev);
static struct net_device_stats *net_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
@@ -126,14 +128,8 @@ static void set_multicast_list(struct net_device *dev);
If dev->base_addr == 2, allocate space for the device and return success
(detachable devices only).
*/
-#ifdef HAVE_DEVLIST
-/* Support for an alternate probe manager, which will eliminate the
- boilerplate below. */
-struct netdev_entry fmv18x_drv =
-{"fmv18x", fmv18x_probe1, FMV18X_IO_EXTENT, fmv18x_probe_list};
-#else
-int __init
-fmv18x_probe(struct net_device *dev)
+
+int __init fmv18x_probe(struct net_device *dev)
{
int i;
int base_addr = dev ? dev->base_addr : 0;
@@ -153,7 +149,6 @@ fmv18x_probe(struct net_device *dev)
return ENODEV;
}
-#endif
/* The Fujitsu datasheet suggests that the NIC be probed for by checking its
"signature", the default bit pattern after a reset. This *doesn't* work --
@@ -276,9 +271,11 @@ int __init fmv18x_probe1(struct net_device *dev, short ioaddr)
dev->open = net_open;
dev->stop = net_close;
- dev->hard_start_xmit = net_send_packet;
- dev->get_stats = net_get_stats;
- dev->set_multicast_list = &set_multicast_list;
+ dev->hard_start_xmit = net_send_packet;
+ dev->tx_timeout = net_timeout;
+ dev->watchdog_timeo = HZ/10;
+ dev->get_stats = net_get_stats;
+ dev->set_multicast_list = set_multicast_list;
/* Fill in the fields of 'dev' with ethernet-generic values. */
@@ -310,10 +307,8 @@ static int net_open(struct net_device *dev)
outb(0xff, ioaddr + RX_STATUS);
lp->open_time = jiffies;
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
-
+ netif_start_queue(dev);
+
/* Enable the IRQ of the LAN Card */
outb(0x80, ioaddr + FJ_CONFIG1);
@@ -325,93 +320,86 @@ static int net_open(struct net_device *dev)
return 0;
}
-static int
-net_send_packet(struct sk_buff *skb, struct net_device *dev)
+static void net_timeout(struct net_device *dev)
{
struct net_local *lp = (struct net_local *)dev->priv;
int ioaddr = dev->base_addr;
+ unsigned long flags;
+
+
+ printk(KERN_WARNING "%s: transmit timed out with status %04x, %s?\n", dev->name,
+ htons(inw(ioaddr + TX_STATUS)),
+ inb(ioaddr + TX_STATUS) & 0x80
+ ? "IRQ conflict" : "network cable problem");
+ printk(KERN_WARNING "%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
+ dev->name, htons(inw(ioaddr + 0)),
+ htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
+ htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
+ htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
+ htons(inw(ioaddr +14)));
+ printk(KERN_WARNING "eth card: %04x %04x\n",
+ htons(inw(ioaddr+FJ_STATUS0)),
+ htons(inw(ioaddr+FJ_CONFIG0)));
+ lp->stats.tx_errors++;
+ /* ToDo: We should try to restart the adaptor... */
+ save_flags(flags);
+ cli();
- if (dev->tbusy) {
- /* If we get here, some higher level has decided we are broken.
- There should really be a "kick me" function call instead. */
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 10)
- return 1;
- printk("%s: transmit timed out with status %04x, %s?\n", dev->name,
- htons(inw(ioaddr + TX_STATUS)),
- inb(ioaddr + TX_STATUS) & 0x80
- ? "IRQ conflict" : "network cable problem");
- printk("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
- dev->name, htons(inw(ioaddr + 0)),
- htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
- htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
- htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
- htons(inw(ioaddr +14)));
- printk("eth card: %04x %04x\n",
- htons(inw(ioaddr+FJ_STATUS0)),
- htons(inw(ioaddr+FJ_CONFIG0)));
- lp->stats.tx_errors++;
- /* ToDo: We should try to restart the adaptor... */
- cli();
-
- /* Initialize LAN Controller and LAN Card */
- outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */
- outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */
- outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */
- outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure */
- net_open(dev);
-
- sti();
- }
-
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk("%s: Transmitter access conflict.\n", dev->name);
- else {
- short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned char *buf = skb->data;
-
- if (length > ETH_FRAME_LEN) {
- if (net_debug)
- printk("%s: Attempting to send a large packet (%d bytes).\n",
- dev->name, length);
- return 1;
- }
+ /* Initialize LAN Controller and LAN Card */
+ outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */
+ outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */
+ outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */
+ outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure */
+ net_open(dev);
+ restore_flags(flags);
+}
- if (net_debug > 4)
- printk("%s: Transmitting a packet of length %lu.\n", dev->name,
- (unsigned long)skb->len);
-
- /* We may not start transmitting unless we finish transferring
- a packet into the Tx queue. During executing the following
- codes we possibly catch a Tx interrupt. Thus we flag off
- tx_queue_ready, so that we prevent the interrupt routine
- (net_interrupt) to start transmitting. */
- lp->tx_queue_ready = 0;
- {
- outw(length, ioaddr + DATAPORT);
- outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
-
- lp->tx_queue++;
- lp->tx_queue_len += length + 2;
- }
- lp->tx_queue_ready = 1;
-
- if (lp->tx_started == 0) {
- /* If the Tx is idle, always trigger a transmit. */
- outb(0x80 | lp->tx_queue, ioaddr + TX_START);
- lp->tx_queue = 0;
- lp->tx_queue_len = 0;
- dev->trans_start = jiffies;
- lp->tx_started = 1;
- dev->tbusy = 0;
- } else if (lp->tx_queue_len < 4096 - 1502)
- /* Yes, there is room for one more packet. */
- dev->tbusy = 0;
+static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+ short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+ unsigned char *buf = skb->data;
+
+ /* Block a transmit from overlapping. */
+
+ netif_stop_queue(dev);
+
+ if (length > ETH_FRAME_LEN) {
+ if (net_debug)
+ printk("%s: Attempting to send a large packet (%d bytes).\n",
+ dev->name, length);
+ return 1;
}
- dev_kfree_skb (skb);
-
+ if (net_debug > 4)
+ printk("%s: Transmitting a packet of length %lu.\n", dev->name,
+ (unsigned long)skb->len);
+ /* We may not start transmitting unless we finish transferring
+ a packet into the Tx queue. During executing the following
+ codes we possibly catch a Tx interrupt. Thus we flag off
+ tx_queue_ready, so that we prevent the interrupt routine
+ (net_interrupt) to start transmitting. */
+ lp->tx_queue_ready = 0;
+ {
+ outw(length, ioaddr + DATAPORT);
+ outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
+ lp->tx_queue++;
+ lp->tx_queue_len += length + 2;
+ }
+ lp->tx_queue_ready = 1;
+ if (lp->tx_started == 0) {
+ /* If the Tx is idle, always trigger a transmit. */
+ outb(0x80 | lp->tx_queue, ioaddr + TX_START);
+ lp->tx_queue = 0;
+ lp->tx_queue_len = 0;
+ dev->trans_start = jiffies;
+ lp->tx_started = 1;
+ netif_wake_queue(dev);
+ } else if (lp->tx_queue_len < 4096 - 1502)
+ /* Yes, there is room for one more packet. */
+ netif_wake_queue(dev);
+
+ dev_kfree_skb(skb);
return 0;
}
@@ -424,12 +412,6 @@ net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
struct net_local *lp;
int ioaddr, status;
- if (dev == NULL) {
- printk ("fmv18x_interrupt(): irq %d for unknown device.\n", irq);
- return;
- }
- dev->interrupt = 1;
-
ioaddr = dev->base_addr;
lp = (struct net_local *)dev->priv;
status = inw(ioaddr + TX_STATUS);
@@ -467,23 +449,18 @@ net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
lp->tx_queue = 0;
lp->tx_queue_len = 0;
dev->trans_start = jiffies;
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_wake_queue(dev); /* Inform upper layers. */
} else {
lp->tx_started = 0;
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_wake_queue(dev); /* Inform upper layers. */
}
}
}
-
- dev->interrupt = 0;
return;
}
/* We have a good packet(s), get it/them out of the buffers. */
-static void
-net_rx(struct net_device *dev)
+static void net_rx(struct net_device *dev)
{
struct net_local *lp = (struct net_local *)dev->priv;
int ioaddr = dev->base_addr;
@@ -578,9 +555,8 @@ static int net_close(struct net_device *dev)
((struct net_local *)dev->priv)->open_time = 0;
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
+
/* Set configuration register 0 to disable Tx and Rx. */
outb(0xda, ioaddr + CONFIG_0);
@@ -602,11 +578,6 @@ static int net_close(struct net_device *dev)
static struct net_device_stats *net_get_stats(struct net_device *dev)
{
struct net_local *lp = (struct net_local *)dev->priv;
-
- cli();
- /* ToDo: Update the statistics from the device registers. */
- sti();
-
return &lp->stats;
}
diff --git a/drivers/net/gmac.c b/drivers/net/gmac.c
index 7ee18bfe9..b1a431499 100644
--- a/drivers/net/gmac.c
+++ b/drivers/net/gmac.c
@@ -51,6 +51,7 @@ struct gmac {
int phy_addr;
int full_duplex;
struct net_device_stats stats;
+ struct net_device *next_gmac;
};
#define GM_OUT(r, v) out_le32(gm->regs + (r)/4, (v))
@@ -80,6 +81,7 @@ static void gmac_receive(struct net_device *dev);
static void gmac_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static struct net_device_stats *gmac_stats(struct net_device *dev);
static int gmac_probe(void);
+static void gmac_probe1(struct device_node *gmac);
/* Stuff for talking to the physical-layer chip */
static int
@@ -383,7 +385,7 @@ static int gmac_xmit_start(struct sk_buff *skb, struct net_device *dev)
i = gm->next_tx;
if (gm->tx_buff[i] != 0) {
/* buffer is full, can't send this packet at the moment */
- dev->tbusy = 1;
+ netif_stop_queue(dev);
gm->tx_full = 1;
restore_flags(flags);
return 1;
@@ -421,7 +423,7 @@ static int gmac_tx_cleanup(struct gmac *gm)
gm->stats.tx_bytes += skb->len;
++gm->stats.tx_packets;
gm->tx_buff[i] = NULL;
- dev_kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
if (++i >= NTX)
i = 0;
}
@@ -452,7 +454,7 @@ static void gmac_receive(struct net_device *dev)
++gm->stats.rx_dropped;
} else if (ld_le32(&dp->status) & 0x40000000) {
++gm->stats.rx_errors;
- dev_kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
} else {
skb_put(skb, len);
skb->dev = dev;
@@ -486,14 +488,11 @@ static void gmac_interrupt(int irq, void *dev_id, struct pt_regs *regs)
status = GM_IN(INTR_STATUS);
GM_OUT(INTR_ACK, status);
- if (status & GMAC_IRQ_MIF) {
+ if (status & GMAC_IRQ_MIF)
mii_interrupt(gm);
- }
gmac_receive(dev);
- if (gmac_tx_cleanup(gm)){
- dev->tbusy = 0;
- mark_bh(NET_BH);
- }
+ if (gmac_tx_cleanup(gm))
+ netif_wake_queue(dev);
}
static struct net_device_stats *gmac_stats(struct net_device *dev)
@@ -505,33 +504,44 @@ static struct net_device_stats *gmac_stats(struct net_device *dev)
static int __init gmac_probe(void)
{
- static int gmacs_found;
- static struct device_node *next_gmac;
struct device_node *gmac;
- struct gmac *gm;
- unsigned long descpage;
- unsigned char *addr;
- int i;
-
- if (gmacs != NULL)
- return -EBUSY;
/*
* We could (and maybe should) do this using PCI scanning
* for vendor/net_device ID 0x106b/0x21.
*/
- if (!gmacs_found) {
- next_gmac = find_compatible_devices("network", "gmac");
- gmacs_found = 1;
- }
- if ((gmac = next_gmac) == 0)
- return -ENODEV;
- next_gmac = gmac->next;
+ for (gmac = find_compatible_devices("network", "gmac"); gmac != 0;
+ gmac = gmac->next)
+ gmac_probe1(gmac);
+
+ return 0;
+}
+
+static void gmac_probe1(struct device_node *gmac)
+{
+ struct gmac *gm;
+ unsigned long descpage;
+ unsigned char *addr;
+ struct net_device *dev;
+ int i;
if (gmac->n_addrs < 1 || gmac->n_intrs < 1) {
printk(KERN_ERR "can't use GMAC %s: %d addrs and %d intrs\n",
gmac->full_name, gmac->n_addrs, gmac->n_intrs);
- return -ENODEV;
+ return;
+ }
+
+ addr = get_property(gmac, "local-mac-address", NULL);
+ if (addr == NULL) {
+ printk(KERN_ERR "Can't get mac-address for GMAC %s\n",
+ gmac->full_name);
+ return;
+ }
+
+ descpage = get_free_page(GFP_KERNEL);
+ if (descpage == 0) {
+ printk(KERN_ERR "GMAC: can't get a page for descriptors\n");
+ return;
}
dev = init_etherdev(0, sizeof(struct gmac));
@@ -544,13 +554,6 @@ static int __init gmac_probe(void)
gm->sysregs = (volatile unsigned int *) ioremap(0xf8000000, 0x1000);
dev->irq = gmac->intrs[0].line;
- addr = get_property(gmac, "local-mac-address", NULL);
- if (addr == NULL) {
- printk(KERN_ERR "Can't get mac-address for GMAC %s\n",
- gmac->full_name);
- return -EAGAIN;
- }
-
printk(KERN_INFO "%s: GMAC at", dev->name);
for (i = 0; i < 6; ++i) {
dev->dev_addr[i] = addr[i];
@@ -558,12 +561,6 @@ static int __init gmac_probe(void)
}
printk("\n");
- descpage = get_free_page(GFP_KERNEL);
- if (descpage == 0) {
- printk(KERN_ERR "GMAC: can't get a page for descriptors\n");
- return -EAGAIN;
- }
-
gm->desc_page = descpage;
gm->rxring = (volatile struct gmac_dma_desc *) descpage;
gm->txring = (volatile struct gmac_dma_desc *) (descpage + 0x800);
@@ -577,34 +574,29 @@ static int __init gmac_probe(void)
ether_setup(dev);
- if (request_irq(dev->irq, gmac_interrupt, 0, "GMAC", dev)) {
+ if (request_irq(dev->irq, gmac_interrupt, 0, "GMAC", dev))
printk(KERN_ERR "GMAC: can't get irq %d\n", dev->irq);
- return -EAGAIN;
- }
+ gm->next_gmac = gmacs;
gmacs = dev;
-
- return 0;
}
-MODULE_AUTHOR("Paul Mackerras");
+MODULE_AUTHOR("Paul Mackerras/Ben Herrenschmidt");
MODULE_DESCRIPTION("PowerMac GMAC driver.");
-
static void __exit gmac_cleanup_module(void)
{
struct gmac *gm;
-
- /* XXX should handle more than one */
- if (gmacs == NULL)
- return;
-
- gm = (struct gmac *) gmacs->priv;
- free_irq(gmacs->irq, gmac_interrupt);
- free_page(gm->descpage);
- unregister_netdev(gmacs);
- kfree(gmacs);
- gmacs = NULL;
+ struct net_device *dev;
+
+ while ((dev = gmacs) != NULL) {
+ gm = (struct gmac *) dev->priv;
+ gmacs = gm->next_gmac;
+ free_irq(dev->irq, dev);
+ free_page(gm->desc_page);
+ unregister_netdev(dev);
+ kfree(dev);
+ }
}
module_init(gmac_probe);
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 16dc8a976..b1871485a 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -158,24 +158,6 @@ sp_free(struct sixpack *sp)
}
-/* Set the "sending" flag. */
-static inline void
-sp_lock(struct sixpack *sp)
-{
- if (test_and_set_bit(0, (void *) &sp->dev->tbusy))
- printk(KERN_WARNING "%s: trying to lock already locked device!\n", sp->dev->name);
-}
-
-
-/* Clear the "sending" flag. */
-static inline void
-sp_unlock(struct sixpack *sp)
-{
- if (!test_and_clear_bit(0, (void *)&sp->dev->tbusy))
- printk(KERN_WARNING "%s: trying to unlock already unlocked device!\n", sp->dev->name);
-}
-
-
/* Send one completely decapsulated IP datagram to the IP layer. */
/* This is the routine that sends the received data to the kernel AX.25.
@@ -226,7 +208,7 @@ sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
len = sp->mtu;
printk(KERN_DEBUG "%s: truncating oversized transmit packet!\n", sp->dev->name);
sp->tx_dropped++;
- sp_unlock(sp);
+ netif_start_queue(sp->dev);
return;
}
@@ -235,21 +217,21 @@ sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
if (p[0] > 5)
{
printk(KERN_DEBUG "%s: invalid KISS command -- dropped\n", sp->dev->name);
- sp_unlock(sp);
+ netif_start_queue(sp->dev);
return;
}
if ((p[0] != 0) && (len > 2))
{
printk(KERN_DEBUG "%s: KISS control packet too long -- dropped\n", sp->dev->name);
- sp_unlock(sp);
+ netif_start_queue(sp->dev);
return;
}
if ((p[0] == 0) && (len < 15))
{
printk(KERN_DEBUG "%s: bad AX.25 packet to transmit -- dropped\n", sp->dev->name);
- sp_unlock(sp);
+ netif_start_queue(sp->dev);
sp->tx_dropped++;
return;
}
@@ -301,17 +283,18 @@ static void sixpack_write_wakeup(struct tty_struct *tty)
struct sixpack *sp = (struct sixpack *) tty->disc_data;
/* First make sure we're connected. */
- if (!sp || sp->magic != SIXPACK_MAGIC || !sp->dev->start) {
+ if (!sp || sp->magic != SIXPACK_MAGIC ||
+ !netif_running(sp->dev)) {
return;
}
+
if (sp->xleft <= 0) {
/* Now serial buffer is almost free & we can start
* transmission of another packet */
sp->tx_packets++;
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
- sp_unlock(sp);
sp->tx_enable = 0;
- mark_bh(NET_BH);
+ netif_wake_queue(sp->dev);
return;
}
@@ -331,18 +314,9 @@ sp_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct sixpack *sp = (struct sixpack*)(dev->priv);
- if (!dev->start)
- {
- printk(KERN_WARNING "%s: xmit call when iface is down\n", dev->name);
- return 1;
- }
-
- if (dev->tbusy)
- return 1;
-
/* We were not busy, so we are now... :-) */
if (skb != NULL) {
- sp_lock(sp);
+ netif_stop_queue(dev);
sp->tx_bytes+=skb->len; /*---2.1.x---*/
sp_encaps(sp, skb->data, skb->len);
dev_kfree_skb(skb);
@@ -458,8 +432,7 @@ sp_open(struct net_device *dev)
sp->tnc_ok = 0;
sp->tx_enable = 0;
- dev->tbusy = 0;
- dev->start = 1;
+ netif_start_queue(dev);
init_timer(&sp->tx_t);
init_timer(&sp->resync_t);
@@ -477,9 +450,8 @@ sp_close(struct net_device *dev)
return -EBUSY;
}
sp->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue(dev);
return 0;
}
@@ -506,7 +478,8 @@ sixpack_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, i
struct sixpack *sp = (struct sixpack *) tty->disc_data;
- if (!sp || sp->magic != SIXPACK_MAGIC || !sp->dev->start || !count)
+ if (!sp || sp->magic != SIXPACK_MAGIC ||
+ !netif_running(sp->dev) || !count)
return;
save_flags(flags);
@@ -723,17 +696,13 @@ static int sp_open_dev(struct net_device *dev)
/* Initialize 6pack control device -- register 6pack line discipline */
-#ifdef MODULE
-static int sixpack_init_ctrl_dev(void)
-#else /* !MODULE */
-int __init sixpack_init_ctrl_dev(struct net_device *dummy)
-#endif /* !MODULE */
+static int __init sixpack_init_ctrl_dev(void)
{
int status;
if (sixpack_maxdev < 4) sixpack_maxdev = 4; /* Sanity */
- printk(KERN_INFO "6pack: %s (dynamic channels, max=%d)\n",
+ printk(KERN_INFO "AX.25: 6pack driver, %s (dynamic channels, max=%d)\n",
SIXPACK_VERSION, sixpack_maxdev);
sixpack_ctrls = (sixpack_ctrl_t **) kmalloc(sizeof(void*)*sixpack_maxdev, GFP_KERNEL);
@@ -766,16 +735,40 @@ int __init sixpack_init_ctrl_dev(struct net_device *dummy)
printk(KERN_WARNING "6pack: can't register line discipline (err = %d)\n", status);
}
-#ifdef MODULE
return status;
-#else
- /* Return "not found", so that dev_init() will unlink
- * the placeholder device entry for us.
- */
- return ENODEV;
-#endif
}
+static void __exit sixpack_cleanup_driver(void)
+{
+ int i;
+
+ if (sixpack_ctrls != NULL)
+ {
+ for (i = 0; i < sixpack_maxdev; i++)
+ {
+ if (sixpack_ctrls[i])
+ {
+ /*
+ * VSV = if dev->start==0, then device
+ * unregistered while close proc.
+ */
+ if (netif_running(sixpack_ctrls[i]->dev))
+ unregister_netdev(&(sixpack_ctrls[i]->dev));
+
+ kfree(sixpack_ctrls[i]);
+ sixpack_ctrls[i] = NULL;
+ }
+ }
+ kfree(sixpack_ctrls);
+ sixpack_ctrls = NULL;
+ }
+ if ((i = tty_register_ldisc(N_6PACK, NULL)))
+ {
+ printk(KERN_WARNING "6pack: can't unregister line discipline (err = %d)\n", i);
+ }
+}
+
+
/* Initialize the 6pack driver. Called by DDI. */
int
sixpack_init(struct net_device *dev)
@@ -809,6 +802,7 @@ sixpack_init(struct net_device *dev)
dev->type = ARPHRD_AX25;
dev->tx_queue_len = 10;
dev->rebuild_header = sp_rebuild_header;
+ dev->tx_timeout = NULL;
memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN); /* Only activated in AX.25 mode */
memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN); /* "" "" "" "" */
@@ -821,45 +815,8 @@ sixpack_init(struct net_device *dev)
return 0;
}
-#ifdef MODULE
-
-int
-init_module(void)
-{
- return sixpack_init_ctrl_dev();
-}
-
-void
-cleanup_module(void)
-{
- int i;
- if (sixpack_ctrls != NULL)
- {
- for (i = 0; i < sixpack_maxdev; i++)
- {
- if (sixpack_ctrls[i])
- {
- /*
- * VSV = if dev->start==0, then device
- * unregistered while close proc.
- */
- if (sixpack_ctrls[i]->dev.start)
- unregister_netdev(&(sixpack_ctrls[i]->dev));
- kfree(sixpack_ctrls[i]);
- sixpack_ctrls[i] = NULL;
- }
- }
- kfree(sixpack_ctrls);
- sixpack_ctrls = NULL;
- }
- if ((i = tty_register_ldisc(N_6PACK, NULL)))
- {
- printk(KERN_WARNING "6pack: can't unregister line discipline (err = %d)\n", i);
- }
-}
-#endif /* MODULE */
/* ----> 6pack timer interrupt handler and friends. <---- */
static void
@@ -1127,3 +1084,9 @@ void decode_data(byte inbyte, struct sixpack *sp)
sp->rx_count = 0;
}
}
+
+
+MODULE_AUTHOR("Andreas Könsgen <ajk@ccac.rwth-aachen.de>");
+MODULE_DESCRIPTION("6pack driver for AX.25");
+module_init(sixpack_init_ctrl_dev);
+module_exit(sixpack_cleanup_driver);
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index d4191258d..98d228b91 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -3,7 +3,7 @@
/*
* baycom_epp.c -- baycom epp radio modem driver.
*
- * Copyright (C) 1998-1999
+ * Copyright (C) 1998-2000
* Thomas Sailer (sailer@ife.ee.ethz.ch)
*
* This program is free software; you can redistribute it and/or modify
@@ -26,14 +26,15 @@
*
*
* History:
- * 0.1 xx.xx.98 Initial version by Matthias Welwarsky (dg2fef)
- * 0.2 21.04.98 Massive rework by Thomas Sailer
- * Integrated FPGA EPP modem configuration routines
- * 0.3 11.05.98 Took FPGA config out and moved it into a separate program
- * 0.4 26.07.99 Adapted to new lowlevel parport driver interface
- * 0.5 03.08.99 adapt to Linus' new __setup/__initcall
- * removed some pre-2.2 kernel compatibility cruft
- * 0.6 10.08.99 Check if parport can do SPP and is safe to access during interrupt contexts
+ * 0.1 xx.xx.1998 Initial version by Matthias Welwarsky (dg2fef)
+ * 0.2 21.04.1998 Massive rework by Thomas Sailer
+ * Integrated FPGA EPP modem configuration routines
+ * 0.3 11.05.1998 Took FPGA config out and moved it into a separate program
+ * 0.4 26.07.1999 Adapted to new lowlevel parport driver interface
+ * 0.5 03.08.1999 adapt to Linus' new __setup/__initcall
+ * removed some pre-2.2 kernel compatibility cruft
+ * 0.6 10.08.1999 Check if parport can do SPP and is safe to access during interrupt contexts
+ * 0.7 12.02.2000 adapted to softnet driver interface
*
*/
@@ -47,8 +48,10 @@
#include <linux/tqueue.h>
#include <linux/fs.h>
#include <linux/parport.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <linux/if_arp.h>
+#include <linux/kmod.h>
#include <linux/hdlcdrv.h>
#include <linux/baycom.h>
#include <linux/soundmodem.h>
@@ -89,8 +92,8 @@ static const char paranoia_str[] = KERN_ERR
/* --------------------------------------------------------------------- */
static const char bc_drvname[] = "baycom_epp";
-static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-1999 Thomas Sailer, HB9JNX/AE4WA\n"
-KERN_INFO "baycom_epp: version 0.5 compiled " __TIME__ " " __DATE__ "\n";
+static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-2000 Thomas Sailer, HB9JNX/AE4WA\n"
+KERN_INFO "baycom_epp: version 0.7 compiled " __TIME__ " " __DATE__ "\n";
/* --------------------------------------------------------------------- */
@@ -228,8 +231,7 @@ struct baycom_state {
struct net_device_stats stats;
unsigned int ptt_keyed;
- struct sk_buff_head send_queue; /* Packets awaiting transmission */
-
+ struct sk_buff *skb; /* next transmit packet */
#ifdef BAYCOM_DEBUG
struct debug_vals {
@@ -394,15 +396,11 @@ static int exec_eppfpga(void *b)
sprintf(portarg, "%ld", bc->pdev->port->base);
printk(KERN_DEBUG "%s: %s -s -p %s -m %s\n", bc_drvname, eppconfig_path, portarg, modearg);
- for (i = 0; i < current->files->max_fds; i++ )
- if (current->files->fd[i])
- close(i);
- set_fs(KERNEL_DS); /* Allow execve args to be in kernel space. */
- current->uid = current->euid = current->fsuid = 0;
- if (execve(eppconfig_path, argv, envp) < 0) {
+ i = exec_usermodehelper(eppconfig_path, argv, envp);
+ if (i < 0) {
printk(KERN_ERR "%s: failed to exec %s -s -p %s -m %s, errno = %d\n",
- bc_drvname, eppconfig_path, portarg, modearg, errno);
- return -errno;
+ bc_drvname, eppconfig_path, portarg, modearg, i);
+ return i;
}
return 0;
}
@@ -515,71 +513,63 @@ static void encode_hdlc(struct baycom_state *bc)
if (bc->hdlctx.bufcnt > 0)
return;
- while ((skb = skb_dequeue(&bc->send_queue))) {
- if (skb->data[0] != 0) {
- do_kiss_params(bc, skb->data, skb->len);
- dev_kfree_skb(skb);
- continue;
- }
- pkt_len = skb->len-1; /* strip KISS byte */
- if (pkt_len >= HDLCDRV_MAXFLEN || pkt_len < 2) {
- dev_kfree_skb(skb);
- continue;
- }
- wp = bc->hdlctx.buf;
- bp = skb->data+1;
- crc = calc_crc_ccitt(bp, pkt_len);
- crcarr[0] = crc;
- crcarr[1] = crc >> 8;
- *wp++ = 0x7e;
- bitstream = bitbuf = numbit = 0;
- while (pkt_len > -2) {
- bitstream >>= 8;
- bitstream |= ((unsigned int)*bp) << 8;
- bitbuf |= ((unsigned int)*bp) << numbit;
- notbitstream = ~bitstream;
- bp++;
- pkt_len--;
- if (!pkt_len)
- bp = crcarr;
- ENCODEITERA(0);
- ENCODEITERA(1);
- ENCODEITERA(2);
- ENCODEITERA(3);
- ENCODEITERA(4);
- ENCODEITERA(5);
- ENCODEITERA(6);
- ENCODEITERA(7);
- goto enditer;
- ENCODEITERB(0);
- ENCODEITERB(1);
- ENCODEITERB(2);
- ENCODEITERB(3);
- ENCODEITERB(4);
- ENCODEITERB(5);
- ENCODEITERB(6);
- ENCODEITERB(7);
- enditer:
- numbit += 8;
- while (numbit >= 8) {
- *wp++ = bitbuf;
- bitbuf >>= 8;
- numbit -= 8;
- }
- }
- bitbuf |= 0x7e7e << numbit;
- numbit += 16;
- while (numbit >= 8) {
- *wp++ = bitbuf;
- bitbuf >>= 8;
- numbit -= 8;
- }
- bc->hdlctx.bufptr = bc->hdlctx.buf;
- bc->hdlctx.bufcnt = wp - bc->hdlctx.buf;
- dev_kfree_skb(skb);
- bc->stats.tx_packets++;
+ skb = bc->skb;
+ if (!skb)
return;
+ bc->skb = NULL;
+ pkt_len = skb->len-1; /* strip KISS byte */
+ wp = bc->hdlctx.buf;
+ bp = skb->data+1;
+ crc = calc_crc_ccitt(bp, pkt_len);
+ crcarr[0] = crc;
+ crcarr[1] = crc >> 8;
+ *wp++ = 0x7e;
+ bitstream = bitbuf = numbit = 0;
+ while (pkt_len > -2) {
+ bitstream >>= 8;
+ bitstream |= ((unsigned int)*bp) << 8;
+ bitbuf |= ((unsigned int)*bp) << numbit;
+ notbitstream = ~bitstream;
+ bp++;
+ pkt_len--;
+ if (!pkt_len)
+ bp = crcarr;
+ ENCODEITERA(0);
+ ENCODEITERA(1);
+ ENCODEITERA(2);
+ ENCODEITERA(3);
+ ENCODEITERA(4);
+ ENCODEITERA(5);
+ ENCODEITERA(6);
+ ENCODEITERA(7);
+ goto enditer;
+ ENCODEITERB(0);
+ ENCODEITERB(1);
+ ENCODEITERB(2);
+ ENCODEITERB(3);
+ ENCODEITERB(4);
+ ENCODEITERB(5);
+ ENCODEITERB(6);
+ ENCODEITERB(7);
+ enditer:
+ numbit += 8;
+ while (numbit >= 8) {
+ *wp++ = bitbuf;
+ bitbuf >>= 8;
+ numbit -= 8;
+ }
}
+ bitbuf |= 0x7e7e << numbit;
+ numbit += 16;
+ while (numbit >= 8) {
+ *wp++ = bitbuf;
+ bitbuf >>= 8;
+ numbit -= 8;
+ }
+ bc->hdlctx.bufptr = bc->hdlctx.buf;
+ bc->hdlctx.bufcnt = wp - bc->hdlctx.buf;
+ dev_kfree_skb(skb);
+ bc->stats.tx_packets++;
}
/* ---------------------------------------------------------------------- */
@@ -944,6 +934,8 @@ static void epp_bh(struct net_device *dev)
bc->debug_vals.demod_cycles = time3 - time2;
#endif /* BAYCOM_DEBUG */
queue_task(&bc->run_bh, &tq_timer);
+ if (!bc->skb)
+ netif_wake_queue(dev);
return;
epptimeout:
printk(KERN_ERR "%s: EPP timeout!\n", bc_drvname);
@@ -960,8 +952,20 @@ static int baycom_send_packet(struct sk_buff *skb, struct net_device *dev)
baycom_paranoia_check(dev, "baycom_send_packet", 0);
bc = (struct baycom_state *)dev->priv;
- skb_queue_tail(&bc->send_queue, skb);
- dev->trans_start = jiffies;
+ if (skb->data[0] != 0) {
+ do_kiss_params(bc, skb->data, skb->len);
+ dev_kfree_skb(skb);
+ return 0;
+ }
+ if (bc->skb)
+ return -1;
+ /* strip KISS byte */
+ if (skb->len >= HDLCDRV_MAXFLEN+1 || skb->len < 3) {
+ dev_kfree_skb(skb);
+ return 0;
+ }
+ netif_stop_queue(dev);
+ bc->skb = skb;
return 0;
}
@@ -1030,8 +1034,6 @@ static int epp_open(struct net_device *dev)
baycom_paranoia_check(dev, "epp_open", -ENXIO);
bc = (struct baycom_state *)dev->priv;
- if (dev->start)
- return 0;
pp = parport_enumerate();
while (pp && pp->base != dev->base_addr)
pp = pp->next;
@@ -1122,11 +1124,9 @@ static int epp_open(struct net_device *dev)
bc->hdlctx.bufcnt = 0;
bc->hdlctx.slotcnt = bc->ch_params.slottime;
bc->hdlctx.calibrate = 0;
- dev->start = 1;
- dev->tbusy = 0;
- dev->interrupt = 0;
/* start the bottom half stuff */
queue_task(&bc->run_bh, &tq_timer);
+ netif_start_queue(dev);
MOD_INC_USE_COUNT;
return 0;
@@ -1144,17 +1144,12 @@ static int epp_close(struct net_device *dev)
{
struct baycom_state *bc;
struct parport *pp;
- struct sk_buff *skb;
unsigned char tmp[1];
baycom_paranoia_check(dev, "epp_close", -EINVAL);
- if (!dev->start)
- return 0;
bc = (struct baycom_state *)dev->priv;
pp = bc->pdev->port;
bc->bh_running = 0;
- dev->start = 0;
- dev->tbusy = 1;
run_task_queue(&tq_timer); /* dequeue bottom half */
bc->stat = EPP_DCDBIT;
tmp[0] = 0;
@@ -1162,9 +1157,9 @@ static int epp_close(struct net_device *dev)
parport_write_control(pp, 0); /* reset the adapter */
parport_release(bc->pdev);
parport_unregister_device(bc->pdev);
- /* Free any buffers left in the hardware transmit queue */
- while ((skb = skb_dequeue(&bc->send_queue)))
- dev_kfree_skb(skb);
+ if (bc->skb)
+ dev_kfree_skb(bc->skb);
+ bc->skb = NULL;
printk(KERN_INFO "%s: close epp at iobase 0x%lx irq %u\n",
bc_drvname, dev->base_addr, dev->irq);
MOD_DEC_USE_COUNT;
@@ -1280,7 +1275,7 @@ static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
break;
case HDLCDRVCTL_SETMODEMPAR:
- if ((!suser()) || dev->start)
+ if ((!suser()) || netif_running(dev))
return -EACCES;
dev->base_addr = hi.data.mp.iobase;
dev->irq = /*hi.data.mp.irq*/0;
@@ -1319,7 +1314,7 @@ static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
break;
case HDLCDRVCTL_SETMODE:
- if (!suser() || dev->start)
+ if (!suser() || netif_running(dev))
return -EACCES;
hi.data.modename[sizeof(hi.data.modename)-1] = '\0';
return baycom_setmode(bc, hi.data.modename);
@@ -1385,7 +1380,7 @@ static int baycom_probe(struct net_device *dev)
/* Fill in the fields of the device structure */
dev_init_buffers(dev);
- skb_queue_head_init(&bc->send_queue);
+ bc->skb = NULL;
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
dev->hard_header = ax25_encapsulate;
@@ -1402,6 +1397,7 @@ static int baycom_probe(struct net_device *dev)
dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */
memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
memcpy(dev->dev_addr, ax25_nocall, AX25_ADDR_LEN);
+ dev->tx_queue_len = 16;
/* New style flags */
dev->flags = 0;
@@ -1461,8 +1457,6 @@ static int __init init_baycomepp(void)
dev->name = bc->ifname;
dev->if_port = 0;
dev->init = baycom_probe;
- dev->start = 0;
- dev->tbusy = 1;
dev->base_addr = iobase[i];
dev->irq = 0;
dev->dma = 0;
diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c
index 0bd2a1725..b68063b07 100644
--- a/drivers/net/hamradio/baycom_par.c
+++ b/drivers/net/hamradio/baycom_par.c
@@ -3,7 +3,7 @@
/*
* baycom_par.c -- baycom par96 and picpar radio modem driver.
*
- * Copyright (C) 1996-1999 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ * Copyright (C) 1996-2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
*
* 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
@@ -53,14 +53,16 @@
*
*
* History:
- * 0.1 26.06.96 Adapted from baycom.c and made network driver interface
- * 18.10.96 Changed to new user space access routines (copy_{to,from}_user)
- * 0.3 26.04.97 init code/data tagged
- * 0.4 08.07.97 alternative ser12 decoding algorithm (uses delta CTS ints)
- * 0.5 11.11.97 split into separate files for ser12/par96
- * 0.6 03.08.99 adapt to Linus' new __setup/__initcall
- * removed some pre-2.2 kernel compatibility cruft
- * 0.7 10.08.99 Check if parport can do SPP and is safe to access during interrupt contexts
+ * 0.1 26.06.1996 Adapted from baycom.c and made network driver interface
+ * 18.10.1996 Changed to new user space access routines (copy_{to,from}_user)
+ * 0.3 26.04.1997 init code/data tagged
+ * 0.4 08.07.1997 alternative ser12 decoding algorithm (uses delta CTS ints)
+ * 0.5 11.11.1997 split into separate files for ser12/par96
+ * 0.6 03.08.1999 adapt to Linus' new __setup/__initcall
+ * removed some pre-2.2 kernel compatibility cruft
+ * 0.7 10.08.1999 Check if parport can do SPP and is safe to access during interrupt contexts
+ * 0.8 12.02.2000 adapted to softnet driver interface
+ * removed direct parport access, uses parport driver methods
*/
/*****************************************************************************/
@@ -77,7 +79,6 @@
#include <linux/string.h>
#include <asm/system.h>
#include <asm/bitops.h>
-#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/init.h>
#include <linux/delay.h>
@@ -99,8 +100,8 @@
/* --------------------------------------------------------------------- */
static const char bc_drvname[] = "baycom_par";
-static const char bc_drvinfo[] = KERN_INFO "baycom_par: (C) 1996-1999 Thomas Sailer, HB9JNX/AE4WA\n"
-KERN_INFO "baycom_par: version 0.6 compiled " __TIME__ " " __DATE__ "\n";
+static const char bc_drvinfo[] = KERN_INFO "baycom_par: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
+KERN_INFO "baycom_par: version 0.8 compiled " __TIME__ " " __DATE__ "\n";
/* --------------------------------------------------------------------- */
@@ -110,13 +111,6 @@ static struct net_device baycom_device[NR_PORTS];
/* --------------------------------------------------------------------- */
-#define SER12_EXTENT 8
-
-#define LPT_DATA(dev) ((dev)->base_addr+0)
-#define LPT_STATUS(dev) ((dev)->base_addr+1)
-#define LPT_CONTROL(dev) ((dev)->base_addr+2)
-#define LPT_IRQ_ENABLE 0x10
-
#define PAR96_BURSTBITS 16
#define PAR96_BURST 4
#define PAR96_PTT 2
@@ -207,6 +201,7 @@ static __inline__ void par96_tx(struct net_device *dev, struct baycom_state *bc)
{
int i;
unsigned int data = hdlcdrv_getbits(&bc->hdrv);
+ struct parport *pp = bc->pdev->port;
for(i = 0; i < PAR96_BURSTBITS; i++, data >>= 1) {
unsigned char val = PAR97_POWER;
@@ -219,8 +214,8 @@ static __inline__ void par96_tx(struct net_device *dev, struct baycom_state *bc)
(PAR96_SCRAM_TAPN << 1);
if (bc->modem.par96.scram & (PAR96_SCRAM_TAP1 << 2))
val |= PAR96_TXBIT;
- outb(val, LPT_DATA(dev));
- outb(val | PAR96_BURST, LPT_DATA(dev));
+ pp->ops->write_data(pp, val);
+ pp->ops->write_data(pp, val | PAR96_BURST);
}
}
@@ -230,24 +225,25 @@ static __inline__ void par96_rx(struct net_device *dev, struct baycom_state *bc)
{
int i;
unsigned int data, mask, mask2, descx;
+ struct parport *pp = bc->pdev->port;
/*
* do receiver; differential decode and descramble on the fly
*/
for(data = i = 0; i < PAR96_BURSTBITS; i++) {
bc->modem.par96.descram = (bc->modem.par96.descram << 1);
- if (inb(LPT_STATUS(dev)) & PAR96_RXBIT)
+ if (pp->ops->read_status(pp) & PAR96_RXBIT)
bc->modem.par96.descram |= 1;
descx = bc->modem.par96.descram ^
(bc->modem.par96.descram >> 1);
/* now the diff decoded data is inverted in descram */
- outb(PAR97_POWER | PAR96_PTT, LPT_DATA(dev));
+ pp->ops->write_data(pp, PAR97_POWER | PAR96_PTT);
descx ^= ((descx >> PAR96_DESCRAM_TAPSH1) ^
(descx >> PAR96_DESCRAM_TAPSH2));
data >>= 1;
if (!(descx & 1))
data |= 0x8000;
- outb(PAR97_POWER | PAR96_PTT | PAR96_BURST, LPT_DATA(dev));
+ pp->ops->write_data(pp, PAR97_POWER | PAR96_PTT | PAR96_BURST);
}
hdlcdrv_putbits(&bc->hdrv, data);
/*
@@ -272,7 +268,7 @@ static __inline__ void par96_rx(struct net_device *dev, struct baycom_state *bc)
bc->modem.par96.dcd_count -= 2;
hdlcdrv_setdcd(&bc->hdrv, bc->modem.par96.dcd_count > 0);
} else {
- hdlcdrv_setdcd(&bc->hdrv, !!(inb(LPT_STATUS(dev)) & PAR96_DCD));
+ hdlcdrv_setdcd(&bc->hdrv, !!(pp->ops->read_status(pp) & PAR96_DCD));
}
}
@@ -353,13 +349,12 @@ static int par96_open(struct net_device *dev)
parport_unregister_device(bc->pdev);
return -EBUSY;
}
+ pp = bc->pdev->port;
dev->irq = pp->irq;
- /* bc->pdev->port->ops->change_mode(bc->pdev->port, PARPORT_MODE_PCSPP); not yet implemented */
+ pp->ops->data_forward(pp);
bc->hdrv.par.bitrate = 9600;
- /* switch off PTT */
- outb(PAR96_PTT | PAR97_POWER, LPT_DATA(dev));
- /*bc->pdev->port->ops->enable_irq(bc->pdev->port); not yet implemented */
- outb(LPT_IRQ_ENABLE, LPT_CONTROL(dev));
+ pp->ops->write_data(pp, PAR96_PTT | PAR97_POWER); /* switch off PTT */
+ pp->ops->enable_irq(pp);
printk(KERN_INFO "%s: par96 at iobase 0x%lx irq %u options 0x%x\n",
bc_drvname, dev->base_addr, dev->irq, bc->options);
MOD_INC_USE_COUNT;
@@ -371,14 +366,15 @@ static int par96_open(struct net_device *dev)
static int par96_close(struct net_device *dev)
{
struct baycom_state *bc = (struct baycom_state *)dev->priv;
+ struct parport *pp;
if (!dev || !bc)
return -EINVAL;
+ pp = bc->pdev->port;
/* disable interrupt */
- outb(0, LPT_CONTROL(dev));
- /*bc->pdev->port->ops->disable_irq(bc->pdev->port); not yet implemented */
+ pp->ops->disable_irq(pp);
/* switch off PTT */
- outb(PAR96_PTT | PAR97_POWER, LPT_DATA(dev));
+ pp->ops->write_data(pp, PAR96_PTT | PAR97_POWER);
parport_release(bc->pdev);
parport_unregister_device(bc->pdev);
printk(KERN_INFO "%s: close par96 at iobase 0x%lx irq %u\n",
@@ -449,7 +445,7 @@ static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
return 0;
case HDLCDRVCTL_SETMODE:
- if (dev->start || !suser())
+ if (netif_running(dev) || !suser())
return -EACCES;
hi->data.modename[sizeof(hi->data.modename)-1] = '\0';
return baycom_setmode(bc, hi->data.modename);
diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c
index 9c6e69cf6..cdcab2621 100644
--- a/drivers/net/hamradio/baycom_ser_fdx.c
+++ b/drivers/net/hamradio/baycom_ser_fdx.c
@@ -3,7 +3,7 @@
/*
* baycom_ser_fdx.c -- baycom ser12 fullduplex radio modem driver.
*
- * Copyright (C) 1996-1999 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ * Copyright (C) 1996-2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
*
* 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
@@ -55,16 +55,17 @@
*
*
* History:
- * 0.1 26.06.96 Adapted from baycom.c and made network driver interface
- * 18.10.96 Changed to new user space access routines (copy_{to,from}_user)
- * 0.3 26.04.97 init code/data tagged
- * 0.4 08.07.97 alternative ser12 decoding algorithm (uses delta CTS ints)
- * 0.5 11.11.97 ser12/par96 split into separate files
- * 0.6 24.01.98 Thorsten Kranzkowski, dl8bcu and Thomas Sailer:
- * reduced interrupt load in transmit case
- * reworked receiver
- * 0.7 03.08.99 adapt to Linus' new __setup/__initcall
- * 0.8 10.08.99 use module_init/module_exit
+ * 0.1 26.06.1996 Adapted from baycom.c and made network driver interface
+ * 18.10.1996 Changed to new user space access routines (copy_{to,from}_user)
+ * 0.3 26.04.1997 init code/data tagged
+ * 0.4 08.07.1997 alternative ser12 decoding algorithm (uses delta CTS ints)
+ * 0.5 11.11.1997 ser12/par96 split into separate files
+ * 0.6 24.01.1998 Thorsten Kranzkowski, dl8bcu and Thomas Sailer:
+ * reduced interrupt load in transmit case
+ * reworked receiver
+ * 0.7 03.08.1999 adapt to Linus' new __setup/__initcall
+ * 0.8 10.08.1999 use module_init/module_exit
+ * 0.9 12.02.2000 adapted to softnet driver interface
*/
/*****************************************************************************/
@@ -86,8 +87,8 @@
/* --------------------------------------------------------------------- */
static const char bc_drvname[] = "baycom_ser_fdx";
-static const char bc_drvinfo[] = KERN_INFO "baycom_ser_fdx: (C) 1996-1999 Thomas Sailer, HB9JNX/AE4WA\n"
-KERN_INFO "baycom_ser_fdx: version 0.7 compiled " __TIME__ " " __DATE__ "\n";
+static const char bc_drvinfo[] = KERN_INFO "baycom_ser_fdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
+KERN_INFO "baycom_ser_fdx: version 0.9 compiled " __TIME__ " " __DATE__ "\n";
/* --------------------------------------------------------------------- */
@@ -554,7 +555,7 @@ static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
return 0;
case HDLCDRVCTL_SETMODE:
- if (dev->start || !suser())
+ if (netif_running(dev) || !suser())
return -EACCES;
hi->data.modename[sizeof(hi->data.modename)-1] = '\0';
return baycom_setmode(bc, hi->data.modename);
diff --git a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c
index c44395f84..64b27286c 100644
--- a/drivers/net/hamradio/baycom_ser_hdx.c
+++ b/drivers/net/hamradio/baycom_ser_hdx.c
@@ -3,7 +3,7 @@
/*
* baycom_ser_hdx.c -- baycom ser12 halfduplex radio modem driver.
*
- * Copyright (C) 1996-1999 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ * Copyright (C) 1996-2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
*
* 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
@@ -47,14 +47,15 @@
*
*
* History:
- * 0.1 26.06.96 Adapted from baycom.c and made network driver interface
- * 18.10.96 Changed to new user space access routines (copy_{to,from}_user)
- * 0.3 26.04.97 init code/data tagged
- * 0.4 08.07.97 alternative ser12 decoding algorithm (uses delta CTS ints)
- * 0.5 11.11.97 ser12/par96 split into separate files
- * 0.6 14.04.98 cleanups
- * 0.7 03.08.99 adapt to Linus' new __setup/__initcall
- * 0.8 10.08.99 use module_init/module_exit
+ * 0.1 26.06.1996 Adapted from baycom.c and made network driver interface
+ * 18.10.1996 Changed to new user space access routines (copy_{to,from}_user)
+ * 0.3 26.04.1997 init code/data tagged
+ * 0.4 08.07.1997 alternative ser12 decoding algorithm (uses delta CTS ints)
+ * 0.5 11.11.1997 ser12/par96 split into separate files
+ * 0.6 14.04.1998 cleanups
+ * 0.7 03.08.1999 adapt to Linus' new __setup/__initcall
+ * 0.8 10.08.1999 use module_init/module_exit
+ * 0.9 12.02.2000 adapted to softnet driver interface
*/
/*****************************************************************************/
@@ -76,8 +77,8 @@
/* --------------------------------------------------------------------- */
static const char bc_drvname[] = "baycom_ser_hdx";
-static const char bc_drvinfo[] = KERN_INFO "baycom_ser_hdx: (C) 1996-1999 Thomas Sailer, HB9JNX/AE4WA\n"
-KERN_INFO "baycom_ser_hdx: version 0.7 compiled " __TIME__ " " __DATE__ "\n";
+static const char bc_drvinfo[] = KERN_INFO "baycom_ser_hdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
+KERN_INFO "baycom_ser_hdx: version 0.9 compiled " __TIME__ " " __DATE__ "\n";
/* --------------------------------------------------------------------- */
@@ -597,7 +598,7 @@ static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
return 0;
case HDLCDRVCTL_SETMODE:
- if (dev->start || !suser())
+ if (netif_running(dev) || !suser())
return -EACCES;
hi->data.modename[sizeof(hi->data.modename)-1] = '\0';
return baycom_setmode(bc, hi->data.modename);
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 55ed5254e..0cc9aa7c1 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -222,7 +222,7 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
dev = bpq_get_ax25_dev(dev);
- if (dev == NULL || dev->start == 0) {
+ if (dev == NULL || !netif_running(dev)) {
kfree_skb(skb);
return 0;
}
@@ -275,7 +275,7 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev)
* Just to be *really* sure not to send anything if the interface
* is down, the ethernet device may have gone.
*/
- if (!dev->start) {
+ if (!netif_running(dev)) {
bpq_check_devices(dev);
kfree_skb(skb);
return -ENODEV;
@@ -324,7 +324,7 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev)
bpq->stats.tx_bytes+=skb->len;
dev_queue_xmit(skb);
-
+ netif_wake_queue(dev);
return 0;
}
@@ -407,22 +407,17 @@ static int bpq_open(struct net_device *dev)
{
if (bpq_check_devices(dev))
return -ENODEV; /* oops, it's gone */
-
- dev->tbusy = 0;
- dev->start = 1;
-
+
MOD_INC_USE_COUNT;
+ netif_start_queue(dev);
return 0;
}
static int bpq_close(struct net_device *dev)
{
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
MOD_DEC_USE_COUNT;
-
return 0;
}
@@ -621,7 +616,7 @@ static int bpq_device_event(struct notifier_block *this,unsigned long event, voi
* Initialize driver. To be called from af_ax25 if not compiled as a
* module
*/
-int __init bpq_init(void)
+static int __init bpq_init_driver(void)
{
struct net_device *dev;
@@ -630,7 +625,7 @@ int __init bpq_init(void)
register_netdevice_notifier(&bpq_dev_notifier);
- printk(KERN_INFO "AX.25 ethernet driver version 0.01\n");
+ printk(KERN_INFO "AX.25: bpqether driver version 0.01\n");
proc_net_create ("bpqether", 0, bpq_get_info);
@@ -643,22 +638,10 @@ int __init bpq_init(void)
}
}
read_unlock_bh(&dev_base_lock);
-out:
return 0;
}
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-MODULE_AUTHOR("Joerg Reuter DL1BKE <jreuter@lykos.oche.de>");
-MODULE_DESCRIPTION("Transmit and receive AX.25 packets over Ethernet");
-
-int init_module(void)
-{
- return bpq_init();
-}
-
-void cleanup_module(void)
+static void __exit bpq_cleanup_driver(void)
{
struct bpqdev *bpq;
@@ -671,4 +654,8 @@ void cleanup_module(void)
for (bpq = bpq_devices; bpq != NULL; bpq = bpq->next)
unregister_netdev(&bpq->axdev);
}
-#endif
+
+MODULE_AUTHOR("Joerg Reuter DL1BKE <jreuter@poboxes.com>");
+MODULE_DESCRIPTION("Transmit and receive AX.25 packets over Ethernet");
+module_init(bpq_init_driver);
+module_exit(bpq_cleanup_driver);
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index afba5cb14..3e7cd8e44 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -643,7 +643,6 @@ static int scc_open(struct net_device *dev)
}
/* Initialize local variables */
- dev->tbusy = 0;
priv->rx_ptr = 0;
priv->rx_over = 0;
priv->rx_head = priv->rx_tail = priv->rx_count = 0;
@@ -732,7 +731,7 @@ static int scc_open(struct net_device *dev)
/* Configure PI2 DMA */
if (info->type <= TYPE_PI2) outb_p(1, io + PI_DREQ_MASK);
- dev->start = 1;
+ netif_start_queue(dev);
info->open++;
MOD_INC_USE_COUNT;
@@ -747,9 +746,8 @@ static int scc_close(struct net_device *dev)
int io = dev->base_addr;
int cmd = priv->cmd;
- dev->start = 0;
+ netif_stop_queue(dev);
info->open--;
- MOD_DEC_USE_COUNT;
if (info->type == TYPE_TWIN)
/* Drop DTR */
@@ -768,6 +766,7 @@ static int scc_close(struct net_device *dev)
if (info->type <= TYPE_PI2) outb_p(0, io + PI_DREQ_MASK);
free_irq(dev->irq, info);
}
+ MOD_DEC_USE_COUNT;
return 0;
}
@@ -779,16 +778,16 @@ static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
switch (cmd) {
case SIOCGSCCPARAM:
- rc = verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(struct scc_param));
- if (rc) return rc;
- copy_to_user(ifr->ifr_data, &priv->param, sizeof(struct scc_param));
+ if(copy_to_user(ifr->ifr_data, &priv->param, sizeof(struct scc_param)))
+ return -EFAULT;
return 0;
case SIOCSSCCPARAM:
- if (!suser()) return -EPERM;
- rc = verify_area(VERIFY_READ, ifr->ifr_data, sizeof(struct scc_param));
- if (rc) return rc;
- if (dev->start) return -EAGAIN;
- copy_from_user(&priv->param, ifr->ifr_data, sizeof(struct scc_param));
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (netif_running(dev))
+ return -EAGAIN;
+ if(copy_from_user(&priv->param, ifr->ifr_data, sizeof(struct scc_param)))
+ return -EFAULT;
dev->dma = priv->param.dma;
return 0;
default:
@@ -806,18 +805,8 @@ static int scc_send_packet(struct sk_buff *skb, struct net_device *dev)
int i;
/* Block a timer-based transmit from overlapping */
- if (test_and_set_bit(0, (void *) &priv->tx_sem) != 0) {
- atomic_inc((void *) &priv->stats.tx_dropped);
- dev_kfree_skb(skb);
- return 0;
- }
-
- /* Return with an error if we cannot accept more data */
- if (dev->tbusy) {
- priv->tx_sem = 0;
- return -1;
- }
-
+ netif_stop_queue(dev);
+
/* Transfer data to DMA buffer */
i = priv->tx_head;
memcpy(priv->tx_buf[i], skb->data+1, skb->len-1);
@@ -829,7 +818,8 @@ static int scc_send_packet(struct sk_buff *skb, struct net_device *dev)
/* Set the busy flag if we just filled up the last buffer */
priv->tx_head = (i + 1) % NUM_TX_BUF;
priv->tx_count++;
- if (priv->tx_count == NUM_TX_BUF) dev->tbusy = 1;
+ if (priv->tx_count != NUM_TX_BUF)
+ netif_wake_queue(dev);
/* Set new TX state */
if (priv->tx_state == TX_IDLE) {
@@ -1139,7 +1129,6 @@ static void es_isr(struct net_device *dev)
/* Remove frame from FIFO */
priv->tx_tail = (i + 1) % NUM_TX_BUF;
priv->tx_count--;
- dev->tbusy = 0;
/* Check if another frame is available and we are allowed to transmit */
if (priv->tx_count && (jiffies - priv->tx_start) < priv->param.txtime) {
if (dev->dma) {
@@ -1171,7 +1160,7 @@ static void es_isr(struct net_device *dev)
priv->stats.tx_packets++;
}
/* Inform upper layers */
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
}
/* DCD transition */
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index 67a835b02..a3560c207 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -3,7 +3,7 @@
/*
* hdlcdrv.c -- HDLC packet radio network driver.
*
- * Copyright (C) 1996-1999 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ * Copyright (C) 1996-2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
*
* 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
@@ -27,16 +27,17 @@
* Written 1993-94 by Donald Becker.
*
* History:
- * 0.1 21.09.96 Started
- * 18.10.96 Changed to new user space access routines
- * (copy_{to,from}_user)
- * 0.2 21.11.96 various small changes
- * 0.3 03.03.97 fixed (hopefully) IP not working with ax.25 as a module
- * 0.4 16.04.97 init code/data tagged
- * 0.5 30.07.97 made HDLC buffers bigger (solves a problem with the
- * soundmodem driver)
- * 0.6 05.04.98 add spinlocks
- * 0.7 03.08.99 removed some old compatibility cruft
+ * 0.1 21.09.1996 Started
+ * 18.10.1996 Changed to new user space access routines
+ * (copy_{to,from}_user)
+ * 0.2 21.11.1996 various small changes
+ * 0.3 03.03.1997 fixed (hopefully) IP not working with ax.25 as a module
+ * 0.4 16.04.1997 init code/data tagged
+ * 0.5 30.07.1997 made HDLC buffers bigger (solves a problem with the
+ * soundmodem driver)
+ * 0.6 05.04.1998 add spinlocks
+ * 0.7 03.08.1999 removed some old compatibility cruft
+ * 0.8 12.02.2000 adapted to softnet driver interface
*/
/*****************************************************************************/
@@ -366,29 +367,25 @@ void hdlcdrv_transmitter(struct net_device *dev, struct hdlcdrv_state *s)
clear_bit(0, &s->hdlctx.in_hdlc_tx);
return;
}
- if (!(skb = skb_dequeue(&s->send_queue))) {
- int flgs = tenms_to_2flags
- (s, s->ch_params.tx_tail);
+ if (!(skb = s->skb)) {
+ int flgs = tenms_to_2flags(s, s->ch_params.tx_tail);
if (flgs < 2)
flgs = 2;
s->hdlctx.tx_state = 1;
s->hdlctx.numflags = flgs;
break;
}
- if (skb->data[0] != 0) {
- do_kiss_params(s, skb->data, skb->len);
- dev_kfree_skb(skb);
- break;
- }
+ s->skb = NULL;
+ netif_wake_queue(dev);
pkt_len = skb->len-1; /* strip KISS byte */
if (pkt_len >= HDLCDRV_MAXFLEN || pkt_len < 2) {
s->hdlctx.tx_state = 0;
s->hdlctx.numflags = 1;
- dev_kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
break;
}
memcpy(s->hdlctx.buffer, skb->data+1, pkt_len);
- dev_kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
s->hdlctx.bp = s->hdlctx.buffer;
append_crc_ccitt(s->hdlctx.buffer, pkt_len);
s->hdlctx.len = pkt_len+2; /* the appended CRC */
@@ -454,8 +451,7 @@ static inline unsigned short random_num(void)
void hdlcdrv_arbitrate(struct net_device *dev, struct hdlcdrv_state *s)
{
- if (!s || s->magic != HDLCDRV_MAGIC || s->hdlctx.ptt ||
- skb_queue_empty(&s->send_queue))
+ if (!s || s->magic != HDLCDRV_MAGIC || s->hdlctx.ptt || !s->skb)
return;
if (s->ch_params.fulldup) {
start_tx(dev, s);
@@ -499,8 +495,15 @@ static int hdlcdrv_send_packet(struct sk_buff *skb, struct net_device *dev)
if (hdlcdrv_paranoia_check(dev, "hdlcdrv_send_packet"))
return 0;
sm = (struct hdlcdrv_state *)dev->priv;
- skb_queue_tail(&sm->send_queue, skb);
- dev->trans_start = jiffies;
+ if (skb->data[0] != 0) {
+ do_kiss_params(sm, skb->data, skb->len);
+ dev_kfree_skb(skb);
+ return 0;
+ }
+ if (sm->skb)
+ return -1;
+ netif_stop_queue(dev);
+ sm->skb = skb;
return 0;
}
@@ -550,12 +553,9 @@ static int hdlcdrv_open(struct net_device *dev)
return -EINVAL;
s = (struct hdlcdrv_state *)dev->priv;
- if (dev->start)
- return 0;
if (!s->ops || !s->ops->open)
return -ENODEV;
- dev->start = 1;
/*
* initialise some variables
*/
@@ -573,14 +573,9 @@ static int hdlcdrv_open(struct net_device *dev)
s->hdlctx.calibrate = 0;
i = s->ops->open(dev);
- if (i) {
- dev->start = 0;
+ if (i)
return i;
- }
-
- dev->tbusy = 0;
- dev->interrupt = 0;
-
+ netif_start_queue(dev);
return 0;
}
@@ -592,23 +587,17 @@ static int hdlcdrv_open(struct net_device *dev)
static int hdlcdrv_close(struct net_device *dev)
{
struct hdlcdrv_state *s;
- struct sk_buff *skb;
int i = 0;
if (hdlcdrv_paranoia_check(dev, "hdlcdrv_close"))
return -EINVAL;
s = (struct hdlcdrv_state *)dev->priv;
- if (!dev->start)
- return 0;
- dev->start = 0;
- dev->tbusy = 1;
-
if (s->ops && s->ops->close)
i = s->ops->close(dev);
- /* Free any buffers left in the hardware transmit queue */
- while ((skb = skb_dequeue(&s->send_queue)))
- dev_kfree_skb(skb);
+ if (s->skb)
+ dev_kfree_skb(s->skb);
+ s->skb = NULL;
return i;
}
@@ -667,7 +656,7 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
break;
case HDLCDRVCTL_SETMODEMPAR:
- if ((!suser()) || dev->start)
+ if ((!suser()) || netif_running(dev))
return -EACCES;
dev->base_addr = bi.data.mp.iobase;
dev->irq = bi.data.mp.irq;
@@ -801,10 +790,9 @@ static int hdlcdrv_probe(struct net_device *dev)
dev->get_stats = hdlcdrv_get_stats;
/* Fill in the fields of the device structure */
-
dev_init_buffers(dev);
- skb_queue_head_init(&s->send_queue);
+ s->skb = NULL;
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
dev->hard_header = ax25_encapsulate;
@@ -821,6 +809,7 @@ static int hdlcdrv_probe(struct net_device *dev)
dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */
memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
memcpy(dev->dev_addr, ax25_nocall, AX25_ADDR_LEN);
+ dev->tx_queue_len = 16;
/* New style flags */
dev->flags = 0;
@@ -857,8 +846,6 @@ int hdlcdrv_register_hdlcdrv(struct net_device *dev, const struct hdlcdrv_ops *o
dev->name = s->ifname;
dev->if_port = 0;
dev->init = hdlcdrv_probe;
- dev->start = 0;
- dev->tbusy = 1;
dev->base_addr = baseaddr;
dev->irq = irq;
dev->dma = dma;
@@ -884,7 +871,7 @@ int hdlcdrv_unregister_hdlcdrv(struct net_device *dev)
return -EINVAL;
if (s->magic != HDLCDRV_MAGIC)
return -EINVAL;
- if (dev->start && s->ops->close)
+ if (s->ops->close)
s->ops->close(dev);
unregister_netdev(dev);
kfree(s);
@@ -911,8 +898,8 @@ MODULE_DESCRIPTION("Packet Radio network interface HDLC encoder/decoder");
int __init init_module(void)
{
- printk(KERN_INFO "hdlcdrv: (C) 1996 Thomas Sailer HB9JNX/AE4WA\n");
- printk(KERN_INFO "hdlcdrv: version 0.7 compiled " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "hdlcdrv: (C) 1996-2000 Thomas Sailer HB9JNX/AE4WA\n");
+ printk(KERN_INFO "hdlcdrv: version 0.8 compiled " __TIME__ " " __DATE__ "\n");
return 0;
}
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index 4de421874..09bb422f1 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1,7 +1,7 @@
#define RCS_ID "$Id: scc.c,v 1.75 1998/11/04 15:15:01 jreuter Exp jreuter $"
#define VERSION "3.0"
-#define BANNER "Z8530 SCC driver version "VERSION".dl1bke (experimental) by DL1BKE\n"
+#define BANNER "AX.25: Z8530 SCC driver version "VERSION".dl1bke\n"
/*
* Please use z8530drv-utils-3.0 with this version.
@@ -19,7 +19,7 @@
********************************************************************
- Copyright (c) 1993, 1998 Joerg Reuter DL1BKE
+ Copyright (c) 1993, 2000 Joerg Reuter DL1BKE
portions (c) 1993 Guido ten Dolle PE1NNZ
@@ -104,6 +104,9 @@
flags that aren't... Restarting the DPLL does not help
either, it resynchronizes too slow and the first received
frame gets lost.
+ 2000-02-13 Fixed for new network driver interface changes, still
+ does TX timeouts itself since it uses its own queue
+ scheme.
Thanks to all who contributed to this driver with ideas and bug
reports!
@@ -236,9 +239,6 @@ static unsigned char Driver_Initialized = 0;
static int Nchips = 0;
static io_port Vector_Latch = 0;
-MODULE_AUTHOR("Joerg Reuter <jreuter@poboxes.com>");
-MODULE_DESCRIPTION("Network Device Driver for Z8530 based HDLC cards for Amateur Packet Radio");
-MODULE_SUPPORTED_DEVICE("scc");
/* ******************************************************************** */
/* * Port Access Functions * */
@@ -314,17 +314,6 @@ static inline void scc_sti(int irq)
/* * Some useful macros * */
/* ******************************************************************** */
-
-static inline void scc_lock_dev(struct scc_channel *scc)
-{
- scc->dev->tbusy = 1;
-}
-
-static inline void scc_unlock_dev(struct scc_channel *scc)
-{
- scc->dev->tbusy = 0;
-}
-
static inline void scc_discard_buffers(struct scc_channel *scc)
{
unsigned long flags;
@@ -382,7 +371,7 @@ static inline void flush_rx_FIFO(struct scc_channel *scc)
if(scc->rx_buff != NULL) /* did we receive something? */
{
scc->stat.rxerrs++; /* then count it as an error */
- kfree_skb(scc->rx_buff);
+ dev_kfree_skb_irq(scc->rx_buff);
scc->rx_buff = NULL;
}
}
@@ -411,7 +400,7 @@ static inline void scc_txint(struct scc_channel *scc)
{
skb = skb_dequeue(&scc->tx_queue);
scc->tx_buff = skb;
- scc_unlock_dev(scc);
+ netif_wake_queue(scc->dev);
if (skb == NULL)
{
@@ -422,7 +411,7 @@ static inline void scc_txint(struct scc_channel *scc)
if (skb->len == 0) /* Paranoia... */
{
- dev_kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
scc->tx_buff = NULL;
scc_tx_done(scc);
Outb(scc->ctrl, RES_Tx_P);
@@ -448,7 +437,7 @@ static inline void scc_txint(struct scc_channel *scc)
{
Outb(scc->ctrl, RES_Tx_P); /* reset pending int */
cl(scc, R10, ABUNDER); /* send CRC */
- dev_kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
scc->tx_buff = NULL;
scc->stat.tx_state = TXS_NEWFRAME; /* next frame... */
return;
@@ -533,7 +522,7 @@ static inline void scc_exint(struct scc_channel *scc)
if (scc->tx_buff != NULL)
{
- dev_kfree_skb(scc->tx_buff);
+ dev_kfree_skb_irq(scc->tx_buff);
scc->tx_buff = NULL;
}
@@ -583,7 +572,7 @@ static inline void scc_rxint(struct scc_channel *scc)
#ifdef notdef
printk(KERN_DEBUG "z8530drv: oops, scc_rxint() received huge frame...\n");
#endif
- kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
scc->rx_buff = NULL;
Inb(scc->data);
or(scc, R3, ENT_HM);
@@ -613,7 +602,7 @@ static inline void scc_spint(struct scc_channel *scc)
or(scc,R3,ENT_HM); /* enter hunt mode for next flag */
if (skb != NULL)
- kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
scc->rx_buff = NULL;
}
@@ -629,7 +618,7 @@ static inline void scc_spint(struct scc_channel *scc)
scc->rx_buff = NULL;
scc->stat.rxframes++;
} else { /* a bad frame */
- kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
scc->rx_buff = NULL;
scc->stat.rxerrs++;
}
@@ -1112,7 +1101,7 @@ static void scc_tx_done(struct scc_channel *scc)
scc_start_tx_timer(scc, t_tail, scc->kiss.tailtime);
}
- scc_unlock_dev(scc);
+ netif_wake_queue(scc->dev);
}
@@ -1163,7 +1152,7 @@ static void t_dwait(unsigned long channel)
if (skb_queue_len(&scc->tx_queue) == 0) /* nothing to send */
{
scc->stat.tx_state = TXS_IDLE;
- scc_unlock_dev(scc); /* t_maxkeyup locked it. */
+ netif_wake_queue(scc->dev); /* t_maxkeyup locked it. */
return;
}
@@ -1243,7 +1232,7 @@ static void t_tail(unsigned long channel)
}
scc->stat.tx_state = TXS_IDLE;
- scc_unlock_dev(scc);
+ netif_wake_queue(scc->dev);
}
@@ -1257,14 +1246,13 @@ static void t_busy(unsigned long channel)
struct scc_channel *scc = (struct scc_channel *) channel;
del_timer(&scc->tx_t);
- scc_lock_dev(scc);
+ netif_stop_queue(scc->dev); /* don't pile on the wabbit! */
scc_discard_buffers(scc);
-
scc->stat.txerrs++;
scc->stat.tx_state = TXS_IDLE;
-
- scc_unlock_dev(scc);
+
+ netif_wake_queue(scc->dev);
}
/* MAXKEYUP timeout
@@ -1285,7 +1273,7 @@ static void t_maxkeyup(unsigned long channel)
* accept new data.
*/
- scc_lock_dev(scc);
+ netif_stop_queue(scc->dev);
scc_discard_buffers(scc);
del_timer(&scc->tx_t);
@@ -1460,8 +1448,7 @@ static void scc_stop_calibrate(unsigned long channel)
Outb(scc->ctrl,RES_EXT_INT); /* reset ext/status interrupts */
Outb(scc->ctrl,RES_EXT_INT);
- scc_unlock_dev(scc);
-
+ netif_wake_queue(scc->dev);
restore_flags(flags);
}
@@ -1474,7 +1461,7 @@ scc_start_calibrate(struct scc_channel *scc, int duration, unsigned char pattern
save_flags(flags);
cli();
- scc_lock_dev(scc);
+ netif_stop_queue(scc->dev);
scc_discard_buffers(scc);
del_timer(&scc->tx_wdog);
@@ -1497,7 +1484,6 @@ scc_start_calibrate(struct scc_channel *scc, int duration, unsigned char pattern
Outb(scc->ctrl,RES_EXT_INT);
scc_key_trx(scc, TX_ON);
-
restore_flags(flags);
}
@@ -1583,7 +1569,9 @@ static int scc_net_setup(struct scc_channel *scc, unsigned char *name, int addev
dev = scc->dev;
memset(dev, 0, sizeof(struct net_device));
- buf = (unsigned char *) kmalloc(10, GFP_KERNEL);
+ if ((buf = (unsigned char *) kmalloc(10, GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+
strcpy(buf, name);
dev->priv = (void *) scc;
@@ -1627,6 +1615,7 @@ static int scc_net_init(struct net_device *dev)
dev->set_mac_address = scc_net_set_mac_address;
dev->get_stats = scc_net_get_stats;
dev->do_ioctl = scc_net_ioctl;
+ dev->tx_timeout = NULL;
memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
memcpy(dev->dev_addr, ax25_nocall, AX25_ADDR_LEN);
@@ -1647,22 +1636,17 @@ static int scc_net_open(struct net_device *dev)
{
struct scc_channel *scc = (struct scc_channel *) dev->priv;
- if (scc == NULL || scc->magic != SCC_MAGIC)
- return -ENODEV;
-
if (!scc->init)
return -EINVAL;
MOD_INC_USE_COUNT;
-
+
scc->tx_buff = NULL;
skb_queue_head_init(&scc->tx_queue);
init_channel(scc);
- dev->tbusy = 0;
- dev->start = 1;
-
+ netif_start_queue(dev);
return 0;
}
@@ -1673,10 +1657,7 @@ static int scc_net_close(struct net_device *dev)
struct scc_channel *scc = (struct scc_channel *) dev->priv;
unsigned long flags;
- if (scc == NULL || scc->magic != SCC_MAGIC)
- return -ENODEV;
-
- MOD_DEC_USE_COUNT;
+ netif_stop_queue(dev);
save_flags(flags);
cli();
@@ -1692,9 +1673,7 @@ static int scc_net_close(struct net_device *dev)
scc_discard_buffers(scc);
- dev->tbusy = 1;
- dev->start = 0;
-
+ MOD_DEC_USE_COUNT;
return 0;
}
@@ -1704,7 +1683,7 @@ static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb)
{
if (skb->len == 0)
{
- kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
return;
}
@@ -1726,12 +1705,6 @@ static int scc_net_tx(struct sk_buff *skb, struct net_device *dev)
struct scc_channel *scc = (struct scc_channel *) dev->priv;
unsigned long flags;
char kisscmd;
-
- if (scc == NULL || scc->magic != SCC_MAGIC || dev->tbusy)
- {
- dev_kfree_skb(skb);
- return 0;
- }
if (skb->len > scc->stat.bufsize || skb->len < 2)
{
@@ -1759,12 +1732,12 @@ static int scc_net_tx(struct sk_buff *skb, struct net_device *dev)
if (skb_queue_len(&scc->tx_queue) > scc->dev->tx_queue_len)
{
struct sk_buff *skb_del;
- skb_del = __skb_dequeue(&scc->tx_queue);
+ skb_del = skb_dequeue(&scc->tx_queue);
dev_kfree_skb(skb_del);
}
- __skb_queue_tail(&scc->tx_queue, skb);
-
+ skb_queue_tail(&scc->tx_queue, skb);
dev->trans_start = jiffies;
+
/*
* Start transmission if the trx state is idle or
@@ -1781,8 +1754,7 @@ static int scc_net_tx(struct sk_buff *skb, struct net_device *dev)
scc_start_tx_timer(scc, t_dwait, 0);
}
- restore_flags(flags);
-
+ restore_flags(flags);
return 0;
}
@@ -1811,9 +1783,6 @@ static int scc_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
struct scc_channel *scc;
scc = (struct scc_channel *) dev->priv;
- if (scc == NULL || scc->magic != SCC_MAGIC)
- return -EINVAL;
-
arg = (void *) ifr->ifr_data;
if (!Driver_Initialized)
@@ -2052,9 +2021,6 @@ static struct net_device_stats *scc_net_get_stats(struct net_device *dev)
{
struct scc_channel *scc = (struct scc_channel *) dev->priv;
- if (scc == NULL || scc->magic != SCC_MAGIC)
- return NULL;
-
scc->dev_stat.rx_errors = scc->stat.rxerrs + scc->stat.rx_over;
scc->dev_stat.tx_errors = scc->stat.txerrs + scc->stat.tx_under;
scc->dev_stat.rx_fifo_errors = scc->stat.rx_over;
@@ -2186,7 +2152,7 @@ done:
/* * Init SCC driver * */
/* ******************************************************************** */
-int __init scc_init (void)
+static int __init scc_init_driver (void)
{
int chip, chan, k, result;
char devname[10];
@@ -2222,25 +2188,7 @@ int __init scc_init (void)
return 0;
}
-/* ******************************************************************** */
-/* * Module support * */
-/* ******************************************************************** */
-
-
-#ifdef MODULE
-int init_module(void)
-{
- int result = 0;
-
- result = scc_init();
-
- if (result == 0)
- printk(KERN_INFO "Copyright 1993,1998 Joerg Reuter DL1BKE (jreuter@poboxes.com)\n");
-
- return result;
-}
-
-void cleanup_module(void)
+static void __exit scc_cleanup_driver(void)
{
long flags;
io_port ctrl;
@@ -2283,4 +2231,9 @@ void cleanup_module(void)
scc_net_procfs_remove();
}
-#endif
+
+MODULE_AUTHOR("Joerg Reuter <jreuter@poboxes.com>");
+MODULE_DESCRIPTION("AX.25 Device Driver for Z8530 based HDLC cards");
+MODULE_SUPPORTED_DEVICE("scc");
+module_init(scc_init_driver);
+module_exit(scc_cleanup_driver);
diff --git a/drivers/net/hamradio/soundmodem/sm.c b/drivers/net/hamradio/soundmodem/sm.c
index 6fa4aca6b..4e5e3e9b9 100644
--- a/drivers/net/hamradio/soundmodem/sm.c
+++ b/drivers/net/hamradio/soundmodem/sm.c
@@ -3,7 +3,7 @@
/*
* sm.c -- soundcard radio modem driver.
*
- * Copyright (C) 1996-1999 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ * Copyright (C) 1996-2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
*
* 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
@@ -34,17 +34,18 @@
*
*
* History:
- * 0.1 21.09.96 Started
- * 18.10.96 Changed to new user space access routines (copy_{to,from}_user)
- * 0.4 21.01.97 Separately compileable soundcard/modem modules
- * 0.5 03.03.97 fixed LPT probing (check_lpt result was interpreted the wrong way round)
- * 0.6 16.04.97 init code/data tagged
- * 0.7 30.07.97 fixed halfduplex interrupt handlers/hotfix for CS423X
- * 0.8 14.04.98 cleanups
- * 0.9 03.08.99 adapt to Linus' new __setup/__initcall
- * use parport lowlevel drivers instead of directly writing to a parallel port
- * removed some pre-2.2 kernel compatibility cruft
- * 0.10 10.08.99 Check if parport can do SPP and is safe to access during interrupt contexts
+ * 0.1 21.09.1996 Started
+ * 18.10.1996 Changed to new user space access routines (copy_{to,from}_user)
+ * 0.4 21.01.1997 Separately compileable soundcard/modem modules
+ * 0.5 03.03.1997 fixed LPT probing (check_lpt result was interpreted the wrong way round)
+ * 0.6 16.04.1997 init code/data tagged
+ * 0.7 30.07.1997 fixed halfduplex interrupt handlers/hotfix for CS423X
+ * 0.8 14.04.1998 cleanups
+ * 0.9 03.08.1999 adapt to Linus' new __setup/__initcall
+ * use parport lowlevel drivers instead of directly writing to a parallel port
+ * removed some pre-2.2 kernel compatibility cruft
+ * 0.10 10.08.1999 Check if parport can do SPP and is safe to access during interrupt contexts
+ * 0.11 12.02.2000 adapted to softnet driver interface
*/
/*****************************************************************************/
@@ -63,8 +64,8 @@
/* --------------------------------------------------------------------- */
/*static*/ const char sm_drvname[] = "soundmodem";
-static const char sm_drvinfo[] = KERN_INFO "soundmodem: (C) 1996-1999 Thomas Sailer, HB9JNX/AE4WA\n"
-KERN_INFO "soundmodem: version 0.9 compiled " __TIME__ " " __DATE__ "\n";
+static const char sm_drvinfo[] = KERN_INFO "soundmodem: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
+KERN_INFO "soundmodem: version 0.11 compiled " __TIME__ " " __DATE__ "\n";
/* --------------------------------------------------------------------- */
@@ -508,7 +509,7 @@ static int sm_ioctl(struct net_device *dev, struct ifreq *ifr,
return 0;
case HDLCDRVCTL_SETMODE:
- if (dev->start || !suser())
+ if (netif_running(dev) || !suser())
return -EACCES;
hi->data.modename[sizeof(hi->data.modename)-1] = '\0';
return sethw(dev, sm, hi->data.modename);
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index e99d4c7a9..400facbf8 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -649,7 +649,7 @@ static void yam_dotimer(unsigned long dummy)
for (i = 0; i < NR_PORTS; i++) {
struct net_device *dev = &yam_ports[i].dev;
- if (dev->start)
+ if (netif_running(dev))
yam_arbitrate(dev);
}
yam_timer.expires = jiffies + HZ / 100;
@@ -748,7 +748,7 @@ static void yam_interrupt(int irq, void *dev_id, struct pt_regs *regs)
yp = &yam_ports[i];
dev = &yp->dev;
- if (!dev->start)
+ if (!netif_running(dev))
continue;
while ((iir = IIR_MASK & inb(IIR(dev->base_addr))) != IIR_NOPEND) {
@@ -794,7 +794,7 @@ static int yam_net_get_info(char *buffer, char **start, off_t offset, int length
if (yam_ports[i].iobase == 0 || yam_ports[i].irq == 0)
continue;
len += sprintf(buffer + len, "Device %s\n", yam_ports[i].name);
- len += sprintf(buffer + len, " Up %d\n", yam_ports[i].dev.start);
+ len += sprintf(buffer + len, " Up %d\n", netif_running(&yam_ports[i].dev));
len += sprintf(buffer + len, " Speed %u\n", yam_ports[i].bitrate);
len += sprintf(buffer + len, " IoBase 0x%x\n", yam_ports[i].iobase);
len += sprintf(buffer + len, " BaudRate %u\n", yam_ports[i].baudrate);
@@ -903,7 +903,9 @@ static int yam_open(struct net_device *dev)
request_region(dev->base_addr, YAM_EXTENT, dev->name);
yam_set_uart(dev);
- dev->start = 1;
+
+ netif_start_queue(dev);
+
yp->slotcnt = yp->slot / 10;
/* Reset overruns for all ports - FPGA programming makes overruns */
@@ -935,8 +937,7 @@ static int yam_close(struct net_device *dev)
/* Remove IRQ handler if last */
free_irq(dev->irq, NULL);
release_region(dev->base_addr, YAM_EXTENT);
- dev->start = 0;
- dev->tbusy = 1;
+ netif_stop_queue(dev);
while ((skb = skb_dequeue(&yp->send_queue)))
dev_kfree_skb(skb);
@@ -973,7 +974,7 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return -EINVAL; /* unused */
case SIOCYAMSMCS:
- if (dev->start)
+ if (netif_running(dev))
return -EINVAL; /* Cannot change this parameter when up */
ym = kmalloc(sizeof(struct yamdrv_ioctl_mcs), GFP_ATOMIC);
ym->bitrate = 9600;
@@ -989,13 +990,13 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (copy_from_user(&yi, ifr->ifr_data, sizeof(struct yamdrv_ioctl_cfg)))
return -EFAULT;
- if ((yi.cfg.mask & YAM_IOBASE) && dev->start)
+ if ((yi.cfg.mask & YAM_IOBASE) && netif_running(dev))
return -EINVAL; /* Cannot change this parameter when up */
- if ((yi.cfg.mask & YAM_IRQ) && dev->start)
+ if ((yi.cfg.mask & YAM_IRQ) && netif_running(dev))
return -EINVAL; /* Cannot change this parameter when up */
- if ((yi.cfg.mask & YAM_BITRATE) && dev->start)
+ if ((yi.cfg.mask & YAM_BITRATE) && netif_running(dev))
return -EINVAL; /* Cannot change this parameter when up */
- if ((yi.cfg.mask & YAM_BAUDRATE) && dev->start)
+ if ((yi.cfg.mask & YAM_BAUDRATE) && netif_running(dev))
return -EINVAL; /* Cannot change this parameter when up */
if (yi.cfg.mask & YAM_IOBASE) {
@@ -1164,8 +1165,6 @@ int __init yam_init(void)
dev->irq = yam_ports[i].irq;
dev->init = yam_probe;
dev->if_port = 0;
- dev->start = 0;
- dev->tbusy = 1;
if (register_netdev(dev)) {
printk(KERN_WARNING "yam: cannot register net device %s\n", dev->name);
@@ -1211,7 +1210,7 @@ void cleanup_module(void)
struct net_device *dev = &yam_ports[i].dev;
if (!dev->priv)
continue;
- if (dev->start)
+ if (netif_running(dev))
yam_close(dev);
unregister_netdev(dev);
}
diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c
index 922b28437..8e5511da1 100644
--- a/drivers/net/hydra.c
+++ b/drivers/net/hydra.c
@@ -175,17 +175,16 @@ int __init hydra_probe(struct net_device *dev)
}
strcpy(z->name, "Hydra Ethernet Card");
+ dev = init_etherdev(NULL, sizeof(struct hydra_private));
+ memset(dev->priv, 0, sizeof(struct hydra_private));
+
for(j = 0; j < ETHER_ADDR_LEN; j++)
dev->dev_addr[j] = *((u8 *)ZTWO_VADDR(board + HYDRA_ADDRPROM + 2*j));
printk("%s: hydra at 0x%08x, address %02x:%02x:%02x:%02x:%02x:%02x (hydra.c " HYDRA_VERSION ")\n",
dev->name, (int)board, dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
- init_etherdev(dev, 0);
-
- dev->priv = kmalloc(sizeof(struct hydra_private), GFP_KERNEL);
- memset(dev->priv, 0, sizeof(struct hydra_private));
-
+
dev->base_addr = ZTWO_VADDR(base_addr);
dev->mem_start = ZTWO_VADDR(board);
dev->mem_end = dev->mem_start+0x4000;
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index c0d6d265e..1a52df5f9 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -458,8 +458,7 @@ static void ioc3_interrupt(int irq, void *_dev, struct pt_regs *regs)
ioc3_error(dev, ip, ioc3, eisr);
}
- if (test_bit(LINK_STATE_XOFF, &dev->state) &&
- (TX_BUFFS_AVAIL(ip) >= 0)) {
+ if ((TX_BUFFS_AVAIL(ip) >= 0) && netif_queue_stopped(dev)) {
netif_wake_queue(dev);
}
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
index d8832292a..bf001d83d 100644
--- a/drivers/net/irda/irport.c
+++ b/drivers/net/irda/irport.c
@@ -85,6 +85,7 @@ static int irport_set_dtr_rts(struct net_device *dev, int dtr, int rts);
static int irport_raw_write(struct net_device *dev, __u8 *buf, int len);
static struct net_device_stats *irport_net_get_stats(struct net_device *dev);
static int irport_change_speed_complete(struct irda_task *task);
+static void irport_timeout(struct net_device *dev);
EXPORT_SYMBOL(irport_open);
EXPORT_SYMBOL(irport_close);
@@ -92,6 +93,7 @@ EXPORT_SYMBOL(irport_start);
EXPORT_SYMBOL(irport_stop);
EXPORT_SYMBOL(irport_interrupt);
EXPORT_SYMBOL(irport_hard_xmit);
+EXPORT_SYMBOL(irport_timeout);
EXPORT_SYMBOL(irport_change_speed);
EXPORT_SYMBOL(irport_net_open);
EXPORT_SYMBOL(irport_net_close);
@@ -227,6 +229,8 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
/* Override the network functions we need to use */
dev->init = irport_net_init;
dev->hard_start_xmit = irport_hard_xmit;
+ dev->tx_timeout = irport_timeout;
+ dev->watchdog_timeo = HZ/20;
dev->open = irport_net_open;
dev->stop = irport_net_close;
dev->get_stats = irport_net_get_stats;
@@ -505,16 +509,11 @@ static void irport_write_wakeup(struct irport_cb *self)
NULL, (void *) self->new_speed);
self->new_speed = 0;
} else {
- self->netdev->tbusy = 0; /* Unlock */
-
/* Tell network layer that we want more frames */
- mark_bh(NET_BH);
+ netif_wake_queue(self->netdev);
}
self->stats.tx_packets++;
- /* Schedule network layer, so we can get some more frames */
- mark_bh(NET_BH);
-
/*
* Reset Rx FIFO to make sure that all reflected transmit data
* is discarded. This is needed for half duplex operation
@@ -577,16 +576,37 @@ static int irport_change_speed_complete(struct irda_task *task)
ASSERT(self->netdev != NULL, return -1;);
/* Finished changing speed, so we are not busy any longer */
- self->netdev->tbusy = 0;
-
/* Signal network layer so it can try to send the frame */
- mark_bh(NET_BH);
+ netif_wake_queue(self->netdev);
+
return 0;
}
/*
- * Function irport_xmit (void)
+ * Function irport_timeout (struct net_device *dev)
+ *
+ * The networking layer thinks we timed out.
+ *
+ */
+
+static void irport_timeout(struct net_device *dev)
+{
+ struct irport_cb *self;
+ int iobase;
+
+ self = (struct irport_cb *) dev->priv;
+ iobase = self->io.sir_base;
+
+ WARNING("%s: transmit timed out\n", dev->name);
+ irport_start(self);
+ self->change_speed(self->priv, self->io.speed);
+ dev->trans_start = jiffies;
+ netif_wake_queue(dev);
+}
+
+/*
+ * Function irport_hard_start_xmit (struct sk_buff *skb, struct net_device *dev)
*
* Transmits the current frame until FIFO is full, then
* waits until the next transmitt interrupt, and continues until the
@@ -606,19 +626,8 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
iobase = self->io.sir_base;
- /* Lock transmit buffer */
- if (irda_lock((void *) &dev->tbusy) == FALSE) {
- int tickssofar = jiffies - dev->trans_start;
- if ((tickssofar < 5) || !dev->start)
- return -EBUSY;
-
- WARNING("%s: transmit timed out\n", dev->name);
- irport_start(self);
- self->change_speed(self->priv, self->io.speed);
-
- dev->trans_start = jiffies;
- }
-
+ netif_stop_queue(dev);
+
/* Check if we need to change the speed */
if ((speed = irda_get_speed(skb)) != self->io.speed)
self->new_speed = speed;
@@ -696,8 +705,6 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
spin_lock(&self->lock);
- dev->interrupt = 1;
-
iobase = self->io.sir_base;
iir = inb(iobase+UART_IIR) & UART_IIR_ID;
@@ -733,8 +740,6 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
iir = inb(iobase + UART_IIR) & UART_IIR_ID;
}
- dev->interrupt = 0;
-
spin_unlock(&self->lock);
}
@@ -770,10 +775,6 @@ int irport_net_open(struct net_device *dev)
irport_start(self);
- /* Ready to play! */
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
/*
* Open new IrLAP layer instance, now that everything should be
@@ -782,7 +783,10 @@ int irport_net_open(struct net_device *dev)
self->irlap = irlap_open(dev, &self->qos);
/* FIXME: change speed of dongle */
+ /* Ready to play! */
+ netif_start_queue(dev);
+
MOD_INC_USE_COUNT;
return 0;
@@ -809,9 +813,8 @@ int irport_net_close(struct net_device *dev)
iobase = self->io.sir_base;
/* Stop device */
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
+
/* Stop and remove instance of IrLAP */
if (self->irlap)
irlap_close(self->irlap);
diff --git a/drivers/net/irda/irtty.c b/drivers/net/irda/irtty.c
index 370a9c7fe..931ae9c4c 100644
--- a/drivers/net/irda/irtty.c
+++ b/drivers/net/irda/irtty.c
@@ -615,11 +615,9 @@ static int irtty_change_speed_complete(struct irda_task *task)
ASSERT(self->netdev != NULL, return -1;);
/* Finished changing speed, so we are not busy any longer */
- self->netdev->tbusy = 0;
-
/* Signal network layer so it can try to send the frame */
- mark_bh(NET_BH);
-
+ netif_wake_queue(self->netdev);
+
return 0;
}
@@ -639,9 +637,8 @@ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev)
ASSERT(self != NULL, return 0;);
/* Lock transmit buffer */
- if (irda_lock((void *) &dev->tbusy) == FALSE)
- return -EBUSY;
-
+ netif_stop_queue(dev);
+
/* Check if we need to change the speed */
if ((speed = irda_get_speed(skb)) != self->io.speed)
self->new_speed = speed;
@@ -727,10 +724,8 @@ static void irtty_write_wakeup(struct tty_struct *tty)
NULL, (void *) self->new_speed);
self->new_speed = 0;
} else {
- self->netdev->tbusy = 0; /* Unlock */
-
/* Tell network layer that we want more frames */
- mark_bh(NET_BH);
+ netif_wake_queue(self->netdev);
}
}
}
@@ -899,10 +894,8 @@ static int irtty_net_open(struct net_device *dev)
IRDA_DEBUG(0, __FUNCTION__ "()\n");
/* Ready to play! */
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
-
+ netif_start_queue(dev);
+
/* Make sure we can receive more data */
irtty_stop_receiver(self, FALSE);
@@ -928,9 +921,8 @@ static int irtty_net_close(struct net_device *dev)
irtty_stop_receiver(self, TRUE);
/* Stop device */
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
+
/* Stop and remove instance of IrLAP */
if (self->irlap)
irlap_close(self->irlap);
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 5e30b22ad..1886ec73a 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -1033,8 +1033,6 @@ static void nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 speed)
switch_bank(iobase, BANK2);
outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);
- self->netdev->tbusy = 0;
-
/* Enable some interrupts so we can receive frames */
switch_bank(iobase, BANK0);
if (speed > 115200) {
@@ -1050,6 +1048,8 @@ static void nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 speed)
/* Restore BSR */
outb(bank, iobase+BSR);
+ netif_wake_queue(dev);
+
}
/*
@@ -1072,10 +1072,8 @@ static int nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
iobase = self->io.fir_base;
- /* Lock transmit buffer */
- if (irda_lock((void *) &dev->tbusy) == FALSE)
- return -EBUSY;
-
+ netif_stop_queue(dev);
+
/* Check if we need to change the speed */
if ((speed = irda_get_speed(skb)) != self->io.speed)
self->new_speed = speed;
@@ -1118,10 +1116,8 @@ static int nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
self = (struct nsc_ircc_cb *) dev->priv;
iobase = self->io.fir_base;
- /* Lock transmit buffer */
- if (irda_lock((void *) &dev->tbusy) == FALSE)
- return -EBUSY;
-
+ netif_stop_queue(dev);
+
/* Check if we need to change the speed */
if ((speed = irda_get_speed(skb)) != self->io.speed)
self->new_speed = speed;
@@ -1199,7 +1195,7 @@ static int nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
out:
/* Not busy transmitting anymore if window is not full */
if (self->tx_fifo.free < MAX_TX_WINDOW)
- dev->tbusy = 0;
+ netif_wake_queue(self->netdev);
/* Restore bank register */
outb(bank, iobase+BSR);
@@ -1347,10 +1343,8 @@ static int nsc_ircc_dma_xmit_complete(struct nsc_ircc_cb *self)
/* Make sure we have room for more frames */
if (self->tx_fifo.free < MAX_TX_WINDOW) {
/* Not busy transmitting anymore */
- self->netdev->tbusy = 0;
-
/* Tell the network layer, that we can accept more frames */
- mark_bh(NET_BH);
+ netif_wake_queue(self->netdev);
}
/* Restore bank */
@@ -1601,11 +1595,9 @@ static void nsc_ircc_sir_interrupt(struct nsc_ircc_cb *self, int eir)
if (self->tx_buff.len > 0)
self->ier = IER_TXLDL_IE;
else {
- self->netdev->tbusy = 0; /* Unlock */
- self->stats.tx_packets++;
-
- mark_bh(NET_BH);
+ self->stats.tx_packets++;
+ netif_wakeup_queue(self->netdev);
self->ier = IER_TXEMP_IE;
}
@@ -1731,7 +1723,6 @@ static void nsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
self = (struct nsc_ircc_cb *) dev->priv;
spin_lock(&self->lock);
- dev->interrupt = 1;
iobase = self->io.fir_base;
@@ -1754,7 +1745,6 @@ static void nsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
outb(self->ier, iobase+IER); /* Restore interrupts */
outb(bsr, iobase+BSR); /* Restore bank register */
- dev->interrupt = 0;
spin_unlock(&self->lock);
}
@@ -1860,10 +1850,9 @@ static int nsc_ircc_net_open(struct net_device *dev)
outb(bank, iobase+BSR);
/* Ready to play! */
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue(dev);
+
/*
* Open new IrLAP layer instance, now that everything should be
* initialized properly
@@ -1895,9 +1884,8 @@ static int nsc_ircc_net_close(struct net_device *dev)
ASSERT(self != NULL, return 0;);
/* Stop device */
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
+
/* Stop and remove instance of IrLAP */
if (self->irlap)
irlap_close(self->irlap);
diff --git a/drivers/net/irda/toshoboe.c b/drivers/net/irda/toshoboe.c
index 3420b670b..951b08d8f 100644
--- a/drivers/net/irda/toshoboe.c
+++ b/drivers/net/irda/toshoboe.c
@@ -275,6 +275,8 @@ toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev)
if ((speed = irda_get_speed(skb)) != self->io.speed)
self->new_speed = speed;
+ netif_stop_queue(dev);
+
if (self->stopped) {
dev_kfree_skb(skb);
return 0;
@@ -318,17 +320,14 @@ toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev)
self->txpending++;
- /*FIXME: ask about tbusy,media_busy stuff, for the moment */
- /*tbusy means can't queue any more */
+ /*FIXME: ask about busy,media_busy stuff, for the moment */
+ /*busy means can't queue any more */
#ifndef ONETASK
- if (self->txpending == TX_SLOTS)
- {
-#else
+ if (self->txpending != TX_SLOTS)
{
-#endif
- if (irda_lock ((void *) &dev->tbusy) == FALSE)
- return -EBUSY;
+ netif_wake_queue(dev);
}
+#endif
outb_p (0x80, OBOE_RST);
outb_p (1, OBOE_REG_9);
@@ -379,10 +378,8 @@ toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs)
self->new_speed = 0;
}
- self->netdev->tbusy = 0; /* Unlock */
-
/* Tell network layer that we want more frames */
- mark_bh(NET_BH);
+ netif_wake_queue(self->netdev);
}
if (irqstat & OBOE_ISR_RXDONE)
@@ -529,10 +526,7 @@ toshoboe_net_open (struct net_device *dev)
toshoboe_initptrs (self);
/* Ready to play! */
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
-
+ netif_start_queue(dev);
/*
* Open new IrLAP layer instance, now that everything should be
* initialized properly
@@ -559,9 +553,8 @@ toshoboe_net_close (struct net_device *dev)
self = (struct toshoboe_cb *) dev->priv;
/* Stop device */
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
+
/* Stop and remove instance of IrLAP */
if (self->irlap)
irlap_close(self->irlap);
@@ -926,11 +919,7 @@ toshoboe_wakeup (struct toshoboe_cb *self)
toshoboe_initptrs (self);
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
- self->stopped = 0;
-
+ netif_wake_queue(self->netdev);
restore_flags (flags);
printk (KERN_WARNING "ToshOboe: waking up\n");
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index 7f781719c..239120e51 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -475,8 +475,8 @@ void w83977af_change_speed(struct w83977af_ir *self, __u32 speed)
outb(UFR_EN_FIFO, iobase+UFR); /* First we must enable FIFO */
outb(0xa7, iobase+UFR);
- self->netdev->tbusy = 0;
-
+ netif_wake_queue(self->netdev);
+
/* Enable some interrupts so we can receive frames */
switch_bank(iobase, SET0);
if (speed > PIO_MAX_SPEED) {
@@ -511,9 +511,8 @@ int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev)
(int) skb->len);
/* Lock transmit buffer */
- if (irda_lock((void *) &dev->tbusy) == FALSE)
- return -EBUSY;
-
+ netif_stop_queue(dev);
+
/* Check if we need to change the speed */
if ((speed = irda_get_speed(skb)) != self->io.speed)
self->new_speed = speed;
@@ -715,11 +714,9 @@ void w83977af_dma_xmit_complete(struct w83977af_ir *self)
}
/* Unlock tx_buff and request another frame */
- self->netdev->tbusy = 0; /* Unlock */
-
/* Tell the network layer, that we want more frames */
- mark_bh(NET_BH);
-
+ netif_wake_queue(self->netdev);
+
/* Restore set */
outb(set, iobase+SSR);
}
@@ -991,12 +988,10 @@ static __u8 w83977af_sir_interrupt(struct w83977af_ir *self, int isr)
outb(AUDR_SFEND, iobase+AUDR);
outb(set, iobase+SSR);
- self->netdev->tbusy = 0; /* Unlock */
self->stats.tx_packets++;
- /* Schedule network layer */
- mark_bh(NET_BH);
-
+ /* Feed me more packets */
+ netif_wake_queue(self->netdev);
new_icr |= ICR_ETBREI;
}
}
@@ -1124,8 +1119,6 @@ static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
self = (struct w83977af_ir *) dev->priv;
- dev->interrupt = 1;
-
iobase = self->io.fir_base;
/* Save current bank */
@@ -1148,7 +1141,6 @@ static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs)
outb(icr, iobase+ICR); /* Restore (new) interrupts */
outb(set, iobase+SSR); /* Restore bank register */
- self->netdev->interrupt = 0;
}
/*
@@ -1250,10 +1242,8 @@ static int w83977af_net_open(struct net_device *dev)
outb(set, iobase+SSR);
/* Ready to play! */
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
-
+ netif_start_queue(dev);
+
/*
* Open new IrLAP layer instance, now that everything should be
* initialized properly
@@ -1288,9 +1278,8 @@ static int w83977af_net_close(struct net_device *dev)
iobase = self->io.fir_base;
/* Stop device */
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
+
/* Stop and remove instance of IrLAP */
if (self->irlap)
irlap_close(self->irlap);
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index 0151d4d52..689ffbd22 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -195,6 +195,8 @@ tx_full and tbusy flags.
#define LANCE_BUS_IF 0x16
#define LANCE_TOTAL_SIZE 0x18
+#define TX_TIMEOUT 20
+
/* The LANCE Rx and Tx ring descriptors. */
struct lance_rx_head {
s32 base;
@@ -237,7 +239,7 @@ struct lance_private {
struct net_device_stats stats;
unsigned char chip_version; /* See lance_chip_type. */
char tx_full;
- unsigned long lock;
+ spinlock_t devlock;
};
#define LANCE_MUST_PAD 0x00000001
@@ -296,6 +298,7 @@ static void lance_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int lance_close(struct net_device *dev);
static struct net_device_stats *lance_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
+static void lance_tx_timeout (struct net_device *dev);
@@ -518,6 +521,7 @@ int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int options
lp->tx_bounce_buffs = NULL;
lp->chip_version = lance_version;
+ lp->devlock = SPIN_LOCK_UNLOCKED;
lp->init_block.mode = 0x0003; /* Disable Rx and Tx. */
for (i = 0; i < 6; i++)
@@ -676,6 +680,8 @@ int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int options
dev->stop = lance_close;
dev->get_stats = lance_get_stats;
dev->set_multicast_list = set_multicast_list;
+ dev->tx_timeout = lance_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
return 0;
}
@@ -747,9 +753,8 @@ lance_open(struct net_device *dev)
outw(0x0000, ioaddr+LANCE_ADDR);
outw(0x0001, ioaddr+LANCE_DATA);
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue (dev);
+
i = 0;
while (i++ < 100)
if (inw(ioaddr+LANCE_DATA) & 0x0100)
@@ -801,7 +806,7 @@ lance_init_ring(struct net_device *dev, int gfp)
struct lance_private *lp = (struct lance_private *)dev->priv;
int i;
- lp->lock = 0, lp->tx_full = 0;
+ lp->tx_full = 0;
lp->cur_rx = lp->cur_tx = 0;
lp->dirty_rx = lp->dirty_tx = 0;
@@ -852,48 +857,47 @@ lance_restart(struct net_device *dev, unsigned int csr0_bits, int must_reinit)
outw(csr0_bits, dev->base_addr + LANCE_DATA);
}
-static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
+
+static void lance_tx_timeout (struct net_device *dev)
{
- struct lance_private *lp = (struct lance_private *)dev->priv;
+ struct lance_private *lp = (struct lance_private *) dev->priv;
int ioaddr = dev->base_addr;
- int entry;
- unsigned long flags;
- /* Transmitter timeout, serious problems. */
- if (dev->tbusy) {
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 20)
- return 1;
- outw(0, ioaddr+LANCE_ADDR);
- printk("%s: transmit timed out, status %4.4x, resetting.\n",
- dev->name, inw(ioaddr+LANCE_DATA));
- outw(0x0004, ioaddr+LANCE_DATA);
- lp->stats.tx_errors++;
+ outw (0, ioaddr + LANCE_ADDR);
+ printk ("%s: transmit timed out, status %4.4x, resetting.\n",
+ dev->name, inw (ioaddr + LANCE_DATA));
+ outw (0x0004, ioaddr + LANCE_DATA);
+ lp->stats.tx_errors++;
#ifndef final_version
- {
- int i;
- printk(" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
- lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "",
- lp->cur_rx);
- for (i = 0 ; i < RX_RING_SIZE; i++)
- printk("%s %08x %04x %04x", i & 0x3 ? "" : "\n ",
- lp->rx_ring[i].base, -lp->rx_ring[i].buf_length,
- lp->rx_ring[i].msg_length);
- for (i = 0 ; i < TX_RING_SIZE; i++)
- printk("%s %08x %04x %04x", i & 0x3 ? "" : "\n ",
- lp->tx_ring[i].base, -lp->tx_ring[i].length,
- lp->tx_ring[i].misc);
- printk("\n");
- }
+ {
+ int i;
+ printk (" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
+ lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "",
+ lp->cur_rx);
+ for (i = 0; i < RX_RING_SIZE; i++)
+ printk ("%s %08x %04x %04x", i & 0x3 ? "" : "\n ",
+ lp->rx_ring[i].base, -lp->rx_ring[i].buf_length,
+ lp->rx_ring[i].msg_length);
+ for (i = 0; i < TX_RING_SIZE; i++)
+ printk ("%s %08x %04x %04x", i & 0x3 ? "" : "\n ",
+ lp->tx_ring[i].base, -lp->tx_ring[i].length,
+ lp->tx_ring[i].misc);
+ printk ("\n");
+ }
#endif
- lance_restart(dev, 0x0043, 1);
+ lance_restart (dev, 0x0043, 1);
- dev->tbusy=0;
- dev->trans_start = jiffies;
+ dev->trans_start = jiffies;
+ netif_start_queue (dev);
+}
- return 0;
- }
+static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct lance_private *lp = (struct lance_private *)dev->priv;
+ int ioaddr = dev->base_addr;
+ int entry;
+ unsigned long flags;
if (lance_debug > 3) {
outw(0x0000, ioaddr+LANCE_ADDR);
printk("%s: lance_start_xmit() called, csr0 %4.4x.\n", dev->name,
@@ -901,20 +905,8 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
outw(0x0000, ioaddr+LANCE_DATA);
}
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
- printk("%s: Transmitter access conflict.\n", dev->name);
- return 1;
- }
-
- if (test_and_set_bit(0, (void*)&lp->lock) != 0) {
- if (lance_debug > 0)
- printk("%s: tx queue lock!.\n", dev->name);
- /* don't clear dev->tbusy flag. */
- return 1;
- }
-
+ netif_stop_queue (dev);
+
/* Fill in a Tx ring entry */
/* Mask to ring buffer boundary. */
@@ -955,14 +947,12 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
- save_flags(flags);
- cli();
- lp->lock = 0;
+ spin_lock_irqsave (&lp->devlock, flags);
if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0)
- dev->tbusy=0;
+ netif_start_queue (dev);
else
lp->tx_full = 1;
- restore_flags(flags);
+ spin_unlock_irqrestore (&lp->devlock, flags);
return 0;
}
@@ -983,10 +973,8 @@ lance_interrupt(int irq, void *dev_id, struct pt_regs * regs)
ioaddr = dev->base_addr;
lp = (struct lance_private *)dev->priv;
- if (dev->interrupt)
- printk(KERN_WARNING "%s: Re-entering the interrupt handler.\n", dev->name);
-
- dev->interrupt = 1;
+
+ spin_lock (&lp->devlock);
outw(0x00, dev->base_addr + LANCE_ADDR);
while ((csr0 = inw(dev->base_addr + LANCE_DATA)) & 0x8600
@@ -1040,7 +1028,7 @@ lance_interrupt(int irq, void *dev_id, struct pt_regs * regs)
/* We must free the original skb if it's not a data-only copy
in the bounce buffer. */
if (lp->tx_skbuff[entry]) {
- dev_kfree_skb(lp->tx_skbuff[entry]);
+ dev_kfree_skb_irq(lp->tx_skbuff[entry]);
lp->tx_skbuff[entry] = 0;
}
dirty_tx++;
@@ -1054,12 +1042,12 @@ lance_interrupt(int irq, void *dev_id, struct pt_regs * regs)
}
#endif
- if (lp->tx_full && dev->tbusy
- && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
+ if (lp->tx_full &&
+ (netif_queue_stopped(dev)) &&
+ dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
/* The ring is no longer full, clear tbusy. */
lp->tx_full = 0;
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue (dev);
}
lp->dirty_tx = dirty_tx;
@@ -1092,8 +1080,7 @@ lance_interrupt(int irq, void *dev_id, struct pt_regs * regs)
dev->name, inw(ioaddr + LANCE_ADDR),
inw(dev->base_addr + LANCE_DATA));
- dev->interrupt = 0;
- return;
+ spin_unlock (&lp->devlock);
}
static int
@@ -1181,8 +1168,7 @@ lance_close(struct net_device *dev)
struct lance_private *lp = (struct lance_private *)dev->priv;
int i;
- dev->start = 0;
- dev->tbusy = 1;
+ netif_stop_queue (dev);
if (chip_table[lp->chip_version].flags & LANCE_HAS_MISSED_FRAME) {
outw(112, ioaddr+LANCE_ADDR);
diff --git a/drivers/net/ltpc.c b/drivers/net/ltpc.c
index f572a5ea6..e461f8807 100644
--- a/drivers/net/ltpc.c
+++ b/drivers/net/ltpc.c
@@ -246,23 +246,9 @@ static int sendup_buffer (struct net_device *dev);
/* Dma Memory related stuff, cribbed directly from 3c505.c */
-/* Pure 2^n version of get_order */
-static inline int __get_order(unsigned long size)
-{
- int order;
-
- size = (size - 1) >> (PAGE_SHIFT - 1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
static unsigned long dma_mem_alloc(int size)
{
- int order = __get_order(size);
+ int order = get_order(size);
return __get_dma_pages(GFP_KERNEL, order);
}
@@ -1364,7 +1350,7 @@ void cleanup_module(void)
if(debug&DEBUG_VERBOSE) printk("free_pages\n");
- free_pages( (unsigned long) ltdmabuf, __get_order(1000));
+ free_pages( (unsigned long) ltdmabuf, get_order(1000));
ltdmabuf=NULL;
ltdmacbuf=NULL;
diff --git a/drivers/net/mace.c b/drivers/net/mace.c
index 3a69c5c80..ac0771bd8 100644
--- a/drivers/net/mace.c
+++ b/drivers/net/mace.c
@@ -20,9 +20,7 @@
#include <asm/pgtable.h>
#include "mace.h"
-#ifdef MODULE
static struct net_device *mace_devs = NULL;
-#endif
#define N_RX_RING 8
#define N_TX_RING 6
@@ -55,6 +53,7 @@ struct mace_data {
struct net_device_stats stats;
struct timer_list tx_timeout;
int timeout_active;
+ struct net_device *next_mace;
};
/*
@@ -67,6 +66,8 @@ struct mace_data {
+ (N_RX_RING + NCMDS_TX * N_TX_RING + 3) * sizeof(struct dbdma_cmd))
static int bitrev(int);
+static int mace_probe(void);
+static void mace_probe1(struct device_node *mace);
static int mace_open(struct net_device *dev);
static int mace_close(struct net_device *dev);
static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
@@ -99,34 +100,36 @@ bitrev(int b)
return d;
}
-static int __init mace_probe (void)
+static int __init mace_probe(void)
+{
+ struct device_node *mace;
+
+ for (mace = find_devices("mace"); mace != NULL; mace = mace->next)
+ mace_probe1(mace);
+ return 0;
+}
+
+static void __init mace_probe1(struct device_node *mace)
{
int j, rev;
struct net_device *dev;
struct mace_data *mp;
- struct device_node *mace;
unsigned char *addr;
- static int maces_found = 0;
- static struct device_node *next_mace;
-
-#ifdef MODULE
- if(mace_devs != NULL)
- return -EBUSY;
-#endif
-
- if (!maces_found) {
- next_mace = find_devices("mace");
- maces_found = 1;
- }
- mace = next_mace;
- if (mace == 0)
- return -ENODEV;
- next_mace = mace->next;
if (mace->n_addrs != 3 || mace->n_intrs != 3) {
- printk(KERN_ERR "can't use MACE %s: expect 3 addrs and 3 intrs\n",
+ printk(KERN_ERR "can't use MACE %s: need 3 addrs and 3 irqs\n",
mace->full_name);
- return -ENODEV;
+ return;
+ }
+
+ addr = get_property(mace, "mac-address", NULL);
+ if (addr == NULL) {
+ addr = get_property(mace, "local-mac-address", NULL);
+ if (addr == NULL) {
+ printk(KERN_ERR "Can't get mac-address for MACE %s\n",
+ mace->full_name);
+ return;
+ }
}
dev = init_etherdev(0, PRIV_BYTES);
@@ -138,16 +141,6 @@ static int __init mace_probe (void)
ioremap(mace->addrs[0].address, 0x1000);
dev->irq = mace->intrs[0].line;
- addr = get_property(mace, "mac-address", NULL);
- if (addr == NULL) {
- addr = get_property(mace, "local-mac-address", NULL);
- if (addr == NULL) {
- printk(KERN_ERR "Can't get mac-address for MACE at %lx\n",
- dev->base_addr);
- return -EAGAIN;
- }
- }
-
printk(KERN_INFO "%s: MACE at", dev->name);
rev = addr[0] == 0 && addr[1] == 0xA0;
for (j = 0; j < 6; ++j) {
@@ -186,22 +179,17 @@ static int __init mace_probe (void)
mace_reset(dev);
- if (request_irq(dev->irq, mace_interrupt, 0, "MACE", dev)) {
+ if (request_irq(dev->irq, mace_interrupt, 0, "MACE", dev))
printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq);
- return -EAGAIN;
- }
if (request_irq(mace->intrs[1].line, mace_txdma_intr, 0, "MACE-txdma",
- dev)) {
+ dev))
printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[1].line);
- return -EAGAIN;
- }
if (request_irq(mace->intrs[2].line, mace_rxdma_intr, 0, "MACE-rxdma",
- dev)) {
+ dev))
printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[2].line);
- return -EAGAIN;
- }
- return 0;
+ mp->next_mace = mace_devs;
+ mace_devs = dev;
}
static void dbdma_reset(volatile struct dbdma_regs *dma)
@@ -365,9 +353,7 @@ static int mace_open(struct net_device *dev)
/* enable all interrupts except receive interrupts */
out_8(&mb->imr, RCVINT);
-#ifdef MOD_INC_USE_COUNT
MOD_INC_USE_COUNT;
-#endif
return 0;
}
@@ -406,9 +392,7 @@ static int mace_close(struct net_device *dev)
mace_clean_rings(mp);
-#ifdef MOD_DEC_USE_COUNT
MOD_DEC_USE_COUNT;
-#endif
return 0;
}
@@ -445,7 +429,7 @@ static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
if (next >= N_TX_RING)
next = 0;
if (next == mp->tx_empty) {
- dev->tbusy = 1;
+ netif_stop_queue(dev);
mp->tx_fullup = 1;
restore_flags(flags);
return 1; /* can't take it at the moment */
@@ -480,7 +464,7 @@ static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
if (++next >= N_TX_RING)
next = 0;
if (next == mp->tx_empty)
- dev->tbusy = 1;
+ netif_stop_queue(dev);
restore_flags(flags);
return 0;
@@ -683,7 +667,7 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
mp->stats.tx_bytes += mp->tx_bufs[i]->len;
++mp->stats.tx_packets;
}
- dev_kfree_skb(mp->tx_bufs[i]);
+ dev_kfree_skb_irq(mp->tx_bufs[i]);
--mp->tx_active;
if (++i >= N_TX_RING)
i = 0;
@@ -695,8 +679,7 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (i != mp->tx_empty) {
mp->tx_fullup = 0;
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
}
mp->tx_empty = i;
i += mp->tx_active;
@@ -765,8 +748,7 @@ static void mace_tx_timeout(unsigned long data)
mp->tx_empty = i;
}
mp->tx_fullup = 0;
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
if (i != mp->tx_fill) {
cp = mp->tx_cmds + NCMDS_TX * i;
out_le16(&cp->xfer_status, 0);
@@ -897,23 +879,25 @@ static void mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs)
}
}
-
MODULE_AUTHOR("Paul Mackerras");
MODULE_DESCRIPTION("PowerMac MACE driver.");
static void __exit mace_cleanup (void)
{
-#ifdef MODULE
- struct mace_data *mp = (struct mace_data *) mace_devs->priv;
- unregister_netdev(mace_devs);
+ struct net_device *dev;
+ struct mace_data *mp;
- free_irq(mace_devs->irq, mace_interrupt);
- free_irq(mp->tx_dma_intr, mace_txdma_intr);
- free_irq(mp->rx_dma_intr, mace_rxdma_intr);
+ while ((dev = mace_devs) != 0) {
+ mp = (struct mace_data *) mace_devs->priv;
+ mace_devs = mp->next_mace;
- kfree(mace_devs);
- mace_devs = NULL;
-#endif
+ free_irq(dev->irq, dev);
+ free_irq(mp->tx_dma_intr, dev);
+ free_irq(mp->rx_dma_intr, dev);
+
+ unregister_netdev(dev);
+ kfree(dev);
+ }
}
module_init(mace_probe);
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index 3c4e23016..bd1406e1f 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -256,7 +256,7 @@ static void myri_clean_rings(struct myri_eth *mp)
u32 dma_addr;
dma_addr = sbus_readl(&rxd->myri_scatters[0].addr);
- sbus_unmap_single(mp->myri_sdev, dma_addr, RX_ALLOC_SIZE);
+ sbus_unmap_single(mp->myri_sdev, dma_addr, RX_ALLOC_SIZE, SBUS_DMA_FROMDEVICE);
dev_kfree_skb(mp->rx_skbs[i]);
mp->rx_skbs[i] = NULL;
}
@@ -272,7 +272,7 @@ static void myri_clean_rings(struct myri_eth *mp)
u32 dma_addr;
dma_addr = sbus_readl(&txd->myri_gathers[0].addr);
- sbus_unmap_single(mp->myri_sdev, dma_addr, (skb->len + 3) & ~3);
+ sbus_unmap_single(mp->myri_sdev, dma_addr, (skb->len + 3) & ~3, SBUS_DMA_TODEVICE);
dev_kfree_skb(mp->tx_skbs[i]);
mp->tx_skbs[i] = NULL;
}
@@ -301,7 +301,7 @@ static void myri_init_rings(struct myri_eth *mp, int from_irq)
skb->dev = dev;
skb_put(skb, RX_ALLOC_SIZE);
- dma_addr = sbus_map_single(mp->myri_sdev, skb->data, RX_ALLOC_SIZE);
+ dma_addr = sbus_map_single(mp->myri_sdev, skb->data, RX_ALLOC_SIZE, SBUS_DMA_FROMDEVICE);
sbus_writel(dma_addr, &rxd[i].myri_scatters[0].addr);
sbus_writel(RX_ALLOC_SIZE, &rxd[i].myri_scatters[0].len);
sbus_writel(i, &rxd[i].ctx);
@@ -363,7 +363,7 @@ static void myri_tx(struct myri_eth *mp, struct net_device *dev)
DTX(("SKB[%d] ", entry));
dma_addr = sbus_readl(&sq->myri_txd[entry].myri_gathers[0].addr);
- sbus_unmap_single(mp->myri_sdev, dma_addr, skb->len);
+ sbus_unmap_single(mp->myri_sdev, dma_addr, skb->len, SBUS_DMA_TODEVICE);
dev_kfree_skb(skb);
mp->tx_skbs[entry] = NULL;
mp->enet_stats.tx_packets++;
@@ -444,7 +444,7 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev)
DRX(("rxd[%d]: %p len[%d] csum[%08x] ", entry, rxd, len, csum));
sbus_dma_sync_single(mp->myri_sdev,
sbus_readl(&rxd->myri_scatters[0].addr),
- RX_ALLOC_SIZE);
+ RX_ALLOC_SIZE, SBUS_DMA_FROMDEVICE);
if (len < (ETH_HLEN + MYRI_PAD_LEN) || (skb->data[0] != MYRI_PAD_LEN)) {
DRX(("ERROR["));
mp->enet_stats.rx_errors++;
@@ -481,13 +481,15 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev)
}
sbus_unmap_single(mp->myri_sdev,
sbus_readl(&rxd->myri_scatters[0].addr),
- RX_ALLOC_SIZE);
+ RX_ALLOC_SIZE,
+ SBUS_DMA_FROMDEVICE);
mp->rx_skbs[index] = new_skb;
new_skb->dev = dev;
skb_put(new_skb, RX_ALLOC_SIZE);
dma_addr = sbus_map_single(mp->myri_sdev,
new_skb->data,
- RX_ALLOC_SIZE);
+ RX_ALLOC_SIZE,
+ SBUS_DMA_FROMDEVICE);
sbus_writel(dma_addr, &rxd->myri_scatters[0].addr);
sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
sbus_writel(index, &rxd->ctx);
@@ -650,7 +652,7 @@ static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev)
sbus_writew((skb->data[4] << 8) | skb->data[5], &txd->addr[3]);
}
- dma_addr = sbus_map_single(mp->myri_sdev, skb->data, len);
+ dma_addr = sbus_map_single(mp->myri_sdev, skb->data, len, SBUS_DMA_TODEVICE);
sbus_writel(dma_addr, &txd->myri_gathers[0].addr);
sbus_writel(len, &txd->myri_gathers[0].len);
sbus_writel(1, &txd->num_sg);
diff --git a/drivers/net/ncr885e.c b/drivers/net/ncr885e.c
index fd120de2b..6a8c8b412 100644
--- a/drivers/net/ncr885e.c
+++ b/drivers/net/ncr885e.c
@@ -11,9 +11,10 @@
*/
static const char *version =
-"ncr885e.c:v0.8 11/30/98 dan@synergymicro.com\n";
+"ncr885e.c:v1.0 02/10/00 dan@synergymicro.com, cort@fsmlabs.com\n";
#include <linux/config.h>
+
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
@@ -81,8 +82,6 @@ static const char *chipname = "ncr885e";
int ncr885e_debug = NCR885E_DEBUG;
static int print_version = 0;
-static int debug = NCR885E_DEBUG; /* module parm */
-
struct ncr885e_private {
@@ -426,7 +425,6 @@ ncr885e_tx( struct net_device *dev )
if ( xfer ) {
dev_kfree_skb( sp->tx_skbufs[i] );
- mark_bh( NET_BH );
if ( txbits & TX_STATUS_TXOK ) {
sp->stats.tx_packets++;
@@ -443,7 +441,7 @@ ncr885e_tx( struct net_device *dev )
}
- dev->tbusy = 0;
+ netif_start_queue(dev);
return;
}
@@ -626,12 +624,6 @@ ncr885e_interrupt( int irq, void *dev_id, struct pt_regs *regs )
sp = (struct ncr885e_private *) dev->priv;
spin_lock( &sp->lock );
- if ( dev->interrupt ) {
- printk( KERN_ERR "%s: Re-entering interrupt handler...\n",
- dev->name );
- }
-
- dev->interrupt = 1;
status = inw( ioaddr + INTERRUPT_CLEAR );
if (ncr885e_debug > 2)
@@ -671,7 +663,6 @@ ncr885e_interrupt( int irq, void *dev_id, struct pt_regs *regs )
ncr885e_rx( dev );
}
- dev->interrupt = 0;
spin_unlock( &sp->lock );
return;
@@ -779,8 +770,7 @@ ncr885e_tx_timeout( unsigned long data )
/* start anew from the beginning of the ring buffer (why not?) */
sp->tx_current = 0;
- dev->tbusy = 0;
- mark_bh( NET_BH );
+ netif_wake_queue(dev);
/* restart rx dma */
outl( (RX_DBDMA_ENABLE << 16) | RX_CHANNEL_RUN,
@@ -958,9 +948,7 @@ ncr885e_open( struct net_device *dev )
outl( (RX_DBDMA_ENABLE << 16)|RX_CHANNEL_RUN,
ioaddr + RX_CHANNEL_CONTROL );
- dev->start = 1;
- dev->tbusy = 0;
- dev->interrupt = 0;
+ netif_start_queue(dev);
MOD_INC_USE_COUNT;
@@ -990,7 +978,7 @@ ncr885e_xmit_start( struct sk_buff *skb, struct net_device *dev )
next = 0;
/* mark ourselves as busy, even if we have too many packets waiting */
- dev->tbusy = 1;
+ netif_stop_queue(dev);
/* see if it's necessary to defer this packet */
if ( sp->tx_active >= MAX_TX_ACTIVE ) {
@@ -1058,8 +1046,7 @@ ncr885e_close(struct net_device *dev)
struct ncr885e_private *np = (struct ncr885e_private *) dev->priv;
unsigned long ioaddr = dev->base_addr;
- dev->start = 0;
- dev->tbusy = 1;
+ netif_stop_queue(dev);
spin_lock( &np->lock );
@@ -1148,8 +1135,7 @@ ncr885e_stats( struct net_device *dev )
* configuration.
*/
-static int
-ncr885e_probe1(unsigned long ioaddr, unsigned char irq )
+static int __init ncr885e_probe1(unsigned long ioaddr, unsigned char irq )
{
struct net_device *dev;
@@ -1158,9 +1144,6 @@ ncr885e_probe1(unsigned long ioaddr, unsigned char irq )
unsigned char *p;
int i;
- if (!request_region( ioaddr, NCR885E_TOTAL_SIZE, dev->name))
- return -EBUSY;
-
dev = init_etherdev(NULL, 0 );
/* construct private data for the 885 ethernet */
@@ -1413,12 +1396,16 @@ write_mii( unsigned long ioaddr, int reg, int data )
#endif /* NCR885E_DEBUG_MII */
-MODULE_AUTHOR("dan@synergymicro.com");
-MODULE_DESCRIPTION("Symbios 53C885 Ethernet driver");
-MODULE_PARM(debug, "i");
+int
+init_module(void)
+{
+ if ( debug >= 0)
+ ncr885e_debug = debug;
+ return ncr885e_probe();
+}
-static void __exit ncr885e_cleanup (void)
+static void __exit cleanup_module(void)
{
struct ncr885e_private *np;
@@ -1435,7 +1422,6 @@ static void __exit ncr885e_cleanup (void)
module_init(ncr885e_probe);
module_exit(ncr885e_cleanup);
-
/*
* Local variables:
* compile-command: "gcc -DMODULE -DMODVERSIONS -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O6 -c symba.c"
diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c
index 0a69d9004..269300c0d 100644
--- a/drivers/net/ne2.c
+++ b/drivers/net/ne2.c
@@ -425,9 +425,8 @@ static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
If it does, it's the last thing you'll see */
if (ei_status.dmaing) {
printk("%s: DMAing conflict in ne_get_8390_hdr "
- "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
- dev->name, ei_status.dmaing, ei_status.irqlock,
- dev->interrupt);
+ "[DMAstat:%d][irqlock:%d].\n",
+ dev->name, ei_status.dmaing, ei_status.irqlock);
return;
}
@@ -468,9 +467,8 @@ static void ne_block_input(struct net_device *dev, int count, struct sk_buff *sk
If it does, it's the last thing you'll see */
if (ei_status.dmaing) {
printk("%s: DMAing conflict in ne_block_input "
- "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
- dev->name, ei_status.dmaing, ei_status.irqlock,
- dev->interrupt);
+ "[DMAstat:%d][irqlock:%d].\n",
+ dev->name, ei_status.dmaing, ei_status.irqlock);
return;
}
ei_status.dmaing |= 0x01;
@@ -537,9 +535,8 @@ static void ne_block_output(struct net_device *dev, int count,
If it does, it's the last thing you'll see */
if (ei_status.dmaing) {
printk("%s: DMAing conflict in ne_block_output."
- "[DMAstat:%d][irqlock:%d][intr:%ld]\n",
- dev->name, ei_status.dmaing, ei_status.irqlock,
- dev->interrupt);
+ "[DMAstat:%d][irqlock:%d]\n",
+ dev->name, ei_status.dmaing, ei_status.irqlock);
return;
}
ei_status.dmaing |= 0x01;
diff --git a/drivers/net/net_init.c b/drivers/net/net_init.c
index 93b2f9923..b4fc3e0a8 100644
--- a/drivers/net/net_init.c
+++ b/drivers/net/net_init.c
@@ -153,7 +153,7 @@ struct net_device *init_etherdev(struct net_device *dev, int sizeof_priv)
static int eth_mac_addr(struct net_device *dev, void *p)
{
struct sockaddr *addr=p;
- if(test_bit(LINK_STATE_START, &dev->state))
+ if (netif_running(dev))
return -EBUSY;
memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
return 0;
@@ -200,7 +200,7 @@ static int hippi_change_mtu(struct net_device *dev, int new_mtu)
static int hippi_mac_addr(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
- if(test_bit(LINK_STATE_START, &dev->state))
+ if (netif_running(dev))
return -EBUSY;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
return 0;
diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c
index 9a81ff0f7..8e5bca56a 100644
--- a/drivers/net/ni5010.c
+++ b/drivers/net/ni5010.c
@@ -106,6 +106,7 @@ static int ni5010_open(struct net_device *dev);
static int ni5010_send_packet(struct sk_buff *skb, struct net_device *dev);
static void ni5010_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void ni5010_rx(struct net_device *dev);
+static void ni5010_timeout(struct net_device *dev);
static int ni5010_close(struct net_device *dev);
static struct net_device_stats *ni5010_get_stats(struct net_device *dev);
static void ni5010_set_multicast_list(struct net_device *dev);
@@ -320,15 +321,13 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
dev->stop = ni5010_close;
dev->hard_start_xmit = ni5010_send_packet;
dev->get_stats = ni5010_get_stats;
- dev->set_multicast_list = &ni5010_set_multicast_list;
+ dev->set_multicast_list = ni5010_set_multicast_list;
+ dev->tx_timeout = ni5010_timeout;
+ dev->watchdog_timeo = HZ/20;
/* Fill in the fields of the device structure with ethernet values. */
ether_setup(dev);
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 0;
-
dev->flags &= ~IFF_MULTICAST; /* Multicast doesn't work */
/* Shut up the ni5010 */
@@ -403,10 +402,8 @@ static int ni5010_open(struct net_device *dev)
outb(0, EDLC_RESET); /* Un-reset the ni5010 */
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
-
+ netif_start_queue(dev);
+
if (NI5010_DEBUG) show_registers(dev);
MOD_INC_USE_COUNT;
@@ -426,42 +423,31 @@ static void reset_receiver(struct net_device *dev)
outb(0xff, EDLC_RMASK); /* Enable all rcv interrupts */
}
+static void ni5010_timeout(struct net_device *dev)
+{
+ printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
+ tx_done(dev) ? "IRQ conflict" : "network cable problem");
+ /* Try to restart the adaptor. */
+ /* FIXME: Give it a real kick here */
+ chipset_init(dev, 1);
+ dev->trans_start = jiffies;
+ netif_wake_queue(dev);
+}
+
static int ni5010_send_packet(struct sk_buff *skb, struct net_device *dev)
{
+ int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+
PRINTK2((KERN_DEBUG "%s: entering ni5010_send_packet\n", dev->name));
- if (dev->tbusy) {
- /*
- * If we get here, some higher level has decided we are broken.
- * There should really be a "kick me" function call instead.
- */
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 5)
- return 1;
- printk("tbusy\n");
- printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
- tx_done(dev) ? "IRQ conflict" : "network cable problem");
- /* Try to restart the adaptor. */
- /* FIXME: Give it a real kick here */
- chipset_init(dev, 1);
- dev->tbusy=0;
- dev->trans_start = jiffies;
- }
/*
- * Block a timer-based transmit from overlapping. This could better be
- * done with atomic_swap(1, dev->tbusy), but test_and_set_bit() works as well.
+ * Block sending
*/
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
- printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
- return 1;
- } else {
- int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-
- hardware_send_packet(dev, (unsigned char *)skb->data, length);
- dev->trans_start = jiffies;
- }
+
+ netif_stop_queue(dev);
+ hardware_send_packet(dev, (unsigned char *)skb->data, length);
+ dev->trans_start = jiffies;
dev_kfree_skb (skb);
-
return 0;
}
@@ -469,23 +455,13 @@ static int ni5010_send_packet(struct sk_buff *skb, struct net_device *dev)
* The typical workload of the driver:
* Handle the network interface interrupts.
*/
-static void
-ni5010_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void ni5010_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
struct ni5010_local *lp;
int ioaddr, status;
int xmit_was_error = 0;
- if (dev == NULL || dev->irq != irq) {
- printk(KERN_WARNING "%s: irq %d for unknown device.\n",
- boardname, irq);
- return;
- }
-
- if (dev->interrupt) printk(KERN_WARNING "%s: Reentering IRQ-handler!\n", dev->name);
- dev->interrupt = 1;
-
PRINTK2((KERN_DEBUG "%s: entering ni5010_interrupt\n", dev->name));
ioaddr = dev->base_addr;
@@ -507,8 +483,6 @@ ni5010_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (!xmit_was_error)
reset_receiver(dev);
-
- dev->interrupt = 0;
return;
}
@@ -530,8 +504,7 @@ static void dump_packet(void *buf, int len)
}
/* We have a good packet, get it out of the buffer. */
-static void
-ni5010_rx(struct net_device *dev)
+static void ni5010_rx(struct net_device *dev)
{
struct ni5010_local *lp = (struct ni5010_local *)dev->priv;
int ioaddr = dev->base_addr;
@@ -624,8 +597,7 @@ static int process_xmt_interrupt(struct net_device *dev)
lp->stats.tx_packets++;
lp->stats.tx_bytes += lp->o_pkt_size;
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_wake_queue(dev);
PRINTK2((KERN_DEBUG "%s: sent packet, size=%#4.4x\n",
dev->name, lp->o_pkt_size));
@@ -634,8 +606,7 @@ static int process_xmt_interrupt(struct net_device *dev)
}
/* The inverse routine to ni5010_open(). */
-static int
-ni5010_close(struct net_device *dev)
+static int ni5010_close(struct net_device *dev)
{
int ioaddr = dev->base_addr;
@@ -647,9 +618,8 @@ ni5010_close(struct net_device *dev)
outb(0, IE_MMODE);
outb(RS_RESET, EDLC_RESET);
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
+
MOD_DEC_USE_COUNT;
PRINTK((KERN_DEBUG "%s: %s closed down\n", dev->name, boardname));
return 0;
@@ -658,8 +628,7 @@ ni5010_close(struct net_device *dev)
/* Get the current statistics. This may be called with the card open or
closed. */
-static struct net_device_stats *
-ni5010_get_stats(struct net_device *dev)
+static struct net_device_stats *ni5010_get_stats(struct net_device *dev)
{
struct ni5010_local *lp = (struct ni5010_local *)dev->priv;
@@ -681,8 +650,7 @@ ni5010_get_stats(struct net_device *dev)
num_addrs > 0 Multicast mode, receive normal and MC packets, and do
best-effort filtering.
*/
-static void
-ni5010_set_multicast_list(struct net_device *dev)
+static void ni5010_set_multicast_list(struct net_device *dev)
{
short ioaddr = dev->base_addr;
@@ -748,6 +716,8 @@ extern void hardware_send_packet(struct net_device *dev, char *buf, int length)
restore_flags(flags);
+ netif_wake_queue(dev);
+
if (NI5010_DEBUG) show_registers(dev);
}
diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c
index 7efc0dca6..6d1d0e714 100644
--- a/drivers/net/ni52.c
+++ b/drivers/net/ni52.c
@@ -199,6 +199,7 @@ static int ni52_close(struct net_device *dev);
static int ni52_send_packet(struct sk_buff *,struct net_device *);
static struct net_device_stats *ni52_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
+static void ni52_timeout(struct net_device *dev);
#if 0
static void ni52_dump(struct net_device *,void *);
#endif
@@ -244,9 +245,7 @@ static int ni52_close(struct net_device *dev)
ni_reset586(); /* the hard way to stop the receiver */
- dev->start = 0;
- dev->tbusy = 0;
-
+ netif_stop_queue(dev);
MOD_DEC_USE_COUNT;
return 0;
@@ -269,10 +268,7 @@ static int ni52_open(struct net_device *dev)
return -EAGAIN;
}
- dev->interrupt = 0;
- dev->tbusy = 0;
- dev->start = 1;
-
+ netif_start_queue(dev);
MOD_INC_USE_COUNT;
return 0; /* most done by init */
@@ -512,20 +508,18 @@ static int __init ni52_probe1(struct net_device *dev,int ioaddr)
printk("IRQ %d (assigned and not checked!).\n",dev->irq);
}
- dev->open = &ni52_open;
- dev->stop = &ni52_close;
- dev->get_stats = &ni52_get_stats;
- dev->hard_start_xmit = &ni52_send_packet;
- dev->set_multicast_list = &set_multicast_list;
+ dev->open = ni52_open;
+ dev->stop = ni52_close;
+ dev->get_stats = ni52_get_stats;
+ dev->tx_timeout = ni52_timeout;
+ dev->watchdog_timeo = HZ/20;
+ dev->hard_start_xmit = ni52_send_packet;
+ dev->set_multicast_list = set_multicast_list;
dev->if_port = 0;
ether_setup(dev);
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 0;
-
return 0;
}
@@ -831,8 +825,6 @@ static void ni52_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr)
if(debuglevel > 1)
printk("I");
- dev->interrupt = 1;
-
WAIT_4_SCB_CMD(); /* wait for last command */
while((stat=p->scb->cus & STAT_MASK))
@@ -866,7 +858,7 @@ static void ni52_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr)
#ifndef NO_NOPCOMMANDS
if(stat & STAT_CNA) /* CU went 'not ready' */
{
- if(dev->start)
+ if(netif_running(dev))
printk("%s: oops! CU has left active state. stat: %04x/%02x.\n",dev->name,(int) stat,(int) p->scb->cus);
}
#endif
@@ -885,8 +877,6 @@ static void ni52_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr)
if(debuglevel > 1)
printk("i");
-
- dev->interrupt = 0;
}
/*******************************************************
@@ -1083,9 +1073,7 @@ static void ni52_xmt_int(struct net_device *dev)
if( (++p->xmit_last) == NUM_XMIT_BUFFS)
p->xmit_last = 0;
#endif
-
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
}
/***********************************************************
@@ -1104,6 +1092,40 @@ static void startrecv586(struct net_device *dev)
WAIT_4_SCB_CMD_RUC(); /* wait for accept cmd. (no timeout!!) */
}
+static void ni52_timeout(struct net_device *dev)
+{
+ struct priv *p = (struct priv *) dev->priv;
+#ifndef NO_NOPCOMMANDS
+ if(p->scb->cus & CU_ACTIVE) /* COMMAND-UNIT active? */
+ {
+ netif_wake_queue(dev);
+#ifdef DEBUG
+ printk("%s: strange ... timeout with CU active?!?\n",dev->name);
+ printk("%s: X0: %04x N0: %04x N1: %04x %d\n",dev->name,(int)p->xmit_cmds[0]->cmd_status,(int)p->nop_cmds[0]->cmd_status,(int)p->nop_cmds[1]->cmd_status,(int)p->nop_point);
+#endif
+ p->scb->cmd_cuc = CUC_ABORT;
+ ni_attn586();
+ WAIT_4_SCB_CMD();
+ p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]);
+ p->scb->cmd_cuc = CUC_START;
+ ni_attn586();
+ WAIT_4_SCB_CMD();
+ dev->trans_start = jiffies;
+ return 0;
+ }
+#endif
+ {
+#ifdef DEBUG
+ printk("%s: xmitter timed out, try to restart! stat: %02x\n",dev->name,p->scb->cus);
+ printk("%s: command-stats: %04x %04x\n",dev->name,p->xmit_cmds[0]->cmd_status,p->xmit_cmds[1]->cmd_status);
+ printk("%s: check, whether you set the right interrupt number!\n",dev->name);
+#endif
+ ni52_close(dev);
+ ni52_open(dev);
+ }
+ dev->trans_start = jiffies;
+}
+
/******************************************************
* send frame
*/
@@ -1116,62 +1138,21 @@ static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev)
#endif
struct priv *p = (struct priv *) dev->priv;
- if(dev->tbusy)
- {
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 5)
- return 1;
-
-#ifndef NO_NOPCOMMANDS
- if(p->scb->cus & CU_ACTIVE) /* COMMAND-UNIT active? */
- {
- dev->tbusy = 0;
-#ifdef DEBUG
- printk("%s: strange ... timeout with CU active?!?\n",dev->name);
- printk("%s: X0: %04x N0: %04x N1: %04x %d\n",dev->name,(int)p->xmit_cmds[0]->cmd_status,(int)p->nop_cmds[0]->cmd_status,(int)p->nop_cmds[1]->cmd_status,(int)p->nop_point);
-#endif
- p->scb->cmd_cuc = CUC_ABORT;
- ni_attn586();
- WAIT_4_SCB_CMD();
- p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]);
- p->scb->cmd_cuc = CUC_START;
- ni_attn586();
- WAIT_4_SCB_CMD();
- dev->trans_start = jiffies;
- return 0;
- }
- else
-#endif
- {
-#ifdef DEBUG
- printk("%s: xmitter timed out, try to restart! stat: %02x\n",dev->name,p->scb->cus);
- printk("%s: command-stats: %04x %04x\n",dev->name,p->xmit_cmds[0]->cmd_status,p->xmit_cmds[1]->cmd_status);
- printk("%s: check, whether you set the right interrupt number!\n",dev->name);
-#endif
- ni52_close(dev);
- ni52_open(dev);
- }
- dev->trans_start = jiffies;
- return 0;
- }
-
if(skb->len > XMIT_BUFF_SIZE)
{
printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %d bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len);
return 0;
}
- if (test_and_set_bit(0, (void*)&dev->tbusy)) {
- printk("%s: Transmitter access conflict.\n", dev->name);
- return 1;
- }
+ netif_stop_queue(dev);
+
#if(NUM_XMIT_BUFFS > 1)
- else if(test_and_set_bit(0,(void *) &p->lock)) {
+ if(test_and_set_bit(0,(void *) &p->lock)) {
printk("%s: Queue was locked\n",dev->name);
return 1;
}
-#endif
else
+#endif
{
memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len);
len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
@@ -1231,7 +1212,7 @@ static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev)
next_nop = 0;
p->xmit_cmds[p->xmit_count]->cmd_status = 0;
- /* linkpointer of xmit-command already points to next nop cmd */
+ /* linkpointer of xmit-command already points to next nop cmd */
p->nop_cmds[next_nop]->cmd_link = make16((p->nop_cmds[next_nop]));
p->nop_cmds[next_nop]->cmd_status = 0;
@@ -1240,11 +1221,11 @@ static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev)
p->xmit_count = next_nop;
{
- long flags;
+ unsigned long flags;
save_flags(flags);
cli();
if(p->xmit_count != p->xmit_last)
- dev->tbusy = 0;
+ netif_wake_queue(dev);
p->lock = 0;
restore_flags(flags);
}
@@ -1283,23 +1264,16 @@ static struct net_device_stats *ni52_get_stats(struct net_device *dev)
/********************************************************
* Set MC list ..
*/
+
static void set_multicast_list(struct net_device *dev)
{
- if(!dev->start)
- {
- printk("%s: Can't apply promiscuous/multicastmode to a not running interface.\n",dev->name);
- return;
- }
-
- dev->start = 0;
-
+ netif_stop_queue(dev);
ni_disint();
alloc586(dev);
init586(dev);
startrecv586(dev);
ni_enaint();
-
- dev->start = 1;
+ netif_wake_queue(dev);
}
#ifdef MODULE
diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c
index 5c671a4ea..2e82ceca5 100644
--- a/drivers/net/ni65.c
+++ b/drivers/net/ni65.c
@@ -228,6 +228,7 @@ static int ni65_open(struct net_device *dev);
static int ni65_lance_reinit(struct net_device *dev);
static void ni65_init_lance(struct priv *p,unsigned char*,int,int);
static int ni65_send_packet(struct sk_buff *skb, struct net_device *dev);
+static void ni65_timeout(struct net_device *dev);
static int ni65_close(struct net_device *dev);
static int ni65_alloc_buffer(struct net_device *dev);
static void ni65_free_buffer(struct priv *p);
@@ -278,16 +279,13 @@ static int ni65_open(struct net_device *dev)
if(ni65_lance_reinit(dev))
{
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue(dev);
MOD_INC_USE_COUNT;
return 0;
}
else
{
free_irq(dev->irq,dev);
- dev->start = 0;
return -EAGAIN;
}
}
@@ -299,6 +297,8 @@ static int ni65_close(struct net_device *dev)
{
struct priv *p = (struct priv *) dev->priv;
+ netif_stop_queue(dev);
+
outw(inw(PORT+L_RESET),PORT+L_RESET); /* that's the hard way */
#ifdef XMT_VIA_SKB
@@ -314,8 +314,6 @@ static int ni65_close(struct net_device *dev)
}
#endif
free_irq(dev->irq,dev);
- dev->tbusy = 1;
- dev->start = 0;
MOD_DEC_USE_COUNT;
return 0;
}
@@ -482,15 +480,13 @@ static int __init ni65_probe1(struct net_device *dev,int ioaddr)
dev->open = ni65_open;
dev->stop = ni65_close;
dev->hard_start_xmit = ni65_send_packet;
+ dev->tx_timeout = ni65_timeout;
+ dev->watchdog_timeo = HZ/2;
dev->get_stats = ni65_get_stats;
dev->set_multicast_list = set_multicast_list;
ether_setup(dev);
- dev->interrupt = 0;
- dev->tbusy = 0;
- dev->start = 0;
-
return 0; /* everything is OK */
}
@@ -714,7 +710,8 @@ static void ni65_stop_start(struct net_device *dev,struct priv *p)
}
p->rmdnum = p->tmdlast = 0;
if(!p->lock)
- dev->tbusy = (p->tmdnum || !p->xmit_queued) ? 0 : 1;
+ if (p->tmdnum || !p->xmit_queued)
+ netif_wake_queue(dev);
dev->trans_start = jiffies;
}
else
@@ -813,15 +810,6 @@ static void ni65_interrupt(int irq, void * dev_id, struct pt_regs * regs)
struct priv *p;
int bcnt = 32;
- if (dev == NULL) {
- printk (KERN_ERR "ni65_interrupt(): irq %d for unknown device.\n", irq);
- return;
- }
-
- if(test_and_set_bit(0,(int *) &dev->interrupt)) {
- printk("ni65: oops .. interrupt while proceeding interrupt\n");
- return;
- }
p = (struct priv *) dev->priv;
while(--bcnt) {
@@ -916,8 +904,6 @@ static void ni65_interrupt(int irq, void * dev_id, struct pt_regs * regs)
else
writedatareg(CSR0_INEA);
- dev->interrupt = 0;
-
return;
}
@@ -974,7 +960,7 @@ static void ni65_xmit_intr(struct net_device *dev,int csr0)
#ifdef XMT_VIA_SKB
if(p->tmd_skb[p->tmdlast]) {
- dev_kfree_skb(p->tmd_skb[p->tmdlast]);
+ dev_kfree_skb_irq(p->tmd_skb[p->tmdlast]);
p->tmd_skb[p->tmdlast] = NULL;
}
#endif
@@ -983,8 +969,7 @@ static void ni65_xmit_intr(struct net_device *dev,int csr0)
if(p->tmdlast == p->tmdnum)
p->xmit_queued = 0;
}
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
}
/*
@@ -1082,32 +1067,31 @@ static void ni65_recv_intr(struct net_device *dev,int csr0)
/*
* kick xmitter ..
*/
-static int ni65_send_packet(struct sk_buff *skb, struct net_device *dev)
+
+static void ni65_timeout(struct net_device *dev)
{
+ int i;
struct priv *p = (struct priv *) dev->priv;
- if(dev->tbusy)
- {
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 50)
- return 1;
+ printk(KERN_ERR "%s: xmitter timed out, try to restart!\n",dev->name);
+ for(i=0;i<TMDNUM;i++)
+ printk("%02x ",p->tmdhead[i].u.s.status);
+ printk("\n");
+ ni65_lance_reinit(dev);
+ dev->trans_start = jiffies;
+ netif_wake_queue(dev);
+}
- printk(KERN_ERR "%s: xmitter timed out, try to restart!\n",dev->name);
- {
- int i;
- for(i=0;i<TMDNUM;i++)
- printk("%02x ",p->tmdhead[i].u.s.status);
- printk("\n");
- }
- ni65_lance_reinit(dev);
- dev->tbusy=0;
- dev->trans_start = jiffies;
- }
+/*
+ * Send a packet
+ */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
- printk(KERN_ERR "%s: Transmitter access conflict.\n", dev->name);
- return 1;
- }
+static int ni65_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+ struct priv *p = (struct priv *) dev->priv;
+
+ netif_stop_queue(dev);
+
if (test_and_set_bit(0, (void*)&p->lock)) {
printk(KERN_ERR "%s: Queue was locked.\n", dev->name);
return 1;
@@ -1152,7 +1136,9 @@ static int ni65_send_packet(struct sk_buff *skb, struct net_device *dev)
p->xmit_queued = 1;
p->tmdnum = (p->tmdnum + 1) & (TMDNUM-1);
- dev->tbusy = (p->tmdnum == p->tmdlast) ? 1 : 0;
+ if(p->tmdnum != p->tmdlast)
+ netif_wake_queue(dev);
+
p->lock = 0;
dev->trans_start = jiffies;
@@ -1183,7 +1169,7 @@ static void set_multicast_list(struct net_device *dev)
{
if(!ni65_lance_reinit(dev))
printk(KERN_ERR "%s: Can't switch card into MC mode!\n",dev->name);
- dev->tbusy = 0;
+ netif_wake_queue(dev);
}
#ifdef MODULE
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 4e4fc4157..2b5624b29 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -105,11 +105,6 @@ MODULE_PARM(irq_mask, "i");
MODULE_PARM(irq_list, "1-4i");
MODULE_PARM(max_interrupt_work, "i");
MODULE_PARM(full_duplex, "i");
-#ifdef BROKEN_FEATURES
-MODULE_PARM(use_fifo_buffer, "i");
-MODULE_PARM(use_memory_ops, "i");
-MODULE_PARM(no_wait, "i");
-#endif
/* Now-standard PC card module parameters. */
static u_int irq_mask = 0xdeb8; /* IRQ3,4,5,7,9,10,11,12,14,15 */
@@ -124,16 +119,6 @@ static int max_interrupt_work = 32;
/* Force full duplex modes? */
static int full_duplex = 0;
-#ifdef BROKEN_FEATURES
-/* Performance features: best left disabled. */
-/* Set to buffer all Tx/RxFIFO accesses. */
-static int use_fifo_buffer = 0;
-/* Set iff memory ops are faster than I/O ops. */
-static int use_memory_ops = 0;
-/* Set iff disabling the WAIT signal is reliable and faster. */
-static int no_wait = 0;
-#endif
-
/* To minimize the size of the driver source and make the driver more
readable not all constants are symbolically defined.
You'll need the manual if you want to understand driver details anyway. */
@@ -220,6 +205,7 @@ struct el3_private {
u_short media_status;
u_short fast_poll;
u_long last_irq;
+ spinlock_t lock;
};
/* Set iff a MII transceiver on any interface requires mdio preamble.
@@ -261,6 +247,7 @@ static int el3_rx(struct net_device *dev, int worklimit);
static int el3_close(struct net_device *dev);
static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static void set_rx_mode(struct net_device *dev);
+static void el3_tx_timeout(struct net_device *dev);
static dev_info_t dev_info = "3c574_cs";
@@ -320,6 +307,8 @@ static dev_link_t *tc574_attach(void)
lp = kmalloc(sizeof(*lp), GFP_KERNEL);
if (!lp) return NULL;
memset(lp, 0, sizeof(*lp));
+
+ lp->lock = SPIN_LOCK_UNLOCKED;
link = &lp->link; dev = &lp->dev;
link->priv = dev->priv = link->irq.Instance = lp;
@@ -351,7 +340,10 @@ static dev_link_t *tc574_attach(void)
dev->init = &tc574_init;
dev->open = &el3_open;
dev->stop = &el3_close;
- dev->tbusy = 1;
+ dev->tx_timeout = el3_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
+ netif_start_queue (dev);
/* Register with Card Services */
link->next = dev_list;
@@ -398,13 +390,12 @@ static void tc574_detach(dev_link_t *link)
if (*linkp == NULL)
return;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&lp->lock, flags);
if (link->state & DEV_RELEASE_PENDING) {
del_timer(&link->release);
link->state &= ~DEV_RELEASE_PENDING;
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&lp->lock, flags);
if (link->state & DEV_CONFIG) {
tc574_release((u_long)link);
@@ -478,31 +469,10 @@ static void tc574_config(dev_link_t *link)
CS_CHECK(RequestIRQ, link->handle, &link->irq);
CS_CHECK(RequestConfiguration, link->handle, &link->conf);
- dev->mem_start = 0;
-#ifdef BROKEN_FEATURES
- if (use_memory_ops) {
- win_req_t req;
- memreq_t mem;
- req.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM |
- WIN_ENABLE | WIN_USE_WAIT;
- req.Base = 0;
- req.Size = 0x1000;
- req.AccessSpeed = 0;
- link->win = (window_handle_t)link->handle;
- i = CardServices(RequestWindow, &link->win, &req);
- if (i == CS_SUCCESS) {
- mem.Page = mem.CardOffset = 0;
- CardServices(MapMemPage, link->win, &mem);
- dev->mem_start = (long)(ioremap(req.Base, 0x1000)) + 0x800;
- } else
- cs_error(link->handle, RequestWindow, i);
- }
-#endif
-
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- dev->tbusy = 0;
+ netif_start_queue (dev);
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n");
goto failed;
@@ -545,10 +515,6 @@ static void tc574_config(dev_link_t *link)
for (i = 0; i < 6; i++)
printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : ".\n"));
- if (dev->mem_start)
- printk(KERN_INFO" Acceleration window at memory base %#lx.\n",
- dev->mem_start);
-
{
u_char mcr, *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
union wn3_config config;
@@ -623,8 +589,6 @@ failed:
static void tc574_release(u_long arg)
{
dev_link_t *link = (dev_link_t *)arg;
- struct el3_private *lp = link->priv;
- struct net_device *dev = &lp->dev;
DEBUG(0, "3c574_release(0x%p)\n", link);
@@ -638,10 +602,6 @@ static void tc574_release(u_long arg)
CardServices(ReleaseConfiguration, link->handle);
CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq);
- if (link->win) {
- iounmap((void *)(dev->mem_start - 0x800));
- CardServices(ReleaseWindow, link->win);
- }
link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
@@ -667,7 +627,7 @@ static int tc574_event(event_t event, int priority,
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
- dev->tbusy = 1; dev->start = 0;
+ netif_device_detach(dev);
link->release.expires = jiffies + HZ/20;
add_timer(&link->release);
}
@@ -681,9 +641,9 @@ static int tc574_event(event_t event, int priority,
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
- if (link->open) {
- dev->tbusy = 1; dev->start = 0;
- }
+ if (link->open)
+ netif_device_detach(dev);
+
CardServices(ReleaseConfiguration, link->handle);
}
break;
@@ -695,7 +655,7 @@ static int tc574_event(event_t event, int priority,
CardServices(RequestConfiguration, link->handle, &link->conf);
if (link->open) {
tc574_reset(dev);
- dev->tbusy = 0; dev->start = 1;
+ netif_device_attach(dev);
}
}
break;
@@ -831,19 +791,6 @@ static void tc574_reset(struct net_device *dev)
wait_for_completion(dev, TotalReset|0x10);
-#ifdef BROKEN_FEATURES
- /* Set the PIO ctrl bits in the PC card LAN COR using Runner window 1. */
- if (dev->mem_start || no_wait) {
- u8 lan_cor;
- outw(1<<11, ioaddr + RunnerRdCtrl);
- lan_cor = inw(ioaddr) & ~0x30;
- if (dev->mem_start) /* Iff use_memory_ops worked! */
- lan_cor |= 0x10;
- if (no_wait)
- lan_cor |= 0x20;
- outw(lan_cor, ioaddr);
- }
-#endif
/* Clear any transactions in progress. */
outw(0, ioaddr + RunnerWrCtrl);
outw(0, ioaddr + RunnerRdCtrl);
@@ -877,10 +824,10 @@ static void tc574_reset(struct net_device *dev)
inb(ioaddr + i);
inw(ioaddr + 10);
inw(ioaddr + 12);
-
EL3WINDOW(4);
- /* New: On the Vortex/Odie we must also clear the BadSSD counter.. */
inb(ioaddr + 12);
+ inb(ioaddr + 13);
+
/* .. enable any extra statistics bits.. */
outw(0x0040, ioaddr + Wn4_NetDiag);
/* .. re-sync MII and re-fill what NWay is advertising. */
@@ -913,7 +860,7 @@ static int el3_open(struct net_device *dev)
link->open++;
MOD_INC_USE_COUNT;
- dev->interrupt = 0; dev->tbusy = 0; dev->start = 1;
+ netif_start_queue (dev);
tc574_reset(dev);
lp->media.function = &media_check;
@@ -939,7 +886,7 @@ static void el3_tx_timeout(struct net_device *dev)
/* Issue TX_RESET and TX_START commands. */
wait_for_completion(dev, TxReset);
outw(TxEnable, ioaddr + EL3_CMD);
- dev->tbusy = 0;
+ netif_start_queue (dev);
}
static void pop_tx_status(struct net_device *dev)
@@ -968,60 +915,22 @@ static void pop_tx_status(struct net_device *dev)
static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
ioaddr_t ioaddr = dev->base_addr;
-#ifdef BROKEN_FEATURES
- long flags = 0;
-#endif
-
- /* Transmitter timeout, serious problems. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
- if (jiffies - dev->trans_start < TX_TIMEOUT)
- return 1;
- el3_tx_timeout(dev);
- }
DEBUG(3, "%s: el3_start_xmit(length = %ld) called, "
"status %4.4x.\n", dev->name, (long)skb->len,
inw(ioaddr + EL3_STATUS));
-#ifdef BROKEN_FEATURES
- if (use_fifo_buffer) {
- /* Avoid other accesses to the chip while RunnerWrCtrl is non-zero. */
- save_flags(flags);
- cli();
- outw((((skb->len + 7)>>2)<<1), ioaddr + RunnerWrCtrl);
- DEBUG(0, "TxFree %x, tx length %x, RunnerWrCtrl is %4.4x.\n",
- inw(ioaddr+TxFree), skb->len, inw(ioaddr+RunnerWrCtrl));
- }
-
- /* Put out the doubleword header... */
- /* ... and the packet rounded to a doubleword. */
- if (dev->mem_start) {
- writew(skb->len, (void *)dev->mem_start);
- writew(0, (void *)dev->mem_start);
- copy_to_pc((void*)dev->mem_start, skb->data, (skb->len+3)&~3);
- } else {
- outw(skb->len, ioaddr + TX_FIFO);
- outw(0, ioaddr + TX_FIFO);
- outsl(ioaddr + TX_FIFO, skb->data, (skb->len+3)>>2);
- }
-
- if (use_fifo_buffer) {
- DEBUG(0, " RunnerWr/RdCtrl is %4.4x/%4.4x, TxFree %x.\n",
- inw(ioaddr + RunnerWrCtrl), inw(ioaddr + RunnerRdCtrl),
- inw(ioaddr + TxFree));
- restore_flags(flags);
- }
-#else
+ netif_stop_queue (dev);
+
outw(skb->len, ioaddr + TX_FIFO);
outw(0, ioaddr + TX_FIFO);
outsl(ioaddr + TX_FIFO, skb->data, (skb->len+3)>>2);
-#endif
dev->trans_start = jiffies;
/* TxFree appears only in Window 1, not offset 0x1c. */
if (inw(ioaddr + TxFree) > 1536) {
- dev->tbusy = 0;
+ netif_start_queue (dev);
} else
/* Interrupt us when the FIFO has room for max-sized packet.
The threshold is in units of dwords. */
@@ -1041,23 +950,20 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
ioaddr_t ioaddr, status;
int work_budget = max_interrupt_work;
- if ((lp == NULL) || !dev->start)
+ if (!netif_device_present(dev))
return;
+
+ spin_lock (&lp->lock);
+
ioaddr = dev->base_addr;
-#ifdef PCMCIA_DEBUG
- if (test_and_set_bit(0, (void*)&dev->interrupt)) {
- printk(KERN_NOTICE "%s: re-entering the interrupt handler.\n",
- dev->name);
- return;
- }
DEBUG(3, "%s: interrupt, status %4.4x.\n",
dev->name, inw(ioaddr + EL3_STATUS));
-#endif
while ((status = inw(ioaddr + EL3_STATUS)) &
(IntLatch | RxComplete | RxEarly | StatsFull)) {
- if ((dev->start == 0) || ((status & 0xe000) != 0x2000)) {
+
+ if (!netif_device_present(dev) || ((status & 0xe000) != 0x2000)) {
DEBUG(1, "%s: Interrupt from dead card\n", dev->name);
break;
}
@@ -1069,8 +975,9 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
DEBUG(3, " TX room bit was handled.\n");
/* There's room in the FIFO for a full-sized packet. */
outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue (dev);
+ } else {
+ netif_stop_queue (dev);
}
if (status & TxComplete)
@@ -1117,12 +1024,10 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
}
-#ifdef PCMCIA_DEBUG
DEBUG(3, "%s: exiting interrupt, status %4.4x.\n",
dev->name, inw(ioaddr + EL3_STATUS));
- dev->interrupt = 0;
-#endif
- return;
+
+ spin_unlock (&lp->lock);
}
/*
@@ -1138,7 +1043,8 @@ static void media_check(u_long arg)
u_long flags;
u_short /* cable, */ media, partner;
- if (dev->start == 0) goto reschedule;
+ if (!netif_device_present(dev))
+ goto reschedule;
/* Check for pending interrupt with expired latency timer: with
this, we can limp along even if the interrupt is blocked */
@@ -1208,7 +1114,7 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev)
{
struct el3_private *lp = (struct el3_private *)dev->priv;
- if (dev->start)
+ if (netif_device_present(dev))
update_stats(dev);
return &lp->stats;
}
@@ -1249,6 +1155,12 @@ static void update_stats(struct net_device *dev)
EL3WINDOW(4);
inb(ioaddr + 12);
+ {
+ u8 up = inb(ioaddr + 13);
+ lp->stats.rx_bytes += (up & 0x0f) << 16;
+ lp->stats.tx_bytes += (up & 0xf0) << 12;
+ }
+
EL3WINDOW(1);
}
@@ -1285,30 +1197,8 @@ static int el3_rx(struct net_device *dev, int worklimit)
skb->dev = dev;
skb_reserve(skb, 2);
-#ifdef BROKEN_FEATURES
- if (use_fifo_buffer) {
- outw(((pkt_len+3)>>2)<<1, ioaddr + RunnerRdCtrl);
- DEBUG(0,"Start Rx %x -- RunnerRdCtrl is %4.4x.\n",
- pkt_len, inw(ioaddr + RunnerRdCtrl));
- }
- if (dev->mem_start) {
- copy_from_pc(skb_put(skb, pkt_len),
- (void*)dev->mem_start, (pkt_len+3)&~3);
- } else {
- insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len),
- ((pkt_len+3)>>2));
- }
- if (use_fifo_buffer) {
- DEBUG(0," RunnerRdCtrl is now %4.4x.\n",
- inw(ioaddr + RunnerRdCtrl));
- outw(0, ioaddr + RunnerRdCtrl);
- DEBUG(0, " Rx packet with data %2.2x:%2.2x:%2.2x\n",
- skb->head[0], skb->head[1], skb->head[2]);
- }
-#else
insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len),
((pkt_len+3)>>2));
-#endif
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
@@ -1404,6 +1294,8 @@ static int el3_close(struct net_device *dev)
DEBUG(2, "%s: shutting down ethercard.\n", dev->name);
+ netif_stop_queue (dev);
+
if (DEV_OK(link)) {
/* Turn off statistics ASAP. We update lp->stats below. */
outw(StatsDisable, ioaddr + EL3_CMD);
@@ -1419,7 +1311,6 @@ static int el3_close(struct net_device *dev)
}
link->open--;
- dev->start = 0;
del_timer(&lp->media);
if (link->state & DEV_STALE_CONFIG) {
link->release.expires = jiffies + HZ/20;
diff --git a/drivers/net/pcmcia/3c575_cb.c b/drivers/net/pcmcia/3c575_cb.c
index 82f534f0c..e98e1eda8 100644
--- a/drivers/net/pcmcia/3c575_cb.c
+++ b/drivers/net/pcmcia/3c575_cb.c
@@ -53,18 +53,7 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits;
#error You must compile this driver with "-O".
#endif
-#include <linux/config.h>
-#include <linux/version.h>
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
#include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
@@ -89,13 +78,6 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits;
#include <linux/delay.h>
-#define PCI_SUPPORT_VER2
-#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
-#if ! defined(CAP_NET_ADMIN)
-#define capable(CAP_XXX) (suser())
-#endif
-
-#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_DESCRIPTION("3Com 3c590/3c900 series Vortex/Boomerang driver");
MODULE_PARM(debug, "i");
@@ -106,7 +88,6 @@ MODULE_PARM(max_interrupt_work, "i");
MODULE_PARM(compaq_ioaddr, "i");
MODULE_PARM(compaq_irq, "i");
MODULE_PARM(compaq_device_id, "i");
-#endif
/* Operational parameter that usually are not changed. */
@@ -209,15 +190,15 @@ struct pci_id_info {
const char *name;
u16 vendor_id, device_id, device_id_mask, flags;
int drv_flags, io_size;
- struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev,
- long ioaddr, int irq, int chip_idx, int fnd_cnt);
+ struct net_device *(*probe1)(struct pci_dev *pdev, struct net_device *dev,
+ long ioaddr, int irq, int chip_idx, int fnd_cnt);
};
enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4,
HAS_PWR_CTRL=0x10, HAS_MII=0x20, HAS_NWAY=0x40, HAS_CB_FNS=0x80, };
-static struct net_device *vortex_probe1(int pci_bus, int pci_devfn,
- struct net_device *dev, long ioaddr,
- int irq, int dev_id, int card_idx);
+static struct net_device *vortex_probe1(struct pci_dev *pdev,
+ struct net_device *dev, long ioaddr,
+ int irq, int dev_id, int card_idx);
static struct pci_id_info pci_tbl[] = {
{"3c590 Vortex 10Mbps", 0x10B7, 0x5900, 0xffff,
PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
@@ -427,7 +408,7 @@ struct vortex_private {
struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */
/* PCI configuration space information. */
- u8 pci_bus, pci_devfn; /* PCI bus location, for power management. */
+ struct pci_dev *pdev;
char *cb_fn_base; /* CardBus function status addr space. */
int chip_id;
@@ -451,6 +432,7 @@ struct vortex_private {
u16 advertising; /* NWay media advertisement */
unsigned char phys[2]; /* MII device addresses. */
u16 deferred;
+ spinlock_t lock;
};
/* The action to take with a media selection timer tick.
@@ -501,7 +483,8 @@ static void update_stats(long ioaddr, struct net_device *dev);
static struct net_device_stats *vortex_get_stats(struct net_device *dev);
static void set_rx_mode(struct net_device *dev);
static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static void acpi_wake(int pci_bus, int pci_devfn);
+static void vortex_tx_timeout(struct net_device *dev);
+static void acpi_wake(struct pci_dev *pdev);
static void acpi_set_WOL(struct net_device *dev);
/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
@@ -542,20 +525,21 @@ static dev_node_t *vortex_attach(dev_locator_t *loc)
{
u16 dev_id, vendor_id;
u32 io;
- u8 bus, devfn, irq;
+ u8 irq;
struct net_device *dev;
int chip_idx;
+ struct pci_dev *pdev;
vortex_reap();
if (loc->bus != LOC_PCI) return NULL;
- bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
- pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
- pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
- pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor_id);
- pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
+ pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn);
+ if (!pdev) return NULL;
+ io = pci_resource_start (pdev, 0);
+ irq = pdev->irq;
+ vendor_id = pdev->vendor;
+ dev_id = pdev->device;
printk(KERN_INFO "vortex_attach(bus %d, function %d, device %4.4x)\n",
- bus, devfn, dev_id);
- io &= ~3;
+ pdev->bus->number, pdev->devfn, dev_id);
if (io == 0 || irq == 0) {
printk(KERN_ERR "The 3Com CardBus Ethernet interface was not "
"assigned an %s.\n" KERN_ERR " It will not be activated.\n",
@@ -572,7 +556,7 @@ static dev_node_t *vortex_attach(dev_locator_t *loc)
"vortex_attach().\n", vendor_id, dev_id);
return NULL;
}
- dev = vortex_probe1(bus, devfn, NULL, io, irq, chip_idx, MAX_UNITS+1);
+ dev = vortex_probe1(pdev, NULL, io, irq, chip_idx, MAX_UNITS+1);
if (dev) {
dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
strcpy(node->dev_name, dev->name);
@@ -663,44 +647,6 @@ static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[])
int cards_found = 0;
/* Allow an EISA-only driver. */
-#if defined(CONFIG_PCI) || (defined(MODULE) && !defined(NO_PCI))
- /* Ideally we would detect all cards in slot order. That would
- be best done a central PCI probe dispatch, which wouldn't work
- well with the current structure. So instead we detect 3Com cards
- in slot order. */
- if (pcibios_present()) {
- static int pci_index = 0;
- unsigned char pci_bus, pci_device_fn;
-
- for (;pci_index < 0xff; pci_index++) {
- u16 vendor, device, pci_command, new_command;
- int chip_idx, irq;
- long ioaddr;
-
- if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index,
- &pci_bus, &pci_device_fn)
- != PCIBIOS_SUCCESSFUL)
- break;
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_VENDOR_ID, &vendor);
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_DEVICE_ID, &device);
- for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
- if (vendor == pci_tbl[chip_idx].vendor_id
- && (device & pci_tbl[chip_idx].device_id_mask) ==
- pci_tbl[chip_idx].device_id)
- break;
- if (pci_tbl[chip_idx].vendor_id == 0) /* Compiled out! */
- continue;
-
- /* The Cyclone requires config space re-write if powered down. */
- acpi_wake(pci_bus, pci_device_fn);
-
- {
- struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
- ioaddr = pdev->resource[0].start;
- irq = pdev->irq;
-#elif LINUX_VERSION_CODE >= 0x20155
struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
ioaddr = pdev->base_address[0] & ~3;
irq = pdev->irq;
@@ -751,7 +697,6 @@ static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[])
}
}
}
-#endif /* NO_PCI */
/* Now check all slots of the EISA bus. */
if (EISA_bus) {
@@ -787,9 +732,9 @@ static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[])
}
#endif /* ! Cardbus */
-static struct net_device *vortex_probe1(int pci_bus, int pci_devfn,
- struct net_device *dev, long ioaddr,
- int irq, int chip_idx, int card_idx)
+static struct net_device *vortex_probe1(struct pci_dev *pdev,
+ struct net_device *dev, long ioaddr,
+ int irq, int chip_idx, int card_idx)
{
struct vortex_private *vp;
int option;
@@ -817,9 +762,9 @@ static struct net_device *vortex_probe1(int pci_bus, int pci_devfn,
vp->next_module = root_vortex_dev;
root_vortex_dev = dev;
+ vp->lock = SPIN_LOCK_UNLOCKED;
vp->chip_id = chip_idx;
- vp->pci_bus = pci_bus;
- vp->pci_devfn = pci_devfn;
+ vp->pdev = pdev;
/* The lower four bits are the media type. */
if (dev->mem_start)
@@ -892,10 +837,9 @@ static struct net_device *vortex_probe1(int pci_bus, int pci_devfn,
if (pci_tbl[vp->chip_id].drv_flags & HAS_CB_FNS) {
u32 fn_st_addr; /* Cardbus function status space */
- pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_2,
- &fn_st_addr);
+ fn_st_addr = pci_resource_start (pdev, 2);
if (fn_st_addr)
- vp->cb_fn_base = ioremap(fn_st_addr & ~3, 128);
+ vp->cb_fn_base = ioremap(fn_st_addr, 128);
printk(KERN_INFO "%s: CardBus functions mapped %8.8x->%p\n",
dev->name, fn_st_addr, vp->cb_fn_base);
}
@@ -988,6 +932,8 @@ static struct net_device *vortex_probe1(int pci_bus, int pci_devfn,
dev->get_stats = &vortex_get_stats;
dev->do_ioctl = &vortex_ioctl;
dev->set_multicast_list = &set_rx_mode;
+ dev->tx_timeout = vortex_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
return dev;
}
@@ -1013,7 +959,7 @@ vortex_up(struct net_device *dev)
int i;
/* Should be if(HAS_ACPI) */
- acpi_wake(vp->pci_bus, vp->pci_devfn);
+ acpi_wake(vp->pdev);
/* Before initializing select the active media port. */
EL3WINDOW(3);
@@ -1157,9 +1103,7 @@ vortex_up(struct net_device *dev)
outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
vp->in_interrupt = 0;
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue (dev);
outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
@@ -1377,8 +1321,10 @@ static void vortex_tx_timeout(struct net_device *dev)
ioaddr + DownListPtr);
if (vp->tx_full && (vp->cur_tx - vp->dirty_tx <= TX_RING_SIZE - 1)) {
vp->tx_full = 0;
- clear_bit(0, (void*)&dev->tbusy);
+ netif_start_queue (dev);
}
+ if (vp->tx_full)
+ netif_stop_queue (dev);
outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
outw(DownUnstall, ioaddr + EL3_CMD);
} else
@@ -1478,12 +1424,8 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct vortex_private *vp = (struct vortex_private *)dev->priv;
long ioaddr = dev->base_addr;
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
- if (jiffies - dev->trans_start >= TX_TIMEOUT)
- vortex_tx_timeout(dev);
- return 1;
- }
-
+ netif_stop_queue (dev);
+
/* Put out the doubleword header... */
outl(skb->len, ioaddr + TX_FIFO);
if (vp->bus_master) {
@@ -1496,9 +1438,9 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
} else {
/* ... and the packet rounded to a doubleword. */
outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
- DEV_FREE_SKB(skb);
+ dev_kfree_skb (skb);
if (inw(ioaddr + TxFree) > 1536) {
- clear_bit(0, (void*)&dev->tbusy);
+ netif_start_queue (dev);
} else
/* Interrupt us when the FIFO has room for max-sized packet. */
outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
@@ -1535,11 +1477,8 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct vortex_private *vp = (struct vortex_private *)dev->priv;
long ioaddr = dev->base_addr;
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
- if (jiffies - dev->trans_start >= TX_TIMEOUT)
- vortex_tx_timeout(dev);
- return 1;
- } else {
+ netif_stop_queue (dev);
+ if (1) {
/* Calculate the next Tx descriptor entry. */
int entry = vp->cur_tx % TX_RING_SIZE;
struct boom_tx_desc *prev_entry =
@@ -1561,8 +1500,7 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG);
vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&vp->lock, flags);
/* Wait for the stall to complete. */
wait_for_completion(dev, DownStall);
prev_entry->next = cpu_to_le32(virt_to_bus(&vp->tx_ring[entry]));
@@ -1571,16 +1509,17 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
queued_packet++;
}
outw(DownUnstall, ioaddr + EL3_CMD);
- restore_flags(flags);
+ spin_unlock_irqrestore(&vp->lock, flags);
vp->cur_tx++;
- if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1)
+ if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1) {
vp->tx_full = 1;
- else { /* Clear previous interrupt enable. */
+ netif_stop_queue (dev);
+ } else { /* Clear previous interrupt enable. */
#if defined(tx_interrupt_mitigation)
prev_entry->status &= cpu_to_le32(~TxIntrUploaded);
#endif
- clear_bit(0, (void*)&dev->tbusy);
+ netif_start_queue (dev);
}
dev->trans_start = jiffies;
return 0;
@@ -1597,23 +1536,8 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
int latency, status;
int work_done = max_interrupt_work;
-#if defined(__i386__)
- /* A lock to prevent simultaneous entry bug on Intel SMP machines. */
- if (test_and_set_bit(0, (void*)&dev->interrupt)) {
- printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
- dev->name);
- dev->interrupt = 0; /* Avoid halting machine. */
- return;
- }
-#else
- if (dev->interrupt) {
- printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
- return;
- }
- dev->interrupt = 1;
-#endif
-
- dev->interrupt = 1;
+ spin_lock (&vp->lock);
+
ioaddr = dev->base_addr;
latency = inb(ioaddr + Timer);
status = inw(ioaddr + EL3_STATUS);
@@ -1643,8 +1567,7 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
printk(KERN_DEBUG " TX room bit was handled.\n");
/* There's room in the FIFO for a full-sized packet. */
outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
- clear_bit(0, (void*)&dev->tbusy);
- mark_bh(NET_BH);
+ netif_wake_queue (dev);
}
if (status & DownComplete) {
@@ -1657,7 +1580,7 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
virt_to_bus(&vp->tx_ring[entry]))
break; /* It still hasn't been processed. */
if (vp->tx_skbuff[entry]) {
- DEV_FREE_SKB(vp->tx_skbuff[entry]);
+ dev_kfree_skb_irq(vp->tx_skbuff[entry]);
vp->tx_skbuff[entry] = 0;
}
/* vp->stats.tx_packets++; Counted below. */
@@ -1666,19 +1589,21 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
vp->dirty_tx = dirty_tx;
if (vp->tx_full && (vp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) {
vp->tx_full = 0;
- clear_bit(0, (void*)&dev->tbusy);
- mark_bh(NET_BH);
+ netif_wake_queue (dev);
}
}
+ if (vp->tx_full)
+ netif_stop_queue (dev);
if (status & DMADone) {
if (inw(ioaddr + Wn7_MasterStatus) & 0x1000) {
outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
- DEV_FREE_SKB(vp->tx_skb); /* Release the transfered buffer */
+ dev_kfree_skb_irq(vp->tx_skb); /* Release the transfered buffer */
if (inw(ioaddr + TxFree) > 1536) {
- clear_bit(0, (void*)&dev->tbusy);
- mark_bh(NET_BH);
- } else /* Interrupt when FIFO has room for max-sized packet. */
+ netif_wake_queue (dev);
+ } else { /* Interrupt when FIFO has room for max-sized packet. */
outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
+ netif_stop_queue (dev);
+ }
}
}
/* Check for all uncommon interrupts at once. */
@@ -1715,12 +1640,7 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
dev->name, status);
handler_exit:
-#if defined(__i386__)
- clear_bit(0, (void*)&dev->interrupt);
-#else
- dev->interrupt = 0;
-#endif
- return;
+ spin_unlock (&vp->lock);
}
static int vortex_rx(struct net_device *dev)
@@ -1891,8 +1811,7 @@ vortex_down(struct net_device *dev)
struct vortex_private *vp = (struct vortex_private *)dev->priv;
long ioaddr = dev->base_addr;
- dev->start = 0;
- dev->tbusy = 1;
+ netif_stop_queue (dev);
del_timer(&vp->timer);
@@ -1926,7 +1845,7 @@ vortex_close(struct net_device *dev)
long ioaddr = dev->base_addr;
int i;
- if (dev->start)
+ if (netif_device_present(dev))
vortex_down(dev);
if (vortex_debug > 1) {
@@ -1942,14 +1861,14 @@ vortex_close(struct net_device *dev)
if (vp->full_bus_master_rx) { /* Free Boomerang bus master Rx buffers. */
for (i = 0; i < RX_RING_SIZE; i++)
if (vp->rx_skbuff[i]) {
- DEV_FREE_SKB(vp->rx_skbuff[i]);
+ dev_kfree_skb(vp->rx_skbuff[i]);
vp->rx_skbuff[i] = 0;
}
}
if (vp->full_bus_master_tx) { /* Free Boomerang bus master Tx buffers. */
for (i = 0; i < TX_RING_SIZE; i++)
if (vp->tx_skbuff[i]) {
- DEV_FREE_SKB(vp->tx_skbuff[i]);
+ dev_kfree_skb(vp->tx_skbuff[i]);
vp->tx_skbuff[i] = 0;
}
}
@@ -1964,11 +1883,10 @@ static struct net_device_stats *vortex_get_stats(struct net_device *dev)
struct vortex_private *vp = (struct vortex_private *)dev->priv;
unsigned long flags;
- if (dev->start) {
- save_flags(flags);
- cli();
+ if (netif_device_present(dev)) {
+ spin_lock_irqsave (&vp->lock, flags);
update_stats(dev->base_addr, dev);
- restore_flags(flags);
+ spin_unlock_irqrestore (&vp->lock, flags);
}
return &vp->stats;
}
@@ -2168,35 +2086,35 @@ static void acpi_set_WOL(struct net_device *dev)
outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
outw(RxEnable, ioaddr + EL3_CMD);
/* Change the power state to D3; RxEnable doesn't take effect. */
- pcibios_write_config_word(vp->pci_bus, vp->pci_devfn, 0xe0, 0x8103);
+ pci_write_config_word(vp->pdev, 0xe0, 0x8103);
}
/* Change from D3 (sleep) to D0 (active).
Problem: The Cyclone forgets all PCI config info during the transition! */
-static void acpi_wake(int bus, int devfn)
+static void acpi_wake(struct pci_dev *pdev)
{
u32 base0, base1, romaddr;
u16 pci_command, pwr_command;
u8 pci_latency, pci_cacheline, irq;
- pcibios_read_config_word(bus, devfn, 0xe0, &pwr_command);
+ pci_read_config_word(pdev, 0xe0, &pwr_command);
if ((pwr_command & 3) == 0)
return;
- pcibios_read_config_word( bus, devfn, PCI_COMMAND, &pci_command);
- pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &base0);
- pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_1, &base1);
- pcibios_read_config_dword(bus, devfn, PCI_ROM_ADDRESS, &romaddr);
- pcibios_read_config_byte( bus, devfn, PCI_LATENCY_TIMER, &pci_latency);
- pcibios_read_config_byte( bus, devfn, PCI_CACHE_LINE_SIZE, &pci_cacheline);
- pcibios_read_config_byte( bus, devfn, PCI_INTERRUPT_LINE, &irq);
-
- pcibios_write_config_word( bus, devfn, 0xe0, 0x0000);
- pcibios_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, base0);
- pcibios_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_1, base1);
- pcibios_write_config_dword(bus, devfn, PCI_ROM_ADDRESS, romaddr);
- pcibios_write_config_byte( bus, devfn, PCI_INTERRUPT_LINE, irq);
- pcibios_write_config_byte( bus, devfn, PCI_LATENCY_TIMER, pci_latency);
- pcibios_write_config_byte( bus, devfn, PCI_CACHE_LINE_SIZE, pci_cacheline);
- pcibios_write_config_word( bus, devfn, PCI_COMMAND, pci_command | 5);
+ pci_read_config_word( pdev, PCI_COMMAND, &pci_command);
+ pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &base0);
+ pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1, &base1);
+ pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &romaddr);
+ pci_read_config_byte( pdev, PCI_LATENCY_TIMER, &pci_latency);
+ pci_read_config_byte( pdev, PCI_CACHE_LINE_SIZE, &pci_cacheline);
+ pci_read_config_byte( pdev, PCI_INTERRUPT_LINE, &irq);
+
+ pci_write_config_word( pdev, 0xe0, 0x0000);
+ pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, base0);
+ pci_write_config_dword(pdev, PCI_BASE_ADDRESS_1, base1);
+ pci_write_config_dword(pdev, PCI_ROM_ADDRESS, romaddr);
+ pci_write_config_byte( pdev, PCI_INTERRUPT_LINE, irq);
+ pci_write_config_byte( pdev, PCI_LATENCY_TIMER, pci_latency);
+ pci_write_config_byte( pdev, PCI_CACHE_LINE_SIZE, pci_cacheline);
+ pci_write_config_word( pdev, PCI_COMMAND, pci_command | 5);
}
#ifdef MODULE
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index e95b87104..33b1dbc60 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -4,7 +4,7 @@
Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org
- 3c589_cs.c 1.143 1999/12/30 21:28:10
+ 3c589_cs.c 1.145 2000/02/11 03:11:51
The network driver code is based on Donald Becker's 3c589 code:
@@ -117,7 +117,7 @@ static int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"3c589_cs.c 1.143 1999/12/30 21:28:10 (David Hinds)";
+"3c589_cs.c 1.145 2000/02/11 03:11:51 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
@@ -155,6 +155,7 @@ static void update_stats(struct net_device *dev);
static struct net_device_stats *el3_get_stats(struct net_device *dev);
static int el3_rx(struct net_device *dev);
static int el3_close(struct net_device *dev);
+static void el3_tx_timeout(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
@@ -257,7 +258,10 @@ static dev_link_t *tc589_attach(void)
dev->init = &tc589_init;
dev->open = &el3_open;
dev->stop = &el3_close;
- dev->tbusy = 1;
+ dev->tx_timeout = el3_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
+ netif_start_queue (dev);
/* Register with Card Services */
link->next = dev_list;
@@ -399,7 +403,7 @@ static void tc589_config(dev_link_t *link)
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- dev->tbusy = 0;
+ netif_start_queue (dev);
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "3c589_cs: register_netdev() failed\n");
goto failed;
@@ -508,7 +512,7 @@ static int tc589_event(event_t event, int priority,
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
- dev->tbusy = 1; dev->start = 0;
+ netif_device_detach(dev);
link->release.expires = jiffies + HZ/20;
add_timer(&link->release);
}
@@ -522,9 +526,9 @@ static int tc589_event(event_t event, int priority,
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
- if (link->open) {
- dev->tbusy = 1; dev->start = 0;
- }
+ if (link->open)
+ netif_device_detach(dev);
+
CardServices(ReleaseConfiguration, link->handle);
}
break;
@@ -536,7 +540,7 @@ static int tc589_event(event_t event, int priority,
CardServices(RequestConfiguration, link->handle, &link->conf);
if (link->open) {
tc589_reset(dev);
- dev->tbusy = 0; dev->start = 1;
+ netif_device_attach(dev);
}
}
break;
@@ -683,7 +687,7 @@ static int el3_open(struct net_device *dev)
link->open++;
MOD_INC_USE_COUNT;
- dev->interrupt = 0; dev->tbusy = 0; dev->start = 1;
+ netif_start_queue (dev);
tc589_reset(dev);
lp->media.function = &media_check;
@@ -709,7 +713,7 @@ static void el3_tx_timeout(struct net_device *dev)
/* Issue TX_RESET and TX_START commands. */
wait_for_completion(dev, TxReset);
outw(TxEnable, ioaddr + EL3_CMD);
- dev->tbusy = 0;
+ netif_start_queue (dev);
}
static void pop_tx_status(struct net_device *dev)
@@ -739,37 +743,27 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
ioaddr_t ioaddr = dev->base_addr;
- /* Transmitter timeout, serious problems. */
- if (dev->tbusy) {
- if (jiffies - dev->trans_start < TX_TIMEOUT)
- return 1;
- el3_tx_timeout(dev);
- }
-
DEBUG(3, "%s: el3_start_xmit(length = %ld) called, "
"status %4.4x.\n", dev->name, (long)skb->len,
inw(ioaddr + EL3_STATUS));
- /* Avoid timer-based retransmission conflicts. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk(KERN_NOTICE "%s: transmitter access conflict.\n",
- dev->name);
- else {
+ netif_stop_queue (dev);
+ {
struct el3_private *lp = (struct el3_private *)dev->priv;
lp->stats.tx_bytes += skb->len;
- /* Put out the doubleword header... */
- outw(skb->len, ioaddr + TX_FIFO);
- outw(0x00, ioaddr + TX_FIFO);
- /* ... and the packet rounded to a doubleword. */
- outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
-
- dev->trans_start = jiffies;
- if (inw(ioaddr + TX_FREE) > 1536) {
- dev->tbusy = 0;
- } else
- /* Interrupt us when the FIFO has room for max-sized packet. */
- outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
}
+ /* Put out the doubleword header... */
+ outw(skb->len, ioaddr + TX_FIFO);
+ outw(0x00, ioaddr + TX_FIFO);
+ /* ... and the packet rounded to a doubleword. */
+ outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+
+ dev->trans_start = jiffies;
+ if (inw(ioaddr + TX_FREE) > 1536) {
+ netif_start_queue (dev);
+ } else
+ /* Interrupt us when the FIFO has room for max-sized packet. */
+ outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
dev_kfree_skb(skb);
pop_tx_status(dev);
@@ -785,24 +779,17 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
ioaddr_t ioaddr, status;
int i = 0;
- if ((lp == NULL) || !dev->start)
+ if (!netif_device_present(dev))
return;
ioaddr = dev->base_addr;
-#ifdef PCMCIA_DEBUG
- if (dev->interrupt) {
- printk(KERN_NOTICE "%s: re-entering the interrupt handler.\n",
- dev->name);
- return;
- }
- dev->interrupt = 1;
DEBUG(3, "%s: interrupt, status %4.4x.\n",
dev->name, inw(ioaddr + EL3_STATUS));
-#endif
while ((status = inw(ioaddr + EL3_STATUS)) &
(IntLatch | RxComplete | StatsFull)) {
- if ((dev->start == 0) || ((status & 0xe000) != 0x2000)) {
+ if (!netif_device_present(dev)) ||
+ ((status & 0xe000) != 0x2000)) {
DEBUG(1, "%s: interrupt from dead card\n", dev->name);
break;
}
@@ -814,8 +801,7 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
DEBUG(3, " TX room bit was handled.\n");
/* There's room in the FIFO for a full-sized packet. */
outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue (dev);
}
if (status & TxComplete)
@@ -863,11 +849,8 @@ static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
lp->last_irq = jiffies;
-#ifdef PCMCIA_DEBUG
DEBUG(3, "%s: exiting interrupt, status %4.4x.\n",
dev->name, inw(ioaddr + EL3_STATUS));
- dev->interrupt = 0;
-#endif
return;
}
@@ -879,7 +862,8 @@ static void media_check(u_long arg)
u_short media, errs;
u_long flags;
- if (dev->start == 0) goto reschedule;
+ if (!netif_device_present(dev))
+ goto reschedule;
EL3WINDOW(1);
/* Check for pending interrupt with expired latency timer: with
@@ -1093,6 +1077,8 @@ static int el3_close(struct net_device *dev)
ioaddr_t ioaddr = dev->base_addr;
DEBUG(1, "%s: shutting down ethercard.\n", dev->name);
+
+ netif_stop_queue (dev);
if (DEV_OK(link)) {
/* Turn off statistics ASAP. We update lp->stats below. */
@@ -1122,7 +1108,6 @@ static int el3_close(struct net_device *dev)
}
link->open--;
- dev->start = 0;
del_timer(&lp->media);
if (link->state & DEV_STALE_CONFIG) {
link->release.expires = jiffies + HZ/20;
diff --git a/drivers/net/pcmcia/Config.in b/drivers/net/pcmcia/Config.in
index 243b5c896..2a3011532 100644
--- a/drivers/net/pcmcia/Config.in
+++ b/drivers/net/pcmcia/Config.in
@@ -20,7 +20,6 @@ if [ "$CONFIG_NET_PCMCIA" = "y" ]; then
if [ "$CONFIG_CARDBUS" = "y" ]; then
dep_tristate ' 3Com 3c575 CardBus support' CONFIG_PCMCIA_3C575 m
dep_tristate ' DEC Tulip CardBus support' CONFIG_PCMCIA_TULIP m
- dep_tristate ' SMC EPIC CardBus support' CONFIG_PCMCIA_EPIC100 m
fi
bool 'Pcmcia Wireless LAN' CONFIG_NET_PCMCIA_RADIO
diff --git a/drivers/net/pcmcia/Makefile b/drivers/net/pcmcia/Makefile
index dfd4ef186..11c583dac 100644
--- a/drivers/net/pcmcia/Makefile
+++ b/drivers/net/pcmcia/Makefile
@@ -41,7 +41,6 @@ obj-$(CONFIG_AIRONET4500_CS) += aironet4500_cs.o
# Cardbus client drivers
obj-$(CONFIG_PCMCIA_3C575) += 3c575_cb.o
obj-$(CONFIG_PCMCIA_TULIP) += tulip_cb.o
-obj-$(CONFIG_PCMCIA_EPIC100) += epic100_cb.o
O_OBJS := $(filter-out $(export-objs), $(obj-y))
OX_OBJS := $(filter $(export-objs), $(obj-y))
@@ -49,6 +48,3 @@ M_OBJS := $(filter-out $(export-objs), $(obj-m))
MX_OBJS := $(filter $(export-objs), $(obj-m))
include $(TOPDIR)/Rules.make
-
-epic100_cb.o: ../epic100.c
- $(CC) $(CFLAGS) -DMODULE -DCARDBUS -c -o $@ ../epic100.c
diff --git a/drivers/net/pcmcia/aironet4500_cs.c b/drivers/net/pcmcia/aironet4500_cs.c
index 3dbb9923f..2acd2e46a 100644
--- a/drivers/net/pcmcia/aironet4500_cs.c
+++ b/drivers/net/pcmcia/aironet4500_cs.c
@@ -231,8 +231,7 @@ static dev_link_t *awc_attach(void)
dev->init = &awc_pcmcia_init;
dev->open = &awc_pcmcia_open;
dev->stop = &awc_pcmcia_close;
- dev->tbusy = 1;
- dev->start = 0;
+ netif_start_queue (dev);
link->priv = dev;
#if CS_RELEASE_CODE > 0x2911
@@ -567,7 +566,7 @@ static int awc_event(event_t event, int priority,
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
- dev->tbusy = 1; dev->start = 0;
+ netif_device_detach(dev);
link->release.expires = RUN_AT( HZ/20 );
add_timer(&link->release);
}
@@ -581,9 +580,9 @@ static int awc_event(event_t event, int priority,
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
- if (link->open) {
- dev->tbusy = 1; dev->start = 0;
- }
+ if (link->open)
+ netif_device_detach(dev);
+
CardServices(ReleaseConfiguration, link->handle);
}
break;
@@ -595,7 +594,7 @@ static int awc_event(event_t event, int priority,
CardServices(RequestConfiguration, link->handle, &link->conf);
if (link->open) {
// awc_reset(dev);
- dev->tbusy = 0; dev->start = 1;
+ netif_device_attach(dev);
}
}
break;
@@ -637,4 +636,4 @@ void cleanup_module(void)
// awc_detach(dev_list);
}
- \ No newline at end of file
+
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 9dd2c188e..a975a4df2 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -115,6 +115,7 @@ static void fjn_rx(struct net_device *dev);
static void fjn_reset(struct net_device *dev);
static struct net_device_stats *fjn_get_stats(struct net_device *dev);
static void set_rx_mode(struct net_device *dev);
+static void fjn_tx_timeout (struct net_device *dev);
static dev_info_t dev_info = "fmvj18x_cs";
static dev_link_t *dev_list = NULL;
@@ -139,6 +140,7 @@ typedef struct local_info_t {
cardtype_t cardtype;
u_short sent;
u_char mc_filter[8];
+ spinlock_t lock;
} local_info_t;
#define MC_FILTERBREAK 64
@@ -235,6 +237,8 @@ typedef struct local_info_t {
#define INTR_OFF 0x0d /* LAN controler ignores interrupts */
#define INTR_ON 0x1d /* LAN controler will catch interrupts */
+#define TX_TIMEOUT 10
+
/*======================================================================
This bit of code is used to avoid unregistering network devices
@@ -278,6 +282,8 @@ static dev_link_t *fmvj18x_attach(void)
lp = kmalloc(sizeof(*lp), GFP_KERNEL);
if (!lp) return NULL;
memset(lp, 0, sizeof(*lp));
+
+ lp->lock = SPIN_LOCK_UNLOCKED;
link = &lp->link; dev = &lp->dev;
link->priv = dev->priv = link->irq.Instance = lp;
@@ -314,7 +320,9 @@ static dev_link_t *fmvj18x_attach(void)
dev->init = &fmvj18x_init;
dev->open = &fjn_open;
dev->stop = &fjn_close;
- dev->tbusy = 0xFF;
+ dev->tx_timeout = fjn_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+ netif_start_queue (dev);
/* Register with Card Services */
link->next = dev_list;
@@ -462,7 +470,7 @@ static void fmvj18x_config(dev_link_t *link)
CS_CHECK(RequestConfiguration, link->handle, &link->conf);
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- dev->tbusy = 0;
+ netif_start_queue (dev);
if (register_netdev(dev) != 0) {
printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
goto failed;
@@ -585,8 +593,7 @@ static int fmvj18x_event(event_t event, int priority,
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
- dev->tbusy = 0xFF;
- dev->start = 0;
+ netif_device_detach(dev);
link->release.expires = jiffies + HZ/20;
add_timer(&link->release);
}
@@ -600,10 +607,9 @@ static int fmvj18x_event(event_t event, int priority,
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
- if (link->open) {
- dev->tbusy = 0xFF;
- dev->start = 0;
- }
+ if (link->open)
+ netif_device_detach(dev);
+
CardServices(ReleaseConfiguration, link->handle);
}
break;
@@ -614,9 +620,8 @@ static int fmvj18x_event(event_t event, int priority,
if (link->state & DEV_CONFIG) {
CardServices(RequestConfiguration, link->handle, &link->conf);
if (link->open) {
- dev->tbusy = 0;
- dev->start = 1;
fjn_reset(dev);
+ netif_device_attach(dev);
}
}
break;
@@ -670,12 +675,9 @@ static void fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
"unknown device.\n", irq);
return;
}
- if (dev->interrupt) {
- printk(KERN_NOTICE "%s: re-entering the interrupt handler.\n",
- dev->name);
- return;
- }
- dev->interrupt = 1;
+
+ spin_lock (&lp->lock);
+
ioaddr = dev->base_addr;
/* avoid multiple interrupts */
@@ -708,71 +710,65 @@ static void fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
lp->tx_queue = 0;
lp->tx_queue_len = 0;
dev->trans_start = jiffies;
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_wake_queue (dev);
} else {
lp->tx_started = 0;
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_stop_queue (dev);
}
}
DEBUG(4, "%s: exiting interrupt,\n", dev->name);
DEBUG(4, " tx_status %02x, rx_status %02x.\n", tx_stat, rx_stat);
- dev->interrupt = 0;
outb(D_TX_INTR, ioaddr + TX_INTR);
outb(D_RX_INTR, ioaddr + RX_INTR);
- return;
+ spin_unlock (&lp->lock);
+
} /* fjn_interrupt */
/*====================================================================*/
-
-static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static void fjn_tx_timeout (struct net_device *dev)
{
- struct local_info_t *lp = (struct local_info_t *)dev->priv;
- ioaddr_t ioaddr = dev->base_addr;
-
- if (dev->tbusy) {
- /* If we get here, some higher level has decided we are broken.
- There should really be a "kick me" function call instead. */
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 10)
- return 1;
- printk(KERN_NOTICE "%s: transmit timed out with status %04x, %s?\n",
- dev->name, htons(inw(ioaddr + TX_STATUS)),
- inb(ioaddr + TX_STATUS) & F_TMT_RDY
- ? "IRQ conflict" : "network cable problem");
- printk(KERN_NOTICE "%s: timeout registers: %04x %04x %04x "
- "%04x %04x %04x %04x %04x.\n",
- dev->name, htons(inw(ioaddr + 0)),
- htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
- htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
- htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
- htons(inw(ioaddr +14)));
+ struct local_info_t *lp = (struct local_info_t *) dev->priv;
+ ioaddr_t ioaddr = dev->base_addr;
+ unsigned long flags;
+
+ printk (KERN_NOTICE "%s: transmit timed out with status %04x, %s?\n",
+ dev->name, htons (inw (ioaddr + TX_STATUS)),
+ inb (ioaddr + TX_STATUS) & F_TMT_RDY
+ ? "IRQ conflict" : "network cable problem");
+ printk (KERN_NOTICE "%s: timeout registers: %04x %04x %04x "
+ "%04x %04x %04x %04x %04x.\n",
+ dev->name, htons (inw (ioaddr + 0)),
+ htons (inw (ioaddr + 2)), htons (inw (ioaddr + 4)),
+ htons (inw (ioaddr + 6)), htons (inw (ioaddr + 8)),
+ htons (inw (ioaddr + 10)), htons (inw (ioaddr + 12)),
+ htons (inw (ioaddr + 14)));
lp->stats.tx_errors++;
+
/* ToDo: We should try to restart the adaptor... */
- cli();
+ spin_lock_irqsave (&lp->lock, flags);
- fjn_reset(dev);
+ fjn_reset (dev);
lp->tx_started = 0;
lp->tx_queue = 0;
lp->tx_queue_len = 0;
lp->sent = 0;
lp->open_time = jiffies;
- dev->interrupt = 0;
- dev->tbusy = 0;
- dev->start = 1;
-
- sti();
- }
+ netif_start_queue (dev);
+
+ spin_unlock_irqrestore (&lp->lock, flags);
+}
+
+
+static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct local_info_t *lp = (struct local_info_t *)dev->priv;
+ ioaddr_t ioaddr = dev->base_addr;
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk(KERN_NOTICE "%s: Transmitter access conflict.\n", dev->name);
- else {
+ netif_stop_queue (dev);
+ if (1) {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
unsigned char *buf = skb->data;
@@ -806,17 +802,17 @@ static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev)
lp->tx_queue_len = 0;
dev->trans_start = jiffies;
lp->tx_started = 1;
- dev->tbusy = 0;
+ netif_start_queue (dev);
} else {
if( sram_config == 0 ) {
if (lp->tx_queue_len < (4096 - (ETH_FRAME_LEN +2)) )
/* Yes, there is room for one more packet. */
- dev->tbusy = 0;
+ netif_start_queue (dev);
} else {
if (lp->tx_queue_len < (8192 - (ETH_FRAME_LEN +2)) &&
lp->tx_queue < 127 )
/* Yes, there is room for one more packet. */
- dev->tbusy = 0;
+ netif_start_queue (dev);
}
}
@@ -1025,9 +1021,7 @@ static int fjn_open(struct net_device *dev)
lp->tx_queue = 0;
lp->tx_queue_len = 0;
lp->open_time = jiffies;
- dev->interrupt = 0;
- dev->tbusy = 0;
- dev->start = 1;
+ netif_start_queue (dev);
MOD_INC_USE_COUNT;
@@ -1045,8 +1039,7 @@ static int fjn_close(struct net_device *dev)
DEBUG(4, "fjn_close('%s').\n", dev->name);
lp->open_time = 0;
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue (dev);
/* Set configuration register 0 to disable Tx and Rx. */
if( sram_config == 0 )
@@ -1064,7 +1057,6 @@ static int fjn_close(struct net_device *dev)
outb(INTR_OFF, ioaddr + LAN_CTRL);
link->open--;
- dev->start = 0;
if (link->state & DEV_STALE_CONFIG) {
link->release.expires = jiffies + HZ/20;
link->state |= DEV_RELEASE_PENDING;
diff --git a/drivers/net/pcmcia/netwave_cs.c b/drivers/net/pcmcia/netwave_cs.c
index 74928fd27..e95916c14 100644
--- a/drivers/net/pcmcia/netwave_cs.c
+++ b/drivers/net/pcmcia/netwave_cs.c
@@ -151,7 +151,7 @@ static const unsigned int txConfEUD = 0x10; /* Enable Uni-Data packets */
static const unsigned int txConfKey = 0x02; /* Scramble data packets */
static const unsigned int txConfLoop = 0x01; /* Loopback mode */
-/*static int netwave_debug = 0;*/
+static int netwave_debug = 0;
/*
All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
@@ -223,6 +223,7 @@ static void netwave_reset(struct net_device *dev);
static int netwave_open(struct net_device *dev); /* Open the device */
static int netwave_close(struct net_device *dev); /* Close the device */
static int netwave_config(struct net_device *dev, struct ifmap *map);
+static void netwave_tx_timeout (struct net_device *dev);
/* Packet transmission and Packet reception */
static int netwave_start_xmit( struct sk_buff *skb, struct net_device *dev);
@@ -308,6 +309,7 @@ typedef struct netwave_private {
u_char *ramBase;
int timeoutCounter;
int lastExec;
+ spinlock_t lock;
struct timer_list watchdog; /* To avoid blocking state */
struct site_survey nss;
struct enet_statistics stats;
@@ -454,6 +456,7 @@ static dev_link_t *netwave_attach(void)
priv = kmalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) return NULL;
memset(priv, 0, sizeof(*priv));
+ priv->lock = SPIN_LOCK_UNLOCKED;
link = &priv->link; dev = &priv->dev;
link->priv = dev->priv = priv;
link->release.function = &netwave_release;
@@ -503,7 +506,9 @@ static dev_link_t *netwave_attach(void)
dev->init = &netwave_init;
dev->open = &netwave_open;
dev->stop = &netwave_close;
- dev->tbusy = 1;
+ dev->tx_timeout = netwave_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+ netif_start_queue (dev);
link->irq.Instance = dev;
/* Register with Card Services */
@@ -835,7 +840,7 @@ static void netwave_pcmcia_config(dev_link_t *link) {
struct net_device *dev = &priv->dev;
tuple_t tuple;
cisparse_t parse;
- int i, j, last_ret, last_fn;
+ int i=0, j, last_ret, last_fn;
u_char buf[64];
win_req_t req;
memreq_t mem;
@@ -910,7 +915,7 @@ static void netwave_pcmcia_config(dev_link_t *link) {
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- dev->tbusy = 0;
+ netif_start_queue (dev);
if (register_netdev(dev) != 0) {
printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n");
goto failed;
@@ -1014,7 +1019,7 @@ static int netwave_event(event_t event, int priority,
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
- dev->tbusy = 1; dev->start = 0;
+ netif_device_detach(dev);
link->release.expires = jiffies + 5;
add_timer(&link->release);
}
@@ -1028,9 +1033,9 @@ static int netwave_event(event_t event, int priority,
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
- if (link->open) {
- dev->tbusy = 1; dev->start = 0;
- }
+ if (link->open)
+ netif_device_detach(dev);
+
CardServices(ReleaseConfiguration, link->handle);
}
break;
@@ -1042,7 +1047,7 @@ static int netwave_event(event_t event, int priority,
CardServices(RequestConfiguration, link->handle, &link->conf);
if (link->open) {
netwave_reset(dev);
- dev->tbusy = 0; dev->start = 1;
+ netif_device_attach(dev);
}
}
break;
@@ -1229,6 +1234,18 @@ static int netwave_hw_xmit(unsigned char* data, int len,
return 0;
}
+
+static void netwave_tx_timeout (struct net_device *dev)
+{
+ if (netwave_debug > 0)
+ printk (KERN_DEBUG "%s timed out.\n", dev->name);
+ netwave_reset (dev);
+ dev->trans_start = jiffies;
+ netif_start_queue (dev);
+}
+
+
+
static int netwave_start_xmit(struct sk_buff *skb, struct net_device *dev) {
/* This flag indicate that the hardware can't perform a transmission.
* Theoritically, NET3 check it before sending a packet to the driver,
@@ -1236,29 +1253,6 @@ static int netwave_start_xmit(struct sk_buff *skb, struct net_device *dev) {
* As the watchdog will abort too long transmissions, we are quite safe...
*/
- if (dev->tbusy) {
- /* Handled by watchdog */
- return 1;
-
- /* If we get here, some higher level has decided we are broken.
- There should really be a 'kick me' function call instead.
- */
- /*int tickssofar = jiffies - dev->trans_start;*/
- /* printk("xmit called with busy. tickssofar %d\n", tickssofar); */
- /*if (tickssofar < TX_TIMEOUT)
- return 1;
- */
- /* Should also detect if the kernel tries to xmit
- * on a stopped card.
- */
-
- /*if (netwave_debug > 0)
- printk(KERN_DEBUG "%s timed out.\n", dev->name);
- netwave_reset(dev);
- dev->trans_start = jiffies;
- dev->tbusy = 0;*/
- }
-
/* Sending a NULL skb means some higher layer thinks we've missed an
* tx-done interrupt. Caution: dev_tint() handles the cli()/sti()
* itself.
@@ -1268,15 +1262,14 @@ static int netwave_start_xmit(struct sk_buff *skb, struct net_device *dev) {
* better be done with atomic_swap(1, dev->tbusy, but set_bit()
* works as well
*/
- if ( test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk("%s: Transmitter access conflict.\n", dev->name);
- else {
+ netif_stop_queue (dev);
+ if (1) {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
unsigned char* buf = skb->data;
if (netwave_hw_xmit( buf, length, dev) == 1) {
/* Some error, let's make them call us another time? */
- dev->tbusy = 0;
+ netif_start_queue (dev);
}
dev->trans_start = jiffies;
}
@@ -1303,14 +1296,10 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) {
dev_link_t *link = &priv->link;
int i;
- if ((dev == NULL) | (!dev->start))
+ if ((dev == NULL) || !netif_device_present(dev))
return;
- if (dev->interrupt) {
- printk("%s: re-entering the interrupt handler.\n", dev->name);
- return;
- }
- dev->interrupt = 1;
+ spin_lock (&priv->lock);
iobase = dev->base_addr;
ramBase = priv->ramBase;
@@ -1409,8 +1398,7 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) {
/* If watchdog was activated, kill it ! */
del_timer(&priv->watchdog);
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue (dev);
}
/* TxBA, this would trigger on all error packets received */
/* if (status & 0x01) {
@@ -1420,8 +1408,7 @@ static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) {
*/
}
/* done.. */
- dev->interrupt = 0;
- return;
+ spin_unlock (&priv->lock);
} /* netwave_interrupt */
/*
@@ -1444,7 +1431,7 @@ static void netwave_watchdog(u_long a) {
netwave_reset(dev);
/* We are not waiting anymore... */
- dev->tbusy = 0;
+ netif_start_queue (dev);
} /* netwave_watchdog */
@@ -1584,7 +1571,7 @@ static int netwave_open(struct net_device *dev) {
link->open++;
MOD_INC_USE_COUNT;
- dev->interrupt = 0; dev->tbusy = 0; dev->start = 1;
+ netif_start_queue (dev);
netwave_reset(dev);
return 0;
@@ -1596,11 +1583,12 @@ static int netwave_close(struct net_device *dev) {
DEBUG(1, "netwave_close: finishing.\n");
+ netif_stop_queue (dev);
+
/* If watchdog was activated, kill it ! */
del_timer(&priv->watchdog);
link->open--;
- dev->start = 0;
if (link->state & DEV_STALE_CONFIG) {
link->release.expires = jiffies + 5;
link->state |= DEV_RELEASE_PENDING;
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index 2fb3772a5..22ff48201 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -307,6 +307,10 @@ four transmit and 12 receive frames at a time.
#undef MACE_IMR_DEFAULT
#define MACE_IMR_DEFAULT 0x00 /* New statistics handling: grab everything */
+#define TX_TIMEOUT (5*HZ)
+
+
+
/* ----------------------------------------------------------------------------
Type Definitions
---------------------------------------------------------------------------- */
@@ -360,6 +364,7 @@ typedef struct _mace_private {
dev_link_t link;
struct net_device dev;
dev_node_t node;
+ spinlock_t lock;
struct net_device_stats linux_stats; /* Linux statistics counters */
mace_statistics mace_stats; /* MACE chip statistics counters */
@@ -432,6 +437,7 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static struct net_device_stats *mace_get_stats(struct net_device *dev);
static int mace_rx(struct net_device *dev, unsigned char RxCnt);
static void restore_multicast_list(struct net_device *dev);
+static void mace_tx_timeout (struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
@@ -498,6 +504,8 @@ static dev_link_t *nmclan_attach(void)
lp = kmalloc(sizeof(*lp), GFP_KERNEL);
if (!lp) return NULL;
memset(lp, 0, sizeof(*lp));
+
+ lp->lock = SPIN_LOCK_UNLOCKED;
link = &lp->link; dev = &lp->dev;
link->priv = dev->priv = link->irq.Instance = lp;
@@ -531,7 +539,10 @@ static dev_link_t *nmclan_attach(void)
dev->init = &nmclan_init;
dev->open = &mace_open;
dev->stop = &mace_close;
- dev->tbusy = 0xFF;
+ dev->tx_timeout = mace_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
+ netif_start_queue (dev);
/* Register with Card Services */
link->next = dev_list;
@@ -752,7 +763,7 @@ static void nmclan_config(dev_link_t *link)
CS_CHECK(RequestConfiguration, handle, &link->conf);
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- dev->tbusy = 0;
+ netif_start_queue (dev);
i = register_netdev(dev);
if (i != 0) {
printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n");
@@ -859,7 +870,7 @@ static int nmclan_event(event_t event, int priority,
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
- dev->tbusy = 0xFF; dev->start = 0;
+ netif_device_detach(dev);
link->release.expires = jiffies + HZ/20;
add_timer(&link->release);
}
@@ -873,9 +884,9 @@ static int nmclan_event(event_t event, int priority,
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
- if (link->open) {
- dev->tbusy = 0xFF; dev->start = 0;
- }
+ if (link->open)
+ netif_device_detach(dev);
+
CardServices(ReleaseConfiguration, link->handle);
}
break;
@@ -886,9 +897,8 @@ static int nmclan_event(event_t event, int priority,
if (link->state & DEV_CONFIG) {
CardServices(RequestConfiguration, link->handle, &link->conf);
if (link->open) {
- dev->tbusy = 0;
- dev->start = 1;
nmclan_reset(dev);
+ netif_device_attach(dev);
}
}
break;
@@ -987,10 +997,7 @@ static int mace_open(struct net_device *dev)
MACEBANK(0);
- dev->interrupt = 0;
- dev->tbusy = 0;
- dev->start = 1;
-
+ netif_start_queue (dev);
nmclan_reset(dev);
return 0; /* Always succeed */
@@ -1007,12 +1014,13 @@ static int mace_close(struct net_device *dev)
dev_link_t *link = &lp->link;
DEBUG(2, "%s: shutting down ethercard.\n", dev->name);
+
+ netif_stop_queue (dev);
/* Mask off all interrupts from the MACE chip. */
outb(0xFF, ioaddr + AM2150_MACE_BASE + MACE_IMR);
link->open--;
- dev->start = 0;
if (link->state & DEV_STALE_CONFIG) {
link->release.expires = jiffies + HZ/20;
link->state |= DEV_RELEASE_PENDING;
@@ -1024,6 +1032,24 @@ static int mace_close(struct net_device *dev)
return 0;
} /* mace_close */
+
+static void mace_tx_timeout (struct net_device *dev)
+{
+ mace_private *lp = (mace_private *)dev->priv;
+ dev_link_t *link = &lp->link;
+
+ printk (KERN_NOTICE "%s: transmit timed out -- ", dev->name);
+#if RESET_ON_TIMEOUT
+ printk ("resetting card\n");
+ CardServices (ResetCard, link->handle);
+#else /* #if RESET_ON_TIMEOUT */
+ printk ("NOT resetting card\n");
+#endif /* #if RESET_ON_TIMEOUT */
+ dev->trans_start = jiffies;
+ netif_start_queue (dev);
+}
+
+
/* ----------------------------------------------------------------------------
mace_start_xmit
This routine begins the packet transmit function. When completed,
@@ -1038,39 +1064,11 @@ static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
mace_private *lp = (mace_private *)dev->priv;
ioaddr_t ioaddr = dev->base_addr;
- dev_link_t *link = &lp->link;
-
-#if TIMEOUT_TX
- /* Transmitter timeout. */
- if (dev->tbusy) {
- int tickssofar = jiffies - dev->trans_start;
-
- if (tickssofar < (HZ/5))
- return 1;
- printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name);
-#if RESET_ON_TIMEOUT
- printk("resetting card\n");
- CardServices(ResetCard, link->handle);
-#else /* #if RESET_ON_TIMEOUT */
- printk("NOT resetting card\n");
-#endif /* #if RESET_ON_TIMEOUT */
- dev->trans_start = jiffies;
- return 1;
- }
-#else /* #if TIMEOUT_TX */
- if (dev->tbusy)
- return 1;
-#endif /* #if TIMEOUT_TX */
DEBUG(3, "%s: mace_start_xmit(length = %ld) called.\n",
dev->name, (long)skb->len);
- /* Avoid timer-based retransmission conflicts. */
- if (test_and_set_bit(TBUSY_UNSPECIFIED, (void*)&dev->tbusy) != 0) {
- printk(KERN_NOTICE "%s: transmitter access conflict.\n",
- dev->name);
- return 1;
- }
+ netif_stop_queue (dev);
#if (!TX_INTERRUPTABLE)
/* Disable MACE TX interrupts. */
@@ -1085,11 +1083,9 @@ static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev)
the upper layers. The interrupt handler is guaranteed never to
service a transmit interrupt while we are in here.
*/
- set_bit(TBUSY_PARTIAL_TX_FRAME, (void*)&dev->tbusy);
lp->linux_stats.tx_bytes += skb->len;
lp->tx_free_frames--;
- set_bit(TBUSY_NO_FREE_TX_FRAMES, (void*)&dev->tbusy);
/* WARNING: Write the _exact_ number of bytes written in the header! */
/* Put out the word header [must be an outw()] . . . */
@@ -1105,11 +1101,10 @@ static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (lp->tx_free_frames > 0) {
#if MULTI_TX
- clear_bit(TBUSY_NO_FREE_TX_FRAMES, (void*)&dev->tbusy);
+ netif_start_queue (dev);
#endif /* #if MULTI_TX */
}
- clear_bit(TBUSY_PARTIAL_TX_FRAME, (void*)&dev->tbusy);
}
#if (!TX_INTERRUPTABLE)
@@ -1140,8 +1135,10 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
irq);
return;
}
+
+ spin_lock (&lp->lock);
- if (dev->interrupt || lp->tx_irq_disabled) {
+ if (lp->tx_irq_disabled) {
printk(
(lp->tx_irq_disabled?
KERN_NOTICE "%s: Interrupt with tx_irq_disabled "
@@ -1155,9 +1152,8 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* WARNING: MACE_IR has been read! */
return;
}
- dev->interrupt = 1;
- if (dev->start == 0) {
+ if (!netif_device_present(dev)) {
DEBUG(2, "%s: interrupt from dead card\n", dev->name);
goto exception;
}
@@ -1230,8 +1226,7 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
lp->linux_stats.tx_packets++;
lp->tx_free_frames++;
- clear_bit(TBUSY_NO_FREE_TX_FRAMES, (void*)&dev->tbusy);
- mark_bh(NET_BH);
+ netif_wake_queue (dev);
} /* if (status & MACE_IR_XMTINT) */
if (status & ~MACE_IMR_DEFAULT & ~MACE_IR_RCVINT & ~MACE_IR_XMTINT) {
@@ -1266,8 +1261,7 @@ static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
} while ((status & ~MACE_IMR_DEFAULT) && (--IntrCnt));
exception:
- dev->interrupt = 0;
- return;
+ spin_unlock (&lp->lock);
} /* mace_interrupt */
/* ----------------------------------------------------------------------------
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 0af9aa04d..185644307 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -11,7 +11,7 @@
Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org
- pcnet_cs.c 1.110 1999/12/06 21:39:18
+ pcnet_cs.c 1.112 2000/02/11 01:24:44
The network driver code is based on Donald Becker's NE2000 code:
@@ -72,7 +72,7 @@ static int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"pcnet_cs.c 1.110 1999/12/06 21:39:18 (David Hinds)";
+"pcnet_cs.c 1.112 2000/02/11 01:24:44 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
@@ -211,7 +211,8 @@ static hw_info_t hw_info[] = {
DELAY_OUTPUT | HAS_MISC_REG | USE_BIG_BUF },
{ /* SuperSocket RE450T */ 0x0110, 0x00, 0xe0, 0x98, 0 },
{ /* Volktek NPL-402CT */ 0x0060, 0x00, 0x40, 0x05, 0 },
- { /* NEC PC-9801N-J12 */ 0x0ff0, 0x00, 0x00, 0x4c, 0 }
+ { /* NEC PC-9801N-J12 */ 0x0ff0, 0x00, 0x00, 0x4c, 0 },
+ { /* PCMCIA Technology OEM */ 0x01c8, 0xa0, 0x0c, 0 }
};
#define NR_INFO (sizeof(hw_info)/sizeof(hw_info_t))
@@ -306,7 +307,6 @@ static dev_link_t *pcnet_attach(void)
for (i = 0; i < 4; i++)
link->irq.IRQInfo2 |= 1 << irq_list[i];
link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
ethdev_init(dev);
@@ -596,6 +596,7 @@ static void pcnet_config(dev_link_t *link)
int i, last_ret, last_fn, start_pg, stop_pg, cm_offset;
int manfid = 0, prodid = 0, has_shmem = 0;
u_short buf[64];
+ config_info_t conf;
hw_info_t *hw_info;
DEBUG(0, "pcnet_config(0x%p)\n", link);
@@ -614,6 +615,10 @@ static void pcnet_config(dev_link_t *link)
/* Configure card */
link->state |= DEV_CONFIG;
+ /* Look up current Vcc */
+ CS_CHECK(GetConfigurationInfo, handle, &conf);
+ link->conf.Vcc = conf.Vcc;
+
tuple.DesiredTuple = CISTPL_MANFID;
tuple.Attributes = TUPLE_RETURN_COMMON;
if ((CardServices(GetFirstTuple, handle, &tuple) == CS_SUCCESS) &&
@@ -807,8 +812,7 @@ static int pcnet_event(event_t event, int priority,
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
- netif_stop_queue(&info->dev);
- clear_bit(LINK_STATE_START, &info->dev.state);
+ netif_device_detach(&info->dev);
link->release.expires = jiffies + HZ/20;
link->state |= DEV_RELEASE_PENDING;
add_timer(&link->release);
@@ -823,10 +827,9 @@ static int pcnet_event(event_t event, int priority,
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
- if (link->open) {
- netif_stop_queue(&info->dev);
- clear_bit(LINK_STATE_START, &info->dev.state);
- }
+ if (link->open)
+ netif_device_detach(&info->dev);
+
CardServices(ReleaseConfiguration, link->handle);
}
break;
@@ -839,8 +842,7 @@ static int pcnet_event(event_t event, int priority,
if (link->open) {
pcnet_reset_8390(&info->dev);
NS8390_init(&info->dev, 1);
- netif_start_queue(&info->dev);
- set_bit(LINK_STATE_START, &info->dev.state);
+ netif_device_attach(&info->dev);
}
}
break;
@@ -908,7 +910,6 @@ static int pcnet_close(struct net_device *dev)
free_irq(dev->irq, dev);
link->open--;
- clear_bit(LINK_STATE_START, &dev->state);
del_timer(&info->watchdog);
if (link->state & DEV_STALE_CONFIG) {
link->release.expires = jiffies + HZ/20;
@@ -984,7 +985,7 @@ static void ei_watchdog(u_long arg)
struct net_device *dev = &info->dev;
ioaddr_t nic_base = dev->base_addr;
- if (!test_bit(LINK_STATE_START, &dev->state))
+ if (!netif_device_present(dev))
goto reschedule;
/* Check for pending interrupt with expired latency timer: with
diff --git a/drivers/net/pcmcia/ray_cs.c b/drivers/net/pcmcia/ray_cs.c
index ea3ffa2cb..7c763cf8e 100644
--- a/drivers/net/pcmcia/ray_cs.c
+++ b/drivers/net/pcmcia/ray_cs.c
@@ -926,8 +926,7 @@ static int ray_event(event_t event, int priority,
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
- netif_stop_queue(dev);
- clear_bit(LINK_STATE_START, &dev->state);
+ netif_device_detach(dev);
if (link->state & DEV_CONFIG) {
link->release.expires = jiffies + HZ/20;
add_timer(&link->release);
@@ -943,10 +942,9 @@ static int ray_event(event_t event, int priority,
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
- if (link->open) {
- netif_stop_queue(dev);
- clear_bit(LINK_STATE_START, &dev->state);
- }
+ if (link->open)
+ netif_device_detach(dev);
+
pcmcia_release_configuration(link->handle);
}
break;
@@ -958,8 +956,7 @@ static int ray_event(event_t event, int priority,
pcmcia_request_configuration(link->handle, &link->conf);
if (link->open) {
ray_reset(dev);
- netif_start_queue(dev);
- set_bit(LINK_STATE_START, &dev->state);
+ netif_device_attach(dev);
}
}
break;
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 4a58706f6..b201d1ec1 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -125,6 +125,8 @@ struct smc_private {
u_short media_status;
u_short fast_poll;
u_long last_rx;
+
+ spinlock_t lock;
};
/* Special definitions for Megahertz multifunction cards */
@@ -281,6 +283,7 @@ static void smc91c92_release(u_long arg);
static int smc91c92_event(event_t event, int priority,
event_callback_args_t *args);
+static void smc91c92_tx_timeout (struct net_device *dev);
static int smc91c92_open(struct net_device *dev);
static int smc91c92_close(struct net_device *dev);
static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev);
@@ -379,9 +382,12 @@ static dev_link_t *smc91c92_attach(void)
dev->init = &smc91c92_init;
dev->open = &smc91c92_open;
dev->stop = &smc91c92_close;
- dev->tbusy = 1;
+ dev->tx_timeout = smc91c92_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
dev->priv = link->priv = link->irq.Instance = smc;
+ netif_start_queue (dev);
+
/* Register with Card Services */
link->next = dev_list;
dev_list = link;
@@ -663,7 +669,7 @@ static int mot_setup(dev_link_t *link) {
struct smc_private *smc = link->priv;
struct net_device *dev = &smc->dev;
ioaddr_t ioaddr = dev->base_addr;
- int i, wait, loop;
+ int i, wait=0, loop;
unsigned int addr;
/* Read Ethernet address from Serial EEPROM */
@@ -775,7 +781,7 @@ static int osi_config(dev_link_t *link)
struct smc_private *smc = link->priv;
struct net_device *dev = &smc->dev;
static ioaddr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
- int i, j;
+ int i=0, j;
link->conf.Attributes |= CONF_ENABLE_SPKR;
link->conf.Status = CCSR_AUDIO_ENA;
@@ -977,7 +983,7 @@ static void smc91c92_config(dev_link_t *link)
dev->if_port = if_port;
else
printk(KERN_NOTICE "smc91c92_cs: invalid if_port requested\n");
- dev->tbusy = 0;
+ netif_start_queue (dev);
if (register_netdev(dev) != 0) {
printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
@@ -1106,8 +1112,7 @@ static int smc91c92_event(event_t event, int priority,
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
- dev->tbusy = 1;
- dev->start = 0;
+ netif_device_detach(dev);
link->release.expires = jiffies + HZ/20;
link->state |= DEV_RELEASE_PENDING;
add_timer(&link->release);
@@ -1122,9 +1127,9 @@ static int smc91c92_event(event_t event, int priority,
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
- if (link->open) {
- dev->tbusy = 1; dev->start = 0;
- }
+ if (link->open)
+ netif_device_detach(dev);
+
CardServices(ReleaseConfiguration, link->handle);
}
break;
@@ -1147,7 +1152,7 @@ static int smc91c92_event(event_t event, int priority,
}
if (link->open) {
smc_reset(dev);
- dev->tbusy = 0; dev->start = 1;
+ netif_device_attach(dev);
}
}
break;
@@ -1201,7 +1206,7 @@ static int smc91c92_open(struct net_device *dev)
link->open++;
MOD_INC_USE_COUNT;
- dev->interrupt = 0; dev->tbusy = 0; dev->start = 1;
+ netif_start_queue (dev);
smc->saved_skb = 0;
smc->packets_waiting = 0;
@@ -1225,8 +1230,7 @@ static int smc91c92_close(struct net_device *dev)
DEBUG(0, "%s: smc91c92_close(), status %4.4x.\n",
dev->name, inw(ioaddr + BANK_SELECT));
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue (dev);
/* Shut off all interrupts, and turn off the Tx and Rx sections.
Don't bother to check for chip present. */
@@ -1240,7 +1244,7 @@ static int smc91c92_close(struct net_device *dev)
SMC_SELECT_BANK( 1 );
outw(CTL_POWERDOWN, ioaddr + CONTROL );
- link->open--; dev->start = 0;
+ link->open--;
del_timer(&smc->media);
if (link->state & DEV_STALE_CONFIG) {
link->release.expires = jiffies + HZ/20;
@@ -1281,7 +1285,7 @@ static void smc_hardware_send_packet( struct net_device * dev )
" failed, status %#2.2x.\n", dev->name, packet_no);
dev_kfree_skb (skb);
smc->saved_skb = NULL;
- dev->tbusy = 0;
+ netif_start_queue (dev);
return;
}
@@ -1329,12 +1333,30 @@ static void smc_hardware_send_packet( struct net_device * dev )
smc->saved_skb = NULL;
dev_kfree_skb (skb);
dev->trans_start = jiffies;
- dev->tbusy = 0;
+ netif_start_queue (dev);
return;
}
/*====================================================================*/
+static void smc91c92_tx_timeout (struct net_device *dev)
+{
+ struct smc_private *smc = dev->priv;
+ ioaddr_t ioaddr = dev->base_addr;
+
+ printk (KERN_NOTICE "%s: SMC91c92 transmit timed out, "
+ "Tx_status %2.2x status %4.4x.\n",
+ dev->name, inw (ioaddr) & 0xff, inw (ioaddr + 2));
+ smc->stats.tx_errors++;
+ smc_reset (dev);
+ dev->trans_start = jiffies;
+ smc->saved_skb = NULL;
+ netif_start_queue (dev);
+}
+
+
+/*====================================================================*/
+
static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct smc_private *smc = dev->priv;
@@ -1342,29 +1364,10 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
unsigned short num_pages;
short time_out, ir;
- /* Transmitter timeout, serious problems. */
- if (dev->tbusy) {
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < TX_TIMEOUT)
- return 1;
- printk(KERN_NOTICE "%s: SMC91c92 transmit timed out, "
- "Tx_status %2.2x status %4.4x.\n",
- dev->name, inw(ioaddr)&0xff, inw(ioaddr + 2));
- smc->stats.tx_errors++;
- smc_reset(dev);
- dev->trans_start = jiffies;
- dev->tbusy = 0;
- smc->saved_skb = NULL;
- }
-
DEBUG(2, "%s: smc91c92_start_xmit(length = %d) called,"
" status %4.4x.\n", dev->name, skb->len, inw(ioaddr + 2));
-
- /* Avoid timer-based retransmission conflicts. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
- printk(KERN_ERR "%s: transmitter access conflict.\n", dev->name);
- return 1;
- }
+
+ netif_stop_queue (dev);
if ( smc->saved_skb) {
/* THIS SHOULD NEVER HAPPEN. */
@@ -1500,21 +1503,14 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
u_short saved_bank, saved_pointer, mask, status;
char bogus_cnt = INTR_WORK; /* Work we are willing to do. */
- if ((smc == NULL) || !dev->start)
+ if ((smc == NULL) || !netif_device_present(dev))
return;
ioaddr = dev->base_addr;
-#ifdef PCMCIA_DEBUG
- if (dev->interrupt) {
- printk(KERN_ERR "%s: re-entering the interrupt handler.\n",
- dev->name);
- return;
- }
- dev->interrupt = 1;
+ spin_lock (&smc->lock);
DEBUG(3, "%s: SMC91c92 interrupt %d at %#x.\n", dev->name,
irq, ioaddr);
-#endif
smc->watchdog = 0;
saved_bank = inw(ioaddr + BANK_SELECT);
@@ -1525,7 +1521,6 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (dev->start)
DEBUG(1, "%s: SMC91c92 interrupt %d for non-existent"
"/ejected device.\n", dev->name, irq);
- dev->interrupt = 0;
#endif
goto irq_done;
}
@@ -1569,7 +1564,7 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
mask |= ( IM_TX_EMPTY_INT | IM_TX_INT );
/* and let the card send more packets to me */
- mark_bh( NET_BH );
+ netif_wake_queue (dev);
}
if (status & IM_RX_OVRN_INT) {
smc->stats.rx_errors++;
@@ -1588,10 +1583,9 @@ static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
outw(saved_pointer, ioaddr + POINTER);
SMC_SELECT_BANK( saved_bank );
-#ifdef PCMCIA_DEBUG
- dev->interrupt = 0;
+ spin_unlock (&smc->lock);
+
DEBUG(3, "%s: Exiting interrupt IRQ%d.\n", dev->name, irq);
-#endif
irq_done:
@@ -1913,8 +1907,9 @@ static void media_check(u_long arg)
ioaddr_t ioaddr = dev->base_addr;
u_short i, media, saved_bank;
- if (dev->start == 0) goto reschedule;
-
+ if (!netif_device_present(dev))
+ goto reschedule;
+
saved_bank = inw(ioaddr + BANK_SELECT);
SMC_SELECT_BANK(2);
i = inw(ioaddr + INTERRUPT);
diff --git a/drivers/net/pcmcia/tulip_cb.c b/drivers/net/pcmcia/tulip_cb.c
index ee49f58eb..38dcdc0c1 100644
--- a/drivers/net/pcmcia/tulip_cb.c
+++ b/drivers/net/pcmcia/tulip_cb.c
@@ -96,16 +96,7 @@ static int csr0 = 0x00A00000 | 0x4800;
#endif
#include <linux/version.h>
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
#include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
@@ -128,7 +119,6 @@ static int csr0 = 0x00A00000 | 0x4800;
/* Kernel compatibility defines, some common to David Hinds' PCMCIA package.
This is only in the support-all-kernels source code. */
-#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver");
MODULE_PARM(debug, "i");
@@ -138,14 +128,9 @@ MODULE_PARM(rx_copybreak, "i");
MODULE_PARM(csr0, "i");
MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-#endif
#define RUN_AT(x) (jiffies + (x))
-#define NETSTATS_VER2
-#define PCI_SUPPORT_VER3
-#define dev_free_skb(skb) dev_kfree_skb(skb);
-
#define tulip_debug debug
#ifdef TULIP_DEBUG
static int tulip_debug = TULIP_DEBUG;
@@ -438,7 +423,8 @@ struct tulip_private {
struct mediatable *mtable;
int cur_index; /* Current media index. */
int saved_if_port;
- unsigned char pci_bus, pci_devfn;
+ struct pci_dev *pdev;
+ spinlock_t lock;
int pad0, pad1; /* Used for 8-byte alignment */
};
@@ -515,9 +501,9 @@ static void outl_CSR6 (u32 newcsr6, long ioaddr, int chip_idx)
restore_flags(flags);
}
-static struct net_device *tulip_probe1(int pci_bus, int pci_devfn,
- struct net_device *dev, long ioaddr, int irq,
- int chip_idx, int board_idx)
+static struct net_device *tulip_probe1(struct pci_dev *pdev,
+ struct net_device *dev, long ioaddr, int irq,
+ int chip_idx, int board_idx)
{
static int did_version = 0; /* Already printed version info. */
struct tulip_private *tp;
@@ -534,11 +520,11 @@ static struct net_device *tulip_probe1(int pci_bus, int pci_devfn,
dev = init_etherdev(dev, 0);
- pcibios_read_config_byte(pci_bus, pci_devfn, PCI_REVISION_ID, &chip_rev);
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev);
/* Bring the 21143 out of sleep mode.
Caution: Snooze mode does not work with some boards! */
if (tulip_tbl[chip_idx].flags & HAS_ACPI)
- pcibios_write_config_dword(pci_bus, pci_devfn, 0x40, 0x00000000);
+ pci_write_config_dword(pdev, 0x40, 0x00000000);
printk(KERN_INFO "%s: %s rev %d at %#3lx,",
dev->name, tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr);
@@ -691,8 +677,8 @@ static struct net_device *tulip_probe1(int pci_bus, int pci_devfn,
memset(tp, 0, sizeof(*tp));
dev->priv = tp;
- tp->pci_bus = pci_bus;
- tp->pci_devfn = pci_devfn;
+ tp->lock = SPIN_LOCK_UNLOCKED;
+ tp->pdev = pdev;
tp->chip_id = chip_idx;
tp->revision = chip_rev;
tp->csr0 = csr0;
@@ -807,6 +793,8 @@ static struct net_device *tulip_probe1(int pci_bus, int pci_devfn,
#ifdef HAVE_MULTICAST
dev->set_multicast_list = &set_rx_mode;
#endif
+ dev->tx_timeout = tulip_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
/* Reset the xcvr interface and turn on heartbeat. */
switch (chip_idx) {
@@ -1302,7 +1290,7 @@ tulip_up(struct net_device *dev)
udelay(2);
if (tulip_tbl[tp->chip_id].flags & HAS_ACPI)
- pcibios_write_config_dword(tp->pci_bus, tp->pci_devfn, 0x40, 0x00000000);
+ pci_write_config_dword(tp->pdev, 0x40, 0x00000000);
/* Clear the tx ring */
for (i = 0; i < TX_RING_SIZE; i++) {
@@ -1461,15 +1449,13 @@ media_picked:
outl_CSR6(tp->csr6, ioaddr, tp->chip_id);
outl_CSR6(tp->csr6 | 0x2000, ioaddr, tp->chip_id);
- dev->tbusy = 0;
- tp->interrupt = 0;
- dev->start = 1;
-
/* Enable interrupts by setting the interrupt mask. */
outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5);
outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id);
outl(0, ioaddr + CSR2); /* Rx poll demand */
+
+ netif_start_queue (dev);
if (tulip_debug > 2) {
printk(KERN_DEBUG "%s: Done tulip_open(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n",
@@ -2354,8 +2340,8 @@ static void tulip_tx_timeout(struct net_device *dev)
outl(0, ioaddr + CSR1);
dev->trans_start = jiffies;
+ netif_wake_queue (dev);
tp->stats.tx_errors++;
- return;
}
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
@@ -2413,15 +2399,6 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev)
int entry;
u32 flag;
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
- if (jiffies - dev->trans_start < TX_TIMEOUT)
- return 1;
- tulip_tx_timeout(dev);
- return 1;
- }
-
/* Caution: the write order is important here, set the base address
with the "ownership" bits last. */
@@ -2454,8 +2431,10 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev)
tp->tx_ring[entry].length = skb->len | flag;
tp->tx_ring[entry].status = DescOwned; /* Pass ownership to the chip. */
tp->cur_tx++;
- if ( ! tp->tx_full)
- clear_bit(0, (void*)&dev->tbusy);
+ if (tp->tx_full)
+ netif_stop_queue (dev);
+ else
+ netif_wake_queue (dev);
/* Trigger an immediate transmit demand. */
outl(0, dev->base_addr + CSR1);
@@ -2474,21 +2453,7 @@ static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
long ioaddr = dev->base_addr;
int csr5, work_budget = max_interrupt_work;
-#if defined(__i386__) && defined(SMP_CHECK)
- if (test_and_set_bit(0, (void*)&dev->interrupt)) {
- printk(KERN_ERR "%s: Duplicate entry of the interrupt handler by "
- "processor %d.\n",
- dev->name, smp_processor_id());
- dev->interrupt = 0;
- return;
- }
-#else
- if (dev->interrupt) {
- printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
- return;
- }
- dev->interrupt = 1;
-#endif
+ spin_lock (&tp->lock);
do {
csr5 = inl(ioaddr + CSR5);
@@ -2549,7 +2514,7 @@ static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
}
/* Free the original skb. */
- dev_free_skb(tp->tx_skbuff[entry]);
+ dev_kfree_skb_irq(tp->tx_skbuff[entry]);
tp->tx_skbuff[entry] = 0;
}
@@ -2561,13 +2526,15 @@ static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
}
#endif
- if (tp->tx_full && dev->tbusy
- && tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) {
- /* The ring is no longer full, clear tbusy. */
+ if (tp->tx_full &&
+ tp->cur_tx - dirty_tx < TX_RING_SIZE - 2)
+ /* The ring is no longer full */
tp->tx_full = 0;
- dev->tbusy = 0;
- mark_bh(NET_BH);
- }
+
+ if (tp->tx_full)
+ netif_stop_queue (dev);
+ else
+ netif_wake_queue (dev);
tp->dirty_tx = dirty_tx;
if (csr5 & TxDied) {
@@ -2630,12 +2597,7 @@ static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",
dev->name, inl(ioaddr + CSR5));
-#if defined(__i386__)
- clear_bit(0, (void*)&dev->interrupt);
-#else
- dev->interrupt = 0;
-#endif
- return;
+ spin_unlock (&tp->lock);
}
static int
@@ -2751,9 +2713,6 @@ tulip_down(struct net_device *dev)
long ioaddr = dev->base_addr;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- dev->start = 0;
- dev->tbusy = 1;
-
/* Disable interrupts by clearing the interrupt mask. */
outl(0x00000000, ioaddr + CSR7);
/* Stop the chip's Tx and Rx processes. */
@@ -2765,8 +2724,6 @@ tulip_down(struct net_device *dev)
if (inl(ioaddr + CSR6) != 0xffffffff)
tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
- del_timer(&tp->timer);
-
dev->if_port = tp->saved_if_port;
}
@@ -2781,9 +2738,13 @@ tulip_close(struct net_device *dev)
printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
dev->name, inl(ioaddr + CSR5));
- if (dev->start)
+ netif_stop_queue(dev);
+
+ if (netif_device_present(dev))
tulip_down(dev);
+ del_timer(&tp->timer);
+
free_irq(dev->irq, dev);
/* Free all the skbuffs in the Rx queue. */
@@ -2794,12 +2755,12 @@ tulip_close(struct net_device *dev)
tp->rx_ring[i].length = 0;
tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */
if (skb) {
- dev_free_skb(skb);
+ dev_kfree_skb(skb);
}
}
for (i = 0; i < TX_RING_SIZE; i++) {
if (tp->tx_skbuff[i])
- dev_free_skb(tp->tx_skbuff[i]);
+ dev_kfree_skb(tp->tx_skbuff[i]);
tp->tx_skbuff[i] = 0;
}
@@ -2813,7 +2774,7 @@ static struct net_device_stats *tulip_get_stats(struct net_device *dev)
struct tulip_private *tp = (struct tulip_private *)dev->priv;
long ioaddr = dev->base_addr;
- if (dev->start)
+ if (netif_device_present(dev))
tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
return &tp->stats;
@@ -3075,8 +3036,8 @@ static void set_rx_mode(struct net_device *dev)
tp->tx_ring[entry].buffer1 = virt_to_bus(tp->setup_frame);
tp->tx_ring[entry].status = DescOwned;
if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) {
- set_bit(0, (void*)&dev->tbusy);
tp->tx_full = 1;
+ netif_stop_queue (dev);
}
if (dummy >= 0)
tp->tx_ring[dummy].status = DescOwned;
@@ -3114,10 +3075,11 @@ static int __devinit tulip_pci_probe(struct pci_dev *pdev, const struct pci_devi
printk(KERN_INFO "tulip_attach(%s)\n", pdev->slot_name);
- pci_set_master(pdev);
- dev = tulip_probe1(pdev->bus->number, pdev->devfn, NULL,
- pdev->resource[0].start, pdev->irq,
- id->driver_data, board_idx++);
+ pci_enable_device (pdev);
+ pci_set_master (pdev);
+ dev = tulip_probe1(pdev, NULL,
+ pci_resource_start (pdev, 0), pdev->irq,
+ id->driver_data, board_idx++);
if (dev) {
pdev->driver_data = dev;
return 0;
diff --git a/drivers/net/pcmcia/wavelan_cs.c b/drivers/net/pcmcia/wavelan_cs.c
index c1c38aa28..ae9bb0548 100644
--- a/drivers/net/pcmcia/wavelan_cs.c
+++ b/drivers/net/pcmcia/wavelan_cs.c
@@ -66,31 +66,6 @@
/*------------------------------------------------------------------*/
/*
- * Wrapper for disabling interrupts.
- */
-static inline unsigned long
-wv_splhi(void)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- return(flags);
-}
-
-/*------------------------------------------------------------------*/
-/*
- * Wrapper for re-enabling interrupts.
- */
-static inline void
-wv_splx(unsigned long flags)
-{
- restore_flags(flags);
-}
-
-/*------------------------------------------------------------------*/
-/*
* Wrapper for reporting error to cardservices
*/
static void cs_error(client_handle_t handle, int func, int ret)
@@ -581,20 +556,20 @@ void wv_roam_cleanup(struct net_device *dev)
void wv_nwid_filter(unsigned char mode, net_local *lp)
{
mm_t m;
- unsigned long x;
+ unsigned long flags;
#ifdef WAVELAN_ROAMING_DEBUG
printk(KERN_DEBUG "WaveLAN: NWID promisc %s, device %s\n",(mode==NWID_PROMISC) ? "on" : "off", lp->dev->name);
#endif
/* Disable interrupts & save flags */
- x = wv_splhi();
+ spin_lock_irqsave (&lp->lock, flags);
m.w.mmw_loopt_sel = (mode==NWID_PROMISC) ? MMW_LOOPT_SEL_DIS_NWID : 0x00;
mmc_write(lp->dev->base_addr, (char *)&m.w.mmw_loopt_sel - (char *)&m, (unsigned char *)&m.w.mmw_loopt_sel, 1);
/* ReEnable interrupts & restore flags */
- wv_splx(x);
+ spin_unlock_irqrestore (&lp->lock, flags);
if(mode==NWID_PROMISC)
lp->cell_search=1;
@@ -755,7 +730,7 @@ void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp)
{
ioaddr_t base = lp->dev->base_addr;
mm_t m;
- unsigned long x;
+ unsigned long flags;
if(wavepoint==lp->curr_point) /* Sanity check... */
{
@@ -768,7 +743,7 @@ void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp)
#endif
/* Disable interrupts & save flags */
- x = wv_splhi();
+ spin_lock_irqsave(&lp->lock, flags);
m.w.mmw_netw_id_l = wavepoint->nwid & 0xFF;
m.w.mmw_netw_id_h = (wavepoint->nwid & 0xFF00) >> 8;
@@ -776,7 +751,7 @@ void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp)
mmc_write(base, (char *)&m.w.mmw_netw_id_l - (char *)&m, (unsigned char *)&m.w.mmw_netw_id_l, 2);
/* ReEnable interrupts & restore flags */
- wv_splx(x);
+ spin_unlock_irqrestore (&lp->lock, flags);
wv_nwid_filter(!NWID_PROMISC,lp);
lp->curr_point=wavepoint;
@@ -863,15 +838,15 @@ wv_82593_cmd(device * dev,
net_local * lp = (net_local *)dev->priv;
int status;
long spin;
- u_long opri;
+ u_long flags;
/* Spin until the chip finishes executing its current command (if any) */
do
{
- opri = wv_splhi();
+ spin_lock_irqsave (&lp->lock, flags);
outb(OP0_NOP | CR0_STATUS_3, LCCR(base));
status = inb(LCSR(base));
- wv_splx(opri);
+ spin_unlock_irqrestore (&lp->lock, flags);
}
while((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE);
@@ -1009,27 +984,25 @@ read_ringbuf(device * dev,
* wavelan_interrupt is not an option...), so you may experience
* some delay sometime...
*/
-static inline void
-wv_82593_reconfig(device * dev)
+static inline void wv_82593_reconfig (device * dev)
{
- net_local * lp = (net_local *)dev->priv;
- dev_link_t * link = ((net_local *) dev->priv)->link;
+ net_local *lp = (net_local *) dev->priv;
+ dev_link_t *link = ((net_local *) dev->priv)->link;
- /* Check if we can do it now ! */
- if(!(link->open) || (test_and_set_bit(0, (void *)&dev->tbusy) != 0))
- {
- lp->reconfig_82593 = TRUE;
+ /* Check if we can do it now ! */
+ if (!(link->open)) {
+ lp->reconfig_82593 = TRUE;
#ifdef DEBUG_IOCTL_INFO
- printk(KERN_DEBUG "%s: wv_82593_reconfig(): delayed (busy = %ld, link = %d)\n",
- dev->name, dev->tbusy, link->open);
+ printk (KERN_DEBUG "%s: wv_82593_reconfig(): delayed (link = %d)\n",
+ dev->name, link->open);
#endif
- }
- else
- {
- lp->reconfig_82593 = FALSE;
- wv_82593_config(dev);
- dev->tbusy = 0;
- }
+ } else {
+ netif_stop_queue (dev);
+
+ lp->reconfig_82593 = FALSE;
+ wv_82593_config (dev);
+ netif_wake_queue (dev);
+ }
}
#ifdef OLDIES
@@ -1286,9 +1259,6 @@ static void
wv_dev_show(device * dev)
{
printk(KERN_DEBUG "dev:");
- printk(" start=%d,", dev->start);
- printk(" tbusy=%ld,", dev->tbusy);
- printk(" interrupt=%d,", dev->interrupt);
printk(" trans_start=%ld,", dev->trans_start);
printk(" flags=0x%x,", dev->flags);
printk("\n");
@@ -1908,7 +1878,7 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */
struct iwreq * wrq = (struct iwreq *) rq;
psa_t psa;
mm_t m;
- unsigned long x;
+ unsigned long flags;
int ret = 0;
#ifdef DEBUG_IOCTL_TRACE
@@ -1916,7 +1886,7 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */
#endif
/* Disable interrupts & save flags */
- x = wv_splhi();
+ spin_lock_irqsave (&lp->lock, flags);
/* Look what is the request */
switch(cmd)
@@ -2528,7 +2498,7 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */
}
/* ReEnable interrupts & restore flags */
- wv_splx(x);
+ spin_unlock_irqrestore (&lp->lock, flags);
#ifdef DEBUG_IOCTL_TRACE
printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name);
@@ -2548,14 +2518,14 @@ wavelan_get_wireless_stats(device * dev)
net_local * lp = (net_local *) dev->priv;
mmr_t m;
iw_stats * wstats;
- unsigned long x;
+ unsigned long flags;
#ifdef DEBUG_IOCTL_TRACE
printk(KERN_DEBUG "%s: ->wavelan_get_wireless_stats()\n", dev->name);
#endif
/* Disable interrupts & save flags */
- x = wv_splhi();
+ spin_lock_irqsave (&lp->lock, flags);
if(lp == (net_local *) NULL)
return (iw_stats *) NULL;
@@ -2583,7 +2553,7 @@ wavelan_get_wireless_stats(device * dev)
wstats->discard.misc = 0L;
/* ReEnable interrupts & restore flags */
- wv_splx(x);
+ spin_unlock_irqrestore (&lp->lock, flags);
#ifdef DEBUG_IOCTL_TRACE
printk(KERN_DEBUG "%s: <-wavelan_get_wireless_stats()\n", dev->name);
@@ -2917,7 +2887,7 @@ wv_packet_write(device * dev,
{
net_local * lp = (net_local *) dev->priv;
ioaddr_t base = dev->base_addr;
- unsigned long x;
+ unsigned long flags;
int clen = length;
register u_short xmtdata_base = TX_BASE;
@@ -2925,7 +2895,7 @@ wv_packet_write(device * dev,
printk(KERN_DEBUG "%s: ->wv_packet_write(%d)\n", dev->name, length);
#endif
- x = wv_splhi();
+ spin_lock_irqsave (&lp->lock, flags);
/* Check if we need some padding */
if(clen < ETH_ZLEN)
@@ -2963,7 +2933,7 @@ wv_packet_write(device * dev,
add_timer(&lp->watchdog);
}
- wv_splx(x);
+ spin_unlock_irqrestore (&lp->lock, flags);
#ifdef DEBUG_TX_INFO
wv_packet_info((u_char *) buf, length, dev->name, "wv_packet_write");
@@ -2972,6 +2942,8 @@ wv_packet_write(device * dev,
#ifdef DEBUG_TX_TRACE
printk(KERN_DEBUG "%s: <-wv_packet_write()\n", dev->name);
#endif
+
+ netif_start_queue (dev);
}
/*------------------------------------------------------------------*/
@@ -2981,60 +2953,45 @@ wv_packet_write(device * dev,
* the packet. We also prevent reentrance. Then, we call the function
* to send the packet...
*/
-static int
-wavelan_packet_xmit(struct sk_buff * skb,
- device * dev)
+static int wavelan_packet_xmit (struct sk_buff *skb,
+ device * dev)
{
- net_local * lp = (net_local *)dev->priv;
+ net_local *lp = (net_local *) dev->priv;
#ifdef DEBUG_TX_TRACE
- printk(KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name,
- (unsigned) skb);
+ printk (KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name,
+ (unsigned) skb);
#endif
- /* This flag indicate that the hardware can't perform a transmission.
- * Theoritically, NET3 check it before sending a packet to the driver,
- * but in fact it never do that and pool continuously.
- * As the watchdog will abort too long transmissions, we are quite safe...
- */
- if(dev->tbusy)
- return(1);
-
- /*
- * For ethernet, fill in the header.
- */
+ /*
+ * For ethernet, fill in the header.
+ */
- /*
- * Block a timer-based transmit from overlapping a previous transmit.
- * In other words, prevent reentering this routine.
- */
- if(test_and_set_bit(0, (void *)&dev->tbusy) != 0)
-#ifdef DEBUG_TX_ERROR
- printk(KERN_INFO "%s: Transmitter access conflict.\n", dev->name);
-#endif
- else
- {
- /* If somebody has asked to reconfigure the controler, we can do it now */
- if(lp->reconfig_82593)
- {
- lp->reconfig_82593 = FALSE;
- wv_82593_config(dev);
- }
+ netif_stop_queue (dev);
+ /*
+ * Block a timer-based transmit from overlapping a previous transmit.
+ * In other words, prevent reentering this routine.
+ */
+ if (1) {
+ /* If somebody has asked to reconfigure the controler, we can do it now */
+ if (lp->reconfig_82593) {
+ lp->reconfig_82593 = FALSE;
+ wv_82593_config (dev);
+ }
#ifdef DEBUG_TX_ERROR
- if(skb->next)
- printk(KERN_INFO "skb has next\n");
+ if (skb->next)
+ printk (KERN_INFO "skb has next\n");
#endif
-
- wv_packet_write(dev, skb->data, skb->len);
- }
- dev_kfree_skb(skb);
+ wv_packet_write (dev, skb->data, skb->len);
+ }
+ dev_kfree_skb (skb);
#ifdef DEBUG_TX_TRACE
- printk(KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name);
+ printk (KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name);
#endif
- return(0);
+ return (0);
}
/********************** HARDWARE CONFIGURATION **********************/
@@ -3245,7 +3202,8 @@ static int
wv_ru_stop(device * dev)
{
ioaddr_t base = dev->base_addr;
- unsigned long opri;
+ net_local *lp = (net_local *) dev->priv;
+ unsigned long flags;
int status;
int spin;
@@ -3262,10 +3220,10 @@ wv_ru_stop(device * dev)
do
{
udelay(10);
- opri = wv_splhi();
+ spin_lock_irqsave (&lp->lock, flags);
outb(OP0_NOP | CR0_STATUS_3, LCCR(base));
status = inb(LCSR(base));
- wv_splx(opri);
+ spin_unlock_irqrestore (&lp->lock, flags);
}
while(((status & SR3_RCV_STATE_MASK) != SR3_RCV_IDLE) && (spin++ < 300));
@@ -3273,10 +3231,10 @@ wv_ru_stop(device * dev)
do
{
udelay(10);
- opri = wv_splhi();
+ spin_lock_irqsave (&lp->lock, flags);
outb(OP0_NOP | CR0_STATUS_3, LCCR(base));
status = inb(LCSR(base));
- wv_splx(opri);
+ spin_unlock_irqrestore (&lp->lock, flags);
}
while(((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE) && (spin++ < 300));
@@ -3347,16 +3305,16 @@ wv_ru_start(device * dev)
#ifdef DEBUG_I82593_SHOW
{
int status;
- int opri;
+ unsigned long flags;
int i = 0;
/* spin until the chip starts receiving */
do
{
- opri = wv_splhi();
+ spin_lock_irqsave (&lp->lock, flags);
outb(OP0_NOP | CR0_STATUS_3, LCCR(base));
status = inb(LCSR(base));
- wv_splx(opri);
+ spin_unlock_irqrestore (&lp->lock, flags);
if(i++ > 10000)
break;
}
@@ -3838,7 +3796,7 @@ wv_pcmcia_config(dev_link_t * link)
/* Feed device with this info... */
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- dev->tbusy = 0;
+ netif_start_queue (dev);
#ifdef DEBUG_CONFIG_INFO
printk(KERN_DEBUG "wv_pcmcia_config: MEMSTART 0x%x IRQ %d IOPORT 0x%x\n",
@@ -3991,13 +3949,7 @@ wavelan_interrupt(int irq,
lp = (net_local *) dev->priv;
base = dev->base_addr;
- /* Prevent reentrance. What should we do here ? */
-#ifdef DEBUG_INTERRUPT_ERROR
- if(dev->interrupt)
- printk(KERN_INFO "%s: wavelan_interrupt(): Re-entering the interrupt handler.\n",
- dev->name);
-#endif
- dev->interrupt = 1;
+ spin_lock (&lp->lock);
/* Treat all pending interrupts */
while(1)
@@ -4201,8 +4153,7 @@ wavelan_interrupt(int irq,
lp->stats.collisions += (tx_status & TX_NCOL_MASK);
lp->stats.tx_packets++;
- dev->tbusy = FALSE;
- mark_bh(NET_BH);
+ netif_wake_queue (dev);
outb(CR0_INT_ACK | OP0_NOP, LCCR(base)); /* Acknowledge the interrupt */
}
else /* if interrupt = transmit done or retransmit done */
@@ -4214,7 +4165,8 @@ wavelan_interrupt(int irq,
outb(CR0_INT_ACK | OP0_NOP, LCCR(base)); /* Acknowledge the interrupt */
}
}
- dev->interrupt = FALSE;
+
+ spin_unlock_irq (&lp->lock);
#ifdef DEBUG_INTERRUPT_TRACE
printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name);
@@ -4296,7 +4248,7 @@ wavelan_watchdog(u_long a)
#endif
/* We are no more waiting for something... */
- dev->tbusy = 0;
+ netif_start_queue (dev);
#ifdef DEBUG_INTERRUPT_TRACE
printk(KERN_DEBUG "%s: <-wavelan_watchdog()\n", dev->name);
@@ -4349,9 +4301,7 @@ wavelan_open(device * dev)
return FALSE;
if(!wv_ru_start(dev))
wv_hw_reset(dev); /* If problem : reset */
- dev->interrupt = 0;
- dev->start = 1;
- dev->tbusy = 0;
+ netif_start_queue (dev);
/* Mark the device as used */
link->open++;
@@ -4385,6 +4335,8 @@ wavelan_close(device * dev)
(unsigned int) dev);
#endif
+ netif_stop_queue (dev);
+
/* If the device isn't open, then nothing to do */
if(!link->open)
{
@@ -4408,10 +4360,9 @@ wavelan_close(device * dev)
MOD_DEC_USE_COUNT;
/* If the card is still present */
- if(dev->start)
+ if (netif_device_present(dev))
{
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue (dev);
/* Stop receiving new messages and wait end of transmission */
wv_ru_stop(dev);
@@ -4549,7 +4500,7 @@ wavelan_attach(void)
/* Other specific data */
/* Provide storage area for device name */
dev->name = ((net_local *)dev->priv)->node.dev_name;
- dev->tbusy = 1;
+ netif_start_queue (dev);
dev->mtu = WAVELAN_MTU;
/* Register with Card Services */
@@ -4711,7 +4662,7 @@ wavelan_event(event_t event, /* The event received */
if(link->state & DEV_CONFIG)
{
/* Accept no more transmissions */
- dev->tbusy = 1; dev->start = 0;
+ netif_device_detach(dev);
/* Release the card */
wv_pcmcia_release((u_long) link);
@@ -4748,10 +4699,8 @@ wavelan_event(event_t event, /* The event received */
if(link->state & DEV_CONFIG)
{
if(link->open)
- {
- dev->tbusy = 1;
- dev->start = 0;
- }
+ netif_device_detach(dev);
+
CardServices(ReleaseConfiguration, link->handle);
}
break;
@@ -4766,8 +4715,7 @@ wavelan_event(event_t event, /* The event received */
if(link->open) /* If RESET -> True, If RESUME -> False ??? */
{
wv_hw_reset(dev);
- dev->tbusy = 0;
- dev->start = 1;
+ netif_device_attach(dev);
}
}
break;
diff --git a/drivers/net/pcmcia/wavelan_cs.h b/drivers/net/pcmcia/wavelan_cs.h
index 0f5be4f37..f35a81ac9 100644
--- a/drivers/net/pcmcia/wavelan_cs.h
+++ b/drivers/net/pcmcia/wavelan_cs.h
@@ -550,6 +550,7 @@ typedef u_char mac_addr[WAVELAN_ADDR_SIZE]; /* Hardware address */
*/
struct net_local
{
+ spinlock_t lock;
dev_node_t node; /* ???? What is this stuff ???? */
device * dev; /* Reverse link... */
dev_link_t * link; /* pcmcia structure */
@@ -609,10 +610,6 @@ void wv_roam_cleanup(struct net_device *dev);
#endif /* WAVELAN_ROAMING */
/* ----------------------- MISC SUBROUTINES ------------------------ */
-static inline unsigned long /* flags */
- wv_splhi(void); /* Disable interrupts */
-static inline void
- wv_splx(unsigned long); /* ReEnable interrupts : flags */
static void
cs_error(client_handle_t, /* Report error to cardmgr */
int,
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 0c4f72ae7..b63ff08d5 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -410,6 +410,7 @@ typedef struct local_info_t {
int suspended;
unsigned last_ptr_value; /* last packets transmitted value */
const char *manf_str;
+ spinlock_t lock;
} local_info_t;
/****************
@@ -429,6 +430,7 @@ static void do_reset(struct net_device *dev, int full);
static int init_mii(struct net_device *dev);
static void do_powerdown(struct net_device *dev);
static int do_stop(struct net_device *dev);
+static void xirc_tx_timeout (struct net_device *dev);
/*=============== Helper functions =========================*/
static void
@@ -691,6 +693,8 @@ xirc2ps_attach(void)
local = kmalloc(sizeof(*local), GFP_KERNEL);
if (!local) return NULL;
memset(local, 0, sizeof(*local));
+
+ local->lock = SPIN_LOCK_UNLOCKED;
link = &local->link; dev = &local->dev;
link->priv = dev->priv = local;
@@ -717,7 +721,9 @@ xirc2ps_attach(void)
dev->init = &do_init;
dev->open = &do_open;
dev->stop = &do_stop;
- dev->tbusy = 1;
+ dev->tx_timeout = xirc_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+ netif_start_queue(dev);
/* Register with Card Services */
link->next = dev_list;
@@ -1233,7 +1239,7 @@ xirc2ps_config(dev_link_t * link)
/* we can now register the device with the net subsystem */
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- dev->tbusy = 0;
+ netif_start_queue(dev);
if ((err=register_netdev(dev))) {
printk(KNOT_XIRC "register_netdev() failed\n");
goto config_error;
@@ -1334,7 +1340,7 @@ xirc2ps_event(event_t event, int priority,
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
- dev->tbusy = 1; dev->start = 0;
+ netif_device_detach(dev);
link->release.expires = jiffies + HZ / 20;
add_timer(&link->release);
}
@@ -1349,7 +1355,7 @@ xirc2ps_event(event_t event, int priority,
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
if (link->open) {
- dev->tbusy = 1; dev->start = 0;
+ netif_device_detach(dev);
lp->suspended=1;
do_powerdown(dev);
}
@@ -1365,7 +1371,7 @@ xirc2ps_event(event_t event, int priority,
if (link->open) {
do_reset(dev,1);
lp->suspended=0;
- dev->tbusy = 0; dev->start = 1;
+ netif_device_attach(dev);
}
}
break;
@@ -1393,14 +1399,10 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* -- on a laptop?
*/
- if (!dev->start)
- return;
-
- if (dev->interrupt) {
- printk(KERR_XIRC "re-entering isr on irq %d (dev=%p)\n", irq, dev);
+ spin_lock (&lp->lock);
+ if (!netif_device_present(dev))
return;
- }
- dev->interrupt = 1;
+
ioaddr = dev->base_addr;
if (lp->mohawk) { /* must disable the interrupt */
PutByte(XIRCREG_CR, 0);
@@ -1555,8 +1557,7 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
DEBUG(0, "PTR not changed?\n");
} else
lp->stats.tx_packets += lp->last_ptr_value - n;
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_wake_queue(dev);
}
if (tx_status & 0x0002) { /* Execessive collissions */
DEBUG(0, "tx restarted due to execssive collissions\n");
@@ -1595,7 +1596,9 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
goto loop_entry;
}
SelectPage(saved_page);
- dev->interrupt = 0;
+
+ spin_unlock (&lp->lock);
+
PutByte(XIRCREG_CR, EnableIntr); /* re-enable interrupts */
/* Instead of dropping packets during a receive, we could
* force an interrupt with this command:
@@ -1605,44 +1608,39 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*====================================================================*/
-static int
-do_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static void xirc_tx_timeout (struct net_device *dev)
{
- local_info_t *lp = dev->priv;
- ioaddr_t ioaddr = dev->base_addr;
- int okay;
- unsigned freespace;
- unsigned pktlen = skb? skb->len : 0;
-
- DEBUG(1, "do_start_xmit(skb=%p, dev=%p) len=%u\n",
- skb, dev, pktlen);
-
- /* Transmitter timeout, serious problems */
- if (dev->tbusy) {
- int tickssofar = jiffies - dev->trans_start;
+ local_info_t *lp = dev->priv;
if (lp->suspended) {
- dev_kfree_skb (skb);
dev->trans_start = jiffies;
lp->stats.tx_dropped++;
- return 0;
+ netif_start_queue(dev);
+ return;
}
- if (tickssofar < TX_TIMEOUT)
- return 1;
printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);
lp->stats.tx_errors++;
/* reset the card */
do_reset(dev,1);
dev->trans_start = jiffies;
- dev->tbusy = 0;
- }
+ netif_start_queue(dev);
+}
- if (test_and_set_bit(0, (void*)&dev->tbusy)) {
- printk(KWRN_XIRC "transmitter access conflict\n");
- dev_kfree_skb (skb);
- return 0;
- }
+
+static int
+do_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ local_info_t *lp = dev->priv;
+ ioaddr_t ioaddr = dev->base_addr;
+ int okay;
+ unsigned freespace;
+ unsigned pktlen = skb? skb->len : 0;
+
+ DEBUG(1, "do_start_xmit(skb=%p, dev=%p) len=%u\n",
+ skb, dev, pktlen);
+
+ netif_stop_queue(dev);
/* adjust the packet length to min. required
* and hope that the buffer is large enough
@@ -1664,7 +1662,6 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev)
DEBUG(2 + (okay ? 2 : 0), "%s: avail. tx space=%u%s\n",
dev->name, freespace, okay ? " (okay)":" (not enough)");
if (!okay) { /* not enough space */
- dev->tbusy = 1;
return 1; /* upper layer may decide to requeue this packet */
}
/* send the packet */
@@ -1678,7 +1675,7 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb (skb);
dev->trans_start = jiffies;
- dev->tbusy = 0;
+ netif_start_queue(dev);
lp->stats.tx_bytes += pktlen;
return 0;
}
@@ -1823,7 +1820,7 @@ do_open(struct net_device *dev)
link->open++;
MOD_INC_USE_COUNT;
- dev->interrupt = 0; dev->tbusy = 0; dev->start = 1;
+ netif_start_queue(dev);
lp->suspended = 0;
do_reset(dev,1);
@@ -2141,8 +2138,7 @@ do_stop(struct net_device *dev)
if (!link)
return -ENODEV;
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue(dev);
SelectPage(0);
PutByte(XIRCREG_CR, 0); /* disable interrupts */
@@ -2152,7 +2148,7 @@ do_stop(struct net_device *dev)
PutByte(XIRCREG4_GPR1, 0); /* clear bit 0: power down */
SelectPage(0);
- link->open--; dev->start = 0;
+ link->open--;
if (link->state & DEV_STALE_CONFIG) {
link->release.expires = jiffies + HZ/20;
link->state |= DEV_RELEASE_PENDING;
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 30bc7a7ba..7374eac66 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -1162,7 +1162,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
/* We must free the original skb */
if (lp->tx_skbuff[entry]) {
- dev_kfree_skb(lp->tx_skbuff[entry]);
+ dev_kfree_skb_irq(lp->tx_skbuff[entry]);
lp->tx_skbuff[entry] = 0;
}
dirty_tx++;
@@ -1176,8 +1176,8 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
}
#endif
if (lp->tx_full &&
- test_bit(LINK_STATE_XOFF, &dev->flags) &&
- dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
+ netif_queue_stopped(dev) &&
+ dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
/* The ring is no longer full, clear tbusy. */
lp->tx_full = 0;
netif_wake_queue (dev);
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index 75a703886..d86ce1d85 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -442,8 +442,7 @@ plip_timer_bh(struct net_device *dev)
struct net_local *nl = (struct net_local *)dev->priv;
if (!(atomic_read (&nl->kill_timer))) {
- if (!dev->interrupt)
- plip_interrupt (-1, dev, NULL);
+ plip_interrupt (-1, dev, NULL);
queue_task (&nl->timer, &tq_timer);
}
@@ -521,7 +520,7 @@ plip_bh_timeout_error(struct net_device *dev, struct net_local *nl,
synchronize_irq();
}
disable_parport_interrupts (dev);
- dev->tbusy = 1;
+ netif_stop_queue (dev);
nl->connection = PLIP_CN_ERROR;
write_data (dev, 0x00);
@@ -597,7 +596,6 @@ plip_receive_packet(struct net_device *dev, struct net_local *nl,
DISABLE(dev->irq);
/* Don't need to synchronize irq, as we can safely ignore it */
disable_parport_interrupts (dev);
- dev->interrupt = 0;
write_data (dev, 0x01); /* send ACK */
if (net_debug > 2)
printk(KERN_DEBUG "%s: receive start\n", dev->name);
@@ -869,8 +867,7 @@ plip_connection_close(struct net_device *dev, struct net_local *nl,
spin_lock_irq(&nl->lock);
if (nl->connection == PLIP_CN_CLOSING) {
nl->connection = PLIP_CN_NONE;
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue (dev);
}
spin_unlock_irq(&nl->lock);
if (nl->should_relinquish) {
@@ -893,11 +890,10 @@ plip_error(struct net_device *dev, struct net_local *nl,
printk(KERN_DEBUG "%s: reset interface.\n", dev->name);
nl->connection = PLIP_CN_NONE;
nl->should_relinquish = 0;
- dev->tbusy = 0;
- dev->interrupt = 0;
+ netif_start_queue (dev);
enable_parport_interrupts (dev);
ENABLE(dev->irq);
- mark_bh(NET_BH);
+ netif_wake_queue (dev);
} else {
nl->is_deferred = 1;
queue_task(&nl->deferred, &tq_timer);
@@ -923,23 +919,22 @@ plip_interrupt(int irq, void *dev_id, struct pt_regs * regs)
nl = (struct net_local *)dev->priv;
rcv = &nl->rcv_data;
- if (dev->interrupt)
- return;
+ spin_lock_irq (&nl->lock);
c0 = read_status(dev);
if ((c0 & 0xf8) != 0xc0) {
if ((dev->irq != -1) && (net_debug > 1))
printk(KERN_DEBUG "%s: spurious interrupt\n", dev->name);
+ spin_unlock_irq (&nl->lock);
return;
}
- dev->interrupt = 1;
+
if (net_debug > 3)
printk(KERN_DEBUG "%s: interrupt.\n", dev->name);
- spin_lock_irq(&nl->lock);
switch (nl->connection) {
case PLIP_CN_CLOSING:
- dev->tbusy = 0;
+ netif_start_queue (dev);
case PLIP_CN_NONE:
case PLIP_CN_SEND:
dev->last_rx = jiffies;
@@ -948,21 +943,20 @@ plip_interrupt(int irq, void *dev_id, struct pt_regs * regs)
nl->timeout_count = 0;
queue_task(&nl->immediate, &tq_immediate);
mark_bh(IMMEDIATE_BH);
- spin_unlock_irq(&nl->lock);
break;
case PLIP_CN_RECEIVE:
/* May occur because there is race condition
around test and set of dev->interrupt.
Ignore this interrupt. */
- spin_unlock_irq(&nl->lock);
break;
case PLIP_CN_ERROR:
- spin_unlock_irq(&nl->lock);
printk(KERN_ERR "%s: receive interrupt in error state\n", dev->name);
break;
}
+
+ spin_unlock_irq(&nl->lock);
}
static int
@@ -971,7 +965,7 @@ plip_tx_packet(struct sk_buff *skb, struct net_device *dev)
struct net_local *nl = (struct net_local *)dev->priv;
struct plip_local *snd = &nl->snd_data;
- if (dev->tbusy)
+ if (netif_queue_stopped(dev))
return 1;
/* We may need to grab the bus */
@@ -981,14 +975,11 @@ plip_tx_packet(struct sk_buff *skb, struct net_device *dev)
nl->port_owner = 1;
}
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
- printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
- return 1;
- }
-
+ netif_stop_queue (dev);
+
if (skb->len > dev->mtu + dev->hard_header_len) {
printk(KERN_WARNING "%s: packet too big, %d.\n", dev->name, (int)skb->len);
- dev->tbusy = 0;
+ netif_start_queue (dev);
return 0;
}
@@ -1007,7 +998,8 @@ plip_tx_packet(struct sk_buff *skb, struct net_device *dev)
queue_task(&nl->immediate, &tq_immediate);
mark_bh(IMMEDIATE_BH);
spin_unlock_irq(&nl->lock);
-
+
+ netif_start_queue (dev);
return 0;
}
@@ -1115,9 +1107,7 @@ plip_open(struct net_device *dev)
}
}
- dev->interrupt = 0;
- dev->start = 1;
- dev->tbusy = 0;
+ netif_start_queue (dev);
MOD_INC_USE_COUNT;
return 0;
@@ -1131,8 +1121,7 @@ plip_close(struct net_device *dev)
struct plip_local *snd = &nl->snd_data;
struct plip_local *rcv = &nl->rcv_data;
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue (dev);
DISABLE(dev->irq);
synchronize_irq();
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index fad5da9fe..ddfed868e 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -30,6 +30,7 @@
#include <linux/kmod.h>
#include <linux/init.h>
#include <linux/list.h>
+#include <linux/devfs_fs_kernel.h>
#include <linux/netdevice.h>
#include <linux/poll.h>
#include <linux/ppp_defs.h>
@@ -549,6 +550,8 @@ static struct file_operations ppp_device_fops = {
#define PPP_MAJOR 108
+static devfs_handle_t devfs_handle = NULL;
+
/* Called at boot time if ppp is compiled into the kernel,
or at module load time (from init_module) if compiled as a module. */
int __init ppp_init(void)
@@ -561,9 +564,13 @@ int __init ppp_init(void)
#endif
printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n");
- err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops);
+ err = devfs_register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops);
if (err)
printk(KERN_ERR "failed to register PPP device (%d)\n", err);
+ devfs_handle = devfs_register (NULL, "ppp", 0, DEVFS_FL_NONE,
+ PPP_MAJOR, 0,
+ S_IFCHR | S_IRUSR | S_IWUSR, 0, 0,
+ &ppp_device_fops, NULL);
#ifndef MODULE
#ifdef CONFIG_PPP_ASYNC
ppp_async_init();
@@ -1613,7 +1620,8 @@ cleanup_module(void)
/* should never happen */
if (!list_empty(&all_ppp_units))
printk(KERN_ERR "PPP: removing module but units remain!\n");
- if (unregister_chrdev(PPP_MAJOR, "ppp") != 0)
+ if (devfs_unregister_chrdev(PPP_MAJOR, "ppp") != 0)
printk(KERN_ERR "PPP: failed to unregister PPP device\n");
+ devfs_unregister (devfs_handle);
}
#endif /* MODULE */
diff --git a/drivers/net/rcpci45.c b/drivers/net/rcpci45.c
index 396e783c5..27b0c6474 100644
--- a/drivers/net/rcpci45.c
+++ b/drivers/net/rcpci45.c
@@ -309,7 +309,6 @@ RCfound_device(int memaddr, int irq,
#endif
dev->base_addr = (unsigned long)vaddr;
dev->irq = irq;
- dev->interrupt = 0;
/*
* Request a shared interrupt line.
@@ -430,6 +429,7 @@ RCopen(struct net_device *dev)
printk("rc: RCopen: posted %d buffers\n", (uint)pDpa->numOutRcvBuffers);
#endif
MOD_INC_USE_COUNT;
+ netif_start_queue(dev);
return 0;
}
@@ -441,29 +441,26 @@ RC_xmit_packet(struct sk_buff *skb, struct net_device *dev)
singleTCB tcb;
psingleTCB ptcb = &tcb;
RC_RETURN status = 0;
-
- if (dev->tbusy || pDpa->shutdown || pDpa->reboot)
- {
+
+ netif_stop_queue(dev);
+
+ if (pDpa->shutdown || pDpa->reboot)
+ {
#ifdef RCDEBUG
printk("rc: RC_xmit_packet: tbusy!\n");
#endif
- dev->tbusy = 1;
return 1;
- }
-
- if ( skb->len <= 0 )
- {
- printk("RC_xmit_packet: skb->len less than 0!\n");
- return 0;
}
-
+
/*
* The user is free to reuse the TCB after RCI2OSendPacket() returns, since
* the function copies the necessary info into its own private space. Thus,
* our TCB can be a local structure. The skb, on the other hand, will be
* freed up in our interrupt handler.
*/
+
ptcb->bcount = 1;
+
/*
* we'll get the context when the adapter interrupts us to tell us that
* the transmision is done. At that time, we can free skb.
@@ -483,13 +480,12 @@ RC_xmit_packet(struct sk_buff *skb, struct net_device *dev)
#ifdef RCDEBUG
printk("rc: RC send error 0x%x\n", (uint)status);
#endif
- dev->tbusy = 1;
return 1;
}
else
{
dev->trans_start = jiffies;
- // dev->tbusy = 0;
+ netif_wake_queue(dev);
}
/*
* That's it!
@@ -546,10 +542,9 @@ RCxmit_callback(U32 Status,
printk("rc: skb = 0x%x\n", (uint)skb);
#endif
BufferContext++;
- dev_kfree_skb (skb);
+ dev_kfree_skb_irq(skb);
}
- dev->tbusy = 0;
-
+ netif_wake_queue(dev);
}
static void
@@ -811,14 +806,8 @@ RCinterrupt(int irq, void *dev_id, struct pt_regs *regs)
(uint)pDpa, (uint)dev, (uint)pDpa->id);
printk("dev = 0x%x\n", (uint)dev);
#endif
- if (dev->interrupt)
- printk("%s: Re-entering the interrupt handler.\n", dev->name);
- dev->interrupt = 1;
RCProcI2OMsgQ(pDpa->id);
- dev->interrupt = 0;
-
- return;
}
@@ -870,7 +859,7 @@ static void rc_timer(unsigned long data)
(uint)pDpa->numOutRcvBuffers);
}
printk("rc: Initialization done.\n");
- dev->tbusy=0;
+ netif_wake_queue(dev);
retry=0;
return;
case RC_RTN_FREE_Q_EMPTY:
@@ -913,6 +902,8 @@ RCclose(struct net_device *dev)
PDPA pDpa = (PDPA) dev->priv;
+ netif_stop_queue(dev);
+
#ifdef RCDEBUG
printk("rc: RCclose\r\n");
#endif
diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8129.c
index e5a5c6115..b60a62608 100644
--- a/drivers/net/rtl8139.c
+++ b/drivers/net/rtl8129.c
@@ -1,4 +1,4 @@
-/* rtl8139.c: A RealTek RTL8129/8139 Fast Ethernet driver for Linux. */
+/* rtl8129.c: A RealTek RTL8129 Fast Ethernet driver for Linux. */
/*
Written 1997-1999 by Donald Becker.
@@ -6,8 +6,7 @@
of the GNU Public License, incorporated herein by reference.
All other rights reserved.
- This driver is for boards based on the RTL8129 and RTL8139 PCI ethernet
- chips.
+ This driver is for boards based on the RTL8129 PCI ethernet chip.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
@@ -20,7 +19,7 @@
*/
static const char *version =
-"rtl8139.c:v1.07 5/6/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html\n";
+"rtl8129.c:v1.07 5/6/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html\n";
/* A few user-configurable values. */
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
@@ -66,6 +65,7 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
#include <linux/ioport.h>
#include <linux/malloc.h>
#include <linux/interrupt.h>
+#include <linux/init.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -96,11 +96,6 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
#else
#define PCI_SUPPORT_VER2
#endif
-#if LINUX_VERSION_CODE < 0x20159
-#define dev_free_skb(skb) dev_kfree_skb(skb, FREE_WRITE);
-#else
-#define dev_free_skb(skb) dev_kfree_skb(skb);
-#endif
/* The I/O extent. */
#define RTL8129_TOTAL_SIZE 0x80
@@ -175,12 +170,14 @@ static struct net_device * rtl8129_probe1(struct pci_dev *pdev, int pci_bus,
static struct pci_id_info pci_tbl[] =
{{ "RealTek RTL8129 Fast Ethernet",
0x10ec, 0x8129, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
+#ifdef USE_8139_SUPPORT_ALSO
{ "RealTek RTL8139 Fast Ethernet",
0x10ec, 0x8139, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
{ "SMC1211TX EZCard 10/100 (RealTek RTL8139)",
0x1113, 0x1211, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
{ "Accton MPX5030 (RealTek RTL8139)",
0x1113, 0x1211, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
+#endif
{0,}, /* 0 terminated list. */
};
@@ -243,7 +240,7 @@ enum CSCRBits {
CSCR_LinkStatusBits=0x0f000, CSCR_LinkDownOffCmd=0x003c0,
CSCR_LinkDownCmd=0x0f3c0,
};
-unsigned long param[4][4]={
+static const unsigned long param[4][4]={
{0x0cb39de43,0x0cb39ce43,0x0fb38de03,0x0cb38de43},
{0x0cb39de43,0x0cb39ce43,0x0cb39ce83,0x0cb39ce83},
{0x0cb39de43,0x0cb39ce43,0x0cb39ce83,0x0cb39ce83},
@@ -289,17 +286,13 @@ struct rtl8129_private {
unsigned int mediasense:1; /* Media sensing in progress. */
};
-#ifdef MODULE
-#if LINUX_VERSION_CODE > 0x20115
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
-MODULE_DESCRIPTION("RealTek RTL8129/8139 Fast Ethernet driver");
+MODULE_DESCRIPTION("RealTek RTL8129 Fast Ethernet driver");
MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
MODULE_PARM(multicast_filter_limit, "i");
MODULE_PARM(max_interrupt_work, "i");
MODULE_PARM(debug, "i");
-#endif
-#endif
static int rtl8129_open(struct net_device *dev);
static int read_eeprom(long ioaddr, int location);
@@ -326,7 +319,7 @@ static struct net_device *root_rtl8129_dev = NULL;
well when dynamically adding drivers. So instead we detect just the
Rtl81*9 cards in slot order. */
-int rtl8139_probe(void)
+static int __init rtl8129_probe(void)
{
int cards_found = 0;
int pci_index = 0;
@@ -789,12 +782,12 @@ static void rtl8129_timer(unsigned long data)
if (inw(ioaddr + IntrStatus) & (TxOK | RxOK)) {
int status = inw(ioaddr + IntrStatus);
if (status & (TxOK | RxOK)) { /* Double check */
- printk(KERN_ERR "%s: RTL8139 Interrupt line blocked, status %x.\n",
+ printk(KERN_ERR "%s: RTL8129 Interrupt line blocked, status %x.\n",
dev->name, status);
rtl8129_interrupt(dev->irq, dev, 0);
}
}
- if (test_bit(LINK_STATE_XOFF, &dev->state) &&
+ if (netif_queue_stopped(dev) &&
(jiffies - dev->trans_start) >= 2*TX_TIMEOUT)
rtl8129_tx_timeout(dev);
@@ -915,7 +908,7 @@ static void rtl8129_tx_timeout(struct net_device *dev)
saved_skb[j] = rp->skb;
if (rp->mapping != 0) {
- pci_unmap_single(tp->pdev, rp->mapping, rp->skb->len);
+ pci_unmap_single(tp->pdev, rp->mapping, rp->skb->len, PCI_DMA_TODEVICE);
rp->mapping = 0;
}
}
@@ -929,7 +922,7 @@ static void rtl8129_tx_timeout(struct net_device *dev)
ioaddr + TxAddr0 + i*4);
} else {
tp->tx_info[i].mapping =
- pci_map_single(tp->pdev, skb->data, skb->len);
+ pci_map_single(tp->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
outl(tp->tx_info[i].mapping, ioaddr + TxAddr0 + i*4);
}
/* Note: the chip doesn't have auto-pad! */
@@ -947,6 +940,7 @@ static void rtl8129_tx_timeout(struct net_device *dev)
tp->tx_full = 0;
} else {
tp->tx_full = 1;
+ netif_stop_queue(dev);
}
}
@@ -997,7 +991,7 @@ rtl8129_start_xmit(struct sk_buff *skb, struct net_device *dev)
ioaddr + TxAddr0 + entry*4);
} else {
tp->tx_info[entry].mapping =
- pci_map_single(tp->pdev, skb->data, skb->len);
+ pci_map_single(tp->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
outl(tp->tx_info[entry].mapping, ioaddr + TxAddr0 + entry*4);
}
/* Note: the chip doesn't have auto-pad! */
@@ -1091,12 +1085,13 @@ static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
if (tp->tx_info[entry].mapping != 0) {
pci_unmap_single(tp->pdev,
tp->tx_info[entry].mapping,
- tp->tx_info[entry].skb->len);
+ tp->tx_info[entry].skb->len,
+ PCI_DMA_TODEVICE);
tp->tx_info[entry].mapping = 0;
}
/* Free the original skb. */
- dev_free_skb(tp->tx_info[entry].skb);
+ dev_kfree_skb_irq(tp->tx_info[entry].skb);
tp->tx_info[entry].skb = NULL;
if (tp->tx_full) {
/* The ring is no longer full, wake the queue. */
@@ -1321,8 +1316,8 @@ rtl8129_close(struct net_device *dev)
if (skb) {
if (mapping)
- pci_unmap_single(tp->pdev, mapping, skb->len);
- dev_free_skb(skb);
+ pci_unmap_single(tp->pdev, mapping, skb->len, PCI_DMA_TODEVICE);
+ dev_kfree_skb(skb);
}
tp->tx_info[i].skb = NULL;
tp->tx_info[i].mapping = 0;
@@ -1372,7 +1367,7 @@ rtl8129_get_stats(struct net_device *dev)
struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
long ioaddr = dev->base_addr;
- if (test_bit(LINK_STATE_START, &dev->state)) {
+ if (netif_running(dev)) {
tp->stats.rx_missed_errors += inl(ioaddr + RxMissed);
outl(0, ioaddr + RxMissed);
}
@@ -1440,14 +1435,8 @@ static void set_rx_mode(struct net_device *dev)
return;
}
-#ifdef MODULE
-int init_module(void)
-{
- return rtl8139_probe();
-}
-void
-cleanup_module(void)
+static void __exit rtl8129_cleanup (void)
{
struct net_device *next_dev;
@@ -1465,12 +1454,13 @@ cleanup_module(void)
}
}
-#endif /* MODULE */
-
+module_init(rtl8129_probe);
+module_exit(rtl8129_cleanup);
+
/*
* Local variables:
- * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8139.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
- * SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8139.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8129.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ * SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8129.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
* c-indent-level: 4
* c-basic-offset: 4
* tab-width: 4
diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c
index 5bdb0176a..9b17cc79d 100644
--- a/drivers/net/sb1000.c
+++ b/drivers/net/sb1000.c
@@ -1002,10 +1002,8 @@ sb1000_open(struct net_device *dev)
"(should be %x.%02x)\n", name, version[0], version[1],
FirmwareVersion[0], FirmwareVersion[1]);
- dev->interrupt = 0;
- dev->tbusy = 0;
- dev->start = 1;
+ netif_start_queue(dev);
MOD_INC_USE_COUNT;
return 0; /* Always succeed */
}
@@ -1122,10 +1120,6 @@ static void sb1000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
irq);
return;
}
- if (dev->interrupt)
- printk(KERN_ERR "%s: Re-entering the interrupt handler.\n",
- dev->name);
- dev->interrupt = 1;
ioaddr[0] = dev->base_addr;
/* rmem_end holds the second I/O address - fv */
@@ -1135,7 +1129,6 @@ static void sb1000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* is it a good interrupt? */
st = inb(ioaddr[1] + 6);
if (!(st & 0x08 && st & 0x20)) {
- dev->interrupt = 0;
return;
}
@@ -1167,7 +1160,6 @@ static void sb1000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
lp->rx_error_count = 0;
}
- dev->interrupt = 0;
return;
}
@@ -1186,9 +1178,8 @@ static int sb1000_close(struct net_device *dev)
if (sb1000_debug > 2)
printk(KERN_DEBUG "%s: Shutting down sb1000.\n", dev->name);
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
+
ioaddr[0] = dev->base_addr;
/* rmem_end holds the second I/O address - fv */
ioaddr[1] = dev->rmem_end;
diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c
index d2756c92f..f7d86c103 100644
--- a/drivers/net/seeq8005.c
+++ b/drivers/net/seeq8005.c
@@ -83,6 +83,7 @@ extern int seeq8005_probe(struct net_device *dev);
static int seeq8005_probe1(struct net_device *dev, int ioaddr);
static int seeq8005_open(struct net_device *dev);
+static void seeq8005_timeout(struct net_device *dev);
static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev);
static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void seeq8005_rx(struct net_device *dev);
@@ -324,9 +325,11 @@ static int __init seeq8005_probe1(struct net_device *dev, int ioaddr)
dev->open = seeq8005_open;
dev->stop = seeq8005_close;
- dev->hard_start_xmit = seeq8005_send_packet;
- dev->get_stats = seeq8005_get_stats;
- dev->set_multicast_list = &set_multicast_list;
+ dev->hard_start_xmit = seeq8005_send_packet;
+ dev->tx_timeout = seeq8005_timeout;
+ dev->watchdog_timeo = HZ/20;
+ dev->get_stats = seeq8005_get_stats;
+ dev->set_multicast_list = set_multicast_list;
/* Fill in the fields of the device structure with ethernet values. */
ether_setup(dev);
@@ -344,8 +347,7 @@ static int __init seeq8005_probe1(struct net_device *dev, int ioaddr)
registers that "should" only need to be set once at boot, so that
there is non-reboot way to recover if something goes wrong.
*/
-static int
-seeq8005_open(struct net_device *dev)
+static int seeq8005_open(struct net_device *dev)
{
struct net_local *lp = (struct net_local *)dev->priv;
@@ -363,46 +365,34 @@ seeq8005_open(struct net_device *dev)
lp->open_time = jiffies;
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue(dev);
return 0;
}
-static int
-seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev)
+static void seeq8005_timeout(struct net_device *dev)
{
int ioaddr = dev->base_addr;
- struct net_local *lp = (struct net_local *)dev->priv;
+ printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
+ tx_done(dev) ? "IRQ conflict" : "network cable problem");
+ /* Try to restart the adaptor. */
+ seeq8005_init(dev, 1);
+ dev->trans_start = jiffies;
+ netif_wake_queue(dev);
+}
- if (dev->tbusy) {
- /* If we get here, some higher level has decided we are broken.
- There should really be a "kick me" function call instead. */
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 5)
- return 1;
- printk("%s: transmit timed out, %s?\n", dev->name,
- tx_done(dev) ? "IRQ conflict" : "network cable problem");
- /* Try to restart the adaptor. */
- seeq8005_init(dev, 1);
- dev->tbusy=0;
- dev->trans_start = jiffies;
- }
+static int seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+ short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+ unsigned char *buf = skb->data;
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk("%s: Transmitter access conflict.\n", dev->name);
- else {
- short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned char *buf = skb->data;
-
- hardware_send_packet(dev, buf, length);
- dev->trans_start = jiffies;
- lp->stats.tx_bytes += length;
- }
+ /* Block a timer-based transmit from overlapping */
+ netif_stop_queue(dev);
+
+ hardware_send_packet(dev, buf, length);
+ dev->trans_start = jiffies;
+ lp->stats.tx_bytes += length;
dev_kfree_skb (skb);
-
/* You might need to clean up and record Tx statistics here. */
return 0;
@@ -410,22 +400,12 @@ seeq8005_send_packet(struct sk_buff *skb, struct net_device *dev)
/* The typical workload of the driver:
Handle the network interface interrupts. */
-static void
-seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static void seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct net_device *dev = dev_id;
struct net_local *lp;
int ioaddr, status, boguscount = 0;
- if (dev == NULL) {
- printk ("net_interrupt(): irq %d for unknown device.\n", irq);
- return;
- }
-
- if (dev->interrupt)
- printk ("%s: Re-entering the interrupt handler.\n", dev->name);
- dev->interrupt = 1;
-
ioaddr = dev->base_addr;
lp = (struct net_local *)dev->priv;
@@ -444,8 +424,7 @@ seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
if (status & SEEQSTAT_TX_INT) {
outw( SEEQCMD_TX_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
lp->stats.tx_packets++;
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_wake_queue(dev); /* Inform upper layers. */
}
if (status & SEEQSTAT_RX_INT) {
/* Got a packet(s). */
@@ -457,13 +436,10 @@ seeq8005_interrupt(int irq, void *dev_id, struct pt_regs * regs)
if(net_debug>2) {
printk("%s: eoi\n",dev->name);
}
- dev->interrupt = 0;
- return;
}
/* We have a good packet(s), get it/them out of the buffers. */
-static void
-seeq8005_rx(struct net_device *dev)
+static void seeq8005_rx(struct net_device *dev)
{
struct net_local *lp = (struct net_local *)dev->priv;
int boguscount = 10;
@@ -561,17 +537,15 @@ seeq8005_rx(struct net_device *dev)
}
/* The inverse routine to net_open(). */
-static int
-seeq8005_close(struct net_device *dev)
+static int seeq8005_close(struct net_device *dev)
{
struct net_local *lp = (struct net_local *)dev->priv;
int ioaddr = dev->base_addr;
lp->open_time = 0;
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
+
/* Flush the Tx and disable Rx here. */
outw( SEEQCMD_SET_ALL_OFF, SEEQ_CMD);
@@ -598,8 +572,7 @@ static struct net_device_stats *seeq8005_get_stats(struct net_device *dev)
num_addrs > 0 Multicast mode, receive normal and MC packets, and do
best-effort filtering.
*/
-static void
-set_multicast_list(struct net_device *dev)
+static void set_multicast_list(struct net_device *dev)
{
/*
* I _could_ do up to 6 addresses here, but won't (yet?)
diff --git a/drivers/net/setup.c b/drivers/net/setup.c
index 29a63e1aa..472b23a8c 100644
--- a/drivers/net/setup.c
+++ b/drivers/net/setup.c
@@ -15,9 +15,7 @@ extern int strip_init_ctrl_dev(void);
extern int x25_asy_init_ctrl_dev(void);
extern int slhc_install(void);
-extern int bpq_init(void);
extern int dmascc_init(void);
-extern int scc_init(void);
extern int yam_init(void);
extern int awc4500_pci_probe(void);
@@ -59,15 +57,9 @@ struct net_probe pci_probes[] __initdata = {
* Early setup devices
*/
-#if defined(CONFIG_SCC)
- {scc_init, 0},
-#endif
#if defined(CONFIG_DMASCC)
{dmascc_init, 0},
#endif
-#if defined(CONFIG_BPQETHER)
- {bpq_init, 0},
-#endif
#if defined(CONFIG_DLCI)
{dlci_setup, 0},
#endif
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index 7d072d5f0..56333fea0 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -1,4 +1,4 @@
-/* $Id: sgiseeq.c,v 1.13 1999/12/04 03:59:03 ralf Exp $
+/* $Id: sgiseeq.c,v 1.14 2000/02/23 00:41:14 ralf Exp $
*
* sgiseeq.c: Seeq8003 ethernet driver for SGI machines.
*
@@ -428,8 +428,7 @@ static void sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (sp->tx_old != sp->tx_new)
sgiseeq_tx(dev, sp, hregs, sregs);
- if ((TX_BUFFS_AVAIL(sp) > 0) && \
- test_bit(LINK_STATE_XOFF, &dev->state)) {
+ if ((TX_BUFFS_AVAIL(sp) > 0) && netif_queue_stopped(dev)) {
netif_wake_queue(dev);
}
}
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 60d730699..f8af277ea 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -1,6 +1,6 @@
/* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux.
Copyright 1999 Silicon Integrated System Corporation
- Revision: 1.06.03 Dec 23 1999
+ Revision: 1.06.04 Feb 11 2000
Modified from the driver which is originally written by Donald Becker.
@@ -17,7 +17,8 @@
SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution,
preliminary Rev. 1.0 Jan. 18, 1998
http://www.sis.com.tw/support/databook.htm
-
+
+ Rev 1.06.04 Feb. 11 2000 Jeff Garzik <jgarzik@mandrakesoft.com> softnet and init for kernel 2.4
Rev 1.06.03 Dec. 23 1999 Ollie Lho Third release
Rev 1.06.02 Nov. 23 1999 Ollie Lho bug in mac probing fixed
Rev 1.06.01 Nov. 16 1999 Ollie Lho CRC calculation provide by Joseph Zbiciak (im14u2c@primenet.com)
@@ -51,7 +52,7 @@
#include "sis900.h"
static const char *version =
-"sis900.c: v1.06.03 12/23/99\n";
+"sis900.c: v1.06.04 02/11/2000\n";
static int max_interrupt_work = 20;
#define sis900_debug debug
@@ -134,7 +135,7 @@ struct sis900_private {
int LinkOn;
};
-MODULE_AUTHOR("Jim Huang <cmhuang@sis.com.tw>");
+MODULE_AUTHOR("Jim Huang <cmhuang@sis.com.tw>, Ollie Lho <ollie@sis.com.tw>");
MODULE_DESCRIPTION("SiS 900 PCI Fast Ethernet driver");
MODULE_PARM(multicast_filter_limit, "i");
MODULE_PARM(max_interrupt_work, "i");
@@ -256,7 +257,7 @@ static struct net_device * sis900_mac_probe (struct mac_chip_info * mac, struct
net_dev->irq = irq;
sis_priv->pci_dev = pci_dev;
sis_priv->mac = mac;
- sis_priv->lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&sis_priv->lock);
/* probe for mii transciver */
if (sis900_mii_probe(net_dev) == 0) {
@@ -667,8 +668,8 @@ static void sis900_timer(unsigned long data)
next_tick = 5*HZ;
/* change what cur_phy means */
if (mii_phy->phy_addr != sis_priv->cur_phy) {
- printk(KERN_INFO "%s: Changing transceiver to %s\n", net_dev->name,
- mii_phy->chip_info->name);
+ printk(KERN_INFO "%s: Changing transceiver to %s\n",
+ net_dev->name, mii_phy->chip_info->name);
status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL);
mdio_write(net_dev, sis_priv->cur_phy,
MII_CONTROL, status | MII_CNTL_ISOLATE);
@@ -788,6 +789,7 @@ static void sis900_tx_timeout(struct net_device *net_dev)
{
struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv;
long ioaddr = net_dev->base_addr;
+ unsigned long flags;
int i;
printk(KERN_INFO "%s: Transmit timeout, status %8.8x %8.8x \n",
@@ -796,8 +798,10 @@ static void sis900_tx_timeout(struct net_device *net_dev)
/* Disable interrupts by clearing the interrupt mask. */
outl(0x0000, ioaddr + imr);
- /* discard unsent packets, should this code section be protected by
- cli(), sti() ?? */
+ /* use spinlock to prevent interrupt handler accessing buffer ring */
+ spin_lock_irqsave(&sis_priv->lock, flags);
+
+ /* discard unsent packets */
sis_priv->dirty_tx = sis_priv->cur_tx = 0;
for (i = 0; i < NUM_TX_DESC; i++) {
if (sis_priv->tx_skbuff[i] != NULL) {
@@ -808,12 +812,15 @@ static void sis900_tx_timeout(struct net_device *net_dev)
sis_priv->stats.tx_dropped++;
}
}
+ sis_priv->tx_full = 0;
+ netif_wake_queue(net_dev);
+
+ spin_unlock_irqrestore(&sis_priv->lock, flags);
net_dev->trans_start = jiffies;
- sis_priv->tx_full = 0;
- netif_start_queue(net_dev);
/* FIXME: Should we restart the transmission thread here ?? */
+ outl(TxENA, ioaddr + cr);
/* Enable all known interrupts by setting the interrupt mask. */
outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
@@ -826,6 +833,9 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv;
long ioaddr = net_dev->base_addr;
unsigned int entry;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sis_priv->lock, flags);
/* Calculate the next Tx descriptor entry. */
entry = sis_priv->cur_tx % NUM_TX_DESC;
@@ -837,14 +847,16 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
outl(TxENA, ioaddr + cr);
if (++sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC) {
- /* Typical path, clear tbusy to indicate more
- transmission is possible */
+ /* Typical path, tell upper layer that more transmission is possible */
netif_start_queue(net_dev);
} else {
- /* no more transmit descriptor avaiable, tbusy remain set */
+ /* buffer full, tell upper layer no more transmission */
sis_priv->tx_full = 1;
+ netif_stop_queue(net_dev);
}
+ spin_unlock_irqrestore(&sis_priv->lock, flags);
+
net_dev->trans_start = jiffies;
if (sis900_debug > 3)
@@ -918,7 +930,7 @@ static int sis900_rx(struct net_device *net_dev)
if (sis900_debug > 3)
printk(KERN_INFO "sis900_rx, cur_rx:%4.4d, dirty_rx:%4.4d "
"status:0x%8.8x\n",
- sis_priv->cur_rx, sis_priv->dirty_rx,rx_status);
+ sis_priv->cur_rx, sis_priv->dirty_rx, rx_status);
while (rx_status & OWN) {
unsigned int rx_size;
@@ -1048,16 +1060,16 @@ static void sis900_finish_xmit (struct net_device *net_dev)
sis_priv->stats.tx_packets++;
}
/* Free the original skb. */
- dev_kfree_skb(sis_priv->tx_skbuff[entry]);
+ dev_kfree_skb_irq(sis_priv->tx_skbuff[entry]);
sis_priv->tx_skbuff[entry] = NULL;
sis_priv->tx_ring[entry].bufptr = 0;
sis_priv->tx_ring[entry].cmdsts = 0;
}
- if (sis_priv->tx_full && test_bit(LINK_STATE_XOFF, &net_dev->flags) &&
+ if (sis_priv->tx_full && netif_queue_stopped(net_dev) &&
sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC - 4) {
- /* The ring is no longer full, clear tbusy, tx_full and
- schedule more transmission by marking NET_BH */
+ /* The ring is no longer full, clear tx_full and schedule more transmission
+ by netif_wake_queue(net_dev) */
sis_priv->tx_full = 0;
netif_wake_queue (net_dev);
}
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index d7ed239a4..f6710a0b5 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -276,7 +276,9 @@ static const char SysKonnectBuildNumber[] =
// #define RLMT_MODE {"CheckLink", }
-#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb);
+#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb)
+#define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb)
+#define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb)
/* function prototypes ******************************************************/
static void FreeResources(struct net_device *dev);
@@ -410,6 +412,21 @@ static int __init skge_probe (void)
pci_set_master(pdev);
+#ifdef __sparc__
+ /* Set the proper cache line size value, plus enable
+ * write-invalidate and fast back-to-back on Sparc.
+ */
+ {
+ SK_U16 pci_command;
+
+ SkPciWriteCfgByte(pAC, PCI_CACHE_LINE_SIZE, 0x10);
+
+ SkPciReadCfgWord(pAC, PCI_COMMAND, &pci_command);
+ pci_command |= (PCI_COMMAND_INVALIDATE | PCI_COMMAND_FAST_BACK);
+ SkPciWriteCfgWord(pAC, PCI_COMMAND, pci_command);
+ }
+#endif
+
base_address = pdev->resource[0].start;
#ifdef SK_BIG_ENDIAN
@@ -1507,13 +1524,16 @@ int Rc; /* return code of XmitFrame */
Rc = XmitFrame(pAC, &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW], skb);
- if (Rc == 0) {
- /* transmitter out of resources */
+ /* Transmitter out of resources? */
+ if (Rc <= 0)
netif_stop_queue(dev);
- /* give buffer ownership back to the queueing layer */
+ /* If not taken, give buffer ownership back to the
+ * queueing layer.
+ */
+ if (Rc < 0)
return (1);
- }
+
dev->trans_start = jiffies;
return (0);
} /* SkGeXmit */
@@ -1539,7 +1559,7 @@ int Rc; /* return code of XmitFrame */
* > 0 - on succes: the number of bytes in the message
* = 0 - on resource shortage: this frame sent or dropped, now
* the ring is full ( -> set tbusy)
- * < 0 - on failure: other problems (not used)
+ * < 0 - on failure: other problems ( -> return failure to upper layers)
*/
static int XmitFrame(
SK_AC *pAC, /* pointer to adapter context */
@@ -1566,7 +1586,7 @@ int BytesSend;
SK_DBGCAT_DRV_TX_PROGRESS,
("XmitFrame failed\n"));
/* this message can not be sent now */
- return (0);
+ return (-1);
}
}
/* advance head counter behind descriptor needed for this frame */
@@ -1586,7 +1606,8 @@ int BytesSend;
/* set up descriptor and CONTROL dword */
PhysAddr = (SK_U64) pci_map_single(&pAC->PciDev,
pMessage->data,
- pMessage->len);
+ pMessage->len,
+ PCI_DMA_TODEVICE);
pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
pTxd->pMBuf = pMessage;
@@ -1679,9 +1700,11 @@ SK_U64 PhysAddr; /* address of DMA mapping */
PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32;
PhysAddr |= (SK_U64) pTxd->VDataLow;
pci_unmap_single(&pAC->PciDev, PhysAddr,
- pTxd->pMBuf->len);
+ pTxd->pMBuf->len,
+ PCI_DMA_TODEVICE);
- DEV_KFREE_SKB(pTxd->pMBuf); /* free message */
+ /* free message */
+ DEV_KFREE_SKB_ANY(pTxd->pMBuf);
pTxPort->TxdRingFree++;
pTxd->TBControl &= ~TX_CTRL_SOFTWARE;
pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */
@@ -1759,7 +1782,8 @@ SK_U64 PhysAddr; /* physical address of a rx buffer */
Length = pAC->RxBufSize;
PhysAddr = (SK_U64) pci_map_single(&pAC->PciDev,
pMsgBlock->data,
- pAC->RxBufSize - 2);
+ pAC->RxBufSize - 2,
+ PCI_DMA_FROMDEVICE);
pRxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
pRxd->pMBuf = pMsgBlock;
@@ -1882,7 +1906,8 @@ rx_start:
skb_put(pNewMsg, FrameLength);
pci_dma_sync_single(&pAC->PciDev,
(dma_addr_t) PhysAddr,
- FrameLength);
+ FrameLength,
+ PCI_DMA_FROMDEVICE);
eth_copy_and_sum(pNewMsg, pMsg->data,
FrameLength, 0);
ReQueueRxBuffer(pAC, pRxPort, pMsg,
@@ -1902,15 +1927,16 @@ rx_start:
/* release the DMA mapping */
pci_unmap_single(&pAC->PciDev,
PhysAddr,
- pAC->RxBufSize - 2);
+ pAC->RxBufSize - 2,
+ PCI_DMA_FROMDEVICE);
/* set length in message */
skb_put(pMsg, FrameLength);
/* hardware checksum */
Type = ntohs(*((short*)&pMsg->data[12]));
if (Type == 0x800) {
- Csum1= pRxd->TcpSums & 0xffff;
- Csum2=(pRxd->TcpSums >> 16) & 0xffff;
+ Csum1=le16_to_cpu(pRxd->TcpSums & 0xffff);
+ Csum2=le16_to_cpu((pRxd->TcpSums >> 16) & 0xffff);
if ((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) {
Result = SkCsGetReceiveInfo(pAC,
&pMsg->data[14],
@@ -1980,7 +2006,7 @@ rx_start:
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_RX_PROGRESS,
("D"));
- DEV_KFREE_SKB(pMsg);
+ DEV_KFREE_SKB_IRQ(pMsg);
}
} /* if not for rlmt */
else {
@@ -2016,7 +2042,7 @@ rx_start:
pAC->dev->last_rx = jiffies;
}
else {
- DEV_KFREE_SKB(pMsg);
+ DEV_KFREE_SKB_IRQ(pMsg);
}
} /* if packet for rlmt */
@@ -2040,7 +2066,7 @@ rx_start:
("skge: Error in received frame, dropped!\n"
"Control: %x\nRxStat: %x\n",
Control, FrameStat));
- DEV_KFREE_SKB(pMsg);
+ DEV_KFREE_SKB_IRQ(pMsg);
}
} /* while */
FillRxRing(pAC, pRxPort);
@@ -2060,8 +2086,9 @@ rx_failed:
PhysAddr |= (SK_U64) pRxd->VDataLow;
pci_unmap_single(&pAC->PciDev,
PhysAddr,
- pAC->RxBufSize - 2);
- DEV_KFREE_SKB(pRxd->pMBuf);
+ pAC->RxBufSize - 2,
+ PCI_DMA_FROMDEVICE);
+ DEV_KFREE_SKB_IRQ(pRxd->pMBuf);
pRxd->pMBuf = NULL;
pRxPort->RxdRingFree++;
pRxPort->pRxdRingHead = pRxd->pNextRxd;
@@ -2139,7 +2166,8 @@ unsigned int Flags;
PhysAddr |= (SK_U64) pRxd->VDataLow;
pci_unmap_single(&pAC->PciDev,
PhysAddr,
- pAC->RxBufSize - 2);
+ pAC->RxBufSize - 2,
+ PCI_DMA_FROMDEVICE);
DEV_KFREE_SKB(pRxd->pMBuf);
pRxd->pMBuf = NULL;
}
@@ -2276,7 +2304,7 @@ unsigned int Flags;
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
("SkGeSetMacAddr starts now...\n"));
- if(test_bit(LINK_STATE_START, &dev->state)) {
+ if(netif_running(dev)) {
return -EBUSY;
}
memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
@@ -3120,7 +3148,7 @@ SK_MBUF *pNextMbuf;
pFreeMbuf = pMbuf;
do {
pNextMbuf = pFreeMbuf->pNext;
- DEV_KFREE_SKB(pFreeMbuf->pOs);
+ DEV_KFREE_SKB_ANY(pFreeMbuf->pOs);
pFreeMbuf = pNextMbuf;
} while ( pFreeMbuf != NULL );
} /* SkDrvFreeRlmtMbuf */
@@ -3489,8 +3517,9 @@ unsigned int Flags;
pRlmtMbuf = (SK_MBUF*) Param.pParaPtr;
pMsg = (struct sk_buff*) pRlmtMbuf->pOs;
skb_put(pMsg, pRlmtMbuf->Length);
- XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW],
- pMsg);
+ if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW],
+ pMsg) < 0)
+ DEV_KFREE_SKB_ANY(pMsg);
break;
default:
break;
diff --git a/drivers/net/sk_g16.c b/drivers/net/sk_g16.c
index 24dd1ff1c..d3722cf2d 100644
--- a/drivers/net/sk_g16.c
+++ b/drivers/net/sk_g16.c
@@ -472,6 +472,7 @@ static spinlock_t SK_lock = SPIN_LOCK_UNLOCKED;
int SK_init(struct net_device *dev);
static int SK_probe(struct net_device *dev, short ioaddr);
+static void SK_timeout(struct net_device *dev);
static int SK_open(struct net_device *dev);
static int SK_send_packet(struct sk_buff *skb, struct net_device *dev);
static void SK_interrupt(int irq, void *dev_id, struct pt_regs * regs);
@@ -778,11 +779,13 @@ int __init SK_probe(struct net_device *dev, short ioaddr)
/* Assign our Device Driver functions */
- dev->open = &SK_open;
- dev->stop = &SK_close;
- dev->hard_start_xmit = &SK_send_packet;
- dev->get_stats = &SK_get_stats;
- dev->set_multicast_list = &set_multicast_list;
+ dev->open = SK_open;
+ dev->stop = SK_close;
+ dev->hard_start_xmit = SK_send_packet;
+ dev->get_stats = SK_get_stats;
+ dev->set_multicast_list = set_multicast_list;
+ dev->tx_timeout = SK_timeout;
+ dev->watchdog_timeo = HZ/7;
/* Set the generic fields of the device structure */
@@ -1169,30 +1172,18 @@ static int SK_lance_init(struct net_device *dev, unsigned short mode)
* YY/MM/DD uid Description
-*/
-static int SK_send_packet(struct sk_buff *skb, struct net_device *dev)
+static int SK_timeout(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
- struct tmd *tmdp;
-
- if (test_bit(LINK_STATE_XOFF, &dev->flags))
- {
- /* if Transmitter more than 150ms busy -> time_out */
-
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 15)
- {
- return 1; /* We have to try transmit later */
- }
-
- printk("%s: xmitter timed out, try to restart!\n", dev->name);
-
+ printk(KERN_WARNING "%s: xmitter timed out, try to restart!\n", dev->name);
SK_lance_init(dev, MODE_NORMAL); /* Reinit LANCE */
-
netif_start_queue(dev); /* Clear Transmitter flag */
-
dev->trans_start = jiffies; /* Mark Start of transmission */
+}
- }
+static int SK_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+ struct priv *p = (struct priv *) dev->priv;
+ struct tmd *tmdp;
PRINTK2(("## %s: SK_send_packet() called, CSR0 %#04x.\n",
SK_NAME, SK_read_reg(CSR0)));
diff --git a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c
index 902644162..088b89388 100644
--- a/drivers/net/sk_mca.c
+++ b/drivers/net/sk_mca.c
@@ -96,12 +96,13 @@ History:
* have to pack all state info into the device struct!
* ------------------------------------------------------------------------ */
-static char *MediaNames[Media_Count]=
- {"10Base2", "10BaseT", "10Base5", "Unknown"};
+static char *MediaNames[Media_Count] = {
+ "10Base2", "10BaseT", "10Base5", "Unknown" };
-static unsigned char poly[] =
- {1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0,
- 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0};
+static unsigned char poly[] = {
+ 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0
+};
/* ------------------------------------------------------------------------
* private subfunctions
@@ -112,64 +113,70 @@ static unsigned char poly[] =
#ifdef DEBUG
static void dumpmem(struct net_device *dev, u32 start, u32 len)
{
- int z;
-
- for (z = 0; z < len; z++)
- {
- if ((z & 15) == 0)
- printk("%04x:", z);
- printk(" %02x", readb(dev->mem_start + start + z));
- if ((z & 15) == 15)
- printk("\n");
- }
+ int z;
+
+ for (z = 0; z < len; z++) {
+ if ((z & 15) == 0)
+ printk("%04x:", z);
+ printk(" %02x", readb(dev->mem_start + start + z));
+ if ((z & 15) == 15)
+ printk("\n");
+ }
}
/* print exact time - ditto */
static void PrTime(void)
{
- struct timeval tv;
+ struct timeval tv;
- do_gettimeofday(&tv);
- printk("%9d:%06d: ", tv.tv_sec, tv.tv_usec);
+ do_gettimeofday(&tv);
+ printk("%9d:%06d: ", tv.tv_sec, tv.tv_usec);
}
+
#endif
/* deduce resources out of POS registers */
static void getaddrs(int slot, int junior, int *base, int *irq,
- skmca_medium *medium)
+ skmca_medium * medium)
{
- u_char pos0, pos1, pos2;
-
- if (junior)
- {
- pos0 = mca_read_stored_pos(slot, 2);
- *base = ((pos0 & 0x0e) << 13) + 0xc0000;
- *irq = ((pos0 & 0x10) >> 4) + 10;
- *medium = Media_Unknown;
- }
- else
- {
- /* reset POS 104 Bits 0+1 so the shared memory region goes to the
- configured area between 640K and 1M. Afterwards, enable the MC2.
- I really don't know what rode SK to do this... */
-
- mca_write_pos(slot, 4, mca_read_stored_pos(slot, 4) & 0xfc);
- mca_write_pos(slot, 2, mca_read_stored_pos(slot, 2) | 0x01);
-
- pos1 = mca_read_stored_pos(slot, 3);
- pos2 = mca_read_stored_pos(slot, 4);
- *base = ((pos1 & 0x07) << 14) + 0xc0000;
- switch (pos2 & 0x0c)
- {
- case 0: *irq = 3; break;
- case 4: *irq = 5; break;
- case 8: *irq = 10; break;
- case 12: *irq = 11; break;
- }
- *medium = (pos2 >> 6) & 3;
- }
+ u_char pos0, pos1, pos2;
+
+ if (junior) {
+ pos0 = mca_read_stored_pos(slot, 2);
+ *base = ((pos0 & 0x0e) << 13) + 0xc0000;
+ *irq = ((pos0 & 0x10) >> 4) + 10;
+ *medium = Media_Unknown;
+ } else {
+ /* reset POS 104 Bits 0+1 so the shared memory region goes to the
+ configured area between 640K and 1M. Afterwards, enable the MC2.
+ I really don't know what rode SK to do this... */
+
+ mca_write_pos(slot, 4,
+ mca_read_stored_pos(slot, 4) & 0xfc);
+ mca_write_pos(slot, 2,
+ mca_read_stored_pos(slot, 2) | 0x01);
+
+ pos1 = mca_read_stored_pos(slot, 3);
+ pos2 = mca_read_stored_pos(slot, 4);
+ *base = ((pos1 & 0x07) << 14) + 0xc0000;
+ switch (pos2 & 0x0c) {
+ case 0:
+ *irq = 3;
+ break;
+ case 4:
+ *irq = 5;
+ break;
+ case 8:
+ *irq = 10;
+ break;
+ case 12:
+ *irq = 11;
+ break;
+ }
+ *medium = (pos2 >> 6) & 3;
+ }
}
/* check for both cards:
@@ -179,157 +186,162 @@ static void getaddrs(int slot, int junior, int *base, int *irq,
static int dofind(int *junior, int firstslot)
{
- int slot;
- unsigned int id;
-
- for (slot = firstslot; slot < MCA_MAX_SLOT_NR; slot++)
- {
- id = mca_read_stored_pos(slot, 0)
- + (((unsigned int) mca_read_stored_pos(slot, 1)) << 8);
-
- *junior = 0;
- if (id == SKNET_MCA_ID)
- return slot;
- *junior = 1;
- if (id == SKNET_JUNIOR_MCA_ID)
- return slot;
- }
- return MCA_NOTFOUND;
+ int slot;
+ unsigned int id;
+
+ for (slot = firstslot; slot < MCA_MAX_SLOT_NR; slot++) {
+ id = mca_read_stored_pos(slot, 0)
+ + (((unsigned int) mca_read_stored_pos(slot, 1)) << 8);
+
+ *junior = 0;
+ if (id == SKNET_MCA_ID)
+ return slot;
+ *junior = 1;
+ if (id == SKNET_JUNIOR_MCA_ID)
+ return slot;
+ }
+ return MCA_NOTFOUND;
}
/* reset the whole board */
static void ResetBoard(struct net_device *dev)
{
- skmca_priv *priv = (skmca_priv*) dev->priv;
+ skmca_priv *priv = (skmca_priv *) dev->priv;
- writeb(CTRL_RESET_ON, priv->ctrladdr);
- udelay(10);
- writeb(CTRL_RESET_OFF, priv->ctrladdr);
+ writeb(CTRL_RESET_ON, priv->ctrladdr);
+ udelay(10);
+ writeb(CTRL_RESET_OFF, priv->ctrladdr);
}
/* set LANCE register - must be atomic */
static void SetLANCE(struct net_device *dev, u16 addr, u16 value)
{
- skmca_priv *priv = (skmca_priv*) dev->priv;
- unsigned long flags;
+ skmca_priv *priv = (skmca_priv *) dev->priv;
+ unsigned long flags;
- /* disable interrupts */
+ /* disable interrupts */
- save_flags(flags);
- cli();
+ save_flags(flags);
+ cli();
- /* wait until no transfer is pending */
-
- while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+ /* wait until no transfer is pending */
- /* transfer register address to RAP */
+ while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
- writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP, priv->ctrladdr);
- writew(addr, priv->ioregaddr);
- writeb(IOCMD_GO, priv->cmdaddr);
- udelay(1);
- while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+ /* transfer register address to RAP */
- /* transfer data to register */
+ writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP,
+ priv->ctrladdr);
+ writew(addr, priv->ioregaddr);
+ writeb(IOCMD_GO, priv->cmdaddr);
+ udelay(1);
+ while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
- writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_DATA, priv->ctrladdr);
- writew(value, priv->ioregaddr);
- writeb(IOCMD_GO, priv->cmdaddr);
- udelay(1);
- while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+ /* transfer data to register */
- /* reenable interrupts */
+ writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_DATA,
+ priv->ctrladdr);
+ writew(value, priv->ioregaddr);
+ writeb(IOCMD_GO, priv->cmdaddr);
+ udelay(1);
+ while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
- restore_flags(flags);
+ /* reenable interrupts */
+
+ restore_flags(flags);
}
/* get LANCE register */
static u16 GetLANCE(struct net_device *dev, u16 addr)
{
- skmca_priv *priv = (skmca_priv*) dev->priv;
- unsigned long flags;
- unsigned int res;
+ skmca_priv *priv = (skmca_priv *) dev->priv;
+ unsigned long flags;
+ unsigned int res;
- /* disable interrupts */
+ /* disable interrupts */
- save_flags(flags);
- cli();
+ save_flags(flags);
+ cli();
- /* wait until no transfer is pending */
+ /* wait until no transfer is pending */
- while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+ while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
- /* transfer register address to RAP */
+ /* transfer register address to RAP */
- writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP, priv->ctrladdr);
- writew(addr, priv->ioregaddr);
- writeb(IOCMD_GO, priv->cmdaddr);
- udelay(1);
- while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+ writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP,
+ priv->ctrladdr);
+ writew(addr, priv->ioregaddr);
+ writeb(IOCMD_GO, priv->cmdaddr);
+ udelay(1);
+ while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
- /* transfer data from register */
+ /* transfer data from register */
- writeb(CTRL_RESET_OFF | CTRL_RW_READ | CTRL_ADR_DATA, priv->ctrladdr);
- writeb(IOCMD_GO, priv->cmdaddr);
- udelay(1);
- while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
- res = readw(priv->ioregaddr);
+ writeb(CTRL_RESET_OFF | CTRL_RW_READ | CTRL_ADR_DATA,
+ priv->ctrladdr);
+ writeb(IOCMD_GO, priv->cmdaddr);
+ udelay(1);
+ while ((readb(priv->ctrladdr) & STAT_IO_BUSY) == STAT_IO_BUSY);
+ res = readw(priv->ioregaddr);
- /* reenable interrupts */
+ /* reenable interrupts */
- restore_flags(flags);
+ restore_flags(flags);
- return res;
+ return res;
}
/* build up descriptors in shared RAM */
static void InitDscrs(struct net_device *dev)
{
- u32 bufaddr;
-
- /* Set up Tx descriptors. The board has only 16K RAM so bits 16..23
- are always 0. */
-
- bufaddr = RAM_DATABASE;
- {
- LANCE_TxDescr descr;
- int z;
-
- for (z = 0; z < TXCOUNT; z++)
- {
- descr.LowAddr = bufaddr;
- descr.Flags = 0;
- descr.Len = 0xf000;
- descr.Status = 0;
- isa_memcpy_toio(dev->mem_start + RAM_TXBASE + (z * sizeof(LANCE_TxDescr)),
- &descr, sizeof(LANCE_TxDescr));
- memset_io(dev->mem_start + bufaddr, 0, RAM_BUFSIZE);
- bufaddr += RAM_BUFSIZE;
- }
- }
-
- /* do the same for the Rx descriptors */
-
- {
- LANCE_RxDescr descr;
- int z;
-
- for (z = 0; z < RXCOUNT; z++)
- {
- descr.LowAddr = bufaddr;
- descr.Flags = RXDSCR_FLAGS_OWN;
- descr.MaxLen = -RAM_BUFSIZE;
- descr.Len = 0;
- isa_memcpy_toio(dev->mem_start + RAM_RXBASE + (z * sizeof(LANCE_RxDescr)),
- &descr, sizeof(LANCE_RxDescr));
- isa_memset_io(dev->mem_start + bufaddr, 0, RAM_BUFSIZE);
- bufaddr += RAM_BUFSIZE;
- }
- }
+ u32 bufaddr;
+
+ /* Set up Tx descriptors. The board has only 16K RAM so bits 16..23
+ are always 0. */
+
+ bufaddr = RAM_DATABASE;
+ {
+ LANCE_TxDescr descr;
+ int z;
+
+ for (z = 0; z < TXCOUNT; z++) {
+ descr.LowAddr = bufaddr;
+ descr.Flags = 0;
+ descr.Len = 0xf000;
+ descr.Status = 0;
+ isa_memcpy_toio(dev->mem_start + RAM_TXBASE +
+ (z * sizeof(LANCE_TxDescr)),
+ &descr, sizeof(LANCE_TxDescr));
+ memset_io(dev->mem_start + bufaddr, 0,
+ RAM_BUFSIZE);
+ bufaddr += RAM_BUFSIZE;
+ }
+ }
+
+ /* do the same for the Rx descriptors */
+
+ {
+ LANCE_RxDescr descr;
+ int z;
+
+ for (z = 0; z < RXCOUNT; z++) {
+ descr.LowAddr = bufaddr;
+ descr.Flags = RXDSCR_FLAGS_OWN;
+ descr.MaxLen = -RAM_BUFSIZE;
+ descr.Len = 0;
+ isa_memcpy_toio(dev->mem_start + RAM_RXBASE +
+ (z * sizeof(LANCE_RxDescr)),
+ &descr, sizeof(LANCE_RxDescr));
+ isa_memset_io(dev->mem_start + bufaddr, 0,
+ RAM_BUFSIZE);
+ bufaddr += RAM_BUFSIZE;
+ }
+ }
}
/* calculate the hash bit position for a given multicast address
@@ -337,136 +349,138 @@ static void InitDscrs(struct net_device *dev)
static void UpdateCRC(unsigned char *CRC, int bit)
{
- int j;
+ int j;
- /* shift CRC one bit */
+ /* shift CRC one bit */
- memmove(CRC + 1, CRC, 32 * sizeof(unsigned char));
- CRC[0] = 0;
+ memmove(CRC + 1, CRC, 32 * sizeof(unsigned char));
+ CRC[0] = 0;
- /* if bit XOR controlbit = 1, set CRC = CRC XOR polynomial */
+ /* if bit XOR controlbit = 1, set CRC = CRC XOR polynomial */
- if (bit ^ CRC[32])
- for (j = 0; j < 32; j++)
- CRC[j] ^= poly[j];
+ if (bit ^ CRC[32])
+ for (j = 0; j < 32; j++)
+ CRC[j] ^= poly[j];
}
static unsigned int GetHash(char *address)
{
- unsigned char CRC[33];
- int i, byte, hashcode;
+ unsigned char CRC[33];
+ int i, byte, hashcode;
- /* a multicast address has bit 0 in the first byte set */
+ /* a multicast address has bit 0 in the first byte set */
- if ((address[0] & 1) == 0)
- return -1;
+ if ((address[0] & 1) == 0)
+ return -1;
- /* initialize CRC */
+ /* initialize CRC */
- memset(CRC, 1, sizeof(CRC));
+ memset(CRC, 1, sizeof(CRC));
- /* loop through address bits */
+ /* loop through address bits */
- for (byte = 0; byte < 6; byte++)
- for (i = 0; i < 8; i++)
- UpdateCRC(CRC, (address[byte] >> i) & 1);
+ for (byte = 0; byte < 6; byte++)
+ for (i = 0; i < 8; i++)
+ UpdateCRC(CRC, (address[byte] >> i) & 1);
- /* hashcode is the 6 least significant bits of the CRC */
+ /* hashcode is the 6 least significant bits of the CRC */
- hashcode = 0;
- for (i = 0; i < 6; i++)
- hashcode = (hashcode << 1) + CRC[i];
- return hashcode;
+ hashcode = 0;
+ for (i = 0; i < 6; i++)
+ hashcode = (hashcode << 1) + CRC[i];
+ return hashcode;
}
/* feed ready-built initialization block into LANCE */
static void InitLANCE(struct net_device *dev)
{
- skmca_priv *priv = (skmca_priv*) dev->priv;
-
- /* build up descriptors. */
+ skmca_priv *priv = (skmca_priv *) dev->priv;
- InitDscrs(dev);
+ /* build up descriptors. */
- /* next RX descriptor to be read is the first one. Since the LANCE
- will start from the beginning after initialization, we have to
- reset out pointers too. */
+ InitDscrs(dev);
- priv->nextrx = 0;
+ /* next RX descriptor to be read is the first one. Since the LANCE
+ will start from the beginning after initialization, we have to
+ reset out pointers too. */
- /* no TX descriptors active */
+ priv->nextrx = 0;
- priv->nexttxput = priv->nexttxdone = priv->txbusy = 0;
+ /* no TX descriptors active */
- /* set up the LANCE bus control register - constant for SKnet boards */
+ priv->nexttxput = priv->nexttxdone = priv->txbusy = 0;
- SetLANCE(dev, LANCE_CSR3, CSR3_BSWAP_OFF | CSR3_ALE_LOW | CSR3_BCON_HOLD);
+ /* set up the LANCE bus control register - constant for SKnet boards */
- /* write address of initialization block into LANCE */
+ SetLANCE(dev, LANCE_CSR3,
+ CSR3_BSWAP_OFF | CSR3_ALE_LOW | CSR3_BCON_HOLD);
- SetLANCE(dev, LANCE_CSR1, RAM_INITBASE & 0xffff);
- SetLANCE(dev, LANCE_CSR2, (RAM_INITBASE >> 16) & 0xff);
+ /* write address of initialization block into LANCE */
- /* we don't get ready until the LANCE has read the init block */
+ SetLANCE(dev, LANCE_CSR1, RAM_INITBASE & 0xffff);
+ SetLANCE(dev, LANCE_CSR2, (RAM_INITBASE >> 16) & 0xff);
- dev->tbusy = 1;
+ /* we don't get ready until the LANCE has read the init block */
- /* let LANCE read the initialization block. LANCE is ready
- when we receive the corresponding interrupt. */
+ netif_stop_queue(dev);
+
+ /* let LANCE read the initialization block. LANCE is ready
+ when we receive the corresponding interrupt. */
- SetLANCE(dev, LANCE_CSR0, CSR0_INEA | CSR0_INIT);
+ SetLANCE(dev, LANCE_CSR0, CSR0_INEA | CSR0_INIT);
}
/* stop the LANCE so we can reinitialize it */
static void StopLANCE(struct net_device *dev)
{
- /* can't take frames any more */
+ /* can't take frames any more */
- dev->tbusy = 1;
+ netif_stop_queue(dev);
+
+ /* disable interrupts, stop it */
- /* disable interrupts, stop it */
-
- SetLANCE(dev, LANCE_CSR0, CSR0_STOP);
+ SetLANCE(dev, LANCE_CSR0, CSR0_STOP);
}
/* initialize card and LANCE for proper operation */
static void InitBoard(struct net_device *dev)
{
- LANCE_InitBlock block;
+ LANCE_InitBlock block;
- /* Lay out the shared RAM - first we create the init block for the LANCE.
- We do not overwrite it later because we need it again when we switch
- promiscous mode on/off. */
+ /* Lay out the shared RAM - first we create the init block for the LANCE.
+ We do not overwrite it later because we need it again when we switch
+ promiscous mode on/off. */
- block.Mode = 0;
- if (dev->flags & IFF_PROMISC)
- block.Mode |= LANCE_INIT_PROM;
- memcpy(block.PAdr, dev->dev_addr, 6);
- memset(block.LAdrF, 0, sizeof(block.LAdrF));
- block.RdrP = (RAM_RXBASE & 0xffffff) | (LRXCOUNT << 29);
- block.TdrP = (RAM_TXBASE & 0xffffff) | (LTXCOUNT << 29);
+ block.Mode = 0;
+ if (dev->flags & IFF_PROMISC)
+ block.Mode |= LANCE_INIT_PROM;
+ memcpy(block.PAdr, dev->dev_addr, 6);
+ memset(block.LAdrF, 0, sizeof(block.LAdrF));
+ block.RdrP = (RAM_RXBASE & 0xffffff) | (LRXCOUNT << 29);
+ block.TdrP = (RAM_TXBASE & 0xffffff) | (LTXCOUNT << 29);
- isa_memcpy_toio(dev->mem_start + RAM_INITBASE, &block, sizeof(block));
+ isa_memcpy_toio(dev->mem_start + RAM_INITBASE, &block,
+ sizeof(block));
- /* initialize LANCE. Implicitly sets up other structures in RAM. */
+ /* initialize LANCE. Implicitly sets up other structures in RAM. */
- InitLANCE(dev);
+ InitLANCE(dev);
}
/* deinitialize card and LANCE */
static void DeinitBoard(struct net_device *dev)
{
- /* stop LANCE */
+ /* stop LANCE */
- StopLANCE(dev);
+ StopLANCE(dev);
- /* reset board */
+ /* reset board */
- ResetBoard(dev);
+ ResetBoard(dev);
}
/* ------------------------------------------------------------------------
@@ -477,210 +491,201 @@ static void DeinitBoard(struct net_device *dev)
static u16 irqstart_handler(struct net_device *dev, u16 oldcsr0)
{
- /* now we're ready to transmit */
-
- dev->tbusy = 0;
+ /* now we're ready to transmit */
- /* reset IDON bit, start LANCE */
+ netif_wake_queue(dev);
+
+ /* reset IDON bit, start LANCE */
- SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_IDON | CSR0_STRT);
- return GetLANCE(dev, LANCE_CSR0);
+ SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_IDON | CSR0_STRT);
+ return GetLANCE(dev, LANCE_CSR0);
}
/* receive interrupt */
static u16 irqrx_handler(struct net_device *dev, u16 oldcsr0)
{
- skmca_priv *priv = (skmca_priv*) dev->priv;
- LANCE_RxDescr descr;
- unsigned int descraddr;
+ skmca_priv *priv = (skmca_priv *) dev->priv;
+ LANCE_RxDescr descr;
+ unsigned int descraddr;
+
+ /* did we loose blocks due to a FIFO overrun ? */
- /* did we loose blocks due to a FIFO overrun ? */
+ if (oldcsr0 & CSR0_MISS)
+ priv->stat.rx_fifo_errors++;
- if (oldcsr0 & CSR0_MISS)
- priv->stat.rx_fifo_errors++;
+ /* run through queue until we reach a descriptor we do not own */
- /* run through queue until we reach a descriptor we do not own */
+ descraddr = RAM_RXBASE + (priv->nextrx * sizeof(LANCE_RxDescr));
+ while (1) {
+ /* read descriptor */
+ isa_memcpy_fromio(&descr, dev->mem_start + descraddr,
+ sizeof(LANCE_RxDescr));
- descraddr = RAM_RXBASE + (priv->nextrx * sizeof(LANCE_RxDescr));
- while (1)
- {
- /* read descriptor */
- isa_memcpy_fromio(&descr, dev->mem_start + descraddr, sizeof(LANCE_RxDescr));
-
- /* if we reach a descriptor we do not own, we're done */
- if ((descr.Flags & RXDSCR_FLAGS_OWN) != 0)
- break;
+ /* if we reach a descriptor we do not own, we're done */
+ if ((descr.Flags & RXDSCR_FLAGS_OWN) != 0)
+ break;
#ifdef DEBUG
- PrTime(); printk("Receive packet on descr %d len %d\n", priv->nextrx, descr.Len);
+ PrTime();
+ printk("Receive packet on descr %d len %d\n", priv->nextrx,
+ descr.Len);
#endif
- /* erroneous packet ? */
- if ((descr.Flags & RXDSCR_FLAGS_ERR) != 0)
- {
- priv->stat.rx_errors++;
- if ((descr.Flags & RXDSCR_FLAGS_CRC) != 0)
- priv->stat.rx_crc_errors++;
- else if ((descr.Flags & RXDSCR_FLAGS_CRC) != 0)
- priv->stat.rx_frame_errors++;
- else if ((descr.Flags & RXDSCR_FLAGS_OFLO) != 0)
- priv->stat.rx_fifo_errors++;
- }
-
- /* good packet ? */
- else
- {
- struct sk_buff *skb;
-
- skb = dev_alloc_skb(descr.Len + 2);
- if (skb == NULL)
- priv->stat.rx_dropped++;
- else
- {
- isa_memcpy_fromio(skb_put(skb, descr.Len),
- dev->mem_start + descr.LowAddr, descr.Len);
- skb->dev = dev;
- skb->protocol = eth_type_trans(skb, dev);
- skb->ip_summed = CHECKSUM_NONE;
- priv->stat.rx_packets++;
-#if LINUX_VERSION_CODE >= 0x020119 /* byte counters for >= 2.1.25 */
- priv->stat.rx_bytes += descr.Len;
+ /* erroneous packet ? */
+ if ((descr.Flags & RXDSCR_FLAGS_ERR) != 0) {
+ priv->stat.rx_errors++;
+ if ((descr.Flags & RXDSCR_FLAGS_CRC) != 0)
+ priv->stat.rx_crc_errors++;
+ else if ((descr.Flags & RXDSCR_FLAGS_CRC) != 0)
+ priv->stat.rx_frame_errors++;
+ else if ((descr.Flags & RXDSCR_FLAGS_OFLO) != 0)
+ priv->stat.rx_fifo_errors++;
+ }
+
+ /* good packet ? */
+ else {
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(descr.Len + 2);
+ if (skb == NULL)
+ priv->stat.rx_dropped++;
+ else {
+ isa_memcpy_fromio(skb_put(skb, descr.Len),
+ dev->mem_start +
+ descr.LowAddr,
+ descr.Len);
+ skb->dev = dev;
+ skb->protocol = eth_type_trans(skb, dev);
+ skb->ip_summed = CHECKSUM_NONE;
+ priv->stat.rx_packets++;
+#if LINUX_VERSION_CODE >= 0x020119 /* byte counters for >= 2.1.25 */
+ priv->stat.rx_bytes += descr.Len;
#endif
- netif_rx(skb);
- }
- }
-
- /* give descriptor back to LANCE */
- descr.Len = 0;
- descr.Flags |= RXDSCR_FLAGS_OWN;
-
- /* update descriptor in shared RAM */
- isa_memcpy_toio(dev->mem_start + descraddr, &descr, sizeof(LANCE_RxDescr));
-
- /* go to next descriptor */
- priv->nextrx++; descraddr += sizeof(LANCE_RxDescr);
- if (priv->nextrx >= RXCOUNT)
- {
- priv->nextrx = 0;
- descraddr = RAM_RXBASE;
- }
- }
-
- /* reset RINT bit */
-
- SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_RINT);
- return GetLANCE(dev, LANCE_CSR0);
+ netif_rx(skb);
+ }
+ }
+
+ /* give descriptor back to LANCE */
+ descr.Len = 0;
+ descr.Flags |= RXDSCR_FLAGS_OWN;
+
+ /* update descriptor in shared RAM */
+ isa_memcpy_toio(dev->mem_start + descraddr, &descr,
+ sizeof(LANCE_RxDescr));
+
+ /* go to next descriptor */
+ priv->nextrx++;
+ descraddr += sizeof(LANCE_RxDescr);
+ if (priv->nextrx >= RXCOUNT) {
+ priv->nextrx = 0;
+ descraddr = RAM_RXBASE;
+ }
+ }
+
+ /* reset RINT bit */
+
+ SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_RINT);
+ return GetLANCE(dev, LANCE_CSR0);
}
/* transmit interrupt */
static u16 irqtx_handler(struct net_device *dev, u16 oldcsr0)
{
- skmca_priv *priv = (skmca_priv*) dev->priv;
- LANCE_TxDescr descr;
- unsigned int descraddr;
+ skmca_priv *priv = (skmca_priv *) dev->priv;
+ LANCE_TxDescr descr;
+ unsigned int descraddr;
- /* check descriptors at most until no busy one is left */
+ /* check descriptors at most until no busy one is left */
- descraddr = RAM_TXBASE + (priv->nexttxdone * sizeof(LANCE_TxDescr));
- while (priv->txbusy > 0)
- {
- /* read descriptor */
- isa_memcpy_fromio(&descr, dev->mem_start + descraddr, sizeof(LANCE_TxDescr));
+ descraddr =
+ RAM_TXBASE + (priv->nexttxdone * sizeof(LANCE_TxDescr));
+ while (priv->txbusy > 0) {
+ /* read descriptor */
+ isa_memcpy_fromio(&descr, dev->mem_start + descraddr,
+ sizeof(LANCE_TxDescr));
- /* if the LANCE still owns this one, we've worked out all sent packets */
- if ((descr.Flags & TXDSCR_FLAGS_OWN) != 0)
- break;
+ /* if the LANCE still owns this one, we've worked out all sent packets */
+ if ((descr.Flags & TXDSCR_FLAGS_OWN) != 0)
+ break;
#ifdef DEBUG
- PrTime(); printk("Send packet done on descr %d\n", priv->nexttxdone);
+ PrTime();
+ printk("Send packet done on descr %d\n", priv->nexttxdone);
#endif
- /* update statistics */
- if ((descr.Flags & TXDSCR_FLAGS_ERR) == 0)
- {
- priv->stat.tx_packets++;
-#if LINUX_VERSION_CODE >= 0x020119 /* byte counters for >= 2.1.25 */
- priv->stat.tx_bytes++;
+ /* update statistics */
+ if ((descr.Flags & TXDSCR_FLAGS_ERR) == 0) {
+ priv->stat.tx_packets++;
+#if LINUX_VERSION_CODE >= 0x020119 /* byte counters for >= 2.1.25 */
+ priv->stat.tx_bytes++;
#endif
- }
- else
- {
- priv->stat.tx_errors++;
- if ((descr.Status & TXDSCR_STATUS_UFLO) != 0)
- {
- priv->stat.tx_fifo_errors++;
- InitLANCE(dev);
- }
- else if ((descr.Status & TXDSCR_STATUS_LCOL) != 0)
- priv->stat.tx_window_errors++;
- else if ((descr.Status & TXDSCR_STATUS_LCAR) != 0)
- priv->stat.tx_carrier_errors++;
- else if ((descr.Status & TXDSCR_STATUS_RTRY) != 0)
- priv->stat.tx_aborted_errors++;
- }
-
- /* go to next descriptor */
- priv->nexttxdone++;
- descraddr += sizeof(LANCE_TxDescr);
- if (priv->nexttxdone >= TXCOUNT)
- {
- priv->nexttxdone = 0;
- descraddr = RAM_TXBASE;
- }
- priv->txbusy--;
- }
-
- /* reset TX interrupt bit */
-
- SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_TINT);
- oldcsr0 = GetLANCE(dev, LANCE_CSR0);
-
- /* at least one descriptor is freed. Therefore we can accept
- a new one */
-
- dev->tbusy = 0;
-
- /* inform upper layers we're in business again */
-
- mark_bh(NET_BH);
-
- return oldcsr0;
+ } else {
+ priv->stat.tx_errors++;
+ if ((descr.Status & TXDSCR_STATUS_UFLO) != 0) {
+ priv->stat.tx_fifo_errors++;
+ InitLANCE(dev);
+ }
+ else
+ if ((descr.Status & TXDSCR_STATUS_LCOL) !=
+ 0) priv->stat.tx_window_errors++;
+ else if ((descr.Status & TXDSCR_STATUS_LCAR) != 0)
+ priv->stat.tx_carrier_errors++;
+ else if ((descr.Status & TXDSCR_STATUS_RTRY) != 0)
+ priv->stat.tx_aborted_errors++;
+ }
+
+ /* go to next descriptor */
+ priv->nexttxdone++;
+ descraddr += sizeof(LANCE_TxDescr);
+ if (priv->nexttxdone >= TXCOUNT) {
+ priv->nexttxdone = 0;
+ descraddr = RAM_TXBASE;
+ }
+ priv->txbusy--;
+ }
+
+ /* reset TX interrupt bit */
+
+ SetLANCE(dev, LANCE_CSR0, oldcsr0 | CSR0_TINT);
+ oldcsr0 = GetLANCE(dev, LANCE_CSR0);
+
+ /* at least one descriptor is freed. Therefore we can accept
+ a new one */
+
+ netif_wake_queue(dev);
+
+ return oldcsr0;
}
/* general interrupt entry */
static void irq_handler(int irq, void *device, struct pt_regs *regs)
{
- struct net_device *dev = (struct net_device*) device;
- u16 csr0val;
-
- /* read CSR0 to get interrupt cause */
-
- csr0val = GetLANCE(dev, LANCE_CSR0);
+ struct net_device *dev = (struct net_device *) device;
+ u16 csr0val;
- /* in case we're not meant... */
+ /* read CSR0 to get interrupt cause */
- if ((csr0val & CSR0_INTR) == 0)
- return;
+ csr0val = GetLANCE(dev, LANCE_CSR0);
- dev->interrupt = 1;
+ /* in case we're not meant... */
- /* loop through the interrupt bits until everything is clear */
+ if ((csr0val & CSR0_INTR) == 0)
+ return;
- do
- {
- if ((csr0val & CSR0_IDON) != 0)
- csr0val = irqstart_handler(dev, csr0val);
- if ((csr0val & CSR0_RINT) != 0)
- csr0val = irqrx_handler(dev, csr0val);
- if ((csr0val & CSR0_TINT) != 0)
- csr0val = irqtx_handler(dev, csr0val);
- }
- while ((csr0val & CSR0_INTR) != 0);
+ /* loop through the interrupt bits until everything is clear */
- dev->interrupt = 0;
+ do {
+ if ((csr0val & CSR0_IDON) != 0)
+ csr0val = irqstart_handler(dev, csr0val);
+ if ((csr0val & CSR0_RINT) != 0)
+ csr0val = irqrx_handler(dev, csr0val);
+ if ((csr0val & CSR0_TINT) != 0)
+ csr0val = irqtx_handler(dev, csr0val);
+ }
+ while ((csr0val & CSR0_INTR) != 0);
}
/* ------------------------------------------------------------------------
@@ -691,184 +696,177 @@ static void irq_handler(int irq, void *device, struct pt_regs *regs)
static int skmca_getinfo(char *buf, int slot, void *d)
{
- int len = 0, i;
- struct net_device *dev = (struct net_device*) d;
- skmca_priv *priv;
-
- /* can't say anything about an uninitialized device... */
-
- if (dev == NULL)
- return len;
- if (dev->priv == NULL)
- return len;
- priv = (skmca_priv*) dev->priv;
-
- /* print info */
-
- len += sprintf(buf + len, "IRQ: %d\n", priv->realirq);
- len += sprintf(buf + len, "Memory: %#lx-%#lx\n", dev->mem_start,
- dev->mem_end - 1);
- len += sprintf(buf + len, "Transceiver: %s\n", MediaNames[priv->medium]);
- len += sprintf(buf + len, "Device: %s\n", dev->name);
- len += sprintf(buf + len, "MAC address:");
- for (i = 0; i < 6; i ++ )
- len += sprintf( buf+len, " %02x", dev->dev_addr[i] );
- buf[len++] = '\n';
- buf[len] = 0;
-
- return len;
+ int len = 0, i;
+ struct net_device *dev = (struct net_device *) d;
+ skmca_priv *priv;
+
+ /* can't say anything about an uninitialized device... */
+
+ if (dev == NULL)
+ return len;
+ if (dev->priv == NULL)
+ return len;
+ priv = (skmca_priv *) dev->priv;
+
+ /* print info */
+
+ len += sprintf(buf + len, "IRQ: %d\n", priv->realirq);
+ len += sprintf(buf + len, "Memory: %#lx-%#lx\n", dev->mem_start,
+ dev->mem_end - 1);
+ len +=
+ sprintf(buf + len, "Transceiver: %s\n",
+ MediaNames[priv->medium]);
+ len += sprintf(buf + len, "Device: %s\n", dev->name);
+ len += sprintf(buf + len, "MAC address:");
+ for (i = 0; i < 6; i++)
+ len += sprintf(buf + len, " %02x", dev->dev_addr[i]);
+ buf[len++] = '\n';
+ buf[len] = 0;
+
+ return len;
}
/* open driver. Means also initialization and start of LANCE */
static int skmca_open(struct net_device *dev)
{
- int result;
- skmca_priv *priv = (skmca_priv*) dev->priv;
-
- /* register resources - only necessary for IRQ */
- result = request_irq(priv->realirq, irq_handler, SA_SHIRQ | SA_SAMPLE_RANDOM,
- "sk_mca", dev);
- if (result != 0)
- {
- printk("%s: failed to register irq %d\n", dev->name, dev->irq);
- return result;
- }
- dev->irq = priv->realirq;
-
- /* set up the card and LANCE */
- InitBoard(dev);
+ int result;
+ skmca_priv *priv = (skmca_priv *) dev->priv;
+
+ /* register resources - only necessary for IRQ */
+ result =
+ request_irq(priv->realirq, irq_handler,
+ SA_SHIRQ | SA_SAMPLE_RANDOM, "sk_mca", dev);
+ if (result != 0) {
+ printk("%s: failed to register irq %d\n", dev->name,
+ dev->irq);
+ return result;
+ }
+ dev->irq = priv->realirq;
+
+ /* set up the card and LANCE */
+ InitBoard(dev);
#ifdef MODULE
- MOD_INC_USE_COUNT;
+ MOD_INC_USE_COUNT;
#endif
- return 0;
+ return 0;
}
/* close driver. Shut down board and free allocated resources */
static int skmca_close(struct net_device *dev)
{
- /* turn off board */
- DeinitBoard(dev);
+ /* turn off board */
+ DeinitBoard(dev);
- /* release resources */
- if (dev->irq != 0)
- free_irq(dev->irq, dev);
- dev->irq = 0;
+ /* release resources */
+ if (dev->irq != 0)
+ free_irq(dev->irq, dev);
+ dev->irq = 0;
#ifdef MODULE
- MOD_DEC_USE_COUNT;
+ MOD_DEC_USE_COUNT;
#endif
- return 0;
+ return 0;
}
/* transmit a block. */
static int skmca_tx(struct sk_buff *skb, struct net_device *dev)
{
- skmca_priv *priv = (skmca_priv*) dev->priv;
- LANCE_TxDescr descr;
- unsigned int address;
- int tmplen, retval = 0;
- unsigned long flags;
-
- /* if we get called with a NULL descriptor, the Ethernet layer thinks
- our card is stuck an we should reset it. We'll do this completely: */
-
- if (skb == NULL)
- {
- DeinitBoard(dev);
- InitBoard(dev);
- return 0; /* don't try to free the block here ;-) */
- }
-
- /* is there space in the Tx queue ? If no, the upper layer gave us a
- packet in spite of us not being ready and is really in trouble.
- We'll do the dropping for him: */
- if (priv->txbusy >= TXCOUNT)
- {
- priv->stat.tx_dropped++;
- retval = -EIO;
- goto tx_done;
- }
-
- /* get TX descriptor */
- address = RAM_TXBASE + (priv->nexttxput * sizeof(LANCE_TxDescr));
- isa_memcpy_fromio(&descr, dev->mem_start + address, sizeof(LANCE_TxDescr));
-
- /* enter packet length as 2s complement - assure minimum length */
- tmplen = skb->len;
- if (tmplen < 60)
- tmplen = 60;
- descr.Len = 65536 - tmplen;
-
- /* copy filler into RAM - in case we're filling up...
- we're filling a bit more than necessary, but that doesn't harm
- since the buffer is far larger... */
- if (tmplen > skb->len)
- {
- char *fill = "NetBSD is a nice OS too! ";
- unsigned int destoffs = 0, l = strlen(fill);
-
- while (destoffs < tmplen)
- {
- isa_memcpy_toio(dev->mem_start + descr.LowAddr + destoffs, fill, l);
- destoffs += l;
- }
- }
-
- /* do the real data copying */
- isa_memcpy_toio(dev->mem_start + descr.LowAddr, skb->data, skb->len);
-
- /* hand descriptor over to LANCE - this is the first and last chunk */
- descr.Flags = TXDSCR_FLAGS_OWN | TXDSCR_FLAGS_STP | TXDSCR_FLAGS_ENP;
+ skmca_priv *priv = (skmca_priv *) dev->priv;
+ LANCE_TxDescr descr;
+ unsigned int address;
+ int tmplen, retval = 0;
+ unsigned long flags;
+
+ netif_stop_queue(dev);
+
+ /* is there space in the Tx queue ? If no, the upper layer gave us a
+ packet in spite of us not being ready and is really in trouble.
+ We'll do the dropping for him: */
+ if (priv->txbusy >= TXCOUNT) {
+ priv->stat.tx_dropped++;
+ retval = -EIO;
+ goto tx_done;
+ }
+
+ /* get TX descriptor */
+ address = RAM_TXBASE + (priv->nexttxput * sizeof(LANCE_TxDescr));
+ isa_memcpy_fromio(&descr, dev->mem_start + address,
+ sizeof(LANCE_TxDescr));
+
+ /* enter packet length as 2s complement - assure minimum length */
+ tmplen = skb->len;
+ if (tmplen < 60)
+ tmplen = 60;
+ descr.Len = 65536 - tmplen;
+
+ /* copy filler into RAM - in case we're filling up...
+ we're filling a bit more than necessary, but that doesn't harm
+ since the buffer is far larger... */
+ if (tmplen > skb->len) {
+ char *fill = "NetBSD is a nice OS too! ";
+ unsigned int destoffs = 0, l = strlen(fill);
+
+ while (destoffs < tmplen) {
+ isa_memcpy_toio(dev->mem_start + descr.LowAddr +
+ destoffs, fill, l);
+ destoffs += l;
+ }
+ }
+
+ /* do the real data copying */
+ isa_memcpy_toio(dev->mem_start + descr.LowAddr, skb->data,
+ skb->len);
+
+ /* hand descriptor over to LANCE - this is the first and last chunk */
+ descr.Flags =
+ TXDSCR_FLAGS_OWN | TXDSCR_FLAGS_STP | TXDSCR_FLAGS_ENP;
#ifdef DEBUG
- PrTime(); printk("Send packet on descr %d len %d\n", priv->nexttxput, skb->len);
+ PrTime();
+ printk("Send packet on descr %d len %d\n", priv->nexttxput,
+ skb->len);
#endif
- /* one more descriptor busy */
- save_flags(flags);
- cli();
- priv->nexttxput++;
- if (priv->nexttxput >= TXCOUNT)
- priv->nexttxput = 0;
- priv->txbusy++;
- dev->tbusy = (priv->txbusy >= TXCOUNT);
+ /* one more descriptor busy */
+ save_flags(flags);
+ cli();
+ priv->nexttxput++;
+ if (priv->nexttxput >= TXCOUNT)
+ priv->nexttxput = 0;
+ priv->txbusy++;
+ if (priv->txbusy < TXCOUNT)
+ netif_wake_queue(dev);
- /* write descriptor back to RAM */
- isa_memcpy_toio(dev->mem_start + address, &descr, sizeof(LANCE_TxDescr));
+ /* write descriptor back to RAM */
+ isa_memcpy_toio(dev->mem_start + address, &descr,
+ sizeof(LANCE_TxDescr));
- /* if no descriptors were active, give the LANCE a hint to read it
- immediately */
+ /* if no descriptors were active, give the LANCE a hint to read it
+ immediately */
- if (priv->txbusy == 0)
- SetLANCE(dev, LANCE_CSR0, CSR0_INEA | CSR0_TDMD);
+ if (priv->txbusy == 0)
+ SetLANCE(dev, LANCE_CSR0, CSR0_INEA | CSR0_TDMD);
- restore_flags(flags);
+ restore_flags(flags);
tx_done:
-
- /* When did that change exactly ? */
-
-#if LINUX_VERSION_CODE >= 0x020200
- dev_kfree_skb(skb);
-#else
- dev_kfree_skb(skb, FREE_WRITE);
-#endif
- return retval;
+ /* When did that change exactly ? */
+ dev_kfree_skb(skb);
+ return retval;
}
/* return pointer to Ethernet statistics */
static struct enet_statistics *skmca_stats(struct net_device *dev)
{
- skmca_priv *priv = (skmca_priv*) dev->priv;
-
- return &(priv->stat);
+ skmca_priv *priv = (skmca_priv *) dev->priv;
+ return &(priv->stat);
}
/* we don't support runtime reconfiguration, since an MCA card can
@@ -876,7 +874,7 @@ static struct enet_statistics *skmca_stats(struct net_device *dev)
static int skmca_config(struct net_device *dev, struct ifmap *map)
{
- return 0;
+ return 0;
}
/* switch receiver mode. We use the LANCE's multicast filter to prefilter
@@ -884,39 +882,38 @@ static int skmca_config(struct net_device *dev, struct ifmap *map)
static void skmca_set_multicast_list(struct net_device *dev)
{
- LANCE_InitBlock block;
-
- /* first stop the LANCE... */
- StopLANCE(dev);
-
- /* ...then modify the initialization block... */
- isa_memcpy_fromio(&block, dev->mem_start + RAM_INITBASE, sizeof(block));
- if (dev->flags & IFF_PROMISC)
- block.Mode |= LANCE_INIT_PROM;
- else
- block.Mode &= ~LANCE_INIT_PROM;
-
- if (dev->flags & IFF_ALLMULTI) /* get all multicasts */
- {
- memset(block.LAdrF, 8, 0xff);
- }
- else /* get selected/no multicasts */
- {
- struct dev_mc_list *mptr;
- int code;
-
- memset(block.LAdrF, 8, 0x00);
- for (mptr = dev->mc_list; mptr != NULL; mptr = mptr->next)
- {
- code = GetHash(mptr->dmi_addr);
- block.LAdrF[(code >> 3) & 7] |= 1 << (code & 7);
- }
- }
-
- isa_memcpy_toio(dev->mem_start + RAM_INITBASE, &block, sizeof(block));
-
- /* ...then reinit LANCE with the correct flags */
- InitLANCE(dev);
+ LANCE_InitBlock block;
+
+ /* first stop the LANCE... */
+ StopLANCE(dev);
+
+ /* ...then modify the initialization block... */
+ isa_memcpy_fromio(&block, dev->mem_start + RAM_INITBASE,
+ sizeof(block));
+ if (dev->flags & IFF_PROMISC)
+ block.Mode |= LANCE_INIT_PROM;
+ else
+ block.Mode &= ~LANCE_INIT_PROM;
+
+ if (dev->flags & IFF_ALLMULTI) { /* get all multicasts */
+ memset(block.LAdrF, 8, 0xff);
+ } else { /* get selected/no multicasts */
+
+ struct dev_mc_list *mptr;
+ int code;
+
+ memset(block.LAdrF, 8, 0x00);
+ for (mptr = dev->mc_list; mptr != NULL; mptr = mptr->next) {
+ code = GetHash(mptr->dmi_addr);
+ block.LAdrF[(code >> 3) & 7] |= 1 << (code & 7);
+ }
+ }
+
+ isa_memcpy_toio(dev->mem_start + RAM_INITBASE, &block,
+ sizeof(block));
+
+ /* ...then reinit LANCE with the correct flags */
+ InitLANCE(dev);
}
/* ------------------------------------------------------------------------
@@ -924,149 +921,143 @@ static void skmca_set_multicast_list(struct net_device *dev)
* ------------------------------------------------------------------------ */
#ifdef MODULE
-static int startslot; /* counts through slots when probing multiple devices */
+static int startslot; /* counts through slots when probing multiple devices */
#else
-#define startslot 0 /* otherwise a dummy, since there is only eth0 in-kern*/
+#define startslot 0 /* otherwise a dummy, since there is only eth0 in-kern */
#endif
int skmca_probe(struct net_device *dev)
{
- int force_detect = 0;
- int junior, slot, i;
- int base = 0, irq = 0;
- skmca_priv *priv;
- skmca_medium medium;
+ int force_detect = 0;
+ int junior, slot, i;
+ int base = 0, irq = 0;
+ skmca_priv *priv;
+ skmca_medium medium;
- /* can't work without an MCA bus ;-) */
-
- if (MCA_bus == 0)
- return ENODEV;
-
- /* start address of 1 --> forced detection */
-
- if (dev->mem_start == 1)
- force_detect = 1;
+ /* can't work without an MCA bus ;-) */
- /* search through slots */
-
- if (dev != NULL)
- {
- base = dev->mem_start;
- irq = dev->irq;
- }
- slot = dofind(&junior, startslot);
+ if (MCA_bus == 0)
+ return ENODEV;
+
+ /* start address of 1 --> forced detection */
+
+ if (dev->mem_start == 1)
+ force_detect = 1;
+
+ /* search through slots */
+
+ if (dev != NULL) {
+ base = dev->mem_start;
+ irq = dev->irq;
+ }
+ slot = dofind(&junior, startslot);
- while (slot != -1)
- {
- /* deduce card addresses */
+ while (slot != -1) {
+ /* deduce card addresses */
- getaddrs(slot, junior, &base, &irq, &medium);
+ getaddrs(slot, junior, &base, &irq, &medium);
#if LINUX_VERSION_CODE >= 0x020200
- /* slot already in use ? */
+ /* slot already in use ? */
- if (mca_is_adapter_used(slot))
- {
- slot = dofind(&junior, slot + 1);
- continue;
- }
+ if (mca_is_adapter_used(slot)) {
+ slot = dofind(&junior, slot + 1);
+ continue;
+ }
#endif
- /* were we looking for something different ? */
-
- if ((dev->irq != 0) || (dev->mem_start != 0))
- {
- if ((dev->irq != 0) && (dev->irq != irq))
- {
- slot = dofind(&junior, slot + 1);
- continue;
- }
- if ((dev->mem_start != 0) && (dev->mem_start != base))
- {
- slot = dofind(&junior, slot + 1);
- continue;
- }
- }
-
- /* found something that matches */
-
- break;
- }
+ /* were we looking for something different ? */
- /* nothing found ? */
-
- if (slot == -1)
- return ((base != 0) || (irq != 0)) ? ENXIO : ENODEV;
-
- /* make procfs entries */
-
- if (junior)
- mca_set_adapter_name(slot, "SKNET junior MC2 Ethernet Adapter");
- else
- mca_set_adapter_name(slot, "SKNET MC2+ Ethernet Adapter");
- mca_set_adapter_procfn(slot, (MCA_ProcFn) skmca_getinfo, dev);
+ if ((dev->irq != 0) || (dev->mem_start != 0)) {
+ if ((dev->irq != 0) && (dev->irq != irq)) {
+ slot = dofind(&junior, slot + 1);
+ continue;
+ }
+ if ((dev->mem_start != 0)
+ && (dev->mem_start != base)) {
+ slot = dofind(&junior, slot + 1);
+ continue;
+ }
+ }
+
+ /* found something that matches */
+
+ break;
+ }
+
+ /* nothing found ? */
+
+ if (slot == -1)
+ return ((base != 0) || (irq != 0)) ? ENXIO : ENODEV;
+
+ /* make procfs entries */
+
+ if (junior)
+ mca_set_adapter_name(slot,
+ "SKNET junior MC2 Ethernet Adapter");
+ else
+ mca_set_adapter_name(slot, "SKNET MC2+ Ethernet Adapter");
+ mca_set_adapter_procfn(slot, (MCA_ProcFn) skmca_getinfo, dev);
#if LINUX_VERSION_CODE >= 0x020200
- mca_mark_as_used(slot);
+ mca_mark_as_used(slot);
#endif
-
- /* announce success */
- printk("%s: SKNet %s adapter found in slot %d\n", dev->name,
- junior ? "Junior MC2" : "MC2+", slot + 1);
-
- /* allocate structure */
- priv = dev->priv = (skmca_priv*) kmalloc(sizeof(skmca_priv), GFP_KERNEL);
- priv->slot = slot;
- priv->macbase = base + 0x3fc0;
- priv->ioregaddr = base + 0x3ff0;
- priv->ctrladdr = base + 0x3ff2;
- priv->cmdaddr = base + 0x3ff3;
- priv->realirq = irq;
- priv->medium = medium;
- memset(&(priv->stat), 0, sizeof(struct enet_statistics));
-
- /* set base + irq for this device (irq not allocated so far) */
- dev->irq = 0;
- dev->mem_start = base;
- dev->mem_end = base + 0x4000;
-
- /* set methods */
- dev->open = skmca_open;
- dev->stop = skmca_close;
- dev->set_config = skmca_config;
- dev->hard_start_xmit = skmca_tx;
- dev->do_ioctl = NULL;
- dev->get_stats = skmca_stats;
- dev->set_multicast_list = skmca_set_multicast_list;
- dev->flags |= IFF_MULTICAST;
-
- /* generic setup */
- ether_setup(dev);
- dev->interrupt = 0;
- dev->tbusy = 0;
- dev->start = 0;
-
- /* copy out MAC address */
- for (i = 0; i < 6; i++)
- dev->dev_addr[i] = readb(priv->macbase + (i << 1));
-
- /* print config */
- printk("%s: IRQ %d, memory %#lx-%#lx, "
- "MAC address %02x:%02x:%02x:%02x:%02x:%02x.\n",
- dev->name, priv->realirq, dev->mem_start, dev->mem_end - 1,
- dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
- dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
- printk("%s: %s medium\n", dev->name, MediaNames[priv->medium]);
-
- /* reset board */
-
- ResetBoard(dev);
+
+ /* announce success */
+ printk("%s: SKNet %s adapter found in slot %d\n", dev->name,
+ junior ? "Junior MC2" : "MC2+", slot + 1);
+
+ /* allocate structure */
+ priv = dev->priv =
+ (skmca_priv *) kmalloc(sizeof(skmca_priv), GFP_KERNEL);
+ priv->slot = slot;
+ priv->macbase = base + 0x3fc0;
+ priv->ioregaddr = base + 0x3ff0;
+ priv->ctrladdr = base + 0x3ff2;
+ priv->cmdaddr = base + 0x3ff3;
+ priv->realirq = irq;
+ priv->medium = medium;
+ memset(&(priv->stat), 0, sizeof(struct enet_statistics));
+
+ /* set base + irq for this device (irq not allocated so far) */
+ dev->irq = 0;
+ dev->mem_start = base;
+ dev->mem_end = base + 0x4000;
+
+ /* set methods */
+ dev->open = skmca_open;
+ dev->stop = skmca_close;
+ dev->set_config = skmca_config;
+ dev->hard_start_xmit = skmca_tx;
+ dev->do_ioctl = NULL;
+ dev->get_stats = skmca_stats;
+ dev->set_multicast_list = skmca_set_multicast_list;
+ dev->flags |= IFF_MULTICAST;
+
+ /* generic setup */
+ ether_setup(dev);
+
+ /* copy out MAC address */
+ for (i = 0; i < 6; i++)
+ dev->dev_addr[i] = readb(priv->macbase + (i << 1));
+
+ /* print config */
+ printk("%s: IRQ %d, memory %#lx-%#lx, "
+ "MAC address %02x:%02x:%02x:%02x:%02x:%02x.\n",
+ dev->name, priv->realirq, dev->mem_start, dev->mem_end - 1,
+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+ printk("%s: %s medium\n", dev->name, MediaNames[priv->medium]);
+
+ /* reset board */
+
+ ResetBoard(dev);
#ifdef MODULE
- startslot = slot + 1;
+ startslot = slot + 1;
#endif
- return 0;
+ return 0;
}
/* ------------------------------------------------------------------------
@@ -1079,61 +1070,58 @@ int skmca_probe(struct net_device *dev)
static char NameSpace[8 * DEVMAX];
static struct net_device moddevs[DEVMAX] =
- {{NameSpace + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
- {NameSpace + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
- {NameSpace + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
- {NameSpace + 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
- {NameSpace + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}};
+ { {NameSpace + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+{NameSpace + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+{NameSpace + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+{NameSpace + 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+{NameSpace + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}
+};
-int irq=0;
-int io=0;
+int irq = 0;
+int io = 0;
int init_module(void)
{
- int z, res;
-
- startslot = 0;
- for (z = 0; z < DEVMAX; z++)
- {
- strcpy(moddevs[z].name, " ");
- res = register_netdev(moddevs + z);
- if (res != 0)
- return (z > 0) ? 0 : -EIO;
- }
-
- return 0;
+ int z, res;
+
+ startslot = 0;
+ for (z = 0; z < DEVMAX; z++) {
+ strcpy(moddevs[z].name, " ");
+ res = register_netdev(moddevs + z);
+ if (res != 0)
+ return (z > 0) ? 0 : -EIO;
+ }
+
+ return 0;
}
void cleanup_module(void)
{
- struct net_device *dev;
- skmca_priv *priv;
- int z;
-
- if (MOD_IN_USE)
- {
- printk("cannot unload, module in use\n");
- return;
- }
-
- for (z = 0; z < DEVMAX; z++)
- {
- dev = moddevs + z;
- if (dev->priv != NULL)
- {
- priv = (skmca_priv*) dev->priv;
- DeinitBoard(dev);
- if (dev->irq != 0)
- free_irq(dev->irq, dev);
- dev->irq = 0;
- unregister_netdev(dev);
+ struct net_device *dev;
+ skmca_priv *priv;
+ int z;
+
+ if (MOD_IN_USE) {
+ printk("cannot unload, module in use\n");
+ return;
+ }
+
+ for (z = 0; z < DEVMAX; z++) {
+ dev = moddevs + z;
+ if (dev->priv != NULL) {
+ priv = (skmca_priv *) dev->priv;
+ DeinitBoard(dev);
+ if (dev->irq != 0)
+ free_irq(dev->irq, dev);
+ dev->irq = 0;
+ unregister_netdev(dev);
#if LINUX_VERSION_CODE >= 0x020200
- mca_mark_as_unused(priv->slot);
+ mca_mark_as_unused(priv->slot);
#endif
- mca_set_adapter_procfn(priv->slot, NULL, NULL);
- kfree_s(dev->priv, sizeof(skmca_priv));
- dev->priv = NULL;
- }
- }
+ mca_set_adapter_procfn(priv->slot, NULL, NULL);
+ kfree_s(dev->priv, sizeof(skmca_priv));
+ dev->priv = NULL;
+ }
+ }
}
-#endif /* MODULE */
+#endif /* MODULE */
diff --git a/drivers/net/skeleton.c b/drivers/net/skeleton.c
index 21628c1fc..776b7a6a6 100644
--- a/drivers/net/skeleton.c
+++ b/drivers/net/skeleton.c
@@ -416,7 +416,7 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
spin_lock_irq(&np->lock);
add_to_tx_ring(np, skb, length);
- dev->trans_start = jiffied;
+ dev->trans_start = jiffies;
/* If we just used up the very last entry in the
* TX ring on this device, tell the queueing
@@ -482,8 +482,7 @@ void net_tx(struct net_device *dev)
* condition, and space has now been made available,
* wake up the queue.
*/
- if (test_bit(LINK_STATE_XOFF, &dev->state) &&
- ! tx_full(dev))
+ if (netif_queue_stopped(dev) && ! tx_full(dev))
netif_wake_queue(dev);
spin_unlock(&np->lock);
diff --git a/drivers/net/skfp/.cvsignore b/drivers/net/skfp/.cvsignore
new file mode 100644
index 000000000..f7cf9ab27
--- /dev/null
+++ b/drivers/net/skfp/.cvsignore
@@ -0,0 +1,10 @@
+! RCS SCCS CVS CVS.adm
+RCSLOG cvslog.*
+tags TAGS
+.make.state .nse_depinfo
+*~ #* .#* ,* _$* *$
+*.old *.bak *.BAK *.orig *.rej .del-*
+*.a *.olb *.o *.obj *.so *.exe
+*.Z *.elc *.ln
+.depend
+.*.flags
diff --git a/drivers/net/skfp/Makefile b/drivers/net/skfp/Makefile
new file mode 100644
index 000000000..82aa26e4c
--- /dev/null
+++ b/drivers/net/skfp/Makefile
@@ -0,0 +1,39 @@
+#
+# Makefile for the SysKonnect FDDI PCI adapter driver
+#
+
+ifeq ($(CONFIG_SKFP),y)
+ O_TARGET := skfp.o
+ O_OBJS = skfddi.o hwmtm.o fplustm.o smt.o cfm.o \
+ ecm.o pcmplc.o pmf.o queue.o rmt.o \
+ smtdef.o smtinit.o smttimer.o srf.o lnkstat.o \
+ smtparse.o hwt.o drvfbi.o ess.o
+else
+ ifeq ($(CONFIG_SKFP),m)
+ MOD_LIST_NAME := SKFP_MODULES
+ M_OBJS := skfp.o
+ O_TARGET := skfp.o
+ O_OBJS = skfddi.o hwmtm.o fplustm.o smt.o cfm.o \
+ ecm.o pcmplc.o pmf.o queue.o rmt.o \
+ smtdef.o smtinit.o smttimer.o srf.o lnkstat.o \
+ smtparse.o hwt.o drvfbi.o ess.o
+ endif
+endif
+
+# NOTE:
+# Compiling this driver produces some warnings (and some more are
+# switched off below), but I did not fix this, because the Hardware
+# Module source (see skfddi.c for details) is used for different
+# drivers, and fixing it for Linux might bring problems on other
+# projects. To keep the source common for all those drivers (and
+# thus simplify fixes to it), please do not clean it up!
+
+EXTRA_CFLAGS += -I. -DPCI -DMEM_MAPPED_IO -Wno-strict-prototypes
+
+include $(TOPDIR)/Rules.make
+
+clean:
+ rm -f core *.o *.a *.s
+
+
+
diff --git a/drivers/net/skfp/can.c b/drivers/net/skfp/can.c
new file mode 100644
index 000000000..8a49abce7
--- /dev/null
+++ b/drivers/net/skfp/can.c
@@ -0,0 +1,83 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef lint
+static const char xID_sccs[] = "@(#)can.c 1.5 97/04/07 (C) SK " ;
+#endif
+
+/*
+ * canonical bit order
+ */
+const u_char canonical[256] = {
+ 0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0,
+ 0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0,
+ 0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8,
+ 0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8,
+ 0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4,
+ 0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4,
+ 0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec,
+ 0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc,
+ 0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2,
+ 0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2,
+ 0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea,
+ 0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa,
+ 0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6,
+ 0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6,
+ 0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee,
+ 0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe,
+ 0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1,
+ 0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1,
+ 0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9,
+ 0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9,
+ 0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5,
+ 0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5,
+ 0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed,
+ 0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd,
+ 0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3,
+ 0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3,
+ 0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb,
+ 0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb,
+ 0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7,
+ 0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7,
+ 0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef,
+ 0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff
+} ;
+
+#ifdef MAKE_TABLE
+int byte_reverse(x)
+int x ;
+{
+ int y = 0 ;
+
+ if (x & 0x01)
+ y |= 0x80 ;
+ if (x & 0x02)
+ y |= 0x40 ;
+ if (x & 0x04)
+ y |= 0x20 ;
+ if (x & 0x08)
+ y |= 0x10 ;
+ if (x & 0x10)
+ y |= 0x08 ;
+ if (x & 0x20)
+ y |= 0x04 ;
+ if (x & 0x40)
+ y |= 0x02 ;
+ if (x & 0x80)
+ y |= 0x01 ;
+ return(y) ;
+}
+#endif
diff --git a/drivers/net/skfp/cfm.c b/drivers/net/skfp/cfm.c
new file mode 100644
index 000000000..7a51b765b
--- /dev/null
+++ b/drivers/net/skfp/cfm.c
@@ -0,0 +1,642 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ SMT CFM
+ Configuration Management
+ DAS with single MAC
+*/
+
+/*
+ * Hardware independant state machine implemantation
+ * The following external SMT functions are referenced :
+ *
+ * queue_event()
+ *
+ * The following external HW dependant functions are referenced :
+ * config_mux()
+ *
+ * The following HW dependant events are required :
+ * NONE
+ */
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+
+#define KERNEL
+#include "h/smtstate.h"
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)cfm.c 2.18 98/10/06 (C) SK " ;
+#endif
+
+/*
+ * FSM Macros
+ */
+#define AFLAG 0x10
+#define GO_STATE(x) (smc->mib.fddiSMTCF_State = (x)|AFLAG)
+#define ACTIONS_DONE() (smc->mib.fddiSMTCF_State &= ~AFLAG)
+#define ACTIONS(x) (x|AFLAG)
+
+#ifdef DEBUG
+/*
+ * symbolic state names
+ */
+static const char * const cfm_states[] = {
+ "SC0_ISOLATED","CF1","CF2","CF3","CF4",
+ "SC1_WRAP_A","SC2_WRAP_B","SC5_TRHU_B","SC7_WRAP_S",
+ "SC9_C_WRAP_A","SC10_C_WRAP_B","SC11_C_WRAP_S","SC4_THRU_A"
+} ;
+
+/*
+ * symbolic event names
+ */
+static const char * const cfm_events[] = {
+ "NONE","CF_LOOP_A","CF_LOOP_B","CF_JOIN_A","CF_JOIN_B"
+} ;
+#endif
+
+/*
+ * map from state to downstream port type
+ */
+static const u_char cf_to_ptype[] = {
+ TNONE,TNONE,TNONE,TNONE,TNONE,
+ TNONE,TB,TB,TS,
+ TA,TB,TS,TB
+} ;
+
+/*
+ * CEM port states
+ */
+#define CEM_PST_DOWN 0
+#define CEM_PST_UP 1
+#define CEM_PST_HOLD 2
+/* define portstate array only for A and B port */
+/* Do this within the smc structure (use in multiple cards) */
+
+/*
+ * all Globals are defined in smc.h
+ * struct s_cfm
+ */
+
+/*
+ * function declarations
+ */
+static void cfm_fsm() ;
+
+/*
+ init CFM state machine
+ clear all CFM vars and flags
+*/
+void cfm_init(smc)
+struct s_smc *smc ;
+{
+ smc->mib.fddiSMTCF_State = ACTIONS(SC0_ISOLATED) ;
+ smc->r.rm_join = 0 ;
+ smc->r.rm_loop = 0 ;
+ smc->y[PA].scrub = 0 ;
+ smc->y[PB].scrub = 0 ;
+ smc->y[PA].cem_pst = CEM_PST_DOWN ;
+ smc->y[PB].cem_pst = CEM_PST_DOWN ;
+}
+
+/* Some terms conditions used by the selection criteria */
+#define THRU_ENABLED(smc) (smc->y[PA].pc_mode != PM_TREE && \
+ smc->y[PB].pc_mode != PM_TREE)
+/* Selection criteria for the ports */
+static void selection_criteria (smc,phy)
+struct s_smc *smc ;
+struct s_phy *phy ;
+{
+
+ switch (phy->mib->fddiPORTMy_Type) {
+ case TA:
+ if ( !THRU_ENABLED(smc) && smc->y[PB].cf_join ) {
+ phy->wc_flag = TRUE ;
+ } else {
+ phy->wc_flag = FALSE ;
+ }
+
+ break;
+ case TB:
+ /* take precedence over PA */
+ phy->wc_flag = FALSE ;
+ break;
+ case TS:
+ phy->wc_flag = FALSE ;
+ break;
+ case TM:
+ phy->wc_flag = FALSE ;
+ break;
+ }
+
+}
+
+void all_selection_criteria (smc)
+struct s_smc *smc ;
+{
+ struct s_phy *phy ;
+ int p ;
+
+ for ( p = 0,phy = smc->y ; p < NUMPHYS; p++, phy++ ) {
+ /* Do the selection criteria */
+ selection_criteria (smc,phy);
+ }
+}
+
+static void cem_priv_state (smc, event)
+struct s_smc *smc ;
+int event ;
+/* State machine for private PORT states: used to optimize dual homing */
+{
+ int np; /* Number of the port */
+ int i;
+
+ /* Do this only in a DAS */
+ if (smc->s.sas != SMT_DAS )
+ return ;
+
+ np = event - CF_JOIN;
+
+ if (np != PA && np != PB) {
+ return ;
+ }
+ /* Change the port state according to the event (portnumber) */
+ if (smc->y[np].cf_join) {
+ smc->y[np].cem_pst = CEM_PST_UP ;
+ } else if (!smc->y[np].wc_flag) {
+ /* set the port to done only if it is not withheld */
+ smc->y[np].cem_pst = CEM_PST_DOWN ;
+ }
+
+ /* Don't set an hold port to down */
+
+ /* Check all ports of restart conditions */
+ for (i = 0 ; i < 2 ; i ++ ) {
+ /* Check all port for PORT is on hold and no withhold is done */
+ if ( smc->y[i].cem_pst == CEM_PST_HOLD && !smc->y[i].wc_flag ) {
+ smc->y[i].cem_pst = CEM_PST_DOWN;
+ queue_event(smc,(int)(EVENT_PCM+i),PC_START) ;
+ }
+ if ( smc->y[i].cem_pst == CEM_PST_UP && smc->y[i].wc_flag ) {
+ smc->y[i].cem_pst = CEM_PST_HOLD;
+ queue_event(smc,(int)(EVENT_PCM+i),PC_START) ;
+ }
+ if ( smc->y[i].cem_pst == CEM_PST_DOWN && smc->y[i].wc_flag ) {
+ /*
+ * The port must be restarted when the wc_flag
+ * will be reset. So set the port on hold.
+ */
+ smc->y[i].cem_pst = CEM_PST_HOLD;
+ }
+ }
+ return ;
+}
+
+/*
+ CFM state machine
+ called by dispatcher
+
+ do
+ display state change
+ process event
+ until SM is stable
+*/
+void cfm(smc,event)
+struct s_smc *smc ;
+int event ;
+{
+ int state ; /* remember last state */
+ int cond ;
+ int oldstate ;
+
+ /* We will do the following: */
+ /* - compute the variable WC_Flag for every port (This is where */
+ /* we can extend the requested path checking !!) */
+ /* - do the old (SMT 6.2 like) state machine */
+ /* - do the resulting station states */
+
+ all_selection_criteria (smc);
+
+ /* We will check now whether a state transition is allowed or not */
+ /* - change the portstates */
+ cem_priv_state (smc, event);
+
+ oldstate = smc->mib.fddiSMTCF_State ;
+ do {
+ DB_CFM("CFM : state %s%s",
+ (smc->mib.fddiSMTCF_State & AFLAG) ? "ACTIONS " : "",
+ cfm_states[smc->mib.fddiSMTCF_State & ~AFLAG]) ;
+ DB_CFM(" event %s\n",cfm_events[event],0) ;
+ state = smc->mib.fddiSMTCF_State ;
+ cfm_fsm(smc,event) ;
+ event = 0 ;
+ } while (state != smc->mib.fddiSMTCF_State) ;
+
+#ifndef SLIM_SMT
+ /*
+ * check peer wrap condition
+ */
+ cond = FALSE ;
+ if ( (smc->mib.fddiSMTCF_State == SC9_C_WRAP_A &&
+ smc->y[PA].pc_mode == PM_PEER) ||
+ (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B &&
+ smc->y[PB].pc_mode == PM_PEER) ||
+ (smc->mib.fddiSMTCF_State == SC11_C_WRAP_S &&
+ smc->y[PS].pc_mode == PM_PEER &&
+ smc->y[PS].mib->fddiPORTNeighborType != TS ) ) {
+ cond = TRUE ;
+ }
+ if (cond != smc->mib.fddiSMTPeerWrapFlag)
+ smt_srf_event(smc,SMT_COND_SMT_PEER_WRAP,0,cond) ;
+
+#if 0
+ /*
+ * Don't send ever MAC_PATH_CHANGE events. Our MAC is hard-wired
+ * to the primary path.
+ */
+ /*
+ * path change
+ */
+ if (smc->mib.fddiSMTCF_State != oldstate) {
+ smt_srf_event(smc,SMT_EVENT_MAC_PATH_CHANGE,INDEX_MAC,0) ;
+ }
+#endif
+#endif /* no SLIM_SMT */
+
+ /*
+ * set MAC port type
+ */
+ smc->mib.m[MAC0].fddiMACDownstreamPORTType =
+ cf_to_ptype[smc->mib.fddiSMTCF_State] ;
+ cfm_state_change(smc,(int)smc->mib.fddiSMTCF_State) ;
+}
+
+/*
+ process CFM event
+*/
+/*ARGSUSED1*/
+static void cfm_fsm(smc,cmd)
+struct s_smc *smc ;
+int cmd ;
+{
+ switch(smc->mib.fddiSMTCF_State) {
+ case ACTIONS(SC0_ISOLATED) :
+ smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
+ smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
+ smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
+ smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
+ smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_SEPA ;
+ config_mux(smc,MUX_ISOLATE) ; /* configure PHY Mux */
+ smc->r.rm_loop = FALSE ;
+ smc->r.rm_join = FALSE ;
+ queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
+ /* Don't do the WC-Flag changing here */
+ ACTIONS_DONE() ;
+ DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
+ break;
+ case SC0_ISOLATED :
+ /*SC07*/
+ /*SAS port can be PA or PB ! */
+ if (smc->s.sas && (smc->y[PA].cf_join || smc->y[PA].cf_loop ||
+ smc->y[PB].cf_join || smc->y[PB].cf_loop)) {
+ GO_STATE(SC11_C_WRAP_S) ;
+ break ;
+ }
+ /*SC01*/
+ if ((smc->y[PA].cem_pst == CEM_PST_UP && smc->y[PA].cf_join &&
+ !smc->y[PA].wc_flag) || smc->y[PA].cf_loop) {
+ GO_STATE(SC9_C_WRAP_A) ;
+ break ;
+ }
+ /*SC02*/
+ if ((smc->y[PB].cem_pst == CEM_PST_UP && smc->y[PB].cf_join &&
+ !smc->y[PB].wc_flag) || smc->y[PB].cf_loop) {
+ GO_STATE(SC10_C_WRAP_B) ;
+ break ;
+ }
+ break ;
+ case ACTIONS(SC9_C_WRAP_A) :
+ smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
+ smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
+ smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ;
+ smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
+ smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
+ config_mux(smc,MUX_WRAPA) ; /* configure PHY mux */
+ if (smc->y[PA].cf_loop) {
+ smc->r.rm_join = FALSE ;
+ smc->r.rm_loop = TRUE ;
+ queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */
+ }
+ if (smc->y[PA].cf_join) {
+ smc->r.rm_loop = FALSE ;
+ smc->r.rm_join = TRUE ;
+ queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
+ }
+ ACTIONS_DONE() ;
+ DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
+ break ;
+ case SC9_C_WRAP_A :
+ /*SC10*/
+ if ( (smc->y[PA].wc_flag || !smc->y[PA].cf_join) &&
+ !smc->y[PA].cf_loop ) {
+ GO_STATE(SC0_ISOLATED) ;
+ break ;
+ }
+ /*SC12*/
+ else if ( (smc->y[PB].cf_loop && smc->y[PA].cf_join &&
+ smc->y[PA].cem_pst == CEM_PST_UP) ||
+ ((smc->y[PB].cf_loop ||
+ (smc->y[PB].cf_join &&
+ smc->y[PB].cem_pst == CEM_PST_UP)) &&
+ (smc->y[PA].pc_mode == PM_TREE ||
+ smc->y[PB].pc_mode == PM_TREE))) {
+ smc->y[PA].scrub = TRUE ;
+ GO_STATE(SC10_C_WRAP_B) ;
+ break ;
+ }
+ /*SC14*/
+ else if (!smc->s.attach_s &&
+ smc->y[PA].cf_join &&
+ smc->y[PA].cem_pst == CEM_PST_UP &&
+ smc->y[PA].pc_mode == PM_PEER && smc->y[PB].cf_join &&
+ smc->y[PB].cem_pst == CEM_PST_UP &&
+ smc->y[PB].pc_mode == PM_PEER) {
+ smc->y[PA].scrub = TRUE ;
+ smc->y[PB].scrub = TRUE ;
+ GO_STATE(SC4_THRU_A) ;
+ break ;
+ }
+ /*SC15*/
+ else if ( smc->s.attach_s &&
+ smc->y[PA].cf_join &&
+ smc->y[PA].cem_pst == CEM_PST_UP &&
+ smc->y[PA].pc_mode == PM_PEER &&
+ smc->y[PB].cf_join &&
+ smc->y[PB].cem_pst == CEM_PST_UP &&
+ smc->y[PB].pc_mode == PM_PEER) {
+ smc->y[PA].scrub = TRUE ;
+ smc->y[PB].scrub = TRUE ;
+ GO_STATE(SC5_THRU_B) ;
+ break ;
+ }
+ break ;
+ case ACTIONS(SC10_C_WRAP_B) :
+ smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
+ smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
+ smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
+ smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ;
+ smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
+ config_mux(smc,MUX_WRAPB) ; /* configure PHY mux */
+ if (smc->y[PB].cf_loop) {
+ smc->r.rm_join = FALSE ;
+ smc->r.rm_loop = TRUE ;
+ queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */
+ }
+ if (smc->y[PB].cf_join) {
+ smc->r.rm_loop = FALSE ;
+ smc->r.rm_join = TRUE ;
+ queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
+ }
+ ACTIONS_DONE() ;
+ DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
+ break ;
+ case SC10_C_WRAP_B :
+ /*SC20*/
+ if ( !smc->y[PB].cf_join && !smc->y[PB].cf_loop ) {
+ GO_STATE(SC0_ISOLATED) ;
+ break ;
+ }
+ /*SC21*/
+ else if ( smc->y[PA].cf_loop && smc->y[PA].pc_mode == PM_PEER &&
+ smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
+ smc->y[PB].scrub = TRUE ;
+ GO_STATE(SC9_C_WRAP_A) ;
+ break ;
+ }
+ /*SC24*/
+ else if (!smc->s.attach_s &&
+ smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER &&
+ smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
+ smc->y[PA].scrub = TRUE ;
+ smc->y[PB].scrub = TRUE ;
+ GO_STATE(SC4_THRU_A) ;
+ break ;
+ }
+ /*SC25*/
+ else if ( smc->s.attach_s &&
+ smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER &&
+ smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
+ smc->y[PA].scrub = TRUE ;
+ smc->y[PB].scrub = TRUE ;
+ GO_STATE(SC5_THRU_B) ;
+ break ;
+ }
+ break ;
+ case ACTIONS(SC4_THRU_A) :
+ smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ;
+ smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ;
+ smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
+ smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ;
+ smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ;
+ config_mux(smc,MUX_THRUA) ; /* configure PHY mux */
+ smc->r.rm_loop = FALSE ;
+ smc->r.rm_join = TRUE ;
+ queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
+ ACTIONS_DONE() ;
+ DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
+ break ;
+ case SC4_THRU_A :
+ /*SC41*/
+ if (smc->y[PB].wc_flag || !smc->y[PB].cf_join) {
+ smc->y[PA].scrub = TRUE ;
+ GO_STATE(SC9_C_WRAP_A) ;
+ break ;
+ }
+ /*SC42*/
+ else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) {
+ smc->y[PB].scrub = TRUE ;
+ GO_STATE(SC10_C_WRAP_B) ;
+ break ;
+ }
+ /*SC45*/
+ else if (smc->s.attach_s) {
+ smc->y[PB].scrub = TRUE ;
+ GO_STATE(SC5_THRU_B) ;
+ break ;
+ }
+ break ;
+ case ACTIONS(SC5_THRU_B) :
+ smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ;
+ smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ;
+ smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ;
+ smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
+ smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ;
+ config_mux(smc,MUX_THRUB) ; /* configure PHY mux */
+ smc->r.rm_loop = FALSE ;
+ smc->r.rm_join = TRUE ;
+ queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
+ ACTIONS_DONE() ;
+ DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
+ break ;
+ case SC5_THRU_B :
+ /*SC51*/
+ if (!smc->y[PB].cf_join || smc->y[PB].wc_flag) {
+ smc->y[PA].scrub = TRUE ;
+ GO_STATE(SC9_C_WRAP_A) ;
+ break ;
+ }
+ /*SC52*/
+ else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) {
+ smc->y[PB].scrub = TRUE ;
+ GO_STATE(SC10_C_WRAP_B) ;
+ break ;
+ }
+ /*SC54*/
+ else if (!smc->s.attach_s) {
+ smc->y[PA].scrub = TRUE ;
+ GO_STATE(SC4_THRU_A) ;
+ break ;
+ }
+ break ;
+ case ACTIONS(SC11_C_WRAP_S) :
+ smc->mib.p[PS].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
+ smc->mib.p[PS].fddiPORTMACPlacement = INDEX_MAC ;
+ smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
+ config_mux(smc,MUX_WRAPS) ; /* configure PHY mux */
+ if (smc->y[PA].cf_loop || smc->y[PB].cf_loop) {
+ smc->r.rm_join = FALSE ;
+ smc->r.rm_loop = TRUE ;
+ queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */
+ }
+ if (smc->y[PA].cf_join || smc->y[PB].cf_join) {
+ smc->r.rm_loop = FALSE ;
+ smc->r.rm_join = TRUE ;
+ queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
+ }
+ ACTIONS_DONE() ;
+ DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
+ break ;
+ case SC11_C_WRAP_S :
+ /*SC70*/
+ if ( !smc->y[PA].cf_join && !smc->y[PA].cf_loop &&
+ !smc->y[PB].cf_join && !smc->y[PB].cf_loop) {
+ GO_STATE(SC0_ISOLATED) ;
+ break ;
+ }
+ break ;
+ default:
+ SMT_PANIC(smc,SMT_E0106, SMT_E0106_MSG) ;
+ break;
+ }
+}
+
+/*
+ * get MAC's input Port
+ * return :
+ * PA or PB
+ */
+int cfm_get_mac_input(smc)
+struct s_smc *smc ;
+{
+ return((smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
+ smc->mib.fddiSMTCF_State == SC5_THRU_B) ? PB : PA) ;
+}
+
+/*
+ * get MAC's output Port
+ * return :
+ * PA or PB
+ */
+int cfm_get_mac_output(smc)
+struct s_smc *smc ;
+{
+ return((smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
+ smc->mib.fddiSMTCF_State == SC4_THRU_A) ? PB : PA) ;
+}
+
+static char path_iso[] = {
+ 0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_ISO,
+ 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_ISO,
+ 0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_ISO
+} ;
+
+static char path_wrap_a[] = {
+ 0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_PRIM,
+ 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM,
+ 0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_ISO
+} ;
+
+static char path_wrap_b[] = {
+ 0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_PRIM,
+ 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM,
+ 0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_ISO
+} ;
+
+static char path_thru[] = {
+ 0,0, 0,RES_PORT, 0,PA + INDEX_PORT, 0,PATH_PRIM,
+ 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM,
+ 0,0, 0,RES_PORT, 0,PB + INDEX_PORT, 0,PATH_PRIM
+} ;
+
+static char path_wrap_s[] = {
+ 0,0, 0,RES_PORT, 0,PS + INDEX_PORT, 0,PATH_PRIM,
+ 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_PRIM,
+} ;
+
+static char path_iso_s[] = {
+ 0,0, 0,RES_PORT, 0,PS + INDEX_PORT, 0,PATH_ISO,
+ 0,0, 0,RES_MAC, 0,INDEX_MAC, 0,PATH_ISO,
+} ;
+
+int cem_build_path(smc,to,path_index)
+struct s_smc *smc ;
+char *to ;
+int path_index ;
+{
+ char *path ;
+ int len ;
+
+ switch (smc->mib.fddiSMTCF_State) {
+ default :
+ case SC0_ISOLATED :
+ path = smc->s.sas ? path_iso_s : path_iso ;
+ len = smc->s.sas ? sizeof(path_iso_s) : sizeof(path_iso) ;
+ break ;
+ case SC9_C_WRAP_A :
+ path = path_wrap_a ;
+ len = sizeof(path_wrap_a) ;
+ break ;
+ case SC10_C_WRAP_B :
+ path = path_wrap_b ;
+ len = sizeof(path_wrap_b) ;
+ break ;
+ case SC4_THRU_A :
+ path = path_thru ;
+ len = sizeof(path_thru) ;
+ break ;
+ case SC11_C_WRAP_S :
+ path = path_wrap_s ;
+ len = sizeof(path_wrap_s) ;
+ break ;
+ }
+ memcpy(to,path,len) ;
+
+ LINT_USE(path_index);
+
+ return(len) ;
+}
diff --git a/drivers/net/skfp/drvfbi.c b/drivers/net/skfp/drvfbi.c
new file mode 100644
index 000000000..e1e48bc91
--- /dev/null
+++ b/drivers/net/skfp/drvfbi.c
@@ -0,0 +1,1612 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * FBI board dependent Driver for SMT and LLC
+ */
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/supern_2.h"
+#include "h/skfbiinc.h"
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)drvfbi.c 1.63 99/02/11 (C) SK " ;
+#endif
+
+/*
+ * PCM active state
+ */
+#define PC8_ACTIVE 8
+
+#define LED_Y_ON 0x11 /* Used for ring up/down indication */
+#define LED_Y_OFF 0x10
+
+
+#define MS2BCLK(x) ((x)*12500L)
+
+/*
+ * valid configuration values are:
+ */
+#ifdef ISA
+const int opt_ints[] = {8, 3, 4, 5, 9, 10, 11, 12, 15} ;
+const int opt_iops[] = {8,
+ 0x100, 0x120, 0x180, 0x1a0, 0x220, 0x240, 0x320, 0x340};
+const int opt_dmas[] = {4, 3, 5, 6, 7} ;
+const int opt_eproms[] = {15, 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce,
+ 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc} ;
+#endif
+#ifdef EISA
+const int opt_ints[] = {5, 9, 10, 11} ;
+const int opt_dmas[] = {0, 5, 6, 7} ;
+const int opt_eproms[] = {0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce,
+ 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc} ;
+#endif
+
+#ifdef MCA
+int opt_ints[] = {3, 11, 10, 9} ; /* FM1 */
+int opt_eproms[] = {0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4, 0xd8, 0xdc} ;
+#endif /* MCA */
+
+/*
+ * xPOS_ID:xxxx
+ * | \ /
+ * | \/
+ * | --------------------- the patched POS_ID of the Adapter
+ * | xxxx = (Vendor ID low byte,
+ * | Vendor ID high byte,
+ * | Device ID low byte,
+ * | Device ID high byte)
+ * +------------------------------ the patched oem_id must be
+ * 'S' for SK or 'I' for IBM
+ * this is a short id for the driver.
+ */
+#ifndef MULT_OEM
+#ifndef OEM_CONCEPT
+#ifndef MCA
+const u_char oem_id[] = "xPOS_ID:xxxx" ;
+#else
+const u_char oem_id[] = "xPOSID1:xxxx" ; /* FM1 card id. */
+#endif
+#else /* OEM_CONCEPT */
+#ifndef MCA
+const u_char oem_id[] = OEM_ID ;
+#else
+const u_char oem_id[] = OEM_ID1 ; /* FM1 card id. */
+#endif /* MCA */
+#endif /* OEM_CONCEPT */
+#define ID_BYTE0 8
+#define OEMID(smc,i) oem_id[ID_BYTE0 + i]
+#else /* MULT_OEM */
+const struct s_oem_ids oem_ids[] = {
+#include "oemids.h"
+{0}
+};
+#define OEMID(smc,i) smc->hw.oem_id->oi_id[i]
+#endif /* MULT_OEM */
+
+/* Prototypes of external functions */
+extern void hwt_restart() ;
+#ifdef AIX
+extern int AIX_vpdReadByte() ;
+#endif
+
+
+/* Prototypes of local functions. */
+void smt_stop_watchdog() ;
+
+#ifdef MCA
+static int read_card_id() ;
+static void DisableSlotAccess() ;
+static void EnableSlotAccess() ;
+#ifdef AIX
+extern int attach_POS_addr() ;
+extern int detach_POS_addr() ;
+extern u_char read_POS() ;
+extern void write_POS() ;
+extern int AIX_vpdReadByte() ;
+#else
+#define read_POS(smc,a1,a2) ((u_char) inp(a1))
+#define write_POS(smc,a1,a2,a3) outp((a1),(a3))
+#endif
+#endif /* MCA */
+
+
+/*
+ * FDDI card reset
+ */
+void card_start(smc)
+struct s_smc *smc ;
+{
+ int i ;
+#ifdef PCI
+ u_char rev_id ;
+ u_short word;
+#endif
+
+ smt_stop_watchdog(smc) ;
+
+#ifdef ISA
+ outpw(CSR_A,0) ; /* reset for all chips */
+ for (i = 10 ; i ; i--) /* delay for PLC's */
+ (void)inpw(ISR_A) ;
+ OUT_82c54_TIMER(3,COUNT(2) | RW_OP(3) | TMODE(2)) ;
+ /* counter 2, mode 2 */
+ OUT_82c54_TIMER(2,97) ; /* LSB */
+ OUT_82c54_TIMER(2,0) ; /* MSB ( 15.6 us ) */
+ outpw(CSR_A,CS_CRESET) ;
+#endif
+#ifdef EISA
+ outpw(CSR_A,0) ; /* reset for all chips */
+ for (i = 10 ; i ; i--) /* delay for PLC's */
+ (void)inpw(ISR_A) ;
+ outpw(CSR_A,CS_CRESET) ;
+ smc->hw.led = (2<<6) ;
+ outpw(CSR_A,CS_CRESET | smc->hw.led) ;
+#endif
+#ifdef MCA
+ outp(ADDR(CARD_DIS),0) ; /* reset for all chips */
+ for (i = 10 ; i ; i--) /* delay for PLC's */
+ (void)inpw(ISR_A) ;
+ outp(ADDR(CARD_EN),0) ;
+ /* first I/O after reset must not be a access to FORMAC or PLC */
+
+ /*
+ * bus timeout (MCA)
+ */
+ OUT_82c54_TIMER(3,COUNT(2) | RW_OP(3) | TMODE(3)) ;
+ /* counter 2, mode 3 */
+ OUT_82c54_TIMER(2,(2*24)) ; /* 3.9 us * 2 square wave */
+ OUT_82c54_TIMER(2,0) ; /* MSB */
+
+ /* POS 102 indicated an activ Check Line or Buss Error monitoring */
+ if (inpw(CSA_A) & (POS_EN_CHKINT | POS_EN_BUS_ERR)) {
+ outp(ADDR(IRQ_CHCK_EN),0) ;
+ }
+
+ if (!((i = inpw(CSR_A)) & CS_SAS)) {
+ if (!(i & CS_BYSTAT)) {
+ outp(ADDR(BYPASS(STAT_INS)),0) ;/* insert station */
+ }
+ }
+ outpw(LEDR_A,LED_1) ; /* yellow */
+#endif /* MCA */
+#ifdef PCI
+ /*
+ * make sure no transfer activity is pending
+ */
+ outpw(FM_A(FM_MDREG1),FM_MINIT) ;
+ outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
+ hwt_wait_time(smc,hwt_quick_read(smc),MS2BCLK(10)) ;
+ /*
+ * now reset everything
+ */
+ outp(ADDR(B0_CTRL),CTRL_RST_SET) ; /* reset for all chips */
+ i = (int) inp(ADDR(B0_CTRL)) ; /* do dummy read */
+ SK_UNUSED(i) ; /* Make LINT happy. */
+ outp(ADDR(B0_CTRL), CTRL_RST_CLR) ;
+
+ /*
+ * Reset all bits in the PCI STATUS register
+ */
+ outp(ADDR(B0_TST_CTRL), TST_CFG_WRITE_ON) ; /* enable for writes */
+ word = inpw(PCI_C(PCI_STATUS)) ;
+ outpw(PCI_C(PCI_STATUS), word | PCI_ERRBITS) ;
+ outp(ADDR(B0_TST_CTRL), TST_CFG_WRITE_OFF) ; /* disable writes */
+
+ /*
+ * Release the reset of all the State machines
+ * Release Master_Reset
+ * Release HPI_SM_Reset
+ */
+ outp(ADDR(B0_CTRL), CTRL_MRST_CLR|CTRL_HPI_CLR) ;
+
+ /*
+ * determine the adapter type
+ * Note: Do it here, because some drivers may call card_start() once
+ * at very first before any other initialization functions is
+ * executed.
+ */
+ rev_id = inp(PCI_C(PCI_REV_ID)) ;
+ if ((rev_id & 0xf0) == SK_ML_ID_1 || (rev_id & 0xf0) == SK_ML_ID_2) {
+ smc->hw.hw_is_64bit = TRUE ;
+ } else {
+ smc->hw.hw_is_64bit = FALSE ;
+ }
+
+ /*
+ * Watermark initialization
+ */
+ if (!smc->hw.hw_is_64bit) {
+ outpd(ADDR(B4_R1_F), RX_WATERMARK) ;
+ outpd(ADDR(B5_XA_F), TX_WATERMARK) ;
+ outpd(ADDR(B5_XS_F), TX_WATERMARK) ;
+ }
+
+ outp(ADDR(B0_CTRL),CTRL_RST_CLR) ; /* clear the reset chips */
+ outp(ADDR(B0_LED),LED_GA_OFF|LED_MY_ON|LED_GB_OFF) ; /* ye LED on */
+
+ /* init the timer value for the watch dog 2,5 minutes */
+ outpd(ADDR(B2_WDOG_INI),0x6FC23AC0) ;
+
+ /* initialize the ISR mask */
+ smc->hw.is_imask = ISR_MASK ;
+ smc->hw.hw_state = STOPPED ;
+#endif
+ GET_PAGE(0) ; /* necessary for BOOT */
+}
+
+void card_stop(smc)
+struct s_smc *smc ;
+{
+ smt_stop_watchdog(smc) ;
+ smc->hw.mac_ring_is_up = 0 ; /* ring down */
+#ifdef ISA
+ outpw(CSR_A,0) ; /* reset for all chips */
+#endif
+#ifdef EISA
+ outpw(CSR_A,0) ; /* reset for all chips */
+#endif
+#ifdef MCA
+ outp(ADDR(CARD_DIS),0) ; /* reset for all chips */
+#endif
+#ifdef PCI
+ /*
+ * make sure no transfer activity is pending
+ */
+ outpw(FM_A(FM_MDREG1),FM_MINIT) ;
+ outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
+ hwt_wait_time(smc,hwt_quick_read(smc),MS2BCLK(10)) ;
+ /*
+ * now reset everything
+ */
+ outp(ADDR(B0_CTRL),CTRL_RST_SET) ; /* reset for all chips */
+ outp(ADDR(B0_CTRL),CTRL_RST_CLR) ; /* reset for all chips */
+ outp(ADDR(B0_LED),LED_GA_OFF|LED_MY_OFF|LED_GB_OFF) ; /* all LEDs off */
+ smc->hw.hw_state = STOPPED ;
+#endif
+}
+/*--------------------------- ISR handling ----------------------------------*/
+
+#ifndef PCI
+void mac1_irq(smc,stu, stl)
+struct s_smc *smc ;
+u_short stu;
+u_short stl;
+{
+ int restart_tx = 0 ;
+again:
+#ifndef ISA
+/*
+ * FORMAC+ bug modified the queue pointer if many read/write accesses happens!?
+ */
+ if (stl & (FM_SPCEPDS | /* parit/coding err. syn.q.*/
+ FM_SPCEPDA0 | /* parit/coding err. a.q.0 */
+ FM_SPCEPDA1 | /* parit/coding err. a.q.1 */
+ FM_SPCEPDA2)) { /* parit/coding err. a.q.2 */
+ SMT_PANIC(smc,SMT_E0132, SMT_E0132_MSG) ;
+ }
+ if (stl & (FM_STBURS | /* tx buffer underrun syn.q.*/
+ FM_STBURA0 | /* tx buffer underrun a.q.0 */
+ FM_STBURA1 | /* tx buffer underrun a.q.1 */
+ FM_STBURA2)) { /* tx buffer underrun a.q.2 */
+ SMT_PANIC(smc,SMT_E0133, SMT_E0133_MSG) ;
+ }
+#endif
+ if ( (stu & (FM_SXMTABT | /* transmit abort */
+#ifdef SYNC
+ FM_STXABRS | /* syn. tx abort */
+#endif /* SYNC */
+ FM_STXABRA0)) || /* asyn. tx abort */
+ (stl & (FM_SQLCKS | /* lock for syn. q. */
+ FM_SQLCKA0)) ) { /* lock for asyn. q. */
+ formac_tx_restart(smc) ; /* init tx */
+ restart_tx = 1 ;
+ stu = inpw(FM_A(FM_ST1U)) ;
+ stl = inpw(FM_A(FM_ST1L)) ;
+ stu &= ~ (FM_STECFRMA0 | FM_STEFRMA0 | FM_STEFRMS) ;
+ if (stu || stl)
+ goto again ;
+ }
+
+#ifndef SYNC
+ if (stu & (FM_STECFRMA0 | /* end of chain asyn tx */
+ FM_STEFRMA0)) { /* end of frame asyn tx */
+ /* free tx_queue */
+ smc->hw.n_a_send = 0 ;
+ if (++smc->hw.fp.tx_free < smc->hw.fp.tx_max) {
+ start_next_send(smc);
+ }
+ restart_tx = 1 ;
+ }
+#else /* SYNC */
+ if (stu & (FM_STEFRMA0 | /* end of asyn tx */
+ FM_STEFRMS)) { /* end of sync tx */
+ restart_tx = 1 ;
+ }
+#endif /* SYNC */
+ if (restart_tx)
+ llc_restart_tx(smc) ;
+}
+#else /* PCI */
+
+void mac1_irq(smc,stu, stl)
+struct s_smc *smc ;
+u_short stu;
+u_short stl;
+{
+ int restart_tx = 0 ;
+again:
+
+ /*
+ * parity error: note encoding error is not possible in tag mode
+ */
+ if (stl & (FM_SPCEPDS | /* parity err. syn.q.*/
+ FM_SPCEPDA0 | /* parity err. a.q.0 */
+ FM_SPCEPDA1)) { /* parity err. a.q.1 */
+ SMT_PANIC(smc,SMT_E0134, SMT_E0134_MSG) ;
+ }
+ /*
+ * buffer underrun: can only occur if a tx threshold is specified
+ */
+ if (stl & (FM_STBURS | /* tx buffer underrun syn.q.*/
+ FM_STBURA0 | /* tx buffer underrun a.q.0 */
+ FM_STBURA1)) { /* tx buffer underrun a.q.2 */
+ SMT_PANIC(smc,SMT_E0133, SMT_E0133_MSG) ;
+ }
+
+ if ( (stu & (FM_SXMTABT | /* transmit abort */
+ FM_STXABRS | /* syn. tx abort */
+ FM_STXABRA0)) || /* asyn. tx abort */
+ (stl & (FM_SQLCKS | /* lock for syn. q. */
+ FM_SQLCKA0)) ) { /* lock for asyn. q. */
+ formac_tx_restart(smc) ; /* init tx */
+ restart_tx = 1 ;
+ stu = inpw(FM_A(FM_ST1U)) ;
+ stl = inpw(FM_A(FM_ST1L)) ;
+ stu &= ~ (FM_STECFRMA0 | FM_STEFRMA0 | FM_STEFRMS) ;
+ if (stu || stl)
+ goto again ;
+ }
+
+ if (stu & (FM_STEFRMA0 | /* end of asyn tx */
+ FM_STEFRMS)) { /* end of sync tx */
+ restart_tx = 1 ;
+ }
+
+ if (restart_tx)
+ llc_restart_tx(smc) ;
+}
+#endif /* PCI */
+/*
+ * interrupt source= plc1
+ * this function is called in nwfbisr.asm
+ */
+void plc1_irq(smc)
+struct s_smc *smc ;
+{
+ u_short st = inpw(PLC(PB,PL_INTR_EVENT)) ;
+
+#if (defined(ISA) || defined(EISA))
+ /* reset PLC Int. bits */
+ outpw(PLC1_I,inpw(PLC1_I)) ;
+#endif
+ plc_irq(smc,PB,st) ;
+}
+
+/*
+ * interrupt source= plc2
+ * this function is called in nwfbisr.asm
+ */
+void plc2_irq(smc)
+struct s_smc *smc ;
+{
+ u_short st = inpw(PLC(PA,PL_INTR_EVENT)) ;
+
+#if (defined(ISA) || defined(EISA))
+ /* reset PLC Int. bits */
+ outpw(PLC2_I,inpw(PLC2_I)) ;
+#endif
+ plc_irq(smc,PA,st) ;
+}
+
+
+/*
+ * interrupt source= timer
+ */
+void timer_irq(smc)
+struct s_smc *smc ;
+{
+ hwt_restart(smc);
+ smc->hw.t_stop = smc->hw.t_start;
+ smt_timer_done(smc) ;
+}
+
+/*
+ * return S-port (PA or PB)
+ */
+int pcm_get_s_port(smc)
+struct s_smc *smc ;
+{
+ SK_UNUSED(smc) ;
+ return(PS) ;
+}
+
+/*
+ * Station Label = "FDDI-XYZ" where
+ *
+ * X = connector type
+ * Y = PMD type
+ * Z = port type
+ */
+#define STATION_LABEL_CONNECTOR_OFFSET 5
+#define STATION_LABEL_PMD_OFFSET 6
+#define STATION_LABEL_PORT_OFFSET 7
+
+void read_address(smc,mac_addr)
+struct s_smc *smc ;
+u_char *mac_addr ;
+{
+ char ConnectorType ;
+ char PmdType ;
+ int i ;
+
+ extern const u_char canonical[256] ;
+
+#if (defined(ISA) || defined(MCA))
+ for (i = 0; i < 4 ;i++) { /* read mac address from board */
+ smc->hw.fddi_phys_addr.a[i] =
+ canonical[(inpw(PR_A(i+SA_MAC))&0xff)] ;
+ }
+ for (i = 4; i < 6; i++) {
+ smc->hw.fddi_phys_addr.a[i] =
+ canonical[(inpw(PR_A(i+SA_MAC+PRA_OFF))&0xff)] ;
+ }
+#endif
+#ifdef EISA
+ /*
+ * Note: We get trouble on an Alpha machine if we make a inpw()
+ * instead of inp()
+ */
+ for (i = 0; i < 4 ;i++) { /* read mac address from board */
+ smc->hw.fddi_phys_addr.a[i] =
+ canonical[inp(PR_A(i+SA_MAC))] ;
+ }
+ for (i = 4; i < 6; i++) {
+ smc->hw.fddi_phys_addr.a[i] =
+ canonical[inp(PR_A(i+SA_MAC+PRA_OFF))] ;
+ }
+#endif
+#ifdef PCI
+ for (i = 0; i < 6; i++) { /* read mac address from board */
+ smc->hw.fddi_phys_addr.a[i] =
+ canonical[inp(ADDR(B2_MAC_0+i))] ;
+ }
+#endif
+#ifndef PCI
+ ConnectorType = inpw(PR_A(SA_PMD_TYPE)) & 0xff ;
+ PmdType = inpw(PR_A(SA_PMD_TYPE+1)) & 0xff ;
+#else
+ ConnectorType = inp(ADDR(B2_CONN_TYP)) ;
+ PmdType = inp(ADDR(B2_PMD_TYP)) ;
+#endif
+
+ smc->y[PA].pmd_type[PMD_SK_CONN] =
+ smc->y[PB].pmd_type[PMD_SK_CONN] = ConnectorType ;
+ smc->y[PA].pmd_type[PMD_SK_PMD ] =
+ smc->y[PB].pmd_type[PMD_SK_PMD ] = PmdType ;
+
+ if (mac_addr) {
+ for (i = 0; i < 6 ;i++) {
+ smc->hw.fddi_canon_addr.a[i] = mac_addr[i] ;
+ smc->hw.fddi_home_addr.a[i] = canonical[mac_addr[i]] ;
+ }
+ return ;
+ }
+ smc->hw.fddi_home_addr = smc->hw.fddi_phys_addr ;
+
+ for (i = 0; i < 6 ;i++) {
+ smc->hw.fddi_canon_addr.a[i] =
+ canonical[smc->hw.fddi_phys_addr.a[i]] ;
+ }
+}
+
+/*
+ * FDDI card soft reset
+ */
+void init_board(smc,mac_addr)
+struct s_smc *smc ;
+u_char *mac_addr ;
+{
+ card_start(smc) ;
+ read_address(smc,mac_addr) ;
+
+#ifndef PCI
+ if (inpw(CSR_A) & CS_SAS)
+#else
+ if (!(inp(ADDR(B0_DAS)) & DAS_AVAIL))
+#endif
+ smc->s.sas = SMT_SAS ; /* Single att. station */
+ else
+ smc->s.sas = SMT_DAS ; /* Dual att. station */
+
+#ifndef PCI
+ if (inpw(CSR_A) & CS_BYSTAT)
+#else
+ if (!(inp(ADDR(B0_DAS)) & DAS_BYP_ST))
+#endif
+ smc->mib.fddiSMTBypassPresent = 0 ;
+ /* without opt. bypass */
+ else
+ smc->mib.fddiSMTBypassPresent = 1 ;
+ /* with opt. bypass */
+}
+
+/*
+ * insert or deinsert optical bypass (called by ECM)
+ */
+void sm_pm_bypass_req(smc,mode)
+struct s_smc *smc ;
+int mode;
+{
+#if (defined(ISA) || defined(EISA))
+ int csra_v ;
+#endif
+
+ DB_ECMN(1,"ECM : sm_pm_bypass_req(%s)\n",(mode == BP_INSERT) ?
+ "BP_INSERT" : "BP_DEINSERT",0) ;
+
+ if (smc->s.sas != SMT_DAS)
+ return ;
+
+#if (defined(ISA) || defined(EISA))
+
+ csra_v = inpw(CSR_A) & ~CS_BYPASS ;
+#ifdef EISA
+ csra_v |= smc->hw.led ;
+#endif
+
+ switch(mode) {
+ case BP_INSERT :
+ outpw(CSR_A,csra_v | CS_BYPASS) ;
+ break ;
+ case BP_DEINSERT :
+ outpw(CSR_A,csra_v) ;
+ break ;
+ }
+#endif /* ISA / EISA */
+#ifdef MCA
+ switch(mode) {
+ case BP_INSERT :
+ outp(ADDR(BYPASS(STAT_INS)),0) ;/* insert station */
+ break ;
+ case BP_DEINSERT :
+ outp(ADDR(BYPASS(STAT_BYP)),0) ; /* bypass station */
+ break ;
+ }
+#endif
+#ifdef PCI
+ switch(mode) {
+ case BP_INSERT :
+ outp(ADDR(B0_DAS),DAS_BYP_INS) ; /* insert station */
+ break ;
+ case BP_DEINSERT :
+ outp(ADDR(B0_DAS),DAS_BYP_RMV) ; /* bypass station */
+ break ;
+ }
+#endif
+}
+
+/*
+ * check if bypass connected
+ */
+int sm_pm_bypass_present(smc)
+struct s_smc *smc ;
+{
+#ifndef PCI
+ return( (inpw(CSR_A) & CS_BYSTAT) ? FALSE : TRUE ) ;
+#else
+ return( (inp(ADDR(B0_DAS)) & DAS_BYP_ST) ? TRUE: FALSE) ;
+#endif
+}
+
+void plc_clear_irq(smc,p)
+struct s_smc *smc ;
+int p ;
+{
+ SK_UNUSED(p) ;
+
+#if (defined(ISA) || defined(EISA))
+ switch (p) {
+ case PA :
+ /* reset PLC Int. bits */
+ outpw(PLC2_I,inpw(PLC2_I)) ;
+ break ;
+ case PB :
+ /* reset PLC Int. bits */
+ outpw(PLC1_I,inpw(PLC1_I)) ;
+ break ;
+ }
+#else
+ SK_UNUSED(smc) ;
+#endif
+}
+
+
+/*
+ * led_indication called by rmt_indication() and
+ * pcm_state_change()
+ *
+ * Input:
+ * smc: SMT context
+ * led_event:
+ * 0 Only switch green LEDs according to their respective PCM state
+ * LED_Y_OFF just switch yellow LED off
+ * LED_Y_ON just switch yello LED on
+ */
+void led_indication(smc,led_event)
+struct s_smc *smc ;
+int led_event;
+{
+ /* use smc->hw.mac_ring_is_up == TRUE
+ * as indication for Ring Operational
+ */
+ u_short led_state ;
+ struct s_phy *phy ;
+ struct fddi_mib_p *mib_a ;
+ struct fddi_mib_p *mib_b ;
+
+ phy = &smc->y[PA] ;
+ mib_a = phy->mib ;
+ phy = &smc->y[PB] ;
+ mib_b = phy->mib ;
+
+#ifdef EISA
+ /* Ring up = yellow led OFF*/
+ if (led_event == LED_Y_ON) {
+ smc->hw.led |= CS_LED_1 ;
+ }
+ else if (led_event == LED_Y_OFF) {
+ smc->hw.led &= ~CS_LED_1 ;
+ }
+ else {
+ /* Link at Port A or B = green led ON */
+ if (mib_a->fddiPORTPCMState == PC8_ACTIVE ||
+ mib_b->fddiPORTPCMState == PC8_ACTIVE) {
+ smc->hw.led |= CS_LED_0 ;
+ }
+ else {
+ smc->hw.led &= ~CS_LED_0 ;
+ }
+ }
+#endif
+#ifdef MCA
+ led_state = inpw(LEDR_A) ;
+
+ /* Ring up = yellow led OFF*/
+ if (led_event == LED_Y_ON) {
+ led_state |= LED_1 ;
+ }
+ else if (led_event == LED_Y_OFF) {
+ led_state &= ~LED_1 ;
+ }
+ else {
+ led_state &= ~(LED_2|LED_0) ;
+
+ /* Link at Port A = green led A ON */
+ if (mib_a->fddiPORTPCMState == PC8_ACTIVE) {
+ led_state |= LED_2 ;
+ }
+
+ /* Link at Port B/S = green led B ON */
+ if (mib_b->fddiPORTPCMState == PC8_ACTIVE) {
+ led_state |= LED_0 ;
+ }
+ }
+
+ outpw(LEDR_A, led_state) ;
+#endif /* MCA */
+#ifdef PCI
+ led_state = 0 ;
+
+ /* Ring up = yellow led OFF*/
+ if (led_event == LED_Y_ON) {
+ led_state |= LED_MY_ON ;
+ }
+ else if (led_event == LED_Y_OFF) {
+ led_state |= LED_MY_OFF ;
+ }
+ else { /* PCM state changed */
+ /* Link at Port A/S = green led A ON */
+ if (mib_a->fddiPORTPCMState == PC8_ACTIVE) {
+ led_state |= LED_GA_ON ;
+ }
+ else {
+ led_state |= LED_GA_OFF ;
+ }
+
+ /* Link at Port B = green led B ON */
+ if (mib_b->fddiPORTPCMState == PC8_ACTIVE) {
+ led_state |= LED_GB_ON ;
+ }
+ else {
+ led_state |= LED_GB_OFF ;
+ }
+ }
+
+ outp(ADDR(B0_LED), led_state) ;
+#endif /* PCI */
+
+}
+
+
+void pcm_state_change(smc,plc,p_state)
+struct s_smc *smc;
+int plc;
+int p_state;
+{
+ /*
+ * the current implementation of pcm_state_change() in the driver
+ * parts must be renamed to drv_pcm_state_change() which will be called
+ * now after led_indication.
+ */
+ DRV_PCM_STATE_CHANGE(smc,plc,p_state) ;
+
+ led_indication(smc,0) ;
+}
+
+
+void rmt_indication(smc,i)
+struct s_smc *smc ;
+int i;
+{
+ /* Call a driver special function if defined */
+ DRV_RMT_INDICATION(smc,i) ;
+
+ led_indication(smc, i ? LED_Y_OFF : LED_Y_ON) ;
+}
+
+
+/*
+ * llc_recover_tx called by init_tx (fplus.c)
+ */
+void llc_recover_tx(smc)
+struct s_smc *smc ;
+{
+#ifdef LOAD_GEN
+ extern int load_gen_flag ;
+
+ load_gen_flag = 0 ;
+#endif
+#ifndef SYNC
+ smc->hw.n_a_send= 0 ;
+#else
+ SK_UNUSED(smc) ;
+#endif
+}
+
+/*--------------------------- DMA init ----------------------------*/
+#ifdef ISA
+
+/*
+ * init DMA
+ */
+void init_dma(smc,dma)
+struct s_smc *smc;
+int dma;
+{
+ SK_UNUSED(smc) ;
+
+ /*
+ * set cascade mode,
+ * clear mask bit (enable DMA cannal)
+ */
+ if (dma > 3) {
+ outp(0xd6,(dma & 0x03) | 0xc0) ;
+ outp(0xd4, dma & 0x03) ;
+ }
+ else {
+ outp(0x0b,(dma & 0x03) | 0xc0) ;
+ outp(0x0a,dma & 0x03) ;
+ }
+}
+
+/*
+ * disable DMA
+ */
+void dis_dma(smc,dma)
+struct s_smc *smc ;
+int dma;
+{
+ SK_UNUSED(smc) ;
+
+ /*
+ * set mask bit (disable DMA cannal)
+ */
+ if (dma > 3) {
+ outp(0xd4,(dma & 0x03) | 0x04) ;
+ }
+ else {
+ outp(0x0a,(dma & 0x03) | 0x04) ;
+ }
+}
+
+#endif /* ISA */
+
+#ifdef EISA
+
+/*arrays with io adresses of dma controller length and adress registers*/
+static const int cntr[8] = { 0x001,0x003,0x005,0x007,0,0x0c6,0x0ca,0x0ce } ;
+static const int base[8] = { 0x000,0x002,0x004,0x006,0,0x0c4,0x0c8,0x0cc } ;
+static const int page[8] = { 0x087,0x083,0x081,0x082,0,0x08b,0x089,0x08a } ;
+
+void init_dma(smc,dma)
+struct s_smc *smc ;
+int dma;
+{
+ /*
+ * extended mode register
+ * 32 bit IO
+ * type c
+ * TC output
+ * disable stop
+ */
+
+ /* mode read (write) demand */
+ smc->hw.dma_rmode = (dma & 3) | 0x08 | 0x0 ;
+ smc->hw.dma_wmode = (dma & 3) | 0x04 | 0x0 ;
+
+ /* 32 bit IO's, burst DMA mode (type "C") */
+ smc->hw.dma_emode = (dma & 3) | 0x08 | 0x30 ;
+
+ outp((dma < 4) ? 0x40b : 0x4d6,smc->hw.dma_emode) ;
+
+ /* disable chaining */
+ outp((dma < 4) ? 0x40a : 0x4d4,(dma&3)) ;
+
+ /*load dma controller addresses for fast access during set dma*/
+ smc->hw.dma_base_word_count = cntr[smc->hw.dma];
+ smc->hw.dma_base_address = base[smc->hw.dma];
+ smc->hw.dma_base_address_page = page[smc->hw.dma];
+
+}
+
+void dis_dma(smc,dma)
+struct s_smc *smc ;
+int dma;
+{
+ SK_UNUSED(smc) ;
+
+ outp((dma < 4) ? 0x0a : 0xd4,(dma&3)|4) ;/* mask bit */
+}
+#endif /* EISA */
+
+#ifdef MCA
+void init_dma(smc,dma)
+struct s_smc *smc;
+int dma;
+{
+ SK_UNUSED(smc) ;
+ SK_UNUSED(dma) ;
+}
+void dis_dma(smc,dma)
+struct s_smc *smc;
+int dma;
+{
+ SK_UNUSED(smc) ;
+ SK_UNUSED(dma) ;
+}
+#endif
+
+#ifdef PCI
+void init_dma(smc,dma)
+struct s_smc *smc;
+int dma;
+{
+ SK_UNUSED(smc) ;
+ SK_UNUSED(dma) ;
+}
+void dis_dma(smc,dma)
+struct s_smc *smc;
+int dma;
+{
+ SK_UNUSED(smc) ;
+ SK_UNUSED(dma) ;
+}
+#endif
+
+#ifdef MULT_OEM
+static int is_equal_num(comp1,comp2,num)
+char comp1[] ;
+char comp2[] ;
+int num ;
+{
+ int i ;
+
+ for (i = 0 ; i < num ; i++) {
+ if (comp1[i] != comp2[i])
+ return (0) ;
+ }
+ return (1) ;
+} /* is_equal_num */
+
+
+/*
+ * set the OEM ID defaults, and test the contents of the OEM data base
+ * The default OEM is the first ACTIVE entry in the OEM data base
+ *
+ * returns: 0 success
+ * 1 error in data base
+ * 2 data base empty
+ * 3 no active entry
+ */
+int set_oi_id_def(smc)
+struct s_smc *smc ;
+{
+ int sel_id ;
+ int i ;
+ int act_entries ;
+
+ i = 0 ;
+ sel_id = -1 ;
+ act_entries = FALSE ;
+ smc->hw.oem_id = 0 ;
+ smc->hw.oem_min_status = OI_STAT_ACTIVE ;
+
+ /* check OEM data base */
+ while (oem_ids[i].oi_status) {
+ switch (oem_ids[i].oi_status) {
+ case OI_STAT_ACTIVE:
+ act_entries = TRUE ; /* we have active IDs */
+ if (sel_id == -1)
+ sel_id = i ; /* save the first active ID */
+ case OI_STAT_VALID:
+ case OI_STAT_PRESENT:
+ i++ ;
+ break ; /* entry ok */
+ default:
+ return (1) ; /* invalid oi_status */
+ }
+ }
+
+ if (i == 0)
+ return (2) ;
+ if (!act_entries)
+ return (3) ;
+
+ /* ok, we have a valid OEM data base with an active entry */
+ smc->hw.oem_id = (struct s_oem_ids *) &oem_ids[sel_id] ;
+ return (0) ;
+}
+#endif /* MULT_OEM */
+
+
+#ifdef MCA
+/************************
+ *
+ * BEGIN_MANUAL_ENTRY()
+ *
+ * exist_board
+ *
+ * Check if an MCA board is present in the specified slot.
+ *
+ * int exist_board(
+ * struct s_smc *smc,
+ * int slot) ;
+ * In
+ * smc - A pointer to the SMT Context struct.
+ *
+ * slot - The number of the slot to inspect.
+ * Out
+ * 0 = No adapter present.
+ * 1 = Found FM1 adapter.
+ *
+ * Pseudo
+ * Read MCA ID
+ * for all valid OEM_IDs
+ * compare with ID read
+ * if equal, return 1
+ * return(0
+ *
+ * Note
+ * The smc pointer must be valid now.
+ *
+ * END_MANUAL_ENTRY()
+ *
+ ************************/
+#define LONG_CARD_ID(lo, hi) ((((hi) & 0xff) << 8) | ((lo) & 0xff))
+int exist_board(smc,slot)
+struct s_smc *smc ;
+int slot ;
+{
+#ifdef MULT_OEM
+ SK_LOC_DECL(u_char,id[2]) ;
+ int idi ;
+#endif /* MULT_OEM */
+
+ /* No longer valid. */
+ if (smc == NULL)
+ return(0) ;
+
+#ifndef MULT_OEM
+ if (read_card_id(smc, slot)
+ == LONG_CARD_ID(OEMID(smc,0), OEMID(smc,1)))
+ return (1) ; /* Found FM adapter. */
+
+#else /* MULT_OEM */
+ idi = read_card_id(smc, slot) ;
+ id[0] = idi & 0xff ;
+ id[1] = idi >> 8 ;
+
+ smc->hw.oem_id = (struct s_oem_ids *) &oem_ids[0] ;
+ for (; smc->hw.oem_id->oi_status != OI_STAT_LAST; smc->hw.oem_id++) {
+ if (smc->hw.oem_id->oi_status < smc->hw.oem_min_status)
+ continue ;
+
+ if (is_equal_num(&id[0],&OEMID(smc,0),2))
+ return (1) ;
+ }
+#endif /* MULT_OEM */
+ return (0) ; /* No adapter found. */
+}
+
+/************************
+ *
+ * read_card_id
+ *
+ * Read the MCA card id from the specified slot.
+ * In
+ * smc - A pointer to the SMT Context struct.
+ * CAVEAT: This pointer may be NULL and *must not* be used within this
+ * function. It's only purpose is for drivers that need some information
+ * for the inp() and outp() macros.
+ *
+ * slot - The number of the slot for which the card id is returned.
+ * Out
+ * Returns the card id read from the specified slot. If an illegal slot
+ * number is specified, the function returns zero.
+ *
+ ************************/
+static int read_card_id(smc,slot)
+struct s_smc *smc ; /* Do not use. */
+int slot ;
+{
+ int card_id ;
+
+ SK_UNUSED(smc) ; /* Make LINT happy. */
+ if ((slot < 1) || (slot > 15)) /* max 16 slots, 0 = motherboard */
+ return (0) ; /* Illegal slot number specified. */
+
+ EnableSlotAccess(smc, slot) ;
+
+ card_id = ((read_POS(smc,POS_ID_HIGH,slot - 1) & 0xff) << 8) |
+ (read_POS(smc,POS_ID_LOW,slot - 1) & 0xff) ;
+
+ DisableSlotAccess(smc) ;
+
+ return (card_id) ;
+}
+
+/************************
+ *
+ * BEGIN_MANUAL_ENTRY()
+ *
+ * get_board_para
+ *
+ * Get adapter configuration information. Fill all board specific
+ * parameters within the 'smc' structure.
+ *
+ * int get_board_para(
+ * struct s_smc *smc,
+ * int slot) ;
+ * In
+ * smc - A pointer to the SMT Context struct, to which this function will
+ * write some adapter configuration data.
+ *
+ * slot - The number of the slot, in which the adapter is installed.
+ * Out
+ * 0 = No adapter present.
+ * 1 = Ok.
+ * 2 = Adapter present, but card enable bit not set.
+ *
+ * END_MANUAL_ENTRY()
+ *
+ ************************/
+int get_board_para(smc,slot)
+struct s_smc *smc ;
+int slot ;
+{
+ int val ;
+ int i ;
+
+ /* Check if adapter present & get type of adapter. */
+ switch (exist_board(smc, slot)) {
+ case 0: /* Adapter not present. */
+ return (0) ;
+ case 1: /* FM Rev. 1 */
+ smc->hw.rev = FM1_REV ;
+ smc->hw.VFullRead = 0x0a ;
+ smc->hw.VFullWrite = 0x05 ;
+ smc->hw.DmaWriteExtraBytes = 8 ; /* 2 extra words. */
+ break ;
+ }
+ smc->hw.slot = slot ;
+
+ EnableSlotAccess(smc, slot) ;
+
+ if (!(read_POS(smc,POS_102, slot - 1) & POS_CARD_EN)) {
+ DisableSlotAccess(smc) ;
+ return (2) ; /* Card enable bit not set. */
+ }
+
+ val = read_POS(smc,POS_104, slot - 1) ; /* I/O, IRQ */
+
+#ifndef MEM_MAPPED_IO /* is defined by the operating system */
+ i = val & POS_IOSEL ; /* I/O base addr. (0x0200 .. 0xfe00) */
+ smc->hw.iop = (i + 1) * 0x0400 - 0x200 ;
+#endif
+ i = ((val & POS_IRQSEL) >> 6) & 0x03 ; /* IRQ <0, 1> */
+ smc->hw.irq = opt_ints[i] ;
+
+ /* FPROM base addr. */
+ i = ((read_POS(smc,POS_103, slot - 1) & POS_MSEL) >> 4) & 0x07 ;
+ smc->hw.eprom = opt_eproms[i] ;
+
+ DisableSlotAccess(smc) ;
+
+ /* before this, the smc->hw.iop must be set !!! */
+ smc->hw.slot_32 = inpw(CSF_A) & SLOT_32 ;
+
+ return (1) ;
+}
+
+/* Enable access to specified MCA slot. */
+static void EnableSlotAccess(smc,slot)
+struct s_smc *smc ;
+int slot ;
+{
+ SK_UNUSED(slot) ;
+
+#ifndef AIX
+ SK_UNUSED(smc) ;
+
+ /* System mode. */
+ outp(POS_SYS_SETUP, POS_SYSTEM) ;
+
+ /* Select slot. */
+ outp(POS_CHANNEL_POS, POS_CHANNEL_BIT | (slot-1)) ;
+#else
+ attach_POS_addr (smc) ;
+#endif
+}
+
+/* Disable access to MCA slot formerly enabled via EnableSlotAccess(). */
+static void DisableSlotAccess(smc)
+struct s_smc *smc ;
+{
+#ifndef AIX
+ SK_UNUSED(smc) ;
+
+ outp(POS_CHANNEL_POS, 0) ;
+#else
+ detach_POS_addr (smc) ;
+#endif
+}
+#endif /* MCA */
+
+#ifdef EISA
+#ifndef MEM_MAPPED_IO
+#define SADDR(slot) (((slot)<<12)&0xf000)
+#else /* MEM_MAPPED_IO */
+#define SADDR(slot) (smc->hw.iop)
+#endif /* MEM_MAPPED_IO */
+
+/************************
+ *
+ * BEGIN_MANUAL_ENTRY()
+ *
+ * exist_board
+ *
+ * Check if an EISA board is present in the specified slot.
+ *
+ * int exist_board(
+ * struct s_smc *smc,
+ * int slot) ;
+ * In
+ * smc - A pointer to the SMT Context struct.
+ *
+ * slot - The number of the slot to inspect.
+ * Out
+ * 0 = No adapter present.
+ * 1 = Found adapter.
+ *
+ * Pseudo
+ * Read EISA ID
+ * for all valid OEM_IDs
+ * compare with ID read
+ * if equal, return 1
+ * return(0
+ *
+ * Note
+ * The smc pointer must be valid now.
+ *
+ ************************/
+int exist_board(smc,slot)
+struct s_smc *smc ;
+int slot ;
+{
+ int i ;
+#ifdef MULT_OEM
+ SK_LOC_DECL(u_char,id[4]) ;
+#endif /* MULT_OEM */
+
+ /* No longer valid. */
+ if (smc == NULL)
+ return(0);
+
+ SK_UNUSED(slot) ;
+
+#ifndef MULT_OEM
+ for (i = 0 ; i < 4 ; i++) {
+ if (inp(SADDR(slot)+PRA(i)) != OEMID(smc,i))
+ return(0) ;
+ }
+ return(1) ;
+#else /* MULT_OEM */
+ for (i = 0 ; i < 4 ; i++)
+ id[i] = inp(SADDR(slot)+PRA(i)) ;
+
+ smc->hw.oem_id = (struct s_oem_ids *) &oem_ids[0] ;
+
+ for (; smc->hw.oem_id->oi_status != OI_STAT_LAST; smc->hw.oem_id++) {
+ if (smc->hw.oem_id->oi_status < smc->hw.oem_min_status)
+ continue ;
+
+ if (is_equal_num(&id[0],&OEMID(smc,0),4))
+ return (1) ;
+ }
+ return (0) ; /* No adapter found. */
+#endif /* MULT_OEM */
+}
+
+
+int get_board_para(smc,slot)
+struct s_smc *smc ;
+int slot ;
+{
+ int i ;
+
+ if (!exist_board(smc,slot))
+ return(0) ;
+
+ smc->hw.slot = slot ;
+#ifndef MEM_MAPPED_IO /* if defined by the operating system */
+ smc->hw.iop = SADDR(slot) ;
+#endif
+
+ if (!(inp(C0_A(0))&CFG_CARD_EN)) {
+ return(2) ; /* CFG_CARD_EN bit not set! */
+ }
+
+ smc->hw.irq = opt_ints[(inp(C1_A(0)) & CFG_IRQ_SEL)] ;
+ smc->hw.dma = opt_dmas[((inp(C1_A(0)) & CFG_DRQ_SEL)>>3)] ;
+
+ if ((i = inp(C2_A(0)) & CFG_EPROM_SEL) != 0x0f)
+ smc->hw.eprom = opt_eproms[i] ;
+ else
+ smc->hw.eprom = 0 ;
+
+ smc->hw.DmaWriteExtraBytes = 8 ;
+
+ return(1) ;
+}
+#endif /* EISA */
+
+#ifdef ISA
+#ifndef MULT_OEM
+const u_char sklogo[6] = SKLOGO_STR ;
+#define SIZE_SKLOGO(smc) sizeof(sklogo)
+#define SKLOGO(smc,i) sklogo[i]
+#else /* MULT_OEM */
+#define SIZE_SKLOGO(smc) smc->hw.oem_id->oi_logo_len
+#define SKLOGO(smc,i) smc->hw.oem_id->oi_logo[i]
+#endif /* MULT_OEM */
+
+
+int exist_board(smc,port)
+struct s_smc *smc ;
+HW_PTR port ;
+{
+ int i ;
+#ifdef MULT_OEM
+ int bytes_read ;
+ u_char board_logo[15] ;
+ SK_LOC_DECL(u_char,id[4]) ;
+#endif /* MULT_OEM */
+
+ /* No longer valid. */
+ if (smc == NULL)
+ return(0);
+
+ SK_UNUSED(smc) ;
+#ifndef MULT_OEM
+ for (i = SADDRL ; i < (signed) (SADDRL+SIZE_SKLOGO(smc)) ; i++) {
+ if ((u_char)inpw((PRA(i)+port)) != SKLOGO(smc,i-SADDRL)) {
+ return(0) ;
+ }
+ }
+
+ /* check MAC address (S&K or other) */
+ for (i = 0 ; i < 3 ; i++) {
+ if ((u_char)inpw((PRA(i)+port)) != OEMID(smc,i))
+ return(0) ;
+ }
+ return(1) ;
+#else /* MULT_OEM */
+ smc->hw.oem_id = (struct s_oem_ids *) &oem_ids[0] ;
+ board_logo[0] = (u_char)inpw((PRA(SADDRL)+port)) ;
+ bytes_read = 1 ;
+
+ for (; smc->hw.oem_id->oi_status != OI_STAT_LAST; smc->hw.oem_id++) {
+ if (smc->hw.oem_id->oi_status < smc->hw.oem_min_status)
+ continue ;
+
+ /* Test all read bytes with current OEM_entry */
+ /* for (i=0; (i<bytes_read) && (i < SIZE_SKLOGO(smc)); i++) { */
+ for (i = 0; i < bytes_read; i++) {
+ if (board_logo[i] != SKLOGO(smc,i))
+ break ;
+ }
+
+ /* If mismatch, switch to next OEM entry */
+ if ((board_logo[i] != SKLOGO(smc,i)) && (i < bytes_read))
+ continue ;
+
+ --i ;
+ while (bytes_read < SIZE_SKLOGO(smc)) {
+ // inpw next byte SK_Logo
+ i++ ;
+ board_logo[i] = (u_char)inpw((PRA(SADDRL+i)+port)) ;
+ bytes_read++ ;
+ if (board_logo[i] != SKLOGO(smc,i))
+ break ;
+ }
+
+ for (i = 0 ; i < 3 ; i++)
+ id[i] = (u_char)inpw((PRA(i)+port)) ;
+
+ if ((board_logo[i] == SKLOGO(smc,i))
+ && (bytes_read == SIZE_SKLOGO(smc))) {
+
+ if (is_equal_num(&id[0],&OEMID(smc,0),3))
+ return(1);
+ }
+ } /* for */
+ return(0) ;
+#endif /* MULT_OEM */
+}
+
+int get_board_para(smc,slot)
+struct s_smc *smc ;
+int slot ;
+{
+ SK_UNUSED(smc) ;
+ SK_UNUSED(slot) ;
+ return(0) ; /* for ISA not supported */
+}
+#endif /* ISA */
+
+#ifdef PCI
+#ifdef USE_BIOS_FUN
+int exist_board(smc,slot)
+struct s_smc *smc ;
+int slot ;
+{
+ u_short dev_id ;
+ u_short ven_id ;
+ int found ;
+ int i ;
+
+ found = FALSE ; /* make sure we returned with adatper not found*/
+ /* if an empty oemids.h was included */
+
+#ifdef MULT_OEM
+ smc->hw.oem_id = (struct s_oem_ids *) &oem_ids[0] ;
+ for (; smc->hw.oem_id->oi_status != OI_STAT_LAST; smc->hw.oem_id++) {
+ if (smc->hw.oem_id->oi_status < smc->hw.oem_min_status)
+ continue ;
+#endif
+ ven_id = OEMID(smc,0) + (OEMID(smc,1) << 8) ;
+ dev_id = OEMID(smc,2) + (OEMID(smc,3) << 8) ;
+ for (i = 0; i < slot; i++) {
+ if (pci_find_device(i,&smc->hw.pci_handle,
+ dev_id,ven_id) != 0) {
+
+ found = FALSE ;
+ } else {
+ found = TRUE ;
+ }
+ }
+ if (found) {
+ return(1) ; /* adapter was found */
+ }
+#ifdef MULT_OEM
+ }
+#endif
+ return(0) ; /* adapter was not found */
+}
+#endif /* PCI */
+#endif /* USE_BIOS_FUNC */
+
+void driver_get_bia(smc, bia_addr)
+struct s_smc *smc ;
+struct fddi_addr *bia_addr ;
+{
+ int i ;
+
+ extern const u_char canonical[256] ;
+
+ for (i = 0 ; i < 6 ; i++) {
+ bia_addr->a[i] = canonical[smc->hw.fddi_phys_addr.a[i]] ;
+ }
+}
+
+void smt_start_watchdog(smc)
+struct s_smc *smc ;
+{
+ SK_UNUSED(smc) ; /* Make LINT happy. */
+
+#ifndef DEBUG
+
+#ifdef PCI
+ if (smc->hw.wdog_used) {
+ outpw(ADDR(B2_WDOG_CRTL),TIM_START) ; /* Start timer. */
+ }
+#endif
+
+#endif /* DEBUG */
+}
+
+void smt_stop_watchdog(smc)
+struct s_smc *smc ;
+{
+ SK_UNUSED(smc) ; /* Make LINT happy. */
+#ifndef DEBUG
+
+#ifdef PCI
+ if (smc->hw.wdog_used) {
+ outpw(ADDR(B2_WDOG_CRTL),TIM_STOP) ; /* Stop timer. */
+ }
+#endif
+
+#endif /* DEBUG */
+}
+
+#ifdef PCI
+static char get_rom_byte(smc,addr)
+struct s_smc *smc ;
+u_short addr ;
+{
+ GET_PAGE(addr) ;
+ return (READ_PROM(ADDR(B2_FDP))) ;
+}
+
+/*
+ * ROM image defines
+ */
+#define ROM_SIG_1 0
+#define ROM_SIG_2 1
+#define PCI_DATA_1 0x18
+#define PCI_DATA_2 0x19
+
+/*
+ * PCI data structure defines
+ */
+#define VPD_DATA_1 0x08
+#define VPD_DATA_2 0x09
+#define IMAGE_LEN_1 0x10
+#define IMAGE_LEN_2 0x11
+#define CODE_TYPE 0x14
+#define INDICATOR 0x15
+
+/*
+ * BEGIN_MANUAL_ENTRY(mac_drv_vpd_read)
+ * mac_drv_vpd_read(smc,buf,size,image)
+ *
+ * function DOWNCALL (FDDIWARE)
+ * reads the VPD data of the FPROM and writes it into the
+ * buffer
+ *
+ * para buf points to the buffer for the VPD data
+ * size size of the VPD data buffer
+ * image boot image; code type of the boot image
+ * image = 0 Intel x86, PC-AT compatible
+ * 1 OPENBOOT standard for PCI
+ * 2-FF reserved
+ *
+ * returns len number of VPD data bytes read form the FPROM
+ * <0 number of read bytes
+ * >0 error: data invalid
+ *
+ * END_MANUAL_ENTRY
+ */
+int mac_drv_vpd_read(smc,buf,size,image)
+struct s_smc *smc ;
+char *buf ;
+int size ;
+char image ;
+{
+ u_short ibase ;
+ u_short pci_base ;
+ u_short vpd ;
+ int len ;
+
+ len = 0 ;
+ ibase = 0 ;
+ /*
+ * as long images defined
+ */
+ while (get_rom_byte(smc,ibase+ROM_SIG_1) == 0x55 &&
+ (u_char) get_rom_byte(smc,ibase+ROM_SIG_2) == 0xaa) {
+ /*
+ * get the pointer to the PCI data structure
+ */
+ pci_base = ibase + get_rom_byte(smc,ibase+PCI_DATA_1) +
+ (get_rom_byte(smc,ibase+PCI_DATA_2) << 8) ;
+
+ if (image == get_rom_byte(smc,pci_base+CODE_TYPE)) {
+ /*
+ * we have the right image, read the VPD data
+ */
+ vpd = ibase + get_rom_byte(smc,pci_base+VPD_DATA_1) +
+ (get_rom_byte(smc,pci_base+VPD_DATA_2) << 8) ;
+ if (vpd == ibase) {
+ break ; /* no VPD data */
+ }
+ for (len = 0; len < size; len++,buf++,vpd++) {
+ *buf = get_rom_byte(smc,vpd) ;
+ }
+ break ;
+ }
+ else {
+ /*
+ * try the next image
+ */
+ if (get_rom_byte(smc,pci_base+INDICATOR) & 0x80) {
+ break ; /* this was the last image */
+ }
+ ibase = ibase + get_rom_byte(smc,ibase+IMAGE_LEN_1) +
+ (get_rom_byte(smc,ibase+IMAGE_LEN_2) << 8) ;
+ }
+ }
+
+ return(len) ;
+}
+
+void mac_drv_pci_fix(smc,fix_value)
+struct s_smc *smc ;
+u_long fix_value ;
+{
+ smc->hw.pci_fix_value = fix_value ;
+}
+
+void mac_do_pci_fix(smc)
+struct s_smc *smc ;
+{
+ SK_UNUSED(smc) ;
+}
+#endif /* PCI */
diff --git a/drivers/net/skfp/ecm.c b/drivers/net/skfp/ecm.c
new file mode 100644
index 000000000..411169286
--- /dev/null
+++ b/drivers/net/skfp/ecm.c
@@ -0,0 +1,547 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ SMT ECM
+ Entity Coordination Management
+ Hardware independant state machine
+*/
+
+/*
+ * Hardware independant state machine implemantation
+ * The following external SMT functions are referenced :
+ *
+ * queue_event()
+ * smt_timer_start()
+ * smt_timer_stop()
+ *
+ * The following external HW dependant functions are referenced :
+ * sm_pm_bypass_req()
+ * sm_pm_ls_latch()
+ * sm_pm_get_ls()
+ *
+ * The following HW dependant events are required :
+ * NONE
+ *
+ */
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+
+#define KERNEL
+#include "h/smtstate.h"
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)ecm.c 2.7 99/08/05 (C) SK " ;
+#endif
+
+/*
+ * FSM Macros
+ */
+#define AFLAG 0x10
+#define GO_STATE(x) (smc->mib.fddiSMTECMState = (x)|AFLAG)
+#define ACTIONS_DONE() (smc->mib.fddiSMTECMState &= ~AFLAG)
+#define ACTIONS(x) (x|AFLAG)
+
+#define EC0_OUT 0 /* not inserted */
+#define EC1_IN 1 /* inserted */
+#define EC2_TRACE 2 /* tracing */
+#define EC3_LEAVE 3 /* leaving the ring */
+#define EC4_PATH_TEST 4 /* performing path test */
+#define EC5_INSERT 5 /* bypass being turned on */
+#define EC6_CHECK 6 /* checking bypass */
+#define EC7_DEINSERT 7 /* bypass being turnde off */
+
+#ifdef DEBUG
+/*
+ * symbolic state names
+ */
+static const char * const ecm_states[] = {
+ "EC0_OUT","EC1_IN","EC2_TRACE","EC3_LEAVE","EC4_PATH_TEST",
+ "EC5_INSERT","EC6_CHECK","EC7_DEINSERT"
+} ;
+
+/*
+ * symbolic event names
+ */
+static const char * const ecm_events[] = {
+ "NONE","EC_CONNECT","EC_DISCONNECT","EC_TRACE_PROP","EC_PATH_TEST",
+ "EC_TIMEOUT_TD","EC_TIMEOUT_TMAX",
+ "EC_TIMEOUT_IMAX","EC_TIMEOUT_INMAX","EC_TEST_DONE"
+} ;
+#endif
+
+/*
+ * all Globals are defined in smc.h
+ * struct s_ecm
+ */
+
+/*
+ * function declarations
+ */
+
+static void ecm_fsm() ;
+static void start_ecm_timer() ;
+static void stop_ecm_timer() ;
+static void prop_actions() ;
+
+/*
+ init ECM state machine
+ clear all ECM vars and flags
+*/
+void ecm_init(smc)
+struct s_smc *smc ;
+{
+ smc->e.path_test = PT_PASSED ;
+ smc->e.trace_prop = 0 ;
+ smc->e.sb_flag = 0 ;
+ smc->mib.fddiSMTECMState = ACTIONS(EC0_OUT) ;
+ smc->e.ecm_line_state = FALSE ;
+}
+
+/*
+ ECM state machine
+ called by dispatcher
+
+ do
+ display state change
+ process event
+ until SM is stable
+*/
+void ecm(smc,event)
+struct s_smc *smc ;
+int event ;
+{
+ int state ;
+
+ do {
+ DB_ECM("ECM : state %s%s",
+ (smc->mib.fddiSMTECMState & AFLAG) ? "ACTIONS " : "",
+ ecm_states[smc->mib.fddiSMTECMState & ~AFLAG]) ;
+ DB_ECM(" event %s\n",ecm_events[event],0) ;
+ state = smc->mib.fddiSMTECMState ;
+ ecm_fsm(smc,event) ;
+ event = 0 ;
+ } while (state != smc->mib.fddiSMTECMState) ;
+ ecm_state_change(smc,(int)smc->mib.fddiSMTECMState) ;
+}
+
+/*
+ process ECM event
+*/
+static void ecm_fsm(smc,cmd)
+struct s_smc *smc ;
+int cmd ;
+{
+ int ls_a ; /* current line state PHY A */
+ int ls_b ; /* current line state PHY B */
+ int p ; /* ports */
+
+
+ smc->mib.fddiSMTBypassPresent = sm_pm_bypass_present(smc) ;
+ if (cmd == EC_CONNECT)
+ smc->mib.fddiSMTRemoteDisconnectFlag = FALSE ;
+
+ /* For AIX event notification: */
+ /* Is a disconnect command remotely issued ? */
+ if (cmd == EC_DISCONNECT &&
+ smc->mib.fddiSMTRemoteDisconnectFlag == TRUE)
+ AIX_EVENT (smc, (u_long) CIO_HARD_FAIL, (u_long)
+ FDDI_REMOTE_DISCONNECT, smt_get_event_word(smc),
+ smt_get_error_word(smc) );
+
+ /*jd 05-Aug-1999 Bug #10419 "Port Disconnect fails at Dup MAc Cond."*/
+ if (cmd == EC_CONNECT) {
+ smc->e.DisconnectFlag = FALSE ;
+ }
+ else if (cmd == EC_DISCONNECT) {
+ smc->e.DisconnectFlag = TRUE ;
+ }
+
+ switch(smc->mib.fddiSMTECMState) {
+ case ACTIONS(EC0_OUT) :
+ /*
+ * We do not perform a path test
+ */
+ smc->e.path_test = PT_PASSED ;
+ smc->e.ecm_line_state = FALSE ;
+ stop_ecm_timer(smc) ;
+ ACTIONS_DONE() ;
+ break ;
+ case EC0_OUT:
+ /*EC01*/
+ if (cmd == EC_CONNECT && !smc->mib.fddiSMTBypassPresent
+ && smc->e.path_test==PT_PASSED) {
+ GO_STATE(EC1_IN) ;
+ break ;
+ }
+ /*EC05*/
+ else if (cmd == EC_CONNECT && (smc->e.path_test==PT_PASSED) &&
+ smc->mib.fddiSMTBypassPresent &&
+ (smc->s.sas == SMT_DAS)) {
+ GO_STATE(EC5_INSERT) ;
+ break ;
+ }
+ break;
+ case ACTIONS(EC1_IN) :
+ stop_ecm_timer(smc) ;
+ smc->e.trace_prop = 0 ;
+ sm_ma_control(smc,MA_TREQ) ;
+ for (p = 0 ; p < NUMPHYS ; p++)
+ if (smc->mib.p[p].fddiPORTHardwarePresent)
+ queue_event(smc,EVENT_PCMA+p,PC_START) ;
+ ACTIONS_DONE() ;
+ break ;
+ case EC1_IN:
+ /*EC12*/
+ if (cmd == EC_TRACE_PROP) {
+ prop_actions(smc) ;
+ GO_STATE(EC2_TRACE) ;
+ break ;
+ }
+ /*EC13*/
+ else if (cmd == EC_DISCONNECT) {
+ GO_STATE(EC3_LEAVE) ;
+ break ;
+ }
+ break;
+ case ACTIONS(EC2_TRACE) :
+ start_ecm_timer(smc,MIB2US(smc->mib.fddiSMTTrace_MaxExpiration),
+ EC_TIMEOUT_TMAX) ;
+ ACTIONS_DONE() ;
+ break ;
+ case EC2_TRACE :
+ /*EC22*/
+ if (cmd == EC_TRACE_PROP) {
+ prop_actions(smc) ;
+ GO_STATE(EC2_TRACE) ;
+ break ;
+ }
+ /*EC23a*/
+ else if (cmd == EC_DISCONNECT) {
+ smc->e.path_test = PT_EXITING ;
+ GO_STATE(EC3_LEAVE) ;
+ break ;
+ }
+ /*EC23b*/
+ else if (smc->e.path_test == PT_PENDING) {
+ GO_STATE(EC3_LEAVE) ;
+ break ;
+ }
+ /*EC23c*/
+ else if (cmd == EC_TIMEOUT_TMAX) {
+ /* Trace_Max is expired */
+ /* -> send AIX_EVENT */
+ AIX_EVENT(smc, (u_long) FDDI_RING_STATUS,
+ (u_long) FDDI_SMT_ERROR, (u_long)
+ FDDI_TRACE_MAX, smt_get_error_word(smc));
+ smc->e.path_test = PT_PENDING ;
+ GO_STATE(EC3_LEAVE) ;
+ break ;
+ }
+ break ;
+ case ACTIONS(EC3_LEAVE) :
+ start_ecm_timer(smc,smc->s.ecm_td_min,EC_TIMEOUT_TD) ;
+ for (p = 0 ; p < NUMPHYS ; p++)
+ queue_event(smc,EVENT_PCMA+p,PC_STOP) ;
+ ACTIONS_DONE() ;
+ break ;
+ case EC3_LEAVE:
+ /*EC30*/
+ if (cmd == EC_TIMEOUT_TD && !smc->mib.fddiSMTBypassPresent &&
+ (smc->e.path_test != PT_PENDING)) {
+ GO_STATE(EC0_OUT) ;
+ break ;
+ }
+ /*EC34*/
+ else if (cmd == EC_TIMEOUT_TD &&
+ (smc->e.path_test == PT_PENDING)) {
+ GO_STATE(EC4_PATH_TEST) ;
+ break ;
+ }
+ /*EC31*/
+ else if (cmd == EC_CONNECT && smc->e.path_test == PT_PASSED) {
+ GO_STATE(EC1_IN) ;
+ break ;
+ }
+ /*EC33*/
+ else if (cmd == EC_DISCONNECT &&
+ smc->e.path_test == PT_PENDING) {
+ smc->e.path_test = PT_EXITING ;
+ /*
+ * stay in state - state will be left via timeout
+ */
+ }
+ /*EC37*/
+ else if (cmd == EC_TIMEOUT_TD &&
+ smc->mib.fddiSMTBypassPresent &&
+ smc->e.path_test != PT_PENDING) {
+ GO_STATE(EC7_DEINSERT) ;
+ break ;
+ }
+ break ;
+ case ACTIONS(EC4_PATH_TEST) :
+ stop_ecm_timer(smc) ;
+ smc->e.path_test = PT_TESTING ;
+ start_ecm_timer(smc,smc->s.ecm_test_done,EC_TEST_DONE) ;
+ /* now perform path test ... just a simulation */
+ ACTIONS_DONE() ;
+ break ;
+ case EC4_PATH_TEST :
+ /* path test done delay */
+ if (cmd == EC_TEST_DONE)
+ smc->e.path_test = PT_PASSED ;
+
+ if (smc->e.path_test == PT_FAILED)
+ RS_SET(smc,RS_PATHTEST) ;
+
+ /*EC40a*/
+ if (smc->e.path_test == PT_FAILED &&
+ !smc->mib.fddiSMTBypassPresent) {
+ GO_STATE(EC0_OUT) ;
+ break ;
+ }
+ /*EC40b*/
+ else if (cmd == EC_DISCONNECT &&
+ !smc->mib.fddiSMTBypassPresent) {
+ GO_STATE(EC0_OUT) ;
+ break ;
+ }
+ /*EC41*/
+ else if (smc->e.path_test == PT_PASSED) {
+ GO_STATE(EC1_IN) ;
+ break ;
+ }
+ /*EC47a*/
+ else if (smc->e.path_test == PT_FAILED &&
+ smc->mib.fddiSMTBypassPresent) {
+ GO_STATE(EC7_DEINSERT) ;
+ break ;
+ }
+ /*EC47b*/
+ else if (cmd == EC_DISCONNECT &&
+ smc->mib.fddiSMTBypassPresent) {
+ GO_STATE(EC7_DEINSERT) ;
+ break ;
+ }
+ break ;
+ case ACTIONS(EC5_INSERT) :
+ sm_pm_bypass_req(smc,BP_INSERT);
+ start_ecm_timer(smc,smc->s.ecm_in_max,EC_TIMEOUT_INMAX) ;
+ ACTIONS_DONE() ;
+ break ;
+ case EC5_INSERT :
+ /*EC56*/
+ if (cmd == EC_TIMEOUT_INMAX) {
+ GO_STATE(EC6_CHECK) ;
+ break ;
+ }
+ /*EC57*/
+ else if (cmd == EC_DISCONNECT) {
+ GO_STATE(EC7_DEINSERT) ;
+ break ;
+ }
+ break ;
+ case ACTIONS(EC6_CHECK) :
+ /*
+ * in EC6_CHECK, we *POLL* the line state !
+ * check whether both bypass switches have switched.
+ */
+ start_ecm_timer(smc,smc->s.ecm_check_poll,0) ;
+ smc->e.ecm_line_state = TRUE ; /* flag to pcm: report Q/HLS */
+ (void) sm_pm_ls_latch(smc,PA,1) ; /* enable line state latch */
+ (void) sm_pm_ls_latch(smc,PB,1) ; /* enable line state latch */
+ ACTIONS_DONE() ;
+ break ;
+ case EC6_CHECK :
+ ls_a = sm_pm_get_ls(smc,PA) ;
+ ls_b = sm_pm_get_ls(smc,PB) ;
+
+ /*EC61*/
+ if (((ls_a == PC_QLS) || (ls_a == PC_HLS)) &&
+ ((ls_b == PC_QLS) || (ls_b == PC_HLS)) ) {
+ smc->e.sb_flag = FALSE ;
+ smc->e.ecm_line_state = FALSE ;
+ GO_STATE(EC1_IN) ;
+ break ;
+ }
+ /*EC66*/
+ else if (!smc->e.sb_flag &&
+ (((ls_a == PC_ILS) && (ls_b == PC_QLS)) ||
+ ((ls_a == PC_QLS) && (ls_b == PC_ILS)))){
+ smc->e.sb_flag = TRUE ;
+ DB_ECMN(1,"ECM : EC6_CHECK - stuck bypass\n",0,0) ;
+ AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
+ FDDI_SMT_ERROR, (u_long) FDDI_BYPASS_STUCK,
+ smt_get_error_word(smc));
+ }
+ /*EC67*/
+ else if (cmd == EC_DISCONNECT) {
+ smc->e.ecm_line_state = FALSE ;
+ GO_STATE(EC7_DEINSERT) ;
+ break ;
+ }
+ else {
+ /*
+ * restart poll
+ */
+ start_ecm_timer(smc,smc->s.ecm_check_poll,0) ;
+ }
+ break ;
+ case ACTIONS(EC7_DEINSERT) :
+ sm_pm_bypass_req(smc,BP_DEINSERT);
+ start_ecm_timer(smc,smc->s.ecm_i_max,EC_TIMEOUT_IMAX) ;
+ ACTIONS_DONE() ;
+ break ;
+ case EC7_DEINSERT:
+ /*EC70*/
+ if (cmd == EC_TIMEOUT_IMAX) {
+ GO_STATE(EC0_OUT) ;
+ break ;
+ }
+ /*EC75*/
+ else if (cmd == EC_CONNECT && smc->e.path_test == PT_PASSED) {
+ GO_STATE(EC5_INSERT) ;
+ break ;
+ }
+ break;
+ default:
+ SMT_PANIC(smc,SMT_E0107, SMT_E0107_MSG) ;
+ break;
+ }
+}
+
+#ifndef CONCENTRATOR
+/*
+ * trace propagation actions for SAS & DAS
+ */
+static void prop_actions(smc)
+struct s_smc *smc ;
+{
+ int port_in ;
+ int port_out ;
+
+ RS_SET(smc,RS_EVENT) ;
+ switch (smc->s.sas) {
+ case SMT_SAS :
+ port_in = port_out = pcm_get_s_port(smc) ;
+ break ;
+ case SMT_DAS :
+ port_in = cfm_get_mac_input(smc) ; /* PA or PB */
+ port_out = cfm_get_mac_output(smc) ; /* PA or PB */
+ break ;
+ case SMT_NAC :
+ SMT_PANIC(smc,SMT_E0108, SMT_E0108_MSG) ;
+ return ;
+ }
+
+ DB_ECM("ECM : prop_actions - trace_prop %d\n", smc->e.trace_prop,0) ;
+ DB_ECM("ECM : prop_actions - in %d out %d\n", port_in,port_out) ;
+
+ if (smc->e.trace_prop & ENTITY_BIT(ENTITY_MAC)) {
+ /* trace initiatior */
+ DB_ECM("ECM : initiate TRACE on PHY %c\n",'A'+port_in-PA,0) ;
+ queue_event(smc,EVENT_PCM+port_in,PC_TRACE) ;
+ }
+ else if ((smc->e.trace_prop & ENTITY_BIT(ENTITY_PHY(PA))) &&
+ port_out != PA) {
+ /* trace propagate upstream */
+ DB_ECM("ECM : propagate TRACE on PHY B\n",0,0) ;
+ queue_event(smc,EVENT_PCMB,PC_TRACE) ;
+ }
+ else if ((smc->e.trace_prop & ENTITY_BIT(ENTITY_PHY(PB))) &&
+ port_out != PB) {
+ /* trace propagate upstream */
+ DB_ECM("ECM : propagate TRACE on PHY A\n",0,0) ;
+ queue_event(smc,EVENT_PCMA,PC_TRACE) ;
+ }
+ else {
+ /* signal trace termination */
+ DB_ECM("ECM : TRACE terminated\n",0,0) ;
+ smc->e.path_test = PT_PENDING ;
+ }
+ smc->e.trace_prop = 0 ;
+}
+#else
+/*
+ * trace propagation actions for Concentrator
+ */
+static void prop_actions(smc)
+struct s_smc *smc ;
+{
+ int initiator ;
+ int upstream ;
+ int p ;
+
+ RS_SET(smc,RS_EVENT) ;
+ while (smc->e.trace_prop) {
+ DB_ECM("ECM : prop_actions - trace_prop %d\n",
+ smc->e.trace_prop,0) ;
+
+ if (smc->e.trace_prop & ENTITY_BIT(ENTITY_MAC)) {
+ initiator = ENTITY_MAC ;
+ smc->e.trace_prop &= ~ENTITY_BIT(ENTITY_MAC) ;
+ DB_ECM("ECM: MAC initiates trace\n",0,0) ;
+ }
+ else {
+ for (p = NUMPHYS-1 ; p >= 0 ; p--) {
+ if (smc->e.trace_prop &
+ ENTITY_BIT(ENTITY_PHY(p)))
+ break ;
+ }
+ initiator = ENTITY_PHY(p) ;
+ smc->e.trace_prop &= ~ENTITY_BIT(ENTITY_PHY(p)) ;
+ }
+ upstream = cem_get_upstream(smc,initiator) ;
+
+ if (upstream == ENTITY_MAC) {
+ /* signal trace termination */
+ DB_ECM("ECM : TRACE terminated\n",0,0) ;
+ smc->e.path_test = PT_PENDING ;
+ }
+ else {
+ /* trace propagate upstream */
+ DB_ECM("ECM : propagate TRACE on PHY %d\n",upstream,0) ;
+ queue_event(smc,EVENT_PCM+upstream,PC_TRACE) ;
+ }
+ }
+}
+#endif
+
+
+/*
+ * SMT timer interface
+ * start ECM timer
+ */
+static void start_ecm_timer(smc,value,event)
+struct s_smc *smc ;
+u_long value;
+int event ;
+{
+ smt_timer_start(smc,&smc->e.ecm_timer,value,EV_TOKEN(EVENT_ECM,event));
+}
+
+/*
+ * SMT timer interface
+ * stop ECM timer
+ */
+static void stop_ecm_timer(smc)
+struct s_smc *smc ;
+{
+ if (smc->e.ecm_timer.tm_active)
+ smt_timer_stop(smc,&smc->e.ecm_timer) ;
+}
diff --git a/drivers/net/skfp/ess.c b/drivers/net/skfp/ess.c
new file mode 100644
index 000000000..868237b30
--- /dev/null
+++ b/drivers/net/skfp/ess.c
@@ -0,0 +1,732 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * *******************************************************************
+ * This SBA code implements the Synchronous Bandwidth Allocation
+ * functions described in the "FDDI Synchronous Forum Implementer's
+ * Agreement" dated December 1th, 1993.
+ * *******************************************************************
+ *
+ * PURPOSE: The purpose of this function is to control
+ * synchronous allocations on a single FDDI segment.
+ * Allocations are limited to the primary FDDI ring.
+ * The SBM provides recovery mechanisms to recover
+ * unused bandwidth also resolves T_Neg and
+ * reconfiguration changes. Many of the SBM state
+ * machine inputs are sourced by the underlying
+ * FDDI sub-system supporting the SBA application.
+ *
+ * *******************************************************************
+ */
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/smt_p.h"
+
+
+#ifndef SLIM_SMT
+
+#ifdef ESS
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)ess.c 1.10 96/02/23 (C) SK" ;
+#define LINT_USE(x)
+#else
+#define LINT_USE(x) (x)=(x)
+#endif
+#define MS2BCLK(x) ((x)*12500L)
+
+/*
+ -------------------------------------------------------------
+ LOCAL VARIABLES:
+ -------------------------------------------------------------
+*/
+
+static const u_short plist_raf_alc_res[] = { SMT_P0012, SMT_P320B, SMT_P320F,
+ SMT_P3210, SMT_P0019, SMT_P001A,
+ SMT_P001D, 0 } ;
+
+static const u_short plist_raf_chg_req[] = { SMT_P320B, SMT_P320F, SMT_P3210,
+ SMT_P001A, 0 } ;
+
+static const struct fddi_addr smt_sba_da = {0x80,0x01,0x43,0x00,0x80,0x0C} ;
+static const struct fddi_addr null_addr = {0,0,0,0,0,0} ;
+
+/*
+ -------------------------------------------------------------
+ GLOBAL VARIABLES:
+ -------------------------------------------------------------
+*/
+
+
+/*
+ -------------------------------------------------------------
+ LOCAL FUNCTIONS:
+ -------------------------------------------------------------
+*/
+
+static void ess_send_response(), ess_config_fifo(),
+ ess_send_alc_req(), ess_send_frame() ;
+
+/*
+ -------------------------------------------------------------
+ EXTERNAL FUNCTIONS:
+ -------------------------------------------------------------
+*/
+
+extern void *sm_to_para() ;
+
+extern void smt_send_frame(), smt_free_mbuf(),
+ set_formac_tsync(), formac_reinit_tx() ;
+
+extern int smt_check_para() ;
+
+extern SMbuf *smt_get_mbuf(), *smt_build_frame() ;
+
+extern u_long smt_get_tid() ;
+
+/*
+ -------------------------------------------------------------
+ PUBLIC FUNCTIONS:
+ -------------------------------------------------------------
+*/
+
+ void ess_timer_poll(), ess_para_change() ;
+
+ int ess_raf_received_pack(), process_bw_alloc() ;
+
+
+/*
+ * --------------------------------------------------------------------------
+ * End Station Support (ESS)
+ * --------------------------------------------------------------------------
+ */
+
+/*
+ * evaluate the RAF frame
+ */
+int ess_raf_received_pack(smc,mb,sm,fs)
+struct s_smc *smc ;
+SMbuf *mb ;
+struct smt_header *sm ;
+int fs ;
+{
+ void *p ; /* universal pointer */
+ struct smt_p_0016 *cmd ; /* para: command for the ESS */
+ SMbuf *db ;
+ u_long msg_res_type ; /* recource type */
+ u_long payload, overhead ;
+ int local ;
+ int i ;
+
+ /*
+ * Message Processing Code
+ */
+ local = ((fs & L_INDICATOR) != 0) ;
+
+ /*
+ * get the resource type
+ */
+ if (!(p = (void *) sm_to_para(smc,sm,SMT_P0015))) {
+ DB_ESS("ESS: RAF frame error, parameter type not found\n",0,0) ;
+ return(fs) ;
+ }
+ msg_res_type = ((struct smt_p_0015 *)p)->res_type ;
+
+ /*
+ * get the pointer to the ESS command
+ */
+ if (!(cmd = (struct smt_p_0016 *) sm_to_para(smc,sm,SMT_P0016))) {
+ /*
+ * error in frame: para ESS command was not found
+ */
+ DB_ESS("ESS: RAF frame error, parameter command not found\n",0,0);
+ return(fs) ;
+ }
+
+ DB_ESSN(2,"fc %x ft %x\n",sm->smt_class,sm->smt_type) ;
+ DB_ESSN(2,"ver %x tran %lx\n",sm->smt_version,sm->smt_tid) ;
+ DB_ESSN(2,"stn_id %s\n",addr_to_string(&sm->smt_source),0) ;
+
+ DB_ESSN(2,"infolen %x res %x\n",sm->smt_len, msg_res_type) ;
+ DB_ESSN(2,"sbacmd %x\n",cmd->sba_cmd,0) ;
+
+ /*
+ * evaluate the ESS command
+ */
+ switch (cmd->sba_cmd) {
+
+ /*
+ * Process an ESS Allocation Request
+ */
+ case REQUEST_ALLOCATION :
+ /*
+ * check for an RAF Request (Allocation Request)
+ */
+ if (sm->smt_type == SMT_REQUEST) {
+ /*
+ * process the Allocation request only if the frame is
+ * local and no static allocation is used
+ */
+ if (!local || smc->mib.fddiESSPayload)
+ return(fs) ;
+
+ p = (void *) sm_to_para(smc,sm,SMT_P0019) ;
+ for (i = 0; i < 5; i++) {
+ if (((struct smt_p_0019 *)p)->alloc_addr.a[i]) {
+ return(fs) ;
+ }
+ }
+
+ /*
+ * Note: The Application should send a LAN_LOC_FRAME.
+ * The ESS do not send the Frame to the network!
+ */
+ smc->ess.alloc_trans_id = sm->smt_tid ;
+ DB_ESS("ESS: save Alloc Req Trans ID %lx\n",sm->smt_tid,0);
+ p = (void *) sm_to_para(smc,sm,SMT_P320F) ;
+ ((struct smt_p_320f *)p)->mib_payload =
+ smc->mib.a[PATH0].fddiPATHSbaPayload ;
+ p = (void *) sm_to_para(smc,sm,SMT_P3210) ;
+ ((struct smt_p_3210 *)p)->mib_overhead =
+ smc->mib.a[PATH0].fddiPATHSbaOverhead ;
+ sm->smt_dest = smt_sba_da ;
+
+ if (smc->ess.local_sba_active)
+ return(fs | I_INDICATOR) ;
+
+ if (!(db = smt_get_mbuf(smc)))
+ return(fs) ;
+
+ db->sm_len = mb->sm_len ;
+ db->sm_off = mb->sm_off ;
+ memcpy(((char *)(db->sm_data+db->sm_off)),(char *)sm,
+ (int)db->sm_len) ;
+ dump_smt(smc,
+ (struct smt_header *)(db->sm_data+db->sm_off),
+ "RAF") ;
+ smt_send_frame(smc,db,FC_SMT_INFO,0) ;
+ return(fs) ;
+ }
+
+ /*
+ * The RAF frame is an Allocation Response !
+ * check the parameters
+ */
+ if (smt_check_para(smc,sm,plist_raf_alc_res)) {
+ DB_ESS("ESS: RAF with para problem, ignoring\n",0,0) ;
+ return(fs) ;
+ }
+
+ /*
+ * VERIFY THE FRAME IS WELL BUILT:
+ *
+ * 1. path index = primary ring only
+ * 2. resource type = sync bw only
+ * 3. trans action id = alloc_trans_id
+ * 4. reason code = success
+ *
+ * If any are violated, discard the RAF frame
+ */
+ if ((((struct smt_p_320b *)sm_to_para(smc,sm,SMT_P320B))->path_index
+ != PRIMARY_RING) ||
+ (msg_res_type != SYNC_BW) ||
+ (((struct smt_p_reason *)sm_to_para(smc,sm,SMT_P0012))->rdf_reason
+ != SMT_RDF_SUCCESS) ||
+ (sm->smt_tid != smc->ess.alloc_trans_id)) {
+
+ DB_ESS("ESS: Allocation Responce not accepted\n",0,0) ;
+ return(fs) ;
+ }
+
+ /*
+ * Extract message parameters
+ */
+ p = (void *) sm_to_para(smc,sm,SMT_P320F) ;
+ payload = ((struct smt_p_320f *)p)->mib_payload ;
+ p = (void *) sm_to_para(smc,sm,SMT_P3210) ;
+ overhead = ((struct smt_p_3210 *)p)->mib_overhead ;
+
+ DB_ESSN(2,"payload= %lx overhead= %lx\n",payload,overhead) ;
+
+ /*
+ * process the bandwidth allocation
+ */
+ (void)process_bw_alloc(smc,(long)payload,(long)overhead) ;
+
+ return(fs) ;
+ /* end of Process Allocation Request */
+
+ /*
+ * Process an ESS Change Request
+ */
+ case CHANGE_ALLOCATION :
+ /*
+ * except only replies
+ */
+ if (sm->smt_type != SMT_REQUEST) {
+ DB_ESS("ESS: Do not process Change Responses\n",0,0) ;
+ return(fs) ;
+ }
+
+ /*
+ * check the para for the Change Request
+ */
+ if (smt_check_para(smc,sm,plist_raf_chg_req)) {
+ DB_ESS("ESS: RAF with para problem, ignoring\n",0,0) ;
+ return(fs) ;
+ }
+
+ /*
+ * Verify the path index and resource
+ * type are correct. If any of
+ * these are false, don't process this
+ * change request frame.
+ */
+ if ((((struct smt_p_320b *)sm_to_para(smc,sm,SMT_P320B))->path_index
+ != PRIMARY_RING) || (msg_res_type != SYNC_BW)) {
+ DB_ESS("ESS: RAF frame with para problem, ignoring\n",0,0) ;
+ return(fs) ;
+ }
+
+ /*
+ * Extract message queue parameters
+ */
+ p = (void *) sm_to_para(smc,sm,SMT_P320F) ;
+ payload = ((struct smt_p_320f *)p)->mib_payload ;
+ p = (void *) sm_to_para(smc,sm,SMT_P3210) ;
+ overhead = ((struct smt_p_3210 *)p)->mib_overhead ;
+
+ DB_ESSN(2,"ESS: Change Request from %s\n",
+ addr_to_string(&sm->smt_source),0) ;
+ DB_ESSN(2,"payload= %lx overhead= %lx\n",payload,overhead) ;
+
+ /*
+ * process the bandwidth allocation
+ */
+ if(!process_bw_alloc(smc,(long)payload,(long)overhead))
+ return(fs) ;
+
+ /*
+ * send an RAF Change Reply
+ */
+ ess_send_response(smc,sm,CHANGE_ALLOCATION) ;
+
+ return(fs) ;
+ /* end of Process Change Request */
+
+ /*
+ * Process Report Response
+ */
+ case REPORT_ALLOCATION :
+ /*
+ * except only requests
+ */
+ if (sm->smt_type != SMT_REQUEST) {
+ DB_ESS("ESS: Do not process a Report Reply\n",0,0) ;
+ return(fs) ;
+ }
+
+ DB_ESSN(2,"ESS: Report Request from %s\n",
+ addr_to_string(&(sm->smt_source)),0) ;
+
+ /*
+ * verify that the resource type is sync bw only
+ */
+ if (msg_res_type != SYNC_BW) {
+ DB_ESS("ESS: ignoring RAF with para problem\n",0,0) ;
+ return(fs) ;
+ }
+
+ /*
+ * send an RAF Change Reply
+ */
+ ess_send_response(smc,sm,REPORT_ALLOCATION) ;
+
+ return(fs) ;
+ /* end of Process Report Request */
+
+ default:
+ /*
+ * error in frame
+ */
+ DB_ESS("ESS: ignoring RAF with bad sba_cmd\n",0,0) ;
+ break ;
+ }
+
+ return(fs) ;
+}
+
+/*
+ * determines the synchronous bandwidth, set the TSYNC register and the
+ * mib variables SBAPayload, SBAOverhead and fddiMACT-NEG.
+ */
+int process_bw_alloc(smc,payload,overhead)
+struct s_smc *smc ;
+long payload ;
+long overhead ;
+{
+ /*
+ * determine the synchronous bandwidth (sync_bw) in bytes per T-NEG,
+ * if the payload is greater than zero.
+ * For the SBAPayload and the SBAOverhead we have the following
+ * unite quations
+ * _ _
+ * | bytes |
+ * SBAPayload = | 8000 ------ |
+ * | s |
+ * - -
+ * _ _
+ * | bytes |
+ * SBAOverhead = | ------ |
+ * | T-NEG |
+ * - -
+ *
+ * T-NEG is discribed by the equation:
+ *
+ * (-) fddiMACT-NEG
+ * T-NEG = -------------------
+ * 12500000 1/s
+ *
+ * The number of bytes we are able to send is the payload
+ * plus the overhead.
+ *
+ * bytes T-NEG SBAPayload 8000 bytes/s
+ * sync_bw = SBAOverhead ------ + -----------------------------
+ * T-NEG T-NEG
+ *
+ *
+ * 1
+ * sync_bw = SBAOverhead + ---- (-)fddiMACT-NEG * SBAPayload
+ * 1562
+ *
+ */
+
+ /*
+ * set the mib attributes fddiPATHSbaOverhead, fddiPATHSbaPayload
+ */
+/* if (smt_set_obj(smc,SMT_P320F,payload,S_SET)) {
+ DB_ESS("ESS: SMT does not accept the payload value\n",0,0) ;
+ return(FALSE) ;
+ }
+ if (smt_set_obj(smc,SMT_P3210,overhead,S_SET)) {
+ DB_ESS("ESS: SMT does not accept the overhead value\n",0,0) ;
+ return(FALSE) ;
+ } */
+
+ /* premliminary */
+ if (payload > MAX_PAYLOAD || overhead > 5000) {
+ DB_ESS("ESS: payload / overhead not accepted\n",0,0) ;
+ return(FALSE) ;
+ }
+
+ /*
+ * start the iterative allocation process if the payload or the overhead
+ * are smaller than the parsed values
+ */
+ if (smc->mib.fddiESSPayload &&
+ ((u_long)payload != smc->mib.fddiESSPayload ||
+ (u_long)overhead != smc->mib.fddiESSOverhead)) {
+ smc->ess.raf_act_timer_poll = TRUE ;
+ smc->ess.timer_count = 0 ;
+ }
+
+ /*
+ * evulate the Payload
+ */
+ if (payload) {
+ DB_ESSN(2,"ESS: turn SMT_ST_SYNC_SERVICE bit on\n",0,0) ;
+ smc->ess.sync_bw_available = TRUE ;
+
+ smc->ess.sync_bw = overhead -
+ (long)smc->mib.m[MAC0].fddiMACT_Neg *
+ payload / 1562 ;
+ }
+ else {
+ DB_ESSN(2,"ESS: turn SMT_ST_SYNC_SERVICE bit off\n",0,0) ;
+ smc->ess.sync_bw_available = FALSE ;
+ smc->ess.sync_bw = 0 ;
+ overhead = 0 ;
+ }
+
+ smc->mib.a[PATH0].fddiPATHSbaPayload = payload ;
+ smc->mib.a[PATH0].fddiPATHSbaOverhead = overhead ;
+
+
+ DB_ESSN(2,"tsync = %lx\n",smc->ess.sync_bw,0) ;
+
+ ess_config_fifo(smc) ;
+ set_formac_tsync(smc,smc->ess.sync_bw) ;
+ return(TRUE) ;
+}
+
+static void ess_send_response(smc,sm,sba_cmd)
+struct s_smc *smc ;
+struct smt_header *sm ;
+int sba_cmd ;
+{
+ struct smt_sba_chg *chg ;
+ SMbuf *mb ;
+ void *p ;
+
+ /*
+ * get and initialize the responce frame
+ */
+ if (sba_cmd == CHANGE_ALLOCATION) {
+ if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REPLY,
+ sizeof(struct smt_sba_chg))))
+ return ;
+ }
+ else {
+ if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REPLY,
+ sizeof(struct smt_sba_rep_res))))
+ return ;
+ }
+
+ chg = smtod(mb,struct smt_sba_chg *) ;
+ chg->smt.smt_tid = sm->smt_tid ;
+ chg->smt.smt_dest = sm->smt_source ;
+
+ /* set P15 */
+ chg->s_type.para.p_type = SMT_P0015 ;
+ chg->s_type.para.p_len = sizeof(struct smt_p_0015) - PARA_LEN ;
+ chg->s_type.res_type = SYNC_BW ;
+
+ /* set P16 */
+ chg->cmd.para.p_type = SMT_P0016 ;
+ chg->cmd.para.p_len = sizeof(struct smt_p_0016) - PARA_LEN ;
+ chg->cmd.sba_cmd = sba_cmd ;
+
+ /* set P320B */
+ chg->path.para.p_type = SMT_P320B ;
+ chg->path.para.p_len = sizeof(struct smt_p_320b) - PARA_LEN ;
+ chg->path.mib_index = SBAPATHINDEX ;
+ chg->path.path_pad = (u_short)NULL ;
+ chg->path.path_index = PRIMARY_RING ;
+
+ /* set P320F */
+ chg->payload.para.p_type = SMT_P320F ;
+ chg->payload.para.p_len = sizeof(struct smt_p_320f) - PARA_LEN ;
+ chg->payload.mib_index = SBAPATHINDEX ;
+ chg->payload.mib_payload = smc->mib.a[PATH0].fddiPATHSbaPayload ;
+
+ /* set P3210 */
+ chg->overhead.para.p_type = SMT_P3210 ;
+ chg->overhead.para.p_len = sizeof(struct smt_p_3210) - PARA_LEN ;
+ chg->overhead.mib_index = SBAPATHINDEX ;
+ chg->overhead.mib_overhead = smc->mib.a[PATH0].fddiPATHSbaOverhead ;
+
+ if (sba_cmd == CHANGE_ALLOCATION) {
+ /* set P1A */
+ chg->cat.para.p_type = SMT_P001A ;
+ chg->cat.para.p_len = sizeof(struct smt_p_001a) - PARA_LEN ;
+ p = (void *) sm_to_para(smc,sm,SMT_P001A) ;
+ chg->cat.category = ((struct smt_p_001a *)p)->category ;
+ }
+ dump_smt(smc,(struct smt_header *)chg,"RAF") ;
+ ess_send_frame(smc,mb) ;
+}
+
+
+void ess_timer_poll(smc)
+struct s_smc *smc ;
+{
+ if (!smc->ess.raf_act_timer_poll)
+ return ;
+
+ DB_ESSN(2,"ESS: timer_poll\n",0,0) ;
+
+ smc->ess.timer_count++ ;
+ if (smc->ess.timer_count == 10) {
+ smc->ess.timer_count = 0 ;
+ ess_send_alc_req(smc) ;
+ }
+}
+
+static void ess_send_alc_req(smc)
+struct s_smc *smc ;
+{
+ struct smt_sba_alc_req *req ;
+ SMbuf *mb ;
+
+ /*
+ * send never allocation request where the requested payload and
+ * overhead is zero or deallocate bandwidht when no bandwidth is
+ * parsed
+ */
+ if (!smc->mib.fddiESSPayload) {
+ smc->mib.fddiESSOverhead = 0 ;
+ }
+ else {
+ if (!smc->mib.fddiESSOverhead)
+ smc->mib.fddiESSOverhead = DEFAULT_OV ;
+ }
+
+ if (smc->mib.fddiESSOverhead ==
+ smc->mib.a[PATH0].fddiPATHSbaOverhead &&
+ smc->mib.fddiESSPayload ==
+ smc->mib.a[PATH0].fddiPATHSbaPayload){
+ smc->ess.raf_act_timer_poll = FALSE ;
+ smc->ess.timer_count = 7 ; /* next RAF alc req after 3 s */
+ return ;
+ }
+
+ /*
+ * get and initialize the responce frame
+ */
+ if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REQUEST,
+ sizeof(struct smt_sba_alc_req))))
+ return ;
+ req = smtod(mb,struct smt_sba_alc_req *) ;
+ req->smt.smt_tid = smc->ess.alloc_trans_id = smt_get_tid(smc) ;
+ req->smt.smt_dest = smt_sba_da ;
+
+ /* set P15 */
+ req->s_type.para.p_type = SMT_P0015 ;
+ req->s_type.para.p_len = sizeof(struct smt_p_0015) - PARA_LEN ;
+ req->s_type.res_type = SYNC_BW ;
+
+ /* set P16 */
+ req->cmd.para.p_type = SMT_P0016 ;
+ req->cmd.para.p_len = sizeof(struct smt_p_0016) - PARA_LEN ;
+ req->cmd.sba_cmd = REQUEST_ALLOCATION ;
+
+ /*
+ * set the parameter type and parameter lenght of all used
+ * parameters
+ */
+
+ /* set P320B */
+ req->path.para.p_type = SMT_P320B ;
+ req->path.para.p_len = sizeof(struct smt_p_320b) - PARA_LEN ;
+ req->path.mib_index = SBAPATHINDEX ;
+ req->path.path_pad = (u_short)NULL ;
+ req->path.path_index = PRIMARY_RING ;
+
+ /* set P0017 */
+ req->pl_req.para.p_type = SMT_P0017 ;
+ req->pl_req.para.p_len = sizeof(struct smt_p_0017) - PARA_LEN ;
+ req->pl_req.sba_pl_req = smc->mib.fddiESSPayload -
+ smc->mib.a[PATH0].fddiPATHSbaPayload ;
+
+ /* set P0018 */
+ req->ov_req.para.p_type = SMT_P0018 ;
+ req->ov_req.para.p_len = sizeof(struct smt_p_0018) - PARA_LEN ;
+ req->ov_req.sba_ov_req = smc->mib.fddiESSOverhead -
+ smc->mib.a[PATH0].fddiPATHSbaOverhead ;
+
+ /* set P320F */
+ req->payload.para.p_type = SMT_P320F ;
+ req->payload.para.p_len = sizeof(struct smt_p_320f) - PARA_LEN ;
+ req->payload.mib_index = SBAPATHINDEX ;
+ req->payload.mib_payload = smc->mib.a[PATH0].fddiPATHSbaPayload ;
+
+ /* set P3210 */
+ req->overhead.para.p_type = SMT_P3210 ;
+ req->overhead.para.p_len = sizeof(struct smt_p_3210) - PARA_LEN ;
+ req->overhead.mib_index = SBAPATHINDEX ;
+ req->overhead.mib_overhead = smc->mib.a[PATH0].fddiPATHSbaOverhead ;
+
+ /* set P19 */
+ req->a_addr.para.p_type = SMT_P0019 ;
+ req->a_addr.para.p_len = sizeof(struct smt_p_0019) - PARA_LEN ;
+ req->a_addr.sba_pad = (u_short)NULL ;
+ req->a_addr.alloc_addr = null_addr ;
+
+ /* set P1A */
+ req->cat.para.p_type = SMT_P001A ;
+ req->cat.para.p_len = sizeof(struct smt_p_001a) - PARA_LEN ;
+ req->cat.category = smc->mib.fddiESSCategory ;
+
+ /* set P1B */
+ req->tneg.para.p_type = SMT_P001B ;
+ req->tneg.para.p_len = sizeof(struct smt_p_001b) - PARA_LEN ;
+ req->tneg.max_t_neg = smc->mib.fddiESSMaxTNeg ;
+
+ /* set P1C */
+ req->segm.para.p_type = SMT_P001C ;
+ req->segm.para.p_len = sizeof(struct smt_p_001c) - PARA_LEN ;
+ req->segm.min_seg_siz = smc->mib.fddiESSMinSegmentSize ;
+
+ dump_smt(smc,(struct smt_header *)req,"RAF") ;
+ ess_send_frame(smc,mb) ;
+}
+
+static void ess_send_frame(smc,mb)
+struct s_smc *smc ;
+SMbuf *mb ;
+{
+ /*
+ * check if the frame must be send to the own ESS
+ */
+ if (smc->ess.local_sba_active) {
+ /*
+ * Send the Change Reply to the local SBA
+ */
+ DB_ESS("ESS:Send to the local SBA\n",0,0) ;
+ if (!smc->ess.sba_reply_pend)
+ smc->ess.sba_reply_pend = mb ;
+ else {
+ DB_ESS("Frame is lost - another frame was pending\n",0,0);
+ smt_free_mbuf(smc,mb) ;
+ }
+ }
+ else {
+ /*
+ * Send the SBA RAF Change Reply to the network
+ */
+ DB_ESS("ESS:Send to the network\n",0,0) ;
+ smt_send_frame(smc,mb,FC_SMT_INFO,0) ;
+ }
+}
+
+void ess_para_change(smc)
+struct s_smc *smc ;
+{
+ (void)process_bw_alloc(smc,(long)smc->mib.a[PATH0].fddiPATHSbaPayload,
+ (long)smc->mib.a[PATH0].fddiPATHSbaOverhead) ;
+}
+
+static void ess_config_fifo(smc)
+struct s_smc *smc ;
+{
+ /*
+ * if nothing to do exit
+ */
+ if (smc->mib.a[PATH0].fddiPATHSbaPayload) {
+ if (smc->hw.fp.fifo.fifo_config_mode & SYNC_TRAFFIC_ON &&
+ (smc->hw.fp.fifo.fifo_config_mode&SEND_ASYNC_AS_SYNC) ==
+ smc->mib.fddiESSSynchTxMode) {
+ return ;
+ }
+ }
+ else {
+ if (!(smc->hw.fp.fifo.fifo_config_mode & SYNC_TRAFFIC_ON)) {
+ return ;
+ }
+ }
+
+ /*
+ * split up the FIFO and reinitialize the queues
+ */
+ formac_reinit_tx(smc) ;
+}
+
+#endif /* ESS */
+
+#endif /* no SLIM_SMT */
diff --git a/drivers/net/skfp/fplustm.c b/drivers/net/skfp/fplustm.c
new file mode 100644
index 000000000..83a935791
--- /dev/null
+++ b/drivers/net/skfp/fplustm.c
@@ -0,0 +1,1645 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * FORMAC+ Driver for tag mode
+ */
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/supern_2.h"
+#include "can.c"
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)fplustm.c 1.32 99/02/23 (C) SK " ;
+#endif
+
+#ifndef UNUSED
+#ifdef lint
+#define UNUSED(x) (x) = (x)
+#else
+#define UNUSED(x)
+#endif
+#endif
+
+#define FM_ADDRX (FM_ADDET|FM_EXGPA0|FM_EXGPA1)
+#define MS2BCLK(x) ((x)*12500L)
+#define US2BCLK(x) ((x)*1250L)
+
+/*
+ * prototypes for static function
+ */
+static void build_claim_beacon() ;
+static int init_mac() ;
+static void rtm_init() ;
+static void smt_split_up_fifo() ;
+
+#if (!defined(NO_SMT_PANIC) || defined(DEBUG))
+static char write_mdr_warning [] = "E350 write_mdr() FM_SNPPND is set\n";
+static char cam_warning [] = "E_SMT_004: CAM still busy\n";
+#endif
+
+#define DUMMY_READ() smc->hw.mc_dummy = (u_short) inp(ADDR(B0_RAP))
+
+#define CHECK_NPP() { unsigned k = 10000 ;\
+ while ((inpw(FM_A(FM_STMCHN)) & FM_SNPPND) && k) k--;\
+ if (!k) { \
+ SMT_PANIC(smc,SMT_E0130, SMT_E0130_MSG) ; \
+ } \
+ }
+
+#define CHECK_CAM() { unsigned k = 10 ;\
+ while (!(inpw(FM_A(FM_AFSTAT)) & FM_DONE) && k) k--;\
+ if (!k) { \
+ SMT_PANIC(smc,SMT_E0131, SMT_E0131_MSG) ; \
+ } \
+ }
+
+const struct fddi_addr fddi_broadcast = {0xff,0xff,0xff,0xff,0xff,0xff};
+static const struct fddi_addr null_addr = {0,0,0,0,0,0} ;
+static const struct fddi_addr dbeacon_multi = {0x01,0x80,0xc2,0x00,0x01,0x00};
+
+static const u_short my_said = 0xffff ; /* short address (n.u.) */
+static const u_short my_sagp = 0xffff ; /* short group address (n.u.) */
+
+/*
+ * define my address
+ */
+#ifdef USE_CAN_ADDR
+#define MA smc->hw.fddi_canon_addr
+#else
+#define MA smc->hw.fddi_home_addr
+#endif
+
+
+/*
+ * usefull interrupt bits
+ */
+static int mac_imsk1u = FM_STXABRS | FM_STXABRA0 | FM_SXMTABT ;
+static int mac_imsk1l = FM_SQLCKS | FM_SQLCKA0 | FM_SPCEPDS | FM_SPCEPDA0|
+ FM_STBURS | FM_STBURA0 ;
+
+ /* delete FM_SRBFL after tests */
+static int mac_imsk2u = FM_SERRSF | FM_SNFSLD | FM_SRCVOVR | FM_SRBFL |
+ FM_SMYCLM ;
+static int mac_imsk2l = FM_STRTEXR | FM_SDUPCLM | FM_SFRMCTR |
+ FM_SERRCTR | FM_SLSTCTR |
+ FM_STRTEXP | FM_SMULTDA | FM_SRNGOP ;
+
+static int mac_imsk3u = FM_SRCVOVR2 | FM_SRBFL2 ;
+static int mac_imsk3l = FM_SRPERRQ2 | FM_SRPERRQ1 ;
+
+static int mac_beacon_imsk2u = FM_SOTRBEC | FM_SMYBEC | FM_SBEC |
+ FM_SLOCLM | FM_SHICLM | FM_SMYCLM | FM_SCLM ;
+
+
+static u_long mac_get_tneg(smc)
+struct s_smc *smc ;
+{
+ u_long tneg ;
+
+ tneg = (u_long)((long)inpw(FM_A(FM_TNEG))<<5) ;
+ return((u_long)((tneg + ((inpw(FM_A(FM_TMRS))>>10)&0x1f)) |
+ 0xffe00000L)) ;
+}
+
+void mac_update_counter(smc)
+struct s_smc *smc ;
+{
+ smc->mib.m[MAC0].fddiMACFrame_Ct =
+ (smc->mib.m[MAC0].fddiMACFrame_Ct & 0xffff0000L)
+ + (u_short) inpw(FM_A(FM_FCNTR)) ;
+ smc->mib.m[MAC0].fddiMACLost_Ct =
+ (smc->mib.m[MAC0].fddiMACLost_Ct & 0xffff0000L)
+ + (u_short) inpw(FM_A(FM_LCNTR)) ;
+ smc->mib.m[MAC0].fddiMACError_Ct =
+ (smc->mib.m[MAC0].fddiMACError_Ct & 0xffff0000L)
+ + (u_short) inpw(FM_A(FM_ECNTR)) ;
+ smc->mib.m[MAC0].fddiMACT_Neg = mac_get_tneg(smc) ;
+#ifdef SMT_REAL_TOKEN_CT
+ /*
+ * If the token counter is emulated it is updated in smt_event.
+ */
+ TBD
+#else
+ smt_emulate_token_ct( smc, MAC0 );
+#endif
+}
+
+/*
+ * write long value into buffer memory over memory data register (MDR),
+ */
+void write_mdr(smc,val)
+struct s_smc *smc ;
+u_long val;
+{
+ CHECK_NPP() ;
+ MDRW(val) ;
+}
+
+/*
+ * read long value from buffer memory over memory data register (MDR),
+ */
+u_long read_mdr(smc,addr)
+struct s_smc *smc ;
+unsigned int addr;
+{
+ long p ;
+ CHECK_NPP() ;
+ MARR(addr) ;
+ outpw(FM_A(FM_CMDREG1),FM_IRMEMWO) ;
+ CHECK_NPP() ; /* needed for PCI to prevent from timeing violations */
+/* p = MDRR() ; */ /* bad read values if the workaround */
+ /* smc->hw.mc_dummy = *((short volatile far *)(addr)))*/
+ /* is used */
+ p = (u_long)inpw(FM_A(FM_MDRU))<<16 ;
+ p += (u_long)inpw(FM_A(FM_MDRL)) ;
+ return(p) ;
+}
+/*
+ * clear buffer memory
+ */
+static void init_ram(smc)
+struct s_smc *smc ;
+{
+ u_short i ;
+
+ smc->hw.fp.fifo.rbc_ram_start = 0 ;
+ smc->hw.fp.fifo.rbc_ram_end =
+ smc->hw.fp.fifo.rbc_ram_start + RBC_MEM_SIZE ;
+ CHECK_NPP() ;
+ MARW(smc->hw.fp.fifo.rbc_ram_start) ;
+ for (i = smc->hw.fp.fifo.rbc_ram_start;
+ i < (u_short) (smc->hw.fp.fifo.rbc_ram_end-1); i++)
+ write_mdr(smc,0L) ;
+ /* Erase the last byte too */
+ write_mdr(smc,0L) ;
+}
+
+/*
+ * set receive FIFO pointer
+ */
+static void set_recvptr(smc)
+struct s_smc *smc ;
+{
+ /*
+ * initialize the pointer for receive queue 1
+ */
+ outpw(FM_A(FM_RPR1),smc->hw.fp.fifo.rx1_fifo_start) ; /* RPR1 */
+ outpw(FM_A(FM_SWPR1),smc->hw.fp.fifo.rx1_fifo_start) ; /* SWPR1 */
+ outpw(FM_A(FM_WPR1),smc->hw.fp.fifo.rx1_fifo_start) ; /* WPR1 */
+ outpw(FM_A(FM_EARV1),smc->hw.fp.fifo.tx_s_start-1) ; /* EARV1 */
+
+ /*
+ * initialize the pointer for receive queue 2
+ */
+ if (smc->hw.fp.fifo.rx2_fifo_size) {
+ outpw(FM_A(FM_RPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
+ outpw(FM_A(FM_SWPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
+ outpw(FM_A(FM_WPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
+ outpw(FM_A(FM_EARV2),smc->hw.fp.fifo.rbc_ram_end-1) ;
+ }
+ else {
+ outpw(FM_A(FM_RPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
+ outpw(FM_A(FM_SWPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
+ outpw(FM_A(FM_WPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
+ outpw(FM_A(FM_EARV2),smc->hw.fp.fifo.rbc_ram_end-1) ;
+ }
+}
+
+/*
+ * set transmit FIFO pointer
+ */
+static void set_txptr(smc)
+struct s_smc *smc ;
+{
+ outpw(FM_A(FM_CMDREG2),FM_IRSTQ) ; /* reset transmit queues */
+
+ /*
+ * initialize the pointer for asynchronous transmit queue
+ */
+ outpw(FM_A(FM_RPXA0),smc->hw.fp.fifo.tx_a0_start) ; /* RPXA0 */
+ outpw(FM_A(FM_SWPXA0),smc->hw.fp.fifo.tx_a0_start) ; /* SWPXA0 */
+ outpw(FM_A(FM_WPXA0),smc->hw.fp.fifo.tx_a0_start) ; /* WPXA0 */
+ outpw(FM_A(FM_EAA0),smc->hw.fp.fifo.rx2_fifo_start-1) ; /* EAA0 */
+
+ /*
+ * initialize the pointer for synchronous transmit queue
+ */
+ if (smc->hw.fp.fifo.tx_s_size) {
+ outpw(FM_A(FM_RPXS),smc->hw.fp.fifo.tx_s_start) ;
+ outpw(FM_A(FM_SWPXS),smc->hw.fp.fifo.tx_s_start) ;
+ outpw(FM_A(FM_WPXS),smc->hw.fp.fifo.tx_s_start) ;
+ outpw(FM_A(FM_EAS),smc->hw.fp.fifo.tx_a0_start-1) ;
+ }
+ else {
+ outpw(FM_A(FM_RPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
+ outpw(FM_A(FM_SWPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
+ outpw(FM_A(FM_WPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
+ outpw(FM_A(FM_EAS),smc->hw.fp.fifo.tx_a0_start-1) ;
+ }
+}
+
+/*
+ * init memory buffer management registers
+ */
+static void init_rbc(smc)
+struct s_smc *smc ;
+{
+ u_short rbc_ram_addr ;
+
+ /*
+ * set unused pointers or permanent pointers
+ */
+ rbc_ram_addr = smc->hw.fp.fifo.rx2_fifo_start - 1 ;
+
+ outpw(FM_A(FM_RPXA1),rbc_ram_addr) ; /* a1-send pointer */
+ outpw(FM_A(FM_WPXA1),rbc_ram_addr) ;
+ outpw(FM_A(FM_SWPXA1),rbc_ram_addr) ;
+ outpw(FM_A(FM_EAA1),rbc_ram_addr) ;
+
+ set_recvptr(smc) ;
+ set_txptr(smc) ;
+}
+
+/*
+ * init rx pointer
+ */
+static void init_rx(smc)
+struct s_smc *smc ;
+{
+ struct s_smt_rx_queue *queue ;
+
+ /*
+ * init all tx data structures for receive queue 1
+ */
+ smc->hw.fp.rx[QUEUE_R1] = queue = &smc->hw.fp.rx_q[QUEUE_R1] ;
+ queue->rx_bmu_ctl = (HW_PTR) ADDR(B0_R1_CSR) ;
+ queue->rx_bmu_dsc = (HW_PTR) ADDR(B4_R1_DA) ;
+
+ /*
+ * init all tx data structures for receive queue 2
+ */
+ smc->hw.fp.rx[QUEUE_R2] = queue = &smc->hw.fp.rx_q[QUEUE_R2] ;
+ queue->rx_bmu_ctl = (HW_PTR) ADDR(B0_R2_CSR) ;
+ queue->rx_bmu_dsc = (HW_PTR) ADDR(B4_R2_DA) ;
+}
+
+/*
+ * set the TSYNC register of the FORMAC to regulate synchronous transmission
+ */
+void set_formac_tsync(smc,sync_bw)
+struct s_smc *smc ;
+long sync_bw ;
+{
+ outpw(FM_A(FM_TSYNC),(unsigned int) (((-sync_bw) >> 5) & 0xffff) ) ;
+}
+
+/*
+ * init all tx data structures
+ */
+static void init_tx(smc)
+struct s_smc *smc ;
+{
+ struct s_smt_tx_queue *queue ;
+
+ /*
+ * init all tx data structures for the synchronous queue
+ */
+ smc->hw.fp.tx[QUEUE_S] = queue = &smc->hw.fp.tx_q[QUEUE_S] ;
+ queue->tx_bmu_ctl = (HW_PTR) ADDR(B0_XS_CSR) ;
+ queue->tx_bmu_dsc = (HW_PTR) ADDR(B5_XS_DA) ;
+
+#ifdef ESS
+ set_formac_tsync(smc,smc->ess.sync_bw) ;
+#endif
+
+ /*
+ * init all tx data structures for the asynchronous queue 0
+ */
+ smc->hw.fp.tx[QUEUE_A0] = queue = &smc->hw.fp.tx_q[QUEUE_A0] ;
+ queue->tx_bmu_ctl = (HW_PTR) ADDR(B0_XA_CSR) ;
+ queue->tx_bmu_dsc = (HW_PTR) ADDR(B5_XA_DA) ;
+
+
+ llc_recover_tx(smc) ;
+}
+
+static void mac_counter_init(smc)
+struct s_smc *smc ;
+{
+ int i ;
+ u_long *ec ;
+
+ /*
+ * clear FORMAC+ frame-, lost- and error counter
+ */
+ outpw(FM_A(FM_FCNTR),0) ;
+ outpw(FM_A(FM_LCNTR),0) ;
+ outpw(FM_A(FM_ECNTR),0) ;
+ /*
+ * clear internal error counter stucture
+ */
+ ec = (u_long *)&smc->hw.fp.err_stats ;
+ for (i = (sizeof(struct err_st)/sizeof(long)) ; i ; i--)
+ *ec++ = 0L ;
+ smc->mib.m[MAC0].fddiMACRingOp_Ct = 0 ;
+}
+
+/*
+ * set FORMAC address, and t_request
+ */
+static void set_formac_addr(smc)
+struct s_smc *smc ;
+{
+ long t_requ = smc->mib.m[MAC0].fddiMACT_Req ;
+
+ outpw(FM_A(FM_SAID),my_said) ; /* set short address */
+ outpw(FM_A(FM_LAIL),(unsigned)((smc->hw.fddi_home_addr.a[4]<<8) +
+ smc->hw.fddi_home_addr.a[5])) ;
+ outpw(FM_A(FM_LAIC),(unsigned)((smc->hw.fddi_home_addr.a[2]<<8) +
+ smc->hw.fddi_home_addr.a[3])) ;
+ outpw(FM_A(FM_LAIM),(unsigned)((smc->hw.fddi_home_addr.a[0]<<8) +
+ smc->hw.fddi_home_addr.a[1])) ;
+
+ outpw(FM_A(FM_SAGP),my_sagp) ; /* set short group address */
+
+ outpw(FM_A(FM_LAGL),(unsigned)((smc->hw.fp.group_addr.a[4]<<8) +
+ smc->hw.fp.group_addr.a[5])) ;
+ outpw(FM_A(FM_LAGC),(unsigned)((smc->hw.fp.group_addr.a[2]<<8) +
+ smc->hw.fp.group_addr.a[3])) ;
+ outpw(FM_A(FM_LAGM),(unsigned)((smc->hw.fp.group_addr.a[0]<<8) +
+ smc->hw.fp.group_addr.a[1])) ;
+
+ /* set r_request regs. (MSW & LSW of TRT ) */
+ outpw(FM_A(FM_TREQ1),(unsigned)(t_requ>>16)) ;
+ outpw(FM_A(FM_TREQ0),(unsigned)t_requ) ;
+}
+
+void set_long(p,l)
+char *p;
+long l;
+{
+ p[0] = (char)(l >> 24) ;
+ p[1] = (char)(l >> 16) ;
+ p[2] = (char)(l >> 8) ;
+ p[3] = (char)(l >> 0) ;
+}
+
+/*
+ * copy TX descriptor to buffer mem
+ * append FC field and MAC frame
+ * if more bit is set in descr
+ * append pointer to descriptor (endless loop)
+ * else
+ * append 'end of chain' pointer
+ */
+static void copy_tx_mac(smc,td,mac,off,len)
+struct s_smc *smc ;
+u_long td; /* transmit descriptor */
+struct fddi_mac *mac; /* mac frame pointer */
+unsigned off; /* start address within buffer memory */
+int len ; /* lenght of the frame including the FC */
+{
+ int i ;
+ u_long *p ;
+
+ CHECK_NPP() ;
+ MARW(off) ; /* set memory address reg for writes */
+
+ p = (u_long *) mac ;
+ for (i = (len + 3)/4 ; i ; i--) {
+ if (i == 1) {
+ /* last word, set the tag bit */
+ outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;
+ }
+ write_mdr(smc,MDR_REVERSE(*p)) ;
+ p++ ;
+ }
+
+ outpw(FM_A(FM_CMDREG2),FM_ISTTB) ; /* set the tag bit */
+ write_mdr(smc,td) ; /* write over memory data reg to buffer */
+}
+
+/*
+ BEGIN_MANUAL_ENTRY(module;tests;3)
+ How to test directed beacon frames
+ ----------------------------------------------------------------
+
+ o Insert a break point in the function build_claim_beacon()
+ before calling copy_tx_mac() for building the claim frame.
+ o Modify the RM3_DETECT case so that the RM6_DETECT state
+ will always entered from the RM3_DETECT state (function rmt_fsm(),
+ rmt.c)
+ o Compile the driver.
+ o Set the parameter TREQ in the protocol.ini or net.cfg to a
+ small value to make sure your station will win the claim
+ process.
+ o Start the driver.
+ o When you reach the break point, modify the SA and DA address
+ of the claim frame (e.g. SA = DA = 10005affffff).
+ o When you see RM3_DETECT and RM6_DETECT, observe the direct
+ beacon frames on the UPPSLANA.
+
+ END_MANUAL_ENTRY
+ */
+static void directed_beacon(smc)
+struct s_smc *smc ;
+{
+ SK_LOC_DECL(u_long,a[2]) ;
+
+ /*
+ * set UNA in frame
+ * enable FORMAC to send endless queue of directed beacon
+ * important: the UNA starts at byte 1 (not at byte 0)
+ */
+ * (char *) a = (char) ((long)DBEACON_INFO<<24L) ;
+ a[1] = 0 ;
+ memcpy((char *)a+1,(char *) &smc->mib.m[MAC0].fddiMACUpstreamNbr,6) ;
+
+ CHECK_NPP() ;
+ /* set memory address reg for writes */
+ MARW(smc->hw.fp.fifo.rbc_ram_start+DBEACON_FRAME_OFF+4) ;
+ write_mdr(smc,MDR_REVERSE(a[0])) ;
+ outpw(FM_A(FM_CMDREG2),FM_ISTTB) ; /* set the tag bit */
+ write_mdr(smc,MDR_REVERSE(a[1])) ;
+
+ outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF) ;
+}
+
+/*
+ setup claim & beacon pointer
+ NOTE :
+ special frame packets end with a pointer to their own
+ descriptor, and the MORE bit is set in the descriptor
+*/
+static void build_claim_beacon(smc,t_request)
+struct s_smc *smc ;
+u_long t_request;
+{
+ u_long td ;
+ int len ;
+ struct fddi_mac_sf *mac ;
+
+ /*
+ * build claim packet
+ */
+ len = 17 ;
+ td = TX_DESCRIPTOR | ((((u_long)len-1)&3)<<27) ;
+ mac = &smc->hw.fp.mac_sfb ;
+ mac->mac_fc = FC_CLAIM ;
+ /* DA == SA in claim frame */
+ mac->mac_source = mac->mac_dest = MA ;
+ /* 2's complement */
+ set_long((char *)mac->mac_info,(long)t_request) ;
+
+ copy_tx_mac(smc,td,(struct fddi_mac *)mac,
+ smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF,len) ;
+ /* set CLAIM start pointer */
+ outpw(FM_A(FM_SACL),smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF) ;
+
+ /*
+ * build beacon packet
+ */
+ len = 17 ;
+ td = TX_DESCRIPTOR | ((((u_long)len-1)&3)<<27) ;
+ mac->mac_fc = FC_BEACON ;
+ mac->mac_source = MA ;
+ mac->mac_dest = null_addr ; /* DA == 0 in beacon frame */
+ set_long((char *) mac->mac_info,((long)BEACON_INFO<<24L) + 0 ) ;
+
+ copy_tx_mac(smc,td,(struct fddi_mac *)mac,
+ smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF,len) ;
+ /* set beacon start pointer */
+ outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF) ;
+
+ /*
+ * build directed beacon packet
+ * contains optional UNA
+ */
+ len = 23 ;
+ td = TX_DESCRIPTOR | ((((u_long)len-1)&3)<<27) ;
+ mac->mac_fc = FC_BEACON ;
+ mac->mac_source = MA ;
+ mac->mac_dest = dbeacon_multi ; /* multicast */
+ set_long((char *) mac->mac_info,((long)DBEACON_INFO<<24L) + 0 ) ;
+ set_long((char *) mac->mac_info+4,0L) ;
+ set_long((char *) mac->mac_info+8,0L) ;
+
+ copy_tx_mac(smc,td,(struct fddi_mac *)mac,
+ smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF,len) ;
+
+ /* end of claim/beacon queue */
+ outpw(FM_A(FM_EACB),smc->hw.fp.fifo.rx1_fifo_start-1) ;
+
+ outpw(FM_A(FM_WPXSF),0) ;
+ outpw(FM_A(FM_RPXSF),0) ;
+}
+
+void formac_rcv_restart(smc)
+struct s_smc *smc ;
+{
+ /* enable receive function */
+ SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ;
+
+ outpw(FM_A(FM_CMDREG1),FM_ICLLR) ; /* clear receive lock */
+}
+
+void formac_tx_restart(smc)
+struct s_smc *smc ;
+{
+ outpw(FM_A(FM_CMDREG1),FM_ICLLS) ; /* clear s-frame lock */
+ outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ; /* clear a-frame lock */
+}
+
+static void enable_formac(smc)
+struct s_smc *smc ;
+{
+ /* set formac IMSK : 0 enables irq */
+ outpw(FM_A(FM_IMSK1U),~mac_imsk1u) ;
+ outpw(FM_A(FM_IMSK1L),~mac_imsk1l) ;
+ outpw(FM_A(FM_IMSK2U),~mac_imsk2u) ;
+ outpw(FM_A(FM_IMSK2L),~mac_imsk2l) ;
+ outpw(FM_A(FM_IMSK3U),~mac_imsk3u) ;
+ outpw(FM_A(FM_IMSK3L),~mac_imsk3l) ;
+}
+
+#if 0 /* Removed because the driver should use the ASICs TX complete IRQ. */
+ /* The FORMACs tx complete IRQ should be used any longer */
+
+/*
+ BEGIN_MANUAL_ENTRY(if,func;others;4)
+
+ void enable_tx_irq(smc, queue)
+ struct s_smc *smc ;
+ u_short queue ;
+
+Function DOWNCALL (SMT, fplustm.c)
+ enable_tx_irq() enables the FORMACs transmit complete
+ interrupt of the queue.
+
+Para queue = QUEUE_S: synchronous queue
+ = QUEUE_A0: asynchronous queue
+
+Note After any ring operational change the transmit complete
+ interrupts are disabled.
+ The operating system dependent module must enable
+ the transmit complete interrupt of a queue,
+ - when it queues the first frame,
+ because of no transmit resources are beeing
+ available and
+ - when it escapes from the function llc_restart_tx
+ while some frames are still queued.
+
+ END_MANUAL_ENTRY
+ */
+void enable_tx_irq(smc, queue)
+struct s_smc *smc ;
+u_short queue ; /* 0 = synchronous queue, 1 = asynchronous queue 0 */
+{
+ u_short imask ;
+
+ imask = ~(inpw(FM_A(FM_IMSK1U))) ;
+
+ if (queue == 0) {
+ outpw(FM_A(FM_IMSK1U),~(imask|FM_STEFRMS)) ;
+ }
+ if (queue == 1) {
+ outpw(FM_A(FM_IMSK1U),~(imask|FM_STEFRMA0)) ;
+ }
+}
+
+/*
+ BEGIN_MANUAL_ENTRY(if,func;others;4)
+
+ void disable_tx_irq(smc, queue)
+ struct s_smc *smc ;
+ u_short queue ;
+
+Function DOWNCALL (SMT, fplustm.c)
+ disable_tx_irq disables the FORMACs transmit complete
+ interrupt of the queue
+
+Para queue = QUEUE_S: synchronous queue
+ = QUEUE_A0: asynchronous queue
+
+Note The operating system dependent module should disable
+ the transmit complete interrupts if it escapes from the
+ function llc_restart_tx and no frames are queued.
+
+ END_MANUAL_ENTRY
+ */
+void disable_tx_irq(smc, queue)
+struct s_smc *smc ;
+u_short queue ; /* 0 = synchronous queue, 1 = asynchronous queue 0 */
+{
+ u_short imask ;
+
+ imask = ~(inpw(FM_A(FM_IMSK1U))) ;
+
+ if (queue == 0) {
+ outpw(FM_A(FM_IMSK1U),~(imask&~FM_STEFRMS)) ;
+ }
+ if (queue == 1) {
+ outpw(FM_A(FM_IMSK1U),~(imask&~FM_STEFRMA0)) ;
+ }
+}
+#endif
+
+static void disable_formac(smc)
+struct s_smc *smc ;
+{
+ /* clear formac IMSK : 1 disables irq */
+ outpw(FM_A(FM_IMSK1U),MW) ;
+ outpw(FM_A(FM_IMSK1L),MW) ;
+ outpw(FM_A(FM_IMSK2U),MW) ;
+ outpw(FM_A(FM_IMSK2L),MW) ;
+ outpw(FM_A(FM_IMSK3U),MW) ;
+ outpw(FM_A(FM_IMSK3L),MW) ;
+}
+
+
+static void mac_ring_up(smc,up)
+struct s_smc *smc ;
+int up;
+{
+ if (up) {
+ formac_rcv_restart(smc) ; /* enable receive function */
+ smc->hw.mac_ring_is_up = TRUE ;
+ llc_restart_tx(smc) ; /* TX queue */
+ }
+ else {
+ /* disable receive function */
+ SETMASK(FM_A(FM_MDREG1),FM_MDISRCV,FM_ADDET) ;
+
+ /* abort current transmit activity */
+ outpw(FM_A(FM_CMDREG2),FM_IACTR) ;
+
+ smc->hw.mac_ring_is_up = FALSE ;
+ }
+}
+
+/*--------------------------- ISR handling ----------------------------------*/
+/*
+ * mac1_irq is in drvfbi.c
+ */
+
+/*
+ * mac2_irq: status bits for the receive queue 1, and ring status
+ * ring status indication bits
+ */
+void mac2_irq(smc,code_s2u,code_s2l)
+struct s_smc *smc ;
+u_short code_s2u ;
+u_short code_s2l ;
+{
+ u_short change_s2l ;
+ u_short change_s2u ;
+
+ /* (jd) 22-Feb-1999
+ * Restart 2_DMax Timer after end of claiming or beaconing
+ */
+ if (code_s2u & (FM_SCLM|FM_SHICLM|FM_SBEC|FM_SOTRBEC)) {
+ queue_event(smc,EVENT_RMT,RM_TX_STATE_CHANGE) ;
+ }
+ else if (code_s2l & (FM_STKISS)) {
+ queue_event(smc,EVENT_RMT,RM_TX_STATE_CHANGE) ;
+ }
+
+ /*
+ * XOR current st bits with the last to avoid useless RMT event queuing
+ */
+ change_s2l = smc->hw.fp.s2l ^ code_s2l ;
+ change_s2u = smc->hw.fp.s2u ^ code_s2u ;
+
+ if ((change_s2l & FM_SRNGOP) ||
+ (!smc->hw.mac_ring_is_up && ((code_s2l & FM_SRNGOP)))) {
+ if (code_s2l & FM_SRNGOP) {
+ mac_ring_up(smc,1) ;
+ queue_event(smc,EVENT_RMT,RM_RING_OP) ;
+ smc->mib.m[MAC0].fddiMACRingOp_Ct++ ;
+ }
+ else {
+ mac_ring_up(smc,0) ;
+ queue_event(smc,EVENT_RMT,RM_RING_NON_OP) ;
+ }
+ goto mac2_end ;
+ }
+ if (code_s2l & FM_SMISFRM) { /* missed frame */
+ smc->mib.m[MAC0].fddiMACNotCopied_Ct++ ;
+ }
+ if (code_s2u & (FM_SRCVOVR | /* recv. FIFO overflow */
+ FM_SRBFL)) { /* recv. buffer full */
+ smc->hw.mac_ct.mac_r_restart_counter++ ;
+/* formac_rcv_restart(smc) ; */
+ smt_stat_counter(smc,1) ;
+/* goto mac2_end ; */
+ }
+ if (code_s2u & FM_SOTRBEC)
+ queue_event(smc,EVENT_RMT,RM_OTHER_BEACON) ;
+ if (code_s2u & FM_SMYBEC)
+ queue_event(smc,EVENT_RMT,RM_MY_BEACON) ;
+ if (change_s2u & code_s2u & FM_SLOCLM) {
+ DB_RMTN(2,"RMT : lower claim received\n",0,0) ;
+ }
+ if ((code_s2u & FM_SMYCLM) && !(code_s2l & FM_SDUPCLM)) {
+ /*
+ * This is my claim and that claim is not detected as a
+ * duplicate one.
+ */
+ queue_event(smc,EVENT_RMT,RM_MY_CLAIM) ;
+ }
+ if (code_s2l & FM_SDUPCLM) {
+ /*
+ * If a duplicate claim frame (same SA but T_Bid != T_Req)
+ * this flag will be set.
+ * In the RMT state machine we need a RM_VALID_CLAIM event
+ * to do the appropriate state change.
+ * RM(34c)
+ */
+ queue_event(smc,EVENT_RMT,RM_VALID_CLAIM) ;
+ }
+ if (change_s2u & code_s2u & FM_SHICLM) {
+ DB_RMTN(2,"RMT : higher claim received\n",0,0) ;
+ }
+ if ( (code_s2l & FM_STRTEXP) ||
+ (code_s2l & FM_STRTEXR) )
+ queue_event(smc,EVENT_RMT,RM_TRT_EXP) ;
+ if (code_s2l & FM_SMULTDA) {
+ /*
+ * The MAC has found a 2. MAC with the same address.
+ * Signal dup_addr_test = failed to RMT state machine.
+ * RM(25)
+ */
+ smc->r.dup_addr_test = DA_FAILED ;
+ queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;
+ }
+ if (code_s2u & FM_SBEC)
+ smc->hw.fp.err_stats.err_bec_stat++ ;
+ if (code_s2u & FM_SCLM)
+ smc->hw.fp.err_stats.err_clm_stat++ ;
+ if (code_s2l & FM_STVXEXP)
+ smc->mib.m[MAC0].fddiMACTvxExpired_Ct++ ;
+ if ((code_s2u & (FM_SBEC|FM_SCLM))) {
+ if (!(change_s2l & FM_SRNGOP) && (smc->hw.fp.s2l & FM_SRNGOP)) {
+ mac_ring_up(smc,0) ;
+ queue_event(smc,EVENT_RMT,RM_RING_NON_OP) ;
+
+ mac_ring_up(smc,1) ;
+ queue_event(smc,EVENT_RMT,RM_RING_OP) ;
+ smc->mib.m[MAC0].fddiMACRingOp_Ct++ ;
+ }
+ }
+ if (code_s2l & FM_SPHINV)
+ smc->hw.fp.err_stats.err_phinv++ ;
+ if (code_s2l & FM_SSIFG)
+ smc->hw.fp.err_stats.err_sifg_det++ ;
+ if (code_s2l & FM_STKISS)
+ smc->hw.fp.err_stats.err_tkiss++ ;
+ if (code_s2l & FM_STKERR)
+ smc->hw.fp.err_stats.err_tkerr++ ;
+ if (code_s2l & FM_SFRMCTR)
+ smc->mib.m[MAC0].fddiMACFrame_Ct += 0x10000L ;
+ if (code_s2l & FM_SERRCTR)
+ smc->mib.m[MAC0].fddiMACError_Ct += 0x10000L ;
+ if (code_s2l & FM_SLSTCTR)
+ smc->mib.m[MAC0].fddiMACLost_Ct += 0x10000L ;
+ if (code_s2u & FM_SERRSF) {
+ SMT_PANIC(smc,SMT_E0114, SMT_E0114_MSG) ;
+ }
+mac2_end:
+ /* notice old status */
+ smc->hw.fp.s2l = code_s2l ;
+ smc->hw.fp.s2u = code_s2u ;
+ outpw(FM_A(FM_IMSK2U),~mac_imsk2u) ;
+}
+
+/*
+ * mac3_irq: receive queue 2 bits and address detection bits
+ */
+void mac3_irq(smc,code_s3u,code_s3l)
+struct s_smc *smc ;
+u_short code_s3u ;
+u_short code_s3l ;
+{
+ UNUSED(code_s3l) ;
+
+ if (code_s3u & (FM_SRCVOVR2 | /* recv. FIFO overflow */
+ FM_SRBFL2)) { /* recv. buffer full */
+ smc->hw.mac_ct.mac_r_restart_counter++ ;
+ smt_stat_counter(smc,1);
+ }
+
+
+ if (code_s3u & FM_SRPERRQ2) { /* parity error receive queue 2 */
+ SMT_PANIC(smc,SMT_E0115, SMT_E0115_MSG) ;
+ }
+ if (code_s3u & FM_SRPERRQ1) { /* parity error receive queue 2 */
+ SMT_PANIC(smc,SMT_E0116, SMT_E0116_MSG) ;
+ }
+}
+
+
+/*
+ * take formac offline
+ */
+static void formac_offline(smc)
+struct s_smc *smc ;
+{
+ outpw(FM_A(FM_CMDREG2),FM_IACTR) ;/* abort current transmit activity */
+
+ /* disable receive function */
+ SETMASK(FM_A(FM_MDREG1),FM_MDISRCV,FM_ADDET) ;
+
+ /* FORMAC+ 'Initialize Mode' */
+ SETMASK(FM_A(FM_MDREG1),FM_MINIT,FM_MMODE) ;
+
+ disable_formac(smc) ;
+ smc->hw.mac_ring_is_up = FALSE ;
+ smc->hw.hw_state = STOPPED ;
+}
+
+/*
+ * bring formac online
+ */
+static void formac_online(smc)
+struct s_smc *smc ;
+{
+ enable_formac(smc) ;
+ SETMASK(FM_A(FM_MDREG1),FM_MONLINE | FM_SELRA | MDR1INIT |
+ smc->hw.fp.rx_mode, FM_MMODE | FM_SELRA | FM_ADDRX) ;
+}
+
+/*
+ * FORMAC+ full init. (tx, rx, timer, counter, claim & beacon)
+ */
+int init_fplus(smc)
+struct s_smc *smc ;
+{
+ smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ;
+ smc->hw.fp.rx_mode = FM_MDAMA ;
+ smc->hw.fp.group_addr = fddi_broadcast ;
+ smc->hw.fp.func_addr = 0 ;
+ smc->hw.fp.frselreg_init = 0 ;
+
+ init_driver_fplus(smc) ;
+ if (smc->s.sas == SMT_DAS)
+ smc->hw.fp.mdr3init |= FM_MENDAS ;
+
+ smc->hw.mac_ct.mac_nobuf_counter = 0 ;
+ smc->hw.mac_ct.mac_r_restart_counter = 0 ;
+
+ smc->hw.fp.fm_st1u = (HW_PTR) ADDR(B0_ST1U) ;
+ smc->hw.fp.fm_st1l = (HW_PTR) ADDR(B0_ST1L) ;
+ smc->hw.fp.fm_st2u = (HW_PTR) ADDR(B0_ST2U) ;
+ smc->hw.fp.fm_st2l = (HW_PTR) ADDR(B0_ST2L) ;
+ smc->hw.fp.fm_st3u = (HW_PTR) ADDR(B0_ST3U) ;
+ smc->hw.fp.fm_st3l = (HW_PTR) ADDR(B0_ST3L) ;
+
+ smc->hw.fp.s2l = smc->hw.fp.s2u = 0 ;
+ smc->hw.mac_ring_is_up = 0 ;
+
+ mac_counter_init(smc) ;
+
+ /* convert BCKL units to symbol time */
+ smc->hw.mac_pa.t_neg = (u_long)0 ;
+ smc->hw.mac_pa.t_pri = (u_long)0 ;
+
+ /* make sure all PCI settings are correct */
+ mac_do_pci_fix(smc) ;
+
+ return(init_mac(smc,1)) ;
+ /* enable_formac(smc) ; */
+}
+
+static int init_mac(smc,all)
+struct s_smc *smc ;
+int all ;
+{
+ u_short t_max,x ;
+ u_long time=0 ;
+
+ /*
+ * clear memory
+ */
+ outpw(FM_A(FM_MDREG1),FM_MINIT) ; /* FORMAC+ init mode */
+ set_formac_addr(smc) ;
+ outpw(FM_A(FM_MDREG1),FM_MMEMACT) ; /* FORMAC+ memory activ mode */
+ /* Note: Mode register 2 is set here, incase parity is enabled. */
+ outpw(FM_A(FM_MDREG2),smc->hw.fp.mdr2init) ;
+
+ if (all) {
+ init_ram(smc) ;
+ }
+ else {
+ /*
+ * reset the HPI, the Master and the BMUs
+ */
+ outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
+ time = hwt_quick_read(smc) ;
+ }
+
+ /*
+ * set all pointers, frames etc
+ */
+ smt_split_up_fifo(smc) ;
+
+ init_tx(smc) ;
+ init_rx(smc) ;
+ init_rbc(smc) ;
+
+ build_claim_beacon(smc,smc->mib.m[MAC0].fddiMACT_Req) ;
+
+ /* set RX threshold */
+ /* see Errata #SN2 Phantom receive overflow */
+ outpw(FM_A(FM_FRMTHR),14<<12) ; /* switch on */
+
+ /* set formac work mode */
+ outpw(FM_A(FM_MDREG1),MDR1INIT | FM_SELRA | smc->hw.fp.rx_mode) ;
+ outpw(FM_A(FM_MDREG2),smc->hw.fp.mdr2init) ;
+ outpw(FM_A(FM_MDREG3),smc->hw.fp.mdr3init) ;
+ outpw(FM_A(FM_FRSELREG),smc->hw.fp.frselreg_init) ;
+
+ /* set timer */
+ /*
+ * errata #22 fplus:
+ * T_MAX must not be FFFE
+ * or one of FFDF, FFB8, FF91 (-0x27 etc..)
+ */
+ t_max = (u_short)(smc->mib.m[MAC0].fddiMACT_Max/32) ;
+ x = t_max/0x27 ;
+ x *= 0x27 ;
+ if ((t_max == 0xfffe) || (t_max - x == 0x16))
+ t_max-- ;
+ outpw(FM_A(FM_TMAX),(u_short)t_max) ;
+
+ /* BugFix for report #10204 */
+ if (smc->mib.m[MAC0].fddiMACTvxValue < (u_long) (- US2BCLK(52))) {
+ outpw(FM_A(FM_TVX), (u_short) (- US2BCLK(52))/255 & MB) ;
+ } else {
+ outpw(FM_A(FM_TVX),
+ (u_short)((smc->mib.m[MAC0].fddiMACTvxValue/255) & MB)) ;
+ }
+
+ outpw(FM_A(FM_CMDREG1),FM_ICLLS) ; /* clear s-frame lock */
+ outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ; /* clear a-frame lock */
+ outpw(FM_A(FM_CMDREG1),FM_ICLLR); /* clear receive lock */
+
+ /* Auto unlock receice threshold for receive queue 1 and 2 */
+ outpw(FM_A(FM_UNLCKDLY),(0xff|(0xff<<8))) ;
+
+ rtm_init(smc) ; /* RT-Monitor */
+
+ if (!all) {
+ /*
+ * after 10ms, reset the BMUs and repair the rings
+ */
+ hwt_wait_time(smc,time,MS2BCLK(10)) ;
+ outpd(ADDR(B0_R1_CSR),CSR_SET_RESET) ;
+ outpd(ADDR(B0_XA_CSR),CSR_SET_RESET) ;
+ outpd(ADDR(B0_XS_CSR),CSR_SET_RESET) ;
+ outp(ADDR(B0_CTRL), CTRL_HPI_CLR) ;
+ outpd(ADDR(B0_R1_CSR),CSR_CLR_RESET) ;
+ outpd(ADDR(B0_XA_CSR),CSR_CLR_RESET) ;
+ outpd(ADDR(B0_XS_CSR),CSR_CLR_RESET) ;
+ if (!smc->hw.hw_is_64bit) {
+ outpd(ADDR(B4_R1_F), RX_WATERMARK) ;
+ outpd(ADDR(B5_XA_F), TX_WATERMARK) ;
+ outpd(ADDR(B5_XS_F), TX_WATERMARK) ;
+ }
+ smc->hw.hw_state = STOPPED ;
+ mac_drv_repair_descr(smc) ;
+ }
+ smc->hw.hw_state = STARTED ;
+
+ return(0) ;
+}
+
+
+/*
+ * called by CFM
+ */
+void config_mux(smc,mux)
+struct s_smc *smc ;
+int mux;
+{
+ plc_config_mux(smc,mux) ;
+
+ SETMASK(FM_A(FM_MDREG1),FM_SELRA,FM_SELRA) ;
+}
+
+/*
+ * called by RMT
+ * enable CLAIM/BEACON interrupts
+ * (only called if these events are of interest, e.g. in DETECT state
+ * the interrupt must not be permanently enabled
+ * RMT calls this function periodically (timer driven polling)
+ */
+void sm_mac_check_beacon_claim(smc)
+struct s_smc *smc ;
+{
+ /* set formac IMSK : 0 enables irq */
+ outpw(FM_A(FM_IMSK2U),~(mac_imsk2u | mac_beacon_imsk2u)) ;
+ /* the driver must receive the directed beacons */
+ formac_rcv_restart(smc) ;
+ process_receive(smc) ;
+}
+
+/*-------------------------- interface functions ----------------------------*/
+/*
+ * control ODL output
+ */
+void sm_pm_control(smc,mode)
+struct s_smc *smc ;
+int mode;
+{
+ SK_UNUSED(smc) ;
+
+ /*
+ * if PCM logic has set LS_REQUEST = Transmit QUIET Line State
+ * /FOTOFF signal turn activ -> ODL disable
+ */
+ switch(mode) {
+ case PM_TRANSMIT_DISABLE :
+ break ;
+ case PM_TRANSMIT_ENABLE :
+ break ;
+ }
+}
+
+/*
+ * control MAC layer (called by RMT)
+ */
+void sm_ma_control(smc,mode)
+struct s_smc *smc ;
+int mode;
+{
+ switch(mode) {
+ case MA_OFFLINE :
+ /* Add to make the MAC offline in RM0_ISOLATED state */
+ formac_offline(smc) ;
+ break ;
+ case MA_RESET :
+ (void)init_mac(smc,0) ;
+ break ;
+ case MA_BEACON :
+ formac_online(smc) ;
+ break ;
+ case MA_DIRECTED :
+ directed_beacon(smc) ;
+ break ;
+ case MA_TREQ :
+ /*
+ * no actions necessary, TREQ is already set
+ */
+ break ;
+ }
+}
+
+int sm_mac_get_tx_state(smc)
+struct s_smc *smc ;
+{
+ return((inpw(FM_A(FM_STMCHN))>>4)&7) ;
+}
+
+/*
+ * multicast functions
+ */
+
+static struct s_fpmc *mac_get_mc_table(smc,user,own,del,can)
+struct s_smc *smc ;
+struct fddi_addr *user ;
+struct fddi_addr *own ;
+int del ;
+int can ;
+{
+ struct s_fpmc *tb ;
+ struct s_fpmc *slot ;
+ u_char *p ;
+ int i ;
+
+ /*
+ * set own = can(user)
+ */
+ *own = *user ;
+ if (can) {
+ p = own->a ;
+ for (i = 0 ; i < 6 ; i++, p++)
+ *p = canonical[*p] ;
+ }
+ slot = 0 ;
+ for (i = 0, tb = smc->hw.fp.mc.table ; i < FPMAX_MULTICAST ; i++, tb++){
+ if (!tb->n) { /* not used */
+ if (!del && !slot) /* if !del save first free */
+ slot = tb ;
+ continue ;
+ }
+ if (memcmp((char *)&tb->a,(char *)own,6))
+ continue ;
+ return(tb) ;
+ }
+ return(slot) ; /* return first free or NULL */
+}
+
+/*
+ BEGIN_MANUAL_ENTRY(if,func;others;2)
+
+ void mac_clear_multicast(smc)
+ struct s_smc *smc ;
+
+Function DOWNCALL (SMT, fplustm.c)
+ Clear all multicast entries
+
+ END_MANUAL_ENTRY()
+ */
+void mac_clear_multicast(smc)
+struct s_smc *smc ;
+{
+ struct s_fpmc *tb ;
+ int i ;
+
+ smc->hw.fp.os_slots_used = 0 ; /* note the SMT addresses */
+ /* will not be deleted */
+ for (i = 0, tb = smc->hw.fp.mc.table ; i < FPMAX_MULTICAST ; i++, tb++){
+ if (!tb->perm) {
+ tb->n = 0 ;
+ }
+ }
+}
+
+/*
+ BEGIN_MANUAL_ENTRY(if,func;others;2)
+
+ int mac_set_func_addr(smc,f_addr)
+ struct s_smc *smc ;
+ u_long f_addr ;
+
+Function DOWNCALL (SMT, fplustm.c)
+ Set a Token-Ring functional address, the address will
+ be activated after calling mac_update_multicast()
+
+Para f_addr functional bits in non-canonical format
+
+Returns 0: always success
+
+ END_MANUAL_ENTRY()
+ */
+int mac_set_func_addr(smc,f_addr)
+struct s_smc *smc ;
+u_long f_addr ;
+{
+ smc->hw.fp.func_addr = f_addr ;
+ return(0) ;
+}
+
+
+/*
+ BEGIN_MANUAL_ENTRY(if,func;others;2)
+
+ int mac_add_multicast(smc,addr,can)
+ struct s_smc *smc ;
+ struct fddi_addr *addr ;
+ int can ;
+
+Function DOWNCALL (SMC, fplustm.c)
+ Add an entry to the multicast table
+
+Para addr pointer to a multicast address
+ can = 0: the multicast address has the physical format
+ = 1: the multicast address has the canonical format
+ | 0x80 permanent
+
+Returns 0: success
+ 1: address table full
+
+Note After a 'driver reset' or a 'station set address' all
+ entries of the multicast table are cleared.
+ In this case the driver has to fill the multicast table again.
+ After the operating system dependent module filled
+ the multicast table it must call mac_update_multicast
+ to activate the new multicast addresses!
+
+ END_MANUAL_ENTRY()
+ */
+int mac_add_multicast(smc,addr,can)
+struct s_smc *smc ;
+struct fddi_addr *addr ;
+int can ;
+{
+ SK_LOC_DECL(struct fddi_addr,own) ;
+ struct s_fpmc *tb ;
+
+ /*
+ * check if there are free table entries
+ */
+ if (can & 0x80) {
+ if (smc->hw.fp.smt_slots_used >= SMT_MAX_MULTI) {
+ return(1) ;
+ }
+ }
+ else {
+ if (smc->hw.fp.os_slots_used >= FPMAX_MULTICAST-SMT_MAX_MULTI) {
+ return(1) ;
+ }
+ }
+
+ /*
+ * find empty slot
+ */
+ if (!(tb = mac_get_mc_table(smc,addr,&own,0,can & ~0x80)))
+ return(1) ;
+ tb->n++ ;
+ tb->a = own ;
+ tb->perm = (can & 0x80) ? 1 : 0 ;
+
+ if (can & 0x80)
+ smc->hw.fp.smt_slots_used++ ;
+ else
+ smc->hw.fp.os_slots_used++ ;
+
+ return(0) ;
+}
+
+/*
+ BEGIN_MANUAL_ENTRY(if,func;others;2)
+
+ void mac_del_multicast(smc,addr,can)
+ struct s_smc *smc ;
+ struct fddi_addr *addr ;
+ int can ;
+
+Function DOWNCALL (SMT, fplustm.c)
+ Delete an entry from the multicast table
+
+Para addr pointer to a multicast address
+ can = 0: the multicast address has the physical format
+ = 1: the multicast address has the canonical format
+ | 0x80 permanent
+
+ END_MANUAL_ENTRY()
+ */
+void mac_del_multicast(smc,addr,can)
+struct s_smc *smc ;
+struct fddi_addr *addr ;
+int can ;
+{
+ SK_LOC_DECL(struct fddi_addr,own) ;
+ struct s_fpmc *tb ;
+
+ if (!(tb = mac_get_mc_table(smc,addr,&own,1,can & ~0x80)))
+ return ;
+ /*
+ * permanent addresses must be deleted with perm bit
+ * and vice versa
+ */
+ if (( tb->perm && (can & 0x80)) ||
+ (!tb->perm && !(can & 0x80))) {
+ /*
+ * delete it
+ */
+ if (tb->n) {
+ tb->n-- ;
+ if (tb->perm) {
+ smc->hw.fp.smt_slots_used-- ;
+ }
+ else {
+ smc->hw.fp.os_slots_used-- ;
+ }
+ }
+ }
+}
+
+/*
+ * mode
+ */
+
+#define RX_MODE_PROM 0x1
+#define RX_MODE_ALL_MULTI 0x2
+
+/*
+ BEGIN_MANUAL_ENTRY(if,func;others;2)
+
+ void mac_update_multicast(smc)
+ struct s_smc *smc ;
+
+Function DOWNCALL (SMT, fplustm.c)
+ Update FORMAC multicast registers
+
+ END_MANUAL_ENTRY()
+ */
+void mac_update_multicast(smc)
+struct s_smc *smc ;
+{
+ struct s_fpmc *tb ;
+ u_char *fu ;
+ int i ;
+
+ /*
+ * invalidate the CAM
+ */
+ outpw(FM_A(FM_AFCMD),FM_IINV_CAM) ;
+
+ /*
+ * set the functional address
+ */
+ if (smc->hw.fp.func_addr) {
+ fu = (u_char *) &smc->hw.fp.func_addr ;
+ outpw(FM_A(FM_AFMASK2),0xffff) ;
+ outpw(FM_A(FM_AFMASK1),(u_short) ~((fu[0] << 8) + fu[1])) ;
+ outpw(FM_A(FM_AFMASK0),(u_short) ~((fu[2] << 8) + fu[3])) ;
+ outpw(FM_A(FM_AFPERS),FM_VALID|FM_DA) ;
+ outpw(FM_A(FM_AFCOMP2), 0xc000) ;
+ outpw(FM_A(FM_AFCOMP1), 0x0000) ;
+ outpw(FM_A(FM_AFCOMP0), 0x0000) ;
+ outpw(FM_A(FM_AFCMD),FM_IWRITE_CAM) ;
+ }
+
+ /*
+ * set the mask and the personality register(s)
+ */
+ outpw(FM_A(FM_AFMASK0),0xffff) ;
+ outpw(FM_A(FM_AFMASK1),0xffff) ;
+ outpw(FM_A(FM_AFMASK2),0xffff) ;
+ outpw(FM_A(FM_AFPERS),FM_VALID|FM_DA) ;
+
+ for (i = 0, tb = smc->hw.fp.mc.table; i < FPMAX_MULTICAST; i++, tb++) {
+ if (tb->n) {
+ CHECK_CAM() ;
+
+ /*
+ * wirte the multicast addres into the CAM
+ */
+ outpw(FM_A(FM_AFCOMP2),
+ (u_short)((tb->a.a[0]<<8)+tb->a.a[1])) ;
+ outpw(FM_A(FM_AFCOMP1),
+ (u_short)((tb->a.a[2]<<8)+tb->a.a[3])) ;
+ outpw(FM_A(FM_AFCOMP0),
+ (u_short)((tb->a.a[4]<<8)+tb->a.a[5])) ;
+ outpw(FM_A(FM_AFCMD),FM_IWRITE_CAM) ;
+ }
+ }
+}
+
+/*
+ BEGIN_MANUAL_ENTRY(if,func;others;3)
+
+ void mac_set_rx_mode(smc,mode)
+ struct s_smc *smc ;
+ int mode ;
+
+Function DOWNCALL/INTERN (SMT, fplustm.c)
+ This function enables / disables the selected receive.
+ Don't call this function if the hardware module is
+ used -- use mac_drv_rx_mode() instead of.
+
+Para mode = 1 RX_ENABLE_ALLMULTI enable all multicasts
+ 2 RX_DISABLE_ALLMULTI disable "enable all multicasts"
+ 3 RX_ENABLE_PROMISC enable promiscous
+ 4 RX_DISABLE_PROMISC disable promiscous
+ 5 RX_ENABLE_NSA enable reception of NSA frames
+ 6 RX_DISABLE_NSA disable reception of NSA frames
+
+Note The selected receive modes will be lost after 'driver reset'
+ or 'set station address'
+
+ END_MANUAL_ENTRY
+ */
+void mac_set_rx_mode(smc,mode)
+struct s_smc *smc ;
+int mode ;
+{
+ switch (mode) {
+ case RX_ENABLE_ALLMULTI :
+ smc->hw.fp.rx_prom |= RX_MODE_ALL_MULTI ;
+ break ;
+ case RX_DISABLE_ALLMULTI :
+ smc->hw.fp.rx_prom &= ~RX_MODE_ALL_MULTI ;
+ break ;
+ case RX_ENABLE_PROMISC :
+ smc->hw.fp.rx_prom |= RX_MODE_PROM ;
+ break ;
+ case RX_DISABLE_PROMISC :
+ smc->hw.fp.rx_prom &= ~RX_MODE_PROM ;
+ break ;
+ case RX_ENABLE_NSA :
+ smc->hw.fp.nsa_mode = FM_MDAMA ;
+ smc->hw.fp.rx_mode = (smc->hw.fp.rx_mode & ~FM_ADDET) |
+ smc->hw.fp.nsa_mode ;
+ break ;
+ case RX_DISABLE_NSA :
+ smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ;
+ smc->hw.fp.rx_mode = (smc->hw.fp.rx_mode & ~FM_ADDET) |
+ smc->hw.fp.nsa_mode ;
+ break ;
+ }
+ if (smc->hw.fp.rx_prom & RX_MODE_PROM) {
+ smc->hw.fp.rx_mode = FM_MLIMPROM ;
+ }
+ else if (smc->hw.fp.rx_prom & RX_MODE_ALL_MULTI) {
+ smc->hw.fp.rx_mode = smc->hw.fp.nsa_mode | FM_EXGPA0 ;
+ }
+ else
+ smc->hw.fp.rx_mode = smc->hw.fp.nsa_mode ;
+ SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ;
+ mac_update_multicast(smc) ;
+}
+
+/*
+ BEGIN_MANUAL_ENTRY(module;tests;3)
+ How to test the Restricted Token Monitor
+ ----------------------------------------------------------------
+
+ o Insert a break point in the function rtm_irq()
+ o Remove all stations with a restricted token monitor from the
+ network.
+ o Connect a UPPS ISA or EISA station to the network.
+ o Give the FORMAC of UPPS station the command to send
+ restricted tokens until the ring becomes instable.
+ o Now connect your test test client.
+ o The restricted token monitor should detect the restricted token,
+ and your break point will be reached.
+ o You can ovserve how the station will clean the ring.
+
+ END_MANUAL_ENTRY
+ */
+void rtm_irq(smc)
+struct s_smc *smc ;
+{
+ outpw(ADDR(B2_RTM_CRTL),TIM_CL_IRQ) ; /* clear IRQ */
+ if (inpw(ADDR(B2_RTM_CRTL)) & TIM_RES_TOK) {
+ outpw(FM_A(FM_CMDREG1),FM_ICL) ; /* force claim */
+ DB_RMT("RMT: fddiPATHT_Rmode expired\n",0,0) ;
+ AIX_EVENT(smc, (u_long) FDDI_RING_STATUS,
+ (u_long) FDDI_SMT_EVENT,
+ (u_long) FDDI_RTT, smt_get_event_word(smc));
+ }
+ outpw(ADDR(B2_RTM_CRTL),TIM_START) ; /* enable RTM monitoring */
+}
+
+static void rtm_init(smc)
+struct s_smc *smc ;
+{
+ outpd(ADDR(B2_RTM_INI),0) ; /* timer = 0 */
+ outpw(ADDR(B2_RTM_CRTL),TIM_START) ; /* enable IRQ */
+}
+
+void rtm_set_timer(smc)
+struct s_smc *smc ;
+{
+ /*
+ * MIB timer and hardware timer have the same resolution of 80nS
+ */
+ DB_RMT("RMT: setting new fddiPATHT_Rmode, t = %d ns \n",
+ (int) smc->mib.a[PATH0].fddiPATHT_Rmode,0) ;
+ outpd(ADDR(B2_RTM_INI),smc->mib.a[PATH0].fddiPATHT_Rmode) ;
+}
+
+static void smt_split_up_fifo(smc)
+struct s_smc *smc ;
+{
+
+/*
+ BEGIN_MANUAL_ENTRY(module;mem;1)
+ -------------------------------------------------------------
+ RECEIVE BUFFER MEMORY DIVERSION
+ -------------------------------------------------------------
+
+ R1_RxD == SMT_R1_RXD_COUNT
+ R2_RxD == SMT_R2_RXD_COUNT
+
+ SMT_R1_RXD_COUNT must be unequal zero
+
+ | R1_RxD R2_RxD |R1_RxD R2_RxD | R1_RxD R2_RxD
+ | x 0 | x 1-3 | x < 3
+ ----------------------------------------------------------------------
+ | 63,75 kB | 54,75 | R1_RxD
+ rx queue 1 | RX_FIFO_SPACE | RX_LARGE_FIFO| ------------- * 63,75 kB
+ | | | R1_RxD+R2_RxD
+ ----------------------------------------------------------------------
+ | | 9 kB | R2_RxD
+ rx queue 2 | 0 kB | RX_SMALL_FIFO| ------------- * 63,75 kB
+ | (not used) | | R1_RxD+R2_RxD
+
+ END_MANUAL_ENTRY
+*/
+
+ if (SMT_R1_RXD_COUNT == 0) {
+ SMT_PANIC(smc,SMT_E0117, SMT_E0117_MSG) ;
+ }
+
+ switch(SMT_R2_RXD_COUNT) {
+ case 0:
+ smc->hw.fp.fifo.rx1_fifo_size = RX_FIFO_SPACE ;
+ smc->hw.fp.fifo.rx2_fifo_size = 0 ;
+ break ;
+ case 1:
+ case 2:
+ case 3:
+ smc->hw.fp.fifo.rx1_fifo_size = RX_LARGE_FIFO ;
+ smc->hw.fp.fifo.rx2_fifo_size = RX_SMALL_FIFO ;
+ break ;
+ default: /* this is not the real defaule */
+ smc->hw.fp.fifo.rx1_fifo_size = RX_FIFO_SPACE *
+ SMT_R1_RXD_COUNT/(SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT) ;
+ smc->hw.fp.fifo.rx2_fifo_size = RX_FIFO_SPACE *
+ SMT_R2_RXD_COUNT/(SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT) ;
+ break ;
+ }
+
+/*
+ BEGIN_MANUAL_ENTRY(module;mem;1)
+ -------------------------------------------------------------
+ TRANSMIT BUFFER MEMORY DIVERSION
+ -------------------------------------------------------------
+
+
+ | no sync bw | sync bw available and | sync bw available and
+ | available | SynchTxMode = SPLIT | SynchTxMode = ALL
+ -----------------------------------------------------------------------
+ sync tx | 0 kB | 32 kB | 55 kB
+ queue | | TX_MEDIUM_FIFO | TX_LARGE_FIFO
+ -----------------------------------------------------------------------
+ async tx | 64 kB | 32 kB | 9 k
+ queue | TX_FIFO_SPACE| TX_MEDIUM_FIFO | TX_SMALL_FIFO
+
+ END_MANUAL_ENTRY
+*/
+
+ /*
+ * set the tx mode bits
+ */
+ if (smc->mib.a[PATH0].fddiPATHSbaPayload) {
+#ifdef ESS
+ smc->hw.fp.fifo.fifo_config_mode |=
+ smc->mib.fddiESSSynchTxMode | SYNC_TRAFFIC_ON ;
+#endif
+ }
+ else {
+ smc->hw.fp.fifo.fifo_config_mode &=
+ ~(SEND_ASYNC_AS_SYNC|SYNC_TRAFFIC_ON) ;
+ }
+
+ /*
+ * split up the FIFO
+ */
+ if (smc->hw.fp.fifo.fifo_config_mode & SYNC_TRAFFIC_ON) {
+ if (smc->hw.fp.fifo.fifo_config_mode & SEND_ASYNC_AS_SYNC) {
+ smc->hw.fp.fifo.tx_s_size = TX_LARGE_FIFO ;
+ smc->hw.fp.fifo.tx_a0_size = TX_SMALL_FIFO ;
+ }
+ else {
+ smc->hw.fp.fifo.tx_s_size = TX_MEDIUM_FIFO ;
+ smc->hw.fp.fifo.tx_a0_size = TX_MEDIUM_FIFO ;
+ }
+ }
+ else {
+ smc->hw.fp.fifo.tx_s_size = 0 ;
+ smc->hw.fp.fifo.tx_a0_size = TX_FIFO_SPACE ;
+ }
+
+ smc->hw.fp.fifo.rx1_fifo_start = smc->hw.fp.fifo.rbc_ram_start +
+ RX_FIFO_OFF ;
+ smc->hw.fp.fifo.tx_s_start = smc->hw.fp.fifo.rx1_fifo_start +
+ smc->hw.fp.fifo.rx1_fifo_size ;
+ smc->hw.fp.fifo.tx_a0_start = smc->hw.fp.fifo.tx_s_start +
+ smc->hw.fp.fifo.tx_s_size ;
+ smc->hw.fp.fifo.rx2_fifo_start = smc->hw.fp.fifo.tx_a0_start +
+ smc->hw.fp.fifo.tx_a0_size ;
+
+ DB_SMT("FIFO split: mode = %x\n",smc->hw.fp.fifo.fifo_config_mode,0) ;
+ DB_SMT("rbc_ram_start = %x rbc_ram_end = %x\n",
+ smc->hw.fp.fifo.rbc_ram_start, smc->hw.fp.fifo.rbc_ram_end) ;
+ DB_SMT("rx1_fifo_start = %x tx_s_start = %x\n",
+ smc->hw.fp.fifo.rx1_fifo_start, smc->hw.fp.fifo.tx_s_start) ;
+ DB_SMT("tx_a0_start = %x rx2_fifo_start = %x\n",
+ smc->hw.fp.fifo.tx_a0_start, smc->hw.fp.fifo.rx2_fifo_start) ;
+}
+
+void formac_reinit_tx(smc)
+struct s_smc *smc ;
+{
+ /*
+ * Split up the FIFO and reinitialize the MAC if synchronous
+ * bandwidth becomes available but no synchronous queue is
+ * configured.
+ */
+ if (!smc->hw.fp.fifo.tx_s_size && smc->mib.a[PATH0].fddiPATHSbaPayload){
+ (void)init_mac(smc,0) ;
+ }
+}
+
+
diff --git a/drivers/net/skfp/h/cmtdef.h b/drivers/net/skfp/h/cmtdef.h
new file mode 100644
index 000000000..0b54c57ca
--- /dev/null
+++ b/drivers/net/skfp/h/cmtdef.h
@@ -0,0 +1,801 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef _CMTDEF_
+#define _CMTDEF_
+
+/* **************************************************************** */
+
+/*
+ * implementation specific constants
+ * MODIIFY THE FOLLWOING THREE DEFINES
+ */
+#define AMDPLC /* if Amd PLC chip used */
+#ifdef CONC
+#define NUMPHYS 12 /* 2 for SAS or DAS, more for Concentrator */
+#else
+#ifdef CONC_II
+#define NUMPHYS 24 /* 2 for SAS or DAS, more for Concentrator */
+#else
+#define NUMPHYS 2 /* 2 for SAS or DAS, more for Concentrator */
+#endif
+#endif
+#define NUMMACS 1 /* only 1 supported at the moment */
+#define NUMPATHS 2 /* primary and secondary path supported */
+
+/*
+ * DO NOT MODIFY BEYOND THIS POINT
+ */
+
+/* **************************************************************** */
+
+#if NUMPHYS > 2
+#define CONCENTRATOR
+#endif
+
+/*
+ * Definitions for comfortable LINT usage
+ */
+#ifdef lint
+#define LINT_USE(x) (x)=(x)
+#else
+#define LINT_USE(x)
+#endif
+
+#ifdef DEBUG
+#define DB_PR(flag,a,b,c) { if (flag) printf(a,b,c) ; }
+#else
+#define DB_PR(flag,a,b,c)
+#endif
+
+#ifdef DEBUG_BRD
+#define DB_ECM(a,b,c) DB_PR((smc->debug.d_smt&1),a,b,c)
+#define DB_ECMN(n,a,b,c) DB_PR((smc->debug.d_ecm >=(n)),a,b,c)
+#define DB_RMT(a,b,c) DB_PR((smc->debug.d_smt&2),a,b,c)
+#define DB_RMTN(n,a,b,c) DB_PR((smc->debug.d_rmt >=(n)),a,b,c)
+#define DB_CFM(a,b,c) DB_PR((smc->debug.d_smt&4),a,b,c)
+#define DB_CFMN(n,a,b,c) DB_PR((smc->debug.d_cfm >=(n)),a,b,c)
+#define DB_PCM(a,b,c) DB_PR((smc->debug.d_smt&8),a,b,c)
+#define DB_PCMN(n,a,b,c) DB_PR((smc->debug.d_pcm >=(n)),a,b,c)
+#define DB_SMT(a,b,c) DB_PR((smc->debug.d_smtf),a,b,c)
+#define DB_SMTN(n,a,b,c) DB_PR((smc->debug.d_smtf >=(n)),a,b,c)
+#define DB_SBA(a,b,c) DB_PR((smc->debug.d_sba),a,b,c)
+#define DB_SBAN(n,a,b,c) DB_PR((smc->debug.d_sba >=(n)),a,b,c)
+#define DB_ESS(a,b,c) DB_PR((smc->debug.d_ess),a,b,c)
+#define DB_ESSN(n,a,b,c) DB_PR((smc->debug.d_ess >=(n)),a,b,c)
+#else
+#define DB_ECM(a,b,c) DB_PR((debug.d_smt&1),a,b,c)
+#define DB_ECMN(n,a,b,c) DB_PR((debug.d_ecm >=(n)),a,b,c)
+#define DB_RMT(a,b,c) DB_PR((debug.d_smt&2),a,b,c)
+#define DB_RMTN(n,a,b,c) DB_PR((debug.d_rmt >=(n)),a,b,c)
+#define DB_CFM(a,b,c) DB_PR((debug.d_smt&4),a,b,c)
+#define DB_CFMN(n,a,b,c) DB_PR((debug.d_cfm >=(n)),a,b,c)
+#define DB_PCM(a,b,c) DB_PR((debug.d_smt&8),a,b,c)
+#define DB_PCMN(n,a,b,c) DB_PR((debug.d_pcm >=(n)),a,b,c)
+#define DB_SMT(a,b,c) DB_PR((debug.d_smtf),a,b,c)
+#define DB_SMTN(n,a,b,c) DB_PR((debug.d_smtf >=(n)),a,b,c)
+#define DB_SBA(a,b,c) DB_PR((debug.d_sba),a,b,c)
+#define DB_SBAN(n,a,b,c) DB_PR((debug.d_sba >=(n)),a,b,c)
+#define DB_ESS(a,b,c) DB_PR((debug.d_ess),a,b,c)
+#define DB_ESSN(n,a,b,c) DB_PR((debug.d_ess >=(n)),a,b,c)
+#endif
+
+#ifndef SS_NOT_DS
+#define SK_LOC_DECL(type,var) type var
+#else
+#define SK_LOC_DECL(type,var) static type var
+#endif
+/*
+ * PHYs and PORTS
+ * Note: Don't touch the definition of PA and PB. Those might be used
+ * by some "for" loops.
+ */
+#define PA 0
+#define PB 1
+#if defined(SUPERNET_3) || defined(CONC_II)
+/*
+ * The port indices have to be different,
+ * because the MAC output goes through the 2. PLC
+ * Conc II: It has to be the first port in the row.
+ */
+#define PS 0 /* Internal PLC which is the same as PA */
+#else
+#define PS 1
+#endif
+#define PM 2 /* PM .. PA+NUM_PHYS-1 */
+
+/*
+ * PHY types - as in path descriptor 'fddiPHYType'
+ */
+#define TA 0 /* A port */
+#define TB 1 /* B port */
+#define TS 2 /* S port */
+#define TM 3 /* M port */
+#define TNONE 4
+
+
+/*
+ * indexes in MIB
+ */
+#define INDEX_MAC 1
+#define INDEX_PATH 1
+#define INDEX_PORT 1
+
+
+/*
+ * policies
+ */
+#define POLICY_AA (1<<0) /* reject AA */
+#define POLICY_AB (1<<1) /* reject AB */
+#define POLICY_AS (1<<2) /* reject AS */
+#define POLICY_AM (1<<3) /* reject AM */
+#define POLICY_BA (1<<4) /* reject BA */
+#define POLICY_BB (1<<5) /* reject BB */
+#define POLICY_BS (1<<6) /* reject BS */
+#define POLICY_BM (1<<7) /* reject BM */
+#define POLICY_SA (1<<8) /* reject SA */
+#define POLICY_SB (1<<9) /* reject SB */
+#define POLICY_SS (1<<10) /* reject SS */
+#define POLICY_SM (1<<11) /* reject SM */
+#define POLICY_MA (1<<12) /* reject MA */
+#define POLICY_MB (1<<13) /* reject MB */
+#define POLICY_MS (1<<14) /* reject MS */
+#define POLICY_MM (1<<15) /* reject MM */
+
+/*
+ * commands
+ */
+
+/*
+ * EVENTS
+ * event classes
+ */
+#define EVENT_ECM 1 /* event class ECM */
+#define EVENT_CFM 2 /* event class CFM */
+#define EVENT_RMT 3 /* event class RMT */
+#define EVENT_SMT 4 /* event class SMT */
+#define EVENT_PCM 5 /* event class PCM */
+#define EVENT_PCMA 5 /* event class PCMA */
+#define EVENT_PCMB 6 /* event class PCMB */
+
+/* WARNING :
+ * EVENT_PCM* must be last in the above list
+ * if more then two ports are used, EVENT_PCM .. EVENT_PCMA+NUM_PHYS-1
+ * are used !
+ */
+
+#define EV_TOKEN(class,event) (((u_long)(class)<<16L)|((u_long)(event)))
+#define EV_T_CLASS(token) ((int)((token)>>16)&0xffff)
+#define EV_T_EVENT(token) ((int)(token)&0xffff)
+
+/*
+ * ECM events
+ */
+#define EC_CONNECT 1 /* connect request */
+#define EC_DISCONNECT 2 /* disconnect request */
+#define EC_TRACE_PROP 3 /* trace propagation */
+#define EC_PATH_TEST 4 /* path test */
+#define EC_TIMEOUT_TD 5 /* timer TD_min */
+#define EC_TIMEOUT_TMAX 6 /* timer trace_max */
+#define EC_TIMEOUT_IMAX 7 /* timer I_max */
+#define EC_TIMEOUT_INMAX 8 /* timer IN_max */
+#define EC_TEST_DONE 9 /* path test done */
+
+/*
+ * CFM events
+ */
+#define CF_LOOP 1 /* cf_loop flag from PCM */
+#define CF_LOOP_A 1 /* cf_loop flag from PCM */
+#define CF_LOOP_B 2 /* cf_loop flag from PCM */
+#define CF_JOIN 3 /* cf_join flag from PCM */
+#define CF_JOIN_A 3 /* cf_join flag from PCM */
+#define CF_JOIN_B 4 /* cf_join flag from PCM */
+
+/*
+ * PCM events
+ */
+#define PC_START 1
+#define PC_STOP 2
+#define PC_LOOP 3
+#define PC_JOIN 4
+#define PC_SIGNAL 5
+#define PC_REJECT 6
+#define PC_MAINT 7
+#define PC_TRACE 8
+#define PC_PDR 9
+#define PC_ENABLE 10
+#define PC_DISABLE 11
+
+/*
+ * must be ordered as in LineStateType
+ */
+#define PC_QLS 12
+#define PC_ILS 13
+#define PC_MLS 14
+#define PC_HLS 15
+#define PC_LS_PDR 16
+#define PC_LS_NONE 17
+#define LS2MIB(x) ((x)-PC_QLS)
+#define MIB2LS(x) ((x)+PC_QLS)
+
+#define PC_TIMEOUT_TB_MAX 18 /* timer TB_max */
+#define PC_TIMEOUT_TB_MIN 19 /* timer TB_min */
+#define PC_TIMEOUT_C_MIN 20 /* timer C_Min */
+#define PC_TIMEOUT_T_OUT 21 /* timer T_Out */
+#define PC_TIMEOUT_TL_MIN 22 /* timer TL_Min */
+#define PC_TIMEOUT_T_NEXT 23 /* timer t_next[] */
+#define PC_TIMEOUT_LCT 24
+#define PC_NSE 25 /* NOISE hardware timer */
+#define PC_LEM 26 /* LEM done */
+
+/*
+ * RMT events meaning from
+ */
+#define RM_RING_OP 1 /* ring operational MAC */
+#define RM_RING_NON_OP 2 /* ring not operational MAC */
+#define RM_MY_BEACON 3 /* recvd my beacon MAC */
+#define RM_OTHER_BEACON 4 /* recvd other beacon MAC */
+#define RM_MY_CLAIM 5 /* recvd my claim MAC */
+#define RM_TRT_EXP 6 /* TRT exp MAC */
+#define RM_VALID_CLAIM 7 /* claim from dup addr MAC */
+#define RM_JOIN 8 /* signal rm_join CFM */
+#define RM_LOOP 9 /* signal rm_loop CFM */
+#define RM_DUP_ADDR 10 /* dup_addr_test hange SMT-NIF */
+#define RM_ENABLE_FLAG 11 /* enable flag */
+
+#define RM_TIMEOUT_NON_OP 12 /* timeout T_Non_OP */
+#define RM_TIMEOUT_T_STUCK 13 /* timeout T_Stuck */
+#define RM_TIMEOUT_ANNOUNCE 14 /* timeout T_Announce */
+#define RM_TIMEOUT_T_DIRECT 15 /* timeout T_Direct */
+#define RM_TIMEOUT_D_MAX 16 /* timeout D_Max */
+#define RM_TIMEOUT_POLL 17 /* claim/beacon poller */
+#define RM_TX_STATE_CHANGE 18 /* To restart timer for D_Max */
+
+/*
+ * SMT events
+ */
+#define SM_TIMER 1 /* timer */
+#define SM_FAST 2 /* smt_force_irq */
+
+/* PC modes */
+#define PM_NONE 0
+#define PM_PEER 1
+#define PM_TREE 2
+
+/*
+ * PCM withhold codes
+ * MIB PC-WithholdType ENUM
+ */
+#define PC_WH_NONE 0 /* ok */
+#define PC_WH_M_M 1 /* M to M */
+#define PC_WH_OTHER 2 /* other incompatible phys */
+#define PC_WH_PATH 3 /* path not available */
+/*
+ * LCT duration
+ */
+#define LC_SHORT 1 /* short LCT */
+#define LC_MEDIUM 2 /* medium LCT */
+#define LC_LONG 3 /* long LCT */
+#define LC_EXTENDED 4 /* extended LCT */
+
+/*
+ * path_test values
+ */
+#define PT_NONE 0
+#define PT_TESTING 1 /* test is running */
+#define PT_PASSED 2 /* test passed */
+#define PT_FAILED 3 /* test failed */
+#define PT_PENDING 4 /* path test follows */
+#define PT_EXITING 5 /* disconnected while in trace/leave */
+
+/*
+ * duplicate address test
+ * MIB DupAddressTest ENUM
+ */
+#define DA_NONE 0 /* */
+#define DA_PASSED 1 /* test passed */
+#define DA_FAILED 2 /* test failed */
+
+
+/*
+ * optical bypass
+ */
+#define BP_DEINSERT 0 /* disable bypass */
+#define BP_INSERT 1 /* enable bypass */
+
+/*
+ * ODL enable/disable
+ */
+#define PM_TRANSMIT_DISABLE 0 /* disable xmit */
+#define PM_TRANSMIT_ENABLE 1 /* enable xmit */
+
+/*
+ * parameter for config_mux
+ * note : number is index in config_endec table !
+ */
+#define MUX_THRUA 0 /* through A */
+#define MUX_THRUB 1 /* through B */
+#define MUX_WRAPA 2 /* wrap A */
+#define MUX_WRAPB 3 /* wrap B */
+#define MUX_ISOLATE 4 /* isolated */
+#define MUX_WRAPS 5 /* SAS */
+
+/*
+ * MAC control
+ */
+#define MA_RESET 0
+#define MA_BEACON 1
+#define MA_CLAIM 2
+#define MA_DIRECTED 3 /* directed beacon */
+#define MA_TREQ 4 /* change T_Req */
+#define MA_OFFLINE 5 /* switch MAC to offline */
+
+
+/*
+ * trace prop
+ * bit map for trace propagation
+ */
+#define ENTITY_MAC (NUMPHYS)
+#define ENTITY_PHY(p) (p)
+#define ENTITY_BIT(m) (1<<(m))
+
+/*
+ * Resource Tag Types
+ */
+#define PATH_ISO 0 /* isolated */
+#define PATH_PRIM 3 /* primary path */
+#define PATH_THRU 5 /* through path */
+
+#define RES_MAC 2 /* resource type MAC */
+#define RES_PORT 4 /* resource type PORT */
+
+
+/*
+ * CFM state
+ * oops: MUST MATCH CF-StateType in SMT7.2 !
+ */
+#define SC0_ISOLATED 0 /* isolated */
+#define SC1_WRAP_A 5 /* wrap A (not used) */
+#define SC2_WRAP_B 6 /* wrap B (not used) */
+#define SC4_THRU_A 12 /* through A */
+#define SC5_THRU_B 7 /* through B (used in SMT 6.2) */
+#define SC7_WRAP_S 8 /* SAS (not used) */
+#define SC9_C_WRAP_A 9 /* c wrap A */
+#define SC10_C_WRAP_B 10 /* c wrap B */
+#define SC11_C_WRAP_S 11 /* c wrap S */
+
+/*
+ * convert MIB time in units of 80nS to uS
+ */
+#define MIB2US(t) ((t)/12)
+#define SEC2MIB(s) ((s)*12500000L)
+/*
+ * SMT timer
+ */
+struct smt_timer {
+ struct smt_timer *tm_next ; /* linked list */
+ struct s_smc *tm_smc ; /* pointer to context */
+ u_long tm_delta ; /* delta time */
+ u_long tm_token ; /* token value */
+ u_short tm_active ; /* flag : active/inactive */
+ u_short tm_pad ; /* pad field */
+} ;
+
+/*
+ * communication structures
+ */
+struct mac_parameter {
+ u_long t_neg ; /* T_Neg parameter */
+ u_long t_pri ; /* T_Pri register in MAC */
+} ;
+
+/*
+ * MAC counters
+ */
+struct mac_counter {
+ u_long mac_nobuf_counter ; /* MAC SW counter: no buffer */
+ u_long mac_r_restart_counter ; /* MAC SW counter: rx restarted */
+} ;
+
+/*
+ * para struct context for SMT parameters
+ */
+struct s_pcon {
+ int pc_len ;
+ int pc_err ;
+ int pc_badset ;
+ void *pc_p ;
+} ;
+
+
+/*
+ * link error monitor
+ */
+#define LEM_AVG 5
+struct lem_counter {
+#ifdef AM29K
+ int lem_on ;
+ u_long lem_errors ;
+ u_long lem_symbols ;
+ u_long lem_tsymbols ;
+ int lem_s_count ;
+ int lem_n_s ;
+ int lem_values ;
+ int lem_index ;
+ int lem_avg_ber[LEM_AVG] ;
+ int lem_sum ;
+#else
+ u_short lem_float_ber ; /* 10E-nn bit error rate */
+ u_long lem_errors ; /* accumulated error count */
+ u_short lem_on ;
+#endif
+} ;
+
+#define NUMBITS 10
+
+
+#ifdef AMDPLC
+
+/*
+ * PLC state table
+ */
+struct s_plc {
+ u_short p_state ; /* current state */
+ u_short p_bits ; /* number of bits to send */
+ u_short p_start ; /* first bit pos */
+ u_short p_pad ; /* padding for alignment */
+ u_long soft_err ; /* error counter */
+ u_long parity_err ; /* error counter */
+ u_long ebuf_err ; /* error counter */
+ u_long ebuf_cont ; /* continous error counter */
+ u_long phyinv ; /* error counter */
+ u_long vsym_ctr ; /* error counter */
+ u_long mini_ctr ; /* error counter */
+ u_long tpc_exp ; /* error counter */
+ u_long np_err ; /* error counter */
+ u_long b_pcs ; /* error counter */
+ u_long b_tpc ; /* error counter */
+ u_long b_tne ; /* error counter */
+ u_long b_qls ; /* error counter */
+ u_long b_ils ; /* error counter */
+ u_long b_hls ; /* error counter */
+} ;
+#endif
+
+#ifdef PROTOTYP_INC
+#include "fddi/driver.pro"
+#else /* PROTOTYP_INC */
+/*
+ * function prototypes
+ */
+#include "h/mbuf.h" /* Type definitions for MBUFs */
+void hwt_restart( /* hwt.c */
+#ifdef ANSIC
+ struct s_smc *smc
+#endif
+ ) ;
+
+SMbuf *smt_build_frame( /* smt.c */
+#ifdef ANSIC
+ struct s_smc *smc,
+ int class,
+ int type,
+ int length
+#endif
+ ) ;
+
+SMbuf *smt_get_mbuf( /* drvsr.c */
+#ifdef ANSIC
+ struct s_smc *smc
+#endif
+ ) ;
+
+void *sm_to_para( /* smt.c */
+#ifdef ANSIC
+ struct s_smc *smc,
+ struct smt_header *sm,
+ int para
+#endif
+ ) ;
+
+#ifndef SK_UNUSED
+#define SK_UNUSED(var) (void)(var)
+#endif
+
+void queue_event() ;
+void ecm() ;
+void ecm_init() ;
+void rmt() ;
+void rmt_init() ;
+void pcm() ;
+void pcm_init() ;
+void cfm() ;
+void cfm_init() ;
+void smt_timer_start() ;
+void smt_timer_stop() ;
+void pcm_status_state() ;
+void plc_config_mux() ;
+void sm_lem_evaluate() ;
+void smt_clear_una_dna() ;
+void mac_status_para() ;
+void mac_update_counter() ;
+void sm_pm_ls_latch() ;
+void sm_ma_control() ;
+void sm_mac_check_beacon_claim() ;
+void config_mux() ;
+void smt_agent_init() ;
+void smt_timer_init() ;
+void smt_received_pack() ;
+void smt_add_para() ;
+void smt_swap_para() ;
+void ev_init() ;
+void hwt_init() ;
+u_long hwt_read() ;
+void hwt_stop() ;
+void hwt_start() ;
+void smt_send_mbuf() ;
+void smt_free_mbuf() ;
+void sm_pm_bypass_req() ;
+void rmt_indication() ;
+void cfm_state_change() ;
+void rx_indication() ;
+void tx_indication() ;
+#ifndef NO_SMT_PANIC
+void smt_panic() ;
+#else
+#ifdef DEBUG
+void smt_panic() ;
+#else
+#define smt_panic(smc,text)
+#endif /* DEBUG */
+#endif /* NO_SMT_PANIC */
+void smt_stat_counter() ;
+void smt_timer_poll() ;
+u_long smt_get_time() ;
+u_long smt_get_tid() ;
+void smt_timer_done() ;
+void smt_set_defaults() ;
+void smt_fixup_mib() ;
+void smt_reset_defaults() ;
+void smt_agent_task() ;
+void smt_please_reconnect() ;
+int smt_check_para() ;
+void driver_get_bia() ;
+#ifdef SUPERNET_3
+void drv_reset_indication() ;
+#endif /* SUPERNET_3 */
+void smt_start_watchdog() ;
+
+void smt_event() ;
+void pcm_event() ;
+void rmt_event() ;
+void cfm_event() ;
+void timer_event() ;
+void ev_dispatcher() ;
+
+void smt_get_state() ;
+void ecm_get_state() ;
+void pcm_get_state() ;
+void rmt_get_state() ;
+
+void ecm_state_change() ;
+int sm_pm_bypass_present() ;
+void pcm_state_change() ;
+void rmt_state_change() ;
+int sm_pm_get_ls() ;
+int pcm_get_s_port() ;
+int pcm_rooted_station() ;
+int cfm_get_mac_input() ;
+int cfm_get_mac_output() ;
+int port_to_mib() ;
+int cem_build_path() ;
+int sm_mac_get_tx_state() ;
+int is_individual() ;
+int is_my_addr() ;
+int is_broadcast() ;
+int is_equal() ;
+char *get_pcmstate() ;
+
+int smt_action() ;
+u_short smt_online() ;
+void smt_force_irq() ;
+void smt_pmf_received_pack() ;
+void smt_send_frame() ;
+void smt_set_timestamp() ;
+void mac_set_rx_mode() ;
+int mac_add_multicast() ;
+int mac_set_func_addr() ;
+void mac_del_multicast() ;
+void mac_update_multicast() ;
+void mac_clear_multicast() ;
+void mac_rx_directed_beacon() ;
+void set_formac_tsync() ;
+void formac_reinit_tx() ;
+void formac_tx_restart() ;
+void process_receive() ;
+void init_driver_fplus() ;
+
+void rtm_irq() ;
+void rtm_set_timer() ;
+void ring_status_indication() ;
+void llc_recover_tx() ;
+void llc_restart_tx() ;
+void plc_clear_irq() ;
+void plc_irq() ;
+int smt_set_mac_opvalues() ;
+#ifdef TAG_MODE
+void mac_drv_pci_fix() ;
+void mac_do_pci_fix() ;
+void mac_drv_clear_tx_queue() ;
+void mac_drv_repair_descr() ;
+u_long hwt_quick_read() ;
+void hwt_wait_time() ;
+#endif
+
+#ifdef SMT_PNMI
+#ifdef ANSIC
+int pnmi_init (struct s_smc* smc);
+int pnmi_process_ndis_id (struct s_smc* smc, u_long ndis_oid, void* buf,
+ int len, int* BytesAccessed, int* BytesNeeded, u_char action);
+#else
+int pnmi_init ();
+int pnmi_process_ndis_id ();
+#endif
+#endif
+
+#ifdef SBA
+#ifndef _H2INC
+void sba() ;
+#endif
+void sba_raf_received_pack() ;
+void sba_timer_poll() ;
+void smt_init_sba() ;
+#endif
+#ifdef ESS
+int ess_raf_received_pack() ;
+void ess_timer_poll() ;
+void ess_para_change() ;
+#endif
+
+#ifdef BOOT
+#define smt_srf_event(a,b,c,d)
+#define smt_init_evc(a)
+#else
+void smt_init_evc() ;
+void smt_srf_event() ;
+#endif
+
+#ifndef SMT_REAL_TOKEN_CT
+void smt_emulate_token_ct();
+#endif
+
+#if defined(DEBUG) && !defined(BOOT)
+void dump_smt() ;
+#else
+#define dump_smt(smc,sm,text)
+#endif
+
+#ifdef DEBUG
+char *addr_to_string() ;
+void dump_hex() ;
+#endif
+#endif /* PROTOTYP_INC */
+
+/* PNMI default defines */
+#ifndef PNMI_INIT
+#define PNMI_INIT(smc) /* Nothing */
+#endif
+#ifndef PNMI_GET_ID
+#define PNMI_GET_ID( smc, ndis_oid, buf, len, BytesWritten, BytesNeeded ) \
+ ( 1 ? (-1) : (-1) )
+#endif
+#ifndef PNMI_SET_ID
+#define PNMI_SET_ID( smc, ndis_oid, buf, len, BytesRead, BytesNeeded, \
+ set_type) ( 1 ? (-1) : (-1) )
+#endif
+
+/*
+ * SMT_PANIC defines
+ */
+#ifndef SMT_PANIC
+#define SMT_PANIC(smc,nr,msg) smt_panic (smc, msg)
+#endif
+
+#ifndef SMT_ERR_LOG
+#define SMT_ERR_LOG(smc,nr,msg) SMT_PANIC (smc, nr, msg)
+#endif
+
+#ifndef SMT_EBASE
+#define SMT_EBASE 100
+#endif
+
+#define SMT_E0100 SMT_EBASE + 0
+#define SMT_E0100_MSG "cfm FSM: illegal ce_type"
+#define SMT_E0101 SMT_EBASE + 1
+#define SMT_E0101_MSG "CEM: case ???"
+#define SMT_E0102 SMT_EBASE + 2
+#define SMT_E0102_MSG "CEM A: illegal state"
+#define SMT_E0103 SMT_EBASE + 3
+#define SMT_E0103_MSG "CEM B: illegal state"
+#define SMT_E0104 SMT_EBASE + 4
+#define SMT_E0104_MSG "CEM M: illegal state"
+#define SMT_E0105 SMT_EBASE + 5
+#define SMT_E0105_MSG "CEM S: illegal state"
+#define SMT_E0106 SMT_EBASE + 6
+#define SMT_E0106_MSG "CFM : illegal state"
+#define SMT_E0107 SMT_EBASE + 7
+#define SMT_E0107_MSG "ECM : illegal state"
+#define SMT_E0108 SMT_EBASE + 8
+#define SMT_E0108_MSG "prop_actions : NAC in DAS CFM"
+#define SMT_E0109 SMT_EBASE + 9
+#define SMT_E0109_MSG "ST2U.FM_SERRSF error in special frame"
+#define SMT_E0110 SMT_EBASE + 10
+#define SMT_E0110_MSG "ST2U.FM_SRFRCTOV recv. count. overflow"
+#define SMT_E0111 SMT_EBASE + 11
+#define SMT_E0111_MSG "ST2U.FM_SNFSLD NP & FORMAC simult. load"
+#define SMT_E0112 SMT_EBASE + 12
+#define SMT_E0112_MSG "ST2U.FM_SRCVFRM single-frame recv.-mode"
+#define SMT_E0113 SMT_EBASE + 13
+#define SMT_E0113_MSG "FPLUS: Buffer Memory Error"
+#define SMT_E0114 SMT_EBASE + 14
+#define SMT_E0114_MSG "ST2U.FM_SERRSF error in special frame"
+#define SMT_E0115 SMT_EBASE + 15
+#define SMT_E0115_MSG "ST3L: parity error in receive queue 2"
+#define SMT_E0116 SMT_EBASE + 16
+#define SMT_E0116_MSG "ST3L: parity error in receive queue 1"
+#define SMT_E0117 SMT_EBASE + 17
+#define SMT_E0117_MSG "E_SMT_001: RxD count for receive queue 1 = 0"
+#define SMT_E0118 SMT_EBASE + 18
+#define SMT_E0118_MSG "PCM : illegal state"
+#define SMT_E0119 SMT_EBASE + 19
+#define SMT_E0119_MSG "smt_add_para"
+#define SMT_E0120 SMT_EBASE + 20
+#define SMT_E0120_MSG "smt_set_para"
+#define SMT_E0121 SMT_EBASE + 21
+#define SMT_E0121_MSG "illegal event in dispatcher"
+#define SMT_E0122 SMT_EBASE + 22
+#define SMT_E0122_MSG "RMT : illegal state"
+#define SMT_E0123 SMT_EBASE + 23
+#define SMT_E0123_MSG "SBA: state machine has illegal state"
+#define SMT_E0124 SMT_EBASE + 24
+#define SMT_E0124_MSG "sba_free_session() called with NULL pointer"
+#define SMT_E0125 SMT_EBASE + 25
+#define SMT_E0125_MSG "SBA : illegal session pointer"
+#define SMT_E0126 SMT_EBASE + 26
+#define SMT_E0126_MSG "smt_free_mbuf() called with NULL pointer\n"
+#define SMT_E0127 SMT_EBASE + 27
+#define SMT_E0127_MSG "sizeof evcs"
+#define SMT_E0128 SMT_EBASE + 28
+#define SMT_E0128_MSG "evc->evc_cond_state = 0"
+#define SMT_E0129 SMT_EBASE + 29
+#define SMT_E0129_MSG "evc->evc_multiple = 0"
+#define SMT_E0130 SMT_EBASE + 30
+#define SMT_E0130_MSG write_mdr_warning
+#define SMT_E0131 SMT_EBASE + 31
+#define SMT_E0131_MSG cam_warning
+#define SMT_E0132 SMT_EBASE + 32
+#define SMT_E0132_MSG "ST1L.FM_SPCEPDx parity/coding error"
+#define SMT_E0133 SMT_EBASE + 33
+#define SMT_E0133_MSG "ST1L.FM_STBURx tx buffer underrun"
+#define SMT_E0134 SMT_EBASE + 34
+#define SMT_E0134_MSG "ST1L.FM_SPCEPDx parity error"
+#define SMT_E0135 SMT_EBASE + 35
+#define SMT_E0135_MSG "RMT: duplicate MAC address detected. Ring left!"
+#define SMT_E0136 SMT_EBASE + 36
+#define SMT_E0136_MSG "Elasticity Buffer hang-up"
+#define SMT_E0137 SMT_EBASE + 37
+#define SMT_E0137_MSG "SMT: queue overrun"
+#define SMT_E0138 SMT_EBASE + 38
+#define SMT_E0138_MSG "RMT: duplicate MAC address detected. Ring NOT left!"
+#endif /* _CMTDEF_ */
diff --git a/drivers/net/skfp/h/fddi.h b/drivers/net/skfp/h/fddi.h
new file mode 100644
index 000000000..c9a28a8a3
--- /dev/null
+++ b/drivers/net/skfp/h/fddi.h
@@ -0,0 +1,69 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef _FDDI_
+#define _FDDI_
+
+struct fddi_addr {
+ u_char a[6] ;
+} ;
+
+#define GROUP_ADDR 0x80 /* MSB in a[0] */
+
+struct fddi_mac {
+ struct fddi_addr mac_dest ;
+ struct fddi_addr mac_source ;
+ u_char mac_info[4478] ;
+} ;
+
+#define FDDI_MAC_SIZE (12)
+#define FDDI_RAW_MTU (4500-5) /* exl. Pr,SD, ED/FS */
+#define FDDI_RAW (4500)
+
+/*
+ * FC values
+ */
+#define FC_VOID 0x40 /* void frame */
+#define FC_TOKEN 0x80 /* token */
+#define FC_RES_TOKEN 0xc0 /* restricted token */
+#define FC_SMT_INFO 0x41 /* SMT Info frame */
+/*
+ * FC_SMT_LAN_LOC && FC_SMT_LOC are SK specific !
+ */
+#define FC_SMT_LAN_LOC 0x42 /* local SMT Info frame */
+#define FC_SMT_LOC 0x43 /* local SMT Info frame */
+#define FC_SMT_NSA 0x4f /* SMT NSA frame */
+#define FC_MAC 0xc0 /* MAC frame */
+#define FC_BEACON 0xc2 /* MAC beacon frame */
+#define FC_CLAIM 0xc3 /* MAC claim frame */
+#define FC_SYNC_LLC 0xd0 /* sync. LLC frame */
+#define FC_ASYNC_LLC 0x50 /* async. LLC frame */
+#define FC_SYNC_BIT 0x80 /* sync. bit in FC */
+
+#define FC_LLC_PRIOR 0x07 /* priority bits */
+
+#define BEACON_INFO 0 /* beacon type */
+#define DBEACON_INFO 1 /* beacon type DIRECTED */
+
+
+/*
+ * indicator bits
+ */
+#define C_INDICATOR (1<<0)
+#define A_INDICATOR (1<<1)
+#define E_INDICATOR (1<<2)
+#define I_INDICATOR (1<<6) /* SK specific */
+#define L_INDICATOR (1<<7) /* SK specific */
+
+#endif /* _FDDI_ */
diff --git a/drivers/net/skfp/h/fddimib.h b/drivers/net/skfp/h/fddimib.h
new file mode 100644
index 000000000..d1acdc773
--- /dev/null
+++ b/drivers/net/skfp/h/fddimib.h
@@ -0,0 +1,349 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * FDDI MIB
+ */
+
+/*
+ * typedefs
+ */
+
+typedef u_long Counter ;
+typedef u_char TimeStamp[8] ;
+typedef struct fddi_addr LongAddr ;
+typedef u_long Timer_2 ;
+typedef u_long Timer ;
+typedef u_short ResId ;
+typedef u_short SMTEnum ;
+typedef u_char SMTFlag ;
+
+typedef struct {
+ Counter count ;
+ TimeStamp timestamp ;
+} SetCountType ;
+
+/*
+ * bits for bit string "available_path"
+ */
+#define MIB_PATH_P (1<<0)
+#define MIB_PATH_S (1<<1)
+#define MIB_PATH_L (1<<2)
+
+/*
+ * bits for bit string PermittedPaths & RequestedPaths (SIZE(8))
+ */
+#define MIB_P_PATH_LOCAL (1<<0)
+#define MIB_P_PATH_SEC_ALTER (1<<1)
+#define MIB_P_PATH_PRIM_ALTER (1<<2)
+#define MIB_P_PATH_CON_ALTER (1<<3)
+#define MIB_P_PATH_SEC_PREFER (1<<4)
+#define MIB_P_PATH_PRIM_PREFER (1<<5)
+#define MIB_P_PATH_CON_PREFER (1<<6)
+#define MIB_P_PATH_THRU (1<<7)
+
+/*
+ * enum current path
+ */
+#define MIB_PATH_ISOLATED 0
+#define MIB_PATH_LOCAL 1
+#define MIB_PATH_SECONDARY 2
+#define MIB_PATH_PRIMARY 3
+#define MIB_PATH_CONCATENATED 4
+#define MIB_PATH_THRU 5
+
+/*
+ * enum PMDClass
+ */
+#define MIB_PMDCLASS_MULTI 0
+#define MIB_PMDCLASS_SINGLE1 1
+#define MIB_PMDCLASS_SINGLE2 2
+#define MIB_PMDCLASS_SONET 3
+#define MIB_PMDCLASS_LCF 4
+#define MIB_PMDCLASS_TP 5
+#define MIB_PMDCLASS_UNKNOWN 6
+#define MIB_PMDCLASS_UNSPEC 7
+
+/*
+ * enum SMTStationStatus
+ */
+#define MIB_SMT_STASTA_CON 0
+#define MIB_SMT_STASTA_SEPA 1
+#define MIB_SMT_STASTA_THRU 2
+
+
+struct fddi_mib {
+ /*
+ * private
+ */
+ u_char fddiPRPMFPasswd[8] ;
+ struct smt_sid fddiPRPMFStation ;
+
+#ifdef ESS
+ /*
+ * private variables for static allocation of the
+ * End Station Support
+ */
+ u_long fddiESSPayload ; /* payload for static alloc */
+ u_long fddiESSOverhead ; /* frame ov for static alloc */
+ u_long fddiESSMaxTNeg ; /* maximum of T-NEG */
+ u_long fddiESSMinSegmentSize ; /* min size of the sync frames */
+ u_long fddiESSCategory ; /* category for the Alloc req */
+ short fddiESSSynchTxMode ; /* send all LLC frames as sync */
+#endif /* ESS */
+#ifdef SBA
+ /*
+ * private variables for the Synchronous Bandwidth Allocator
+ */
+ char fddiSBACommand ; /* holds the parsed SBA cmd */
+ u_char fddiSBAAvailable ; /* SBA allocatable value */
+#endif /* SBA */
+
+ /*
+ * SMT standard mib
+ */
+ struct smt_sid fddiSMTStationId ;
+ u_short fddiSMTOpVersionId ;
+ u_short fddiSMTHiVersionId ;
+ u_short fddiSMTLoVersionId ;
+ u_char fddiSMTManufacturerData[32] ;
+ u_char fddiSMTUserData[32] ;
+ u_short fddiSMTMIBVersionId ;
+
+ /*
+ * ConfigGrp
+ */
+ u_char fddiSMTMac_Ct ;
+ u_char fddiSMTNonMaster_Ct ;
+ u_char fddiSMTMaster_Ct ;
+ u_char fddiSMTAvailablePaths ;
+ u_short fddiSMTConfigCapabilities ;
+ u_short fddiSMTConfigPolicy ;
+ u_short fddiSMTConnectionPolicy ;
+ u_short fddiSMTTT_Notify ;
+ u_char fddiSMTStatRptPolicy ;
+ u_long fddiSMTTrace_MaxExpiration ;
+ u_short fddiSMTPORTIndexes[NUMPHYS] ;
+ u_short fddiSMTMACIndexes ;
+ u_char fddiSMTBypassPresent ;
+
+ /*
+ * StatusGrp
+ */
+ SMTEnum fddiSMTECMState ;
+ SMTEnum fddiSMTCF_State ;
+ SMTEnum fddiSMTStationStatus ;
+ u_char fddiSMTRemoteDisconnectFlag ;
+ u_char fddiSMTPeerWrapFlag ;
+
+ /*
+ * MIBOperationGrp
+ */
+ TimeStamp fddiSMTTimeStamp ;
+ TimeStamp fddiSMTTransitionTimeStamp ;
+ SetCountType fddiSMTSetCount ;
+ struct smt_sid fddiSMTLastSetStationId ;
+
+ struct fddi_mib_m {
+ u_short fddiMACFrameStatusFunctions ;
+ Timer_2 fddiMACT_MaxCapabilitiy ;
+ Timer_2 fddiMACTVXCapabilitiy ;
+
+ /* ConfigGrp */
+ u_char fddiMACMultiple_N ; /* private */
+ u_char fddiMACMultiple_P ; /* private */
+ u_char fddiMACDuplicateAddressCond ;/* private */
+ u_char fddiMACAvailablePaths ;
+ u_short fddiMACCurrentPath ;
+ LongAddr fddiMACUpstreamNbr ;
+ LongAddr fddiMACDownstreamNbr ;
+ LongAddr fddiMACOldUpstreamNbr ;
+ LongAddr fddiMACOldDownstreamNbr ;
+ SMTEnum fddiMACDupAddressTest ;
+ u_short fddiMACRequestedPaths ;
+ SMTEnum fddiMACDownstreamPORTType ;
+ ResId fddiMACIndex ;
+
+ /* AddressGrp */
+ LongAddr fddiMACSMTAddress ;
+
+ /* OperationGrp */
+ Timer_2 fddiMACT_Min ; /* private */
+ Timer_2 fddiMACT_ReqMIB ;
+ Timer_2 fddiMACT_Req ; /* private */
+ Timer_2 fddiMACT_Neg ;
+ Timer_2 fddiMACT_MaxMIB ;
+ Timer_2 fddiMACT_Max ; /* private */
+ Timer_2 fddiMACTvxValueMIB ;
+ Timer_2 fddiMACTvxValue ; /* private */
+ Timer_2 fddiMACT_Pri0 ;
+ Timer_2 fddiMACT_Pri1 ;
+ Timer_2 fddiMACT_Pri2 ;
+ Timer_2 fddiMACT_Pri3 ;
+ Timer_2 fddiMACT_Pri4 ;
+ Timer_2 fddiMACT_Pri5 ;
+ Timer_2 fddiMACT_Pri6 ;
+
+ /* CountersGrp */
+ Counter fddiMACFrame_Ct ;
+ Counter fddiMACCopied_Ct ;
+ Counter fddiMACTransmit_Ct ;
+ Counter fddiMACToken_Ct ;
+ Counter fddiMACError_Ct ;
+ Counter fddiMACLost_Ct ;
+ Counter fddiMACTvxExpired_Ct ;
+ Counter fddiMACNotCopied_Ct ;
+ Counter fddiMACRingOp_Ct ;
+
+ Counter fddiMACSMTCopied_Ct ; /* private */
+ Counter fddiMACSMTTransmit_Ct ; /* private */
+
+ /* private for delta ratio */
+ Counter fddiMACOld_Frame_Ct ;
+ Counter fddiMACOld_Copied_Ct ;
+ Counter fddiMACOld_Error_Ct ;
+ Counter fddiMACOld_Lost_Ct ;
+ Counter fddiMACOld_NotCopied_Ct ;
+
+ /* FrameErrorConditionGrp */
+ u_short fddiMACFrameErrorThreshold ;
+ u_short fddiMACFrameErrorRatio ;
+
+ /* NotCopiedConditionGrp */
+ u_short fddiMACNotCopiedThreshold ;
+ u_short fddiMACNotCopiedRatio ;
+
+ /* StatusGrp */
+ SMTEnum fddiMACRMTState ;
+ SMTFlag fddiMACDA_Flag ;
+ SMTFlag fddiMACUNDA_Flag ;
+ SMTFlag fddiMACFrameErrorFlag ;
+ SMTFlag fddiMACNotCopiedFlag ;
+ SMTFlag fddiMACMA_UnitdataAvailable ;
+ SMTFlag fddiMACHardwarePresent ;
+ SMTFlag fddiMACMA_UnitdataEnable ;
+
+ } m[NUMMACS] ;
+#define MAC0 0
+
+ struct fddi_mib_a {
+ ResId fddiPATHIndex ;
+ u_long fddiPATHSbaPayload ;
+ u_long fddiPATHSbaOverhead ;
+ /* fddiPATHConfiguration is built on demand */
+ /* u_long fddiPATHConfiguration ; */
+ Timer fddiPATHT_Rmode ;
+ u_long fddiPATHSbaAvailable ;
+ Timer_2 fddiPATHTVXLowerBound ;
+ Timer_2 fddiPATHT_MaxLowerBound ;
+ Timer_2 fddiPATHMaxT_Req ;
+ } a[NUMPATHS] ;
+#define PATH0 0
+
+ struct fddi_mib_p {
+ /* ConfigGrp */
+ SMTEnum fddiPORTMy_Type ;
+ SMTEnum fddiPORTNeighborType ;
+ u_char fddiPORTConnectionPolicies ;
+ struct {
+ u_char T_val ;
+ u_char R_val ;
+ } fddiPORTMacIndicated ;
+ SMTEnum fddiPORTCurrentPath ;
+ /* must be 4: is 32 bit in SMT format
+ * indices :
+ * 1 none
+ * 2 tree
+ * 3 peer
+ */
+ u_char fddiPORTRequestedPaths[4] ;
+ u_short fddiPORTMACPlacement ;
+ u_char fddiPORTAvailablePaths ;
+ u_char fddiPORTConnectionCapabilities ;
+ SMTEnum fddiPORTPMDClass ;
+ ResId fddiPORTIndex ;
+
+ /* OperationGrp */
+ SMTEnum fddiPORTMaint_LS ;
+ SMTEnum fddiPORTPC_LS ;
+ u_char fddiPORTBS_Flag ;
+
+ /* ErrorCtrsGrp */
+ Counter fddiPORTLCTFail_Ct ;
+ Counter fddiPORTEBError_Ct ;
+ Counter fddiPORTOldEBError_Ct ;
+
+ /* LerGrp */
+ Counter fddiPORTLem_Reject_Ct ;
+ Counter fddiPORTLem_Ct ;
+ u_char fddiPORTLer_Estimate ;
+ u_char fddiPORTLer_Cutoff ;
+ u_char fddiPORTLer_Alarm ;
+
+ /* StatusGrp */
+ SMTEnum fddiPORTConnectState ;
+ SMTEnum fddiPORTPCMState ; /* real value */
+ SMTEnum fddiPORTPCMStateX ; /* value for MIB */
+ SMTEnum fddiPORTPC_Withhold ;
+ SMTFlag fddiPORTHardwarePresent ;
+ u_char fddiPORTLerFlag ;
+
+ u_char fddiPORTMultiple_U ; /* private */
+ u_char fddiPORTMultiple_P ; /* private */
+ u_char fddiPORTEB_Condition ; /* private */
+ } p[NUMPHYS] ;
+ struct {
+ Counter fddiPRIVECF_Req_Rx ; /* ECF req received */
+ Counter fddiPRIVECF_Reply_Rx ; /* ECF repl received */
+ Counter fddiPRIVECF_Req_Tx ; /* ECF req transm */
+ Counter fddiPRIVECF_Reply_Tx ; /* ECF repl transm */
+ Counter fddiPRIVPMF_Get_Rx ; /* PMF Get rec */
+ Counter fddiPRIVPMF_Set_Rx ; /* PMF Set rec */
+ Counter fddiPRIVRDF_Rx ; /* RDF received */
+ Counter fddiPRIVRDF_Tx ; /* RDF transmitted */
+ } priv ;
+} ;
+
+/*
+ * OIDs for statistics
+ */
+#define SMT_OID_CF_STATE 1 /* fddiSMTCF_State */
+#define SMT_OID_PCM_STATE_A 2 /* fddiPORTPCMState port A */
+#define SMT_OID_PCM_STATE_B 17 /* fddiPORTPCMState port B */
+#define SMT_OID_RMT_STATE 3 /* fddiMACRMTState */
+#define SMT_OID_UNA 4 /* fddiMACUpstreamNbr */
+#define SMT_OID_DNA 5 /* fddiMACOldDownstreamNbr */
+#define SMT_OID_ERROR_CT 6 /* fddiMACError_Ct */
+#define SMT_OID_LOST_CT 7 /* fddiMACLost_Ct */
+#define SMT_OID_LEM_CT 8 /* fddiPORTLem_Ct */
+#define SMT_OID_LEM_CT_A 11 /* fddiPORTLem_Ct port A */
+#define SMT_OID_LEM_CT_B 12 /* fddiPORTLem_Ct port B */
+#define SMT_OID_LCT_FAIL_CT 9 /* fddiPORTLCTFail_Ct */
+#define SMT_OID_LCT_FAIL_CT_A 13 /* fddiPORTLCTFail_Ct port A */
+#define SMT_OID_LCT_FAIL_CT_B 14 /* fddiPORTLCTFail_Ct port B */
+#define SMT_OID_LEM_REJECT_CT 10 /* fddiPORTLem_Reject_Ct */
+#define SMT_OID_LEM_REJECT_CT_A 15 /* fddiPORTLem_Reject_Ct port A */
+#define SMT_OID_LEM_REJECT_CT_B 16 /* fddiPORTLem_Reject_Ct port B */
+
+/*
+ * SK MIB
+ */
+#define SMT_OID_ECF_REQ_RX 20 /* ECF requests received */
+#define SMT_OID_ECF_REPLY_RX 21 /* ECF replies received */
+#define SMT_OID_ECF_REQ_TX 22 /* ECF requests transmitted */
+#define SMT_OID_ECF_REPLY_TX 23 /* ECF replies transmitted */
+#define SMT_OID_PMF_GET_RX 24 /* PMF get requests received */
+#define SMT_OID_PMF_SET_RX 25 /* PMF set requests received */
+#define SMT_OID_RDF_RX 26 /* RDF received */
+#define SMT_OID_RDF_TX 27 /* RDF transmitted */
diff --git a/drivers/net/skfp/h/fplustm.h b/drivers/net/skfp/h/fplustm.h
new file mode 100644
index 000000000..9e1ce036e
--- /dev/null
+++ b/drivers/net/skfp/h/fplustm.h
@@ -0,0 +1,274 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * AMD Fplus in tag mode data structs
+ * defs for fplustm.c
+ */
+
+#ifndef _FPLUS_
+#define _FPLUS_
+
+#ifndef HW_PTR
+#ifdef MEM_MAPPED_IO
+#define HW_PTR u_long
+#else
+#define HW_PTR u_short
+#endif
+#endif
+
+/*
+ * fplus error statistic structure
+ */
+struct err_st {
+ u_long err_valid ; /* memory status valid */
+ u_long err_abort ; /* memory status receive abort */
+ u_long err_e_indicator ; /* error indicator */
+ u_long err_crc ; /* error detected (CRC or length) */
+ u_long err_llc_frame ; /* LLC frame */
+ u_long err_mac_frame ; /* MAC frame */
+ u_long err_smt_frame ; /* SMT frame */
+ u_long err_imp_frame ; /* implementer frame */
+ u_long err_no_buf ; /* no buffer available */
+ u_long err_too_long ; /* longer than max. buffer */
+ u_long err_bec_stat ; /* beacon state entered */
+ u_long err_clm_stat ; /* claim state entered */
+ u_long err_sifg_det ; /* short interframe gap detect */
+ u_long err_phinv ; /* PHY invalid */
+ u_long err_tkiss ; /* token issued */
+ u_long err_tkerr ; /* token error */
+} ;
+
+/*
+ * Transmit Descriptor struct
+ */
+struct s_smt_fp_txd {
+ u_long txd_tbctrl ; /* transmit buffer control */
+ u_long txd_txdscr ; /* transmit frame status word */
+ u_long txd_tbadr ; /* physical tx buffer address */
+ u_long txd_ntdadr ; /* physical pointer to the next TxD */
+#ifdef ENA_64BIT_SUP
+ u_long txd_tbadr_hi ; /* physical tx buffer addr (high dword)*/
+#endif
+ char far *txd_virt ; /* virtual pointer to the data frag */
+ /* virt pointer to the next TxD */
+ struct s_smt_fp_txd volatile far *txd_next ;
+ struct s_txd_os txd_os ; /* OS - specific struct */
+} ;
+
+/*
+ * Receive Descriptor struct
+ */
+struct s_smt_fp_rxd {
+ u_long rxd_rbctrl ; /* receive buffer control */
+ u_long rxd_rfsw ; /* receive frame status word */
+ u_long rxd_rbadr ; /* physical rx buffer address */
+ u_long rxd_nrdadr ; /* physical pointer to the next RxD */
+#ifdef ENA_64BIT_SUP
+ u_long rxd_rbadr_hi ; /* physical tx buffer addr (high dword)*/
+#endif
+ char far *rxd_virt ; /* virtual pointer to the data frag */
+ /* virt pointer to the next RxD */
+ struct s_smt_fp_rxd volatile far *rxd_next ;
+ struct s_rxd_os rxd_os ; /* OS - specific struct */
+} ;
+
+/*
+ * Descriptor Union Definition
+ */
+union s_fp_descr {
+ struct s_smt_fp_txd t ; /* pointer to the TxD */
+ struct s_smt_fp_rxd r ; /* pointer to the RxD */
+} ;
+
+/*
+ * TxD Ring Control struct
+ */
+struct s_smt_tx_queue {
+ struct s_smt_fp_txd volatile *tx_curr_put ; /* next free TxD */
+ struct s_smt_fp_txd volatile *tx_prev_put ; /* shadow put pointer */
+ struct s_smt_fp_txd volatile *tx_curr_get ; /* next TxD to release*/
+ u_short tx_free ; /* count of free TxD's */
+ u_short tx_used ; /* count of used TxD's */
+ HW_PTR tx_bmu_ctl ; /* BMU addr for tx start */
+ HW_PTR tx_bmu_dsc ; /* BMU addr for curr dsc. */
+} ;
+
+/*
+ * RxD Ring Control struct
+ */
+struct s_smt_rx_queue {
+ struct s_smt_fp_rxd volatile *rx_curr_put ; /* next RxD to queue into */
+ struct s_smt_fp_rxd volatile *rx_prev_put ; /* shadow put pointer */
+ struct s_smt_fp_rxd volatile *rx_curr_get ; /* next RxD to fill */
+ u_short rx_free ; /* count of free RxD's */
+ u_short rx_used ; /* count of used RxD's */
+ HW_PTR rx_bmu_ctl ; /* BMU addr for rx start */
+ HW_PTR rx_bmu_dsc ; /* BMU addr for curr dsc. */
+} ;
+
+#define VOID_FRAME_OFF 0x00
+#define CLAIM_FRAME_OFF 0x08
+#define BEACON_FRAME_OFF 0x10
+#define DBEACON_FRAME_OFF 0x18
+#define RX_FIFO_OFF 0x21 /* to get a prime number for */
+ /* the RX_FIFO_SPACE */
+
+#define RBC_MEM_SIZE 0x8000
+#define SEND_ASYNC_AS_SYNC 0x1
+#define SYNC_TRAFFIC_ON 0x2
+
+/* big FIFO memory */
+#define RX_FIFO_SPACE 0x4000 - RX_FIFO_OFF
+#define TX_FIFO_SPACE 0x4000
+
+#define TX_SMALL_FIFO 0x0900
+#define TX_MEDIUM_FIFO TX_FIFO_SPACE / 2
+#define TX_LARGE_FIFO TX_FIFO_SPACE - TX_SMALL_FIFO
+
+#define RX_SMALL_FIFO 0x0900
+#define RX_LARGE_FIFO RX_FIFO_SPACE - RX_SMALL_FIFO
+
+struct s_smt_fifo_conf {
+ u_short rbc_ram_start ; /* FIFO start address */
+ u_short rbc_ram_end ; /* FIFO size */
+ u_short rx1_fifo_start ; /* rx queue start address */
+ u_short rx1_fifo_size ; /* rx queue size */
+ u_short rx2_fifo_start ; /* rx queue start address */
+ u_short rx2_fifo_size ; /* rx queue size */
+ u_short tx_s_start ; /* sync queue start address */
+ u_short tx_s_size ; /* sync queue size */
+ u_short tx_a0_start ; /* async queue A0 start address */
+ u_short tx_a0_size ; /* async queue A0 size */
+ u_short fifo_config_mode ; /* FIFO configuration mode */
+} ;
+
+#define FM_ADDRX (FM_ADDET|FM_EXGPA0|FM_EXGPA1)
+
+struct s_smt_fp {
+ u_short mdr2init ; /* mode register 2 init value */
+ u_short mdr3init ; /* mode register 3 init value */
+ u_short frselreg_init ; /* frame selection register init val */
+ u_short rx_mode ; /* address mode broad/multi/promisc */
+ u_short nsa_mode ;
+ u_short rx_prom ;
+ u_short exgpa ;
+
+ struct err_st err_stats ; /* error statistics */
+
+ /*
+ * MAC buffers
+ */
+ struct fddi_mac_sf { /* special frame build buffer */
+ u_char mac_fc ;
+ struct fddi_addr mac_dest ;
+ struct fddi_addr mac_source ;
+ u_char mac_info[0x20] ;
+ } mac_sfb ;
+
+
+ /*
+ * queues
+ */
+#define QUEUE_S 0
+#define QUEUE_A0 1
+#define QUEUE_R1 0
+#define QUEUE_R2 1
+#define USED_QUEUES 2
+
+ /*
+ * queue pointers; points to the queue dependent variables
+ */
+ struct s_smt_tx_queue *tx[USED_QUEUES] ;
+ struct s_smt_rx_queue *rx[USED_QUEUES] ;
+
+ /*
+ * queue dependent variables
+ */
+ struct s_smt_tx_queue tx_q[USED_QUEUES] ;
+ struct s_smt_rx_queue rx_q[USED_QUEUES] ;
+
+ /*
+ * FIFO configuration struct
+ */
+ struct s_smt_fifo_conf fifo ;
+
+ /* last formac status */
+ u_short s2u ;
+ u_short s2l ;
+
+ /* calculated FORMAC+ reg.addr. */
+ HW_PTR fm_st1u ;
+ HW_PTR fm_st1l ;
+ HW_PTR fm_st2u ;
+ HW_PTR fm_st2l ;
+ HW_PTR fm_st3u ;
+ HW_PTR fm_st3l ;
+
+
+ /*
+ * multicast table
+ */
+#define FPMAX_MULTICAST 32
+#define SMT_MAX_MULTI 4
+ struct {
+ struct s_fpmc {
+ struct fddi_addr a ; /* mc address */
+ u_char n ; /* usage counter */
+ u_char perm ; /* flag: permanent */
+ } table[FPMAX_MULTICAST] ;
+ } mc ;
+ struct fddi_addr group_addr ;
+ u_long func_addr ; /* functional address */
+ int smt_slots_used ; /* count of table entries for the SMT */
+ int os_slots_used ; /* count of table entries */
+ /* used by the os-specific module */
+} ;
+
+/*
+ * modes for mac_set_rx_mode()
+ */
+#define RX_ENABLE_ALLMULTI 1 /* enable all multicasts */
+#define RX_DISABLE_ALLMULTI 2 /* disable "enable all multicasts" */
+#define RX_ENABLE_PROMISC 3 /* enable promiscous */
+#define RX_DISABLE_PROMISC 4 /* disable promiscous */
+#define RX_ENABLE_NSA 5 /* enable reception of NSA frames */
+#define RX_DISABLE_NSA 6 /* disable reception of NSA frames */
+
+
+/*
+ * support for byte reversal in AIX
+ * (descriptors and pointers must be byte reversed in memory
+ * CPU is big endian; M-Channel is little endian)
+ */
+#ifdef AIX
+#define MDR_REV
+#define AIX_REVERSE(x) ((((x)<<24L)&0xff000000L) + \
+ (((x)<< 8L)&0x00ff0000L) + \
+ (((x)>> 8L)&0x0000ff00L) + \
+ (((x)>>24L)&0x000000ffL))
+#else
+#define AIX_REVERSE(x) (x)
+#endif
+
+#ifdef MDR_REV
+#define MDR_REVERSE(x) ((((x)<<24L)&0xff000000L) + \
+ (((x)<< 8L)&0x00ff0000L) + \
+ (((x)>> 8L)&0x0000ff00L) + \
+ (((x)>>24L)&0x000000ffL))
+#else
+#define MDR_REVERSE(x) (x)
+#endif
+
+#endif
diff --git a/drivers/net/skfp/h/hwmtm.h b/drivers/net/skfp/h/hwmtm.h
new file mode 100644
index 000000000..4e360af07
--- /dev/null
+++ b/drivers/net/skfp/h/hwmtm.h
@@ -0,0 +1,424 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef _HWM_
+#define _HWM_
+
+#include "h/mbuf.h"
+
+/*
+ * MACRO for DMA synchronization:
+ * The descriptor 'desc' is flushed for the device 'flag'.
+ * Devices are the CPU (DDI_DMA_SYNC_FORCPU) and the
+ * adapter (DDI_DMA_SYNC_FORDEV).
+ *
+ * 'desc' Pointer to a Rx or Tx descriptor.
+ * 'flag' Flag for direction (view for CPU or DEVICE) that
+ * should be synchronized.
+ *
+ * Empty macros and defines are specified here. The real macro
+ * is os-specific and should be defined in osdef1st.h.
+ */
+#ifndef DRV_BUF_FLUSH
+#define DRV_BUF_FLUSH(desc,flag)
+#define DDI_DMA_SYNC_FORCPU
+#define DDI_DMA_SYNC_FORDEV
+#endif
+
+ /*
+ * hardware modul dependent receive modes
+ */
+#define RX_ENABLE_PASS_SMT 21
+#define RX_DISABLE_PASS_SMT 22
+#define RX_ENABLE_PASS_NSA 23
+#define RX_DISABLE_PASS_NSA 24
+#define RX_ENABLE_PASS_DB 25
+#define RX_DISABLE_PASS_DB 26
+#define RX_DISABLE_PASS_ALL 27
+#define RX_DISABLE_LLC_PROMISC 28
+#define RX_ENABLE_LLC_PROMISC 29
+
+
+#ifndef DMA_RD
+#define DMA_RD 1 /* memory -> hw */
+#endif
+#ifndef DMA_WR
+#define DMA_WR 2 /* hw -> memory */
+#endif
+#define SMT_BUF 0x80
+
+ /*
+ * bits of the frame status byte
+ */
+#define EN_IRQ_EOF 0x02 /* get IRQ after end of frame transmission */
+#define LOC_TX 0x04 /* send frame to the local SMT */
+#define LAST_FRAG 0x08 /* last TxD of the frame */
+#define FIRST_FRAG 0x10 /* first TxD of the frame */
+#define LAN_TX 0x20 /* send frame to network if set */
+#define RING_DOWN 0x40 /* error: unable to send, ring down */
+#define OUT_OF_TXD 0x80 /* error: not enough TxDs available */
+
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifdef LITTLE_ENDIAN
+#define HWM_REVERSE(x) (x)
+#else
+#define HWM_REVERSE(x) ((((x)<<24L)&0xff000000L) + \
+ (((x)<< 8L)&0x00ff0000L) + \
+ (((x)>> 8L)&0x0000ff00L) + \
+ (((x)>>24L)&0x000000ffL))
+#endif
+
+#define C_INDIC (1L<<25)
+#define A_INDIC (1L<<26)
+#define RD_FS_LOCAL 0x80
+
+ /*
+ * DEBUG FLAGS
+ */
+#define DEBUG_SMTF 1
+#define DEBUG_SMT 2
+#define DEBUG_ECM 3
+#define DEBUG_RMT 4
+#define DEBUG_CFM 5
+#define DEBUG_PCM 6
+#define DEBUG_SBA 7
+#define DEBUG_ESS 8
+
+#define DB_HWM_RX 10
+#define DB_HWM_TX 11
+#define DB_HWM_GEN 12
+
+struct s_mbuf_pool {
+#ifndef MB_OUTSIDE_SMC
+ SMbuf mb[MAX_MBUF] ; /* mbuf pool */
+#endif
+ SMbuf *mb_start ; /* points to the first mb */
+ SMbuf *mb_free ; /* free queue */
+} ;
+
+struct hwm_r {
+ /*
+ * hardware modul specific receive variables
+ */
+ u_int len ; /* length of the whole frame */
+ char *mb_pos ; /* SMbuf receive position */
+} ;
+
+struct hw_modul {
+ /*
+ * All hardware modul specific variables
+ */
+ struct s_mbuf_pool mbuf_pool ;
+ struct hwm_r r ;
+
+ union s_fp_descr volatile *descr_p ; /* points to the desriptor area */
+
+ u_short pass_SMT ; /* pass SMT frames */
+ u_short pass_NSA ; /* pass all NSA frames */
+ u_short pass_DB ; /* pass Direct Beacon Frames */
+ u_short pass_llc_promisc ; /* pass all llc frames (default ON) */
+
+ SMbuf *llc_rx_pipe ; /* points to the first queued llc fr */
+ SMbuf *llc_rx_tail ; /* points to the last queued llc fr */
+ int queued_rx_frames ; /* number of queued frames */
+
+ SMbuf *txd_tx_pipe ; /* points to first mb in the txd ring */
+ SMbuf *txd_tx_tail ; /* points to last mb in the txd ring */
+ int queued_txd_mb ; /* number of SMT MBufs in txd ring */
+
+ int rx_break ; /* rev. was breaked because ind. off */
+ int leave_isr ; /* leave fddi_isr immedeately if set */
+ int isr_flag ; /* set, when HWM is entered from isr */
+ /*
+ * varaibles for the current transmit frame
+ */
+ struct s_smt_tx_queue *tx_p ; /* pointer to the transmit queue */
+ u_long tx_descr ; /* tx descriptor for FORMAC+ */
+ int tx_len ; /* tx frame length */
+ SMbuf *tx_mb ; /* SMT tx MBuf pointer */
+ char *tx_data ; /* data pointer to the SMT tx Mbuf */
+
+ int detec_count ; /* counter for out of RxD condition */
+ u_long rx_len_error ; /* rx len FORMAC != sum of fragments */
+} ;
+
+
+/*
+ * DEBUG structs and macros
+ */
+
+#ifdef DEBUG
+struct os_debug {
+ int hwm_rx ;
+ int hwm_tx ;
+ int hwm_gen ;
+} ;
+#endif
+
+#ifdef DEBUG
+#ifdef DEBUG_BRD
+#define DB_P smc->debug
+#else
+#define DB_P debug
+#endif
+
+#define DB_RX(a,b,c,lev) if (DB_P.d_os.hwm_rx >= (lev)) printf(a,b,c)
+#define DB_TX(a,b,c,lev) if (DB_P.d_os.hwm_tx >= (lev)) printf(a,b,c)
+#define DB_GEN(a,b,c,lev) if (DB_P.d_os.hwm_gen >= (lev)) printf(a,b,c)
+#else /* DEBUG */
+#define DB_RX(a,b,c,lev)
+#define DB_TX(a,b,c,lev)
+#define DB_GEN(a,b,c,lev)
+#endif /* DEBUG */
+
+#ifndef SK_BREAK
+#define SK_BREAK()
+#endif
+
+
+/*
+ * HWM Macros
+ */
+
+/*
+ * BEGIN_MANUAL_ENTRY(HWM_GET_TX_PHYS)
+ * u_long HWM_GET_TX_PHYS(txd)
+ *
+ * function MACRO (hardware module, hwmtm.h)
+ * This macro may be invoked by the OS-specific module to read
+ * the physical address of the specified TxD.
+ *
+ * para txd pointer to the TxD
+ *
+ * END_MANUAL_ENTRY
+ */
+#define HWM_GET_TX_PHYS(txd) (u_long)AIX_REVERSE((txd)->txd_tbadr)
+
+/*
+ * BEGIN_MANUAL_ENTRY(HWM_GET_TX_LEN)
+ * int HWM_GET_TX_LEN(txd)
+ *
+ * function MACRO (hardware module, hwmtm.h)
+ * This macro may be invoked by the OS-specific module to read
+ * the fragment length of the specified TxD
+ *
+ * para rxd pointer to the TxD
+ *
+ * return the length of the fragment in bytes
+ *
+ * END_MANUAL_ENTRY
+ */
+#define HWM_GET_TX_LEN(txd) ((int)AIX_REVERSE((txd)->txd_tbctrl)& RD_LENGTH)
+
+/*
+ * BEGIN_MANUAL_ENTRY(HWM_GET_TX_USED)
+ * txd *HWM_GET_TX_USED(smc,queue)
+ *
+ * function MACRO (hardware module, hwmtm.h)
+ * This macro may be invoked by the OS-specific module to get the
+ * number of used TxDs for the queue, specified by the index.
+ *
+ * para queue the number of the send queue: Can be specified by
+ * QUEUE_A0, QUEUE_S or (frame_status & QUEUE_A0)
+ *
+ * return number of used TxDs for this send queue
+ *
+ * END_MANUAL_ENTRY
+ */
+#define HWM_GET_TX_USED(smc,queue) (int) (smc)->hw.fp.tx_q[queue].tx_used
+
+/*
+ * BEGIN_MANUAL_ENTRY(HWM_GET_CURR_TXD)
+ * txd *HWM_GET_CURR_TXD(smc,queue)
+ *
+ * function MACRO (hardware module, hwmtm.h)
+ * This macro may be invoked by the OS-specific module to get the
+ * pointer to the TxD which points to the current queue put
+ * position.
+ *
+ * para queue the number of the send queue: Can be specified by
+ * QUEUE_A0, QUEUE_S or (frame_status & QUEUE_A0)
+ *
+ * return pointer to the current TxD
+ *
+ * END_MANUAL_ENTRY
+ */
+#define HWM_GET_CURR_TXD(smc,queue) (struct s_smt_fp_txd volatile *)\
+ (smc)->hw.fp.tx_q[queue].tx_curr_put
+
+/*
+ * BEGIN_MANUAL_ENTRY(HWM_TX_CHECK)
+ * void HWM_TX_CHECK(smc,frame_status,low_water)
+ *
+ * function MACRO (hardware module, hwmtm.h)
+ * This macro is invoked by the OS-specific before it left it's
+ * driver_send function. This macro calls mac_drv_clear_txd
+ * if the free TxDs of the current transmit queue is equal or
+ * lower than the given low water mark.
+ *
+ * para frame_status status of the frame, see design description
+ * low_water low water mark of free TxD's
+ *
+ * END_MANUAL_ENTRY
+ */
+#ifndef HWM_NO_FLOW_CTL
+#define HWM_TX_CHECK(smc,frame_status,low_water) {\
+ if ((low_water)>=(smc)->hw.fp.tx_q[(frame_status)&QUEUE_A0].tx_free) {\
+ mac_drv_clear_txd(smc) ;\
+ }\
+}
+#else
+#define HWM_TX_CHECK(smc,frame_status,low_water) mac_drv_clear_txd(smc)
+#endif
+
+/*
+ * BEGIN_MANUAL_ENTRY(HWM_GET_RX_FRAG_LEN)
+ * int HWM_GET_RX_FRAG_LEN(rxd)
+ *
+ * function MACRO (hardware module, hwmtm.h)
+ * This macro may be invoked by the OS-specific module to read
+ * the fragment length of the specified RxD
+ *
+ * para rxd pointer to the RxD
+ *
+ * return the length of the fragment in bytes
+ *
+ * END_MANUAL_ENTRY
+ */
+#define HWM_GET_RX_FRAG_LEN(rxd) ((int)AIX_REVERSE((rxd)->rxd_rbctrl)& \
+ RD_LENGTH)
+
+/*
+ * BEGIN_MANUAL_ENTRY(HWM_GET_RX_PHYS)
+ * u_long HWM_GET_RX_PHYS(rxd)
+ *
+ * function MACRO (hardware module, hwmtm.h)
+ * This macro may be invoked by the OS-specific module to read
+ * the physical address of the specified RxD.
+ *
+ * para rxd pointer to the RxD
+ *
+ * return the RxD's physical pointer to the data fragment
+ *
+ * END_MANUAL_ENTRY
+ */
+#define HWM_GET_RX_PHYS(rxd) (u_long)AIX_REVERSE((rxd)->rxd_rbadr)
+
+/*
+ * BEGIN_MANUAL_ENTRY(HWM_GET_RX_USED)
+ * int HWM_GET_RX_USED(smc)
+ *
+ * function MACRO (hardware module, hwmtm.h)
+ * This macro may be invoked by the OS-specific module to get
+ * the count of used RXDs in receive queue 1.
+ *
+ * return the used RXD count of receive queue 1
+ *
+ * NOTE: Remember, because of an ASIC bug at least one RXD should be unused
+ * in the descriptor ring !
+ *
+ * END_MANUAL_ENTRY
+ */
+#define HWM_GET_RX_USED(smc) ((int)(smc)->hw.fp.rx_q[QUEUE_R1].rx_used)
+
+/*
+ * BEGIN_MANUAL_ENTRY(HWM_GET_RX_FREE)
+ * int HWM_GET_RX_FREE(smc)
+ *
+ * function MACRO (hardware module, hwmtm.h)
+ * This macro may be invoked by the OS-specific module to get
+ * the rxd_free count of receive queue 1.
+ *
+ * return the rxd_free count of receive queue 1
+ *
+ * END_MANUAL_ENTRY
+ */
+#define HWM_GET_RX_FREE(smc) ((int)(smc)->hw.fp.rx_q[QUEUE_R1].rx_free-1)
+
+/*
+ * BEGIN_MANUAL_ENTRY(HWM_GET_CURR_RXD)
+ * rxd *HWM_GET_CURR_RXD(smc)
+ *
+ * function MACRO (hardware module, hwmtm.h)
+ * This macro may be invoked by the OS-specific module to get the
+ * pointer to the RxD which points to the current queue put
+ * position.
+ *
+ * return pointer to the current RxD
+ *
+ * END_MANUAL_ENTRY
+ */
+#define HWM_GET_CURR_RXD(smc) (struct s_smt_fp_rxd volatile *)\
+ (smc)->hw.fp.rx_q[QUEUE_R1].rx_curr_put
+
+/*
+ * BEGIN_MANUAL_ENTRY(HWM_RX_CHECK)
+ * void HWM_RX_CHECK(smc,low_water)
+ *
+ * function MACRO (hardware module, hwmtm.h)
+ * This macro is invoked by the OS-specific before it left the
+ * function mac_drv_rx_complete. This macro calls mac_drv_fill_rxd
+ * if the number of used RxDs is equal or lower than the
+ * the given low water mark.
+ *
+ * para low_water low water mark of used RxD's
+ *
+ * END_MANUAL_ENTRY
+ */
+#ifndef HWM_NO_FLOW_CTL
+#define HWM_RX_CHECK(smc,low_water) {\
+ if ((low_water) >= (smc)->hw.fp.rx_q[QUEUE_R1].rx_used) {\
+ mac_drv_fill_rxd(smc) ;\
+ }\
+}
+#else
+#define HWM_RX_CHECK(smc,low_water) mac_drv_fill_rxd(smc)
+#endif
+
+#ifndef HWM_EBASE
+#define HWM_EBASE 500
+#endif
+
+#define HWM_E0001 HWM_EBASE + 1
+#define HWM_E0001_MSG "HWM: Wrong size of s_rxd_os struct"
+#define HWM_E0002 HWM_EBASE + 2
+#define HWM_E0002_MSG "HWM: Wrong size of s_txd_os struct"
+#define HWM_E0003 HWM_EBASE + 3
+#define HWM_E0003_MSG "HWM: smt_free_mbuf() called with NULL pointer"
+#define HWM_E0004 HWM_EBASE + 4
+#define HWM_E0004_MSG "HWM: Parity error rx queue 1"
+#define HWM_E0005 HWM_EBASE + 5
+#define HWM_E0005_MSG "HWM: Encoding error rx queue 1"
+#define HWM_E0006 HWM_EBASE + 6
+#define HWM_E0006_MSG "HWM: Encoding error async tx queue"
+#define HWM_E0007 HWM_EBASE + 7
+#define HWM_E0007_MSG "HWM: Encoding error sync tx queue"
+#define HWM_E0008 HWM_EBASE + 8
+#define HWM_E0008_MSG ""
+#define HWM_E0009 HWM_EBASE + 9
+#define HWM_E0009_MSG "HWM: Out of RxD condition detected"
+#define HWM_E0010 HWM_EBASE + 10
+#define HWM_E0010_MSG "HWM: A protocol layer has tried to send a frame with an invalid frame control"
+#define HWM_E0011 HWM_EBASE + 11
+#define HWM_E0011_MSG "HWM: mac_drv_clear_tx_queue was called although the hardware wasn't stopped"
+#define HWM_E0012 HWM_EBASE + 12
+#define HWM_E0012_MSG "HWM: mac_drv_clear_rx_queue was called although the hardware wasn't stopped"
+#define HWM_E0013 HWM_EBASE + 13
+#define HWM_E0013_MSG "HWM: mac_drv_repair_descr was called although the hardware wasn't stopped"
+
+#endif
diff --git a/drivers/net/skfp/h/lnkstat.h b/drivers/net/skfp/h/lnkstat.h
new file mode 100644
index 000000000..c73dcd96a
--- /dev/null
+++ b/drivers/net/skfp/h/lnkstat.h
@@ -0,0 +1,84 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * Definition of the Error Log Structure
+ * This structure will be copied into the Error Log buffer
+ * during the NDIS General Request ReadErrorLog by the MAC Driver
+ */
+
+struct s_error_log {
+
+ /*
+ * place holder for token ring adapter error log (zeros)
+ */
+ u_char reserved_0 ; /* byte 0 inside Error Log */
+ u_char reserved_1 ; /* byte 1 */
+ u_char reserved_2 ; /* byte 2 */
+ u_char reserved_3 ; /* byte 3 */
+ u_char reserved_4 ; /* byte 4 */
+ u_char reserved_5 ; /* byte 5 */
+ u_char reserved_6 ; /* byte 6 */
+ u_char reserved_7 ; /* byte 7 */
+ u_char reserved_8 ; /* byte 8 */
+ u_char reserved_9 ; /* byte 9 */
+ u_char reserved_10 ; /* byte 10 */
+ u_char reserved_11 ; /* byte 11 */
+ u_char reserved_12 ; /* byte 12 */
+ u_char reserved_13 ; /* byte 13 */
+
+ /*
+ * FDDI link statistics
+ */
+/*
+ * smt error low
+ */
+#define SMT_ERL_AEB (1<<15) /* A elast. buffer */
+#define SMT_ERL_BLC (1<<14) /* B link error condition */
+#define SMT_ERL_ALC (1<<13) /* A link error condition */
+#define SMT_ERL_NCC (1<<12) /* not copied condition */
+#define SMT_ERL_FEC (1<<11) /* frame error condition */
+
+/*
+ * smt event low
+ */
+#define SMT_EVL_NCE (1<<5)
+
+ u_short smt_error_low ; /* byte 14/15 */
+ u_short smt_error_high ; /* byte 16/17 */
+ u_short smt_event_low ; /* byte 18/19 */
+ u_short smt_event_high ; /* byte 20/21 */
+ u_short connection_policy_violation ; /* byte 22/23 */
+ u_short port_event ; /* byte 24/25 */
+ u_short set_count_low ; /* byte 26/27 */
+ u_short set_count_high ; /* byte 28/29 */
+ u_short aci_id_code ; /* byte 30/31 */
+ u_short purge_frame_counter ; /* byte 32/33 */
+
+ /*
+ * CMT and RMT state machines
+ */
+ u_short ecm_state ; /* byte 34/35 */
+ u_short pcm_a_state ; /* byte 36/37 */
+ u_short pcm_b_state ; /* byte 38/39 */
+ u_short cfm_state ; /* byte 40/41 */
+ u_short rmt_state ; /* byte 42/43 */
+
+ u_short not_used[30] ; /* byte 44-103 */
+
+ u_short ucode_version_level ; /* byte 104/105 */
+
+ u_short not_used_1 ; /* byte 106/107 */
+ u_short not_used_2 ; /* byte 108/109 */
+} ;
diff --git a/drivers/net/skfp/h/mbuf.h b/drivers/net/skfp/h/mbuf.h
new file mode 100644
index 000000000..b339d1f2e
--- /dev/null
+++ b/drivers/net/skfp/h/mbuf.h
@@ -0,0 +1,54 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef _MBUF_
+#define _MBUF_
+
+#ifndef PCI
+#define M_SIZE 4550
+#else
+#define M_SIZE 4504
+#endif
+
+#ifndef MAX_MBUF
+#define MAX_MBUF 4
+#endif
+
+#ifndef NO_STD_MBUF
+#define sm_next m_next
+#define sm_off m_off
+#define sm_len m_len
+#define sm_data m_data
+#define SMbuf Mbuf
+#define mtod smtod
+#define mtodoff smtodoff
+#endif
+
+struct s_mbuf {
+ struct s_mbuf *sm_next ; /* low level linked list */
+ short sm_off ; /* offset in m_data */
+ u_int sm_len ; /* len of data */
+#ifdef PCI
+ int sm_use_count ;
+#endif
+ char sm_data[M_SIZE] ;
+} ;
+
+typedef struct s_mbuf SMbuf ;
+
+/* mbuf head, to typed data */
+#define smtod(x,t) ((t)((x)->sm_data + (x)->sm_off))
+#define smtodoff(x,t,o) ((t)((x)->sm_data + (o)))
+
+#endif /* _MBUF_ */
diff --git a/drivers/net/skfp/h/osdef1st.h b/drivers/net/skfp/h/osdef1st.h
new file mode 100644
index 000000000..69f27707d
--- /dev/null
+++ b/drivers/net/skfp/h/osdef1st.h
@@ -0,0 +1,118 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * Operating system-dependant definitions that have to be defined
+ * before any other header files are included.
+ */
+
+// HWM (HardWare Module) Definitions
+// -----------------------
+
+#ifdef __LITTLE_ENDIAN
+#define LITTLE_ENDIAN
+#else
+#define BIG_ENDIAN
+#endif
+
+// this is set in the makefile
+// #define PCI /* only PCI adapters supported by this driver */
+// #define MEM_MAPPED_IO /* use memory mapped I/O */
+
+
+#define USE_CAN_ADDR /* DA and SA in MAC header are canonical. */
+
+#define MB_OUTSIDE_SMC /* SMT Mbufs outside of smc struct. */
+
+// -----------------------
+
+
+// SMT Definitions
+// -----------------------
+#define SYNC /* allow synchronous frames */
+
+// #define SBA /* Synchronous Bandwidth Allocator support */
+ /* not available as free source */
+
+#define ESS /* SBA End Station Support */
+
+#define SMT_PANIC(smc, nr, msg) printk(KERN_INFO "SMT PANIC: code: %d, msg: %s\n",nr,msg)
+
+
+#ifdef DEBUG
+#define printf(s,args...) printk(KERN_INFO s, ## args)
+#endif
+
+// #define HW_PTR u_long
+// -----------------------
+
+
+
+// HWM and OS-specific buffer definitions
+// -----------------------
+
+// default number of receive buffers.
+#define NUM_RECEIVE_BUFFERS 10
+
+// default number of transmit buffers.
+#define NUM_TRANSMIT_BUFFERS 10
+
+// Number of SMT buffers (Mbufs).
+#define NUM_SMT_BUF 4
+
+// Number of TXDs for asynchronous transmit queue.
+#define HWM_ASYNC_TXD_COUNT (NUM_TRANSMIT_BUFFERS + NUM_SMT_BUF)
+
+// Number of TXDs for synchronous transmit queue.
+#define HWM_SYNC_TXD_COUNT HWM_ASYNC_TXD_COUNT
+
+
+// Number of RXDs for receive queue #1.
+// Note: Workaround for ASIC Errata #7: One extra RXD is required.
+#if (NUM_RECEIVE_BUFFERS > 100)
+#define SMT_R1_RXD_COUNT (1 + 100)
+#else
+#define SMT_R1_RXD_COUNT (1 + NUM_RECEIVE_BUFFERS)
+#endif
+
+// Number of RXDs for receive queue #2.
+#define SMT_R2_RXD_COUNT 0 // Not used.
+// -----------------------
+
+
+
+/*
+ * OS-specific part of the transmit/receive descriptor structure (TXD/RXD).
+ *
+ * Note: The size of these structures must follow this rule:
+ *
+ * size = 8 + n * 16, n >= 0
+ *
+ * NOTE: The size of this structures may not be changed, because
+ * libskfddi.a depends on it. But the dummy fields can be
+ * used freely.
+ */
+
+struct s_txd_os { // os-specific part of transmit descriptor
+ struct sk_buff *skb;
+ long dummy;
+} ;
+
+struct s_rxd_os { // os-specific part of receive descriptor
+ struct sk_buff *skb;
+ long dummy;
+} ;
+
+
+
diff --git a/drivers/net/skfp/h/sba.h b/drivers/net/skfp/h/sba.h
new file mode 100644
index 000000000..df716cd57
--- /dev/null
+++ b/drivers/net/skfp/h/sba.h
@@ -0,0 +1,142 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * Synchronous Bandwith Allocation (SBA) structs
+ */
+
+#ifndef _SBA_
+#define _SBA_
+
+#include "h/mbuf.h"
+#include "h/sba_def.h"
+
+#ifdef SBA
+
+/* Timer Cell Template */
+struct timer_cell {
+ struct timer_cell *next_ptr ;
+ struct timer_cell *prev_ptr ;
+ u_long start_time ;
+ struct s_sba_node_vars *node_var ;
+} ;
+
+/*
+ * Node variables
+ */
+struct s_sba_node_vars {
+ u_char change_resp_flag ;
+ u_char report_resp_flag ;
+ u_char change_req_flag ;
+ u_char report_req_flag ;
+ long change_amount ;
+ long node_overhead ;
+ long node_payload ;
+ u_long node_status ;
+ u_char deallocate_status ;
+ u_char timer_state ;
+ u_short report_cnt ;
+ long lastrep_req_tranid ;
+ struct fddi_addr mac_address ;
+ struct s_sba_sessions *node_sessions ;
+ struct timer_cell timer ;
+} ;
+
+/*
+ * Session variables
+ */
+struct s_sba_sessions {
+ u_long deallocate_status ;
+ long session_overhead ;
+ u_long min_segment_size ;
+ long session_payload ;
+ u_long session_status ;
+ u_long sba_category ;
+ long lastchg_req_tranid ;
+ u_short session_id ;
+ u_char class ;
+ u_char fddi2 ;
+ u_long max_t_neg ;
+ struct s_sba_sessions *next_session ;
+} ;
+
+struct s_sba {
+
+ struct s_sba_node_vars node[MAX_NODES] ;
+ struct s_sba_sessions session[MAX_SESSIONS] ;
+
+ struct s_sba_sessions *free_session ; /* points to the first */
+ /* free session */
+
+ struct timer_cell *tail_timer ; /* points to the last timer cell */
+
+ /*
+ * variables for allocation actions
+ */
+ long total_payload ; /* Total Payload */
+ long total_overhead ; /* Total Overhead */
+ long sba_allocatable ; /* allocatable sync bandwidth */
+
+ /*
+ * RAF message receive parameters
+ */
+ long msg_path_index ; /* Path Type */
+ long msg_sba_pl_req ; /* Payload Request */
+ long msg_sba_ov_req ; /* Overhead Request */
+ long msg_mib_pl ; /* Current Payload for this Path */
+ long msg_mib_ov ; /* Current Overhead for this Path*/
+ long msg_category ; /* Category of the Allocation */
+ u_long msg_max_t_neg ; /* longest T_Neg acceptable */
+ u_long msg_min_seg_siz ; /* minimum segement size */
+ struct smt_header *sm ; /* points to the rec message */
+ struct fddi_addr *msg_alloc_addr ; /* Allocation Address */
+
+ /*
+ * SBA variables
+ */
+ u_long sba_t_neg ; /* holds the last T_NEG */
+ long sba_max_alloc ; /* the parsed value of SBAAvailable */
+
+ /*
+ * SBA state machine variables
+ */
+ short sba_next_state ; /* the next state of the SBA */
+ char sba_command ; /* holds the execuded SBA cmd */
+ u_char sba_available ; /* parsed value after possible check */
+} ;
+
+#endif /* SBA */
+
+ /*
+ * variables for the End Station Support
+ */
+struct s_ess {
+
+ /*
+ * flags and counters
+ */
+ u_char sync_bw_available ; /* is set if sync bw is allocated */
+ u_char local_sba_active ; /* set when a local sba is available */
+ char raf_act_timer_poll ; /* activate the timer to send allc req */
+ char timer_count ; /* counts every timer function call */
+
+ SMbuf *sba_reply_pend ; /* local reply for the sba is pending */
+
+ /*
+ * variables for the ess bandwidth control
+ */
+ long sync_bw ; /* holds the allocaed sync bw */
+ u_long alloc_trans_id ; /* trans id of the last alloc req */
+} ;
+#endif
diff --git a/drivers/net/skfp/h/sba_def.h b/drivers/net/skfp/h/sba_def.h
new file mode 100644
index 000000000..0459a095d
--- /dev/null
+++ b/drivers/net/skfp/h/sba_def.h
@@ -0,0 +1,76 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#define PHYS 0 /* physical addr */
+#define PERM_ADDR 0x80 /* permanet address */
+#define SB_STATIC 0x00000001
+#define MAX_PAYLOAD 1562
+#define PRIMARY_RING 0x00000001
+#ifndef NULL
+#define NULL 0x00
+#endif
+
+/*********************** SB_Input Variable Values ***********************/
+/* may be needed when ever the SBA state machine is called */
+
+#define UNKNOWN_SYNC_SOURCE 0x0001
+#define REQ_ALLOCATION 0x0002
+#define REPORT_RESP 0x0003
+#define CHANGE_RESP 0x0004
+#define TNEG 0x0005
+#define NIF 0x0006
+#define SB_STOP 0x0007
+#define SB_START 0x0008
+#define REPORT_TIMER 0x0009
+#define CHANGE_REQUIRED 0x000A
+
+#define DEFAULT_OV 50
+
+#ifdef SBA
+/**************************** SBA STATES *****************************/
+
+#define SBA_STANDBY 0x00000000
+#define SBA_ACTIVE 0x00000001
+#define SBA_RECOVERY 0x00000002
+#define SBA_REPORT 0x00000003
+#define SBA_CHANGE 0x00000004
+
+/**************************** OTHERS *********************************/
+
+#define FIFTY_PERCENT 50 /* bytes per second */
+#define MAX_SESSIONS 150
+#define TWO_MINUTES 13079 /* 9.175 ms/tick */
+#define FIFTY_BYTES 50
+#define SBA_DENIED 0x0000000D
+#define I_NEED_ONE 0x00000000
+#define MAX_NODES 50
+/*#define T_REPORT 0x59682F00L*/ /* 120s/80ns in Hex */
+#define TWO_MIN 120 /* seconds */
+#define SBA_ST_UNKNOWN 0x00000002
+#define SBA_ST_ACTIVE 0x00000001
+#define S_CLEAR 0x00000000L
+#define ZERO 0x00000000
+#define FULL 0x00000000 /* old: 0xFFFFFFFFF */
+#define S_SET 0x00000001L
+#define LOW_PRIO 0x02 /* ??????? */
+#define OK 0x01 /* ??????? */
+#define NOT_OK 0x00 /* ??????? */
+
+/****************************************/
+/* deallocate_status[ni][si] values */
+/****************************************/
+#define TX_CHANGE 0X00000001L
+#define PENDING 0x00000002L
+#define NONE 0X00000000L
+#endif
diff --git a/drivers/net/skfp/h/skfbi.h b/drivers/net/skfp/h/skfbi.h
new file mode 100644
index 000000000..f127bddb8
--- /dev/null
+++ b/drivers/net/skfp/h/skfbi.h
@@ -0,0 +1,1920 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef _SKFBI_H_
+#define _SKFBI_H_
+
+#ifdef SYNC
+#define exist_board_far exist_board
+#define get_board_para_far get_board_para
+#endif
+
+/*
+ * physical address offset + IO-Port base address
+ */
+#ifndef PCI
+#define ADDR(a) ((a)+smc->hw.iop)
+#define ADDRS(smc,a) ((a)+(smc)->hw.iop)
+#endif
+
+/*
+ * FDDI-Fx (x := {I(SA), E(ISA), M(CA), P(CI)})
+ * address calculation & function defines
+ */
+
+#ifdef EISA
+
+/*
+ * Configuration PROM: !! all 8-Bit IO's !!
+ * |<- MAC-Address ->|
+ * /-+--+--+--+--+-//-+--+--+--+--+-//-+--+--+--+--+-//-+--+--+--+--+-/
+ * val: |PROD_ID0..3| | free | |00|00|5A|40| |nn|mm|00|00|
+ * /-+--+--+--+--+-//-+--+--+--+--+-//-+--+--+--+--+-//-+--+--+--+--+-/
+ * IO- ^ ^ ^ ^ ^
+ * port 0C80 0C83 0C88 0C90 0C98
+ * | \
+ * | \
+ * | \______________________________________________
+ * EISA Expansion Board Product ID: \
+ * BIT: |7 6 5 4 3 2 1 0| \
+ * | PROD_ID0 | PROD_ID1 | PROD_ID2 | PROD_ID3 |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |0| MAN_C0 | MAN_C1 | MAN_C2 | PROD1 | PROD0 | REV1 | REV0 |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ^=reserved | product numb. | revision numb |
+ * MAN_Cx = compressed manufacterer code (x:=0..2)
+ * ASCII : 'A'..'Z' : 0x41..0x5A -> compr.(c-0x40) : 0x01..0x1A (5Bits!)
+ */
+
+#ifndef MULT_OEM
+#ifndef OEM_CONCEPT
+#define MAN_C0 ('S'-0x40)
+#define MAN_C1 ('K'-0x40)
+#define MAN_C2 ('D'-0x40)
+#define PROD_ID0 (u_char)((MAN_C0<<2) | (MAN_C1>>3))
+#define PROD_ID1 (u_char)(((MAN_C1<<5) & 0xff) | MAN_C2)
+#define PROD_ID2 (u_char)(1) /* prod. nr. */
+#define PROD_ID3 (u_char)(0) /* rev. nr. */
+
+#ifndef OEM_USER_DATA
+#define OEM_USER_DATA "SK-NET FDDI V2.0 Userdata"
+#endif
+#else /* OEM_CONCEPT */
+
+/* MAN_C(0|1|2) no longer present (ra). */
+#define PROD_ID0 (u_char)OEM_PROD_ID0
+#define PROD_ID1 (u_char)OEM_PROD_ID1
+#define PROD_ID2 (u_char)OEM_PROD_ID2
+#define PROD_ID3 (u_char)OEM_PROD_ID3
+#endif /* OEM_CONCEPT */
+
+#define SKLOGO PROD_ID0, PROD_ID1, PROD_ID2, PROD_ID3
+#endif /* MULT_OEM */
+
+#define SADDRL (0) /* start address SKLOGO */
+#define SA_MAC (0x10) /* start addr. MAC_AD within the PROM */
+#define PRA_OFF (4)
+#define SA_PMD_TYPE (8) /* start addr. PMD-Type */
+
+#define SKFDDI_PSZ 32 /* address PROM size */
+
+/*
+ * address transmision from logical to physical offset address on board
+ */
+#define FMA(a) (0x0400|((a)<<1)) /* FORMAC+ (r/w) */
+#define P1A(a) (0x0800|((a)<<1)) /* PLC1 (r/w) */
+#define P2A(a) (0x0840|((a)<<1)) /* PLC2 (r/w) */
+#define TIA(a) (0x0880|((a)<<1)) /* Timer (r/w) */
+#define PRA(a) (0x0c80| (a)) /* configuration PROM */
+#define C0A(a) (0x0c84| (a)) /* config. RAM */
+#define C1A(a) (0x0ca0| (a)) /* IRQ-, DMA-nr., EPROM type */
+#define C2A(a) (0x0ca4| (a)) /* EPROM and PAGE selector */
+
+#define CONF C0A(0) /* config RAM (card enable bit port) */
+#define PGRA C2A(0) /* Flash page register */
+#define CDID PRA(0) /* Card ID I/O port addr. offset */
+
+
+/*
+ * physical address offset + slot specific IO-Port base address
+ */
+#define FM_A(a) (FMA(a)+smc->hw.iop) /* FORMAC Plus physical addr */
+#define P1_A(a) (P1A(a)+smc->hw.iop) /* PLC1 (r/w) */
+#define P2_A(a) (P2A(a)+smc->hw.iop) /* PLC2 (r/w) */
+#define TI_A(a) (TIA(a)+smc->hw.iop) /* Timer (r/w) */
+#define PR_A(a) (PRA(a)+smc->hw.iop) /* config. PROM */
+#define C0_A(a) (C0A(a)+smc->hw.iop) /* config. RAM */
+#define C1_A(a) (C1A(a)+smc->hw.iop) /* config. RAM */
+#define C2_A(a) (C2A(a)+smc->hw.iop) /* config. RAM */
+
+
+#define CSRA 0x0008 /* control/status register address (r/w) */
+#define ISRA 0x0008 /* int. source register address (upper 8Bits) */
+#define PLC1I 0x001a /* clear PLC1 interrupt (write only) */
+#define PLC2I 0x0020 /* clear PLC2 interrupt (write only) */
+#define CSFA 0x001c /* control/status FIFO BUSY flags (read only) */
+#define RQAA 0x001c /* Request reg. (write only) */
+#define WCTA 0x001e /* word counter (r/w) */
+#define FFLAG 0x005e /* FLAG/V_FULL (FIFO almost full, write only)*/
+
+#define CSR_A (CSRA+smc->hw.iop) /* control/status register address (r/w) */
+#ifdef UNIX
+#define CSR_AS(smc) (CSRA+(smc)->hw.iop) /* control/status register address (r/w) */
+#endif
+#define ISR_A (ISRA+smc->hw.iop) /* int. source register address (upper 8Bits) */
+#define PLC1_I (PLC1I+smc->hw.iop) /* clear PLC1 internupt (write only) */
+#define PLC2_I (PLC2I+smc->hw.iop) /* clear PLC2 interrupt (write only) */
+#define CSF_A (CSFA+smc->hw.iop) /* control/status FIFO BUSY flags (r/w) */
+#define RQA_A (RQAA+smc->hw.iop) /* Request reg. (write only) */
+#define WCT_A (WCTA+smc->hw.iop) /* word counter (r/w) */
+#define FFLAG_A (FFLAG+smc->hw.iop) /* FLAG/V_FULL (FIFO almost full, write only)*/
+
+/*
+ * control/status register CSRA bits
+ */
+/* write */
+#define CS_CRESET 0x01 /* Card reset (0=reset) */
+#define CS_RESET_FIFO 0x02 /* FIFO reset (0=reset) */
+#define CS_IMSK 0x04 /* enable IRQ (1=enable, 0=disable) */
+#define CS_EN_IRQ_TC 0x08 /* enable IRQ from transfer counter */
+#define CS_BYPASS 0x20 /* bypass switch (0=remove, 1=insert)*/
+#define CS_LED_0 0x40 /* switch LED 0 */
+#define CS_LED_1 0x80 /* switch LED 1 */
+/* read */
+#define CS_BYSTAT 0x40 /* 0=Bypass exist, 1= ..not */
+#define CS_SAS 0x80 /* single attachement station (=1) */
+
+/*
+ * control/status register CSFA bits (FIFO)
+ */
+#define CSF_MUX0 0x01
+#define CSF_MUX1 0x02
+#define CSF_HSREQ0 0x04
+#define CSF_HSREQ1 0x08
+#define CSF_HSREQ2 0x10
+#define CSF_BUSY_DMA 0x40
+#define CSF_BUSY_FIFO 0x80
+
+/*
+ * Interrupt source register ISRA (upper 8 data bits) read only & low activ.
+ */
+#define IS_MINTR1 0x0100 /* FORMAC ST1U/L & ~IMSK1U/L*/
+#define IS_MINTR2 0x0200 /* FORMAC ST2U/L & ~IMSK2U/L*/
+#define IS_PLINT1 0x0400 /* PLC1 */
+#define IS_PLINT2 0x0800 /* PLC2 */
+#define IS_TIMINT 0x1000 /* Timer 82C54-2 */
+#define IS_TC 0x2000 /* transf. counter */
+
+#define ALL_IRSR (IS_MINTR1|IS_MINTR2|IS_PLINT1|IS_PLINT2|IS_TIMINT|IS_TC)
+
+/*
+ * CONFIG<0> RAM (C0_A())
+ */
+#define CFG_CARD_EN 0x01 /* card enable */
+
+/*
+ * CONFIG<1> RAM (C1_A())
+ */
+#define CFG_IRQ_SEL 0x03 /* IRQ select (4 nr.) */
+#define CFG_IRQ_TT 0x04 /* IRQ trigger type (LEVEL/EDGE) */
+#define CFG_DRQ_SEL 0x18 /* DMA requ. (4 nr.) */
+#define CFG_BOOT_EN 0x20 /* 0=BOOT-, 1=Application Software */
+#define CFG_PROG_EN 0x40 /* V_Prog for FLASH_PROM (1=on) */
+
+/*
+ * CONFIG<2> RAM (C2_A())
+ */
+#define CFG_EPROM_SEL 0x0f /* FPROM start address selection */
+#define CFG_PAGE 0xf0 /* FPROM page selection */
+
+
+#define READ_PROM(a) ((u_char)inp(a))
+#define GET_PAGE(i) outp(C2_A(0),((int)(i)<<4) | (inp(C2_A(0)) & ~CFG_PAGE))
+#define FPROM_SW() (inp(C1_A(0)) & CFG_BOOT_EN)
+
+#define MAX_PAGES 16 /* 16 pages */
+#define MAX_FADDR 0x2000 /* 8K per page */
+#define VPP_ON() outp(C1_A(0),inp(C1_A(0)) | CFG_PROG_EN)
+#define VPP_OFF() outp(C1_A(0),inp(C1_A(0)) & ~CFG_PROG_EN)
+
+#define DMA_BUSY() (inpw(CSF_A) & CSF_BUSY_DMA)
+#define FIFO_BUSY() (inpw(CSF_A) & CSF_BUSY_FIFO)
+#define DMA_FIFO_BUSY() (inpw(CSF_A) & (CSF_BUSY_DMA | CSF_BUSY_FIFO))
+#define BUS_CHECK()
+
+#ifdef UNISYS
+/* For UNISYS use another macro with drv_usecewait function */
+#define CHECK_DMA() {u_long k = 1000000; \
+ while (k && (DMA_BUSY())) { k--; drv_usecwait(20); } \
+ if (!k) SMT_PANIC(smc,HWM_E0003,HWM_E0003_MSG) ; }
+#else
+#define CHECK_DMA() {u_long k = 1000000 ;\
+ while (k && (DMA_BUSY())) k-- ;\
+ if (!k) SMT_PANIC(smc,HWM_E0003,HWM_E0003_MSG) ; }
+#endif
+
+#define CHECK_FIFO() {u_long k = 1000000 ;\
+ while (k && (FIFO_BUSY())) k-- ;\
+ if (!k) SMT_PANIC(smc,HWM_E0019,HWM_E0019_MSG) ; }
+
+#define CHECK_DMA_FIFO() {u_long k = 1000000 ;\
+ while (k && (DMA_FIFO_BUSY())) k-- ;\
+ if (!k) SMT_PANIC(smc,HWM_E0004,HWM_E0004_MSG) ; }
+
+#define GET_ISR() ~inpw(ISR_A)
+#define CHECK_ISR() ~inpw(ISR_A)
+
+#ifndef UNIX
+#ifndef WINNT
+#define CLI_FBI() outpw(CSR_A,(inpw(CSR_A)&\
+ (CS_CRESET|CS_BYPASS))|CS_RESET_FIFO|smc->hw.led)
+#else /* WINNT */
+#define CLI_FBI() outpw(CSR_A,(l_inpw(CSR_A)&\
+ (CS_CRESET|CS_BYPASS))|CS_RESET_FIFO|smc->hw.led)
+#endif /* WINNT */
+#else /* UNIX */
+#define CLI_FBI(smc) outpw(CSR_AS(smc),(inpw(CSR_AS(smc))&\
+ (CS_CRESET|CS_BYPASS))|CS_RESET_FIFO|(smc)->hw.led)
+#endif
+
+#ifndef UNIX
+#define STI_FBI() outpw(CSR_A,(inpw(CSR_A)&\
+ (CS_CRESET|CS_BYPASS|CS_RESET_FIFO))|CS_IMSK|smc->hw.led)
+#else
+#define STI_FBI(smc) outpw(CSR_AS(smc),(inpw(CSR_AS(smc))&\
+ (CS_CRESET|CS_BYPASS|CS_RESET_FIFO))|CS_IMSK|(smc)->hw.led)
+#endif
+
+/* EISA DMA Controller */
+#define DMA_WRITE_SINGLE_MASK_BIT_M 0x0a /* Master DMA Controller */
+#define DMA_WRITE_SINGLE_MASK_BIT_S 0xd4 /* Slave DMA Controller */
+#define DMA_CLEAR_BYTE_POINTER_M 0x0c
+#define DMA_CLEAR_BYTE_POINTER_S 0xd8
+
+#endif /* EISA */
+
+#ifdef MCA
+
+/*
+ * POS Register: !! all I/O's are 8-Bit !!
+ */
+#define POS_SYS_SETUP 0x94 /* system setup register */
+#define POS_SYSTEM 0xff /* system mode */
+
+#define POS_CHANNEL_POS 0x96 /* register slot ID */
+#define POS_CHANNEL_BIT 0x08 /* mask for -"- */
+
+#define POS_BASE 0x100 /* POS base address */
+#define POS_ID_LOW POS_BASE /* card ID low */
+#define POS_ID_HIGH (POS_BASE+1) /* card ID high */
+#define POS_102 (POS_BASE+2) /* card en., arbitration level .. */
+#define POS_103 (POS_BASE+3) /* FPROM addr, page */
+#define POS_104 (POS_BASE+4) /* I/O, IRQ */
+#define POS_105 (POS_BASE+5) /* POS_CHCK */
+#define POS_106 (POS_BASE+6) /* to read VPD */
+#define POS_107 (POS_BASE+7) /* added without function */
+
+/* FM1 card IDs */
+#define FM1_CARD_ID0 0x83
+#define FM1_CARD_ID1 0
+
+#define FM1_IBM_ID0 0x9c
+#define FM1_IBM_ID1 0x8f
+
+
+/* FM2 card IDs */
+#define FM2_CARD_ID0 0xab
+#define FM2_CARD_ID1 0
+
+#define FM2_IBM_ID0 0x7e
+#define FM2_IBM_ID1 0x8f
+
+/* Board revision. */
+#define FM1_REV 0
+#define FM2_REV 1
+
+#define MAX_SLOT 8
+
+/*
+ * POS_102
+ */
+#define POS_CARD_EN 0x01 /* card enable =1 */
+#define POS_SDAT_EN 0x02 /* enable 32-bit streaming data mode */
+#define POS_EN_CHKINT 0x04 /* enable int. from check line asserted */
+#define POS_EN_BUS_ERR 0x08 /* enable int. on invalid busmaster transf. */
+#define POS_FAIRNESS 0x10 /* fairnes on =1 */
+/* attention: arbitration level used with bit 0 POS 105 */
+#define POS_LARBIT 0xe0 /* arbitration level (0,0,0)->level = 0x8
+ (1,1,1)->level = 0xf */
+/*
+ * POS_103
+ */
+#define POS_PAGE 0x07 /* FPROM page selection */
+#define POS_BOOT_EN 0x08 /* boot PROM enable =1 */
+#define POS_MSEL 0x70 /* memory start address for FPROM mapping */
+#define PROG_EN 0x80 /* FM1: Vpp prog on/off */
+#define POS_SDR 0x80 /* FM2: Streaming data bit */
+
+/*
+ * POS_104
+ */
+#define POS_IOSEL 0x3f /* selected I/O base address */
+#define POS_IRQSEL 0xc0 /* selected interrupt */
+
+/*
+ * POS_105
+ */
+#define POS_CHCK 0x80
+#define POS_SYNC_ERR 0x20 /* FM2: synchronous error reporting */
+#define POS_PAR_DATA 0x10 /* FM2: data parity enable bit */
+#define POS_PAR_ADDR 0x08 /* FM2: address parity enable bit */
+#define POS_IRQHSEL 0x02 /* FM2: Highest bit for IRQ_selection */
+#define POS_HARBIT 0x01 /* Highest bit in Bus arbitration selection */
+
+#define SA_MAC (0) /* start addr. MAC_AD within the PROM */
+#define PRA_OFF (0)
+#define SA_PMD_TYPE (8) /* start addr. PMD-Type */
+
+/*
+ * address transmision from logical to physical offset address on board
+ */
+#define FMA(a) (0x0100|((a)<<1)) /* FORMAC+ (r/w) */
+#define P2(a) (0x00c0|((a)<<1)) /* PLC2 (r/w) (DAS) */
+#define P1(a) (0x0080|((a)<<1)) /* PLC1 (r/w) */
+#define TI(a) (0x0060|((a)<<1)) /* Timer (r/w) */
+#define PR(a) (0x0040|((a)<<1)) /* configuration PROM */
+#define CS(a) (0x0020| (a)) /* control/status */
+#define FF(a) (0x0010|((a)<<1)) /* FIFO ASIC */
+#define CT(a) (0x0000|((a)<<1)) /* counter */
+
+/*
+ * counter
+ */
+#define ACLA CT(0) /* address counter low */
+#define ACHA CT(1) /* address counter high */
+#define BCN CT(2) /* byte counter */
+#define MUX CT(3) /* MUX-register */
+#define WCN CT(0x08) /* word counter */
+#define FFLG CT(0x09) /* FIFO Flags */
+
+/*
+ * test/control register (FM2 only)
+ */
+#define CNT_TST 0x018 /* Counter test control register */
+#define CNT_STP 0x01a /* Counter test step reg. (8 Bit) */
+
+/*
+ * CS register (read only)
+ */
+#define CSRA CS(0) /* control/status register address */
+#define CSFA CS(2) /* control/status FIFO BUSY ... */
+#define ISRA CS(4) /* first int. source register address */
+#define ISR2 CS(6) /* second int. source register address */
+#define LEDR CS(0x0c) /* LED register r/w */
+#define CSIL CS(0x10) /* I/O mapped POS_ID_low (100) */
+#define CSIH CS(0x12) /* - " - POS_ID_HIGH (101) */
+#define CSA CS(0x14) /* - " - POS_102 */
+#define CSM CS(0x0e) /* - " - POS_103 */
+#define CSM_FM1 CS(0x16) /* - " - POS_103 (copy in FM1) */
+#define CSI CS(0x18) /* - " - POS_104 */
+#define CSS CS(0x1a) /* - " - POS_105 */
+#define CSP_06 CS(0x1c) /* - " - POS_106 */
+#define WDOG_ST 0x1c /* Watchdog status (FM2 only) */
+#define WDOG_EN 0x1c /* Watchdog enabling (FM2 only, 8Bit) */
+#define WDOG_DIS 0x1e /* Watchdog disabling (FM2 only, 8Bit) */
+
+#define PGRA CSM /* Flash page register */
+
+
+#define WCTA FF(0) /* word counter */
+#define FFLAG FF(1) /* FLAG/V_FULL (FIFO almost full, write only)*/
+
+/*
+ * Timer register (FM2 only)
+ */
+#define RTM_CNT 0x28 /* RTM Counter */
+#define TI_DIV 0x60 /* Timer Prescaler */
+#define TI_CH1 0x62 /* Timer channel 1 counter */
+#define TI_STOP 0x64 /* Stop timer on channel 1 */
+#define TI_STRT 0x66 /* Start timer on channel 1 */
+#define TI_INI2 0x68 /* Timer: Bus master preemption */
+#define TI_CNT2 0x6a /* Timer */
+#define TI_INI3 0x6c /* Timer: Streaming data */
+#define TI_CNT3 0x6e /* Timer */
+#define WDOG_LO 0x70 /* Watchdog counter low */
+#define WDOG_HI 0x72 /* Watchdog counter high */
+#define RTM_PRE 0x74 /* restr. token prescaler */
+#define RTM_TIM 0x76 /* restr. token timer */
+
+/*
+ * Recommended Timeout values (for FM2 timer only)
+ */
+#define TOUT_BM_PRE 188 /* 3.76 usec */
+#define TOUT_S_DAT 374 /* 7.48 usec */
+
+/*
+ * CS register (write only)
+ */
+#define HSR(p) CS(0x18|(p)) /* Host request register */
+
+#define RTM_PUT 0x36 /* restr. token counter write */
+#define RTM_GET 0x28 /* - " - clear */
+#define RTM_CLEAR 0x34 /* - " - read */
+
+/*
+ * BCN Bit definitions
+ */
+#define BCN_BUSY 0x8000 /* DMA Busy flag */
+#define BCN_AZERO 0x4000 /* Almost zero flag (BCN < 4) */
+#define BCN_STREAM 0x2000 /* Allow streaming data (BCN >= 8) */
+
+/*
+ * WCN Bit definitions
+ */
+#define WCN_ZERO 0x2000 /* Zero flag (counted to zero) */
+#define WCN_AZERO 0x1000 /* Almost zero flag (BCN < 4) */
+
+/*
+ * CNT_TST Bit definitions
+ */
+#define CNT_MODE 0x01 /* Go into test mode */
+#define CNT_D32 0x02 /* 16/32 BIT test mode */
+
+/*
+ * FIFO Flag FIFO Flags/Vfull register
+ */
+#define FF_VFULL 0x003f /* V_full value mask */
+#define FFLG_FULL 0x2000 /* FULL flag */
+#define FFLG_A_FULL 0x1000 /* Almost full flag */
+#define FFLG_VFULL 0x0800 /* V_full Flag */
+#define FFLG_A_EMP 0x0400 /* almost empty flag */
+#define FFLG_EMP 0x0200 /* empty flag */
+#define FFLG_T_EMP 0x0100 /* totally empty flag */
+
+/*
+ * WDOG Watchdog status register
+ */
+#define WDOG_ALM 0x01 /* Watchdog alarm Bit */
+#define WDOG_ACT 0x02 /* Watchdog active Bit */
+
+/*
+ * CS(0) CONTROLS
+ */
+#define CS_CRESET 0x0001
+#define FIFO_RST 0x0002
+#define CS_IMSK 0x0004
+#define EN_IRQ_CHCK 0x0008
+#define EN_IRQ_TOKEN 0x0010
+#define EN_IRQ_TC 0x0020
+#define TOKEN_STATUS 0x0040
+#define RTM_CHANGE 0x0080
+
+#define CS_SAS 0x0100
+#define CS_BYSTAT 0x0200 /* bypass connected (0=conn.) */
+#define CS_BYPASS 0x0400 /* bypass on/off indication */
+
+/*
+ * CS(2) FIFOSTAT
+ */
+#define HSREQ 0x0007
+#define BIGDIR 0x0008
+#define CSF_BUSY_FIFO 0x0010
+#define CSF_BUSY_DMA 0x0020
+#define SLOT_32 0x0040
+
+#define LED_0 0x0001
+#define LED_1 0x0002
+#define LED_2 0x0100
+
+#define MAX_PAGES 8 /* pages */
+#define MAX_FADDR 0x4000 /* 16K per page */
+
+/*
+ * IRQ = ISRA || ISR2 ;
+ *
+ * ISRA = IRQ_OTH_EN && (IS_LAN | IS_BUS) ;
+ * ISR2 = IRQ_TC_EN && IS_TC ;
+ *
+ * IS_LAN = (IS_MINTR1 | IS_MINTR2 | IS_PLINT1 | IS_PLINT2 | IS_TIMINT) ||
+ * (IRQ_EN_TOKEN && IS_TOKEN) ;
+ * IS_BUS = IRQ_CHCK_EN && (IS_BUSERR | IS_CHCK_L) ;
+ */
+/*
+ * ISRA !!! activ high !!!
+ */
+#define IS_MINTR1 0x0001 /* FORMAC ST1U/L & ~IMSK1U/L*/
+#define IS_MINTR2 0x0002 /* FORMAC ST2U/L & ~IMSK2U/L*/
+#define IS_PLINT1 0x0004 /* PLC1 */
+#define IS_PLINT2 0x0008 /* PLC2 */
+#define IS_TIMINT 0x0010 /* Timer 82C54-2 */
+#define IS_TOKEN 0x0020 /* restrictet token monitoring */
+#define IS_CHCK_L 0x0040 /* check line asserted */
+#define IS_BUSERR 0x0080 /* bus error */
+/*
+ * ISR2
+ */
+#define IS_TC 0x0001 /* terminal count irq */
+#define IS_SFDBKRTN 0x0002 /* selected feedback return */
+#define IS_D16 0x0004 /* DS16 */
+#define IS_D32 0x0008 /* DS32 */
+#define IS_DPEI 0x0010 /* Data Parity Indication */
+
+#define ALL_IRSR 0x00ff
+
+#define FM_A(a) ADDR(FMA(a)) /* FORMAC Plus physical addr */
+#define P1_A(a) ADDR(P1(a)) /* PLC1 (r/w) */
+#define P2_A(a) ADDR(P2(a)) /* PLC2 (r/w) (DAS) */
+#define TI_A(a) ADDR(TI(a)) /* Timer (r/w) FM1 only! */
+#define PR_A(a) ADDR(PR(a)) /* config. PROM */
+#define CS_A(a) ADDR(CS(a)) /* control/status */
+
+#define ISR1_A ADDR(ISRA) /* first int. source register address */
+#define ISR2_A ADDR(ISR2) /* second -"- */
+#define CSR_A ADDR(CSRA) /* control/status register address */
+#define CSF_A ADDR(CSFA) /* control/status FIFO BUSY flags (r/w) */
+
+#define CSIL_A ADDR(CSIL) /* I/O mapped POS_ID_low (102) */
+#define CSIH_A ADDR(CSIH) /* - " - POS_ID_HIGH (101) */
+#define CSA_A ADDR(CSA) /* - " - POS_102 */
+#define CSI_A ADDR(CSI) /* - " - POS_104 */
+#define CSM_A ADDR(CSM) /* - " - POS_103 */
+#define CSM_FM1_A ADDR(CSM_FM1) /* - " - POS_103 (2nd copy, FM1) */
+#define CSP_06_A ADDR(CSP_06) /* - " - POS_106 */
+
+#define WCT_A ADDR(WCTA) /* word counter (r/w) */
+#define FFLAG_A ADDR(FFLAG) /* FLAG/V_FULL (FIFO almost full, write only)*/
+
+#define ACL_A ADDR(ACLA) /* address counter low */
+#define ACH_A ADDR(ACHA) /* address counter high */
+#define BCN_A ADDR(BCN) /* byte counter */
+#define MUX_A ADDR(MUX) /* MUX-register */
+
+#define ISR_A ADDR(ISRA) /* Interrupt Source Register */
+#define FIFO_RESET_A ADDR(FIFO_RESET) /* reset the FIFO */
+#define FIFO_EN_A ADDR(FIFO_EN) /* enable the FIFO */
+
+#define WDOG_EN_A ADDR(WDOG_EN) /* reset and start the WDOG */
+#define WDOG_DIS_A ADDR(WDOG_DIS) /* disable the WDOG */
+/*
+ * all control reg. (read!) are 8 bit (except PAGE_RG_A and LEDR_A)
+ */
+#define HSR_A(p) ADDR(HSR(p)) /* Host request register */
+
+#define STAT_BYP 0 /* bypass station */
+#define STAT_INS 2 /* insert station */
+#define BYPASS(o) CS(0x10|(o)) /* o=STAT_BYP || STAT_INS */
+
+#define IRQ_TC_EN CS(0x0b) /* enable/disable IRQ on TC */
+#define IRQ_TC_DIS CS(0x0a)
+#define IRQ_TOKEN_EN CS(9) /* enable/disable IRQ on restr. Token */
+#define IRQ_TOKEN_DIS CS(8)
+#define IRQ_CHCK_EN CS(7) /* -"- IRQ after CHCK line */
+#define IRQ_CHCK_DIS CS(6)
+#define IRQ_OTH_EN CS(5) /* -"- other IRQ's */
+#define IRQ_OTH_DIS CS(4)
+#define FIFO_EN CS(3) /* disable (reset), enable FIFO */
+#define FIFO_RESET CS(2)
+#define CARD_EN CS(1) /* disable (reset), enable card */
+#define CARD_DIS CS(0)
+
+#define LEDR_A ADDR(LEDR) /* D0=green, D1=yellow, D8=L2 */
+#define PAGE_RG_A ADDR(CSM) /* D<2..0> */
+#define IRQ_CHCK_EN_A ADDR(IRQ_CHCK_EN)
+#define IRQ_CHCK_DIS_A ADDR(IRQ_CHCK_DIS)
+
+#define GET_PAGE(bank) outpw(PAGE_RG_A,(inpw(PAGE_RG_A) &\
+ (~POS_PAGE)) |(int) (bank))
+#define VPP_ON() if (smc->hw.rev == FM1_REV) { \
+ outpw(PAGE_RG_A, \
+ (inpw(PAGE_RG_A) & POS_PAGE) | PROG_EN); \
+ }
+#define VPP_OFF() if (smc->hw.rev == FM1_REV) { \
+ outpw(PAGE_RG_A,(inpw(PAGE_RG_A) & POS_PAGE)); \
+ }
+
+#define SKFDDI_PSZ 16 /* address PROM size */
+
+#define READ_PROM(a) ((u_char)inp(a))
+
+#define GET_ISR() ~inpw(ISR1_A)
+#ifndef TCI
+#define CHECK_ISR() ~inpw(ISR1_A)
+#define CHECK_ISR_SMP(iop) ~inpw((iop)+ISRA)
+#else
+#define CHECK_ISR() (~inpw(ISR1_A) | ~inpw(ISR2_A))
+#define CHECK_ISR_SMP(iop) (~inpw((iop)+ISRA) | ~inpw((iop)+ISR2))
+#endif
+
+#define DMA_BUSY() (inpw(CSF_A) & CSF_BUSY_DMA)
+#define FIFO_BUSY() (inpw(CSF_A) & CSF_BUSY_FIFO)
+#define DMA_FIFO_BUSY() (inpw(CSF_A) & (CSF_BUSY_DMA | CSF_BUSY_FIFO))
+#define BUS_CHECK() { int i ; \
+ if ((i = GET_ISR()) & IS_BUSERR) \
+ SMT_PANIC(smc,HWM_E0020,HWM_E0020_MSG) ; \
+ if (i & IS_CHCK_L) \
+ SMT_PANIC(smc,HWM_E0014,HWM_E0014_MSG) ; \
+ }
+
+#define CHECK_DMA() { u_long k = 10000 ; \
+ while (k && (DMA_BUSY())) { \
+ k-- ; \
+ BUS_CHECK() ; \
+ } \
+ if (!k) SMT_PANIC(smc,HWM_E0003,HWM_E0003_MSG) ; }
+
+#define CHECK_FIFO() {u_long k = 1000000 ;\
+ while (k && (FIFO_BUSY())) k-- ;\
+ if (!k) SMT_PANIC(smc,HWM_E0019,HWM_E0019_MSG) ; }
+
+#define CHECK_DMA_FIFO() {u_long k = 1000000 ;\
+ while (k && (DMA_FIFO_BUSY())) { \
+ k-- ;\
+ BUS_CHECK() ; \
+ } \
+ if (!k) SMT_PANIC(smc,HWM_E0004,HWM_E0004_MSG) ; }
+
+#ifndef UNIX
+#define CLI_FBI() outp(ADDR(IRQ_OTH_DIS),0)
+#else
+#define CLI_FBI(smc) outp(ADDRS((smc),IRQ_OTH_DIS),0)
+#endif
+
+#ifndef TCI
+#define CLI_FBI_SMP(iop) outp((iop)+IRQ_OTH_DIS,0)
+#else
+#define CLI_FBI_SMP(iop) outp((iop)+IRQ_OTH_DIS,0) ;\
+ outp((iop)+IRQ_TC_DIS,0)
+#endif
+
+#ifndef UNIX
+#define STI_FBI() outp(ADDR(IRQ_OTH_EN),0)
+#else
+#define STI_FBI(smc) outp(ADDRS((smc),IRQ_OTH_EN),0)
+#endif
+
+/*
+ * Terminal count primitives
+ */
+#define CLI_TCI(smc) outp(ADDRS((smc),IRQ_TC_DIS),0)
+#define STI_TCI(smc) outp(ADDRS((smc),IRQ_TC_EN),0)
+#define CHECK_TC(smc,k) {(k) = 10000 ;\
+ while ((k) && (~inpw(ISR2_A) & IS_TC)) (k)-- ;\
+ if (!k) SMT_PANIC(smc,HWM_E0018,HWM_E0018_MSG) ; }
+
+#endif /* MCA */
+
+#ifdef ISA
+
+/*
+ * address transmision from logic NPADDR6-0 to physical offset address on board
+ */
+#define FMA(a) (0x8000|(((a)&0x07)<<1)|(((a)&0x78)<<7)) /* FORMAC+ (r/w) */
+#define PRA(a) (0x1000|(((a)&0x07)<<1)|(((a)&0x18)<<7)) /* PROM (read only)*/
+#define P1A(a) (0x4000|(((a)&0x07)<<1)|(((a)&0x18)<<7)) /* PLC1 (r/w) */
+#define P2A(a) (0x5000|(((a)&0x07)<<1)|(((a)&0x18)<<7)) /* PLC2 (r/w) */
+#define TIA(a) (0x6000|(((a)&0x03)<<1)) /* Timer (r/w) */
+
+#define ISRA 0x0000 /* int. source register address (read only) */
+#define ACLA 0x0000 /* address counter low address (write only) */
+#define ACHA 0x0002 /* address counter high address (write only) */
+#define TRCA 0x0004 /* transfer counter address (write only) */
+#define PGRA 0x0006 /* page register address (write only) */
+#define RQAA 0x2000 /* Request reg. (write only) */
+#define CSRA 0x3000 /* control/status register address (r/w) */
+
+/*
+ * physical address offset + IO-Port base address
+ */
+#define FM_A(a) (FMA(a)+smc->hw.iop) /* FORMAC Plus physical addr */
+#define PR_A(a) (PRA(a)+smc->hw.iop) /* PROM (read only)*/
+#define P1_A(a) (P1A(a)+smc->hw.iop) /* PLC1 (r/w) */
+#define P2_A(a) (P2A(a)+smc->hw.iop) /* PLC2 (r/w) */
+#define TI_A(a) (TIA(a)+smc->hw.iop) /* Timer (r/w) */
+
+#define ISR_A (0x0000+smc->hw.iop) /* int. source register address (read only) */
+#define ACL_A (0x0000+smc->hw.iop) /* address counter low address (write only) */
+#define ACH_A (0x0002+smc->hw.iop) /* address counter high address (write only)*/
+#define TRC_A (0x0004+smc->hw.iop) /* transfer counter address (write only) */
+#define PGR_A (0x0006+smc->hw.iop) /* page register address (write only) */
+#define RQA_A (0x2000+smc->hw.iop) /* Request reg. (write only) */
+#define CSR_A (0x3000+smc->hw.iop) /* control/status register address (r/w) */
+#ifdef UNIX
+#define CSR_AS(smc) (0x3000+(smc)->hw.iop) /* control/status register address */
+#endif
+#define PLC1_I (0x3400+smc->hw.iop) /* clear PLC1 interrupt bit */
+#define PLC2_I (0x3800+smc->hw.iop) /* clear PLC2 interrupt bit */
+
+#ifndef MULT_OEM
+#ifndef OEM_CONCEPT
+#define SKLOGO_STR "SKFDDI"
+#else /* OEM_CONCEPT */
+#define SKLOGO_STR OEM_FDDI_LOGO
+#endif /* OEM_CONCEPT */
+#endif /* MULT_OEM */
+#define SADDRL (24) /* start address SKLOGO */
+#define SA_MAC (0) /* start addr. MAC_AD within the PROM */
+#define PRA_OFF (0)
+#define SA_PMD_TYPE (8) /* start addr. PMD-Type */
+
+#define CDID (PRA(SADDRL)) /* Card ID int/O port addr. offset */
+#define NEXT_CDID ((PRA(SADDRL+1)) - CDID)
+
+#define SKFDDI_PSZ 32 /* address PROM size */
+
+#define READ_PROM(a) ((u_char)inpw(a))
+#define GET_PAGE(i) outpw(PGR_A,(int)(i))
+
+#define MAX_PAGES 16 /* 16 pages */
+#define MAX_FADDR 0x2000 /* 8K per page */
+#define VPP_OFF() outpw(CSR_A,(inpw(CSR_A) & (CS_CRESET|CS_BYPASS)))
+#define VPP_ON() outpw(CSR_A,(inpw(CSR_A) & (CS_CRESET|CS_BYPASS)) | \
+ CS_VPPSW)
+
+/*
+ * control/status register CSRA bits (log. addr: 0x3000)
+ */
+/* write */
+#define CS_CRESET 0x01 /* Card reset (0=reset) */
+#define CS_IMSK 0x02 /* enable IRQ (1=enable, 0=disable) */
+#define CS_RESINT1 0x04 /* PLINT1 reset */
+#define CS_VPPSW 0x10 /* 12V power switch (0=off, 1=on) */
+#define CS_BYPASS 0x20 /* bypass switch (0=remove, 1=insert)*/
+#define CS_RESINT2 0x40 /* PLINT2 reset */
+/* read */
+#define CS_BUSY 0x04 /* master transfer activ (=1) */
+#define CS_SW_EPROM 0x08 /* 0=Application Soft. 1=BOOT-EPROM */
+#define CS_BYSTAT 0x40 /* 0=Bypass exist, 1= ..not */
+#define CS_SAS 0x80 /* single attachement station (=1) */
+
+/*
+ * Interrupt source register ISRA (log. addr: 0x0000) read only & low activ.
+ */
+#define IS_MINTR1 0x01 /* FORMAC ST1U/L && ~IMSK1U/L*/
+#define IS_MINTR2 0x02 /* FORMAC ST2U/L && ~IMSK2U/L*/
+#define IS_PLINT1 0x04 /* PLC1 */
+#define IS_PLINT2 0x08 /* PLC2 */
+#define IS_TIMINT 0x10 /* Timer 82C54-2 */
+
+#define ALL_IRSR (IS_MINTR1|IS_MINTR2|IS_PLINT1|IS_PLINT2|IS_TIMINT)
+
+#define FPROM_SW() (inpw(CSR_A)&CS_SW_EPROM)
+#define DMA_BUSY() (inpw(CSR_A)&CS_BUSY)
+#define CHECK_FIFO()
+#define BUS_CHECK()
+
+/*
+ * set Host Request register (wr.)
+ */
+#define SET_HRQ(qup) outpw(RQA_A+((qup)<<1),0)
+
+#ifndef UNIX
+#ifndef WINNT
+#define CLI_FBI() outpw(CSR_A,(inpw(CSR_A)&(CS_CRESET|CS_BYPASS|CS_VPPSW)))
+#else
+#define CLI_FBI() outpw(CSR_A,(l_inpw(CSR_A) & \
+ (CS_CRESET|CS_BYPASS|CS_VPPSW)))
+#endif
+#else
+#define CLI_FBI(smc) outpw(CSR_AS(smc),(inpw(CSR_AS(smc))& \
+ (CS_CRESET|CS_BYPASS|CS_VPPSW)))
+#endif
+
+#ifndef UNIX
+#define STI_FBI() outpw(CSR_A,(inpw(CSR_A) & \
+ (CS_CRESET|CS_BYPASS|CS_VPPSW)) | CS_IMSK)
+#else
+#define STI_FBI(smc) outpw(CSR_AS(smc),(inpw(CSR_AS(smc)) & \
+ (CS_CRESET|CS_BYPASS|CS_VPPSW)) | CS_IMSK)
+#endif
+
+#define CHECK_DMA() {unsigned k = 10000 ;\
+ while (k && (DMA_BUSY())) k-- ;\
+ if (!k) SMT_PANIC(smc,HWM_E0003,HWM_E0003_MSG) ; }
+
+#define GET_ISR() ~inpw(ISR_A)
+
+#endif /* ISA */
+
+/*--------------------------------------------------------------------------*/
+#ifdef PCI
+
+/*
+ * (DV) = only defined for Da Vinci
+ * (ML) = only defined for Monalisa
+ */
+
+/*
+ * Configuration Space header
+ */
+#define PCI_VENDOR_ID 0x00 /* 16 bit Vendor ID */
+#define PCI_DEVICE_ID 0x02 /* 16 bit Device ID */
+#define PCI_COMMAND 0x04 /* 16 bit Command */
+#define PCI_STATUS 0x06 /* 16 bit Status */
+#define PCI_REV_ID 0x08 /* 8 bit Revision ID */
+#define PCI_CLASS_CODE 0x09 /* 24 bit Class Code */
+#define PCI_CACHE_LSZ 0x0c /* 8 bit Cache Line Size */
+#define PCI_LAT_TIM 0x0d /* 8 bit Latency Timer */
+#define PCI_HEADER_T 0x0e /* 8 bit Header Type */
+#define PCI_BIST 0x0f /* 8 bit Built-in selftest */
+#define PCI_BASE_1ST 0x10 /* 32 bit 1st Base address */
+#define PCI_BASE_2ND 0x14 /* 32 bit 2nd Base address */
+/* Byte 18..2b: Reserved */
+#define PCI_SUB_VID 0x2c /* 16 bit Subsystem Vendor ID */
+#define PCI_SUB_ID 0x2e /* 16 bit Subsystem ID */
+#define PCI_BASE_ROM 0x30 /* 32 bit Expansion ROM Base Address */
+/* Byte 34..33: Reserved */
+#define PCI_CAP_PTR 0x34 /* 8 bit (ML) Capabilities Ptr */
+/* Byte 35..3b: Reserved */
+#define PCI_IRQ_LINE 0x3c /* 8 bit Interrupt Line */
+#define PCI_IRQ_PIN 0x3d /* 8 bit Interrupt Pin */
+#define PCI_MIN_GNT 0x3e /* 8 bit Min_Gnt */
+#define PCI_MAX_LAT 0x3f /* 8 bit Max_Lat */
+/* Device Dependent Region */
+#define PCI_OUR_REG 0x40 /* 32 bit (DV) Our Register */
+#define PCI_OUR_REG_1 0x40 /* 32 bit (ML) Our Register 1 */
+#define PCI_OUR_REG_2 0x44 /* 32 bit (ML) Our Register 2 */
+/* Power Management Region */
+#define PCI_PM_CAP_ID 0x48 /* 8 bit (ML) Power Management Cap. ID */
+#define PCI_PM_NITEM 0x49 /* 8 bit (ML) Next Item Ptr */
+#define PCI_PM_CAP_REG 0x4a /* 16 bit (ML) Power Management Capabilities */
+#define PCI_PM_CTL_STS 0x4c /* 16 bit (ML) Power Manag. Control/Status */
+/* Byte 0x4e: Reserved */
+#define PCI_PM_DAT_REG 0x4f /* 8 bit (ML) Power Manag. Data Register */
+/* VPD Region */
+#define PCI_VPD_CAP_ID 0x50 /* 8 bit (ML) VPD Cap. ID */
+#define PCI_VPD_NITEM 0x51 /* 8 bit (ML) Next Item Ptr */
+#define PCI_VPD_ADR_REG 0x52 /* 16 bit (ML) VPD Address Register */
+#define PCI_VPD_DAT_REG 0x54 /* 32 bit (ML) VPD Data Register */
+/* Byte 58..ff: Reserved */
+
+/*
+ * I2C Address (PCI Config)
+ *
+ * Note: The temperature and voltage sensors are relocated on a different
+ * I2C bus.
+ */
+#define I2C_ADDR_VPD 0xA0 /* I2C address for the VPD EEPROM */
+
+/*
+ * Define Bits and Values of the registers
+ */
+/* PCI_VENDOR_ID 16 bit Vendor ID */
+/* PCI_DEVICE_ID 16 bit Device ID */
+/* Values for Vendor ID and Device ID shall be patched into the code */
+/* PCI_COMMAND 16 bit Command */
+#define PCI_FBTEN 0x0200 /* Bit 9: Fast Back-To-Back enable */
+#define PCI_SERREN 0x0100 /* Bit 8: SERR enable */
+#define PCI_ADSTEP 0x0080 /* Bit 7: Address Stepping */
+#define PCI_PERREN 0x0040 /* Bit 6: Parity Report Response enable */
+#define PCI_VGA_SNOOP 0x0020 /* Bit 5: VGA palette snoop */
+#define PCI_MWIEN 0x0010 /* Bit 4: Memory write an inv cycl ena */
+#define PCI_SCYCEN 0x0008 /* Bit 3: Special Cycle enable */
+#define PCI_BMEN 0x0004 /* Bit 2: Bus Master enable */
+#define PCI_MEMEN 0x0002 /* Bit 1: Memory Space Access enable */
+#define PCI_IOEN 0x0001 /* Bit 0: IO Space Access enable */
+
+/* PCI_STATUS 16 bit Status */
+#define PCI_PERR 0x8000 /* Bit 15: Parity Error */
+#define PCI_SERR 0x4000 /* Bit 14: Signaled SERR */
+#define PCI_RMABORT 0x2000 /* Bit 13: Received Master Abort */
+#define PCI_RTABORT 0x1000 /* Bit 12: Received Target Abort */
+#define PCI_STABORT 0x0800 /* Bit 11: Sent Target Abort */
+#define PCI_DEVSEL 0x0600 /* Bit 10..9: DEVSEL Timing */
+#define PCI_DEV_FAST (0<<9) /* fast */
+#define PCI_DEV_MEDIUM (1<<9) /* medium */
+#define PCI_DEV_SLOW (2<<9) /* slow */
+#define PCI_DATAPERR 0x0100 /* Bit 8: DATA Parity error detected */
+#define PCI_FB2BCAP 0x0080 /* Bit 7: Fast Back-to-Back Capability */
+#define PCI_UDF 0x0040 /* Bit 6: User Defined Features */
+#define PCI_66MHZCAP 0x0020 /* Bit 5: 66 MHz PCI bus clock capable */
+#define PCI_NEWCAP 0x0010 /* Bit 4: New cap. list implemented */
+
+#define PCI_ERRBITS (PCI_PERR|PCI_SERR|PCI_RMABORT|PCI_STABORT|PCI_DATAPERR)
+
+/* PCI_REV_ID 8 bit Revision ID */
+/* PCI_CLASS_CODE 24 bit Class Code */
+/* Byte 2: Base Class (02) */
+/* Byte 1: SubClass (02) */
+/* Byte 0: Programming Interface (00) */
+
+/* PCI_CACHE_LSZ 8 bit Cache Line Size */
+/* Possible values: 0,2,4,8,16 */
+
+/* PCI_LAT_TIM 8 bit Latency Timer */
+
+/* PCI_HEADER_T 8 bit Header Type */
+#define PCI_HD_MF_DEV 0x80 /* Bit 7: 0= single, 1= multi-func dev */
+#define PCI_HD_TYPE 0x7f /* Bit 6..0: Header Layout 0= normal */
+
+/* PCI_BIST 8 bit Built-in selftest */
+#define PCI_BIST_CAP 0x80 /* Bit 7: BIST Capable */
+#define PCI_BIST_ST 0x40 /* Bit 6: Start BIST */
+#define PCI_BIST_RET 0x0f /* Bit 3..0: Completion Code */
+
+/* PCI_BASE_1ST 32 bit 1st Base address */
+#define PCI_MEMSIZE 0x800L /* use 2 kB Memory Base */
+#define PCI_MEMBASE_BITS 0xfffff800L /* Bit 31..11: Memory Base Address */
+#define PCI_MEMSIZE_BIIS 0x000007f0L /* Bit 10..4: Memory Size Req. */
+#define PCI_PREFEN 0x00000008L /* Bit 3: Prefetchable */
+#define PCI_MEM_TYP 0x00000006L /* Bit 2..1: Memory Type */
+#define PCI_MEM32BIT (0<<1) /* Base addr anywhere in 32 Bit range */
+#define PCI_MEM1M (1<<1) /* Base addr below 1 MegaByte */
+#define PCI_MEM64BIT (2<<1) /* Base addr anywhere in 64 Bit range */
+#define PCI_MEMSPACE 0x00000001L /* Bit 0: Memory Space Indic. */
+
+/* PCI_BASE_2ND 32 bit 2nd Base address */
+#define PCI_IOBASE 0xffffff00L /* Bit 31..8: I/O Base address */
+#define PCI_IOSIZE 0x000000fcL /* Bit 7..2: I/O Size Requirements */
+#define PCI_IOSPACE 0x00000001L /* Bit 0: I/O Space Indicator */
+
+/* PCI_SUB_VID 16 bit Subsystem Vendor ID */
+/* PCI_SUB_ID 16 bit Subsystem ID */
+
+/* PCI_BASE_ROM 32 bit Expansion ROM Base Address */
+#define PCI_ROMBASE 0xfffe0000L /* Bit 31..17: ROM BASE addres (1st) */
+#define PCI_ROMBASZ 0x0001c000L /* Bit 16..14: Treat as BASE or SIZE */
+#define PCI_ROMSIZE 0x00003800L /* Bit 13..11: ROM Size Requirements */
+#define PCI_ROMEN 0x00000001L /* Bit 0: Address Decode enable */
+
+/* PCI_CAP_PTR 8 bit New Capabilities Pointers */
+/* PCI_IRQ_LINE 8 bit Interrupt Line */
+/* PCI_IRQ_PIN 8 bit Interrupt Pin */
+/* PCI_MIN_GNT 8 bit Min_Gnt */
+/* PCI_MAX_LAT 8 bit Max_Lat */
+/* Device Dependent Region */
+/* PCI_OUR_REG (DV) 32 bit Our Register */
+/* PCI_OUR_REG_1 (ML) 32 bit Our Register 1 */
+ /* Bit 31..29: reserved */
+#define PCI_PATCH_DIR (3L<<27) /*(DV) Bit 28..27: Ext Patchs direction */
+#define PCI_PATCH_DIR_0 (1L<<27) /*(DV) Type of the pins EXT_PATCHS<1..0> */
+#define PCI_PATCH_DIR_1 (1L<<28) /* 0 = input */
+ /* 1 = output */
+#define PCI_EXT_PATCHS (3L<<25) /*(DV) Bit 26..25: Extended Patches */
+#define PCI_EXT_PATCH_0 (1L<<25) /*(DV) */
+#define PCI_EXT_PATCH_1 (1L<<26) /* CLK for MicroWire (ML) */
+#define PCI_VIO (1L<<25) /*(ML) */
+#define PCI_EN_BOOT (1L<<24) /* Bit 24: Enable BOOT via ROM */
+ /* 1 = Don't boot with ROM */
+ /* 0 = Boot with ROM */
+#define PCI_EN_IO (1L<<23) /* Bit 23: Mapping to IO space */
+#define PCI_EN_FPROM (1L<<22) /* Bit 22: FLASH mapped to mem? */
+ /* 1 = Map Flash to Memory */
+ /* 0 = Disable all addr. decoding */
+#define PCI_PAGESIZE (3L<<20) /* Bit 21..20: FLASH Page Size */
+#define PCI_PAGE_16 (0L<<20) /* 16 k pages */
+#define PCI_PAGE_32K (1L<<20) /* 32 k pages */
+#define PCI_PAGE_64K (2L<<20) /* 64 k pages */
+#define PCI_PAGE_128K (3L<<20) /* 128 k pages */
+ /* Bit 19: reserved (ML) and (DV) */
+#define PCI_PAGEREG (7L<<16) /* Bit 18..16: Page Register */
+ /* Bit 15: reserved */
+#define PCI_FORCE_BE (1L<<14) /* Bit 14: Assert all BEs on MR */
+#define PCI_DIS_MRL (1L<<13) /* Bit 13: Disable Mem R Line */
+#define PCI_DIS_MRM (1L<<12) /* Bit 12: Disable Mem R multip */
+#define PCI_DIS_MWI (1L<<11) /* Bit 11: Disable Mem W & inv */
+#define PCI_DISC_CLS (1L<<10) /* Bit 10: Disc: cacheLsz bound */
+#define PCI_BURST_DIS (1L<<9) /* Bit 9: Burst Disable */
+#define PCI_BYTE_SWAP (1L<<8) /*(DV) Bit 8: Byte Swap in DATA */
+#define PCI_SKEW_DAS (0xfL<<4) /* Bit 7..4: Skew Ctrl, DAS Ext */
+#define PCI_SKEW_BASE (0xfL<<0) /* Bit 3..0: Skew Ctrl, Base */
+
+/* PCI_OUR_REG_2 (ML) 32 bit Our Register 2 (Monalisa only) */
+#define PCI_VPD_WR_TH (0xffL<<24) /* Bit 24..31 VPD Write Threshold */
+#define PCI_DEV_SEL (0x7fL<<17) /* Bit 17..23 EEPROM Device Select */
+#define PCI_VPD_ROM_SZ (7L<<14) /* Bit 14..16 VPD ROM Size */
+ /* Bit 12..13 reserved */
+#define PCI_PATCH_DIR2 (0xfL<<8) /* Bit 8..11 Ext Patchs dir 2..5 */
+#define PCI_PATCH_DIR_2 (1L<<8) /* Bit 8 CS for MicroWire */
+#define PCI_PATCH_DIR_3 (1L<<9)
+#define PCI_PATCH_DIR_4 (1L<<10)
+#define PCI_PATCH_DIR_5 (1L<<11)
+#define PCI_EXT_PATCHS2 (0xfL<<4) /* Bit 4..7 Extended Patches */
+#define PCI_EXT_PATCH_2 (1L<<4) /* Bit 4 CS for MicroWire */
+#define PCI_EXT_PATCH_3 (1L<<5)
+#define PCI_EXT_PATCH_4 (1L<<6)
+#define PCI_EXT_PATCH_5 (1L<<7)
+#define PCI_EN_DUMMY_RD (1L<<3) /* Bit 3 Enable Dummy Read */
+#define PCI_REV_DESC (1L<<2) /* Bit 2 Reverse Desc. Bytes */
+#define PCI_USEADDR64 (1L<<1) /* Bit 1 Use 64 Bit Addresse */
+#define PCI_USEDATA64 (1L<<0) /* Bit 0 Use 64 Bit Data bus ext*/
+
+/* Power Management Region */
+/* PCI_PM_CAP_ID 8 bit (ML) Power Management Cap. ID */
+/* PCI_PM_NITEM 8 bit (ML) Next Item Ptr */
+/* PCI_PM_CAP_REG 16 bit (ML) Power Management Capabilities*/
+#define PCI_PME_SUP (0x1f<<11) /* Bit 11..15 PM Manag. Event Support*/
+#define PCI_PM_D2_SUB (1<<10) /* Bit 10 D2 Support Bit */
+#define PCI_PM_D1_SUB (1<<9) /* Bit 9 D1 Support Bit */
+ /* Bit 6..8 reserved */
+#define PCI_PM_DSI (1<<5) /* Bit 5 Device Specific Init.*/
+#define PCI_PM_APS (1<<4) /* Bit 4 Auxialiary Power Src */
+#define PCI_PME_CLOCK (1<<3) /* Bit 3 PM Event Clock */
+#define PCI_PM_VER (7<<0) /* Bit 0..2 PM PCI Spec. version */
+
+/* PCI_PM_CTL_STS 16 bit (ML) Power Manag. Control/Status */
+#define PCI_PME_STATUS (1<<15) /* Bit 15 PFA doesn't sup. PME#*/
+#define PCI_PM_DAT_SCL (3<<13) /* Bit 13..14 dat reg Scaling factor */
+#define PCI_PM_DAT_SEL (0xf<<9) /* Bit 9..12 PM data selector field */
+ /* Bit 7.. 2 reserved */
+#define PCI_PM_STATE (3<<0) /* Bit 0.. 1 Power Management State */
+#define PCI_PM_STATE_D0 (0<<0) /* D0: Operational (default) */
+#define PCI_PM_STATE_D1 (1<<0) /* D1: not supported */
+#define PCI_PM_STATE_D2 (2<<0) /* D2: not supported */
+#define PCI_PM_STATE_D3 (3<<0) /* D3: HOT, Power Down and Reset */
+
+/* PCI_PM_DAT_REG 8 bit (ML) Power Manag. Data Register */
+/* VPD Region */
+/* PCI_VPD_CAP_ID 8 bit (ML) VPD Cap. ID */
+/* PCI_VPD_NITEM 8 bit (ML) Next Item Ptr */
+/* PCI_VPD_ADR_REG 16 bit (ML) VPD Address Register */
+#define PCI_VPD_FLAG (1<<15) /* Bit 15 starts VPD rd/wd cycle*/
+#define PCI_VPD_ADDR (0x3fff<<0) /* Bit 0..14 VPD address */
+
+/* PCI_VPD_DAT_REG 32 bit (ML) VPD Data Register */
+
+/*
+ * Control Register File:
+ * Bank 0
+ */
+#define B0_RAP 0x0000 /* 8 bit register address port */
+ /* 0x0001 - 0x0003: reserved */
+#define B0_CTRL 0x0004 /* 8 bit control register */
+#define B0_DAS 0x0005 /* 8 Bit control register (DAS) */
+#define B0_LED 0x0006 /* 8 Bit LED register */
+#define B0_TST_CTRL 0x0007 /* 8 bit test control register */
+#define B0_ISRC 0x0008 /* 32 bit Interrupt source register */
+#define B0_IMSK 0x000c /* 32 bit Interrupt mask register */
+
+/* 0x0010 - 0x006b: formac+ (supernet_3) fequently used registers */
+#define B0_CMDREG1 0x0010 /* write command reg 1 instruction */
+#define B0_CMDREG2 0x0014 /* write command reg 2 instruction */
+#define B0_ST1U 0x0010 /* read upper 16-bit of status reg 1 */
+#define B0_ST1L 0x0014 /* read lower 16-bit of status reg 1 */
+#define B0_ST2U 0x0018 /* read upper 16-bit of status reg 2 */
+#define B0_ST2L 0x001c /* read lower 16-bit of status reg 2 */
+
+#define B0_MARR 0x0020 /* r/w the memory read addr register */
+#define B0_MARW 0x0024 /* r/w the memory write addr register*/
+#define B0_MDRU 0x0028 /* r/w upper 16-bit of mem. data reg */
+#define B0_MDRL 0x002c /* r/w lower 16-bit of mem. data reg */
+
+#define B0_MDREG3 0x0030 /* r/w Mode Register 3 */
+#define B0_ST3U 0x0034 /* read upper 16-bit of status reg 3 */
+#define B0_ST3L 0x0038 /* read lower 16-bit of status reg 3 */
+#define B0_IMSK3U 0x003c /* r/w upper 16-bit of IMSK reg 3 */
+#define B0_IMSK3L 0x0040 /* r/w lower 16-bit of IMSK reg 3 */
+#define B0_IVR 0x0044 /* read Interrupt Vector register */
+#define B0_IMR 0x0048 /* r/w Interrupt mask register */
+/* 0x4c Hidden */
+
+#define B0_CNTRL_A 0x0050 /* control register A (r/w) */
+#define B0_CNTRL_B 0x0054 /* control register B (r/w) */
+#define B0_INTR_MASK 0x0058 /* interrupt mask (r/w) */
+#define B0_XMIT_VECTOR 0x005c /* transmit vector register (r/w) */
+
+#define B0_STATUS_A 0x0060 /* status register A (read only) */
+#define B0_STATUS_B 0x0064 /* status register B (read only) */
+#define B0_CNTRL_C 0x0068 /* control register C (r/w) */
+#define B0_MDREG1 0x006c /* r/w Mode Register 1 */
+
+#define B0_R1_CSR 0x0070 /* 32 bit BMU control/status reg (rec q 1) */
+#define B0_R2_CSR 0x0074 /* 32 bit BMU control/status reg (rec q 2)(DV)*/
+#define B0_XA_CSR 0x0078 /* 32 bit BMU control/status reg (a xmit q) */
+#define B0_XS_CSR 0x007c /* 32 bit BMU control/status reg (s xmit q) */
+
+/*
+ * Bank 1
+ * - completely empty (this is the RAP Block window)
+ * Note: if RAP = 1 this page is reserved
+ */
+
+/*
+ * Bank 2
+ */
+#define B2_MAC_0 0x0100 /* 8 bit MAC address Byte 0 */
+#define B2_MAC_1 0x0101 /* 8 bit MAC address Byte 1 */
+#define B2_MAC_2 0x0102 /* 8 bit MAC address Byte 2 */
+#define B2_MAC_3 0x0103 /* 8 bit MAC address Byte 3 */
+#define B2_MAC_4 0x0104 /* 8 bit MAC address Byte 4 */
+#define B2_MAC_5 0x0105 /* 8 bit MAC address Byte 5 */
+#define B2_MAC_6 0x0106 /* 8 bit MAC address Byte 6 (== 0) (DV) */
+#define B2_MAC_7 0x0107 /* 8 bit MAC address Byte 7 (== 0) (DV) */
+
+#define B2_CONN_TYP 0x0108 /* 8 bit Connector type */
+#define B2_PMD_TYP 0x0109 /* 8 bit PMD type */
+ /* 0x010a - 0x010b: reserved */
+ /* Eprom registers are currently of no use */
+#define B2_E_0 0x010c /* 8 bit EPROM Byte 0 */
+#define B2_E_1 0x010d /* 8 bit EPROM Byte 1 */
+#define B2_E_2 0x010e /* 8 bit EPROM Byte 2 */
+#define B2_E_3 0x010f /* 8 bit EPROM Byte 3 */
+#define B2_FAR 0x0110 /* 32 bit Flash-Prom Address Register/Counter */
+#define B2_FDP 0x0114 /* 8 bit Flash-Prom Data Port */
+ /* 0x0115 - 0x0117: reserved */
+#define B2_LD_CRTL 0x0118 /* 8 bit loader control */
+#define B2_LD_TEST 0x0119 /* 8 bit loader test */
+ /* 0x011a - 0x011f: reserved */
+#define B2_TI_INI 0x0120 /* 32 bit Timer init value */
+#define B2_TI_VAL 0x0124 /* 32 bit Timer value */
+#define B2_TI_CRTL 0x0128 /* 8 bit Timer control */
+#define B2_TI_TEST 0x0129 /* 8 Bit Timer Test */
+ /* 0x012a - 0x012f: reserved */
+#define B2_WDOG_INI 0x0130 /* 32 bit Watchdog init value */
+#define B2_WDOG_VAL 0x0134 /* 32 bit Watchdog value */
+#define B2_WDOG_CRTL 0x0138 /* 8 bit Watchdog control */
+#define B2_WDOG_TEST 0x0139 /* 8 Bit Watchdog Test */
+ /* 0x013a - 0x013f: reserved */
+#define B2_RTM_INI 0x0140 /* 32 bit RTM init value */
+#define B2_RTM_VAL 0x0144 /* 32 bit RTM value */
+#define B2_RTM_CRTL 0x0148 /* 8 bit RTM control */
+#define B2_RTM_TEST 0x0149 /* 8 Bit RTM Test */
+
+#define B2_TOK_COUNT 0x014c /* (ML) 32 bit Token Counter */
+#define B2_DESC_ADDR_H 0x0150 /* (ML) 32 bit Desciptor Base Addr Reg High */
+#define B2_CTRL_2 0x0154 /* (ML) 8 bit Control Register 2 */
+#define B2_IFACE_REG 0x0155 /* (ML) 8 bit Interface Register */
+ /* 0x0156: reserved */
+#define B2_TST_CTRL_2 0x0157 /* (ML) 8 bit Test Control Register 2 */
+#define B2_I2C_CTRL 0x0158 /* (ML) 32 bit I2C Control Register */
+#define B2_I2C_DATA 0x015c /* (ML) 32 bit I2C Data Register */
+
+#define B2_IRQ_MOD_INI 0x0160 /* (ML) 32 bit IRQ Moderation Timer Init Reg. */
+#define B2_IRQ_MOD_VAL 0x0164 /* (ML) 32 bit IRQ Moderation Timer Value */
+#define B2_IRQ_MOD_CTRL 0x0168 /* (ML) 8 bit IRQ Moderation Timer Control */
+#define B2_IRQ_MOD_TEST 0x0169 /* (ML) 8 bit IRQ Moderation Timer Test */
+ /* 0x016a - 0x017f: reserved */
+
+/*
+ * Bank 3
+ */
+/*
+ * This is a copy of the Configuration register file (lower half)
+ */
+#define B3_CFG_SPC 0x180
+
+/*
+ * Bank 4
+ */
+#define B4_R1_D 0x0200 /* 4*32 bit current receive Descriptor */
+#define B4_R1_DA 0x0210 /* 32 bit current rec desc address */
+#define B4_R1_AC 0x0214 /* 32 bit current receive Address Count */
+#define B4_R1_BC 0x0218 /* 32 bit current receive Byte Counter */
+#define B4_R1_CSR 0x021c /* 32 bit BMU Control/Status Register */
+#define B4_R1_F 0x0220 /* 32 bit flag register */
+#define B4_R1_T1 0x0224 /* 32 bit Test Register 1 */
+#define B4_R1_T1_TR 0x0224 /* 8 bit Test Register 1 TR */
+#define B4_R1_T1_WR 0x0225 /* 8 bit Test Register 1 WR */
+#define B4_R1_T1_RD 0x0226 /* 8 bit Test Register 1 RD */
+#define B4_R1_T1_SV 0x0227 /* 8 bit Test Register 1 SV */
+#define B4_R1_T2 0x0228 /* 32 bit Test Register 2 */
+#define B4_R1_T3 0x022c /* 32 bit Test Register 3 */
+#define B4_R1_DA_H 0x0230 /* (ML) 32 bit Curr Rx Desc Address High */
+#define B4_R1_AC_H 0x0234 /* (ML) 32 bit Curr Addr Counter High dword */
+ /* 0x0238 - 0x023f: reserved */
+ /* Receive queue 2 is removed on Monalisa */
+#define B4_R2_D 0x0240 /* 4*32 bit current receive Descriptor (q2) */
+#define B4_R2_DA 0x0250 /* 32 bit current rec desc address (q2) */
+#define B4_R2_AC 0x0254 /* 32 bit current receive Address Count (q2) */
+#define B4_R2_BC 0x0258 /* 32 bit current receive Byte Counter (q2) */
+#define B4_R2_CSR 0x025c /* 32 bit BMU Control/Status Register (q2) */
+#define B4_R2_F 0x0260 /* 32 bit flag register (q2) */
+#define B4_R2_T1 0x0264 /* 32 bit Test Register 1 (q2) */
+#define B4_R2_T1_TR 0x0264 /* 8 bit Test Register 1 TR (q2) */
+#define B4_R2_T1_WR 0x0265 /* 8 bit Test Register 1 WR (q2) */
+#define B4_R2_T1_RD 0x0266 /* 8 bit Test Register 1 RD (q2) */
+#define B4_R2_T1_SV 0x0267 /* 8 bit Test Register 1 SV (q2) */
+#define B4_R2_T2 0x0268 /* 32 bit Test Register 2 (q2) */
+#define B4_R2_T3 0x026c /* 32 bit Test Register 3 (q2) */
+ /* 0x0270 - 0x027c: reserved */
+
+/*
+ * Bank 5
+ */
+#define B5_XA_D 0x0280 /* 4*32 bit current transmit Descriptor (xa) */
+#define B5_XA_DA 0x0290 /* 32 bit current tx desc address (xa) */
+#define B5_XA_AC 0x0294 /* 32 bit current tx Address Count (xa) */
+#define B5_XA_BC 0x0298 /* 32 bit current tx Byte Counter (xa) */
+#define B5_XA_CSR 0x029c /* 32 bit BMU Control/Status Register (xa) */
+#define B5_XA_F 0x02a0 /* 32 bit flag register (xa) */
+#define B5_XA_T1 0x02a4 /* 32 bit Test Register 1 (xa) */
+#define B5_XA_T1_TR 0x02a4 /* 8 bit Test Register 1 TR (xa) */
+#define B5_XA_T1_WR 0x02a5 /* 8 bit Test Register 1 WR (xa) */
+#define B5_XA_T1_RD 0x02a6 /* 8 bit Test Register 1 RD (xa) */
+#define B5_XA_T1_SV 0x02a7 /* 8 bit Test Register 1 SV (xa) */
+#define B5_XA_T2 0x02a8 /* 32 bit Test Register 2 (xa) */
+#define B5_XA_T3 0x02ac /* 32 bit Test Register 3 (xa) */
+#define B5_XA_DA_H 0x02b0 /* (ML) 32 bit Curr Tx Desc Address High */
+#define B5_XA_AC_H 0x02b4 /* (ML) 32 bit Curr Addr Counter High dword */
+ /* 0x02b8 - 0x02bc: reserved */
+#define B5_XS_D 0x02c0 /* 4*32 bit current transmit Descriptor (xs) */
+#define B5_XS_DA 0x02d0 /* 32 bit current tx desc address (xs) */
+#define B5_XS_AC 0x02d4 /* 32 bit current transmit Address Count(xs) */
+#define B5_XS_BC 0x02d8 /* 32 bit current transmit Byte Counter (xs) */
+#define B5_XS_CSR 0x02dc /* 32 bit BMU Control/Status Register (xs) */
+#define B5_XS_F 0x02e0 /* 32 bit flag register (xs) */
+#define B5_XS_T1 0x02e4 /* 32 bit Test Register 1 (xs) */
+#define B5_XS_T1_TR 0x02e4 /* 8 bit Test Register 1 TR (xs) */
+#define B5_XS_T1_WR 0x02e5 /* 8 bit Test Register 1 WR (xs) */
+#define B5_XS_T1_RD 0x02e6 /* 8 bit Test Register 1 RD (xs) */
+#define B5_XS_T1_SV 0x02e7 /* 8 bit Test Register 1 SV (xs) */
+#define B5_XS_T2 0x02e8 /* 32 bit Test Register 2 (xs) */
+#define B5_XS_T3 0x02ec /* 32 bit Test Register 3 (xs) */
+#define B5_XS_DA_H 0x02f0 /* (ML) 32 bit Curr Tx Desc Address High */
+#define B5_XS_AC_H 0x02f4 /* (ML) 32 bit Curr Addr Counter High dword */
+ /* 0x02f8 - 0x02fc: reserved */
+
+/*
+ * Bank 6
+ */
+/* External PLC-S registers (SN2 compatibility for DV) */
+/* External registers (ML) */
+#define B6_EXT_REG 0x300
+
+/*
+ * Bank 7
+ */
+/* DAS PLC-S Registers */
+
+/*
+ * Bank 8 - 15
+ */
+/* IFCP registers */
+
+/*---------------------------------------------------------------------------*/
+/* Definitions of the Bits in the registers */
+
+/* B0_RAP 16 bit register address port */
+#define RAP_RAP 0x0f /* Bit 3..0: 0 = block0, .., f = block15 */
+
+/* B0_CTRL 8 bit control register */
+#define CTRL_FDDI_CLR (1<<7) /* Bit 7: (ML) Clear FDDI Reset */
+#define CTRL_FDDI_SET (1<<6) /* Bit 6: (ML) Set FDDI Reset */
+#define CTRL_HPI_CLR (1<<5) /* Bit 5: Clear HPI SM reset */
+#define CTRL_HPI_SET (1<<4) /* Bit 4: Set HPI SM reset */
+#define CTRL_MRST_CLR (1<<3) /* Bit 3: Clear Master reset */
+#define CTRL_MRST_SET (1<<2) /* Bit 2: Set Master reset */
+#define CTRL_RST_CLR (1<<1) /* Bit 1: Clear Software reset */
+#define CTRL_RST_SET (1<<0) /* Bit 0: Set Software reset */
+
+/* B0_DAS 8 Bit control register (DAS) */
+#define BUS_CLOCK (1<<7) /* Bit 7: (ML) Bus Clock 0/1 = 33/66MHz */
+#define BUS_SLOT_SZ (1<<6) /* Bit 6: (ML) Slot Size 0/1 = 32/64 bit slot*/
+ /* Bit 5..4: reserved */
+#define DAS_AVAIL (1<<3) /* Bit 3: 1 = DAS, 0 = SAS */
+#define DAS_BYP_ST (1<<2) /* Bit 2: 1 = avail,SAS, 0 = not avail */
+#define DAS_BYP_INS (1<<1) /* Bit 1: 1 = insert Bypass */
+#define DAS_BYP_RMV (1<<0) /* Bit 0: 1 = remove Bypass */
+
+/* B0_LED 8 Bit LED register */
+ /* Bit 7..6: reserved */
+#define LED_2_ON (1<<5) /* Bit 5: 1 = switch LED_2 on (left,gn)*/
+#define LED_2_OFF (1<<4) /* Bit 4: 1 = switch LED_2 off */
+#define LED_1_ON (1<<3) /* Bit 3: 1 = switch LED_1 on (mid,yel)*/
+#define LED_1_OFF (1<<2) /* Bit 2: 1 = switch LED_1 off */
+#define LED_0_ON (1<<1) /* Bit 1: 1 = switch LED_0 on (rght,gn)*/
+#define LED_0_OFF (1<<0) /* Bit 0: 1 = switch LED_0 off */
+/* This hardware defines are very ugly therefore we define some others */
+
+#define LED_GA_ON LED_2_ON /* S port = A port */
+#define LED_GA_OFF LED_2_OFF /* S port = A port */
+#define LED_MY_ON LED_1_ON
+#define LED_MY_OFF LED_1_OFF
+#define LED_GB_ON LED_0_ON
+#define LED_GB_OFF LED_0_OFF
+
+/* B0_TST_CTRL 8 bit test control register */
+#define TST_FRC_DPERR_MR (1<<7) /* Bit 7: force DATAPERR on MST RE. */
+#define TST_FRC_DPERR_MW (1<<6) /* Bit 6: force DATAPERR on MST WR. */
+#define TST_FRC_DPERR_TR (1<<5) /* Bit 5: force DATAPERR on TRG RE. */
+#define TST_FRC_DPERR_TW (1<<4) /* Bit 4: force DATAPERR on TRG WR. */
+#define TST_FRC_APERR_M (1<<3) /* Bit 3: force ADDRPERR on MST */
+#define TST_FRC_APERR_T (1<<2) /* Bit 2: force ADDRPERR on TRG */
+#define TST_CFG_WRITE_ON (1<<1) /* Bit 1: ena configuration reg. WR */
+#define TST_CFG_WRITE_OFF (1<<0) /* Bit 0: dis configuration reg. WR */
+
+/* B0_ISRC 32 bit Interrupt source register */
+ /* Bit 31..28: reserved */
+#define IS_I2C_READY (1L<<27) /* Bit 27: (ML) IRQ on end of I2C tx */
+#define IS_IRQ_SW (1L<<26) /* Bit 26: (ML) SW forced IRQ */
+#define IS_EXT_REG (1L<<25) /* Bit 25: (ML) IRQ from external reg*/
+#define IS_IRQ_STAT (1L<<24) /* Bit 24: IRQ status execption */
+ /* PERR, RMABORT, RTABORT DATAPERR */
+#define IS_IRQ_MST_ERR (1L<<23) /* Bit 23: IRQ master error */
+ /* RMABORT, RTABORT, DATAPERR */
+#define IS_TIMINT (1L<<22) /* Bit 22: IRQ_TIMER */
+#define IS_TOKEN (1L<<21) /* Bit 21: IRQ_RTM */
+/*
+ * Note: The DAS is our First Port (!=PA)
+ */
+#define IS_PLINT1 (1L<<20) /* Bit 20: IRQ_PHY_DAS */
+#define IS_PLINT2 (1L<<19) /* Bit 19: IRQ_IFCP_4 */
+#define IS_MINTR3 (1L<<18) /* Bit 18: IRQ_IFCP_3/IRQ_PHY */
+#define IS_MINTR2 (1L<<17) /* Bit 17: IRQ_IFCP_2/IRQ_MAC_2 */
+#define IS_MINTR1 (1L<<16) /* Bit 16: IRQ_IFCP_1/IRQ_MAC_1 */
+/* Receive Queue 1 */
+#define IS_R1_P (1L<<15) /* Bit 15: Parity Error (q1) */
+#define IS_R1_B (1L<<14) /* Bit 14: End of Buffer (q1) */
+#define IS_R1_F (1L<<13) /* Bit 13: End of Frame (q1) */
+#define IS_R1_C (1L<<12) /* Bit 12: Encoding Error (q1) */
+/* Receive Queue 2 */
+#define IS_R2_P (1L<<11) /* Bit 11: (DV) Parity Error (q2) */
+#define IS_R2_B (1L<<10) /* Bit 10: (DV) End of Buffer (q2) */
+#define IS_R2_F (1L<<9) /* Bit 9: (DV) End of Frame (q2) */
+#define IS_R2_C (1L<<8) /* Bit 8: (DV) Encoding Error (q2) */
+/* Asynchronous Transmit queue */
+ /* Bit 7: reserved */
+#define IS_XA_B (1L<<6) /* Bit 6: End of Buffer (xa) */
+#define IS_XA_F (1L<<5) /* Bit 5: End of Frame (xa) */
+#define IS_XA_C (1L<<4) /* Bit 4: Encoding Error (xa) */
+/* Synchronous Transmit queue */
+ /* Bit 3: reserved */
+#define IS_XS_B (1L<<2) /* Bit 2: End of Buffer (xs) */
+#define IS_XS_F (1L<<1) /* Bit 1: End of Frame (xs) */
+#define IS_XS_C (1L<<0) /* Bit 0: Encoding Error (xs) */
+
+/*
+ * Define all valid interrupt source Bits from GET_ISR ()
+ */
+#define ALL_IRSR 0x01ffff77L /* (DV) */
+#define ALL_IRSR_ML 0x0ffff077L /* (ML) */
+
+
+/* B0_IMSK 32 bit Interrupt mask register */
+/*
+ * The Bit definnition of this register are the same as of the interrupt
+ * source register. These definition are directly derived from the Hardware
+ * spec.
+ */
+ /* Bit 31..28: reserved */
+#define IRQ_I2C_READY (1L<<27) /* Bit 27: (ML) IRQ on end of I2C tx */
+#define IRQ_SW (1L<<26) /* Bit 26: (ML) SW forced IRQ */
+#define IRQ_EXT_REG (1L<<25) /* Bit 25: (ML) IRQ from external reg*/
+#define IRQ_STAT (1L<<24) /* Bit 24: IRQ status execption */
+ /* PERR, RMABORT, RTABORT DATAPERR */
+#define IRQ_MST_ERR (1L<<23) /* Bit 23: IRQ master error */
+ /* RMABORT, RTABORT, DATAPERR */
+#define IRQ_TIMER (1L<<22) /* Bit 22: IRQ_TIMER */
+#define IRQ_RTM (1L<<21) /* Bit 21: IRQ_RTM */
+#define IRQ_DAS (1L<<20) /* Bit 20: IRQ_PHY_DAS */
+#define IRQ_IFCP_4 (1L<<19) /* Bit 19: IRQ_IFCP_4 */
+#define IRQ_IFCP_3 (1L<<18) /* Bit 18: IRQ_IFCP_3/IRQ_PHY */
+#define IRQ_IFCP_2 (1L<<17) /* Bit 17: IRQ_IFCP_2/IRQ_MAC_2 */
+#define IRQ_IFCP_1 (1L<<16) /* Bit 16: IRQ_IFCP_1/IRQ_MAC_1 */
+/* Receive Queue 1 */
+#define IRQ_R1_P (1L<<15) /* Bit 15: Parity Error (q1) */
+#define IRQ_R1_B (1L<<14) /* Bit 14: End of Buffer (q1) */
+#define IRQ_R1_F (1L<<13) /* Bit 13: End of Frame (q1) */
+#define IRQ_R1_C (1L<<12) /* Bit 12: Encoding Error (q1) */
+/* Receive Queue 2 */
+#define IRQ_R2_P (1L<<11) /* Bit 11: (DV) Parity Error (q2) */
+#define IRQ_R2_B (1L<<10) /* Bit 10: (DV) End of Buffer (q2) */
+#define IRQ_R2_F (1L<<9) /* Bit 9: (DV) End of Frame (q2) */
+#define IRQ_R2_C (1L<<8) /* Bit 8: (DV) Encoding Error (q2) */
+/* Asynchronous Transmit queue */
+ /* Bit 7: reserved */
+#define IRQ_XA_B (1L<<6) /* Bit 6: End of Buffer (xa) */
+#define IRQ_XA_F (1L<<5) /* Bit 5: End of Frame (xa) */
+#define IRQ_XA_C (1L<<4) /* Bit 4: Encoding Error (xa) */
+/* Synchronous Transmit queue */
+ /* Bit 3: reserved */
+#define IRQ_XS_B (1L<<2) /* Bit 2: End of Buffer (xs) */
+#define IRQ_XS_F (1L<<1) /* Bit 1: End of Frame (xs) */
+#define IRQ_XS_C (1L<<0) /* Bit 0: Encoding Error (xs) */
+
+/* 0x0010 - 0x006b: formac+ (supernet_3) fequently used registers */
+/* B0_R1_CSR 32 bit BMU control/status reg (rec q 1 ) */
+/* B0_R2_CSR 32 bit BMU control/status reg (rec q 2 ) */
+/* B0_XA_CSR 32 bit BMU control/status reg (a xmit q ) */
+/* B0_XS_CSR 32 bit BMU control/status reg (s xmit q ) */
+/* The registers are the same as B4_R1_CSR, B4_R2_CSR, B5_Xa_CSR, B5_XS_CSR */
+
+/* B2_MAC_0 8 bit MAC address Byte 0 */
+/* B2_MAC_1 8 bit MAC address Byte 1 */
+/* B2_MAC_2 8 bit MAC address Byte 2 */
+/* B2_MAC_3 8 bit MAC address Byte 3 */
+/* B2_MAC_4 8 bit MAC address Byte 4 */
+/* B2_MAC_5 8 bit MAC address Byte 5 */
+/* B2_MAC_6 8 bit MAC address Byte 6 (== 0) (DV) */
+/* B2_MAC_7 8 bit MAC address Byte 7 (== 0) (DV) */
+
+/* B2_CONN_TYP 8 bit Connector type */
+/* B2_PMD_TYP 8 bit PMD type */
+/* Values of connector and PMD type comply to SysKonnect internal std */
+
+/* The EPROM register are currently of no use */
+/* B2_E_0 8 bit EPROM Byte 0 */
+/* B2_E_1 8 bit EPROM Byte 1 */
+/* B2_E_2 8 bit EPROM Byte 2 */
+/* B2_E_3 8 bit EPROM Byte 3 */
+
+/* B2_FAR 32 bit Flash-Prom Address Register/Counter */
+#define FAR_ADDR 0x1ffffL /* Bit 16..0: FPROM Address mask */
+
+/* B2_FDP 8 bit Flash-Prom Data Port */
+
+/* B2_LD_CRTL 8 bit loader control */
+/* Bits are currently reserved */
+
+/* B2_LD_TEST 8 bit loader test */
+#define LD_T_ON (1<<3) /* Bit 3: Loader Testmode on */
+#define LD_T_OFF (1<<2) /* Bit 2: Loader Testmode off */
+#define LD_T_STEP (1<<1) /* Bit 1: Decrement FPROM addr. Counter */
+#define LD_START (1<<0) /* Bit 0: Start loading FPROM */
+
+/* B2_TI_INI 32 bit Timer init value */
+/* B2_TI_VAL 32 bit Timer value */
+/* B2_TI_CRTL 8 bit Timer control */
+/* B2_TI_TEST 8 Bit Timer Test */
+/* B2_WDOG_INI 32 bit Watchdog init value */
+/* B2_WDOG_VAL 32 bit Watchdog value */
+/* B2_WDOG_CRTL 8 bit Watchdog control */
+/* B2_WDOG_TEST 8 Bit Watchdog Test */
+/* B2_RTM_INI 32 bit RTM init value */
+/* B2_RTM_VAL 32 bit RTM value */
+/* B2_RTM_CRTL 8 bit RTM control */
+/* B2_RTM_TEST 8 Bit RTM Test */
+/* B2_<TIM>_CRTL 8 bit <TIM> control */
+/* B2_IRQ_MOD_INI 32 bit IRQ Moderation Timer Init Reg. (ML) */
+/* B2_IRQ_MOD_VAL 32 bit IRQ Moderation Timer Value (ML) */
+/* B2_IRQ_MOD_CTRL 8 bit IRQ Moderation Timer Control (ML) */
+/* B2_IRQ_MOD_TEST 8 bit IRQ Moderation Timer Test (ML) */
+#define GET_TOK_CT (1<<4) /* Bit 4: Get the Token Counter (RTM) */
+#define TIM_RES_TOK (1<<3) /* Bit 3: RTM Status: 1 == restricted */
+#define TIM_ALARM (1<<3) /* Bit 3: Timer Alarm (WDOG) */
+#define TIM_START (1<<2) /* Bit 2: Start Timer (TI,WDOG,RTM,IRQ_MOD)*/
+#define TIM_STOP (1<<1) /* Bit 1: Stop Timer (TI,WDOG,RTM,IRQ_MOD) */
+#define TIM_CL_IRQ (1<<0) /* Bit 0: Clear Timer IRQ (TI,WDOG,RTM) */
+/* B2_<TIM>_TEST 8 Bit <TIM> Test */
+#define TIM_T_ON (1<<2) /* Bit 2: Test mode on (TI,WDOG,RTM,IRQ_MOD) */
+#define TIM_T_OFF (1<<1) /* Bit 1: Test mode off (TI,WDOG,RTM,IRQ_MOD) */
+#define TIM_T_STEP (1<<0) /* Bit 0: Test step (TI,WDOG,RTM,IRQ_MOD) */
+
+/* B2_TOK_COUNT 0x014c (ML) 32 bit Token Counter */
+/* B2_DESC_ADDR_H 0x0150 (ML) 32 bit Desciptor Base Addr Reg High */
+/* B2_CTRL_2 0x0154 (ML) 8 bit Control Register 2 */
+ /* Bit 7..5: reserved */
+#define CTRL_CL_I2C_IRQ (1<<4) /* Bit 4: Clear I2C IRQ */
+#define CTRL_ST_SW_IRQ (1<<3) /* Bit 3: Set IRQ SW Request */
+#define CTRL_CL_SW_IRQ (1<<2) /* Bit 2: Clear IRQ SW Request */
+#define CTRL_STOP_DONE (1<<1) /* Bit 1: Stop Master is finished */
+#define CTRL_STOP_MAST (1<<0) /* Bit 0: Command Bit to stop the master*/
+
+/* B2_IFACE_REG 0x0155 (ML) 8 bit Interface Register */
+ /* Bit 7..3: reserved */
+#define IF_I2C_DATA_DIR (1<<2) /* Bit 2: direction of IF_I2C_DATA*/
+#define IF_I2C_DATA (1<<1) /* Bit 1: I2C Data Port */
+#define IF_I2C_CLK (1<<0) /* Bit 0: I2C Clock Port */
+
+ /* 0x0156: reserved */
+/* B2_TST_CTRL_2 0x0157 (ML) 8 bit Test Control Register 2 */
+ /* Bit 7..4: reserved */
+ /* force the following error on */
+ /* the next master read/write */
+#define TST_FRC_DPERR_MR64 (1<<3) /* Bit 3: DataPERR RD 64 */
+#define TST_FRC_DPERR_MW64 (1<<2) /* Bit 2: DataPERR WR 64 */
+#define TST_FRC_APERR_1M64 (1<<1) /* Bit 1: AddrPERR on 1. phase */
+#define TST_FRC_APERR_2M64 (1<<0) /* Bit 0: AddrPERR on 2. phase */
+
+/* B2_I2C_CTRL 0x0158 (ML) 32 bit I2C Control Register */
+#define I2C_FLAG (1L<<31) /* Bit 31: Start read/write if WR */
+#define I2C_ADDR (0x7fffL<<16) /* Bit 30..16: Addr to be read/written*/
+#define I2C_DEV_SEL (0x7fL<<9) /* Bit 9..15: I2C Device Select */
+ /* Bit 5.. 8: reserved */
+#define I2C_BURST_LEN (1L<<4) /* Bit 4 Burst Len, 1/4 bytes */
+#define I2C_DEV_SIZE (7L<<1) /* Bit 1.. 3: I2C Device Size */
+#define I2C_025K_DEV (0L<<1) /* 0: 256 Bytes or smaller*/
+#define I2C_05K_DEV (1L<<1) /* 1: 512 Bytes */
+#define I2C_1K_DEV (2L<<1) /* 2: 1024 Bytes */
+#define I2C_2K_DEV (3L<<1) /* 3: 2048 Bytes */
+#define I2C_4K_DEV (4L<<1) /* 4: 4096 Bytes */
+#define I2C_8K_DEV (5L<<1) /* 5: 8192 Bytes */
+#define I2C_16K_DEV (6L<<1) /* 6: 16384 Bytes */
+#define I2C_32K_DEV (7L<<1) /* 7: 32768 Bytes */
+#define I2C_STOP_BIT (1<<0) /* Bit 0: Interrupt I2C transfer */
+
+/*
+ * I2C Addresses
+ *
+ * The temperature sensor and the voltage sensor are on the same I2C bus.
+ * Note: The voltage sensor (Micorwire) will be selected by PCI_EXT_PATCH_1
+ * in PCI_OUR_REG 1.
+ */
+#define I2C_ADDR_TEMP 0x90 /* I2C Address Temperature Sensor */
+
+/* B2_I2C_DATA 0x015c (ML) 32 bit I2C Data Register */
+
+/* B4_R1_D 4*32 bit current receive Descriptor (q1) */
+/* B4_R1_DA 32 bit current rec desc address (q1) */
+/* B4_R1_AC 32 bit current receive Address Count (q1) */
+/* B4_R1_BC 32 bit current receive Byte Counter (q1) */
+/* B4_R1_CSR 32 bit BMU Control/Status Register (q1) */
+/* B4_R1_F 32 bit flag register (q1) */
+/* B4_R1_T1 32 bit Test Register 1 (q1) */
+/* B4_R1_T2 32 bit Test Register 2 (q1) */
+/* B4_R1_T3 32 bit Test Register 3 (q1) */
+/* B4_R2_D 4*32 bit current receive Descriptor (q2) */
+/* B4_R2_DA 32 bit current rec desc address (q2) */
+/* B4_R2_AC 32 bit current receive Address Count (q2) */
+/* B4_R2_BC 32 bit current receive Byte Counter (q2) */
+/* B4_R2_CSR 32 bit BMU Control/Status Register (q2) */
+/* B4_R2_F 32 bit flag register (q2) */
+/* B4_R2_T1 32 bit Test Register 1 (q2) */
+/* B4_R2_T2 32 bit Test Register 2 (q2) */
+/* B4_R2_T3 32 bit Test Register 3 (q2) */
+/* B5_XA_D 4*32 bit current receive Descriptor (xa) */
+/* B5_XA_DA 32 bit current rec desc address (xa) */
+/* B5_XA_AC 32 bit current receive Address Count (xa) */
+/* B5_XA_BC 32 bit current receive Byte Counter (xa) */
+/* B5_XA_CSR 32 bit BMU Control/Status Register (xa) */
+/* B5_XA_F 32 bit flag register (xa) */
+/* B5_XA_T1 32 bit Test Register 1 (xa) */
+/* B5_XA_T2 32 bit Test Register 2 (xa) */
+/* B5_XA_T3 32 bit Test Register 3 (xa) */
+/* B5_XS_D 4*32 bit current receive Descriptor (xs) */
+/* B5_XS_DA 32 bit current rec desc address (xs) */
+/* B5_XS_AC 32 bit current receive Address Count (xs) */
+/* B5_XS_BC 32 bit current receive Byte Counter (xs) */
+/* B5_XS_CSR 32 bit BMU Control/Status Register (xs) */
+/* B5_XS_F 32 bit flag register (xs) */
+/* B5_XS_T1 32 bit Test Register 1 (xs) */
+/* B5_XS_T2 32 bit Test Register 2 (xs) */
+/* B5_XS_T3 32 bit Test Register 3 (xs) */
+/* B5_<xx>_CSR 32 bit BMU Control/Status Register (xx) */
+#define CSR_DESC_CLEAR (1L<<21) /* Bit 21: Clear Reset for Descr */
+#define CSR_DESC_SET (1L<<20) /* Bit 20: Set Reset for Descr */
+#define CSR_FIFO_CLEAR (1L<<19) /* Bit 19: Clear Reset for FIFO */
+#define CSR_FIFO_SET (1L<<18) /* Bit 18: Set Reset for FIFO */
+#define CSR_HPI_RUN (1L<<17) /* Bit 17: Release HPI SM */
+#define CSR_HPI_RST (1L<<16) /* Bit 16: Reset HPI SM to Idle */
+#define CSR_SV_RUN (1L<<15) /* Bit 15: Release Supervisor SM */
+#define CSR_SV_RST (1L<<14) /* Bit 14: Reset Supervisor SM */
+#define CSR_DREAD_RUN (1L<<13) /* Bit 13: Release Descr Read SM */
+#define CSR_DREAD_RST (1L<<12) /* Bit 12: Reset Descr Read SM */
+#define CSR_DWRITE_RUN (1L<<11) /* Bit 11: Rel. Descr Write SM */
+#define CSR_DWRITE_RST (1L<<10) /* Bit 10: Reset Descr Write SM */
+#define CSR_TRANS_RUN (1L<<9) /* Bit 9: Release Transfer SM */
+#define CSR_TRANS_RST (1L<<8) /* Bit 8: Reset Transfer SM */
+ /* Bit 7..5: reserved */
+#define CSR_START (1L<<4) /* Bit 4: Start Rec/Xmit Queue */
+#define CSR_IRQ_CL_P (1L<<3) /* Bit 3: Clear Parity IRQ, Rcv */
+#define CSR_IRQ_CL_B (1L<<2) /* Bit 2: Clear EOB IRQ */
+#define CSR_IRQ_CL_F (1L<<1) /* Bit 1: Clear EOF IRQ */
+#define CSR_IRQ_CL_C (1L<<0) /* Bit 0: Clear ERR IRQ */
+
+#define CSR_SET_RESET (CSR_DESC_SET|CSR_FIFO_SET|CSR_HPI_RST|CSR_SV_RST|\
+ CSR_DREAD_RST|CSR_DWRITE_RST|CSR_TRANS_RST)
+#define CSR_CLR_RESET (CSR_DESC_CLEAR|CSR_FIFO_CLEAR|CSR_HPI_RUN|CSR_SV_RUN|\
+ CSR_DREAD_RUN|CSR_DWRITE_RUN|CSR_TRANS_RUN)
+
+
+/* B5_<xx>_F 32 bit flag register (xx) */
+ /* Bit 28..31: reserved */
+#define F_ALM_FULL (1L<<27) /* Bit 27: (ML) FIFO almost full */
+#define F_FIFO_EOF (1L<<26) /* Bit 26: (ML) Fag bit in FIFO */
+#define F_WM_REACHED (1L<<25) /* Bit 25: (ML) Watermark reached */
+#define F_UP_DW_USED (1L<<24) /* Bit 24: (ML) Upper Dword used (bug)*/
+ /* Bit 23: reserved */
+#define F_FIFO_LEVEL (0x1fL<<16) /* Bit 16..22:(ML) # of Qwords in FIFO*/
+ /* Bit 8..15: reserved */
+#define F_ML_WATER_M 0x0000ffL /* Bit 0.. 7:(ML) Watermark */
+#define FLAG_WATER 0x00001fL /* Bit 4..0:(DV) Level of req data tr.*/
+
+/* B5_<xx>_T1 32 bit Test Register 1 (xx) */
+/* Holds four State Machine control Bytes */
+#define SM_CRTL_SV (0xffL<<24) /* Bit 31..24: Control Supervisor SM */
+#define SM_CRTL_RD (0xffL<<16) /* Bit 23..16: Control Read Desc SM */
+#define SM_CRTL_WR (0xffL<<8) /* Bit 15..8: Control Write Desc SM */
+#define SM_CRTL_TR (0xffL<<0) /* Bit 7..0: Control Transfer SM */
+
+/* B4_<xx>_T1_TR 8 bit Test Register 1 TR (xx) */
+/* B4_<xx>_T1_WR 8 bit Test Register 1 WR (xx) */
+/* B4_<xx>_T1_RD 8 bit Test Register 1 RD (xx) */
+/* B4_<xx>_T1_SV 8 bit Test Register 1 SV (xx) */
+/* The control status byte of each machine looks like ... */
+#define SM_STATE 0xf0 /* Bit 7..4: State which shall be loaded */
+#define SM_LOAD 0x08 /* Bit 3: Load the SM with SM_STATE */
+#define SM_TEST_ON 0x04 /* Bit 2: Switch on SM Test Mode */
+#define SM_TEST_OFF 0x02 /* Bit 1: Go off the Test Mode */
+#define SM_STEP 0x01 /* Bit 0: Step the State Machine */
+
+/* The coding of the states */
+#define SM_SV_IDLE 0x0 /* Supervisor Idle Tr/Re */
+#define SM_SV_RES_START 0x1 /* Supervisor Res_Start Tr/Re */
+#define SM_SV_GET_DESC 0x3 /* Supervisor Get_Desc Tr/Re */
+#define SM_SV_CHECK 0x2 /* Supervisor Check Tr/Re */
+#define SM_SV_MOV_DATA 0x6 /* Supervisor Move_Data Tr/Re */
+#define SM_SV_PUT_DESC 0x7 /* Supervisor Put_Desc Tr/Re */
+#define SM_SV_SET_IRQ 0x5 /* Supervisor Set_Irq Tr/Re */
+
+#define SM_RD_IDLE 0x0 /* Read Desc. Idle Tr/Re */
+#define SM_RD_LOAD 0x1 /* Read Desc. Load Tr/Re */
+#define SM_RD_WAIT_TC 0x3 /* Read Desc. Wait_TC Tr/Re */
+#define SM_RD_RST_EOF 0x6 /* Read Desc. Reset_EOF Re */
+#define SM_RD_WDONE_R 0x2 /* Read Desc. Wait_Done Re */
+#define SM_RD_WDONE_T 0x4 /* Read Desc. Wait_Done Tr */
+
+#define SM_TR_IDLE 0x0 /* Trans. Data Idle Tr/Re */
+#define SM_TR_LOAD 0x3 /* Trans. Data Load Tr/Re */
+#define SM_TR_LOAD_R_ML 0x1 /* Trans. Data Load /Re (ML) */
+#define SM_TR_WAIT_TC 0x2 /* Trans. Data Wait_TC Tr/Re */
+#define SM_TR_WDONE 0x4 /* Trans. Data Wait_Done Tr/Re */
+
+#define SM_WR_IDLE 0x0 /* Write Desc. Idle Tr/Re */
+#define SM_WR_ABLEN 0x1 /* Write Desc. Act_Buf_Length Tr/Re */
+#define SM_WR_LD_A4 0x2 /* Write Desc. Load_A4 Re */
+#define SM_WR_RES_OWN 0x2 /* Write Desc. Res_OWN Tr */
+#define SM_WR_WAIT_EOF 0x3 /* Write Desc. Wait_EOF Re */
+#define SM_WR_LD_N2C_R 0x4 /* Write Desc. Load_N2C Re */
+#define SM_WR_WAIT_TC_R 0x5 /* Write Desc. Wait_TC Re */
+#define SM_WR_WAIT_TC4 0x6 /* Write Desc. Wait_TC4 Re */
+#define SM_WR_LD_A_T 0x6 /* Write Desc. Load_A Tr */
+#define SM_WR_LD_A_R 0x7 /* Write Desc. Load_A Re */
+#define SM_WR_WAIT_TC_T 0x7 /* Write Desc. Wait_TC Tr */
+#define SM_WR_LD_N2C_T 0xc /* Write Desc. Load_N2C Tr */
+#define SM_WR_WDONE_T 0x9 /* Write Desc. Wait_Done Tr */
+#define SM_WR_WDONE_R 0xc /* Write Desc. Wait_Done Re */
+#define SM_WR_LD_D_AD 0xe /* Write Desc. Load_Dumr_A Re (ML) */
+#define SM_WR_WAIT_D_TC 0xf /* Write Desc. Wait_Dumr_TC Re (ML) */
+
+/* B5_<xx>_T2 32 bit Test Register 2 (xx) */
+/* Note: This register is only defined for the transmit queues */
+ /* Bit 31..8: reserved */
+#define AC_TEST_ON (1<<7) /* Bit 7: Address Counter Test Mode on */
+#define AC_TEST_OFF (1<<6) /* Bit 6: Address Counter Test Mode off*/
+#define BC_TEST_ON (1<<5) /* Bit 5: Byte Counter Test Mode on */
+#define BC_TEST_OFF (1<<4) /* Bit 4: Byte Counter Test Mode off */
+#define TEST_STEP04 (1<<3) /* Bit 3: Inc AC/Dec BC by 4 */
+#define TEST_STEP03 (1<<2) /* Bit 2: Inc AC/Dec BC by 3 */
+#define TEST_STEP02 (1<<1) /* Bit 1: Inc AC/Dec BC by 2 */
+#define TEST_STEP01 (1<<0) /* Bit 0: Inc AC/Dec BC by 1 */
+
+/* B5_<xx>_T3 32 bit Test Register 3 (xx) */
+/* Note: This register is only defined for the transmit queues */
+ /* Bit 31..8: reserved */
+#define T3_MUX_2 (1<<7) /* Bit 7: (ML) Mux position MSB */
+#define T3_VRAM_2 (1<<6) /* Bit 6: (ML) Virtual RAM buffer addr MSB */
+#define T3_LOOP (1<<5) /* Bit 5: Set Loopback (Xmit) */
+#define T3_UNLOOP (1<<4) /* Bit 4: Unset Loopback (Xmit) */
+#define T3_MUX (3<<2) /* Bit 3..2: Mux position */
+#define T3_VRAM (3<<0) /* Bit 1..0: Virtual RAM buffer Address */
+
+/* PCI card IDs */
+/*
+ * Note: The following 4 byte definitions shall not be used! Use OEM Concept!
+ */
+#define PCI_VEND_ID0 0x48 /* PCI vendor ID (SysKonnect) */
+#define PCI_VEND_ID1 0x11 /* PCI vendor ID (SysKonnect) */
+ /* (High byte) */
+#define PCI_DEV_ID0 0x00 /* PCI device ID */
+#define PCI_DEV_ID1 0x40 /* PCI device ID (High byte) */
+
+/*#define PCI_CLASS 0x02*/ /* PCI class code: network device */
+#define PCI_NW_CLASS 0x02 /* PCI class code: network device */
+#define PCI_SUB_CLASS 0x02 /* PCI subclass ID: FDDI device */
+#define PCI_PROG_INTFC 0x00 /* PCI programming Interface (=0) */
+
+/*
+ * address transmision from logical to physical offset address on board
+ */
+#define FMA(a) (0x0400|((a)<<2)) /* FORMAC+ (r/w) (SN3) */
+#define P1(a) (0x0380|((a)<<2)) /* PLC1 (r/w) (DAS) */
+#define P2(a) (0x0600|((a)<<2)) /* PLC2 (r/w) (covered by the SN3) */
+#define PRA(a) (B2_MAC_0 + (a)) /* configuration PROM (MAC address) */
+
+/*
+ * FlashProm specification
+ */
+#define MAX_PAGES 0x20000L /* Every byte has a single page */
+#define MAX_FADDR 1 /* 1 byte per page */
+
+/*
+ * Receive / Transmit Buffer Control word
+ */
+#define BMU_OWN (1UL<<31) /* OWN bit: 0 == host, 1 == adapter */
+#define BMU_STF (1L<<30) /* Start of Frame ? */
+#define BMU_EOF (1L<<29) /* End of Frame ? */
+#define BMU_EN_IRQ_EOB (1L<<28) /* Enable "End of Buffer" IRQ */
+#define BMU_EN_IRQ_EOF (1L<<27) /* Enable "End of Frame" IRQ */
+#define BMU_DEV_0 (1L<<26) /* RX: don't transfer to system mem */
+#define BMU_SMT_TX (1L<<25) /* TX: if set, buffer type SMT_MBuf */
+#define BMU_ST_BUF (1L<<25) /* RX: copy of start of frame */
+#define BMU_UNUSED (1L<<24) /* Set if the Descr is curr unused */
+#define BMU_SW (3L<<24) /* 2 Bits reserved for SW usage */
+#define BMU_CHECK 0x00550000L /* To identify the control word */
+#define BMU_BBC 0x0000FFFFL /* R/T Buffer Byte Count */
+
+/*
+ * physical address offset + IO-Port base address
+ */
+#ifdef MEM_MAPPED_IO
+#define ADDR(a) (char far *) smc->hw.iop+(a)
+#define ADDRS(smc,a) (char far *) (smc)->hw.iop+(a)
+#else
+#define ADDR(a) (((a)>>7) ? (outp(smc->hw.iop+B0_RAP,(a)>>7), \
+ (smc->hw.iop+(((a)&0x7F)|((a)>>7 ? 0x80:0)))) : \
+ (smc->hw.iop+(((a)&0x7F)|((a)>>7 ? 0x80:0))))
+#define ADDRS(smc,a) (((a)>>7) ? (outp((smc)->hw.iop+B0_RAP,(a)>>7), \
+ ((smc)->hw.iop+(((a)&0x7F)|((a)>>7 ? 0x80:0)))) : \
+ ((smc)->hw.iop+(((a)&0x7F)|((a)>>7 ? 0x80:0))))
+#endif
+
+/*
+ * Define a macro to access the configuration space
+ */
+#define PCI_C(a) ADDR(B3_CFG_SPC + (a)) /* PCI Config Space */
+
+#define EXT_R(a) ADDR(B6_EXT_REG + (a)) /* External Registers */
+
+/*
+ * Define some values needed for the MAC address (PROM)
+ */
+#define SA_MAC (0) /* start addr. MAC_AD within the PROM */
+#define PRA_OFF (0) /* offset correction when 4th byte reading */
+
+#define SKFDDI_PSZ 8 /* address PROM size */
+
+#define FM_A(a) ADDR(FMA(a)) /* FORMAC Plus physical addr */
+#define P1_A(a) ADDR(P1(a)) /* PLC1 (r/w) */
+#define P2_A(a) ADDR(P2(a)) /* PLC2 (r/w) (DAS) */
+#define PR_A(a) ADDR(PRA(a)) /* config. PROM (MAC address) */
+
+/*
+ * Macro to read the PROM
+ */
+#define READ_PROM(a) ((u_char)inp(a))
+
+#define GET_PAGE(bank) outpd(ADDR(B2_FAR),bank)
+#define VPP_ON()
+#define VPP_OFF()
+
+/*
+ * Note: Values of the Interrupt Source Register are defined above
+ */
+#define ISR_A ADDR(B0_ISRC)
+#define GET_ISR() inpd(ISR_A)
+#define GET_ISR_SMP(iop) inpd((iop)+B0_ISRC)
+#define CHECK_ISR() (inpd(ISR_A) & inpd(ADDR(B0_IMSK)))
+#define CHECK_ISR_SMP(iop) (inpd((iop)+B0_ISRC) & inpd((iop)+B0_IMSK))
+
+#define BUS_CHECK()
+
+/*
+ * CLI_FBI: Disable Board Interrupts
+ * STI_FBI: Enable Board Interrupts
+ */
+#ifndef UNIX
+#define CLI_FBI() outpd(ADDR(B0_IMSK),0)
+#else
+#define CLI_FBI(smc) outpd(ADDRS((smc),B0_IMSK),0)
+#endif
+
+#ifndef UNIX
+#define STI_FBI() outpd(ADDR(B0_IMSK),smc->hw.is_imask)
+#else
+#define STI_FBI(smc) outpd(ADDRS((smc),B0_IMSK),(smc)->hw.is_imask)
+#endif
+
+#define CLI_FBI_SMP(iop) outpd((iop)+B0_IMSK,0)
+#define STI_FBI_SMP(smc,iop) outpd((iop)+B0_IMSK,(smc)->hw.is_imask)
+
+#endif /* PCI */
+/*--------------------------------------------------------------------------*/
+
+/*
+ * 12 bit transfer (dword) counter:
+ * (ISA: 2*trc = number of byte)
+ * (EISA: 4*trc = number of byte)
+ * (MCA: 4*trc = number of byte)
+ */
+#define MAX_TRANS (0x0fff)
+
+/*
+ * PC PIC
+ */
+#define MST_8259 (0x20)
+#define SLV_8259 (0xA0)
+
+#define TPS (18) /* ticks per second */
+
+/*
+ * error timer defs
+ */
+#define TN (4) /* number of supported timer = TN+1 */
+#define SNPPND_TIME (5) /* buffer memory access over mem. data reg. */
+
+#define MAC_AD 0x405a0000
+
+#define MODR1 FM_A(FM_MDREG1) /* mode register 1 */
+#define MODR2 FM_A(FM_MDREG2) /* mode register 2 */
+
+#define CMDR1 FM_A(FM_CMDREG1) /* command register 1 */
+#define CMDR2 FM_A(FM_CMDREG2) /* command register 2 */
+
+
+/*
+ * function defines
+ */
+#define CLEAR(io,mask) outpw((io),inpw(io)&(~(mask)))
+#define SET(io,mask) outpw((io),inpw(io)|(mask))
+#define GET(io,mask) (inpw(io)&(mask))
+#define SETMASK(io,val,mask) outpw((io),(inpw(io) & ~(mask)) | (val))
+
+/*
+ * PHY Port A (PA) = PLC 1
+ * With SuperNet 3 PHY-A and PHY S are identical.
+ */
+#define PLC(np,reg) (((np) == PA) ? P2_A(reg) : P1_A(reg))
+
+/*
+ * set memory address register for write and read
+ */
+#define MARW(ma) outpw(FM_A(FM_MARW),(unsigned int)(ma))
+#define MARR(ma) outpw(FM_A(FM_MARR),(unsigned int)(ma))
+
+/*
+ * read/write from/to memory data register
+ */
+/* write double word */
+#define MDRW(dd) outpw(FM_A(FM_MDRU),(unsigned int)((dd)>>16)) ;\
+ outpw(FM_A(FM_MDRL),(unsigned int)(dd))
+
+#ifndef WINNT
+/* read double word */
+#define MDRR() (((long)inpw(FM_A(FM_MDRU))<<16) + inpw(FM_A(FM_MDRL)))
+
+/* read FORMAC+ 32-bit status register */
+#define GET_ST1() (((long)inpw(FM_A(FM_ST1U))<<16) + inpw(FM_A(FM_ST1L)))
+#define GET_ST2() (((long)inpw(FM_A(FM_ST2U))<<16) + inpw(FM_A(FM_ST2L)))
+#ifdef SUPERNET_3
+#define GET_ST3() (((long)inpw(FM_A(FM_ST3U))<<16) + inpw(FM_A(FM_ST3L)))
+#endif
+#else
+/* read double word */
+#define MDRR() inp2w((FM_A(FM_MDRU)),(FM_A(FM_MDRL)))
+
+/* read FORMAC+ 32-bit status register */
+#define GET_ST1() inp2w((FM_A(FM_ST1U)),(FM_A(FM_ST1L)))
+#define GET_ST2() inp2w((FM_A(FM_ST2U)),(FM_A(FM_ST2L)))
+#ifdef SUPERNET_3
+#define GET_ST3() inp2w((FM_A(FM_ST3U)),(FM_A(FM_ST3L)))
+#endif
+#endif
+
+/* Special timer macro for 82c54 */
+ /* timer access over data bus bit 8..15 */
+#define OUT_82c54_TIMER(port,val) outpw(TI_A(port),(val)<<8)
+#define IN_82c54_TIMER(port) ((inpw(TI_A(port))>>8) & 0xff)
+
+
+#ifdef DEBUG
+#define DB_MAC(mac,st) {if (debug_mac & 0x1)\
+ printf("M") ;\
+ if (debug_mac & 0x2)\
+ printf("\tMAC %d status 0x%08lx\n",mac,st) ;\
+ if (debug_mac & 0x4)\
+ dp_mac(mac,st) ;\
+}
+
+#define DB_PLC(p,iev) { if (debug_plc & 0x1)\
+ printf("P") ;\
+ if (debug_plc & 0x2)\
+ printf("\tPLC %s Int 0x%04x\n", \
+ (p == PA) ? "A" : "B", iev) ;\
+ if (debug_plc & 0x4)\
+ dp_plc(p,iev) ;\
+}
+
+#define DB_TIMER() { if (debug_timer & 0x1)\
+ printf("T") ;\
+ if (debug_timer & 0x2)\
+ printf("\tTimer ISR\n") ;\
+}
+
+#else /* no DEBUG */
+
+#define DB_MAC(mac,st)
+#define DB_PLC(p,iev)
+#define DB_TIMER()
+
+#endif /* no DEBUG */
+
+#define INC_PTR(sp,cp,ep) if (++cp == ep) cp = sp
+/*
+ * timer defs
+ */
+#define COUNT(t) ((t)<<6) /* counter */
+#define RW_OP(o) ((o)<<4) /* read/write operation */
+#define TMODE(m) ((m)<<1) /* timer mode */
+
+#endif
diff --git a/drivers/net/skfp/h/skfbiinc.h b/drivers/net/skfp/h/skfbiinc.h
new file mode 100644
index 000000000..79d55ad2c
--- /dev/null
+++ b/drivers/net/skfp/h/skfbiinc.h
@@ -0,0 +1,123 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef _SKFBIINC_
+#define _SKFBIINC_
+
+#include "h/supern_2.h"
+
+/*
+ * special defines for use into .asm files
+ */
+#define ERR_FLAGS (FS_MSRABT | FS_SEAC2 | FS_SFRMERR | FS_SFRMTY1)
+
+#ifdef ISA
+#define DMA_BUSY_CHECK CSRA
+#define IMASK_FAST (IS_PLINT1 | IS_PLINT2 | IS_TIMINT)
+#define HRQR (RQAA+(RQ_RRQ<<1))
+#define HRQW (RQAA+(RQ_WA2<<1))
+#define HRQA0 (RQAA+(RQ_WA0<<1))
+#define HRQSQ (RQAA+(RQ_WSQ<<1))
+#endif
+
+#ifdef EISA
+#define DMA_BUSY_CHECK CSRA
+#define DMA_HIGH_WORD 0x0400
+#define DMA_MASK_M 0x0a
+#define DMA_MODE_M 0x0b
+#define DMA_BYTE_PTR_M 0x0c
+#define DMA_MASK_S 0x0d4
+#define DMA_MODE_S 0x0d6
+#define DMA_BYTE_PTR_S 0x0d8
+#define IMASK_FAST (IS_PLINT1 | IS_PLINT2 | IS_TIMINT | IS_TC)
+#endif /* EISA */
+
+#ifdef MCA
+#define IMASK_FAST (IS_PLINT1 | IS_PLINT2 | IS_TIMINT | IS_TOKEN | \
+ IS_CHCK_L | IS_BUSERR)
+#endif
+
+#ifdef PCI
+#define IMASK_FAST (IS_PLINT1 | IS_PLINT2 | IS_TIMINT | IS_TOKEN | \
+ IS_MINTR2 | IS_MINTR3 | IS_R1_P | \
+ IS_R1_C | IS_XA_C | IS_XS_C)
+#endif
+
+#ifdef PCI
+#define ISR_MASK (IS_MINTR1 | IS_R1_F | IS_XS_F| IS_XA_F | IMASK_FAST)
+#else
+#define ISR_MASK (IS_MINTR1 | IS_MINTR2 | IMASK_FAST)
+#endif
+
+#define FMA_FM_CMDREG1 FMA(FM_CMDREG1)
+#define FMA_FM_CMDREG2 FMA(FM_CMDREG2)
+#define FMA_FM_STMCHN FMA(FM_STMCHN)
+#define FMA_FM_RPR FMA(FM_RPR)
+#define FMA_FM_WPXA0 FMA(FM_WPXA0)
+#define FMA_FM_WPXA2 FMA(FM_WPXA2)
+#define FMA_FM_MARR FMA(FM_MARR)
+#define FMA_FM_MARW FMA(FM_MARW)
+#define FMA_FM_MDRU FMA(FM_MDRU)
+#define FMA_FM_MDRL FMA(FM_MDRL)
+#define FMA_ST1L FMA(FM_ST1L)
+#define FMA_ST1U FMA(FM_ST1U)
+#define FMA_ST2L FMA(FM_ST2L)
+#define FMA_ST2U FMA(FM_ST2U)
+#ifdef SUPERNET_3
+#define FMA_ST3L FMA(FM_ST3L)
+#define FMA_ST3U FMA(FM_ST3U)
+#endif
+
+#define TMODE_RRQ RQ_RRQ
+#define TMODE_WAQ2 RQ_WA2
+#define HSRA HSR(0)
+
+
+#define FMA_FM_ST1L FMA_ST1L
+#define FMA_FM_ST1U FMA_ST1U
+#define FMA_FM_ST2L FMA_ST2L
+#define FMA_FM_ST2U FMA_ST2U
+#ifdef SUPERNET_3
+#define FMA_FM_ST3L FMA_ST3L
+#define FMA_FM_ST3U FMA_ST3U
+#endif
+
+#define FMA_FM_SWPR FMA(FM_SWPR)
+
+#define FMA_FM_RPXA0 FMA(FM_RPXA0)
+
+#define FMA_FM_RPXS FMA(FM_RPXS)
+#define FMA_FM_WPXS FMA(FM_WPXS)
+
+#define FMA_FM_IMSK1U FMA(FM_IMSK1U)
+#define FMA_FM_IMSK1L FMA(FM_IMSK1L)
+
+#define FMA_FM_EAS FMA(FM_EAS)
+#define FMA_FM_EAA0 FMA(FM_EAA0)
+
+#define TMODE_WAQ0 RQ_WA0
+#define TMODE_WSQ RQ_WSQ
+
+/* Define default for DRV_PCM_STATE_CHANGE */
+#ifndef DRV_PCM_STATE_CHANGE
+#define DRV_PCM_STATE_CHANGE(smc,plc,p_state) /* nothing */
+#endif
+
+/* Define default for DRV_RMT_INDICATION */
+#ifndef DRV_RMT_INDICATION
+#define DRV_RMT_INDICATION(smc,i) /* nothing */
+#endif
+
+#endif /* n_SKFBIINC_ */
+
diff --git a/drivers/net/skfp/h/smc.h b/drivers/net/skfp/h/smc.h
new file mode 100644
index 000000000..b909586bc
--- /dev/null
+++ b/drivers/net/skfp/h/smc.h
@@ -0,0 +1,471 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef _SCMECM_
+#define _SCMECM_
+
+#if defined(PCI) && !defined(OSDEF)
+/*
+ * In the case of the PCI bus the file osdef1st.h must be present
+ */
+#define OSDEF
+#endif
+
+#ifdef PCI
+#ifndef SUPERNET_3
+#define SUPERNET_3
+#endif
+#ifndef TAG_MODE
+#define TAG_MODE
+#endif
+#endif
+
+/*
+ * include all other files in required order
+ * the following files must have been included before:
+ * types.h
+ * fddi.h
+ */
+#ifdef OSDEF
+#include "h/osdef1st.h"
+#endif /* OSDEF */
+#ifdef OEM_CONCEPT
+#include "oemdef.h"
+#endif /* OEM_CONCEPT */
+#include "h/smt.h"
+#include "h/cmtdef.h"
+#include "h/fddimib.h"
+#include "h/targethw.h" /* all target hw dependencies */
+#include "h/targetos.h" /* all target os dependencies */
+#ifdef ESS
+#include "h/sba.h"
+#endif
+
+/*
+ * Event Queue
+ * queue.c
+ * events are class/value pairs
+ * class is addressee, e.g. RMT, PCM etc.
+ * value is command, e.g. line state change, ring op change etc.
+ */
+struct event_queue {
+ u_short class ; /* event class */
+ u_short event ; /* event value */
+} ;
+
+/*
+ * define event queue as circular buffer
+ */
+#ifdef CONCENTRATOR
+#define MAX_EVENT 128
+#else /* nCONCENTRATOR */
+#define MAX_EVENT 64
+#endif /* nCONCENTRATOR */
+
+struct s_queue {
+
+ struct event_queue ev_queue[MAX_EVENT];
+ struct event_queue *ev_put ;
+ struct event_queue *ev_get ;
+} ;
+
+/*
+ * ECM - Entity Coordination Management
+ * ecm.c
+ */
+struct s_ecm {
+ u_char path_test ; /* ECM path test variable */
+ u_char sb_flag ; /* ECM stuck bypass */
+ u_char DisconnectFlag ; /* jd 05-Aug-1999 Bug #10419
+ * ECM disconnected */
+ u_char ecm_line_state ; /* flag to dispatcher : line states */
+ u_long trace_prop ; /* ECM Trace_Prop flag >= 16 bits !! */
+ /* NUMPHYS note:
+ * this variable must have enough bits to hold all entiies in
+ * the station. So NUMPHYS may not be greater than 31.
+ */
+ char ec_pad[2] ;
+ struct smt_timer ecm_timer ; /* timer */
+} ;
+
+
+/*
+ * RMT - Ring Management
+ * rmt.c
+ */
+struct s_rmt {
+ u_char dup_addr_test ; /* state of dupl. addr. test */
+ u_char da_flag ; /* flag : duplicate address det. */
+ u_char loop_avail ; /* flag : MAC available for loopback */
+ u_char sm_ma_avail ; /* flag : MAC available for SMT */
+ u_char no_flag ; /* flag : ring not operational */
+ u_char bn_flag ; /* flag : MAC reached beacon state */
+ u_char jm_flag ; /* flag : jamming in NON_OP_DUP */
+ u_char rm_join ; /* CFM flag RM_Join */
+ u_char rm_loop ; /* CFM flag RM_Loop */
+
+ long fast_rm_join ; /* bit mask of active ports */
+ /*
+ * timer and flags
+ */
+ struct smt_timer rmt_timer0 ; /* timer 0 */
+ struct smt_timer rmt_timer1 ; /* timer 1 */
+ struct smt_timer rmt_timer2 ; /* timer 2 */
+ u_char timer0_exp ; /* flag : timer 0 expired */
+ u_char timer1_exp ; /* flag : timer 1 expired */
+ u_char timer2_exp ; /* flag : timer 2 expired */
+
+ u_char rm_pad1[1] ;
+} ;
+
+/*
+ * CFM - Configuration Management
+ * cfm.c
+ * used for SAS and DAS
+ */
+struct s_cfm {
+ u_char cf_state; /* CFM state machine current state */
+ u_char cf_pad[3] ;
+} ;
+
+/*
+ * CEM - Configuration Element Management
+ * cem.c
+ * used for Concentrator
+ */
+#ifdef CONCENTRATOR
+struct s_cem {
+ int ce_state ; /* CEM state */
+ int ce_port ; /* PA PB PM PM+1 .. */
+ int ce_type ; /* TA TB TS TM */
+} ;
+
+/*
+ * linked list of CCEs in current token path
+ */
+struct s_c_ring {
+ struct s_c_ring *c_next ;
+ char c_entity ;
+} ;
+
+struct mib_path_config {
+ u_long fddimibPATHConfigSMTIndex;
+ u_long fddimibPATHConfigPATHIndex;
+ u_long fddimibPATHConfigTokenOrder;
+ u_long fddimibPATHConfigResourceType;
+#define SNMP_RES_TYPE_MAC 2 /* Resource is a MAC */
+#define SNMP_RES_TYPE_PORT 4 /* Resource is a PORT */
+ u_long fddimibPATHConfigResourceIndex;
+ u_long fddimibPATHConfigCurrentPath;
+#define SNMP_PATH_ISOLATED 1 /* Current path is isolated */
+#define SNMP_PATH_LOCAL 2 /* Current path is local */
+#define SNMP_PATH_SECONDARY 3 /* Current path is secondary */
+#define SNMP_PATH_PRIMARY 4 /* Current path is primary */
+#define SNMP_PATH_CONCATENATED 5 /* Current path is concatenated */
+#define SNMP_PATH_THRU 6 /* Current path is thru */
+};
+
+
+#endif
+
+/*
+ * PCM connect states
+ */
+#define PCM_DISABLED 0
+#define PCM_CONNECTING 1
+#define PCM_STANDBY 2
+#define PCM_ACTIVE 3
+
+struct s_pcm {
+ u_char pcm_pad[3] ;
+} ;
+
+/*
+ * PHY struct
+ * one per physical port
+ */
+struct s_phy {
+ /* Inter Module Globals */
+ struct fddi_mib_p *mib ;
+
+ u_char np ; /* index 0 .. NUMPHYS */
+ u_char cf_join ;
+ u_char cf_loop ;
+ u_char wc_flag ; /* withhold connection flag */
+ u_char pc_mode ; /* Holds the negotiated mode of the PCM */
+ u_char pc_lem_fail ; /* flag : LCT failed */
+ u_char lc_test ;
+ u_char scrub ; /* CFM flag Scrub -> PCM */
+ char phy_name ;
+ u_char pmd_type[2] ; /* SK connector/transceiver type codes */
+#define PMD_SK_CONN 0 /* pmd_type[PMD_SK_CONN] = Connector */
+#define PMD_SK_PMD 1 /* pmd_type[PMD_SK_PMD] = Xver */
+ u_char pmd_scramble ; /* scrambler on/off */
+
+ /* inner Module Globals */
+ u_char curr_ls ; /* current line state */
+ u_char ls_flag ;
+ u_char rc_flag ;
+ u_char tc_flag ;
+ u_char td_flag ;
+ u_char bitn ;
+ u_char tr_flag ; /* trace recvd while in active */
+ u_char twisted ; /* flag to indicate an A-A or B-B connection */
+ u_char t_val[NUMBITS] ; /* transmit bits for signaling */
+ u_char r_val[NUMBITS] ; /* receive bits for signaling */
+ u_long t_next[NUMBITS] ;
+ struct smt_timer pcm_timer0 ;
+ struct smt_timer pcm_timer1 ;
+ struct smt_timer pcm_timer2 ;
+ u_char timer0_exp ;
+ u_char timer1_exp ;
+ u_char timer2_exp ;
+ u_char pcm_pad1[1] ;
+ int cem_pst ; /* CEM privae state; used for dual homing */
+ struct lem_counter lem ;
+#ifdef AMDPLC
+ struct s_plc plc ;
+#endif
+} ;
+
+/*
+ * timer package
+ * smttimer.c
+ */
+struct s_timer {
+ struct smt_timer *st_queue ;
+ struct smt_timer st_fast ;
+} ;
+
+/*
+ * SRF types and data
+ */
+#define SMT_EVENT_BASE 1
+#define SMT_EVENT_MAC_PATH_CHANGE (SMT_EVENT_BASE+0)
+#define SMT_EVENT_MAC_NEIGHBOR_CHANGE (SMT_EVENT_BASE+1)
+#define SMT_EVENT_PORT_PATH_CHANGE (SMT_EVENT_BASE+2)
+#define SMT_EVENT_PORT_CONNECTION (SMT_EVENT_BASE+3)
+
+#define SMT_IS_CONDITION(x) ((x)>=SMT_COND_BASE)
+
+#define SMT_COND_BASE (SMT_EVENT_PORT_CONNECTION+1)
+#define SMT_COND_SMT_PEER_WRAP (SMT_COND_BASE+0)
+#define SMT_COND_SMT_HOLD (SMT_COND_BASE+1)
+#define SMT_COND_MAC_FRAME_ERROR (SMT_COND_BASE+2)
+#define SMT_COND_MAC_DUP_ADDR (SMT_COND_BASE+3)
+#define SMT_COND_MAC_NOT_COPIED (SMT_COND_BASE+4)
+#define SMT_COND_PORT_EB_ERROR (SMT_COND_BASE+5)
+#define SMT_COND_PORT_LER (SMT_COND_BASE+6)
+
+#define SR0_WAIT 0
+#define SR1_HOLDOFF 1
+#define SR2_DISABLED 2
+
+struct s_srf {
+ u_long SRThreshold ; /* threshold value */
+ u_char RT_Flag ; /* report transmitted flag */
+ u_char sr_state ; /* state-machine */
+ u_char any_report ; /* any report required */
+ u_long TSR ; /* timer */
+ u_short ring_status ; /* IBM ring status */
+} ;
+
+/*
+ * IBM token ring status
+ */
+#define RS_RES15 (1<<15) /* reserved */
+#define RS_HARDERROR (1<<14) /* ring down */
+#define RS_SOFTERROR (1<<13) /* sent SRF */
+#define RS_BEACON (1<<12) /* transmitted beacon */
+#define RS_PATHTEST (1<<11) /* path test failed */
+#define RS_SELFTEST (1<<10) /* selftest required */
+#define RS_RES9 (1<< 9) /* reserved */
+#define RS_DISCONNECT (1<< 8) /* remote disconnect */
+#define RS_RES7 (1<< 7) /* reserved */
+#define RS_DUPADDR (1<< 6) /* duplicate address */
+#define RS_NORINGOP (1<< 5) /* no ring op */
+#define RS_VERSION (1<< 4) /* SMT version mismatch */
+#define RS_STUCKBYPASSS (1<< 3) /* stuck bypass */
+#define RS_EVENT (1<< 2) /* FDDI event occured */
+#define RS_RINGOPCHANGE (1<< 1) /* ring op changed */
+#define RS_RES0 (1<< 0) /* reserved */
+
+#define RS_SET(smc,bit) \
+ ring_status_indication(smc,smc->srf.ring_status |= bit)
+#define RS_CLEAR(smc,bit) \
+ ring_status_indication(smc,smc->srf.ring_status &= ~bit)
+
+#define RS_CLEAR_EVENT (0xffff & ~(RS_NORINGOP))
+
+/* Define the AIX-event-Notification as null function if it isn't defined */
+/* in the targetos.h file */
+#ifndef AIX_EVENT
+#define AIX_EVENT(smc,opt0,opt1,opt2,opt3) /* nothing */
+#endif
+
+struct s_srf_evc {
+ u_char evc_code ; /* event code type */
+ u_char evc_index ; /* index for mult. instances */
+ u_char evc_rep_required ; /* report required */
+ u_short evc_para ; /* SMT Para Number */
+ u_char *evc_cond_state ; /* condition state */
+ u_char *evc_multiple ; /* multiple occurence */
+} ;
+
+/*
+ * Values used by frame based services
+ * smt.c
+ */
+#define SMT_MAX_TEST 5
+#define SMT_TID_NIF 0 /* pending NIF request */
+#define SMT_TID_NIF_TEST 1 /* pending NIF test */
+#define SMT_TID_ECF_UNA 2 /* pending ECF UNA test */
+#define SMT_TID_ECF_DNA 3 /* pending ECF DNA test */
+#define SMT_TID_ECF 4 /* pending ECF test */
+
+struct smt_values {
+ u_long smt_tvu ; /* timer valid una */
+ u_long smt_tvd ; /* timer valid dna */
+ u_long smt_tid ; /* transaction id */
+ u_long pend[SMT_MAX_TEST] ; /* TID of requests */
+ u_long uniq_time ; /* unique time stamp */
+ u_short uniq_ticks ; /* unique time stamp */
+ u_short please_reconnect ; /* flag : reconnect */
+ u_long smt_last_lem ;
+ u_long smt_last_notify ;
+ struct smt_timer smt_timer ; /* SMT NIF timer */
+ u_long last_tok_time[NUMMACS]; /* token cnt emulation */
+} ;
+
+/*
+ * SMT/CMT configurable parameters
+ */
+#define SMT_DAS 0 /* dual attach */
+#define SMT_SAS 1 /* single attach */
+#define SMT_NAC 2 /* null attach concentrator */
+
+struct smt_config {
+ u_char attach_s ; /* CFM attach to secondary path */
+ u_char sas ; /* SMT_DAS/SAS/NAC */
+ u_char build_ring_map ; /* build ringmap if TRUE */
+ u_char numphys ; /* number of active phys */
+ u_char sc_pad[1] ;
+
+ u_long pcm_tb_min ; /* PCM : TB_Min timer value */
+ u_long pcm_tb_max ; /* PCM : TB_Max timer value */
+ u_long pcm_c_min ; /* PCM : C_Min timer value */
+ u_long pcm_t_out ; /* PCM : T_Out timer value */
+ u_long pcm_tl_min ; /* PCM : TL_min timer value */
+ u_long pcm_lc_short ; /* PCM : LC_Short timer value */
+ u_long pcm_lc_medium ; /* PCM : LC_Medium timer value */
+ u_long pcm_lc_long ; /* PCM : LC_Long timer value */
+ u_long pcm_lc_extended ; /* PCM : LC_Extended timer value */
+ u_long pcm_t_next_9 ; /* PCM : T_Next[9] timer value */
+ u_long pcm_ns_max ; /* PCM : NS_Max timer value */
+
+ u_long ecm_i_max ; /* ECM : I_Max timer value */
+ u_long ecm_in_max ; /* ECM : IN_Max timer value */
+ u_long ecm_td_min ; /* ECM : TD_Min timer */
+ u_long ecm_test_done ; /* ECM : path test done timer */
+ u_long ecm_check_poll ; /* ECM : check bypass poller */
+
+ u_long rmt_t_non_op ; /* RMT : T_Non_OP timer value */
+ u_long rmt_t_stuck ; /* RMT : T_Stuck timer value */
+ u_long rmt_t_direct ; /* RMT : T_Direct timer value */
+ u_long rmt_t_jam ; /* RMT : T_Jam timer value */
+ u_long rmt_t_announce ; /* RMT : T_Announce timer value */
+ u_long rmt_t_poll ; /* RMT : claim/beacon poller */
+ u_long rmt_dup_mac_behavior ; /* Flag for the beavior of SMT if
+ * a Duplicate MAC Address was detected.
+ * FALSE: SMT will leave finaly the ring
+ * TRUE: SMT will reinstert into the ring
+ */
+ u_long mac_d_max ; /* MAC : D_Max timer value */
+
+ u_long lct_short ; /* LCT : error threshhold */
+ u_long lct_medium ; /* LCT : error threshhold */
+ u_long lct_long ; /* LCT : error threshhold */
+ u_long lct_extended ; /* LCT : error threshhold */
+} ;
+
+#ifdef DEBUG
+/*
+ * Debugging struct sometimes used in smc
+ */
+struct smt_debug {
+ int d_smtf ;
+ int d_smt ;
+ int d_ecm ;
+ int d_rmt ;
+ int d_cfm ;
+ int d_pcm ;
+ int d_plc ;
+#ifdef ESS
+ int d_ess ;
+#endif
+#ifdef SBA
+ int d_sba ;
+#endif
+ struct os_debug d_os; /* Include specific OS DEBUG struct */
+} ;
+
+#ifndef DEBUG_BRD
+/* all boards shall be debugged with one debug struct */
+extern struct smt_debug debug; /* Declaration of debug struct */
+#endif /* DEBUG_BRD */
+
+#endif /* DEBUG */
+
+/*
+ * the SMT Context Struct SMC
+ * this struct contains ALL global variables of SMT
+ */
+struct s_smc {
+ struct s_smt_os os ; /* os specific */
+ struct s_smt_hw hw ; /* hardware */
+
+/*
+ * NOTE: os and hw MUST BE the first two structs
+ * anything beyond hw WILL BE SET TO ZERO in smt_set_defaults()
+ */
+ struct smt_config s ; /* smt constants */
+ struct smt_values sm ; /* smt variables */
+ struct s_ecm e ; /* ecm */
+ struct s_rmt r ; /* rmt */
+ struct s_cfm cf ; /* cfm/cem */
+#ifdef CONCENTRATOR
+ struct s_cem ce[NUMPHYS] ; /* cem */
+ struct s_c_ring cr[NUMPHYS+NUMMACS] ;
+#endif
+ struct s_pcm p ; /* pcm */
+ struct s_phy y[NUMPHYS] ; /* phy */
+ struct s_queue q ; /* queue */
+ struct s_timer t ; /* timer */
+ struct s_srf srf ; /* SRF */
+ struct s_srf_evc evcs[6+NUMPHYS*4] ;
+ struct fddi_mib mib ; /* __THE_MIB__ */
+#ifdef SBA
+ struct s_sba sba ; /* SBA variables */
+#endif
+#ifdef ESS
+ struct s_ess ess ; /* Ess variables */
+#endif
+#if defined(DEBUG) && defined(DEBUG_BRD)
+ /* If you want all single board to be debugged separately */
+ struct smt_debug debug; /* Declaration of debug struct */
+#endif /* DEBUG_BRD && DEBUG */
+} ;
+
+#endif /* _SCMECM_ */
+
diff --git a/drivers/net/skfp/h/smt.h b/drivers/net/skfp/h/smt.h
new file mode 100644
index 000000000..08eb1ccbf
--- /dev/null
+++ b/drivers/net/skfp/h/smt.h
@@ -0,0 +1,882 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * SMT 7.2 frame definitions
+ */
+
+#ifndef _SMT_
+#define _SMT_
+
+/* #define SMT5_10 */
+#define SMT6_10
+#define SMT7_20
+
+#define OPT_PMF /* if parameter management is supported */
+#define OPT_SRF /* if status report is supported */
+
+/*
+ * SMT frame version 5.1
+ */
+
+#define SMT_VID 0x0001 /* V 5.1 .. 6.1 */
+#define SMT_VID_2 0x0002 /* V 7.2 */
+
+struct smt_sid {
+ u_char sid_oem[2] ; /* implementation spec. */
+ struct fddi_addr sid_node ; /* node address */
+} ;
+
+typedef u_char t_station_id[8] ;
+
+/*
+ * note on alignment :
+ * sizeof(struct smt_header) = 32
+ * all parameters are long aligned
+ * if struct smt_header starts at offset 0, all longs are aligned correctly
+ * (FC starts at offset 3)
+ */
+_packed struct smt_header {
+ struct fddi_addr smt_dest ; /* destination address */
+ struct fddi_addr smt_source ; /* source address */
+ u_char smt_class ; /* NIF, SIF ... */
+ u_char smt_type ; /* req., response .. */
+ u_short smt_version ; /* version id */
+ u_long smt_tid ; /* transaction ID */
+ struct smt_sid smt_sid ; /* station ID */
+ u_short smt_pad ; /* pad with 0 */
+ u_short smt_len ; /* length of info field */
+} ;
+#define SWAP_SMTHEADER "662sl8ss"
+
+#if 0
+/*
+ * MAC FC values
+ */
+#define FC_SMT_INFO 0x41 /* SMT info */
+#define FC_SMT_NSA 0x4f /* SMT Next Station Addressing */
+#endif
+
+
+/*
+ * type codes
+ */
+#define SMT_ANNOUNCE 0x01 /* announcement */
+#define SMT_REQUEST 0x02 /* request */
+#define SMT_REPLY 0x03 /* reply */
+
+/*
+ * class codes
+ */
+#define SMT_NIF 0x01 /* neighbor information frames */
+#define SMT_SIF_CONFIG 0x02 /* station information configuration */
+#define SMT_SIF_OPER 0x03 /* station information operation */
+#define SMT_ECF 0x04 /* echo frames */
+#define SMT_RAF 0x05 /* resource allocation */
+#define SMT_RDF 0x06 /* request denied */
+#define SMT_SRF 0x07 /* status report */
+#define SMT_PMF_GET 0x08 /* parameter management get */
+#define SMT_PMF_SET 0x09 /* parameter management set */
+#define SMT_ESF 0xff /* extended service */
+
+#define SMT_MAX_ECHO_LEN 4458 /* max length of SMT Echo */
+#if defined(CONC) || defined(CONC_II)
+#define SMT_TEST_ECHO_LEN 50 /* test length of SMT Echo */
+#else
+#define SMT_TEST_ECHO_LEN SMT_MAX_ECHO_LEN /* test length */
+#endif
+
+#define SMT_MAX_INFO_LEN (4352-20) /* max length for SMT info */
+
+
+/*
+ * parameter types
+ */
+
+struct smt_para {
+ u_short p_type ; /* type */
+ u_short p_len ; /* length of parameter */
+} ;
+
+#define PARA_LEN (sizeof(struct smt_para))
+
+#define SMTSETPARA(p,t) (p)->para.p_type = (t),\
+ (p)->para.p_len = sizeof(*(p)) - PARA_LEN
+
+/*
+ * P01 : Upstream Neighbor Address, UNA
+ */
+#define SMT_P_UNA 0x0001 /* upstream neighbor address */
+#define SWAP_SMT_P_UNA "s6"
+
+struct smt_p_una {
+ struct smt_para para ; /* generic parameter header */
+ u_short una_pad ;
+ struct fddi_addr una_node ; /* node address, zero if unknown */
+} ;
+
+/*
+ * P02 : Station Descriptor
+ */
+#define SMT_P_SDE 0x0002 /* station descriptor */
+#define SWAP_SMT_P_SDE "1111"
+
+#define SMT_SDE_STATION 0 /* end node */
+#define SMT_SDE_CONCENTRATOR 1 /* concentrator */
+
+struct smt_p_sde {
+ struct smt_para para ; /* generic parameter header */
+ u_char sde_type ; /* station type */
+ u_char sde_mac_count ; /* number of MACs */
+ u_char sde_non_master ; /* number of A,B or S ports */
+ u_char sde_master ; /* number of S ports on conc. */
+} ;
+
+/*
+ * P03 : Station State
+ */
+#define SMT_P_STATE 0x0003 /* station state */
+#define SWAP_SMT_P_STATE "scc"
+
+struct smt_p_state {
+ struct smt_para para ; /* generic parameter header */
+ u_short st_pad ;
+ u_char st_topology ; /* topology */
+ u_char st_dupl_addr ; /* duplicate address detected */
+} ;
+#define SMT_ST_WRAPPED (1<<0) /* station wrapped */
+#define SMT_ST_UNATTACHED (1<<1) /* unattached concentrator */
+#define SMT_ST_TWISTED_A (1<<2) /* A-A connection, twisted ring */
+#define SMT_ST_TWISTED_B (1<<3) /* B-B connection, twisted ring */
+#define SMT_ST_ROOTED_S (1<<4) /* rooted station */
+#define SMT_ST_SRF (1<<5) /* SRF protocol supported */
+#define SMT_ST_SYNC_SERVICE (1<<6) /* use synchronous bandwidth */
+
+#define SMT_ST_MY_DUPA (1<<0) /* my station detected dupl. */
+#define SMT_ST_UNA_DUPA (1<<1) /* my UNA detected duplicate */
+
+/*
+ * P04 : timestamp
+ */
+#define SMT_P_TIMESTAMP 0x0004 /* time stamp */
+#define SWAP_SMT_P_TIMESTAMP "8"
+struct smt_p_timestamp {
+ struct smt_para para ; /* generic parameter header */
+ u_char ts_time[8] ; /* time, resolution 80nS, unique */
+} ;
+
+/*
+ * P05 : station policies
+ */
+#define SMT_P_POLICY 0x0005 /* station policies */
+#define SWAP_SMT_P_POLICY "ss"
+
+struct smt_p_policy {
+ struct smt_para para ; /* generic parameter header */
+ u_short pl_config ;
+ u_short pl_connect ; /* bit string POLICY_AA ... */
+} ;
+#define SMT_PL_HOLD 1 /* hold policy supported (Dual MAC) */
+
+/*
+ * P06 : latency equivalent
+ */
+#define SMT_P_LATENCY 0x0006 /* latency */
+#define SWAP_SMT_P_LATENCY "ssss"
+
+/*
+ * note: latency has two phy entries by definition
+ * for a SAS, the 2nd one is null
+ */
+struct smt_p_latency {
+ struct smt_para para ; /* generic parameter header */
+ u_short lt_phyout_idx1 ; /* index */
+ u_short lt_latency1 ; /* latency , unit : byte clock */
+ u_short lt_phyout_idx2 ; /* 0 if SAS */
+ u_short lt_latency2 ; /* 0 if SAS */
+} ;
+
+/*
+ * P07 : MAC neighbors
+ */
+#define SMT_P_NEIGHBORS 0x0007 /* MAC neighbor description */
+#define SWAP_SMT_P_NEIGHBORS "ss66"
+
+struct smt_p_neighbor {
+ struct smt_para para ; /* generic parameter header */
+ u_short nb_mib_index ; /* MIB index */
+ u_short nb_mac_index ; /* n+1 .. n+m, m = #MACs, n = #PHYs */
+ struct fddi_addr nb_una ; /* UNA , 0 for unknown */
+ struct fddi_addr nb_dna ; /* DNA , 0 for unknown */
+} ;
+
+/*
+ * PHY record
+ */
+#define SMT_PHY_A 0 /* A port */
+#define SMT_PHY_B 1 /* B port */
+#define SMT_PHY_S 2 /* slave port */
+#define SMT_PHY_M 3 /* master port */
+
+#define SMT_CS_DISABLED 0 /* connect state : disabled */
+#define SMT_CS_CONNECTING 1 /* connect state : connecting */
+#define SMT_CS_STANDBY 2 /* connect state : stand by */
+#define SMT_CS_ACTIVE 3 /* connect state : active */
+
+#define SMT_RM_NONE 0
+#define SMT_RM_MAC 1
+
+struct smt_phy_rec {
+ u_short phy_mib_index ; /* MIB index */
+ u_char phy_type ; /* A/B/S/M */
+ u_char phy_connect_state ; /* disabled/connecting/active */
+ u_char phy_remote_type ; /* A/B/S/M */
+ u_char phy_remote_mac ; /* none/remote */
+ u_short phy_resource_idx ; /* 1 .. n */
+} ;
+
+/*
+ * MAC record
+ */
+struct smt_mac_rec {
+ struct fddi_addr mac_addr ; /* MAC address */
+ u_short mac_resource_idx ; /* n+1 .. n+m */
+} ;
+
+/*
+ * P08 : path descriptors
+ * should be really an array ; however our environment has a fixed number of
+ * PHYs and MACs
+ */
+#define SMT_P_PATH 0x0008 /* path descriptor */
+#define SWAP_SMT_P_PATH "[6s]"
+
+struct smt_p_path {
+ struct smt_para para ; /* generic parameter header */
+ struct smt_phy_rec pd_phy[2] ; /* PHY A */
+ struct smt_mac_rec pd_mac ; /* MAC record */
+} ;
+
+/*
+ * P09 : MAC status
+ */
+#define SMT_P_MAC_STATUS 0x0009 /* MAC status */
+#define SWAP_SMT_P_MAC_STATUS "sslllllllll"
+
+struct smt_p_mac_status {
+ struct smt_para para ; /* generic parameter header */
+ u_short st_mib_index ; /* MIB index */
+ u_short st_mac_index ; /* n+1 .. n+m */
+ u_long st_t_req ; /* T_Req */
+ u_long st_t_neg ; /* T_Neg */
+ u_long st_t_max ; /* T_Max */
+ u_long st_tvx_value ; /* TVX_Value */
+ u_long st_t_min ; /* T_Min */
+ u_long st_sba ; /* synchr. bandwidth alloc */
+ u_long st_frame_ct ; /* frame counter */
+ u_long st_error_ct ; /* error counter */
+ u_long st_lost_ct ; /* lost frames counter */
+} ;
+
+/*
+ * P0A : PHY link error rate monitoring
+ */
+#define SMT_P_LEM 0x000a /* link error monitor */
+#define SWAP_SMT_P_LEM "ssccccll"
+/*
+ * units of lem_cutoff,lem_alarm,lem_estimate : 10**-x
+ */
+struct smt_p_lem {
+ struct smt_para para ; /* generic parameter header */
+ u_short lem_mib_index ; /* MIB index */
+ u_short lem_phy_index ; /* 1 .. n */
+ u_char lem_pad2 ; /* be nice and make it even . */
+ u_char lem_cutoff ; /* 0x4 .. 0xf, default 0x7 */
+ u_char lem_alarm ; /* 0x4 .. 0xf, default 0x8 */
+ u_char lem_estimate ; /* 0x0 .. 0xff */
+ u_long lem_reject_ct ; /* 0x00000000 .. 0xffffffff */
+ u_long lem_ct ; /* 0x00000000 .. 0xffffffff */
+} ;
+
+/*
+ * P0B : MAC frame counters
+ */
+#define SMT_P_MAC_COUNTER 0x000b /* MAC frame counters */
+#define SWAP_SMT_P_MAC_COUNTER "ssll"
+
+struct smt_p_mac_counter {
+ struct smt_para para ; /* generic parameter header */
+ u_short mc_mib_index ; /* MIB index */
+ u_short mc_index ; /* mac index */
+ u_long mc_receive_ct ; /* receive counter */
+ u_long mc_transmit_ct ; /* transmit counter */
+} ;
+
+/*
+ * P0C : MAC frame not copied counter
+ */
+#define SMT_P_MAC_FNC 0x000c /* MAC frame not copied counter */
+#define SWAP_SMT_P_MAC_FNC "ssl"
+
+struct smt_p_mac_fnc {
+ struct smt_para para ; /* generic parameter header */
+ u_short nc_mib_index ; /* MIB index */
+ u_short nc_index ; /* mac index */
+ u_long nc_counter ; /* not copied counter */
+} ;
+
+
+/*
+ * P0D : MAC priority values
+ */
+#define SMT_P_PRIORITY 0x000d /* MAC priority values */
+#define SWAP_SMT_P_PRIORITY "ssl"
+
+struct smt_p_priority {
+ struct smt_para para ; /* generic parameter header */
+ u_short pr_mib_index ; /* MIB index */
+ u_short pr_index ; /* mac index */
+ u_long pr_priority[7] ; /* priority values */
+} ;
+
+/*
+ * P0E : PHY elasticity buffer status
+ */
+#define SMT_P_EB 0x000e /* PHY EB status */
+#define SWAP_SMT_P_EB "ssl"
+
+struct smt_p_eb {
+ struct smt_para para ; /* generic parameter header */
+ u_short eb_mib_index ; /* MIB index */
+ u_short eb_index ; /* phy index */
+ u_long eb_error_ct ; /* # of eb overflows */
+} ;
+
+/*
+ * P0F : manufacturer field
+ */
+#define SMT_P_MANUFACTURER 0x000f /* manufacturer field */
+#define SWAP_SMT_P_MANUFACTURER ""
+
+struct smp_p_manufacturer {
+ struct smt_para para ; /* generic parameter header */
+ u_char mf_data[32] ; /* OUI + arbitrary data */
+} ;
+
+/*
+ * P10 : user field
+ */
+#define SMT_P_USER 0x0010 /* manufacturer field */
+#define SWAP_SMT_P_USER ""
+
+struct smp_p_user {
+ struct smt_para para ; /* generic parameter header */
+ u_char us_data[32] ; /* arbitrary data */
+} ;
+
+
+
+/*
+ * P11 : echo data
+ */
+#define SMT_P_ECHODATA 0x0011 /* echo data */
+#define SWAP_SMT_P_ECHODATA ""
+
+struct smt_p_echo {
+ struct smt_para para ; /* generic parameter header */
+ u_char ec_data[SMT_MAX_ECHO_LEN-4] ; /* echo data */
+} ;
+
+/*
+ * P12 : reason code
+ */
+#define SMT_P_REASON 0x0012 /* reason code */
+#define SWAP_SMT_P_REASON "l"
+
+struct smt_p_reason {
+ struct smt_para para ; /* generic parameter header */
+ u_long rdf_reason ; /* CLASS/VERSION */
+} ;
+#define SMT_RDF_CLASS 0x00000001 /* class not supported */
+#define SMT_RDF_VERSION 0x00000002 /* version not supported */
+#define SMT_RDF_SUCCESS 0x00000003 /* success (PMF) */
+#define SMT_RDF_BADSET 0x00000004 /* bad set count (PMF) */
+#define SMT_RDF_ILLEGAL 0x00000005 /* read only (PMF) */
+#define SMT_RDF_NOPARAM 0x6 /* paramter not supported (PMF) */
+#define SMT_RDF_RANGE 0x8 /* out of range */
+#define SMT_RDF_AUTHOR 0x9 /* not autohorized */
+#define SMT_RDF_LENGTH 0x0a /* length error */
+#define SMT_RDF_TOOLONG 0x0b /* length error */
+#define SMT_RDF_SBA 0x0d /* SBA denied */
+
+/*
+ * P13 : refused frame beginning
+ */
+#define SMT_P_REFUSED 0x0013 /* refused frame beginning */
+#define SWAP_SMT_P_REFUSED "l"
+
+struct smt_p_refused {
+ struct smt_para para ; /* generic parameter header */
+ u_long ref_fc ; /* 3 bytes 0 + FC */
+ struct smt_header ref_header ; /* refused header */
+} ;
+
+/*
+ * P14 : supported SMT versions
+ */
+#define SMT_P_VERSION 0x0014 /* SMT supported versions */
+#define SWAP_SMT_P_VERSION "sccss"
+
+struct smt_p_version {
+ struct smt_para para ; /* generic parameter header */
+ u_short v_pad ;
+ u_char v_n ; /* 1 .. 0xff, #versions */
+ u_char v_index ; /* 1 .. 0xff, index of op. v. */
+ u_short v_version[1] ; /* list of min. 1 version */
+ u_short v_pad2 ; /* pad if necessary */
+} ;
+
+/*
+ * P15 : Resource Type
+ */
+#define SWAP_SMT_P0015 "l"
+
+struct smt_p_0015 {
+ struct smt_para para ; /* generic parameter header */
+ u_long res_type ; /* recsource type */
+} ;
+
+#define SYNC_BW 0x00000001L /* Synchronous Bandwidth */
+
+/*
+ * P16 : SBA Command
+ */
+#define SWAP_SMT_P0016 "l"
+
+struct smt_p_0016 {
+ struct smt_para para ; /* generic parameter header */
+ u_long sba_cmd ; /* command for the SBA */
+} ;
+
+#define REQUEST_ALLOCATION 0x1 /* req allocation of sync bandwidth */
+#define REPORT_ALLOCATION 0x2 /* rep of sync bandwidth allocation */
+#define CHANGE_ALLOCATION 0x3 /* forces a station using sync band-*/
+ /* width to change its current allo-*/
+ /* cation */
+
+/*
+ * P17 : SBA Payload Request
+ */
+#define SWAP_SMT_P0017 "l"
+
+struct smt_p_0017 {
+ struct smt_para para ; /* generic parameter header */
+ long sba_pl_req ; /* total sync bandwidth measured in */
+} ; /* bytes per 125 us */
+
+/*
+ * P18 : SBA Overhead Request
+ */
+#define SWAP_SMT_P0018 "l"
+
+struct smt_p_0018 {
+ struct smt_para para ; /* generic parameter header */
+ long sba_ov_req ; /* total sync bandwidth req for overhead*/
+} ; /* measuered in bytes per T_Neg */
+
+/*
+ * P19 : SBA Allocation Address
+ */
+#define SWAP_SMT_P0019 "s6"
+
+struct smt_p_0019 {
+ struct smt_para para ; /* generic parameter header */
+ u_short sba_pad ;
+ struct fddi_addr alloc_addr ; /* Allocation Address */
+} ;
+
+/*
+ * P1A : SBA Category
+ */
+#define SWAP_SMT_P001A "l"
+
+struct smt_p_001a {
+ struct smt_para para ; /* generic parameter header */
+ u_long category ; /* Allocator defined classification */
+} ;
+
+/*
+ * P1B : Maximum T_Neg
+ */
+#define SWAP_SMT_P001B "l"
+
+struct smt_p_001b {
+ struct smt_para para ; /* generic parameter header */
+ u_long max_t_neg ; /* longest T_NEG for the sync service*/
+} ;
+
+/*
+ * P1C : Minimum SBA Segment Size
+ */
+#define SWAP_SMT_P001C "l"
+
+struct smt_p_001c {
+ struct smt_para para ; /* generic parameter header */
+ u_long min_seg_siz ; /* smallest number of bytes per frame*/
+} ;
+
+/*
+ * P1D : SBA Allocatable
+ */
+#define SWAP_SMT_P001D "l"
+
+struct smt_p_001d {
+ struct smt_para para ; /* generic parameter header */
+ u_long allocatable ; /* total sync bw availabel for alloc */
+} ;
+
+/*
+ * P20 0B : frame status capabilities
+ * NOTE: not in swap table, is used by smt.c AND PMF table
+ */
+#define SMT_P_FSC 0x200b
+/* #define SWAP_SMT_P_FSC "ssss" */
+
+struct smt_p_fsc {
+ struct smt_para para ; /* generic parameter header */
+ u_short fsc_pad0 ;
+ u_short fsc_mac_index ; /* mac index 1 .. ff */
+ u_short fsc_pad1 ;
+ u_short fsc_value ; /* FSC_TYPE[0-2] */
+} ;
+
+#define FSC_TYPE0 0 /* "normal" node (A/C handling) */
+#define FSC_TYPE1 1 /* Special A/C indicator forwarding */
+#define FSC_TYPE2 2 /* Special A/C indicator forwarding */
+
+/*
+ * P00 21 : user defined authoriziation (see pmf.c)
+ */
+#define SMT_P_AUTHOR 0x0021
+
+/*
+ * notification parameters
+ */
+#define SWAP_SMT_P1048 "ll"
+struct smt_p_1048 {
+ u_long p1048_flag ;
+ u_long p1048_cf_state ;
+} ;
+
+/*
+ * NOTE: all 2xxx 3xxx and 4xxx must include the INDEX in the swap string,
+ * even so the INDEX is NOT part of the struct.
+ * INDEX is already swapped in pmf.c, format in string is '4'
+ */
+#define SWAP_SMT_P208C "4lss66"
+struct smt_p_208c {
+ u_long p208c_flag ;
+ u_short p208c_pad ;
+ u_short p208c_dupcondition ;
+ struct fddi_addr p208c_fddilong ;
+ struct fddi_addr p208c_fddiunalong ;
+} ;
+
+#define SWAP_SMT_P208D "4lllll"
+struct smt_p_208d {
+ u_long p208d_flag ;
+ u_long p208d_frame_ct ;
+ u_long p208d_error_ct ;
+ u_long p208d_lost_ct ;
+ u_long p208d_ratio ;
+} ;
+
+#define SWAP_SMT_P208E "4llll"
+struct smt_p_208e {
+ u_long p208e_flag ;
+ u_long p208e_not_copied ;
+ u_long p208e_copied ;
+ u_long p208e_not_copied_ratio ;
+} ;
+
+#define SWAP_SMT_P208F "4ll6666s6"
+
+struct smt_p_208f {
+ u_long p208f_multiple ;
+ u_long p208f_nacondition ;
+ struct fddi_addr p208f_old_una ;
+ struct fddi_addr p208f_new_una ;
+ struct fddi_addr p208f_old_dna ;
+ struct fddi_addr p208f_new_dna ;
+ u_short p208f_curren_path ;
+ struct fddi_addr p208f_smt_address ;
+} ;
+
+#define SWAP_SMT_P2090 "4lssl"
+
+struct smt_p_2090 {
+ u_long p2090_multiple ;
+ u_short p2090_availablepaths ;
+ u_short p2090_currentpath ;
+ u_long p2090_requestedpaths ;
+} ;
+
+/*
+ * NOTE:
+ * special kludge for parameters 320b,320f,3210
+ * these parameters are part of RAF frames
+ * RAF frames are parsed in SBA.C and must be swapped
+ * PMF.C has special code to avoid double swapping
+ */
+#ifdef LITTLE_ENDIAN
+#define SBAPATHINDEX (0x01000000L)
+#else
+#define SBAPATHINDEX (0x01L)
+#endif
+
+#define SWAP_SMT_P320B "42s"
+
+struct smt_p_320b {
+ struct smt_para para ; /* generic parameter header */
+ u_long mib_index ;
+ u_short path_pad ;
+ u_short path_index ;
+} ;
+
+#define SWAP_SMT_P320F "4l"
+
+struct smt_p_320f {
+ struct smt_para para ; /* generic parameter header */
+ u_long mib_index ;
+ u_long mib_payload ;
+} ;
+
+#define SWAP_SMT_P3210 "4l"
+
+struct smt_p_3210 {
+ struct smt_para para ; /* generic parameter header */
+ u_long mib_index ;
+ u_long mib_overhead ;
+} ;
+
+#define SWAP_SMT_P4050 "4l1111ll"
+
+struct smt_p_4050 {
+ u_long p4050_flag ;
+ u_char p4050_pad ;
+ u_char p4050_cutoff ;
+ u_char p4050_alarm ;
+ u_char p4050_estimate ;
+ u_long p4050_reject_ct ;
+ u_long p4050_ct ;
+} ;
+
+#define SWAP_SMT_P4051 "4lssss"
+struct smt_p_4051 {
+ u_long p4051_multiple ;
+ u_short p4051_porttype ;
+ u_short p4051_connectstate ;
+ u_short p4051_pc_neighbor ;
+ u_short p4051_pc_withhold ;
+} ;
+
+#define SWAP_SMT_P4052 "4ll"
+struct smt_p_4052 {
+ u_long p4052_flag ;
+ u_long p4052_eberrorcount ;
+} ;
+
+#define SWAP_SMT_P4053 "4lsslss"
+
+struct smt_p_4053 {
+ u_long p4053_multiple ;
+ u_short p4053_availablepaths ;
+ u_short p4053_currentpath ;
+ u_long p4053_requestedpaths ;
+ u_short p4053_mytype ;
+ u_short p4053_neighbortype ;
+} ;
+
+
+#define SMT_P_SETCOUNT 0x1035
+#define SWAP_SMT_P_SETCOUNT "l8"
+
+struct smt_p_setcount {
+ struct smt_para para ; /* generic parameter header */
+ u_long count ;
+ u_char timestamp[8] ;
+} ;
+
+/*
+ * SMT FRAMES
+ */
+
+/*
+ * NIF : neighbor information frames
+ */
+struct smt_nif {
+ struct smt_header smt ; /* generic header */
+ struct smt_p_una una ; /* UNA */
+ struct smt_p_sde sde ; /* station descriptor */
+ struct smt_p_state state ; /* station state */
+#ifdef SMT6_10
+ struct smt_p_fsc fsc ; /* frame status cap. */
+#endif
+} ;
+
+/*
+ * SIF : station information frames
+ */
+struct smt_sif_config {
+ struct smt_header smt ; /* generic header */
+ struct smt_p_timestamp ts ; /* time stamp */
+ struct smt_p_sde sde ; /* station descriptor */
+ struct smt_p_version version ; /* supported versions */
+ struct smt_p_state state ; /* station state */
+ struct smt_p_policy policy ; /* station policy */
+ struct smt_p_latency latency ; /* path latency */
+ struct smt_p_neighbor neighbor ; /* neighbors, we have only one*/
+#ifdef OPT_PMF
+ struct smt_p_setcount setcount ; /* Set Count mandatory */
+#endif
+ /* WARNING : path MUST BE LAST FIELD !!! (see smt.c:smt_fill_path) */
+ struct smt_p_path path ; /* path descriptor */
+} ;
+#define SIZEOF_SMT_SIF_CONFIG (sizeof(struct smt_sif_config)- \
+ sizeof(struct smt_p_path))
+
+struct smt_sif_operation {
+ struct smt_header smt ; /* generic header */
+ struct smt_p_timestamp ts ; /* time stamp */
+ struct smt_p_mac_status status ; /* mac status */
+ struct smt_p_mac_counter mc ; /* MAC counter */
+ struct smt_p_mac_fnc fnc ; /* MAC frame not copied */
+ struct smp_p_manufacturer man ; /* manufacturer field */
+ struct smp_p_user user ; /* user field */
+#ifdef OPT_PMF
+ struct smt_p_setcount setcount ; /* Set Count mandatory */
+#endif
+ /* must be last */
+ struct smt_p_lem lem[1] ; /* phy lem status */
+} ;
+#define SIZEOF_SMT_SIF_OPERATION (sizeof(struct smt_sif_operation)- \
+ sizeof(struct smt_p_lem))
+
+/*
+ * ECF : echo frame
+ */
+struct smt_ecf {
+ struct smt_header smt ; /* generic header */
+ struct smt_p_echo ec_echo ; /* echo parameter */
+} ;
+#define SMT_ECF_LEN (sizeof(struct smt_header)+sizeof(struct smt_para))
+
+/*
+ * RDF : request denied frame
+ */
+struct smt_rdf {
+ struct smt_header smt ; /* generic header */
+ struct smt_p_reason reason ; /* reason code */
+ struct smt_p_version version ; /* supported versions */
+ struct smt_p_refused refused ; /* refused frame fragment */
+} ;
+
+/*
+ * SBA Request Allocation Responce Frame
+ */
+struct smt_sba_alc_res {
+ struct smt_header smt ; /* generic header */
+ struct smt_p_0015 s_type ; /* resource type */
+ struct smt_p_0016 cmd ; /* SBA command */
+ struct smt_p_reason reason ; /* reason code */
+ struct smt_p_320b path ; /* path type */
+ struct smt_p_320f payload ; /* current SBA payload */
+ struct smt_p_3210 overhead ; /* current SBA overhead */
+ struct smt_p_0019 a_addr ; /* Allocation Address */
+ struct smt_p_001a cat ; /* Category - from the request */
+ struct smt_p_001d alloc ; /* SBA Allocatable */
+} ;
+
+/*
+ * SBA Request Allocation Request Frame
+ */
+struct smt_sba_alc_req {
+ struct smt_header smt ; /* generic header */
+ struct smt_p_0015 s_type ; /* resource type */
+ struct smt_p_0016 cmd ; /* SBA command */
+ struct smt_p_320b path ; /* path type */
+ struct smt_p_0017 pl_req ; /* requested payload */
+ struct smt_p_0018 ov_req ; /* requested SBA overhead */
+ struct smt_p_320f payload ; /* current SBA payload */
+ struct smt_p_3210 overhead ; /* current SBA overhead */
+ struct smt_p_0019 a_addr ; /* Allocation Address */
+ struct smt_p_001a cat ; /* Category - from the request */
+ struct smt_p_001b tneg ; /* max T-NEG */
+ struct smt_p_001c segm ; /* minimum segment size */
+} ;
+
+/*
+ * SBA Change Allocation Request Frame
+ */
+struct smt_sba_chg {
+ struct smt_header smt ; /* generic header */
+ struct smt_p_0015 s_type ; /* resource type */
+ struct smt_p_0016 cmd ; /* SBA command */
+ struct smt_p_320b path ; /* path type */
+ struct smt_p_320f payload ; /* current SBA payload */
+ struct smt_p_3210 overhead ; /* current SBA overhead */
+ struct smt_p_001a cat ; /* Category - from the request */
+} ;
+
+/*
+ * SBA Report Allocation Request Frame
+ */
+struct smt_sba_rep_req {
+ struct smt_header smt ; /* generic header */
+ struct smt_p_0015 s_type ; /* resource type */
+ struct smt_p_0016 cmd ; /* SBA command */
+} ;
+
+/*
+ * SBA Report Allocation Response Frame
+ */
+struct smt_sba_rep_res {
+ struct smt_header smt ; /* generic header */
+ struct smt_p_0015 s_type ; /* resource type */
+ struct smt_p_0016 cmd ; /* SBA command */
+ struct smt_p_320b path ; /* path type */
+ struct smt_p_320f payload ; /* current SBA payload */
+ struct smt_p_3210 overhead ; /* current SBA overhead */
+} ;
+
+/*
+ * actions
+ */
+#define SMT_STATION_ACTION 1
+#define SMT_STATION_ACTION_CONNECT 0
+#define SMT_STATION_ACTION_DISCONNECT 1
+#define SMT_STATION_ACTION_PATHTEST 2
+#define SMT_STATION_ACTION_SELFTEST 3
+#define SMT_STATION_ACTION_DISABLE_A 4
+#define SMT_STATION_ACTION_DISABLE_B 5
+#define SMT_STATION_ACTION_DISABLE_M 6
+
+#define SMT_PORT_ACTION 2
+#define SMT_PORT_ACTION_MAINT 0
+#define SMT_PORT_ACTION_ENABLE 1
+#define SMT_PORT_ACTION_DISABLE 2
+#define SMT_PORT_ACTION_START 3
+#define SMT_PORT_ACTION_STOP 4
+
+#endif /* _SMT_ */
diff --git a/drivers/net/skfp/h/smt_p.h b/drivers/net/skfp/h/smt_p.h
new file mode 100644
index 000000000..99f9be955
--- /dev/null
+++ b/drivers/net/skfp/h/smt_p.h
@@ -0,0 +1,326 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * defines for all SMT attributes
+ */
+
+/*
+ * this boring file was produced by perl
+ * thanks Larry !
+ */
+#define SMT_P0012 0x0012
+
+#define SMT_P0015 0x0015
+#define SMT_P0016 0x0016
+#define SMT_P0017 0x0017
+#define SMT_P0018 0x0018
+#define SMT_P0019 0x0019
+
+#define SMT_P001A 0x001a
+#define SMT_P001B 0x001b
+#define SMT_P001C 0x001c
+#define SMT_P001D 0x001d
+
+#define SMT_P100A 0x100a
+#define SMT_P100B 0x100b
+#define SMT_P100C 0x100c
+#define SMT_P100D 0x100d
+#define SMT_P100E 0x100e
+#define SMT_P100F 0x100f
+#define SMT_P1010 0x1010
+#define SMT_P1011 0x1011
+#define SMT_P1012 0x1012
+#define SMT_P1013 0x1013
+#define SMT_P1014 0x1014
+#define SMT_P1015 0x1015
+#define SMT_P1016 0x1016
+#define SMT_P1017 0x1017
+#define SMT_P1018 0x1018
+#define SMT_P1019 0x1019
+#define SMT_P101A 0x101a
+#define SMT_P101B 0x101b
+#define SMT_P101C 0x101c
+#define SMT_P101D 0x101d
+#define SMT_P101E 0x101e
+#define SMT_P101F 0x101f
+#define SMT_P1020 0x1020
+#define SMT_P1021 0x1021
+#define SMT_P1022 0x1022
+#define SMT_P1023 0x1023
+#define SMT_P1024 0x1024
+#define SMT_P1025 0x1025
+#define SMT_P1026 0x1026
+#define SMT_P1027 0x1027
+#define SMT_P1028 0x1028
+#define SMT_P1029 0x1029
+#define SMT_P102A 0x102a
+#define SMT_P102B 0x102b
+#define SMT_P102C 0x102c
+#define SMT_P102D 0x102d
+#define SMT_P102E 0x102e
+#define SMT_P102F 0x102f
+#define SMT_P1030 0x1030
+#define SMT_P1031 0x1031
+#define SMT_P1032 0x1032
+#define SMT_P1033 0x1033
+#define SMT_P1034 0x1034
+#define SMT_P1035 0x1035
+#define SMT_P1036 0x1036
+#define SMT_P1037 0x1037
+#define SMT_P1038 0x1038
+#define SMT_P1039 0x1039
+#define SMT_P103A 0x103a
+#define SMT_P103B 0x103b
+#define SMT_P103C 0x103c
+#define SMT_P103D 0x103d
+#define SMT_P103E 0x103e
+#define SMT_P103F 0x103f
+#define SMT_P1040 0x1040
+#define SMT_P1041 0x1041
+#define SMT_P1042 0x1042
+#define SMT_P1043 0x1043
+#define SMT_P1044 0x1044
+#define SMT_P1045 0x1045
+#define SMT_P1046 0x1046
+#define SMT_P1047 0x1047
+#define SMT_P1048 0x1048
+#define SMT_P1049 0x1049
+#define SMT_P104A 0x104a
+#define SMT_P104B 0x104b
+#define SMT_P104C 0x104c
+#define SMT_P104D 0x104d
+#define SMT_P104E 0x104e
+#define SMT_P104F 0x104f
+#define SMT_P1050 0x1050
+#define SMT_P1051 0x1051
+#define SMT_P1052 0x1052
+#define SMT_P1053 0x1053
+#define SMT_P1054 0x1054
+
+#define SMT_P10F0 0x10f0
+#define SMT_P10F1 0x10f1
+#ifdef ESS
+#define SMT_P10F2 0x10f2
+#define SMT_P10F3 0x10f3
+#define SMT_P10F4 0x10f4
+#define SMT_P10F5 0x10f5
+#define SMT_P10F6 0x10f6
+#define SMT_P10F7 0x10f7
+#endif
+#ifdef SBA
+#define SMT_P10F8 0x10f8
+#define SMT_P10F9 0x10f9
+#endif
+
+#define SMT_P200A 0x200a
+#define SMT_P200B 0x200b
+#define SMT_P200C 0x200c
+#define SMT_P200D 0x200d
+#define SMT_P200E 0x200e
+#define SMT_P200F 0x200f
+#define SMT_P2010 0x2010
+#define SMT_P2011 0x2011
+#define SMT_P2012 0x2012
+#define SMT_P2013 0x2013
+#define SMT_P2014 0x2014
+#define SMT_P2015 0x2015
+#define SMT_P2016 0x2016
+#define SMT_P2017 0x2017
+#define SMT_P2018 0x2018
+#define SMT_P2019 0x2019
+#define SMT_P201A 0x201a
+#define SMT_P201B 0x201b
+#define SMT_P201C 0x201c
+#define SMT_P201D 0x201d
+#define SMT_P201E 0x201e
+#define SMT_P201F 0x201f
+#define SMT_P2020 0x2020
+#define SMT_P2021 0x2021
+#define SMT_P2022 0x2022
+#define SMT_P2023 0x2023
+#define SMT_P2024 0x2024
+#define SMT_P2025 0x2025
+#define SMT_P2026 0x2026
+#define SMT_P2027 0x2027
+#define SMT_P2028 0x2028
+#define SMT_P2029 0x2029
+#define SMT_P202A 0x202a
+#define SMT_P202B 0x202b
+#define SMT_P202C 0x202c
+#define SMT_P202D 0x202d
+#define SMT_P202E 0x202e
+#define SMT_P202F 0x202f
+#define SMT_P2030 0x2030
+#define SMT_P2031 0x2031
+#define SMT_P2032 0x2032
+#define SMT_P2033 0x2033
+#define SMT_P2034 0x2034
+#define SMT_P2035 0x2035
+#define SMT_P2036 0x2036
+#define SMT_P2037 0x2037
+#define SMT_P2038 0x2038
+#define SMT_P2039 0x2039
+#define SMT_P203A 0x203a
+#define SMT_P203B 0x203b
+#define SMT_P203C 0x203c
+#define SMT_P203D 0x203d
+#define SMT_P203E 0x203e
+#define SMT_P203F 0x203f
+#define SMT_P2040 0x2040
+#define SMT_P2041 0x2041
+#define SMT_P2042 0x2042
+#define SMT_P2043 0x2043
+#define SMT_P2044 0x2044
+#define SMT_P2045 0x2045
+#define SMT_P2046 0x2046
+#define SMT_P2047 0x2047
+#define SMT_P2048 0x2048
+#define SMT_P2049 0x2049
+#define SMT_P204A 0x204a
+#define SMT_P204B 0x204b
+#define SMT_P204C 0x204c
+#define SMT_P204D 0x204d
+#define SMT_P204E 0x204e
+#define SMT_P204F 0x204f
+#define SMT_P2050 0x2050
+#define SMT_P2051 0x2051
+#define SMT_P2052 0x2052
+#define SMT_P2053 0x2053
+#define SMT_P2054 0x2054
+#define SMT_P2055 0x2055
+#define SMT_P2056 0x2056
+#define SMT_P2057 0x2057
+#define SMT_P2058 0x2058
+#define SMT_P2059 0x2059
+#define SMT_P205A 0x205a
+#define SMT_P205B 0x205b
+#define SMT_P205C 0x205c
+#define SMT_P205D 0x205d
+#define SMT_P205E 0x205e
+#define SMT_P205F 0x205f
+#define SMT_P2060 0x2060
+#define SMT_P2061 0x2061
+#define SMT_P2062 0x2062
+#define SMT_P2063 0x2063
+#define SMT_P2064 0x2064
+#define SMT_P2065 0x2065
+#define SMT_P2066 0x2066
+#define SMT_P2067 0x2067
+#define SMT_P2068 0x2068
+#define SMT_P2069 0x2069
+#define SMT_P206A 0x206a
+#define SMT_P206B 0x206b
+#define SMT_P206C 0x206c
+#define SMT_P206D 0x206d
+#define SMT_P206E 0x206e
+#define SMT_P206F 0x206f
+#define SMT_P2070 0x2070
+#define SMT_P2071 0x2071
+#define SMT_P2072 0x2072
+#define SMT_P2073 0x2073
+#define SMT_P2074 0x2074
+#define SMT_P2075 0x2075
+#define SMT_P2076 0x2076
+
+#define SMT_P208C 0x208c
+#define SMT_P208D 0x208d
+#define SMT_P208E 0x208e
+#define SMT_P208F 0x208f
+#define SMT_P2090 0x2090
+
+#define SMT_P20F0 0x20F0
+#define SMT_P20F1 0x20F1
+
+#define SMT_P320A 0x320a
+#define SMT_P320B 0x320b
+#define SMT_P320C 0x320c
+#define SMT_P320D 0x320d
+#define SMT_P320E 0x320e
+#define SMT_P320F 0x320f
+#define SMT_P3210 0x3210
+#define SMT_P3211 0x3211
+#define SMT_P3212 0x3212
+#define SMT_P3213 0x3213
+#define SMT_P3214 0x3214
+#define SMT_P3215 0x3215
+#define SMT_P3216 0x3216
+#define SMT_P3217 0x3217
+
+#define SMT_P400A 0x400a
+#define SMT_P400B 0x400b
+#define SMT_P400C 0x400c
+#define SMT_P400D 0x400d
+#define SMT_P400E 0x400e
+#define SMT_P400F 0x400f
+#define SMT_P4010 0x4010
+#define SMT_P4011 0x4011
+#define SMT_P4012 0x4012
+#define SMT_P4013 0x4013
+#define SMT_P4014 0x4014
+#define SMT_P4015 0x4015
+#define SMT_P4016 0x4016
+#define SMT_P4017 0x4017
+#define SMT_P4018 0x4018
+#define SMT_P4019 0x4019
+#define SMT_P401A 0x401a
+#define SMT_P401B 0x401b
+#define SMT_P401C 0x401c
+#define SMT_P401D 0x401d
+#define SMT_P401E 0x401e
+#define SMT_P401F 0x401f
+#define SMT_P4020 0x4020
+#define SMT_P4021 0x4021
+#define SMT_P4022 0x4022
+#define SMT_P4023 0x4023
+#define SMT_P4024 0x4024
+#define SMT_P4025 0x4025
+#define SMT_P4026 0x4026
+#define SMT_P4027 0x4027
+#define SMT_P4028 0x4028
+#define SMT_P4029 0x4029
+#define SMT_P402A 0x402a
+#define SMT_P402B 0x402b
+#define SMT_P402C 0x402c
+#define SMT_P402D 0x402d
+#define SMT_P402E 0x402e
+#define SMT_P402F 0x402f
+#define SMT_P4030 0x4030
+#define SMT_P4031 0x4031
+#define SMT_P4032 0x4032
+#define SMT_P4033 0x4033
+#define SMT_P4034 0x4034
+#define SMT_P4035 0x4035
+#define SMT_P4036 0x4036
+#define SMT_P4037 0x4037
+#define SMT_P4038 0x4038
+#define SMT_P4039 0x4039
+#define SMT_P403A 0x403a
+#define SMT_P403B 0x403b
+#define SMT_P403C 0x403c
+#define SMT_P403D 0x403d
+#define SMT_P403E 0x403e
+#define SMT_P403F 0x403f
+#define SMT_P4040 0x4040
+#define SMT_P4041 0x4041
+#define SMT_P4042 0x4042
+#define SMT_P4043 0x4043
+#define SMT_P4044 0x4044
+#define SMT_P4045 0x4045
+#define SMT_P4046 0x4046
+
+#define SMT_P4050 0x4050
+#define SMT_P4051 0x4051
+#define SMT_P4052 0x4052
+#define SMT_P4053 0x4053
diff --git a/drivers/net/skfp/h/smtstate.h b/drivers/net/skfp/h/smtstate.h
new file mode 100644
index 000000000..689fa25dc
--- /dev/null
+++ b/drivers/net/skfp/h/smtstate.h
@@ -0,0 +1,100 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * SMT state definitions
+ */
+
+#ifndef KERNEL
+/*
+ * PCM states
+ */
+#define PC0_OFF 0
+#define PC1_BREAK 1
+#define PC2_TRACE 2
+#define PC3_CONNECT 3
+#define PC4_NEXT 4
+#define PC5_SIGNAL 5
+#define PC6_JOIN 6
+#define PC7_VERIFY 7
+#define PC8_ACTIVE 8
+#define PC9_MAINT 9
+
+/*
+ * PCM modes
+ */
+#define PM_NONE 0
+#define PM_PEER 1
+#define PM_TREE 2
+
+/*
+ * PCM type
+ */
+#define TA 0
+#define TB 1
+#define TS 2
+#define TM 3
+#define TNONE 4
+
+/*
+ * CFM states
+ */
+#define SC0_ISOLATED 0 /* isolated */
+#define SC1_WRAP_A 5 /* wrap A */
+#define SC2_WRAP_B 6 /* wrap B */
+#define SC4_THRU_A 12 /* through A */
+#define SC5_THRU_B 7 /* through B (SMt 6.2) */
+#define SC7_WRAP_S 8 /* SAS */
+
+/*
+ * ECM states
+ */
+#define EC0_OUT 0
+#define EC1_IN 1
+#define EC2_TRACE 2
+#define EC3_LEAVE 3
+#define EC4_PATH_TEST 4
+#define EC5_INSERT 5
+#define EC6_CHECK 6
+#define EC7_DEINSERT 7
+
+/*
+ * RMT states
+ */
+#define RM0_ISOLATED 0
+#define RM1_NON_OP 1 /* not operational */
+#define RM2_RING_OP 2 /* ring operational */
+#define RM3_DETECT 3 /* detect dupl addresses */
+#define RM4_NON_OP_DUP 4 /* dupl. addr detected */
+#define RM5_RING_OP_DUP 5 /* ring oper. with dupl. addr */
+#define RM6_DIRECTED 6 /* sending directed beacons */
+#define RM7_TRACE 7 /* trace initiated */
+#endif
+
+struct pcm_state {
+ unsigned char pcm_type ; /* TA TB TS TM */
+ unsigned char pcm_state ; /* state PC[0-9]_* */
+ unsigned char pcm_mode ; /* PM_{NONE,PEER,TREE} */
+ unsigned char pcm_neighbor ; /* TA TB TS TM */
+ unsigned char pcm_bsf ; /* flag bs : TRUE/FALSE */
+ unsigned char pcm_lsf ; /* flag ls : TRUE/FALSE */
+ unsigned char pcm_lct_fail ; /* counter lct_fail */
+ unsigned char pcm_ls_rx ; /* rx line state */
+ short pcm_r_val ; /* signaling bits */
+ short pcm_t_val ; /* signaling bits */
+} ;
+
+struct smt_state {
+ struct pcm_state pcm_state[NUMPHYS] ; /* port A & port B */
+} ;
diff --git a/drivers/net/skfp/h/supern_2.h b/drivers/net/skfp/h/supern_2.h
new file mode 100644
index 000000000..ea564b337
--- /dev/null
+++ b/drivers/net/skfp/h/supern_2.h
@@ -0,0 +1,1059 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ defines for AMD Supernet II chip set
+ the chips are refered to as
+ FPLUS Formac Plus
+ PLC Physical Layer
+
+ added defines for AMD Supernet III chip set
+ added comments on differences between Supernet II and Supernet III
+ added defines for the Motorola ELM (MOT_ELM)
+*/
+
+#ifndef _SUPERNET_
+#define _SUPERNET_
+
+/*
+ * Define Supernet 3 when used
+ */
+#ifdef PCI
+#ifndef SUPERNET_3
+#define SUPERNET_3
+#endif
+#define TAG
+#endif
+
+#define MB 0xff
+#define MW 0xffff
+#define MD 0xffffffff
+
+/*
+ * FORMAC frame status (rx_msext)
+ */
+#define FS_EI (1<<2)
+#define FS_AI (1<<1)
+#define FS_CI (1<<0)
+
+#define FS_MSVALID (1<<15) /* end of queue */
+#define FS_MSRABT (1<<14) /* frame was aborted during reception*/
+#define FS_SSRCRTG (1<<12) /* if SA has set MSB (source-routing)*/
+#define FS_SEAC2 (FS_EI<<9) /* error indicator */
+#define FS_SEAC1 (FS_AI<<9) /* address indicator */
+#define FS_SEAC0 (FS_CI<<9) /* copy indicator */
+#define FS_SFRMERR (1<<8) /* error detected (CRC or length) */
+#define FS_SADRRG (1<<7) /* address recognized */
+#define FS_SFRMTY2 (1<<6) /* frame-class bit */
+#define FS_SFRMTY1 (1<<5) /* frame-type bit (impementor) */
+#define FS_SFRMTY0 (1<<4) /* frame-type bit (LLC) */
+#define FS_ERFBB1 (1<<1) /* byte offset (depends on LSB bit) */
+#define FS_ERFBB0 (1<<0) /* - " - */
+
+/*
+ * status frame type
+ */
+#define FRM_SMT (0) /* asynchr. frames */
+#define FRM_LLCA (1)
+#define FRM_IMPA (2)
+#define FRM_MAC (4) /* synchr. frames */
+#define FRM_LLCS (5)
+#define FRM_IMPS (6)
+
+/*
+ * bits in rx_descr.i (receive frame status word)
+ */
+#define RX_MSVALID ((long)1<<31) /* memory status valid */
+#define RX_MSRABT ((long)1<<30) /* memory status receive abort */
+#define RX_FS_E ((long)FS_SEAC2<<16) /* error indicator */
+#define RX_FS_A ((long)FS_SEAC1<<16) /* address indicator */
+#define RX_FS_C ((long)FS_SEAC0<<16) /* copy indicator */
+#define RX_FS_CRC ((long)FS_SFRMERR<<16)/* error detected */
+#define RX_FS_ADDRESS ((long)FS_SADRRG<<16) /* address recognized */
+#define RX_FS_MAC ((long)FS_SFRMTY2<<16)/* MAC frame */
+#define RX_FS_SMT ((long)0<<16) /* SMT frame */
+#define RX_FS_IMPL ((long)FS_SFRMTY1<<16)/* implementer frame */
+#define RX_FS_LLC ((long)FS_SFRMTY0<<16)/* LLC frame */
+
+/*
+ * receive frame descriptor
+ */
+union rx_descr {
+ struct {
+#ifdef LITTLE_ENDIAN
+ unsigned rx_length :16 ; /* frame length lower/upper byte */
+ unsigned rx_erfbb :2 ; /* received frame byte boundary */
+ unsigned rx_reserv2:2 ; /* reserved */
+ unsigned rx_sfrmty :3 ; /* frame type bits */
+ unsigned rx_sadrrg :1 ; /* DA == MA or broad-/multicast */
+ unsigned rx_sfrmerr:1 ; /* received frame not valid */
+ unsigned rx_seac0 :1 ; /* frame-copied C-indicator */
+ unsigned rx_seac1 :1 ; /* address-match A-indicator */
+ unsigned rx_seac2 :1 ; /* frame-error E-indicator */
+ unsigned rx_ssrcrtg:1 ; /* == 1 SA has MSB set */
+ unsigned rx_reserv1:1 ; /* reserved */
+ unsigned rx_msrabt :1 ; /* memory status receive abort */
+ unsigned rx_msvalid:1 ; /* memory status valid */
+#else
+ unsigned rx_msvalid:1 ; /* memory status valid */
+ unsigned rx_msrabt :1 ; /* memory status receive abort */
+ unsigned rx_reserv1:1 ; /* reserved */
+ unsigned rx_ssrcrtg:1 ; /* == 1 SA has MSB set */
+ unsigned rx_seac2 :1 ; /* frame-error E-indicator */
+ unsigned rx_seac1 :1 ; /* address-match A-indicator */
+ unsigned rx_seac0 :1 ; /* frame-copied C-indicator */
+ unsigned rx_sfrmerr:1 ; /* received frame not valid */
+ unsigned rx_sadrrg :1 ; /* DA == MA or broad-/multicast */
+ unsigned rx_sfrmty :3 ; /* frame type bits */
+ unsigned rx_erfbb :2 ; /* received frame byte boundary */
+ unsigned rx_reserv2:2 ; /* reserved */
+ unsigned rx_length :16 ; /* frame length lower/upper byte */
+#endif
+ } r ;
+ long i ;
+} ;
+
+/* defines for Receive Frame Descriptor access */
+#define RD_S_ERFBB 0x00030000L /* received frame byte boundary */
+#define RD_S_RES2 0x000c0000L /* reserved */
+#define RD_S_SFRMTY 0x00700000L /* frame type bits */
+#define RD_S_SADRRG 0x00800000L /* DA == MA or broad-/multicast */
+#define RD_S_SFRMERR 0x01000000L /* received frame not valid */
+#define RD_S_SEAC 0x0e000000L /* frame status indicators */
+#define RD_S_SEAC0 0x02000000L /* frame-copied case-indicator */
+#define RD_S_SEAC1 0x04000000L /* address-match A-indicator */
+#define RD_S_SEAC2 0x08000000L /* frame-error E-indicator */
+#define RD_S_SSRCRTG 0x10000000L /* == 1 SA has MSB set */
+#define RD_S_RES1 0x20000000L /* reserved */
+#define RD_S_MSRABT 0x40000000L /* memory status receive abort */
+#define RD_S_MSVALID 0x80000000L /* memory status valid */
+
+#define RD_STATUS 0xffff0000L
+#define RD_LENGTH 0x0000ffffL
+
+/* defines for Receive Frames Status Word values */
+/*RD_S_SFRMTY*/
+#define RD_FRM_SMT (unsigned long)(0<<20) /* asynchr. frames */
+#define RD_FRM_LLCA (unsigned long)(1<<20)
+#define RD_FRM_IMPA (unsigned long)(2<<20)
+#define RD_FRM_MAC (unsigned long)(4<<20) /* synchr. frames */
+#define RD_FRM_LLCS (unsigned long)(5<<20)
+#define RD_FRM_IMPS (unsigned long)(6<<20)
+
+#define TX_DESCRIPTOR 0x40000000L
+#define TX_OFFSET_3 0x18000000L
+
+#define TXP1 2
+
+/*
+ * transmit frame descriptor
+ */
+union tx_descr {
+ struct {
+#ifdef LITTLE_ENDIAN
+ unsigned tx_length:16 ; /* frame length lower/upper byte */
+ unsigned tx_res :8 ; /* reserved (bit 16..23) */
+ unsigned tx_xmtabt:1 ; /* transmit abort */
+ unsigned tx_nfcs :1 ; /* no frame check sequence */
+ unsigned tx_xdone :1 ; /* give up token */
+ unsigned tx_rpxm :2 ; /* byte offset */
+ unsigned tx_pat1 :2 ; /* must be TXP1 */
+ unsigned tx_more :1 ; /* more frame in chain */
+#else
+ unsigned tx_more :1 ; /* more frame in chain */
+ unsigned tx_pat1 :2 ; /* must be TXP1 */
+ unsigned tx_rpxm :2 ; /* byte offset */
+ unsigned tx_xdone :1 ; /* give up token */
+ unsigned tx_nfcs :1 ; /* no frame check sequence */
+ unsigned tx_xmtabt:1 ; /* transmit abort */
+ unsigned tx_res :8 ; /* reserved (bit 16..23) */
+ unsigned tx_length:16 ; /* frame length lower/upper byte */
+#endif
+ } t ;
+ long i ;
+} ;
+
+/* defines for Transmit Descriptor access */
+#define TD_C_MORE 0x80000000L /* more frame in chain */
+#define TD_C_DESCR 0x60000000L /* must be TXP1 */
+#define TD_C_TXFBB 0x18000000L /* byte offset */
+#define TD_C_XDONE 0x04000000L /* give up token */
+#define TD_C_NFCS 0x02000000L /* no frame check sequence */
+#define TD_C_XMTABT 0x01000000L /* transmit abort */
+
+#define TD_C_LNCNU 0x0000ff00L
+#define TD_C_LNCNL 0x000000ffL
+#define TD_C_LNCN 0x0000ffffL /* frame length lower/upper byte */
+
+/*
+ * transmit pointer
+ */
+union tx_pointer {
+ struct t {
+#ifdef LITTLE_ENDIAN
+ unsigned tp_pointer:16 ; /* pointer to tx_descr (low/high) */
+ unsigned tp_res :8 ; /* reserved (bit 16..23) */
+ unsigned tp_pattern:8 ; /* fixed pattern (bit 24..31) */
+#else
+ unsigned tp_pattern:8 ; /* fixed pattern (bit 24..31) */
+ unsigned tp_res :8 ; /* reserved (bit 16..23) */
+ unsigned tp_pointer:16 ; /* pointer to tx_descr (low/high) */
+#endif
+ } t ;
+ long i ;
+} ;
+
+/* defines for Nontag Mode Pointer access */
+#define TD_P_CNTRL 0xff000000L
+#define TD_P_RPXU 0x0000ff00L
+#define TD_P_RPXL 0x000000ffL
+#define TD_P_RPX 0x0000ffffL
+
+
+#define TX_PATTERN 0xa0
+#define TX_POINTER_END 0xa0000000L
+#define TX_INT_PATTERN 0xa0000000L
+
+struct tx_queue {
+ struct tx_queue *tq_next ;
+ u_short tq_pack_offset ; /* offset buffer memory */
+ u_char tq_pad[2] ;
+} ;
+
+/*
+ defines for FORMAC Plus (Am79C830)
+*/
+
+/*
+ * FORMAC+ read/write (r/w) registers
+ */
+#define FM_CMDREG1 0x00 /* write command reg 1 instruction */
+#define FM_CMDREG2 0x01 /* write command reg 2 instruction */
+#define FM_ST1U 0x00 /* read upper 16-bit of status reg 1 */
+#define FM_ST1L 0x01 /* read lower 16-bit of status reg 1 */
+#define FM_ST2U 0x02 /* read upper 16-bit of status reg 2 */
+#define FM_ST2L 0x03 /* read lower 16-bit of status reg 2 */
+#define FM_IMSK1U 0x04 /* r/w upper 16-bit of IMSK 1 */
+#define FM_IMSK1L 0x05 /* r/w lower 16-bit of IMSK 1 */
+#define FM_IMSK2U 0x06 /* r/w upper 16-bit of IMSK 2 */
+#define FM_IMSK2L 0x07 /* r/w lower 16-bit of IMSK 2 */
+#define FM_SAID 0x08 /* r/w short addr.-individual */
+#define FM_LAIM 0x09 /* r/w long addr.-ind. (MSW of LAID) */
+#define FM_LAIC 0x0a /* r/w long addr.-ind. (middle)*/
+#define FM_LAIL 0x0b /* r/w long addr.-ind. (LSW) */
+#define FM_SAGP 0x0c /* r/w short address-group */
+#define FM_LAGM 0x0d /* r/w long addr.-gr. (MSW of LAGP) */
+#define FM_LAGC 0x0e /* r/w long addr.-gr. (middle) */
+#define FM_LAGL 0x0f /* r/w long addr.-gr. (LSW) */
+#define FM_MDREG1 0x10 /* r/w 16-bit mode reg 1 */
+#define FM_STMCHN 0x11 /* read state-machine reg */
+#define FM_MIR1 0x12 /* read upper 16-bit of MAC Info Reg */
+#define FM_MIR0 0x13 /* read lower 16-bit of MAC Info Reg */
+#define FM_TMAX 0x14 /* r/w 16-bit TMAX reg */
+#define FM_TVX 0x15 /* write 8-bit TVX reg with NP7-0
+ read TVX on NP7-0, timer on NP15-8*/
+#define FM_TRT 0x16 /* r/w upper 16-bit of TRT timer */
+#define FM_THT 0x17 /* r/w upper 16-bit of THT timer */
+#define FM_TNEG 0x18 /* read upper 16-bit of TNEG (TTRT) */
+#define FM_TMRS 0x19 /* read lower 5-bit of TNEG,TRT,THT */
+ /* F E D C B A 9 8 7 6 5 4 3 2 1 0
+ x |-TNEG4-0| |-TRT4-0-| |-THT4-0-| (x-late count) */
+#define FM_TREQ0 0x1a /* r/w 16-bit TREQ0 reg (LSW of TRT) */
+#define FM_TREQ1 0x1b /* r/w 16-bit TREQ1 reg (MSW of TRT) */
+#define FM_PRI0 0x1c /* r/w priority r. for asyn.-queue 0 */
+#define FM_PRI1 0x1d /* r/w priority r. for asyn.-queue 1 */
+#define FM_PRI2 0x1e /* r/w priority r. for asyn.-queue 2 */
+#define FM_TSYNC 0x1f /* r/w 16-bit of the TSYNC register */
+#define FM_MDREG2 0x20 /* r/w 16-bit mode reg 2 */
+#define FM_FRMTHR 0x21 /* r/w the frame threshold register */
+#define FM_EACB 0x22 /* r/w end addr of claim/beacon area */
+#define FM_EARV 0x23 /* r/w end addr of receive queue */
+/* Supernet 3 */
+#define FM_EARV1 FM_EARV
+
+#define FM_EAS 0x24 /* r/w end addr of synchr. queue */
+#define FM_EAA0 0x25 /* r/w end addr of asyn. queue 0 */
+#define FM_EAA1 0x26 /* r/w end addr of asyn. queue 1 */
+#define FM_EAA2 0x27 /* r/w end addr of asyn. queue 2 */
+#define FM_SACL 0x28 /* r/w start addr of claim frame */
+#define FM_SABC 0x29 /* r/w start addr of beacon frame */
+#define FM_WPXSF 0x2a /* r/w the write ptr. for special fr.*/
+#define FM_RPXSF 0x2b /* r/w the read ptr. for special fr. */
+#define FM_RPR 0x2d /* r/w the read ptr. for receive qu. */
+#define FM_WPR 0x2e /* r/w the write ptr. for receive qu.*/
+#define FM_SWPR 0x2f /* r/w the shadow wr.-ptr. for rec.q.*/
+/* Supernet 3 */
+#define FM_RPR1 FM_RPR
+#define FM_WPR1 FM_WPR
+#define FM_SWPR1 FM_SWPR
+
+#define FM_WPXS 0x30 /* r/w the write ptr. for synchr. qu.*/
+#define FM_WPXA0 0x31 /* r/w the write ptr. for asyn. qu.0 */
+#define FM_WPXA1 0x32 /* r/w the write ptr. for asyn. qu.1 */
+#define FM_WPXA2 0x33 /* r/w the write ptr. for asyn. qu.2 */
+#define FM_SWPXS 0x34 /* r/w the shadow wr.-ptr. for syn.q.*/
+#define FM_SWPXA0 0x35 /* r/w the shad. wr.-ptr. for asyn.q0*/
+#define FM_SWPXA1 0x36 /* r/w the shad. wr.-ptr. for asyn.q1*/
+#define FM_SWPXA2 0x37 /* r/w the shad. wr.-ptr. for asyn.q2*/
+#define FM_RPXS 0x38 /* r/w the read ptr. for synchr. qu. */
+#define FM_RPXA0 0x39 /* r/w the read ptr. for asyn. qu. 0 */
+#define FM_RPXA1 0x3a /* r/w the read ptr. for asyn. qu. 1 */
+#define FM_RPXA2 0x3b /* r/w the read ptr. for asyn. qu. 2 */
+#define FM_MARR 0x3c /* r/w the memory read addr register */
+#define FM_MARW 0x3d /* r/w the memory write addr register*/
+#define FM_MDRU 0x3e /* r/w upper 16-bit of mem. data reg */
+#define FM_MDRL 0x3f /* r/w lower 16-bit of mem. data reg */
+
+/* following instructions relate to MAC counters and timer */
+#define FM_TMSYNC 0x40 /* r/w upper 16 bits of TMSYNC timer */
+#define FM_FCNTR 0x41 /* r/w the 16-bit frame counter */
+#define FM_LCNTR 0x42 /* r/w the 16-bit lost counter */
+#define FM_ECNTR 0x43 /* r/w the 16-bit error counter */
+
+/* Supernet 3: extensions to old register block */
+#define FM_FSCNTR 0x44 /* r/? Frame Strip Counter */
+#define FM_FRSELREG 0x45 /* r/w Frame Selection Register */
+
+/* Supernet 3: extensions for 2. receive queue etc. */
+#define FM_MDREG3 0x60 /* r/w Mode Register 3 */
+#define FM_ST3U 0x61 /* read upper 16-bit of status reg 3 */
+#define FM_ST3L 0x62 /* read lower 16-bit of status reg 3 */
+#define FM_IMSK3U 0x63 /* r/w upper 16-bit of IMSK reg 3 */
+#define FM_IMSK3L 0x64 /* r/w lower 16-bit of IMSK reg 3 */
+#define FM_IVR 0x65 /* read Interrupt Vector register */
+#define FM_IMR 0x66 /* r/w Interrupt mask register */
+/* 0x67 Hidden */
+#define FM_RPR2 0x68 /* r/w the read ptr. for rec. qu. 2 */
+#define FM_WPR2 0x69 /* r/w the write ptr. for rec. qu. 2 */
+#define FM_SWPR2 0x6a /* r/w the shadow wptr. for rec. q. 2 */
+#define FM_EARV2 0x6b /* r/w end addr of rec. qu. 2 */
+#define FM_UNLCKDLY 0x6c /* r/w Auto Unlock Delay register */
+ /* Bit 15-8: RECV2 unlock threshold */
+ /* Bit 7-0: RECV1 unlock threshold */
+/* 0x6f-0x73 Hidden */
+#define FM_LTDPA1 0x79 /* r/w Last Trans desc ptr for A1 qu. */
+/* 0x80-0x9a PLCS registers of built-in PLCS (Supernet 3 only) */
+
+/* Supernet 3: Adderss Filter Registers */
+#define FM_AFCMD 0xb0 /* r/w Address Filter Command Reg */
+#define FM_AFSTAT 0xb2 /* r/w Address Filter Status Reg */
+#define FM_AFBIST 0xb4 /* r/w Address Filter BIST signature */
+#define FM_AFCOMP2 0xb6 /* r/w Address Filter Comparand 2 */
+#define FM_AFCOMP1 0xb8 /* r/w Address Filter Comparand 1 */
+#define FM_AFCOMP0 0xba /* r/w Address Filter Comparand 0 */
+#define FM_AFMASK2 0xbc /* r/w Address Filter Mask 2 */
+#define FM_AFMASK1 0xbe /* r/w Address Filter Mask 1 */
+#define FM_AFMASK0 0xc0 /* r/w Address Filter Mask 0 */
+#define FM_AFPERS 0xc2 /* r/w Address Filter Personality Reg */
+
+/* Supernet 3: Orion (PDX?) Registers */
+#define FM_ORBIST 0xd0 /* r/w Orion BIST signature */
+#define FM_ORSTAT 0xd2 /* r/w Orion Status Register */
+
+
+/*
+ * Mode Register 1 (MDREG1)
+ */
+#define FM_RES0 0x0001 /* reserved */
+ /* SN3: other definition */
+#define FM_XMTINH_HOLD 0x0002 /* transmit-inhibit/hold bit */
+ /* SN3: other definition */
+#define FM_HOFLXI 0x0003 /* SN3: Hold / Flush / Inhibit */
+#define FM_FULL_HALF 0x0004 /* full-duplex/half-duplex bit */
+#define FM_LOCKTX 0x0008 /* lock-transmit-asynchr.-queues bit */
+#define FM_EXGPA0 0x0010 /* extended-group-addressing bit 0 */
+#define FM_EXGPA1 0x0020 /* extended-group-addressing bit 1 */
+#define FM_DISCRY 0x0040 /* disable-carry bit */
+ /* SN3: reserved */
+#define FM_SELRA 0x0080 /* select input from PHY (1=RA,0=RB) */
+
+#define FM_ADDET 0x0700 /* address detection */
+#define FM_MDAMA (0<<8) /* address detection : DA = MA */
+#define FM_MDASAMA (1<<8) /* address detection : DA=MA||SA=MA */
+#define FM_MRNNSAFNMA (2<<8) /* rec. non-NSA frames DA=MA&&SA!=MA */
+#define FM_MRNNSAF (3<<8) /* rec. non-NSA frames DA = MA */
+#define FM_MDISRCV (4<<8) /* disable receive function */
+#define FM_MRES0 (5<<8) /* reserve */
+#define FM_MLIMPROM (6<<8) /* limited-promiscuous mode */
+#define FM_MPROMISCOUS (7<<8) /* address detection : promiscous */
+
+#define FM_SELSA 0x0800 /* select-short-address bit */
+
+#define FM_MMODE 0x7000 /* mode select */
+#define FM_MINIT (0<<12) /* initialize */
+#define FM_MMEMACT (1<<12) /* memory activate */
+#define FM_MONLINESP (2<<12) /* on-line special */
+#define FM_MONLINE (3<<12) /* on-line (FDDI operational mode) */
+#define FM_MILOOP (4<<12) /* internal loopback */
+#define FM_MRES1 (5<<12) /* reserved */
+#define FM_MRES2 (6<<12) /* reserved */
+#define FM_MELOOP (7<<12) /* external loopback */
+
+#define FM_SNGLFRM 0x8000 /* single-frame-receive mode */
+ /* SN3: reserved */
+
+#define MDR1INIT (FM_MINIT | FM_MDAMA)
+
+/*
+ * Mode Register 2 (MDREG2)
+ */
+#define FM_AFULL 0x000f /* 4-bit value (empty loc.in txqueue)*/
+#define FM_RCVERR 0x0010 /* rec.-errored-frames bit */
+#define FM_SYMCTL 0x0020 /* sysmbol-control bit */
+ /* SN3: reserved */
+#define FM_SYNPRQ 0x0040 /* synchron.-NP-DMA-request bit */
+#define FM_ENNPRQ 0x0080 /* enable-NP-DMA-request bit */
+#define FM_ENHSRQ 0x0100 /* enable-host-request bit */
+#define FM_RXFBB01 0x0600 /* rec. frame byte boundary bit0 & 1 */
+#define FM_LSB 0x0800 /* determ. ordering of bytes in buffer*/
+#define FM_PARITY 0x1000 /* 1 = even, 0 = odd */
+#define FM_CHKPAR 0x2000 /* 1 = parity of 32-bit buffer BD-bus*/
+#define FM_STRPFCS 0x4000 /* 1 = strips FCS field of rec.frame */
+#define FM_BMMODE 0x8000 /* Buffer-Memory-Mode (1 = tag mode) */
+ /* SN3: 1 = tag, 0 = modified tag */
+
+/*
+ * Status Register 1, Upper 16 Bits (ST1U)
+ */
+#define FM_STEFRMS 0x0001 /* transmit end of frame: synchr. qu.*/
+#define FM_STEFRMA0 0x0002 /* transmit end of frame: asyn. qu.0 */
+#define FM_STEFRMA1 0x0004 /* transmit end of frame: asyn. qu.1 */
+#define FM_STEFRMA2 0x0008 /* transmit end of frame: asyn. qu.2 */
+ /* SN3: reserved */
+#define FM_STECFRMS 0x0010 /* transmit end of chain of syn. qu. */
+ /* SN3: reserved */
+#define FM_STECFRMA0 0x0020 /* transmit end of chain of asyn. q0 */
+ /* SN3: reserved */
+#define FM_STECFRMA1 0x0040 /* transmit end of chain of asyn. q1 */
+ /* SN3: STECMDA1 */
+#define FM_STECMDA1 0x0040 /* SN3: 'no description' */
+#define FM_STECFRMA2 0x0080 /* transmit end of chain of asyn. q2 */
+ /* SN3: reserved */
+#define FM_STEXDONS 0x0100 /* transmit until XDONE in syn. qu. */
+#define FM_STBFLA 0x0200 /* asynchr.-queue trans. buffer full */
+#define FM_STBFLS 0x0400 /* synchr.-queue transm. buffer full */
+#define FM_STXABRS 0x0800 /* synchr. queue transmit-abort */
+#define FM_STXABRA0 0x1000 /* asynchr. queue 0 transmit-abort */
+#define FM_STXABRA1 0x2000 /* asynchr. queue 1 transmit-abort */
+#define FM_STXABRA2 0x4000 /* asynchr. queue 2 transmit-abort */
+ /* SN3: reserved */
+#define FM_SXMTABT 0x8000 /* transmit abort */
+
+/*
+ * Status Register 1, Lower 16 Bits (ST1L)
+ */
+#define FM_SQLCKS 0x0001 /* queue lock for synchr. queue */
+#define FM_SQLCKA0 0x0002 /* queue lock for asynchr. queue 0 */
+#define FM_SQLCKA1 0x0004 /* queue lock for asynchr. queue 1 */
+#define FM_SQLCKA2 0x0008 /* queue lock for asynchr. queue 2 */
+ /* SN3: reserved */
+#define FM_STXINFLS 0x0010 /* transmit instruction full: syn. */
+ /* SN3: reserved */
+#define FM_STXINFLA0 0x0020 /* transmit instruction full: asyn.0 */
+ /* SN3: reserved */
+#define FM_STXINFLA1 0x0040 /* transmit instruction full: asyn.1 */
+ /* SN3: reserved */
+#define FM_STXINFLA2 0x0080 /* transmit instruction full: asyn.2 */
+ /* SN3: reserved */
+#define FM_SPCEPDS 0x0100 /* parity/coding error: syn. queue */
+#define FM_SPCEPDA0 0x0200 /* parity/coding error: asyn. queue0 */
+#define FM_SPCEPDA1 0x0400 /* parity/coding error: asyn. queue1 */
+#define FM_SPCEPDA2 0x0800 /* parity/coding error: asyn. queue2 */
+ /* SN3: reserved */
+#define FM_STBURS 0x1000 /* transmit buffer underrun: syn. q. */
+#define FM_STBURA0 0x2000 /* transmit buffer underrun: asyn.0 */
+#define FM_STBURA1 0x4000 /* transmit buffer underrun: asyn.1 */
+#define FM_STBURA2 0x8000 /* transmit buffer underrun: asyn.2 */
+ /* SN3: reserved */
+
+/*
+ * Status Register 2, Upper 16 Bits (ST2U)
+ */
+#define FM_SOTRBEC 0x0001 /* other beacon received */
+#define FM_SMYBEC 0x0002 /* my beacon received */
+#define FM_SBEC 0x0004 /* beacon state entered */
+#define FM_SLOCLM 0x0008 /* low claim received */
+#define FM_SHICLM 0x0010 /* high claim received */
+#define FM_SMYCLM 0x0020 /* my claim received */
+#define FM_SCLM 0x0040 /* claim state entered */
+#define FM_SERRSF 0x0080 /* error in special frame */
+#define FM_SNFSLD 0x0100 /* NP and FORMAC+ simultaneous load */
+#define FM_SRFRCTOV 0x0200 /* receive frame counter overflow */
+ /* SN3: reserved */
+#define FM_SRCVFRM 0x0400 /* receive frame */
+ /* SN3: reserved */
+#define FM_SRCVOVR 0x0800 /* receive FIFO overflow */
+#define FM_SRBFL 0x1000 /* receive buffer full */
+#define FM_SRABT 0x2000 /* receive abort */
+#define FM_SRBMT 0x4000 /* receive buffer empty */
+#define FM_SRCOMP 0x8000 /* receive complete. Nontag mode */
+
+/*
+ * Status Register 2, Lower 16 Bits (ST2L)
+ * Attention: SN3 docu shows these bits the other way around
+ */
+#define FM_SRES0 0x0001 /* reserved */
+#define FM_SESTRIPTK 0x0001 /* SN3: 'no description' */
+#define FM_STRTEXR 0x0002 /* TRT expired in claim | beacon st. */
+#define FM_SDUPCLM 0x0004 /* duplicate claim received */
+#define FM_SSIFG 0x0008 /* short interframe gap */
+#define FM_SFRMCTR 0x0010 /* frame counter overflow */
+#define FM_SERRCTR 0x0020 /* error counter overflow */
+#define FM_SLSTCTR 0x0040 /* lost counter overflow */
+#define FM_SPHINV 0x0080 /* PHY invalid */
+#define FM_SADET 0x0100 /* address detect */
+#define FM_SMISFRM 0x0200 /* missed frame */
+#define FM_STRTEXP 0x0400 /* TRT expired and late count > 0 */
+#define FM_STVXEXP 0x0800 /* TVX expired */
+#define FM_STKISS 0x1000 /* token issued */
+#define FM_STKERR 0x2000 /* token error */
+#define FM_SMULTDA 0x4000 /* multiple destination address */
+#define FM_SRNGOP 0x8000 /* ring operational */
+
+/*
+ * Supernet 3:
+ * Status Register 3, Upper 16 Bits (ST3U)
+ */
+#define FM_SRQUNLCK1 0x0001 /* receive queue unlocked queue 1 */
+#define FM_SRQUNLCK2 0x0002 /* receive queue unlocked queue 2 */
+#define FM_SRPERRQ1 0x0004 /* receive parity error rx queue 1 */
+#define FM_SRPERRQ2 0x0008 /* receive parity error rx queue 2 */
+ /* Bit 4-10: reserved */
+#define FM_SRCVOVR2 0x0800 /* receive FIFO overfull rx queue 2 */
+#define FM_SRBFL2 0x1000 /* receive buffer full rx queue 2 */
+#define FM_SRABT2 0x2000 /* receive abort rx queue 2 */
+#define FM_SRBMT2 0x4000 /* receive buf empty rx queue 2 */
+#define FM_SRCOMP2 0x8000 /* receive comp rx queue 2 */
+
+/*
+ * Supernet 3:
+ * Status Register 3, Lower 16 Bits (ST3L)
+ */
+#define FM_AF_BIST_DONE 0x0001 /* Address Filter BIST is done */
+#define FM_PLC_BIST_DONE 0x0002 /* internal PLC Bist is done */
+#define FM_PDX_BIST_DONE 0x0004 /* PDX BIST is done */
+ /* Bit 3: reserved */
+#define FM_SICAMDAMAT 0x0010 /* Status internal CAM DA match */
+#define FM_SICAMDAXACT 0x0020 /* Status internal CAM DA exact match */
+#define FM_SICAMSAMAT 0x0040 /* Status internal CAM SA match */
+#define FM_SICAMSAXACT 0x0080 /* Status internal CAM SA exact match */
+
+/*
+ * MAC State-Machine Register FM_STMCHN
+ */
+#define FM_MDRTAG 0x0004 /* tag bit of long word read */
+#define FM_SNPPND 0x0008 /* r/w from buffer mem. is pending */
+#define FM_TXSTAT 0x0070 /* transmitter state machine state */
+#define FM_RCSTAT 0x0380 /* receiver state machine state */
+#define FM_TM01 0x0c00 /* indicate token mode */
+#define FM_SIM 0x1000 /* indicate send immediate-mode */
+#define FM_REV 0xe000 /* FORMAC Plus revision number */
+
+/*
+ * Supernet 3
+ * Mode Register 3
+ */
+#define FM_MENRS 0x0001 /* Ena enhanced rec status encoding */
+#define FM_MENXS 0x0002 /* Ena enhanced xmit status encoding */
+#define FM_MENXCT 0x0004 /* Ena EXACT/INEXACT matching */
+#define FM_MENAFULL 0x0008 /* Ena enh QCTRL encoding for AFULL */
+#define FM_MEIND 0x0030 /* Ena enh A,C indicator settings */
+#define FM_MENQCTRL 0x0040 /* Ena enh QCTRL encoding */
+#define FM_MENRQAUNLCK 0x0080 /* Ena rec q auto unlock */
+#define FM_MENDAS 0x0100 /* Ena DAS connections by cntr MUX */
+#define FM_MENPLCCST 0x0200 /* Ena Counter Segm test in PLC blck */
+#define FM_MENSGLINT 0x0400 /* Ena Vectored Interrupt reading */
+#define FM_MENDRCV 0x0800 /* Ena dual receive queue operation */
+#define FM_MENFCLOC 0x3000 /* Ena FC location within frm data */
+#define FM_MENTRCMD 0x4000 /* Ena ASYNC1 xmit only after command */
+#define FM_MENTDLPBK 0x8000 /* Ena TDAT to RDAT lkoopback */
+
+/*
+ * Supernet 3
+ * Frame Selection Register
+ */
+#define FM_RECV1 0x000f /* options for receive queue 1 */
+#define FM_RCV1_ALL (0<<0) /* receive all frames */
+#define FM_RCV1_LLC (1<<0) /* rec all LLC frames */
+#define FM_RCV1_SMT (2<<0) /* rec all SMT frames */
+#define FM_RCV1_NSMT (3<<0) /* rec non-SMT frames */
+#define FM_RCV1_IMP (4<<0) /* rec Implementor frames */
+#define FM_RCV1_MAC (5<<0) /* rec all MAC frames */
+#define FM_RCV1_SLLC (6<<0) /* rec all sync LLC frames */
+#define FM_RCV1_ALLC (7<<0) /* rec all async LLC frames */
+#define FM_RCV1_VOID (8<<0) /* rec all void frames */
+#define FM_RCV1_ALSMT (9<<0) /* rec all async LLC & SMT frames */
+#define FM_RECV2 0x00f0 /* options for receive queue 2 */
+#define FM_RCV2_ALL (0<<4) /* receive all other frames */
+#define FM_RCV2_LLC (1<<4) /* rec all LLC frames */
+#define FM_RCV2_SMT (2<<4) /* rec all SMT frames */
+#define FM_RCV2_NSMT (3<<4) /* rec non-SMT frames */
+#define FM_RCV2_IMP (4<<4) /* rec Implementor frames */
+#define FM_RCV2_MAC (5<<4) /* rec all MAC frames */
+#define FM_RCV2_SLLC (6<<4) /* rec all sync LLC frames */
+#define FM_RCV2_ALLC (7<<4) /* rec all async LLC frames */
+#define FM_RCV2_VOID (8<<4) /* rec all void frames */
+#define FM_RCV2_ALSMT (9<<4) /* rec all async LLC & SMT frames */
+#define FM_ENXMTADSWAP 0x4000 /* enh rec addr swap (phys -> can) */
+#define FM_ENRCVADSWAP 0x8000 /* enh tx addr swap (can -> phys) */
+
+/*
+ * Supernet 3:
+ * Address Filter Command Register (AFCMD)
+ */
+#define FM_INST 0x0007 /* Address Filter Operation */
+#define FM_IINV_CAM (0<<0) /* Invalidate CAM */
+#define FM_IWRITE_CAM (1<<0) /* Write CAM */
+#define FM_IREAD_CAM (2<<0) /* Read CAM */
+#define FM_IRUN_BIST (3<<0) /* Run BIST */
+#define FM_IFIND (4<<0) /* Find */
+#define FM_IINV (5<<0) /* Invalidate */
+#define FM_ISKIP (6<<0) /* Skip */
+#define FM_ICL_SKIP (7<<0) /* Clear all SKIP bits */
+
+/*
+ * Supernet 3:
+ * Address Filter Status Register (AFSTAT)
+ */
+ /* Bit 0-4: reserved */
+#define FM_REV_NO 0x00e0 /* Revision Number of Address Filter */
+#define FM_BIST_DONE 0x0100 /* BIST complete */
+#define FM_EMPTY 0x0200 /* CAM empty */
+#define FM_ERROR 0x0400 /* Error (improper operation) */
+#define FM_MULT 0x0800 /* Multiple Match */
+#define FM_EXACT 0x1000 /* Exact Match */
+#define FM_FOUND 0x2000 /* Comparand found in CAM */
+#define FM_FULL 0x4000 /* CAM full */
+#define FM_DONE 0x8000 /* DONE indicator */
+
+/*
+ * Supernet 3:
+ * BIST Signature Register (AFBIST)
+ */
+#define AF_BIST_SIGNAT 0x0553 /* Address Filter BIST Signature */
+
+/*
+ * Supernet 3:
+ * Personality Register (AFPERS)
+ */
+#define FM_VALID 0x0001 /* CAM Entry Valid */
+#define FM_DA 0x0002 /* Destination Address */
+#define FM_DAX 0x0004 /* Destination Address Exact */
+#define FM_SA 0x0008 /* Source Address */
+#define FM_SAX 0x0010 /* Source Address Exact */
+#define FM_SKIP 0x0020 /* Skip this entry */
+
+/*
+ * instruction set for command register 1 (NPADDR6-0 = 0x00)
+ */
+#define FM_IRESET 0x01 /* software reset */
+#define FM_IRMEMWI 0x02 /* load Memory Data Reg., inc MARR */
+#define FM_IRMEMWO 0x03 /* load MDR from buffer memory, n.i. */
+#define FM_IIL 0x04 /* idle/listen */
+#define FM_ICL 0x05 /* claim/listen */
+#define FM_IBL 0x06 /* beacon/listen */
+#define FM_ILTVX 0x07 /* load TVX timer from TVX reg */
+#define FM_INRTM 0x08 /* nonrestricted token mode */
+#define FM_IENTM 0x09 /* enter nonrestricted token mode */
+#define FM_IERTM 0x0a /* enter restricted token mode */
+#define FM_IRTM 0x0b /* restricted token mode */
+#define FM_ISURT 0x0c /* send unrestricted token */
+#define FM_ISRT 0x0d /* send restricted token */
+#define FM_ISIM 0x0e /* enter send-immediate mode */
+#define FM_IESIM 0x0f /* exit send-immediate mode */
+#define FM_ICLLS 0x11 /* clear synchronous queue lock */
+#define FM_ICLLA0 0x12 /* clear asynchronous queue 0 lock */
+#define FM_ICLLA1 0x14 /* clear asynchronous queue 1 lock */
+#define FM_ICLLA2 0x18 /* clear asynchronous queue 2 lock */
+ /* SN3: reserved */
+#define FM_ICLLR 0x20 /* clear receive queue (SN3:1) lock */
+#define FM_ICLLR2 0x21 /* SN3: clear receive queue 2 lock */
+#define FM_ITRXBUS 0x22 /* SN3: Tristate X-Bus (SAS only) */
+#define FM_IDRXBUS 0x23 /* SN3: drive X-Bus */
+#define FM_ICLLAL 0x3f /* clear all queue locks */
+
+/*
+ * instruction set for command register 2 (NPADDR6-0 = 0x01)
+ */
+#define FM_ITRS 0x01 /* transmit synchronous queue */
+ /* SN3: reserved */
+#define FM_ITRA0 0x02 /* transmit asynchronous queue 0 */
+ /* SN3: reserved */
+#define FM_ITRA1 0x04 /* transmit asynchronous queue 1 */
+ /* SN3: reserved */
+#define FM_ITRA2 0x08 /* transmit asynchronous queue 2 */
+ /* SN3: reserved */
+#define FM_IACTR 0x10 /* abort current transmit activity */
+#define FM_IRSTQ 0x20 /* reset transmit queues */
+#define FM_ISTTB 0x30 /* set tag bit */
+#define FM_IERSF 0x40 /* enable receive single frame */
+ /* SN3: reserved */
+#define FM_ITR 0x50 /* SN3: Transmit Command */
+
+
+/*
+ * defines for PLC (Am79C864)
+ */
+
+/*
+ * PLC read/write (r/w) registers
+ */
+#define PL_CNTRL_A 0x00 /* control register A (r/w) */
+#define PL_CNTRL_B 0x01 /* control register B (r/w) */
+#define PL_INTR_MASK 0x02 /* interrupt mask (r/w) */
+#define PL_XMIT_VECTOR 0x03 /* transmit vector register (r/w) */
+#define PL_VECTOR_LEN 0x04 /* transmit vector length (r/w) */
+#define PL_LE_THRESHOLD 0x05 /* link error event threshold (r/w) */
+#define PL_C_MIN 0x06 /* minimum connect state time (r/w) */
+#define PL_TL_MIN 0x07 /* min. line state transmit t. (r/w) */
+#define PL_TB_MIN 0x08 /* minimum break time (r/w) */
+#define PL_T_OUT 0x09 /* signal timeout (r/w) */
+#define PL_CNTRL_C 0x0a /* control register C (r/w) */
+#define PL_LC_LENGTH 0x0b /* link confidence test time (r/w) */
+#define PL_T_SCRUB 0x0c /* scrub time = MAC TVX (r/w) */
+#define PL_NS_MAX 0x0d /* max. noise time before break (r/w)*/
+#define PL_TPC_LOAD_V 0x0e /* TPC timer load value (write only) */
+#define PL_TNE_LOAD_V 0x0f /* TNE timer load value (write only) */
+#define PL_STATUS_A 0x10 /* status register A (read only) */
+#define PL_STATUS_B 0x11 /* status register B (read only) */
+#define PL_TPC 0x12 /* timer for PCM (ro) [20.48 us] */
+#define PL_TNE 0x13 /* time of noise event [0.32 us] */
+#define PL_CLK_DIV 0x14 /* TNE clock divider (read only) */
+#define PL_BIST_SIGNAT 0x15 /* built in self test signature (ro)*/
+#define PL_RCV_VECTOR 0x16 /* receive vector reg. (read only) */
+#define PL_INTR_EVENT 0x17 /* interrupt event reg. (read only) */
+#define PL_VIOL_SYM_CTR 0x18 /* violation symbol count. (read o) */
+#define PL_MIN_IDLE_CTR 0x19 /* minimum idle counter (read only) */
+#define PL_LINK_ERR_CTR 0x1a /* link error event ctr.(read only) */
+#ifdef MOT_ELM
+#define PL_T_FOT_ASS 0x1e /* FOTOFF Assert Timer */
+#define PL_T_FOT_DEASS 0x1f /* FOTOFF Deassert Timer */
+#endif /* MOT_ELM */
+
+#ifdef MOT_ELM
+/*
+ * Special Quad-Elm Registers.
+ * A Quad-ELM consists of for ELMs and these additional registers.
+ */
+#define QELM_XBAR_W 0x80 /* Crossbar Control ELM W */
+#define QELM_XBAR_X 0x81 /* Crossbar Control ELM X */
+#define QELM_XBAR_Y 0x82 /* Crossbar Control ELM Y */
+#define QELM_XBAR_Z 0x83 /* Crossbar Control ELM Z */
+#define QELM_XBAR_P 0x84 /* Crossbar Control Bus P */
+#define QELM_XBAR_S 0x85 /* Crossbar Control Bus S */
+#define QELM_XBAR_R 0x86 /* Crossbar Control Bus R */
+#define QELM_WR_XBAR 0x87 /* Write the Crossbar now (write) */
+#define QELM_CTR_W 0x88 /* Counter W */
+#define QELM_CTR_X 0x89 /* Counter X */
+#define QELM_CTR_Y 0x8a /* Counter Y */
+#define QELM_CTR_Z 0x8b /* Counter Z */
+#define QELM_INT_MASK 0x8c /* Interrupt mask register */
+#define QELM_INT_DATA 0x8d /* Interrupt data (event) register */
+#define QELM_ELMB 0x00 /* Elm base */
+#define QELM_ELM_SIZE 0x20 /* ELM size */
+#endif /* MOT_ELM */
+/*
+ * PLC control register A (PL_CNTRL_A: log. addr. 0x00)
+ * It is used for timer configuration, specification of PCM MAINT state option,
+ * counter interrupt frequency, PLC data path config. and Built In Self Test.
+ */
+#define PL_RUN_BIST 0x0001 /* begin running its Built In Self T.*/
+#define PL_RF_DISABLE 0x0002 /* disable the Repeat Filter state m.*/
+#define PL_SC_REM_LOOP 0x0004 /* remote loopback path */
+#define PL_SC_BYPASS 0x0008 /* by providing a physical bypass */
+#define PL_LM_LOC_LOOP 0x0010 /* loop path just after elastic buff.*/
+#define PL_EB_LOC_LOOP 0x0020 /* loop path just prior to PDT/PDR IF*/
+#define PL_FOT_OFF 0x0040 /* assertion of /FOTOFF pin of PLC */
+#define PL_LOOPBACK 0x0080 /* it cause the /LPBCK pin ass. low */
+#define PL_MINI_CTR_INT 0x0100 /* partially contr. when bit is ass. */
+#define PL_VSYM_CTR_INT 0x0200 /* controls when int bit is asserted */
+#define PL_ENA_PAR_CHK 0x0400 /* enable parity check */
+#define PL_REQ_SCRUB 0x0800 /* limited access to scrub capability*/
+#define PL_TPC_16BIT 0x1000 /* causes the TPC as a 16 bit timer */
+#define PL_TNE_16BIT 0x2000 /* causes the TNE as a 16 bit timer */
+#define PL_NOISE_TIMER 0x4000 /* allows the noise timing function */
+
+/*
+ * PLC control register B (PL_CNTRL_B: log. addr. 0x01)
+ * It contains signals and requeste to direct the process of PCM and it is also
+ * used to control the Line State Match interrupt.
+ */
+#define PL_PCM_CNTRL 0x0003 /* control PCM state machine */
+#define PL_PCM_NAF (0) /* state is not affected */
+#define PL_PCM_START (1) /* goes to the BREAK state */
+#define PL_PCM_TRACE (2) /* goes to the TRACE state */
+#define PL_PCM_STOP (3) /* goes to the OFF state */
+
+#define PL_MAINT 0x0004 /* if OFF state --> MAINT state */
+#define PL_LONG 0x0008 /* perf. a long Link Confid.Test(LCT)*/
+#define PL_PC_JOIN 0x0010 /* if NEXT state --> JOIN state */
+
+#define PL_PC_LOOP 0x0060 /* loopback used in the LCT */
+#define PL_NOLCT (0<<5) /* no LCT is performed */
+#define PL_TPDR (1<<5) /* PCM asserts transmit PDR */
+#define PL_TIDLE (2<<5) /* PCM asserts transmit idle */
+#define PL_RLBP (3<<5) /* trans. PDR & remote loopb. path */
+
+#define PL_CLASS_S 0x0080 /* signif. that single att. station */
+
+#define PL_MAINT_LS 0x0700 /* line state while in the MAINT st. */
+#define PL_M_QUI0 (0<<8) /* transmit QUIET line state */
+#define PL_M_IDLE (1<<8) /* transmit IDLE line state */
+#define PL_M_HALT (2<<8) /* transmit HALT line state */
+#define PL_M_MASTR (3<<8) /* transmit MASTER line state */
+#define PL_M_QUI1 (4<<8) /* transmit QUIET line state */
+#define PL_M_QUI2 (5<<8) /* transmit QUIET line state */
+#define PL_M_TPDR (6<<8) /* tr. PHY_DATA requ.-symbol is tr.ed*/
+#define PL_M_QUI3 (7<<8) /* transmit QUIET line state */
+
+#define PL_MATCH_LS 0x7800 /* line state to be comp. with curr.*/
+#define PL_I_ANY (0<<11) /* Int. on any change in *_LINE_ST */
+#define PL_I_IDLE (1<<11) /* Interrupt on IDLE line state */
+#define PL_I_HALT (2<<11) /* Interrupt on HALT line state */
+#define PL_I_MASTR (4<<11) /* Interrupt on MASTER line state */
+#define PL_I_QUIET (8<<11) /* Interrupt on QUIET line state */
+
+#define PL_CONFIG_CNTRL 0x8000 /* control over scrub, byp. & loopb.*/
+
+/*
+ * PLC control register C (PL_CNTRL_C: log. addr. 0x0a)
+ * It contains the scrambling control registers (PLC-S only)
+ */
+#define PL_C_CIPHER_ENABLE (1<<0) /* enable scrambler */
+#define PL_C_CIPHER_LPBCK (1<<1) /* loopback scrambler */
+#define PL_C_SDOFF_ENABLE (1<<6) /* enable SDOFF timer */
+#define PL_C_SDON_ENABLE (1<<7) /* enable SDON timer */
+#ifdef MOT_ELM
+#define PL_C_FOTOFF_CTRL (3<<2) /* FOTOFF timer control */
+#define PL_C_FOTOFF_TIM (0<<2) /* FOTOFF use timer for (de)-assert */
+#define PL_C_FOTOFF_INA (2<<2) /* FOTOFF forced inactive */
+#define PL_C_FOTOFF_ACT (3<<2) /* FOTOFF forced active */
+#define PL_C_FOTOFF_SRCE (1<<4) /* FOTOFF source is PCM state != OFF */
+#define PL_C_RXDATA_EN (1<<5) /* Rec scr data forced to 0 */
+#define PL_C_SDNRZEN (1<<8) /* Monitor rec descr. data for act */
+#else /* nMOT_ELM */
+#define PL_C_FOTOFF_CTRL (3<<8) /* FOTOFF timer control */
+#define PL_C_FOTOFF_0 (0<<8) /* timer off */
+#define PL_C_FOTOFF_30 (1<<8) /* 30uS */
+#define PL_C_FOTOFF_50 (2<<8) /* 50uS */
+#define PL_C_FOTOFF_NEVER (3<<8) /* never */
+#define PL_C_SDON_TIMER (3<<10) /* SDON timer control */
+#define PL_C_SDON_084 (0<<10) /* 0.84 uS */
+#define PL_C_SDON_132 (1<<10) /* 1.32 uS */
+#define PL_C_SDON_252 (2<<10) /* 2.52 uS */
+#define PL_C_SDON_512 (3<<10) /* 5.12 uS */
+#define PL_C_SOFF_TIMER (3<<12) /* SDOFF timer control */
+#define PL_C_SOFF_076 (0<<12) /* 0.76 uS */
+#define PL_C_SOFF_132 (1<<12) /* 1.32 uS */
+#define PL_C_SOFF_252 (2<<12) /* 2.52 uS */
+#define PL_C_SOFF_512 (3<<12) /* 5.12 uS */
+#define PL_C_TSEL (3<<14) /* scrambler path select */
+#endif /* nMOT_ELM */
+
+/*
+ * PLC status register A (PL_STATUS_A: log. addr. 0x10)
+ * It is used to report status information to the Node Processor about the
+ * Line State Machine (LSM).
+ */
+#ifdef MOT_ELM
+#define PLC_INT_MASK 0xc000 /* ELM integration bits in status A */
+#define PLC_INT_C 0x0000 /* ELM Revision Band C */
+#define PLC_INT_CAMEL 0x4000 /* ELM integrated into CAMEL */
+#define PLC_INT_QE 0x8000 /* ELM integrated into Quad ELM */
+#define PLC_REV_MASK 0x3800 /* revision bits in status A */
+#define PLC_REVISION_B 0x0000 /* rev bits for ELM Rev B */
+#define PLC_REVISION_QA 0x0800 /* rev bits for ELM core in QELM-A */
+#else /* nMOT_ELM */
+#define PLC_REV_MASK 0xf800 /* revision bits in status A */
+#define PLC_REVISION_A 0x0000 /* revision bits for PLC */
+#define PLC_REVISION_S 0xf800 /* revision bits for PLC-S */
+#define PLC_REV_SN3 0x7800 /* revision bits for PLC-S in IFCP */
+#endif /* nMOT_ELM */
+#define PL_SYM_PR_CTR 0x0007 /* contains the LSM symbol pair Ctr. */
+#define PL_UNKN_LINE_ST 0x0008 /* unknown line state bit from LSM */
+#define PL_LSM_STATE 0x0010 /* state bit of LSM */
+
+#define PL_LINE_ST 0x00e0 /* contains recogn. line state of LSM*/
+#define PL_L_NLS (0<<5) /* noise line state */
+#define PL_L_ALS (1<<5) /* activ line state */
+#define PL_L_UND (2<<5) /* undefined */
+#define PL_L_ILS4 (3<<5) /* idle l. s. (after 4 idle symbols) */
+#define PL_L_QLS (4<<5) /* quiet line state */
+#define PL_L_MLS (5<<5) /* master line state */
+#define PL_L_HLS (6<<5) /* halt line state */
+#define PL_L_ILS16 (7<<5) /* idle line state (after 16 idle s.)*/
+
+#define PL_PREV_LINE_ST 0x0300 /* value of previous line state */
+#define PL_P_QLS (0<<8) /* quiet line state */
+#define PL_P_MLS (1<<8) /* master line state */
+#define PL_P_HLS (2<<8) /* halt line state */
+#define PL_P_ILS16 (3<<8) /* idle line state (after 16 idle s.)*/
+
+#define PL_SIGNAL_DET 0x0400 /* 1=that signal detect is deasserted*/
+
+
+/*
+ * PLC status register B (PL_STATUS_B: log. addr. 0x11)
+ * It contains signals and status from the repeat filter and PCM state machine.
+ */
+#define PL_BREAK_REASON 0x0007 /* reason for PCM state mach.s to br.*/
+#define PL_B_NOT (0) /* PCM SM has not gone to BREAK state*/
+#define PL_B_PCS (1) /* PC_Start issued */
+#define PL_B_TPC (2) /* TPC timer expired after T_OUT */
+#define PL_B_TNE (3) /* TNE timer expired after NS_MAX */
+#define PL_B_QLS (4) /* quit line state detected */
+#define PL_B_ILS (5) /* idle line state detected */
+#define PL_B_HLS (6) /* halt line state detected */
+
+#define PL_TCF 0x0008 /* transmit code flag (start exec.) */
+#define PL_RCF 0x0010 /* receive code flag (start exec.) */
+#define PL_LSF 0x0020 /* line state flag (l.s. has been r.)*/
+#define PL_PCM_SIGNAL 0x0040 /* indic. that XMIT_VECTOR hb.written*/
+
+#define PL_PCM_STATE 0x0780 /* state bits of PCM state machine */
+#define PL_PC0 (0<<7) /* OFF - when /RST or PCM_CNTRL */
+#define PL_PC1 (1<<7) /* BREAK - entry point in start PCM*/
+#define PL_PC2 (2<<7) /* TRACE - to localize stuck Beacon*/
+#define PL_PC3 (3<<7) /* CONNECT - synchronize ends of conn*/
+#define PL_PC4 (4<<7) /* NEXT - to seperate the signalng*/
+#define PL_PC5 (5<<7) /* SIGNAL - PCM trans/rec. bit infos*/
+#define PL_PC6 (6<<7) /* JOIN - 1. state to activ conn. */
+#define PL_PC7 (7<<7) /* VERIFY - 2. - " - (3. ACTIVE) */
+#define PL_PC8 (8<<7) /* ACTIVE - PHY has been incorporated*/
+#define PL_PC9 (9<<7) /* MAINT - for test purposes or so
+ that PCM op. completely in softw. */
+
+#define PL_PCI_SCRUB 0x0800 /* scrubbing function is being exec. */
+
+#define PL_PCI_STATE 0x3000 /* Physical Connect. Insertion SM */
+#define PL_CI_REMV (0<<12) /* REMOVED */
+#define PL_CI_ISCR (1<<12) /* INSERT_SCRUB */
+#define PL_CI_RSCR (2<<12) /* REMOVE_SCRUB */
+#define PL_CI_INS (3<<12) /* INSERTED */
+
+#define PL_RF_STATE 0xc000 /* state bit of repeate filter SM */
+#define PL_RF_REPT (0<<14) /* REPEAT */
+#define PL_RF_IDLE (1<<14) /* IDLE */
+#define PL_RF_HALT1 (2<<14) /* HALT1 */
+#define PL_RF_HALT2 (3<<14) /* HALT2 */
+
+
+/*
+ * PLC interrupt event register (PL_INTR_EVENT: log. addr. 0x17)
+ * It is read only and is clearde whenever it is read!
+ * It is used by the PLC to report events to the node processor.
+ */
+#define PL_PARITY_ERR 0x0001 /* p. error h.b.detected on TX9-0 inp*/
+#define PL_LS_MATCH 0x0002 /* l.s.== l.s. PLC_CNTRL_B's MATCH_LS*/
+#define PL_PCM_CODE 0x0004 /* transmit&receive | LCT complete */
+#define PL_TRACE_PROP 0x0008 /* master l.s. while PCM ACTIV|TRACE */
+#define PL_SELF_TEST 0x0010 /* QUIET|HALT while PCM in TRACE st. */
+#define PL_PCM_BREAK 0x0020 /* PCM has entered the BREAK state */
+#define PL_PCM_ENABLED 0x0040 /* asserted SC_JOIN, scrub. & ACTIV */
+#define PL_TPC_EXPIRED 0x0080 /* TPC timer reached zero */
+#define PL_TNE_EXPIRED 0x0100 /* TNE timer reached zero */
+#define PL_EBUF_ERR 0x0200 /* elastic buff. det. over-|underflow*/
+#define PL_PHYINV 0x0400 /* physical layer invalid signal */
+#define PL_VSYM_CTR 0x0800 /* violation symbol counter has incr.*/
+#define PL_MINI_CTR 0x1000 /* dep. on PLC_CNTRL_A's MINI_CTR_INT*/
+#define PL_LE_CTR 0x2000 /* link error event counter */
+#define PL_LSDO 0x4000 /* SDO input pin changed to a 1 */
+#define PL_NP_ERR 0x8000 /* NP has requested to r/w an inv. r.*/
+
+/*
+ * The PLC interrupt mask register (PL_INTR_MASK: log. addr. 0x02) constr. is
+ * equal PL_INTR_EVENT register.
+ * For each set bit, the setting of corresponding bit generate an int to NP.
+ */
+
+#ifdef MOT_ELM
+/*
+ * Quad ELM Crosbar Control register values (QELM_XBAR_?)
+ */
+#define QELM_XOUT_IDLE 0x0000 /* Idles/Passthrough */
+#define QELM_XOUT_P 0x0001 /* Output to: Bus P */
+#define QELM_XOUT_S 0x0002 /* Output to: Bus S */
+#define QELM_XOUT_R 0x0003 /* Output to: Bus R */
+#define QELM_XOUT_W 0x0004 /* Output to: ELM W */
+#define QELM_XOUT_X 0x0005 /* Output to: ELM X */
+#define QELM_XOUT_Y 0x0006 /* Output to: ELM Y */
+#define QELM_XOUT_Z 0x0007 /* Output to: ELM Z */
+
+/*
+ * Quad ELM Interrupt data and event registers.
+ */
+#define QELM_NP_ERR (1<<15) /* Node Processor Error */
+#define QELM_COUNT_Z (1<<7) /* Counter Z Interrupt */
+#define QELM_COUNT_Y (1<<6) /* Counter Y Interrupt */
+#define QELM_COUNT_X (1<<5) /* Counter X Interrupt */
+#define QELM_COUNT_W (1<<4) /* Counter W Interrupt */
+#define QELM_ELM_Z (1<<3) /* ELM Z Interrupt */
+#define QELM_ELM_Y (1<<2) /* ELM Y Interrupt */
+#define QELM_ELM_X (1<<1) /* ELM X Interrupt */
+#define QELM_ELM_W (1<<0) /* ELM W Interrupt */
+#endif /* MOT_ELM */
+/*
+ * PLC Timing Parameters
+ */
+#define TP_C_MIN 0xff9c /* 2 ms */
+#define TP_TL_MIN 0xfff0 /* 0.3 ms */
+#define TP_TB_MIN 0xff10 /* 5 ms */
+#define TP_T_OUT 0xd9db /* 200 ms */
+#define TP_LC_LENGTH 0xf676 /* 50 ms */
+#define TP_LC_LONGLN 0xa0a2 /* 500 ms */
+#define TP_T_SCRUB 0xff6d /* 3.5 ms */
+#define TP_NS_MAX 0xf021 /* 1.3 ms */
+
+/*
+ * BIST values
+ */
+#define PLC_BIST 0x6ecd /* BIST signature for PLC */
+#define PLCS_BIST 0x5b6b /* BIST signature for PLC-S */
+#define PLC_ELM_B_BIST 0x6ecd /* BIST signature of ELM Rev. B */
+#define PLC_ELM_D_BIST 0x5b6b /* BIST signature of ELM Rev. D */
+#define PLC_CAM_A_BIST 0x9e75 /* BIST signature of CAMEL Rev. A */
+#define PLC_CAM_B_BIST 0x5b6b /* BIST signature of CAMEL Rev. B */
+#define PLC_IFD_A_BIST 0x9e75 /* BIST signature of IFDDI Rev. A */
+#define PLC_IFD_B_BIST 0x5b6b /* BIST signature of IFDDI Rev. B */
+#define PLC_QELM_A_BIST 0x5b6b /* BIST signature of QELM Rev. A */
+
+/*
+ FDDI board recources
+ */
+
+/*
+ * request register array (log. addr: RQA_A + a<<1 {a=0..7}) write only.
+ * It specifies to FORMAC+ the type of buffer memory access the host requires.
+ */
+#define RQ_NOT 0 /* not request */
+#define RQ_RES 1 /* reserved */
+#define RQ_SFW 2 /* special frame write */
+#define RQ_RRQ 3 /* read request: receive queue */
+#define RQ_WSQ 4 /* write request: synchronous queue */
+#define RQ_WA0 5 /* write requ.: asynchronous queue 0 */
+#define RQ_WA1 6 /* write requ.: asynchronous queue 1 */
+#define RQ_WA2 7 /* write requ.: asynchronous queue 2 */
+
+#define SZ_LONG (sizeof(long))
+
+/*
+ * FDDI defaults
+ * NOTE : In the ANSI docs, times are specified in units of "symbol time".
+ * AMD chips use BCLK as unit. 1 BCKL == 2 symbols
+ */
+#define COMPLREF ((u_long)32*256*256) /* two's complement 21 bit */
+#define MSTOBCLK(x) ((u_long)(x)*12500L)
+#define MSTOTVX(x) (((u_long)(x)*1000L)/80/255)
+
+#endif /* _SUPERNET_ */
diff --git a/drivers/net/skfp/h/targethw.h b/drivers/net/skfp/h/targethw.h
new file mode 100644
index 000000000..5e6f3a050
--- /dev/null
+++ b/drivers/net/skfp/h/targethw.h
@@ -0,0 +1,173 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef _TARGETHW_
+#define _TARGETHW_
+
+ /*
+ * PCI Watermark definition
+ */
+#ifdef PCI
+#define RX_WATERMARK 24
+#define TX_WATERMARK 24
+#define SK_ML_ID_1 0x20
+#define SK_ML_ID_2 0x30
+#endif
+
+#include "h/skfbi.h"
+#ifndef TAG_MODE
+#include "h/fplus.h"
+#else
+#include "h/fplustm.h"
+#endif
+
+#ifndef HW_PTR
+#ifdef MEM_MAPPED_IO
+#define HW_PTR u_long
+#else
+#define HW_PTR u_short
+#endif
+#endif
+
+#ifdef MULT_OEM
+#define OI_STAT_LAST 0 /* end of OEM data base */
+#define OI_STAT_PRESENT 1 /* entry present but not empty */
+#define OI_STAT_VALID 2 /* holds valid ID, but is not active */
+#define OI_STAT_ACTIVE 3 /* holds valid ID, entry is active */
+ /* active = adapter is supported */
+
+/* Memory representation of IDs must match representation in adapter. */
+struct s_oem_ids {
+ u_char oi_status ; /* Stat: last, present, valid, active */
+ u_char oi_mark[5] ; /* "PID00" .. "PID07" .. */
+ u_char oi_id[4] ; /* id bytes, representation as */
+ /* defined by hardware, */
+#ifdef PCI
+ u_char oi_sub_id[4] ; /* sub id bytes, representation as */
+ /* defined by hardware, */
+#endif
+#ifdef ISA
+ u_char oi_logo_len ; /* the length of the adapter logo */
+ u_char oi_logo[6] ; /* the adapter logo */
+ u_char oi_reserved1 ;
+#endif /* ISA */
+} ;
+#endif /* MULT_OEM */
+
+
+struct s_smt_hw {
+ /*
+ * global
+ */
+ HW_PTR iop ; /* IO base address */
+ short dma ; /* DMA channel */
+ short irq ; /* IRQ level */
+ short eprom ; /* FLASH prom */
+#ifndef PCI
+ short DmaWriteExtraBytes ; /* add bytes for DMA write */
+#endif
+
+#ifndef SYNC
+ u_short n_a_send ; /* pending send requests */
+#endif
+
+#if (defined(EISA) || defined(MCA) || defined(PCI))
+ short slot ; /* slot number */
+ short max_slots ; /* maximum number of slots */
+#endif
+
+#if (defined(PCI) || defined(MCA))
+ short wdog_used ; /* TRUE if the watch dog is used */
+#endif
+
+#ifdef MCA
+ short slot_32 ; /* 32bit slot (1) or 16bit slot (0) */
+ short rev ; /* Board revision (FMx_REV). */
+ short VFullRead ; /* V_full value for DMA read */
+ short VFullWrite ; /* V_full value for DMA write */
+#endif
+
+#ifdef EISA
+ short led ; /* LED for FE card */
+
+ short dma_rmode ; /* read mode */
+ short dma_wmode ; /* write mode */
+ short dma_emode ; /* extend mode */
+
+ /* DMA controller channel dependent io addresses */
+ u_short dma_base_word_count ;
+ u_short dma_base_address ;
+ u_short dma_base_address_page ;
+#endif
+
+#ifdef PCI
+ u_short pci_handle ; /* handle to access the BIOS func */
+ u_long is_imask ; /* int maske for the int source reg */
+ u_long phys_mem_addr ; /* physical memory address */
+ u_short mc_dummy ; /* work around for MC compiler bug */
+ /*
+ * state of the hardware
+ */
+ u_short hw_state ; /* started or stopped */
+
+#define STARTED 1
+#define STOPPED 0
+
+ int hw_is_64bit ; /* does we have a 64 bit adapter */
+#endif
+
+#ifdef TAG_MODE
+ u_long pci_fix_value ; /* value parsed by PCIFIX */
+#endif
+
+ /*
+ * hwt.c
+ */
+ u_long t_start ; /* HWT start */
+ u_long t_stop ; /* HWT stop */
+ u_short timer_activ ; /* HWT timer active */
+
+ /*
+ * PIC
+ */
+ u_char pic_a1 ;
+ u_char pic_21 ;
+
+ /*
+ * GENERIC ; do not modify beyond this line
+ */
+
+ /*
+ * physical and canonical address
+ */
+ struct fddi_addr fddi_home_addr ;
+ struct fddi_addr fddi_canon_addr ;
+ struct fddi_addr fddi_phys_addr ;
+
+ /*
+ * mac variables
+ */
+ struct mac_parameter mac_pa ; /* tmin, tmax, tvx, treq .. */
+ struct mac_counter mac_ct ; /* recv., lost, error */
+ u_short mac_ring_is_up ; /* ring is up flag */
+
+ struct s_smt_fp fp ; /* formac+ */
+
+#ifdef MULT_OEM
+ struct s_oem_ids *oem_id ; /* pointer to selected id */
+ int oem_min_status ; /* IDs to take care of */
+#endif /* MULT_OEM */
+
+} ;
+#endif
diff --git a/drivers/net/skfp/h/targetos.h b/drivers/net/skfp/h/targetos.h
new file mode 100644
index 000000000..dd88fb35e
--- /dev/null
+++ b/drivers/net/skfp/h/targetos.h
@@ -0,0 +1,163 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * Operating system specific definitions for driver and
+ * hardware module.
+ */
+
+#ifndef TARGETOS_H
+#define TARGETOS_H
+
+
+//-------- those should go into include/linux/pci.h
+#define PCI_VENDOR_ID_SK 0x1148
+#define PCI_DEVICE_ID_SK_FP 0x4000
+//--------
+
+
+
+//-------- those should go into include/linux/if_fddi.h
+#define FDDI_MAC_HDR_LEN 13
+
+#define FDDI_RII 0x01 /* routing information bit */
+#define FDDI_RCF_DIR_BIT 0x80
+#define FDDI_RCF_LEN_MASK 0x1f
+#define FDDI_RCF_BROADCAST 0x8000
+#define FDDI_RCF_LIMITED_BROADCAST 0xA000
+#define FDDI_RCF_FRAME2K 0x20
+#define FDDI_RCF_FRAME4K 0x30
+//--------
+
+
+#undef ADDR
+
+#include <linux/version.h>
+#include <asm/io.h>
+#include <linux/netdevice.h>
+#include <linux/fddidevice.h>
+#include <linux/skbuff.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+// is redefined by linux, but we need our definition
+#undef ADDR
+#ifdef MEM_MAPPED_IO
+#define ADDR(a) (char far *) smc->hw.iop+(a)
+#else
+#define ADDR(a) (((a)>>7) ? (outp(smc->hw.iop+B0_RAP,(a)>>7), (smc->hw.iop+( ((a)&0x7F) | ((a)>>7 ? 0x80:0)) )) : (smc->hw.iop+(((a)&0x7F)|((a)>>7 ? 0x80:0))))
+#endif
+
+#include "h/hwmtm.h"
+
+#define TRUE 1
+#define FALSE 0
+
+// HWM Definitions
+// -----------------------
+#define FDDI_TRACE(string, arg1, arg2, arg3) // Performance analysis.
+#ifdef PCI
+#define NDD_TRACE(string, arg1, arg2, arg3) // Performance analysis.
+#endif // PCI
+#define SMT_PAGESIZE PAGE_SIZE // Size of a memory page (power of 2).
+// -----------------------
+
+
+// SMT Definitions
+// -----------------------
+#define TICKS_PER_SECOND HZ
+#define SMC_VERSION 1
+// -----------------------
+
+
+// OS-Driver Definitions
+// -----------------------
+#define NO_ADDRESS 0xffe0 /* No Device (I/O) Address */
+#define SKFP_MAX_NUM_BOARDS 8 /* maximum number of PCI boards */
+
+#define SK_BUS_TYPE_PCI 0
+#define SK_BUS_TYPE_EISA 1
+
+#define FP_IO_LEN 256 /* length of IO area used */
+
+#define u8 unsigned char
+#define u16 unsigned short
+#define u32 unsigned long
+
+#define MAX_TX_QUEUE_LEN 20 // number of packets queued by driver
+#define MAX_FRAME_SIZE 4550
+
+#define RX_LOW_WATERMARK NUM_RECEIVE_BUFFERS / 2
+#define TX_LOW_WATERMARK NUM_TRANSMIT_BUFFERS - 2
+
+/*
+** Include the IOCTL stuff
+*/
+#include <linux/sockios.h>
+
+#define SKFPIOCTL SIOCDEVPRIVATE
+
+struct s_skfp_ioctl {
+ unsigned short cmd; /* Command to run */
+ unsigned short len; /* Length of the data buffer */
+ unsigned char *data; /* Pointer to the data buffer */
+};
+
+/*
+** Recognised ioctl commands for the driver
+*/
+#define SKFP_GET_STATS 0x05 /* Get the driver statistics */
+#define SKFP_CLR_STATS 0x06 /* Zero out the driver statistics */
+
+// The per-adapter driver structure
+struct s_smt_os {
+ struct net_device *dev;
+ struct net_device *next_module;
+ u32 bus_type; /* bus type (0 == PCI, 1 == EISA) */
+ struct pci_dev pdev; /* PCI device structure */
+
+ u32 base_addr;
+ unsigned char factory_mac_addr[8];
+ ulong SharedMemSize;
+ ulong SharedMemHeap;
+ void* SharedMemAddr;
+
+ ulong QueueSkb;
+ struct sk_buff_head SendSkbQueue;
+
+ ulong MaxFrameSize;
+ u8 ResetRequested;
+
+ // MAC statistics structure
+ struct fddi_statistics MacStat;
+
+ // receive into this local buffer if no skb available
+ // data will be not valid, because multiple RxDs can
+ // point here at the same time
+ unsigned char LocalRxBuffer[MAX_FRAME_SIZE];
+
+ // Version (required by SMT module).
+ u_long smc_version ;
+
+ // Required by Hardware Module (HWM).
+ struct hw_modul hwm ;
+
+ // For SMP-savety
+ spinlock_t DriverLock;
+
+};
+
+typedef struct s_smt_os skfddi_priv;
+
+#endif // _TARGETOS_
diff --git a/drivers/net/skfp/h/types.h b/drivers/net/skfp/h/types.h
new file mode 100644
index 000000000..43b48ff3b
--- /dev/null
+++ b/drivers/net/skfp/h/types.h
@@ -0,0 +1,48 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#include <linux/types.h>
+/*
+ ----------------------
+ Basic SMT system types
+ ----------------------
+*/
+#ifndef _TYPES_
+#define _TYPES_
+
+#define _packed
+#ifndef far
+#define far
+#endif
+#ifndef _far
+#define _far
+#endif
+
+#ifndef MEM_MAPPED_IO // "normal" IO
+#define inp(p) inb(p)
+#define inpw(p) inw(p)
+#define inpd(p) inl(p)
+#define outp(p,c) outb(c,p)
+#define outpw(p,s) outw(s,p)
+#define outpd(p,l) outl(l,p)
+#else // memory mapped io
+#define inp(a) readb(a)
+#define inpw(a) readw(a)
+#define inpd(a) readl(a)
+#define outp(a,v) writeb(v, a)
+#define outpw(a,v) writew(v, a)
+#define outpd(a,v) writel(v, a)
+#endif
+
+#endif /* _TYPES_ */
diff --git a/drivers/net/skfp/hwmtm.c b/drivers/net/skfp/hwmtm.c
new file mode 100644
index 000000000..366b3b890
--- /dev/null
+++ b/drivers/net/skfp/hwmtm.c
@@ -0,0 +1,2261 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef lint
+static char const ID_sccs[] = "@(#)hwmtm.c 1.40 99/05/31 (C) SK" ;
+#endif
+
+#define HWMTM
+
+#ifndef FDDI
+#define FDDI
+#endif
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/supern_2.h"
+#include "h/skfbiinc.h"
+
+/*
+ -------------------------------------------------------------
+ DOCUMENTATION
+ -------------------------------------------------------------
+ BEGIN_MANUAL_ENTRY(DOCUMENTATION)
+
+ T B D
+
+ END_MANUAL_ENTRY
+*/
+/*
+ -------------------------------------------------------------
+ LOCAL VARIABLES:
+ -------------------------------------------------------------
+*/
+#ifdef COMMON_MB_POOL
+static SMbuf *mb_start = 0 ;
+static SMbuf *mb_free = 0 ;
+static int mb_init = FALSE ;
+static int call_count = 0 ;
+#endif
+
+/*
+ -------------------------------------------------------------
+ EXTERNE VARIABLES:
+ -------------------------------------------------------------
+*/
+
+#ifdef DEBUG
+#ifndef DEBUG_BRD
+extern struct smt_debug debug ;
+#endif
+#endif
+
+#ifdef NDIS_OS2
+extern u_char offDepth ;
+extern u_char force_irq_pending ;
+#endif
+
+/*
+ -------------------------------------------------------------
+ LOCAL FUNCTIONS:
+ -------------------------------------------------------------
+*/
+
+static void queue_llc_rx(), smt_to_llc(),
+ init_txd_ring(), init_rxd_ring(),
+ queue_txd_mb() ;
+
+static u_long init_descr_ring(), repair_txd_ring(),
+ repair_rxd_ring() ;
+
+static SMbuf *get_llc_rx(), *get_txd_mb() ;
+
+
+/*
+ -------------------------------------------------------------
+ EXTERNAL FUNCTIONS:
+ -------------------------------------------------------------
+*/
+/* The external SMT functions are listed in cmtdef.h */
+
+extern void *mac_drv_get_space(), *mac_drv_get_desc_mem(),
+ init_board(), mac_drv_fill_rxd(),
+ plc1_irq(), mac_drv_tx_complete(),
+ plc2_irq(), mac1_irq(),
+ mac2_irq(), mac3_irq(),
+ timer_irq(), mac_drv_rx_complete(),
+ mac_drv_requeue_rxd(), init_plc(),
+ mac_drv_clear_rxd(), llc_restart_tx(),
+ ev_dispatcher(), smt_force_irq() ;
+
+#ifdef USE_OS_CPY
+extern void hwm_cpy_rxd2mb(), hwm_cpy_txd2mb() ;
+#endif
+#ifdef ALL_RX_COMPLETE
+extern void mac_drv_all_receives_complete() ;
+#endif
+
+extern u_long mac_drv_virt2phys(), dma_master() ;
+
+#ifdef NDIS_OS2
+extern void post_proc() ;
+#else
+extern void dma_complete() ;
+#endif
+
+extern int init_fplus(), mac_drv_rx_init() ;
+
+/*
+ -------------------------------------------------------------
+ PUBLIC FUNCTIONS:
+ -------------------------------------------------------------
+*/
+ void process_receive(), smt_send_mbuf(),
+ fddi_isr(), mac_drv_clear_txd(),
+ smt_free_mbuf(), init_driver_fplus(),
+ mac_drv_rx_mode(), init_fddi_driver(),
+ mac_drv_clear_tx_queue(),
+ mac_drv_clear_rx_queue(),
+ hwm_tx_frag(), hwm_rx_frag() ;
+
+ int mac_drv_rx_frag(), mac_drv_init(),
+ hwm_tx_init() ;
+
+ u_int mac_drv_check_space() ;
+
+ SMbuf *smt_get_mbuf() ;
+
+#ifdef DEBUG
+ void mac_drv_debug_lev() ;
+#endif
+
+/*
+ -------------------------------------------------------------
+ MACROS:
+ -------------------------------------------------------------
+*/
+#ifndef UNUSED
+#ifdef lint
+#define UNUSED(x) (x) = (x)
+#else
+#define UNUSED(x)
+#endif
+#endif
+
+#ifdef USE_CAN_ADDR
+#define MA smc->hw.fddi_canon_addr.a
+#define GROUP_ADDR_BIT 0x01
+#else
+#define MA smc->hw.fddi_home_addr.a
+#define GROUP_ADDR_BIT 0x80
+#endif
+
+#define RXD_TXD_COUNT (HWM_ASYNC_TXD_COUNT+HWM_SYNC_TXD_COUNT+\
+ SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT)
+
+#ifdef MB_OUTSIDE_SMC
+#define EXT_VIRT_MEM ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd) +\
+ MAX_MBUF*sizeof(SMbuf))
+#define EXT_VIRT_MEM_2 ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd))
+#else
+#define EXT_VIRT_MEM ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd))
+#endif
+
+ /*
+ * define critical read for 16 Bit drivers
+ */
+#if defined(NDIS_OS2) || defined(ODI2)
+#define CR_READ(var) ((var) & 0xffff0000 | ((var) & 0xffff))
+#else
+#define CR_READ(var) (u_long)(var)
+#endif
+
+#define IMASK_SLOW (IS_PLINT1 | IS_PLINT2 | IS_TIMINT | IS_TOKEN | \
+ IS_MINTR1 | IS_MINTR2 | IS_MINTR3 | IS_R1_P | \
+ IS_R1_C | IS_XA_C | IS_XS_C)
+
+/*
+ -------------------------------------------------------------
+ INIT- AND SMT FUNCTIONS:
+ -------------------------------------------------------------
+*/
+
+
+/*
+ * BEGIN_MANUAL_ENTRY(mac_drv_check_space)
+ * u_int mac_drv_check_space()
+ *
+ * function DOWNCALL (drvsr.c)
+ * This function calculates the needed non virtual
+ * memory for MBufs, RxD and TxD descriptors etc.
+ * needed by the driver.
+ *
+ * return u_int memory in bytes
+ *
+ * END_MANUAL_ENTRY
+ */
+u_int mac_drv_check_space()
+{
+#ifdef MB_OUTSIDE_SMC
+#ifdef COMMON_MB_POOL
+ call_count++ ;
+ if (call_count == 1) {
+ return(EXT_VIRT_MEM) ;
+ }
+ else {
+ return(EXT_VIRT_MEM_2) ;
+ }
+#else
+ return (EXT_VIRT_MEM) ;
+#endif
+#else
+ return (0) ;
+#endif
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY(mac_drv_init)
+ * void mac_drv_init(smc)
+ *
+ * function DOWNCALL (drvsr.c)
+ * In this function the hardware module allocates it's
+ * memory.
+ * The operating system dependent module should call
+ * mac_drv_init once, after the adatper is detected.
+ * END_MANUAL_ENTRY
+ */
+int mac_drv_init(smc)
+struct s_smc *smc ;
+{
+ if (sizeof(struct s_smt_fp_rxd) % 16) {
+ SMT_PANIC(smc,HWM_E0001,HWM_E0001_MSG) ;
+ }
+ if (sizeof(struct s_smt_fp_txd) % 16) {
+ SMT_PANIC(smc,HWM_E0002,HWM_E0002_MSG) ;
+ }
+
+ /*
+ * get the required memory for the RxDs and TxDs
+ */
+ if (!(smc->os.hwm.descr_p = (union s_fp_descr volatile *)
+ mac_drv_get_desc_mem(smc,(u_int)
+ (RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd)))) {
+ return(1) ; /* no space the hwm modul can't work */
+ }
+
+ /*
+ * get the memory for the SMT MBufs
+ */
+#ifndef MB_OUTSIDE_SMC
+ smc->os.hwm.mbuf_pool.mb_start=(SMbuf *)(&smc->os.hwm.mbuf_pool.mb[0]) ;
+#else
+#ifndef COMMON_MB_POOL
+ if (!(smc->os.hwm.mbuf_pool.mb_start = (SMbuf *) mac_drv_get_space(smc,
+ MAX_MBUF*sizeof(SMbuf)))) {
+ return(1) ; /* no space the hwm modul can't work */
+ }
+#else
+ if (!mb_start) {
+ if (!(mb_start = (SMbuf *) mac_drv_get_space(smc,
+ MAX_MBUF*sizeof(SMbuf)))) {
+ return(1) ; /* no space the hwm modul can't work */
+ }
+ }
+#endif
+#endif
+ return (0) ;
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY(init_driver_fplus)
+ * init_driver_fplus(smc)
+ *
+ * Sets hardware modul specific values for the mode register 2
+ * (e.g. the byte alignment for the received frames, the position of the
+ * least significant byte etc.)
+ * END_MANUAL_ENTRY
+ */
+void init_driver_fplus(smc)
+struct s_smc *smc ;
+{
+ smc->hw.fp.mdr2init = FM_LSB | FM_BMMODE | FM_ENNPRQ | FM_ENHSRQ | 3 ;
+
+#ifdef PCI
+ smc->hw.fp.mdr2init |= FM_CHKPAR | FM_PARITY ;
+#endif
+ smc->hw.fp.mdr3init = FM_MENRQAUNLCK | FM_MENRS ;
+
+#ifdef USE_CAN_ADDR
+ /* enable address bit swapping */
+ smc->hw.fp.frselreg_init = FM_ENXMTADSWAP | FM_ENRCVADSWAP ;
+#endif
+}
+
+static u_long init_descr_ring(smc,start,count)
+struct s_smc *smc ;
+union s_fp_descr volatile *start;
+int count ;
+{
+ int i ;
+ union s_fp_descr volatile *d1 ;
+ union s_fp_descr volatile *d2 ;
+ u_long phys ;
+
+ DB_GEN("descr ring starts at = %x ",(void *)start,0,3) ;
+ for (i=count-1, d1=start; i ; i--) {
+ d2 = d1 ;
+ d1++ ; /* descr is owned by the host */
+ d2->r.rxd_rbctrl = AIX_REVERSE(BMU_CHECK) ;
+ d2->r.rxd_next = &d1->r ;
+ phys = mac_drv_virt2phys(smc,(void *)d1) ;
+ d2->r.rxd_nrdadr = AIX_REVERSE(phys) ;
+ }
+ DB_GEN("descr ring ends at = %x ",(void *)d1,0,3) ;
+ d1->r.rxd_rbctrl = AIX_REVERSE(BMU_CHECK) ;
+ d1->r.rxd_next = &start->r ;
+ phys = mac_drv_virt2phys(smc,(void *)start) ;
+ d1->r.rxd_nrdadr = AIX_REVERSE(phys) ;
+
+ for (i=count, d1=start; i ; i--) {
+ DRV_BUF_FLUSH(&d1->r,DDI_DMA_SYNC_FORDEV) ;
+ d1++;
+ }
+ return(phys) ;
+}
+
+static void init_txd_ring(smc)
+struct s_smc *smc ;
+{
+ struct s_smt_fp_txd volatile *ds ;
+ struct s_smt_tx_queue *queue ;
+ u_long phys ;
+
+ /*
+ * initialize the transmit descriptors
+ */
+ ds = (struct s_smt_fp_txd volatile *) ((char *)smc->os.hwm.descr_p +
+ SMT_R1_RXD_COUNT*sizeof(struct s_smt_fp_rxd)) ;
+ queue = smc->hw.fp.tx[QUEUE_A0] ;
+ DB_GEN("Init async TxD ring, %d TxDs ",HWM_ASYNC_TXD_COUNT,0,3) ;
+ (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
+ HWM_ASYNC_TXD_COUNT) ;
+ phys = AIX_REVERSE(ds->txd_ntdadr) ;
+ ds++ ;
+ queue->tx_curr_put = queue->tx_curr_get = ds ;
+ ds-- ;
+ queue->tx_free = HWM_ASYNC_TXD_COUNT ;
+ queue->tx_used = 0 ;
+ outpd(ADDR(B5_XA_DA),phys) ;
+
+ ds = (struct s_smt_fp_txd volatile *) ((char *)ds +
+ HWM_ASYNC_TXD_COUNT*sizeof(struct s_smt_fp_txd)) ;
+ queue = smc->hw.fp.tx[QUEUE_S] ;
+ DB_GEN("Init sync TxD ring, %d TxDs ",HWM_SYNC_TXD_COUNT,0,3) ;
+ (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
+ HWM_SYNC_TXD_COUNT) ;
+ phys = AIX_REVERSE(ds->txd_ntdadr) ;
+ ds++ ;
+ queue->tx_curr_put = queue->tx_curr_get = ds ;
+ queue->tx_free = HWM_SYNC_TXD_COUNT ;
+ queue->tx_used = 0 ;
+ outpd(ADDR(B5_XS_DA),phys) ;
+}
+
+static void init_rxd_ring(smc)
+struct s_smc *smc ;
+{
+ struct s_smt_fp_rxd volatile *ds ;
+ struct s_smt_rx_queue *queue ;
+ u_long phys ;
+
+ /*
+ * initialize the receive descriptors
+ */
+ ds = (struct s_smt_fp_rxd volatile *) smc->os.hwm.descr_p ;
+ queue = smc->hw.fp.rx[QUEUE_R1] ;
+ DB_GEN("Init RxD ring, %d RxDs ",SMT_R1_RXD_COUNT,0,3) ;
+ (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
+ SMT_R1_RXD_COUNT) ;
+ phys = AIX_REVERSE(ds->rxd_nrdadr) ;
+ ds++ ;
+ queue->rx_curr_put = queue->rx_curr_get = ds ;
+ queue->rx_free = SMT_R1_RXD_COUNT ;
+ queue->rx_used = 0 ;
+ outpd(ADDR(B4_R1_DA),phys) ;
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY(init_fddi_driver)
+ * void init_fddi_driver(smc,mac_addr)
+ *
+ * initializes the driver and it's variables
+ *
+ * END_MANUAL_ENTRY
+ */
+void init_fddi_driver(smc,mac_addr)
+struct s_smc *smc ;
+u_char *mac_addr ; /* canonical address */
+{
+ SMbuf *mb ;
+ int i ;
+
+ init_board(smc,mac_addr) ;
+ (void)init_fplus(smc) ;
+
+ /*
+ * initialize the SMbufs for the SMT
+ */
+#ifndef COMMON_MB_POOL
+ mb = smc->os.hwm.mbuf_pool.mb_start ;
+ smc->os.hwm.mbuf_pool.mb_free = (SMbuf *)NULL ;
+ for (i = 0; i < MAX_MBUF; i++) {
+ mb->sm_use_count = 1 ;
+ smt_free_mbuf(smc,mb) ;
+ mb++ ;
+ }
+#else
+ mb = mb_start ;
+ if (!mb_init) {
+ mb_free = 0 ;
+ for (i = 0; i < MAX_MBUF; i++) {
+ mb->sm_use_count = 1 ;
+ smt_free_mbuf(smc,mb) ;
+ mb++ ;
+ }
+ mb_init = TRUE ;
+ }
+#endif
+
+ /*
+ * initialize the other variables
+ */
+ smc->os.hwm.llc_rx_pipe = smc->os.hwm.llc_rx_tail = (SMbuf *)NULL ;
+ smc->os.hwm.txd_tx_pipe = smc->os.hwm.txd_tx_tail = NULL ;
+ smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = smc->os.hwm.pass_DB = 0 ;
+ smc->os.hwm.pass_llc_promisc = TRUE ;
+ smc->os.hwm.queued_rx_frames = smc->os.hwm.queued_txd_mb = 0 ;
+ smc->os.hwm.detec_count = 0 ;
+ smc->os.hwm.rx_break = 0 ;
+ smc->os.hwm.rx_len_error = 0 ;
+ smc->os.hwm.isr_flag = FALSE ;
+
+ /*
+ * make sure that the start pointer is 16 byte aligned
+ */
+ i = 16 - ((int)smc->os.hwm.descr_p & 0xf) ;
+ if (i != 16) {
+ DB_GEN("i = %d",i,0,3) ;
+ smc->os.hwm.descr_p = (union s_fp_descr volatile *)
+ ((char *)smc->os.hwm.descr_p+i) ;
+ }
+ DB_GEN("pt to descr area = %x",(void *)smc->os.hwm.descr_p,0,3) ;
+
+ init_txd_ring(smc) ;
+ init_rxd_ring(smc) ;
+ mac_drv_fill_rxd(smc) ;
+
+ init_plc(smc) ;
+}
+
+
+SMbuf *smt_get_mbuf(smc)
+struct s_smc *smc ;
+{
+ register SMbuf *mb ;
+
+#ifndef COMMON_MB_POOL
+ mb = smc->os.hwm.mbuf_pool.mb_free ;
+#else
+ mb = mb_free ;
+#endif
+ if (mb) {
+#ifndef COMMON_MB_POOL
+ smc->os.hwm.mbuf_pool.mb_free = mb->sm_next ;
+#else
+ mb_free = mb->sm_next ;
+#endif
+ mb->sm_off = 8 ;
+ mb->sm_use_count = 1 ;
+ }
+ DB_GEN("get SMbuf: mb = %x",(void *)mb,0,3) ;
+ return (mb) ; /* May be NULL */
+}
+
+void smt_free_mbuf(smc, mb)
+struct s_smc *smc ;
+SMbuf *mb;
+{
+
+ if (mb) {
+ mb->sm_use_count-- ;
+ DB_GEN("free_mbuf: sm_use_count = %d",mb->sm_use_count,0,3) ;
+ /*
+ * If the use_count is != zero the MBuf is queued
+ * more than once and must not queued into the
+ * free MBuf queue
+ */
+ if (!mb->sm_use_count) {
+ DB_GEN("free SMbuf: mb = %x",(void *)mb,0,3) ;
+#ifndef COMMON_MB_POOL
+ mb->sm_next = smc->os.hwm.mbuf_pool.mb_free ;
+ smc->os.hwm.mbuf_pool.mb_free = mb ;
+#else
+ mb->sm_next = mb_free ;
+ mb_free = mb ;
+#endif
+ }
+ }
+ else
+ SMT_PANIC(smc,HWM_E0003,HWM_E0003_MSG) ;
+}
+
+
+/*
+ * BEGIN_MANUAL_ENTRY(mac_drv_repair_descr)
+ * void mac_drv_repair_descr(smc)
+ *
+ * function called from SMT (HWM / hwmtm.c)
+ * The BMU is idle when this function is called.
+ * Mac_drv_repair_descr sets up the physical address
+ * for all receive and transmit queues where the BMU
+ * should continue.
+ * It may be that the BMU was reseted during a fragmented
+ * transfer. In this case there are some fragments which will
+ * never completed by the BMU. The OWN bit of this fragments
+ * must be switched to be owned by the host.
+ *
+ * Give a start command to the receive BMU.
+ * Start the transmit BMUs if transmit frames pending.
+ *
+ * END_MANUAL_ENTRY
+ */
+void mac_drv_repair_descr(smc)
+struct s_smc *smc ;
+{
+ u_long phys ;
+
+ if (smc->hw.hw_state != STOPPED) {
+ SK_BREAK() ;
+ SMT_PANIC(smc,HWM_E0013,HWM_E0013_MSG) ;
+ return ;
+ }
+
+ /*
+ * repair tx queues: don't start
+ */
+ phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_A0]) ;
+ outpd(ADDR(B5_XA_DA),phys) ;
+ if (smc->hw.fp.tx_q[QUEUE_A0].tx_used) {
+ outpd(ADDR(B0_XA_CSR),CSR_START) ;
+ }
+ phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_S]) ;
+ outpd(ADDR(B5_XS_DA),phys) ;
+ if (smc->hw.fp.tx_q[QUEUE_S].tx_used) {
+ outpd(ADDR(B0_XS_CSR),CSR_START) ;
+ }
+
+ /*
+ * repair rx queues
+ */
+ phys = repair_rxd_ring(smc,smc->hw.fp.rx[QUEUE_R1]) ;
+ outpd(ADDR(B4_R1_DA),phys) ;
+ outpd(ADDR(B0_R1_CSR),CSR_START) ;
+}
+
+static u_long repair_txd_ring(smc,queue)
+struct s_smc *smc ;
+struct s_smt_tx_queue *queue ;
+{
+ int i ;
+ int tx_used ;
+ u_long phys ;
+ u_long tbctrl ;
+ struct s_smt_fp_txd volatile *t ;
+
+ SK_UNUSED(smc) ;
+
+ t = queue->tx_curr_get ;
+ tx_used = queue->tx_used ;
+ for (i = tx_used+queue->tx_free-1 ; i ; i-- ) {
+ t = t->txd_next ;
+ }
+ phys = AIX_REVERSE(t->txd_ntdadr) ;
+
+ t = queue->tx_curr_get ;
+ while (tx_used) {
+ DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;
+ tbctrl = AIX_REVERSE(t->txd_tbctrl) ;
+
+ if (tbctrl & BMU_OWN) {
+ if (tbctrl & BMU_STF) {
+ break ; /* exit the loop */
+ }
+ else {
+ /*
+ * repair the descriptor
+ */
+ t->txd_tbctrl &= AIX_REVERSE(~BMU_OWN) ;
+ }
+ }
+ phys = AIX_REVERSE(t->txd_ntdadr) ;
+ DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
+ t = t->txd_next ;
+ tx_used-- ;
+ }
+ return(phys) ;
+}
+
+/*
+ * Repairs the receive descriptor ring and returns the physical address
+ * where the BMU should continue working.
+ *
+ * o The physical address where the BMU was stopped has to be
+ * determined. This is the next RxD after rx_curr_get with an OWN
+ * bit set.
+ * o The BMU should start working at beginning of the next frame.
+ * RxDs with an OWN bit set but with a reset STF bit should be
+ * skipped and owned by the driver (OWN = 0).
+ */
+static u_long repair_rxd_ring(smc,queue)
+struct s_smc *smc ;
+struct s_smt_rx_queue *queue ;
+{
+ int i ;
+ int rx_used ;
+ u_long phys ;
+ u_long rbctrl ;
+ struct s_smt_fp_rxd volatile *r ;
+
+ SK_UNUSED(smc) ;
+
+ r = queue->rx_curr_get ;
+ rx_used = queue->rx_used ;
+ for (i = SMT_R1_RXD_COUNT-1 ; i ; i-- ) {
+ r = r->rxd_next ;
+ }
+ phys = AIX_REVERSE(r->rxd_nrdadr) ;
+
+ r = queue->rx_curr_get ;
+ while (rx_used) {
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+ rbctrl = AIX_REVERSE(r->rxd_rbctrl) ;
+
+ if (rbctrl & BMU_OWN) {
+ if (rbctrl & BMU_STF) {
+ break ; /* exit the loop */
+ }
+ else {
+ /*
+ * repair the descriptor
+ */
+ r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ;
+ }
+ }
+ phys = AIX_REVERSE(r->rxd_nrdadr) ;
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
+ r = r->rxd_next ;
+ rx_used-- ;
+ }
+ return(phys) ;
+}
+
+
+/*
+ -------------------------------------------------------------
+ INTERRUPT SERVICE ROUTINE:
+ -------------------------------------------------------------
+*/
+
+/*
+ * BEGIN_MANUAL_ENTRY(fddi_isr)
+ * void fddi_isr(smc)
+ *
+ * function DOWNCALL (drvsr.c)
+ * interrupt service routine, handles the interrupt requests
+ * generated by the FDDI adapter.
+ *
+ * NOTE: The operating system dependent module must garantee that the
+ * interrupts of the adapter are disabled when it calls fddi_isr.
+ *
+ * About the USE_BREAK_ISR mechanismn:
+ *
+ * The main requirement of this mechanismn is to force an timer IRQ when
+ * leaving process_receive() with leave_isr set. process_receive() may
+ * be called at any time from anywhere!
+ * To be sure we don't miss such event we set 'force_irq' per default.
+ * We have to force and Timer IRQ if 'smc->os.hwm.leave_isr' AND
+ * 'force_irq' are set. 'force_irq' may be reset if a receive complete
+ * IRQ is pending.
+ *
+ * END_MANUAL_ENTRY
+ */
+void fddi_isr(smc)
+struct s_smc *smc ;
+{
+ u_long is ; /* ISR source */
+ u_short stu, stl ;
+ SMbuf *mb ;
+
+#ifdef USE_BREAK_ISR
+ int force_irq ;
+#endif
+
+#ifdef ODI2
+ if (smc->os.hwm.rx_break) {
+ mac_drv_fill_rxd(smc) ;
+ if (smc->hw.fp.rx_q[QUEUE_R1].rx_used > 0) {
+ smc->os.hwm.rx_break = 0 ;
+ process_receive(smc) ;
+ }
+ else {
+ smc->os.hwm.detec_count = 0 ;
+ smt_force_irq(smc) ;
+ }
+ }
+#endif
+ smc->os.hwm.isr_flag = TRUE ;
+
+#ifdef USE_BREAK_ISR
+ force_irq = TRUE ;
+ if (smc->os.hwm.leave_isr) {
+ smc->os.hwm.leave_isr = FALSE ;
+ process_receive(smc) ;
+ }
+#endif
+
+ while ((is = GET_ISR() & ISR_MASK)) {
+ NDD_TRACE("CH0B",is,0,0) ;
+ DB_GEN("ISA = 0x%x",is,0,7) ;
+
+ if (is & IMASK_SLOW) {
+ NDD_TRACE("CH1b",is,0,0) ;
+ if (is & IS_PLINT1) { /* PLC1 */
+ plc1_irq(smc) ;
+ }
+ if (is & IS_PLINT2) { /* PLC2 */
+ plc2_irq(smc) ;
+ }
+ if (is & IS_MINTR1) { /* FORMAC+ STU1(U/L) */
+ stu = inpw(FM_A(FM_ST1U)) ;
+ stl = inpw(FM_A(FM_ST1L)) ;
+ DB_GEN("Slow transmit complete",0,0,6) ;
+ mac1_irq(smc,stu,stl) ;
+ }
+ if (is & IS_MINTR2) { /* FORMAC+ STU2(U/L) */
+ stu= inpw(FM_A(FM_ST2U)) ;
+ stl= inpw(FM_A(FM_ST2L)) ;
+ DB_GEN("Slow receive complete",0,0,6) ;
+ DB_GEN("stl = %x : stu = %x",stl,stu,7) ;
+ mac2_irq(smc,stu,stl) ;
+ }
+ if (is & IS_MINTR3) { /* FORMAC+ STU3(U/L) */
+ stu= inpw(FM_A(FM_ST3U)) ;
+ stl= inpw(FM_A(FM_ST3L)) ;
+ DB_GEN("FORMAC Mode Register 3",0,0,6) ;
+ mac3_irq(smc,stu,stl) ;
+ }
+ if (is & IS_TIMINT) { /* Timer 82C54-2 */
+ timer_irq(smc) ;
+#ifdef NDIS_OS2
+ force_irq_pending = 0 ;
+#endif
+ /*
+ * out of RxD detection
+ */
+ if (++smc->os.hwm.detec_count > 4) {
+ /*
+ * check out of RxD condition
+ */
+ process_receive(smc) ;
+ }
+ }
+ if (is & IS_TOKEN) { /* Restricted Token Monitor */
+ rtm_irq(smc) ;
+ }
+ if (is & IS_R1_P) { /* Parity error rx queue 1 */
+ /* clear IRQ */
+ outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_P) ;
+ SMT_PANIC(smc,HWM_E0004,HWM_E0004_MSG) ;
+ }
+ if (is & IS_R1_C) { /* Encoding error rx queue 1 */
+ /* clear IRQ */
+ outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_C) ;
+ SMT_PANIC(smc,HWM_E0005,HWM_E0005_MSG) ;
+ }
+ if (is & IS_XA_C) { /* Encoding error async tx q */
+ /* clear IRQ */
+ outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_C) ;
+ SMT_PANIC(smc,HWM_E0006,HWM_E0006_MSG) ;
+ }
+ if (is & IS_XS_C) { /* Encoding error sync tx q */
+ /* clear IRQ */
+ outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_C) ;
+ SMT_PANIC(smc,HWM_E0007,HWM_E0007_MSG) ;
+ }
+ }
+
+ /*
+ * Fast Tx complete Async/Sync Queue (BMU service)
+ */
+ if (is & (IS_XS_F|IS_XA_F)) {
+ DB_GEN("Fast tx complete queue",0,0,6) ;
+ /*
+ * clear IRQ, Note: no IRQ is lost, because
+ * we always service both queues
+ */
+ outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_F) ;
+ outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_F) ;
+ mac_drv_clear_txd(smc) ;
+ llc_restart_tx(smc) ;
+ }
+
+ /*
+ * Fast Rx Complete (BMU service)
+ */
+ if (is & IS_R1_F) {
+ DB_GEN("Fast receive complete",0,0,6) ;
+ /* clear IRQ */
+#ifndef USE_BREAK_ISR
+ outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ;
+ process_receive(smc) ;
+#else
+ process_receive(smc) ;
+ if (smc->os.hwm.leave_isr) {
+ force_irq = FALSE ;
+ } else {
+ outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ;
+ process_receive(smc) ;
+ }
+#endif
+ }
+
+#ifndef NDIS_OS2
+ while ((mb = get_llc_rx(smc))) {
+ smt_to_llc(smc,mb) ;
+ }
+#else
+ if (offDepth)
+ post_proc() ;
+
+ while (!offDepth && (mb = get_llc_rx(smc))) {
+ smt_to_llc(smc,mb) ;
+ }
+
+ if (!offDepth && smc->os.hwm.rx_break) {
+ process_receive(smc) ;
+ }
+#endif
+ if (smc->q.ev_get != smc->q.ev_put) {
+ NDD_TRACE("CH2a",0,0,0) ;
+ ev_dispatcher(smc) ;
+ }
+#ifdef NDIS_OS2
+ post_proc() ;
+ if (offDepth) { /* leave fddi_isr because */
+ break ; /* indications not allowed */
+ }
+#endif
+#ifdef USE_BREAK_ISR
+ if (smc->os.hwm.leave_isr) {
+ break ; /* leave fddi_isr */
+ }
+#endif
+
+ /* NOTE: when the isr is left, no rx is pending */
+ } /* end of interrupt source polling loop */
+
+#ifdef USE_BREAK_ISR
+ if (smc->os.hwm.leave_isr && force_irq) {
+ smt_force_irq(smc) ;
+ }
+#endif
+ smc->os.hwm.isr_flag = FALSE ;
+ NDD_TRACE("CH0E",0,0,0) ;
+}
+
+
+/*
+ -------------------------------------------------------------
+ RECEIVE FUNCTIONS:
+ -------------------------------------------------------------
+*/
+
+#ifndef NDIS_OS2
+/*
+ * BEGIN_MANUAL_ENTRY(mac_drv_rx_mode)
+ * void mac_drv_rx_mode(smc,mode)
+ *
+ * function DOWNCALL (fplus.c)
+ * Corresponding to the parameter mode, the operating system
+ * dependent module can activate several receive modes.
+ *
+ * para mode = 1: RX_ENABLE_ALLMULTI enable all multicasts
+ * = 2: RX_DISABLE_ALLMULTI disable "enable all multicasts"
+ * = 3: RX_ENABLE_PROMISC enable promiscuous
+ * = 4: RX_DISABLE_PROMISC disable promiscuous
+ * = 5: RX_ENABLE_NSA enable rec. of all NSA frames
+ * (disabled after 'driver reset' & 'set station address')
+ * = 6: RX_DISABLE_NSA disable rec. of all NSA frames
+ *
+ * = 21: RX_ENABLE_PASS_SMT ( see description )
+ * = 22: RX_DISABLE_PASS_SMT ( " " )
+ * = 23: RX_ENABLE_PASS_NSA ( " " )
+ * = 24: RX_DISABLE_PASS_NSA ( " " )
+ * = 25: RX_ENABLE_PASS_DB ( " " )
+ * = 26: RX_DISABLE_PASS_DB ( " " )
+ * = 27: RX_DISABLE_PASS_ALL ( " " )
+ * = 28: RX_DISABLE_LLC_PROMISC ( " " )
+ * = 29: RX_ENABLE_LLC_PROMISC ( " " )
+ *
+ *
+ * RX_ENABLE_PASS_SMT / RX_DISABLE_PASS_SMT
+ *
+ * If the operating system dependent module activates the
+ * mode RX_ENABLE_PASS_SMT, the hardware module
+ * duplicates all SMT frames with the frame control
+ * FC_SMT_INFO and passes them to the LLC receive channel
+ * by calling mac_drv_rx_init.
+ * The SMT Frames which are sent by the local SMT and the NSA
+ * frames whose A- and C-Indicator is not set are also duplicated
+ * and passed.
+ * The receive mode RX_DISABLE_PASS_SMT disables the passing
+ * of SMT frames.
+ *
+ * RX_ENABLE_PASS_NSA / RX_DISABLE_PASS_NSA
+ *
+ * If the operating system dependent module activates the
+ * mode RX_ENABLE_PASS_NSA, the hardware module
+ * duplicates all NSA frames with frame control FC_SMT_NSA
+ * and a set A-Indicator and passed them to the LLC
+ * receive channel by calling mac_drv_rx_init.
+ * All NSA Frames which are sent by the local SMT
+ * are also duplicated and passed.
+ * The receive mode RX_DISABLE_PASS_NSA disables the passing
+ * of NSA frames with the A- or C-Indicator set.
+ *
+ * NOTE: For fear that the hardware module receives NSA frames with
+ * a reset A-Indicator, the operating system dependent module
+ * has to call mac_drv_rx_mode with the mode RX_ENABLE_NSA
+ * before activate the RX_ENABLE_PASS_NSA mode and after every
+ * 'driver reset' and 'set station address'.
+ *
+ * RX_ENABLE_PASS_DB / RX_DISABLE_PASS_DB
+ *
+ * If the operating system dependent module activates the
+ * mode RX_ENABLE_PASS_DB, direct BEACON frames
+ * (FC_BEACON frame control) are passed to the LLC receive
+ * channel by mac_drv_rx_init.
+ * The receive mode RX_DISABLE_PASS_DB disables the passing
+ * of direct BEACON frames.
+ *
+ * RX_DISABLE_PASS_ALL
+ *
+ * Disables all special receives modes. It is equal to
+ * call mac_drv_set_rx_mode successively with the
+ * parameters RX_DISABLE_NSA, RX_DISABLE_PASS_SMT,
+ * RX_DISABLE_PASS_NSA and RX_DISABLE_PASS_DB.
+ *
+ * RX_ENABLE_LLC_PROMISC
+ *
+ * (default) all received LLC frames and all SMT/NSA/DBEACON
+ * frames depending on the attitude of the flags
+ * PASS_SMT/PASS_NSA/PASS_DBEACON will be delivered to the
+ * LLC layer
+ *
+ * RX_DISABLE_LLC_PROMISC
+ *
+ * all received SMT/NSA/DBEACON frames depending on the
+ * attitude of the flags PASS_SMT/PASS_NSA/PASS_DBEACON
+ * will be delivered to the LLC layer.
+ * all received LLC frames with a directed address, Multicast
+ * or Broadcast address will be delivered to the LLC
+ * layer too.
+ *
+ * END_MANUAL_ENTRY
+ */
+void mac_drv_rx_mode(smc,mode)
+struct s_smc *smc ;
+int mode ;
+{
+ switch(mode) {
+ case RX_ENABLE_PASS_SMT:
+ smc->os.hwm.pass_SMT = TRUE ;
+ break ;
+ case RX_DISABLE_PASS_SMT:
+ smc->os.hwm.pass_SMT = FALSE ;
+ break ;
+ case RX_ENABLE_PASS_NSA:
+ smc->os.hwm.pass_NSA = TRUE ;
+ break ;
+ case RX_DISABLE_PASS_NSA:
+ smc->os.hwm.pass_NSA = FALSE ;
+ break ;
+ case RX_ENABLE_PASS_DB:
+ smc->os.hwm.pass_DB = TRUE ;
+ break ;
+ case RX_DISABLE_PASS_DB:
+ smc->os.hwm.pass_DB = FALSE ;
+ break ;
+ case RX_DISABLE_PASS_ALL:
+ smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = FALSE ;
+ smc->os.hwm.pass_DB = FALSE ;
+ smc->os.hwm.pass_llc_promisc = TRUE ;
+ mac_set_rx_mode(smc,RX_DISABLE_NSA) ;
+ break ;
+ case RX_DISABLE_LLC_PROMISC:
+ smc->os.hwm.pass_llc_promisc = FALSE ;
+ break ;
+ case RX_ENABLE_LLC_PROMISC:
+ smc->os.hwm.pass_llc_promisc = TRUE ;
+ break ;
+ case RX_ENABLE_ALLMULTI:
+ case RX_DISABLE_ALLMULTI:
+ case RX_ENABLE_PROMISC:
+ case RX_DISABLE_PROMISC:
+ case RX_ENABLE_NSA:
+ case RX_DISABLE_NSA:
+ default:
+ mac_set_rx_mode(smc,mode) ;
+ break ;
+ }
+}
+#endif /* ifndef NDIS_OS2 */
+
+/*
+ * process receive queue
+ */
+void process_receive(smc)
+struct s_smc *smc ;
+{
+ int i ;
+ int n ;
+ int frag_count ; /* number of RxDs of the curr rx buf */
+ int used_frags ; /* number of RxDs of the curr frame */
+ struct s_smt_rx_queue *queue ; /* points to the queue ctl struct */
+ struct s_smt_fp_rxd volatile *r ; /* rxd pointer */
+ struct s_smt_fp_rxd volatile *rxd ; /* first rxd of rx frame */
+ u_long rbctrl ; /* receive buffer control word */
+ u_long rfsw ; /* receive frame status word */
+ u_short rx_used ;
+ u_char far *virt ;
+ char far *data ;
+ SMbuf *mb ;
+ u_char fc ; /* Frame control */
+ int len ; /* Frame length */
+
+ smc->os.hwm.detec_count = 0 ;
+ queue = smc->hw.fp.rx[QUEUE_R1] ;
+ NDD_TRACE("RHxB",0,0,0) ;
+ for ( ; ; ) {
+ r = queue->rx_curr_get ;
+ rx_used = queue->rx_used ;
+ frag_count = 0 ;
+
+#ifdef USE_BREAK_ISR
+ if (smc->os.hwm.leave_isr) {
+ goto rx_end ;
+ }
+#endif
+#ifdef NDIS_OS2
+ if (offDepth) {
+ smc->os.hwm.rx_break = 1 ;
+ goto rx_end ;
+ }
+ smc->os.hwm.rx_break = 0 ;
+#endif
+#ifdef ODI2
+ if (smc->os.hwm.rx_break) {
+ goto rx_end ;
+ }
+#endif
+ n = 0 ;
+ do {
+ DB_RX("Check RxD %x for OWN and EOF",(void *)r,0,5) ;
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+ rbctrl = CR_READ(r->rxd_rbctrl) ;
+#ifdef AIX
+ rbctrl = AIX_REVERSE(rbctrl) ;
+#endif
+ if (rbctrl & BMU_OWN) {
+ NDD_TRACE("RHxE",r,rfsw,rbctrl) ;
+ DB_RX("End of RxDs",0,0,4) ;
+ goto rx_end ;
+ }
+ /*
+ * out of RxD detection
+ */
+ if (!rx_used) {
+ SK_BREAK() ;
+ SMT_PANIC(smc,HWM_E0009,HWM_E0009_MSG) ;
+ /* Either we don't have an RxD or all
+ * RxDs are filled. Therefore it's allowed
+ * for to set the STOPPED flag */
+ smc->hw.hw_state = STOPPED ;
+ mac_drv_clear_rx_queue(smc) ;
+ smc->hw.hw_state = STARTED ;
+ mac_drv_fill_rxd(smc) ;
+ smc->os.hwm.detec_count = 0 ;
+ goto rx_end ;
+ }
+ rfsw = AIX_REVERSE(r->rxd_rfsw) ;
+ if ((rbctrl & BMU_STF) != ((rbctrl & BMU_ST_BUF) <<5)) {
+ /*
+ * The BMU_STF bit is deleted, 1 frame is
+ * placed into more than 1 rx buffer
+ *
+ * skip frame by setting the rx len to 0
+ *
+ * if fragment count == 0
+ * The missing STF bit belongs to the
+ * current frame, search for the
+ * EOF bit to complete the frame
+ * else
+ * the fragment belongs to the next frame,
+ * exit the loop and process the frame
+ */
+ SK_BREAK() ;
+ rfsw = 0 ;
+ if (frag_count) {
+ break ;
+ }
+ }
+ n += rbctrl & 0xffff ;
+ r = r->rxd_next ;
+ frag_count++ ;
+ rx_used-- ;
+ } while (!(rbctrl & BMU_EOF)) ;
+ used_frags = frag_count ;
+ DB_RX("EOF set in RxD, used_frags = %d ",used_frags,0,5) ;
+
+ /* may be next 2 DRV_BUF_FLUSH() can be skipped, because */
+ /* BMU_ST_BUF will not be changed by the ASIC */
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+ while (rx_used && !(r->rxd_rbctrl & AIX_REVERSE(BMU_ST_BUF))) {
+ DB_RX("Check STF bit in %x",(void *)r,0,5) ;
+ r = r->rxd_next ;
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+ frag_count++ ;
+ rx_used-- ;
+ }
+ DB_RX("STF bit found",0,0,5) ;
+
+ /*
+ * The received frame is finished for the process receive
+ */
+ rxd = queue->rx_curr_get ;
+ queue->rx_curr_get = r ;
+ queue->rx_free += frag_count ;
+ queue->rx_used = rx_used ;
+
+ /*
+ * ASIC Errata no. 7 (STF - Bit Bug)
+ */
+ rxd->rxd_rbctrl &= AIX_REVERSE(~BMU_STF) ;
+
+ for (r=rxd, i=frag_count ; i ; r=r->rxd_next, i--){
+ DB_RX("dma_complete for RxD %x",(void *)r,0,5) ;
+ dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR);
+ }
+ smc->hw.fp.err_stats.err_valid++ ;
+ smc->mib.m[MAC0].fddiMACCopied_Ct++ ;
+
+ /* the length of the data including the FC */
+ len = (rfsw & RD_LENGTH) - 4 ;
+
+ DB_RX("frame length = %d",len,0,4) ;
+ /*
+ * check the frame_lenght and all error flags
+ */
+ if (rfsw & (RX_MSRABT|RX_FS_E|RX_FS_CRC|RX_FS_IMPL)){
+ if (rfsw & RD_S_MSRABT) {
+ DB_RX("Frame aborted by the FORMAC",0,0,2) ;
+ smc->hw.fp.err_stats.err_abort++ ;
+ }
+ /*
+ * check frame status
+ */
+ if (rfsw & RD_S_SEAC2) {
+ DB_RX("E-Indicator set",0,0,2) ;
+ smc->hw.fp.err_stats.err_e_indicator++ ;
+ }
+ if (rfsw & RD_S_SFRMERR) {
+ DB_RX("CRC error",0,0,2) ;
+ smc->hw.fp.err_stats.err_crc++ ;
+ }
+ if (rfsw & RX_FS_IMPL) {
+ DB_RX("Implementer frame",0,0,2) ;
+ smc->hw.fp.err_stats.err_imp_frame++ ;
+ }
+ goto abort_frame ;
+ }
+ if (len > FDDI_RAW_MTU-4) {
+ DB_RX("Frame to long error",0,0,2) ;
+ smc->hw.fp.err_stats.err_too_long++ ;
+ goto abort_frame ;
+ }
+ /*
+ * SUPERNET 3 Bug: FORMAC delivers status words
+ * of aborded frames to the BMU
+ */
+ if (len <= 4) {
+ DB_RX("Frame length = 0",0,0,2) ;
+ goto abort_frame ;
+ }
+
+ if (len != (n-4)) {
+ DB_RX("BMU: rx len differs: [%d:%d]",len,n,4);
+ smc->os.hwm.rx_len_error++ ;
+ goto abort_frame ;
+ }
+
+ /*
+ * Check SA == MA
+ */
+ virt = (u_char far *) rxd->rxd_virt ;
+ DB_RX("FC = %x",*virt,0,2) ;
+ if (virt[12] == MA[5] &&
+ virt[11] == MA[4] &&
+ virt[10] == MA[3] &&
+ virt[9] == MA[2] &&
+ virt[8] == MA[1] &&
+ (virt[7] & ~GROUP_ADDR_BIT) == MA[0]) {
+ goto abort_frame ;
+ }
+
+ /*
+ * test if LLC frame
+ */
+ if (rfsw & RX_FS_LLC) {
+ /*
+ * if pass_llc_promisc is disable
+ * if DA != Multicast or Broadcast or DA!=MA
+ * abort the frame
+ */
+ if (!smc->os.hwm.pass_llc_promisc) {
+ if(!(virt[1] & GROUP_ADDR_BIT)) {
+ if (virt[6] != MA[5] ||
+ virt[5] != MA[4] ||
+ virt[4] != MA[3] ||
+ virt[3] != MA[2] ||
+ virt[2] != MA[1] ||
+ virt[1] != MA[0]) {
+ DB_RX("DA != MA and not multi- or broadcast",0,0,2) ;
+ goto abort_frame ;
+ }
+ }
+ }
+
+ /*
+ * LLC frame received
+ */
+ DB_RX("LLC - receive",0,0,4) ;
+ mac_drv_rx_complete(smc,rxd,frag_count,len) ;
+ }
+ else {
+ if (!(mb = smt_get_mbuf(smc))) {
+ smc->hw.fp.err_stats.err_no_buf++ ;
+ DB_RX("No SMbuf; receive terminated",0,0,4) ;
+ goto abort_frame ;
+ }
+ data = smtod(mb,char *) - 1 ;
+
+ /*
+ * copy the frame into a SMT_MBuf
+ */
+#ifdef USE_OS_CPY
+ hwm_cpy_rxd2mb(rxd,data,len) ;
+#else
+ for (r=rxd, i=used_frags ; i ; r=r->rxd_next, i--){
+ n = AIX_REVERSE(r->rxd_rbctrl) & RD_LENGTH ;
+ DB_RX("cp SMT frame to mb: len = %d",n,0,6) ;
+ memcpy(data,r->rxd_virt,n) ;
+ data += n ;
+ }
+ data = smtod(mb,char *) - 1 ;
+#endif
+ fc = *(char *)mb->sm_data = *data ;
+ mb->sm_len = len - 1 ; /* len - fc */
+ data++ ;
+
+ /*
+ * SMT frame received
+ */
+ switch(fc) {
+ case FC_SMT_INFO :
+ smc->hw.fp.err_stats.err_smt_frame++ ;
+ DB_RX("SMT frame received ",0,0,5) ;
+
+ if (smc->os.hwm.pass_SMT) {
+ DB_RX("pass SMT frame ",0,0,5) ;
+ mac_drv_rx_complete(smc, rxd,
+ frag_count,len) ;
+ }
+ else {
+ DB_RX("requeue RxD",0,0,5) ;
+ mac_drv_requeue_rxd(smc,rxd,frag_count);
+ }
+
+ smt_received_pack(smc,mb,(int)(rfsw>>25)) ;
+ break ;
+ case FC_SMT_NSA :
+ smc->hw.fp.err_stats.err_smt_frame++ ;
+ DB_RX("SMT frame received ",0,0,5) ;
+
+ /* if pass_NSA set pass the NSA frame or */
+ /* pass_SMT set and the A-Indicator */
+ /* is not set, pass the NSA frame */
+ if (smc->os.hwm.pass_NSA ||
+ (smc->os.hwm.pass_SMT &&
+ !(rfsw & A_INDIC))) {
+ DB_RX("pass SMT frame ",0,0,5) ;
+ mac_drv_rx_complete(smc, rxd,
+ frag_count,len) ;
+ }
+ else {
+ DB_RX("requeue RxD",0,0,5) ;
+ mac_drv_requeue_rxd(smc,rxd,frag_count);
+ }
+
+ smt_received_pack(smc,mb,(int)(rfsw>>25)) ;
+ break ;
+ case FC_BEACON :
+ if (smc->os.hwm.pass_DB) {
+ DB_RX("pass DB frame ",0,0,5) ;
+ mac_drv_rx_complete(smc, rxd,
+ frag_count,len) ;
+ }
+ else {
+ DB_RX("requeue RxD",0,0,5) ;
+ mac_drv_requeue_rxd(smc,rxd,frag_count);
+ }
+ smt_free_mbuf(smc,mb) ;
+ break ;
+ default :
+ /*
+ * unknown FC abord the frame
+ */
+ DB_RX("unknown FC error",0,0,2) ;
+ smt_free_mbuf(smc,mb) ;
+ DB_RX("requeue RxD",0,0,5) ;
+ mac_drv_requeue_rxd(smc,rxd,frag_count) ;
+ if ((fc & 0xf0) == FC_MAC)
+ smc->hw.fp.err_stats.err_mac_frame++ ;
+ else
+ smc->hw.fp.err_stats.err_imp_frame++ ;
+
+ break ;
+ }
+ }
+
+ DB_RX("next RxD is %x ",queue->rx_curr_get,0,3) ;
+ NDD_TRACE("RHx1",queue->rx_curr_get,0,0) ;
+
+ continue ;
+ /*--------------------------------------------------------------------*/
+abort_frame:
+ DB_RX("requeue RxD",0,0,5) ;
+ mac_drv_requeue_rxd(smc,rxd,frag_count) ;
+
+ DB_RX("next RxD is %x ",queue->rx_curr_get,0,3) ;
+ NDD_TRACE("RHx2",queue->rx_curr_get,0,0) ;
+ }
+rx_end:
+#ifdef ALL_RX_COMPLETE
+ mac_drv_all_receives_complete(smc) ;
+#endif
+ return ; /* lint bug: needs return detect end of function */
+}
+
+static void smt_to_llc(smc,mb)
+struct s_smc *smc ;
+SMbuf *mb ;
+{
+ u_char fc ;
+
+ DB_RX("send a queued frame to the llc layer",0,0,4) ;
+ smc->os.hwm.r.len = mb->sm_len ;
+ smc->os.hwm.r.mb_pos = smtod(mb,char *) ;
+ fc = *smc->os.hwm.r.mb_pos ;
+ (void)mac_drv_rx_init(smc,(int)mb->sm_len,(int)fc,
+ smc->os.hwm.r.mb_pos,(int)mb->sm_len) ;
+ smt_free_mbuf(smc,mb) ;
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY(hwm_rx_frag)
+ * void hwm_rx_frag(smc,virt,phys,len,frame_status)
+ *
+ * function MACRO (hardware module, hwmtm.h)
+ * This function calls dma_master for preparing the
+ * system hardware for the DMA transfer and initializes
+ * the current RxD with the length and the physical and
+ * virtual address of the fragment. Furthermore, it sets the
+ * STF and EOF bits depending on the frame status byte,
+ * switches the OWN flag of the RxD, so that it is owned by the
+ * adapter and issues an rx_start.
+ *
+ * para virt virtual pointer to the fragment
+ * len the length of the fragment
+ * frame_status status of the frame, see design description
+ *
+ * NOTE: It is possible to call this function with a fragment length
+ * of zero.
+ *
+ * END_MANUAL_ENTRY
+ */
+void hwm_rx_frag(smc,virt,phys,len,frame_status)
+struct s_smc *smc ;
+char far *virt ;
+u_long phys ;
+int len ;
+int frame_status ;
+{
+ struct s_smt_fp_rxd volatile *r ;
+#ifdef AIX
+ u_long rbctrl ;
+#endif
+
+ NDD_TRACE("RHfB",virt,len,frame_status) ;
+ DB_RX("hwm_rx_frag: len = %d, frame_status = %x\n",len,frame_status,2) ;
+ r = smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put ;
+ r->rxd_virt = virt ;
+ r->rxd_rbadr = AIX_REVERSE(phys) ;
+#ifndef AIX
+ r->rxd_rbctrl = (((u_long)frame_status & (FIRST_FRAG|LAST_FRAG))<<26) |
+ (((u_long) frame_status & FIRST_FRAG) << 21) |
+ BMU_OWN | BMU_CHECK | BMU_EN_IRQ_EOF | len ;
+#else
+ rbctrl = AIX_REVERSE( (((u_long)frame_status &
+ (FIRST_FRAG|LAST_FRAG))<<26) |
+ (((u_long) frame_status & FIRST_FRAG) << 21) |
+ BMU_OWN | BMU_CHECK | BMU_EN_IRQ_EOF | len) ;
+ r->rxd_rbctrl = rbctrl ;
+#endif
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
+ outpd(ADDR(B0_R1_CSR),CSR_START) ;
+ smc->hw.fp.rx_q[QUEUE_R1].rx_free-- ;
+ smc->hw.fp.rx_q[QUEUE_R1].rx_used++ ;
+ smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put = r->rxd_next ;
+ NDD_TRACE("RHfE",r,AIX_REVERSE(r->rxd_rbadr),0) ;
+}
+
+#ifndef NDIS_OS2
+/*
+ * BEGIN_MANUAL_ENTRY(mac_drv_rx_frag)
+ * int mac_drv_rx_frag(smc,virt,len)
+ *
+ * function DOWNCALL (hwmtm.c)
+ * mac_drv_rx_frag fills the fragment with a part of the frame.
+ *
+ * para virt the virtual address of the fragment
+ * len the length in bytes of the fragment
+ *
+ * return 0: success code, no errors possible
+ *
+ * END_MANUAL_ENTRY
+ */
+int mac_drv_rx_frag(smc,virt,len)
+struct s_smc *smc ;
+void far *virt ;
+int len ;
+{
+ NDD_TRACE("RHSB",virt,len,smc->os.hwm.r.mb_pos) ;
+
+ DB_RX("receive from queue: len/virt: = %d/%x",len,virt,4) ;
+ memcpy((char far *)virt,smc->os.hwm.r.mb_pos,len) ;
+ smc->os.hwm.r.mb_pos += len ;
+
+ NDD_TRACE("RHSE",smc->os.hwm.r.mb_pos,0,0) ;
+ return(0) ;
+}
+#endif
+
+
+/*
+ * BEGINN_MANUAL_ENTRY(mac_drv_clear_rx_queue)
+ *
+ * void mac_drv_clear_rx_queue(smc)
+ * struct s_smc *smc ;
+ *
+ * function DOWNCALL (hardware module, hwmtm.c)
+ * mac_drv_clear_rx_queue is called by the OS-specific module
+ * after it has issued a card_stop.
+ * In this case, the frames in the receive queue are obsolete and
+ * should be removed. For removing mac_drv_clear_rx_queue
+ * calls dma_master for each RxD and mac_drv_clear_rxd for each
+ * receive buffer.
+ *
+ * NOTE: calling sequence card_stop:
+ * CLI_FBI(), card_stop(),
+ * mac_drv_clear_tx_queue(), mac_drv_clear_rx_queue(),
+ *
+ * NOTE: The caller is responsible that the BMUs are idle
+ * when this function is called.
+ *
+ * END_MANUAL_ENTRY
+ */
+void mac_drv_clear_rx_queue(smc)
+struct s_smc *smc ;
+{
+ struct s_smt_fp_rxd volatile *r ;
+ struct s_smt_fp_rxd volatile *next_rxd ;
+ struct s_smt_rx_queue *queue ;
+ int frag_count ;
+ int i ;
+
+ if (smc->hw.hw_state != STOPPED) {
+ SK_BREAK() ;
+ SMT_PANIC(smc,HWM_E0012,HWM_E0012_MSG) ;
+ return ;
+ }
+
+ queue = smc->hw.fp.rx[QUEUE_R1] ;
+ DB_RX("clear_rx_queue",0,0,5) ;
+
+ /*
+ * dma_complete and mac_drv_clear_rxd for all RxDs / receive buffers
+ */
+ r = queue->rx_curr_get ;
+ while (queue->rx_used) {
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+ DB_RX("switch OWN bit of RxD 0x%x ",r,0,5) ;
+ r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ;
+ frag_count = 1 ;
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
+ r = r->rxd_next ;
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+ while (r != queue->rx_curr_put &&
+ !(r->rxd_rbctrl & AIX_REVERSE(BMU_ST_BUF))) {
+ DB_RX("Check STF bit in %x",(void *)r,0,5) ;
+ r->rxd_rbctrl &= AIX_REVERSE(~BMU_OWN) ;
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
+ r = r->rxd_next ;
+ DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+ frag_count++ ;
+ }
+ DB_RX("STF bit found",0,0,5) ;
+ next_rxd = r ;
+
+ for (r=queue->rx_curr_get,i=frag_count; i ; r=r->rxd_next,i--){
+ DB_RX("dma_complete for RxD %x",(void *)r,0,5) ;
+ dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR);
+ }
+
+ DB_RX("mac_drv_clear_rxd: RxD %x frag_count %d ",
+ (void *)queue->rx_curr_get,frag_count,5) ;
+ mac_drv_clear_rxd(smc,queue->rx_curr_get,frag_count) ;
+
+ queue->rx_curr_get = next_rxd ;
+ queue->rx_used -= frag_count ;
+ queue->rx_free += frag_count ;
+ }
+}
+
+
+/*
+ -------------------------------------------------------------
+ SEND FUNCTIONS:
+ -------------------------------------------------------------
+*/
+
+/*
+ * BEGIN_MANUAL_ENTRY(hwm_tx_init)
+ * int hwm_tx_init(smc,fc,frag_count,frame_len,frame_status)
+ *
+ * function DOWN_CALL (hardware module, hwmtm.c)
+ * hwm_tx_init checks if the frame can be sent through the
+ * corresponding send queue.
+ *
+ * para fc the frame control. To determine through which
+ * send queue the frame should be transmitted.
+ * 0x50 - 0x57: asynchronous LLC frame
+ * 0xD0 - 0xD7: synchronous LLC frame
+ * 0x41, 0x4F: SMT frame to the network
+ * 0x42: SMT frame to the network and to the local SMT
+ * 0x43: SMT frame to the local SMT
+ * frag_count count of the fragments for this frame
+ * frame_len length of the frame
+ * frame_status status of the frame, the send queue bit is already
+ * specified
+ *
+ * return frame_status
+ *
+ * END_MANUAL_ENTRY
+ */
+int hwm_tx_init(smc,fc,frag_count,frame_len,frame_status)
+struct s_smc *smc ;
+u_char fc ;
+int frag_count ;
+int frame_len ;
+int frame_status ;
+{
+ NDD_TRACE("THiB",fc,frag_count,frame_len) ;
+ smc->os.hwm.tx_p = smc->hw.fp.tx[frame_status & QUEUE_A0] ;
+ smc->os.hwm.tx_descr = TX_DESCRIPTOR | (((u_long)(frame_len-1)&3)<<27) ;
+ smc->os.hwm.tx_len = frame_len ;
+ DB_TX("hwm_tx_init: fc = %x, len = %d",fc,frame_len,3) ;
+ if ((fc & ~(FC_SYNC_BIT|FC_LLC_PRIOR)) == FC_ASYNC_LLC) {
+ frame_status |= LAN_TX ;
+ }
+ else {
+ switch (fc) {
+ case FC_SMT_INFO :
+ case FC_SMT_NSA :
+ frame_status |= LAN_TX ;
+ break ;
+ case FC_SMT_LOC :
+ frame_status |= LOC_TX ;
+ break ;
+ case FC_SMT_LAN_LOC :
+ frame_status |= LAN_TX | LOC_TX ;
+ break ;
+ default :
+ SMT_PANIC(smc,HWM_E0010,HWM_E0010_MSG) ;
+ }
+ }
+ if (!smc->hw.mac_ring_is_up) {
+ frame_status &= ~LAN_TX ;
+ frame_status |= RING_DOWN ;
+ DB_TX("Ring is down: terminate LAN_TX",0,0,2) ;
+ }
+ if (frag_count > smc->os.hwm.tx_p->tx_free) {
+#ifndef NDIS_OS2
+ mac_drv_clear_txd(smc) ;
+ if (frag_count > smc->os.hwm.tx_p->tx_free) {
+ DB_TX("Out of TxDs, terminate LAN_TX",0,0,2) ;
+ frame_status &= ~LAN_TX ;
+ frame_status |= OUT_OF_TXD ;
+ }
+#else
+ DB_TX("Out of TxDs, terminate LAN_TX",0,0,2) ;
+ frame_status &= ~LAN_TX ;
+ frame_status |= OUT_OF_TXD ;
+#endif
+ }
+ DB_TX("frame_status = %x",frame_status,0,3) ;
+ NDD_TRACE("THiE",frame_status,smc->os.hwm.tx_p->tx_free,0) ;
+ return(frame_status) ;
+}
+
+/*
+ * BEGIN_MANUAL_ENTRY(hwm_tx_frag)
+ * void hwm_tx_frag(smc,virt,phys,len,frame_status)
+ *
+ * function DOWNCALL (hardware module, hwmtm.c)
+ * If the frame should be sent to the LAN, this function calls
+ * dma_master, fills the current TxD with the virtual and the
+ * physical address, sets the STF and EOF bits dependent on
+ * the frame status, and requests the BMU to start the
+ * transmit.
+ * If the frame should be sent to the local SMT, an SMT_MBuf
+ * is allocated if the FIRST_FRAG bit is set in the frame_status.
+ * The fragment of the frame is copied into the SMT MBuf.
+ * The function smt_received_pack is called if the LAST_FRAG
+ * bit is set in the frame_status word.
+ *
+ * para virt virtual pointer to the fragment
+ * len the length of the fragment
+ * frame_status status of the frame, see design description
+ *
+ * return nothing returned, no parameter is modified
+ *
+ * NOTE: It is possible to invoke this macro with a fragment length
+ * of zero.
+ *
+ * END_MANUAL_ENTRY
+ */
+void hwm_tx_frag(smc,virt,phys,len,frame_status)
+struct s_smc *smc ;
+char far *virt ;
+u_long phys ;
+int len ;
+int frame_status ;
+{
+ struct s_smt_fp_txd volatile *t ;
+ struct s_smt_tx_queue *queue ;
+#ifdef AIX
+ u_long tbctrl ;
+#endif
+
+ queue = smc->os.hwm.tx_p ;
+
+ NDD_TRACE("THfB",virt,len,frame_status) ;
+ /* Bug fix: AF / May 31 1999 (#missing)
+ * snmpinfo problem reported by IBM is caused by invalid
+ * t-pointer (txd) if LAN_TX is not set but LOC_TX only.
+ * Set: t = queue->tx_curr_put here !
+ */
+ t = queue->tx_curr_put ;
+
+ DB_TX("hwm_tx_frag: len = %d, frame_status = %x ",len,frame_status,2) ;
+ if (frame_status & LAN_TX) {
+ /* '*t' is already defined */
+ DB_TX("LAN_TX: TxD = %x, virt = %x ",t,virt,3) ;
+ t->txd_virt = virt ;
+ t->txd_txdscr = AIX_REVERSE(smc->os.hwm.tx_descr) ;
+ t->txd_tbadr = AIX_REVERSE(phys) ;
+#ifndef AIX
+ t->txd_tbctrl = (((u_long)frame_status &
+ (FIRST_FRAG|LAST_FRAG|EN_IRQ_EOF))<< 26) |
+ BMU_OWN|BMU_CHECK |len ;
+ DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
+ outpd(queue->tx_bmu_ctl,CSR_START) ;
+
+#else /* ifndef AIX */
+ tbctrl = AIX_REVERSE((((u_long)frame_status &
+ (FIRST_FRAG|LAST_FRAG|EN_IRQ_EOF))<< 26) |
+ BMU_OWN|BMU_CHECK |len) ;
+ t->txd_tbctrl = tbctrl ;
+
+ DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
+ if (frame_status & QUEUE_A0) {
+ outpd(ADDR(B0_XA_CSR),CSR_START) ;
+ }
+ else {
+ outpd(ADDR(B0_XS_CSR),CSR_START) ;
+ }
+#endif
+ queue->tx_free-- ;
+ queue->tx_used++ ;
+ queue->tx_curr_put = t->txd_next ;
+ if (frame_status & LAST_FRAG) {
+ smc->mib.m[MAC0].fddiMACTransmit_Ct++ ;
+ }
+ }
+ if (frame_status & LOC_TX) {
+ DB_TX("LOC_TX: ",0,0,3) ;
+ if (frame_status & FIRST_FRAG) {
+ if(!(smc->os.hwm.tx_mb = smt_get_mbuf(smc))) {
+ smc->hw.fp.err_stats.err_no_buf++ ;
+ DB_TX("No SMbuf; transmit terminated",0,0,4) ;
+ }
+ else {
+ smc->os.hwm.tx_data =
+ smtod(smc->os.hwm.tx_mb,char *) - 1 ;
+#ifdef USE_OS_CPY
+#ifdef PASS_1ST_TXD_2_TX_COMP
+ hwm_cpy_txd2mb(t,smc->os.hwm.tx_data,
+ smc->os.hwm.tx_len) ;
+#endif
+#endif
+ }
+ }
+ if (smc->os.hwm.tx_mb) {
+#ifndef USE_OS_CPY
+ DB_TX("copy fragment into MBuf ",0,0,3) ;
+ memcpy(smc->os.hwm.tx_data,virt,len) ;
+ smc->os.hwm.tx_data += len ;
+#endif
+ if (frame_status & LAST_FRAG) {
+#ifdef USE_OS_CPY
+#ifndef PASS_1ST_TXD_2_TX_COMP
+ /*
+ * hwm_cpy_txd2mb(txd,data,len) copies 'len'
+ * bytes from the virtual pointer in 'rxd'
+ * to 'data'. The virtual pointer of the
+ * os-specific tx-buffer should be written
+ * in the LAST txd.
+ */
+ hwm_cpy_txd2mb(t,smc->os.hwm.tx_data,
+ smc->os.hwm.tx_len) ;
+#endif /* nPASS_1ST_TXD_2_TX_COMP */
+#endif /* USE_OS_CPY */
+ smc->os.hwm.tx_data =
+ smtod(smc->os.hwm.tx_mb,char *) - 1 ;
+ *(char *)smc->os.hwm.tx_mb->sm_data =
+ *smc->os.hwm.tx_data ;
+ smc->os.hwm.tx_data++ ;
+ smc->os.hwm.tx_mb->sm_len =
+ smc->os.hwm.tx_len - 1 ;
+ DB_TX("pass LLC frame to SMT ",0,0,3) ;
+ smt_received_pack(smc,smc->os.hwm.tx_mb,
+ RD_FS_LOCAL) ;
+ }
+ }
+ }
+ NDD_TRACE("THfE",t,queue->tx_free,0) ;
+}
+
+
+/*
+ * queues a receive for later send
+ */
+static void queue_llc_rx(smc,mb)
+struct s_smc *smc ;
+SMbuf *mb ;
+{
+ DB_GEN("queue_llc_rx: mb = %x",(void *)mb,0,4) ;
+ smc->os.hwm.queued_rx_frames++ ;
+ mb->sm_next = (SMbuf *)NULL ;
+ if (smc->os.hwm.llc_rx_pipe == 0) {
+ smc->os.hwm.llc_rx_pipe = mb ;
+ }
+ else {
+ smc->os.hwm.llc_rx_tail->sm_next = mb ;
+ }
+ smc->os.hwm.llc_rx_tail = mb ;
+
+ /*
+ * force an timer IRQ to receive the data
+ */
+ if (!smc->os.hwm.isr_flag) {
+ smt_force_irq(smc) ;
+ }
+}
+
+/*
+ * get a SMbuf from the llc_rx_queue
+ */
+static SMbuf *get_llc_rx(smc)
+struct s_smc *smc ;
+{
+ SMbuf *mb ;
+
+ if ((mb = smc->os.hwm.llc_rx_pipe)) {
+ smc->os.hwm.queued_rx_frames-- ;
+ smc->os.hwm.llc_rx_pipe = mb->sm_next ;
+ }
+ DB_GEN("get_llc_rx: mb = 0x%x",(void *)mb,0,4) ;
+ return(mb) ;
+}
+
+/*
+ * queues a transmit SMT MBuf during the time were the MBuf is
+ * queued the TxD ring
+ */
+static void queue_txd_mb(smc,mb)
+struct s_smc *smc ;
+SMbuf *mb ;
+{
+ DB_GEN("_rx: queue_txd_mb = %x",(void *)mb,0,4) ;
+ smc->os.hwm.queued_txd_mb++ ;
+ mb->sm_next = (SMbuf *)NULL ;
+ if (smc->os.hwm.txd_tx_pipe == 0) {
+ smc->os.hwm.txd_tx_pipe = mb ;
+ }
+ else {
+ smc->os.hwm.txd_tx_tail->sm_next = mb ;
+ }
+ smc->os.hwm.txd_tx_tail = mb ;
+}
+
+/*
+ * get a SMbuf from the txd_tx_queue
+ */
+static SMbuf *get_txd_mb(smc)
+struct s_smc *smc ;
+{
+ SMbuf *mb ;
+
+ if ((mb = smc->os.hwm.txd_tx_pipe)) {
+ smc->os.hwm.queued_txd_mb-- ;
+ smc->os.hwm.txd_tx_pipe = mb->sm_next ;
+ }
+ DB_GEN("get_txd_mb: mb = 0x%x",(void *)mb,0,4) ;
+ return(mb) ;
+}
+
+/*
+ * SMT Send function
+ */
+void smt_send_mbuf(smc,mb,fc)
+struct s_smc *smc;
+SMbuf *mb;
+int fc;
+{
+ char far *data ;
+ int len ;
+ int n ;
+ int i ;
+ int frag_count ;
+ int frame_status ;
+ SK_LOC_DECL(char far,*virt[3]) ;
+ int frag_len[3] ;
+ struct s_smt_tx_queue *queue ;
+ struct s_smt_fp_txd volatile *t ;
+ u_long phys ;
+#ifdef AIX
+ u_long tbctrl ;
+#endif
+
+ NDD_TRACE("THSB",mb,fc,0) ;
+ DB_TX("smt_send_mbuf: mb = 0x%x, fc = 0x%x",mb,fc,4) ;
+
+ mb->sm_off-- ; /* set to fc */
+ mb->sm_len++ ; /* + fc */
+ data = smtod(mb,char *) ;
+ *data = fc ;
+ if (fc == FC_SMT_LOC)
+ *data = FC_SMT_INFO ;
+
+ /*
+ * determine the frag count and the virt addresses of the frags
+ */
+ frag_count = 0 ;
+ len = mb->sm_len ;
+ while (len) {
+ n = SMT_PAGESIZE - ((int)data & (SMT_PAGESIZE-1)) ;
+ if (n >= len) {
+ n = len ;
+ }
+ DB_TX("frag: virt/len = 0x%x/%d ",(void *)data,n,5) ;
+ virt[frag_count] = data ;
+ frag_len[frag_count] = n ;
+ frag_count++ ;
+ len -= n ;
+ data += n ;
+ }
+
+ /*
+ * determine the frame status
+ */
+ queue = smc->hw.fp.tx[QUEUE_A0] ;
+ if (fc == FC_BEACON || fc == FC_SMT_LOC) {
+ frame_status = LOC_TX ;
+ }
+ else {
+ frame_status = LAN_TX ;
+ if ((smc->os.hwm.pass_NSA &&(fc == FC_SMT_NSA)) ||
+ (smc->os.hwm.pass_SMT &&(fc == FC_SMT_INFO)))
+ frame_status |= LOC_TX ;
+ }
+
+ if (!smc->hw.mac_ring_is_up || frag_count > queue->tx_free) {
+ if (frame_status &= ~LAN_TX) {
+ DB_TX("Ring is down: terminate LAN_TX",0,0,2) ;
+ }
+ else {
+ DB_TX("Ring is down: terminate transmission",0,0,2) ;
+ smt_free_mbuf(smc,mb) ;
+ return ;
+ }
+ }
+ DB_TX("frame_status = 0x%x ",frame_status,0,5) ;
+
+ if ((frame_status & LAN_TX) && (frame_status & LOC_TX)) {
+ mb->sm_use_count = 2 ;
+ }
+
+ if (frame_status & LAN_TX) {
+ t = queue->tx_curr_put ;
+ frame_status |= FIRST_FRAG ;
+ for (i = 0; i < frag_count; i++) {
+ DB_TX("init TxD = 0x%x",(void *)t,0,5) ;
+ if (i == frag_count-1) {
+ frame_status |= LAST_FRAG ;
+ t->txd_txdscr = AIX_REVERSE(TX_DESCRIPTOR |
+ (((u_long)(mb->sm_len-1)&3) << 27)) ;
+ }
+ t->txd_virt = virt[i] ;
+ phys = dma_master(smc, (void far *)virt[i],
+ frag_len[i], DMA_RD|SMT_BUF) ;
+ t->txd_tbadr = AIX_REVERSE(phys) ;
+#ifndef AIX
+ t->txd_tbctrl = (((u_long) frame_status &
+ (FIRST_FRAG|LAST_FRAG)) << 26) |
+ BMU_OWN | BMU_CHECK | BMU_SMT_TX |frag_len[i] ;
+ DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
+ outpd(queue->tx_bmu_ctl,CSR_START) ;
+#else
+ tbctrl = AIX_REVERSE((((u_long) frame_status &
+ (FIRST_FRAG|LAST_FRAG)) << 26) |
+ BMU_OWN | BMU_CHECK | BMU_SMT_TX |frag_len[i]) ;
+ t->txd_tbctrl = tbctrl ;
+ DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
+ outpd(ADDR(B0_XA_CSR),CSR_START) ;
+#endif
+ frame_status &= ~FIRST_FRAG ;
+ queue->tx_curr_put = t = t->txd_next ;
+ queue->tx_free-- ;
+ queue->tx_used++ ;
+ }
+ smc->mib.m[MAC0].fddiMACTransmit_Ct++ ;
+ queue_txd_mb(smc,mb) ;
+ }
+
+ if (frame_status & LOC_TX) {
+ DB_TX("pass Mbuf to LLC queue",0,0,5) ;
+ queue_llc_rx(smc,mb) ;
+ }
+
+ /*
+ * We need to unqueue the free SMT_MBUFs here, because it may
+ * be that the SMT want's to send more than 1 frame for one down call
+ */
+ mac_drv_clear_txd(smc) ;
+ NDD_TRACE("THSE",t,queue->tx_free,frag_count) ;
+}
+
+/* BEGIN_MANUAL_ENTRY(mac_drv_clear_txd)
+ * void mac_drv_clear_txd(smc)
+ *
+ * function DOWNCALL (hardware module, hwmtm.c)
+ * mac_drv_clear_txd searches in both send queues for TxD's
+ * which were finished by the adapter. It calls dma_complete
+ * for each TxD. If the last fragment of an LLC frame is
+ * reached, it calls mac_drv_tx_complete to release the
+ * send buffer.
+ *
+ * return nothing
+ *
+ * END_MANUAL_ENTRY
+ */
+void mac_drv_clear_txd(smc)
+struct s_smc *smc ;
+{
+ struct s_smt_tx_queue *queue ;
+ struct s_smt_fp_txd volatile *t1 ;
+ struct s_smt_fp_txd volatile *t2=0 ;
+ SMbuf *mb ;
+ u_long tbctrl ;
+ int i ;
+ int frag_count ;
+ int n ;
+
+ NDD_TRACE("THcB",0,0,0) ;
+ for (i = QUEUE_S; i <= QUEUE_A0; i++) {
+ queue = smc->hw.fp.tx[i] ;
+ t1 = queue->tx_curr_get ;
+ DB_TX("clear_txd: QUEUE = %d (0=sync/1=async)",i,0,5) ;
+
+ for ( ; ; ) {
+ frag_count = 0 ;
+
+ do {
+ DRV_BUF_FLUSH(t1,DDI_DMA_SYNC_FORCPU) ;
+ DB_TX("check OWN/EOF bit of TxD 0x%x",t1,0,5) ;
+ tbctrl = CR_READ(t1->txd_tbctrl) ;
+#ifdef AIX
+ tbctrl = AIX_REVERSE(tbctrl) ;
+#endif
+ if (tbctrl & BMU_OWN || !queue->tx_used){
+ DB_TX("End of TxDs queue %d",i,0,4) ;
+ goto free_next_queue ; /* next queue */
+ }
+ t1 = t1->txd_next ;
+ frag_count++ ;
+ } while (!(tbctrl & BMU_EOF)) ;
+
+ t1 = queue->tx_curr_get ;
+ for (n = frag_count; n; n--) {
+ tbctrl = AIX_REVERSE(t1->txd_tbctrl) ;
+ dma_complete(smc,
+ (union s_fp_descr volatile *) t1,
+ (int) (DMA_RD |
+ ((tbctrl & BMU_SMT_TX) >> 18))) ;
+ t2 = t1 ;
+ t1 = t1->txd_next ;
+ }
+
+ if (tbctrl & BMU_SMT_TX) {
+ mb = get_txd_mb(smc) ;
+ smt_free_mbuf(smc,mb) ;
+ }
+ else {
+#ifndef PASS_1ST_TXD_2_TX_COMP
+ DB_TX("mac_drv_tx_comp for TxD 0x%x",t2,0,4) ;
+ mac_drv_tx_complete(smc,t2) ;
+#else
+ DB_TX("mac_drv_tx_comp for TxD 0x%x",
+ queue->tx_curr_get,0,4) ;
+ mac_drv_tx_complete(smc,queue->tx_curr_get) ;
+#endif
+ }
+ queue->tx_curr_get = t1 ;
+ queue->tx_free += frag_count ;
+ queue->tx_used -= frag_count ;
+ }
+free_next_queue: ;
+ }
+ NDD_TRACE("THcE",0,0,0) ;
+}
+
+/*
+ * BEGINN_MANUAL_ENTRY(mac_drv_clear_tx_queue)
+ *
+ * void mac_drv_clear_tx_queue(smc)
+ * struct s_smc *smc ;
+ *
+ * function DOWNCALL (hardware module, hwmtm.c)
+ * mac_drv_clear_tx_queue is called from the SMT when
+ * the RMT state machine has entered the ISOLATE state.
+ * This function is also called by the os-specific module
+ * after it has called the function card_stop().
+ * In this case, the frames in the send queues are obsolete and
+ * should be removed.
+ *
+ * note calling sequence:
+ * CLI_FBI(), card_stop(),
+ * mac_drv_clear_tx_queue(), mac_drv_clear_rx_queue(),
+ *
+ * NOTE: The caller is responsible that the BMUs are idle
+ * when this function is called.
+ *
+ * END_MANUAL_ENTRY
+ */
+void mac_drv_clear_tx_queue(smc)
+struct s_smc *smc ;
+{
+ struct s_smt_fp_txd volatile *t ;
+ struct s_smt_tx_queue *queue ;
+ int tx_used ;
+ int i ;
+
+ if (smc->hw.hw_state != STOPPED) {
+ SK_BREAK() ;
+ SMT_PANIC(smc,HWM_E0011,HWM_E0011_MSG) ;
+ return ;
+ }
+
+ for (i = QUEUE_S; i <= QUEUE_A0; i++) {
+ queue = smc->hw.fp.tx[i] ;
+ DB_TX("clear_tx_queue: QUEUE = %d (0=sync/1=async)",i,0,5) ;
+
+ /*
+ * switch the OWN bit of all pending frames to the host
+ */
+ t = queue->tx_curr_get ;
+ tx_used = queue->tx_used ;
+ while (tx_used) {
+ DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;
+ DB_TX("switch OWN bit of TxD 0x%x ",t,0,5) ;
+ t->txd_tbctrl &= AIX_REVERSE(~BMU_OWN) ;
+ DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
+ t = t->txd_next ;
+ tx_used-- ;
+ }
+ }
+
+ /*
+ * release all TxD's for both send queues
+ */
+ mac_drv_clear_txd(smc) ;
+
+ for (i = QUEUE_S; i <= QUEUE_A0; i++) {
+ queue = smc->hw.fp.tx[i] ;
+ t = queue->tx_curr_get ;
+
+ /*
+ * write the phys pointer of the NEXT descriptor into the
+ * BMU's current address descriptor pointer and set
+ * tx_curr_get and tx_curr_put to this position
+ */
+ if (i == QUEUE_S) {
+ outpd(ADDR(B5_XS_DA),AIX_REVERSE(t->txd_ntdadr)) ;
+ }
+ else {
+ outpd(ADDR(B5_XA_DA),AIX_REVERSE(t->txd_ntdadr)) ;
+ }
+
+ queue->tx_curr_put = queue->tx_curr_get->txd_next ;
+ queue->tx_curr_get = queue->tx_curr_put ;
+ }
+}
+
+
+/*
+ -------------------------------------------------------------
+ TEST FUNCTIONS:
+ -------------------------------------------------------------
+*/
+
+#ifdef DEBUG
+/*
+ * BEGIN_MANUAL_ENTRY(mac_drv_debug_lev)
+ * void mac_drv_debug_lev(smc,flag,lev)
+ *
+ * function DOWNCALL (drvsr.c)
+ * To get a special debug info the user can assign a debug level
+ * to any debug flag.
+ *
+ * para flag debug flag, possible values are:
+ * = 0: reset all debug flags (the defined level is
+ * ignored)
+ * = 1: debug.d_smtf
+ * = 2: debug.d_smt
+ * = 3: debug.d_ecm
+ * = 4: debug.d_rmt
+ * = 5: debug.d_cfm
+ * = 6: debug.d_pcm
+ *
+ * = 10: debug.d_os.hwm_rx (hardware module receive path)
+ * = 11: debug.d_os.hwm_tx(hardware module transmit path)
+ * = 12: debug.d_os.hwm_gen(hardware module general flag)
+ *
+ * lev debug level
+ *
+ * END_MANUAL_ENTRY
+ */
+void mac_drv_debug_lev(smc,flag,lev)
+struct s_smc *smc ;
+int flag ;
+int lev ;
+{
+ switch(flag) {
+ case (int)NULL:
+ DB_P.d_smtf = DB_P.d_smt = DB_P.d_ecm = DB_P.d_rmt = 0 ;
+ DB_P.d_cfm = 0 ;
+ DB_P.d_os.hwm_rx = DB_P.d_os.hwm_tx = DB_P.d_os.hwm_gen = 0 ;
+#ifdef SBA
+ DB_P.d_sba = 0 ;
+#endif
+#ifdef ESS
+ DB_P.d_ess = 0 ;
+#endif
+ break ;
+ case DEBUG_SMTF:
+ DB_P.d_smtf = lev ;
+ break ;
+ case DEBUG_SMT:
+ DB_P.d_smt = lev ;
+ break ;
+ case DEBUG_ECM:
+ DB_P.d_ecm = lev ;
+ break ;
+ case DEBUG_RMT:
+ DB_P.d_rmt = lev ;
+ break ;
+ case DEBUG_CFM:
+ DB_P.d_cfm = lev ;
+ break ;
+ case DEBUG_PCM:
+ DB_P.d_pcm = lev ;
+ break ;
+ case DEBUG_SBA:
+#ifdef SBA
+ DB_P.d_sba = lev ;
+#endif
+ break ;
+ case DEBUG_ESS:
+#ifdef ESS
+ DB_P.d_ess = lev ;
+#endif
+ break ;
+ case DB_HWM_RX:
+ DB_P.d_os.hwm_rx = lev ;
+ break ;
+ case DB_HWM_TX:
+ DB_P.d_os.hwm_tx = lev ;
+ break ;
+ case DB_HWM_GEN:
+ DB_P.d_os.hwm_gen = lev ;
+ break ;
+ default:
+ break ;
+ }
+}
+#endif
diff --git a/drivers/net/skfp/hwt.c b/drivers/net/skfp/hwt.c
new file mode 100644
index 000000000..7d51b8b8b
--- /dev/null
+++ b/drivers/net/skfp/hwt.c
@@ -0,0 +1,314 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * Timer Driver for FBI board (timer chip 82C54)
+ */
+
+/*
+ * Modifications:
+ *
+ * 28-Jun-1994 sw Edit v1.6.
+ * MCA: Added support for the SK-NET FDDI-FM2 adapter. The
+ * following functions have been added(+) or modified(*):
+ * hwt_start(*), hwt_stop(*), hwt_restart(*), hwt_read(*)
+ */
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)hwt.c 1.13 97/04/23 (C) SK " ;
+#endif
+
+/*
+ * Prototypes of local functions.
+ */
+/* 28-Jun-1994 sw - Note: hwt_restart() is also used in module 'drvfbi.c'. */
+/*static*/ void hwt_restart() ;
+
+/************************
+ *
+ * hwt_start
+ *
+ * Start hardware timer (clock ticks are 16us).
+ *
+ * void hwt_start(
+ * struct s_smc *smc,
+ * u_long time) ;
+ * In
+ * smc - A pointer to the SMT Context structure.
+ *
+ * time - The time in units of 16us to load the timer with.
+ * Out
+ * Nothing.
+ *
+ ************************/
+#define HWT_MAX (65000)
+
+void hwt_start(smc, time)
+struct s_smc *smc ;
+u_long time ;
+{
+ u_short cnt ;
+
+ if (time > HWT_MAX)
+ time = HWT_MAX ;
+
+ smc->hw.t_start = time ;
+ smc->hw.t_stop = 0L ;
+
+ cnt = (u_short)time ;
+ /*
+ * if time < 16 us
+ * time = 16 us
+ */
+ if (!cnt)
+ cnt++ ;
+#ifndef PCI
+ /*
+ * 6.25MHz -> CLK0 : T0 (cnt0 = 16us) -> OUT0
+ * OUT0 -> CLK1 : T1 (cnt1) OUT1 -> ISRA(IS_TIMINT)
+ */
+ OUT_82c54_TIMER(3,1<<6 | 3<<4 | 0<<1) ; /* counter 1, mode 0 */
+ OUT_82c54_TIMER(1,cnt & 0xff) ; /* LSB */
+ OUT_82c54_TIMER(1,(cnt>>8) & 0xff) ; /* MSB */
+ /*
+ * start timer by switching counter 0 to mode 3
+ * T0 resolution 16 us (CLK0=0.16us)
+ */
+ OUT_82c54_TIMER(3,0<<6 | 3<<4 | 3<<1) ; /* counter 0, mode 3 */
+ OUT_82c54_TIMER(0,100) ; /* LSB */
+ OUT_82c54_TIMER(0,0) ; /* MSB */
+#else /* PCI */
+ outpd(ADDR(B2_TI_INI), (u_long) cnt * 200) ; /* Load timer value. */
+ outpw(ADDR(B2_TI_CRTL), TIM_START) ; /* Start timer. */
+#endif /* PCI */
+ smc->hw.timer_activ = TRUE ;
+}
+
+/************************
+ *
+ * hwt_stop
+ *
+ * Stop hardware timer.
+ *
+ * void hwt_stop(
+ * struct s_smc *smc) ;
+ * In
+ * smc - A pointer to the SMT Context structure.
+ * Out
+ * Nothing.
+ *
+ ************************/
+void hwt_stop(smc)
+struct s_smc *smc ;
+{
+#ifndef PCI
+ /* stop counter 0 by switching to mode 0 */
+ OUT_82c54_TIMER(3,0<<6 | 3<<4 | 0<<1) ; /* counter 0, mode 0 */
+ OUT_82c54_TIMER(0,0) ; /* LSB */
+ OUT_82c54_TIMER(0,0) ; /* MSB */
+#else /* PCI */
+ outpw(ADDR(B2_TI_CRTL), TIM_STOP) ;
+ outpw(ADDR(B2_TI_CRTL), TIM_CL_IRQ) ;
+#endif /* PCI */
+
+ smc->hw.timer_activ = FALSE ;
+}
+
+/************************
+ *
+ * hwt_init
+ *
+ * Initialize hardware timer.
+ *
+ * void hwt_init(
+ * struct s_smc *smc) ;
+ * In
+ * smc - A pointer to the SMT Context structure.
+ * Out
+ * Nothing.
+ *
+ ************************/
+void hwt_init(smc)
+struct s_smc *smc ;
+{
+ smc->hw.t_start = 0 ;
+ smc->hw.t_stop = 0 ;
+ smc->hw.timer_activ = FALSE ;
+
+ hwt_restart(smc) ;
+}
+
+/************************
+ *
+ * hwt_restart
+ *
+ * Clear timer interrupt.
+ *
+ * void hwt_restart(
+ * struct s_smc *smc) ;
+ * In
+ * smc - A pointer to the SMT Context structure.
+ * Out
+ * Nothing.
+ *
+ ************************/
+void hwt_restart(smc)
+struct s_smc *smc ;
+{
+ hwt_stop(smc) ;
+#ifndef PCI
+ OUT_82c54_TIMER(3,1<<6 | 3<<4 | 0<<1) ; /* counter 1, mode 0 */
+ OUT_82c54_TIMER(1,1 ) ; /* LSB */
+ OUT_82c54_TIMER(1,0 ) ; /* MSB */
+#endif
+}
+
+/************************
+ *
+ * hwt_read
+ *
+ * Stop hardware timer and read time elapsed since last start.
+ *
+ * u_long hwt_read(smc) ;
+ * In
+ * smc - A pointer to the SMT Context structure.
+ * Out
+ * The elapsed time since last start in units of 16us.
+ *
+ ************************/
+u_long hwt_read(smc)
+struct s_smc *smc ;
+{
+ u_short tr ;
+#ifndef PCI
+ u_short is ;
+#else
+ u_long is ;
+#endif
+
+ if (smc->hw.timer_activ) {
+ hwt_stop(smc) ;
+#ifndef PCI
+ OUT_82c54_TIMER(3,1<<6) ; /* latch command */
+ tr = IN_82c54_TIMER(1) & 0xff ;
+ tr += (IN_82c54_TIMER(1) & 0xff)<<8 ;
+#else /* PCI */
+ tr = (u_short)((inpd(ADDR(B2_TI_VAL))/200) & 0xffff) ;
+#endif /* PCI */
+ is = GET_ISR() ;
+ /* Check if timer expired (or wraparound). */
+ if ((tr > smc->hw.t_start) || (is & IS_TIMINT)) {
+ hwt_restart(smc) ;
+ smc->hw.t_stop = smc->hw.t_start ;
+ }
+ else
+ smc->hw.t_stop = smc->hw.t_start - tr ;
+ }
+ return (smc->hw.t_stop) ;
+}
+
+#ifdef PCI
+/************************
+ *
+ * hwt_quick_read
+ *
+ * Stop hardware timer and read timer value and start the timer again.
+ *
+ * u_long hwt_read(smc) ;
+ * In
+ * smc - A pointer to the SMT Context structure.
+ * Out
+ * current timer value in units of 80ns.
+ *
+ ************************/
+u_long hwt_quick_read(smc)
+struct s_smc *smc ;
+{
+ u_long interval ;
+ u_long time ;
+
+ interval = inpd(ADDR(B2_TI_INI)) ;
+ outpw(ADDR(B2_TI_CRTL), TIM_STOP) ;
+ time = inpd(ADDR(B2_TI_VAL)) ;
+ outpd(ADDR(B2_TI_INI),time) ;
+ outpw(ADDR(B2_TI_CRTL), TIM_START) ;
+ outpd(ADDR(B2_TI_INI),interval) ;
+
+ return(time) ;
+}
+
+/************************
+ *
+ * hwt_wait_time(smc,start,duration)
+ *
+ * This function returnes after the amount of time is elapsed
+ * since the start time.
+ *
+ * para start start time
+ * duration time to wait
+ *
+ * NOTE: The fuction will return immediatly, if the timer is not
+ * started
+ ************************/
+void hwt_wait_time(smc,start,duration)
+struct s_smc *smc ;
+u_long start ;
+long duration ;
+{
+ long diff ;
+ long interval ;
+ int wrapped ;
+
+ /*
+ * check if timer is running
+ */
+ if (smc->hw.timer_activ == FALSE ||
+ hwt_quick_read(smc) == hwt_quick_read(smc)) {
+ return ;
+ }
+
+ interval = inpd(ADDR(B2_TI_INI)) ;
+ if (interval > duration) {
+ do {
+ diff = (long)(start - hwt_quick_read(smc)) ;
+ if (diff < 0) {
+ diff += interval ;
+ }
+ } while (diff <= duration) ;
+ }
+ else {
+ diff = interval ;
+ wrapped = 0 ;
+ do {
+ if (!wrapped) {
+ if (hwt_quick_read(smc) >= start) {
+ diff += interval ;
+ wrapped = 1 ;
+ }
+ }
+ else {
+ if (hwt_quick_read(smc) < start) {
+ wrapped = 0 ;
+ }
+ }
+ } while (diff <= duration) ;
+ }
+}
+#endif
diff --git a/drivers/net/skfp/lnkstat.c b/drivers/net/skfp/lnkstat.c
new file mode 100644
index 000000000..7d2d94eae
--- /dev/null
+++ b/drivers/net/skfp/lnkstat.c
@@ -0,0 +1,209 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ IBM FDDI read error log function
+*/
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/lnkstat.h"
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)lnkstat.c 1.8 97/04/11 (C) SK " ;
+#endif
+
+#ifdef sun
+#define _far
+#endif
+
+#define EL_IS_OK(x,l) ((((int)&(((struct s_error_log *)0)->x)) + \
+ sizeof(er->x)) <= l)
+
+/*
+ BEGIN_MANUAL_ENTRY(if,func;others;11)
+
+ u_long smt_get_error_word(smc)
+ struct s_smc *smc ;
+
+Function DOWNCALL (SMT, lnkstat.c)
+ This functions returns the SMT error work for AIX events.
+
+Return smt_error_word These bits are supported:
+
+ SMT_ERL_ALC == [PS/PA].fddiPORTLerFlag
+ SMT_ERL_BLC == [PB].fddiPORTLerFlag
+ SMT_ERL_NCC == fddiMACNotCopiedFlag
+ SMT_ERL_FEC == fddiMACFrameErrorFlag
+
+ END_MANUAL_ENTRY()
+ */
+u_long smt_get_error_word(smc)
+struct s_smc *smc ;
+{
+ u_long st;
+
+ /*
+ * smt error word low
+ */
+ st = 0 ;
+ if (smc->s.sas == SMT_SAS) {
+ if (smc->mib.p[PS].fddiPORTLerFlag)
+ st |= SMT_ERL_ALC ;
+ }
+ else {
+ if (smc->mib.p[PA].fddiPORTLerFlag)
+ st |= SMT_ERL_ALC ;
+ if (smc->mib.p[PB].fddiPORTLerFlag)
+ st |= SMT_ERL_BLC ;
+ }
+ if (smc->mib.m[MAC0].fddiMACNotCopiedFlag)
+ st |= SMT_ERL_NCC ; /* not copied condition */
+ if (smc->mib.m[MAC0].fddiMACFrameErrorFlag)
+ st |= SMT_ERL_FEC ; /* frame error condition */
+
+ return st;
+}
+
+/*
+ BEGIN_MANUAL_ENTRY(if,func;others;11)
+
+ u_long smt_get_event_word(smc)
+ struct s_smc *smc ;
+
+Function DOWNCALL (SMT, lnkstat.c)
+ This functions returns the SMT event work for AIX events.
+
+Return smt_event_word always 0
+
+ END_MANUAL_ENTRY()
+ */
+u_long smt_get_event_word(smc)
+struct s_smc *smc ;
+{
+ return (u_long) 0;
+}
+
+/*
+ BEGIN_MANUAL_ENTRY(if,func;others;11)
+
+ u_long smt_get_port_event_word(smc)
+ struct s_smc *smc ;
+
+Function DOWNCALL (SMT, lnkstat.c)
+ This functions returns the SMT port event work for AIX events.
+
+Return smt_port_event_word always 0
+
+ END_MANUAL_ENTRY()
+ */
+u_long smt_get_port_event_word(smc)
+struct s_smc *smc ;
+{
+ return (u_long) 0;
+}
+
+/*
+ BEGIN_MANUAL_ENTRY(if,func;others;11)
+
+ u_long smt_read_errorlog(smc,p,len)
+ struct s_smc *smc ;
+ char _far *p ;
+ int len ;
+
+Function DOWNCALL (SMT, lnkstat.c)
+ This functions returns the SMT error log field for AIX events.
+
+Para p pointer to the error log field
+ len len of the error log field
+
+Return len used len of the error log field
+
+ END_MANUAL_ENTRY()
+ */
+int smt_read_errorlog(smc,p,len)
+struct s_smc *smc ;
+char _far *p ;
+int len ;
+{
+ int i ;
+ int st ;
+ struct s_error_log _far *er ;
+
+ er = (struct s_error_log _far *) p ;
+ if (len > sizeof(struct s_error_log))
+ len = sizeof(struct s_error_log) ;
+ for (i = 0 ; i < len ; i++)
+ *p++ = 0 ;
+ /*
+ * set count
+ */
+ if (EL_IS_OK(set_count_high,len)) {
+ er->set_count_low = (u_short)smc->mib.fddiSMTSetCount.count ;
+ er->set_count_high =
+ (u_short)(smc->mib.fddiSMTSetCount.count >> 16L) ;
+ }
+ /*
+ * aci
+ */
+ if (EL_IS_OK(aci_id_code,len)) {
+ er->aci_id_code = 0 ;
+ }
+ /*
+ * purge counter is missed frames; 16 bits only
+ */
+ if (EL_IS_OK(purge_frame_counter,len)) {
+ if (smc->mib.m[MAC0].fddiMACCopied_Ct > 0xffff)
+ er->purge_frame_counter = 0xffff ;
+ else
+ er->purge_frame_counter =
+ (u_short)smc->mib.m[MAC0].fddiMACCopied_Ct ;
+ }
+ /*
+ * CMT and RMT state machines
+ */
+ if (EL_IS_OK(ecm_state,len))
+ er->ecm_state = smc->mib.fddiSMTECMState ;
+
+ if (EL_IS_OK(pcm_b_state,len)) {
+ if (smc->s.sas == SMT_SAS) {
+ er->pcm_a_state = smc->y[PS].mib->fddiPORTPCMState ;
+ er->pcm_b_state = 0 ;
+ }
+ else {
+ er->pcm_a_state = smc->y[PA].mib->fddiPORTPCMState ;
+ er->pcm_b_state = smc->y[PB].mib->fddiPORTPCMState ;
+ }
+ }
+ if (EL_IS_OK(cfm_state,len))
+ er->cfm_state = smc->mib.fddiSMTCF_State ;
+ if (EL_IS_OK(rmt_state,len))
+ er->rmt_state = smc->mib.m[MAC0].fddiMACRMTState ;
+
+ /*
+ * smt error word low (we only need the low order 16 bits.)
+ */
+
+ st = smt_get_error_word(smc) & 0xffff ;
+
+ if (EL_IS_OK(smt_error_low,len))
+ er->smt_error_low = st ;
+
+ if (EL_IS_OK(ucode_version_level,len))
+ er->ucode_version_level = 0x0101 ;
+ return(len) ;
+}
diff --git a/drivers/net/skfp/pcmplc.c b/drivers/net/skfp/pcmplc.c
new file mode 100644
index 000000000..5479b27ea
--- /dev/null
+++ b/drivers/net/skfp/pcmplc.c
@@ -0,0 +1,2094 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ PCM
+ Physical Connection Management
+*/
+
+/*
+ * Hardware independant state machine implemantation
+ * The following external SMT functions are referenced :
+ *
+ * queue_event()
+ * smt_timer_start()
+ * smt_timer_stop()
+ *
+ * The following external HW dependant functions are referenced :
+ * sm_pm_control()
+ * sm_ph_linestate()
+ * sm_pm_ls_latch()
+ *
+ * The following HW dependant events are required :
+ * PC_QLS
+ * PC_ILS
+ * PC_HLS
+ * PC_MLS
+ * PC_NSE
+ * PC_LEM
+ *
+ */
+
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/supern_2.h"
+#define KERNEL
+#include "h/smtstate.h"
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)pcmplc.c 2.55 99/08/05 (C) SK " ;
+#endif
+
+#ifdef FDDI_MIB
+extern int snmp_fddi_trap(
+#ifdef ANSIC
+struct s_smc * smc, int type, int index
+#endif
+);
+#endif
+#ifdef CONCENTRATOR
+extern int plc_is_installed(
+#ifdef ANSIC
+struct s_smc *smc ,
+int p
+#endif
+) ;
+#endif
+/*
+ * FSM Macros
+ */
+#define AFLAG (0x20)
+#define GO_STATE(x) (mib->fddiPORTPCMState = (x)|AFLAG)
+#define ACTIONS_DONE() (mib->fddiPORTPCMState &= ~AFLAG)
+#define ACTIONS(x) (x|AFLAG)
+
+/*
+ * PCM states
+ */
+#define PC0_OFF 0
+#define PC1_BREAK 1
+#define PC2_TRACE 2
+#define PC3_CONNECT 3
+#define PC4_NEXT 4
+#define PC5_SIGNAL 5
+#define PC6_JOIN 6
+#define PC7_VERIFY 7
+#define PC8_ACTIVE 8
+#define PC9_MAINT 9
+
+#ifdef DEBUG
+/*
+ * symbolic state names
+ */
+static const char * const pcm_states[] = {
+ "PC0_OFF","PC1_BREAK","PC2_TRACE","PC3_CONNECT","PC4_NEXT",
+ "PC5_SIGNAL","PC6_JOIN","PC7_VERIFY","PC8_ACTIVE","PC9_MAINT"
+} ;
+
+/*
+ * symbolic event names
+ */
+static const char * const pcm_events[] = {
+ "NONE","PC_START","PC_STOP","PC_LOOP","PC_JOIN","PC_SIGNAL",
+ "PC_REJECT","PC_MAINT","PC_TRACE","PC_PDR",
+ "PC_ENABLE","PC_DISABLE",
+ "PC_QLS","PC_ILS","PC_MLS","PC_HLS","PC_LS_PDR","PC_LS_NONE",
+ "PC_TIMEOUT_TB_MAX","PC_TIMEOUT_TB_MIN",
+ "PC_TIMEOUT_C_MIN","PC_TIMEOUT_T_OUT",
+ "PC_TIMEOUT_TL_MIN","PC_TIMEOUT_T_NEXT","PC_TIMEOUT_LCT",
+ "PC_NSE","PC_LEM"
+} ;
+#endif
+
+#ifdef MOT_ELM
+/*
+ * PCL-S control register
+ * this register in the PLC-S controls the scrambling parameters
+ */
+#define PLCS_CONTROL_C_U 0
+#define PLCS_CONTROL_C_S (PL_C_SDOFF_ENABLE | PL_C_SDON_ENABLE | \
+ PL_C_CIPHER_ENABLE)
+#define PLCS_FASSERT_U 0
+#define PLCS_FASSERT_S 0xFd76 /* 52.0 us */
+#define PLCS_FDEASSERT_U 0
+#define PLCS_FDEASSERT_S 0
+#else /* nMOT_ELM */
+/*
+ * PCL-S control register
+ * this register in the PLC-S controls the scrambling parameters
+ * can be patched for ANSI compliance if standard changes
+ */
+static const u_char plcs_control_c_u[17] = "PLC_CNTRL_C_U=\0\0" ;
+static const u_char plcs_control_c_s[17] = "PLC_CNTRL_C_S=\01\02" ;
+
+#define PLCS_CONTROL_C_U (plcs_control_c_u[14] | (plcs_control_c_u[15]<<8))
+#define PLCS_CONTROL_C_S (plcs_control_c_s[14] | (plcs_control_c_s[15]<<8))
+#endif /* nMOT_ELM */
+
+/*
+ * external vars
+ */
+/* struct definition see 'cmtdef.h' (also used by CFM) */
+
+#define PS_OFF 0
+#define PS_BIT3 1
+#define PS_BIT4 2
+#define PS_BIT7 3
+#define PS_LCT 4
+#define PS_BIT8 5
+#define PS_JOIN 6
+#define PS_ACTIVE 7
+
+#define LCT_LEM_MAX 255
+
+/*
+ * PLC timing parameter
+ */
+
+#define PLC_MS(m) ((int)((0x10000L-(m*100000L/2048))))
+#define SLOW_TL_MIN PLC_MS(6)
+#define SLOW_C_MIN PLC_MS(10)
+
+static const struct plt {
+ int timer ; /* relative plc timer address */
+ int para ; /* default timing parameters */
+} pltm[] = {
+ { PL_C_MIN, SLOW_C_MIN }, /* min t. to remain Connect State */
+ { PL_TL_MIN, SLOW_TL_MIN }, /* min t. to transmit a Line State */
+ { PL_TB_MIN, TP_TB_MIN }, /* min break time */
+ { PL_T_OUT, TP_T_OUT }, /* Signaling timeout */
+ { PL_LC_LENGTH, TP_LC_LENGTH }, /* Link Confidence Test Time */
+ { PL_T_SCRUB, TP_T_SCRUB }, /* Scrub Time == MAC TVX time ! */
+ { PL_NS_MAX, TP_NS_MAX }, /* max t. that noise is tolerated */
+ { 0,0 }
+} ;
+
+/*
+ * interrupt mask
+ */
+#ifdef SUPERNET_3
+/*
+ * Do we need the EBUF error during signaling, too, to detect SUPERNET_3
+ * PLL bug?
+ */
+static int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
+ PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR;
+#else /* SUPERNET_3 */
+/*
+ * We do NOT need the elasticity buffer error during signaling.
+ */
+static int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
+ PL_PCM_ENABLED | PL_SELF_TEST ;
+#endif /* SUPERNET_3 */
+static int plc_imsk_act = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
+ PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR;
+
+/* external functions */
+void all_selection_criteria ();
+
+/* internal functions */
+static void pcm_fsm() ;
+static void pc_rcode_actions() ;
+static void pc_tcode_actions() ;
+static void reset_lem_struct() ;
+static void plc_init() ;
+static void sm_ph_lem_start() ;
+static void sm_ph_lem_stop() ;
+static void sm_ph_linestate() ;
+static void real_init_plc() ;
+
+/*
+ * SMT timer interface
+ * start PCM timer 0
+ */
+static void start_pcm_timer0(smc,value,event,phy)
+struct s_smc *smc ;
+u_long value;
+int event;
+struct s_phy *phy;
+{
+ phy->timer0_exp = FALSE ; /* clear timer event flag */
+ smt_timer_start(smc,&phy->pcm_timer0,value,
+ EV_TOKEN(EVENT_PCM+phy->np,event)) ;
+}
+/*
+ * SMT timer interface
+ * stop PCM timer 0
+ */
+static void stop_pcm_timer0(smc,phy)
+struct s_smc *smc ;
+struct s_phy *phy;
+{
+ if (phy->pcm_timer0.tm_active)
+ smt_timer_stop(smc,&phy->pcm_timer0) ;
+}
+
+/*
+ init PCM state machine (called by driver)
+ clear all PCM vars and flags
+*/
+void pcm_init(smc)
+struct s_smc *smc ;
+{
+ int i ;
+ int np ;
+ struct s_phy *phy ;
+ struct fddi_mib_p *mib ;
+
+ for (np = 0,phy = smc->y ; np < NUMPHYS ; np++,phy++) {
+ /* Indicates the type of PHY being used */
+ mib = phy->mib ;
+ mib->fddiPORTPCMState = ACTIONS(PC0_OFF) ;
+ phy->np = np ;
+ switch (smc->s.sas) {
+#ifdef CONCENTRATOR
+ case SMT_SAS :
+ mib->fddiPORTMy_Type = (np == PS) ? TS : TM ;
+ break ;
+ case SMT_DAS :
+ mib->fddiPORTMy_Type = (np == PA) ? TA :
+ (np == PB) ? TB : TM ;
+ break ;
+ case SMT_NAC :
+ mib->fddiPORTMy_Type = TM ;
+ break;
+#else
+ case SMT_SAS :
+ mib->fddiPORTMy_Type = (np == PS) ? TS : TNONE ;
+ mib->fddiPORTHardwarePresent = (np == PS) ? TRUE :
+ FALSE ;
+#ifndef SUPERNET_3
+ smc->y[PA].mib->fddiPORTPCMState = PC0_OFF ;
+#else
+ smc->y[PB].mib->fddiPORTPCMState = PC0_OFF ;
+#endif
+ break ;
+ case SMT_DAS :
+ mib->fddiPORTMy_Type = (np == PB) ? TB : TA ;
+ break ;
+#endif
+ }
+ /*
+ * set PMD-type
+ */
+ phy->pmd_scramble = 0 ;
+ switch (phy->pmd_type[PMD_SK_PMD]) {
+ case 'P' :
+ mib->fddiPORTPMDClass = MIB_PMDCLASS_MULTI ;
+ break ;
+ case 'L' :
+ mib->fddiPORTPMDClass = MIB_PMDCLASS_LCF ;
+ break ;
+ case 'D' :
+ mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
+ break ;
+ case 'S' :
+ mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
+ phy->pmd_scramble = TRUE ;
+ break ;
+ case 'U' :
+ mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
+ phy->pmd_scramble = TRUE ;
+ break ;
+ case '1' :
+ mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE1 ;
+ break ;
+ case '2' :
+ mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE2 ;
+ break ;
+ case '3' :
+ mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE2 ;
+ break ;
+ case '4' :
+ mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE1 ;
+ break ;
+ case 'H' :
+ mib->fddiPORTPMDClass = MIB_PMDCLASS_UNKNOWN ;
+ break ;
+ case 'I' :
+ mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
+ break ;
+ case 'G' :
+ mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
+ break ;
+ default:
+ mib->fddiPORTPMDClass = MIB_PMDCLASS_UNKNOWN ;
+ break ;
+ }
+ /*
+ * A and B port can be on primary and secondary path
+ */
+ switch (mib->fddiPORTMy_Type) {
+ case TA :
+ mib->fddiPORTAvailablePaths |= MIB_PATH_S ;
+ mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
+ mib->fddiPORTRequestedPaths[2] =
+ MIB_P_PATH_LOCAL |
+ MIB_P_PATH_CON_ALTER |
+ MIB_P_PATH_SEC_PREFER ;
+ mib->fddiPORTRequestedPaths[3] =
+ MIB_P_PATH_LOCAL |
+ MIB_P_PATH_CON_ALTER |
+ MIB_P_PATH_SEC_PREFER |
+ MIB_P_PATH_THRU ;
+ break ;
+ case TB :
+ mib->fddiPORTAvailablePaths |= MIB_PATH_S ;
+ mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
+ mib->fddiPORTRequestedPaths[2] =
+ MIB_P_PATH_LOCAL |
+ MIB_P_PATH_PRIM_PREFER ;
+ mib->fddiPORTRequestedPaths[3] =
+ MIB_P_PATH_LOCAL |
+ MIB_P_PATH_PRIM_PREFER |
+ MIB_P_PATH_CON_PREFER |
+ MIB_P_PATH_THRU ;
+ break ;
+ case TS :
+ mib->fddiPORTAvailablePaths |= MIB_PATH_S ;
+ mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
+ mib->fddiPORTRequestedPaths[2] =
+ MIB_P_PATH_LOCAL |
+ MIB_P_PATH_CON_ALTER |
+ MIB_P_PATH_PRIM_PREFER ;
+ mib->fddiPORTRequestedPaths[3] =
+ MIB_P_PATH_LOCAL |
+ MIB_P_PATH_CON_ALTER |
+ MIB_P_PATH_PRIM_PREFER ;
+ break ;
+ case TM :
+ mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
+ mib->fddiPORTRequestedPaths[2] =
+ MIB_P_PATH_LOCAL |
+ MIB_P_PATH_SEC_ALTER |
+ MIB_P_PATH_PRIM_ALTER ;
+ mib->fddiPORTRequestedPaths[3] = 0 ;
+ break ;
+ }
+
+ phy->pc_lem_fail = FALSE ;
+ mib->fddiPORTPCMStateX = mib->fddiPORTPCMState ;
+ mib->fddiPORTLCTFail_Ct = 0 ;
+ mib->fddiPORTBS_Flag = 0 ;
+ mib->fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
+ mib->fddiPORTNeighborType = TNONE ;
+ phy->ls_flag = 0 ;
+ phy->rc_flag = 0 ;
+ phy->tc_flag = 0 ;
+ phy->td_flag = 0 ;
+ if (np >= PM)
+ phy->phy_name = '0' + np - PM ;
+ else
+ phy->phy_name = 'A' + np ;
+ phy->wc_flag = FALSE ; /* set by SMT */
+ memset((char *)&phy->lem,0,sizeof(struct lem_counter)) ;
+ reset_lem_struct(phy) ;
+ memset((char *)&phy->plc,0,sizeof(struct s_plc)) ;
+ phy->plc.p_state = PS_OFF ;
+ for (i = 0 ; i < NUMBITS ; i++) {
+ phy->t_next[i] = 0 ;
+ }
+ }
+ real_init_plc(smc) ;
+}
+
+void init_plc(smc)
+struct s_smc *smc ;
+{
+ SK_UNUSED(smc) ;
+
+ /*
+ * dummy
+ * this is an obsolete public entry point that has to remain
+ * for compat. It is used by various drivers.
+ * the work is now done in real_init_plc()
+ * which is called from pcm_init() ;
+ */
+}
+
+static void real_init_plc(smc)
+struct s_smc *smc ;
+{
+ int p ;
+
+ for (p = 0 ; p < NUMPHYS ; p++)
+ plc_init(smc,p) ;
+}
+
+static void plc_init(smc,p)
+struct s_smc *smc ;
+int p;
+{
+ int i ;
+#ifndef MOT_ELM
+ int rev ; /* Revision of PLC-x */
+#endif /* MOT_ELM */
+
+ /* transit PCM state machine to MAINT state */
+ outpw(PLC(p,PL_CNTRL_B),0) ;
+ outpw(PLC(p,PL_CNTRL_B),PL_PCM_STOP) ;
+ outpw(PLC(p,PL_CNTRL_A),0) ;
+
+ /*
+ * if PLC-S then set control register C
+ */
+#ifndef MOT_ELM
+ rev = inpw(PLC(p,PL_STATUS_A)) & PLC_REV_MASK ;
+ if (rev != PLC_REVISION_A)
+#endif /* MOT_ELM */
+ {
+ if (smc->y[p].pmd_scramble) {
+ outpw(PLC(p,PL_CNTRL_C),PLCS_CONTROL_C_S) ;
+#ifdef MOT_ELM
+ outpw(PLC(p,PL_T_FOT_ASS),PLCS_FASSERT_S) ;
+ outpw(PLC(p,PL_T_FOT_DEASS),PLCS_FDEASSERT_S) ;
+#endif /* MOT_ELM */
+ }
+ else {
+ outpw(PLC(p,PL_CNTRL_C),PLCS_CONTROL_C_U) ;
+#ifdef MOT_ELM
+ outpw(PLC(p,PL_T_FOT_ASS),PLCS_FASSERT_U) ;
+ outpw(PLC(p,PL_T_FOT_DEASS),PLCS_FDEASSERT_U) ;
+#endif /* MOT_ELM */
+ }
+ }
+
+ /*
+ * set timer register
+ */
+ for ( i = 0 ; pltm[i].timer; i++) /* set timer parameter reg */
+ outpw(PLC(p,pltm[i].timer),pltm[i].para) ;
+
+ (void)inpw(PLC(p,PL_INTR_EVENT)) ; /* clear interrupt event reg */
+ plc_clear_irq(smc,p) ;
+ outpw(PLC(p,PL_INTR_MASK),plc_imsk_na); /* enable non active irq's */
+
+ /*
+ * if PCM is configured for class s, it will NOT go to the
+ * REMOVE state if offline (page 3-36;)
+ * in the concentrator, all inactive PHYS always must be in
+ * the remove state
+ * there's no real need to use this feature at all ..
+ */
+#ifndef CONCENTRATOR
+ if ((smc->s.sas == SMT_SAS) && (p == PS)) {
+ outpw(PLC(p,PL_CNTRL_B),PL_CLASS_S) ;
+ }
+#endif
+}
+
+/*
+ * control PCM state machine
+ */
+static void plc_go_state(smc,p,state)
+struct s_smc *smc ;
+int p;
+int state;
+{
+ HW_PTR port ;
+ int val ;
+
+ SK_UNUSED(smc) ;
+
+ port = (HW_PTR) (PLC(p,PL_CNTRL_B)) ;
+ val = inpw(port) & ~(PL_PCM_CNTRL | PL_MAINT) ;
+ outpw(port,val) ;
+ outpw(port,val | state) ;
+}
+
+/*
+ * read current line state (called by ECM & PCM)
+ */
+int sm_pm_get_ls(smc,phy)
+struct s_smc *smc ;
+int phy;
+{
+ int state ;
+
+#ifdef CONCENTRATOR
+ if (!plc_is_installed(smc,phy))
+ return(PC_QLS) ;
+#endif
+
+ state = inpw(PLC(phy,PL_STATUS_A)) & PL_LINE_ST ;
+ switch(state) {
+ case PL_L_QLS:
+ state = PC_QLS ;
+ break ;
+ case PL_L_MLS:
+ state = PC_MLS ;
+ break ;
+ case PL_L_HLS:
+ state = PC_HLS ;
+ break ;
+ case PL_L_ILS4:
+ case PL_L_ILS16:
+ state = PC_ILS ;
+ break ;
+ case PL_L_ALS:
+ state = PC_LS_PDR ;
+ break ;
+ default :
+ state = PC_LS_NONE ;
+ }
+ return(state) ;
+}
+
+static int plc_send_bits(smc,phy,len)
+struct s_smc *smc ;
+struct s_phy *phy;
+int len;
+{
+ int np = phy->np ; /* PHY index */
+ int n ;
+ int i ;
+
+ SK_UNUSED(smc) ;
+
+ /* create bit vector */
+ for (i = len-1,n = 0 ; i >= 0 ; i--) {
+ n = (n<<1) | phy->t_val[phy->bitn+i] ;
+ }
+ if (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL) {
+#if 0
+ printf("PL_PCM_SIGNAL is set\n") ;
+#endif
+ return(1) ;
+ }
+ /* write bit[n] & length = 1 to regs */
+ outpw(PLC(np,PL_VECTOR_LEN),len-1) ; /* len=nr-1 */
+ outpw(PLC(np,PL_XMIT_VECTOR),n) ;
+#ifdef DEBUG
+#if 1
+#ifdef DEBUG_BRD
+ if (smc->debug.d_plc & 0x80)
+#else
+ if (debug.d_plc & 0x80)
+#endif
+ printf("SIGNALING bit %d .. %d\n",phy->bitn,phy->bitn+len-1) ;
+#endif
+#endif
+ return(0) ;
+}
+
+/*
+ * config plc muxes
+ */
+void plc_config_mux(smc,mux)
+struct s_smc *smc ;
+int mux ;
+{
+ if (smc->s.sas != SMT_DAS)
+ return ;
+ if (mux == MUX_WRAPB) {
+ SETMASK(PLC(PA,PL_CNTRL_B),PL_CONFIG_CNTRL,PL_CONFIG_CNTRL) ;
+ SETMASK(PLC(PA,PL_CNTRL_A),PL_SC_REM_LOOP,PL_SC_REM_LOOP) ;
+ }
+ else {
+ CLEAR(PLC(PA,PL_CNTRL_B),PL_CONFIG_CNTRL) ;
+ CLEAR(PLC(PA,PL_CNTRL_A),PL_SC_REM_LOOP) ;
+ }
+ CLEAR(PLC(PB,PL_CNTRL_B),PL_CONFIG_CNTRL) ;
+ CLEAR(PLC(PB,PL_CNTRL_A),PL_SC_REM_LOOP) ;
+}
+
+/*
+ PCM state machine
+ called by dispatcher & fddi_init() (driver)
+ do
+ display state change
+ process event
+ until SM is stable
+*/
+void pcm(smc,np,event)
+struct s_smc *smc ;
+const int np;
+int event;
+{
+ int state ;
+ int oldstate ;
+ struct s_phy *phy ;
+ struct fddi_mib_p *mib ;
+
+#ifndef CONCENTRATOR
+ /*
+ * ignore 2nd PHY if SAS
+ */
+ if ((np != PS) && (smc->s.sas == SMT_SAS))
+ return ;
+#endif
+ phy = &smc->y[np] ;
+ mib = phy->mib ;
+ oldstate = mib->fddiPORTPCMState ;
+ do {
+ DB_PCM("PCM %c: state %s",
+ phy->phy_name,
+ (mib->fddiPORTPCMState & AFLAG) ? "ACTIONS " : "") ;
+ DB_PCM("%s, event %s\n",
+ pcm_states[mib->fddiPORTPCMState & ~AFLAG],
+ pcm_events[event]) ;
+ state = mib->fddiPORTPCMState ;
+ pcm_fsm(smc,phy,event) ;
+ event = 0 ;
+ } while (state != mib->fddiPORTPCMState) ;
+ /*
+ * because the PLC does the bit signaling for us,
+ * we're always in SIGNAL state
+ * the MIB want's to see CONNECT
+ * we therefore fake an entry in the MIB
+ */
+ if (state == PC5_SIGNAL)
+ mib->fddiPORTPCMStateX = PC3_CONNECT ;
+ else
+ mib->fddiPORTPCMStateX = state ;
+
+#ifndef SLIM_SMT
+ /*
+ * path change
+ */
+ if ( mib->fddiPORTPCMState != oldstate &&
+ ((oldstate == PC8_ACTIVE) || (mib->fddiPORTPCMState == PC8_ACTIVE))) {
+ smt_srf_event(smc,SMT_EVENT_PORT_PATH_CHANGE,
+ (int) (INDEX_PORT+ phy->np),0) ;
+ }
+#endif
+
+#ifdef FDDI_MIB
+ /* check whether a snmp-trap has to be sent */
+
+ if ( mib->fddiPORTPCMState != oldstate ) {
+ /* a real state change took place */
+ DB_SNMP ("PCM from %d to %d\n", oldstate, mib->fddiPORTPCMState);
+ if ( mib->fddiPORTPCMState == PC0_OFF ) {
+ /* send first trap */
+ snmp_fddi_trap (smc, 1, (int) mib->fddiPORTIndex );
+ } else if ( oldstate == PC0_OFF ) {
+ /* send second trap */
+ snmp_fddi_trap (smc, 2, (int) mib->fddiPORTIndex );
+ } else if ( mib->fddiPORTPCMState != PC2_TRACE &&
+ oldstate == PC8_ACTIVE ) {
+ /* send third trap */
+ snmp_fddi_trap (smc, 3, (int) mib->fddiPORTIndex );
+ } else if ( mib->fddiPORTPCMState == PC8_ACTIVE ) {
+ /* send fourth trap */
+ snmp_fddi_trap (smc, 4, (int) mib->fddiPORTIndex );
+ }
+ }
+#endif
+
+ pcm_state_change(smc,np,state) ;
+}
+
+/*
+ * PCM state machine
+ */
+static void pcm_fsm(smc,phy,cmd)
+struct s_smc *smc ;
+struct s_phy *phy;
+int cmd;
+{
+ int i ;
+ int np = phy->np ; /* PHY index */
+ struct s_plc *plc ;
+ struct fddi_mib_p *mib ;
+#ifndef MOT_ELM
+ u_short plc_rev ; /* Revision of the plc */
+#endif /* nMOT_ELM */
+
+ plc = &phy->plc ;
+ mib = phy->mib ;
+
+ /*
+ * general transitions independant of state
+ */
+ switch (cmd) {
+ case PC_STOP :
+ /*PC00-PC80*/
+ if (mib->fddiPORTPCMState != PC9_MAINT) {
+ GO_STATE(PC0_OFF) ;
+ AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
+ FDDI_PORT_EVENT, (u_long) FDDI_PORT_STOP,
+ smt_get_port_event_word(smc));
+ }
+ return ;
+ case PC_START :
+ /*PC01-PC81*/
+ if (mib->fddiPORTPCMState != PC9_MAINT)
+ GO_STATE(PC1_BREAK) ;
+ return ;
+ case PC_DISABLE :
+ /* PC09-PC99 */
+ GO_STATE(PC9_MAINT) ;
+ AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
+ FDDI_PORT_EVENT, (u_long) FDDI_PORT_DISABLED,
+ smt_get_port_event_word(smc));
+ return ;
+ case PC_TIMEOUT_LCT :
+ /* if long or extended LCT */
+ stop_pcm_timer0(smc,phy) ;
+ CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
+ /* end of LCT is indicate by PCM_CODE (initiate PCM event) */
+ return ;
+ }
+
+ switch(mib->fddiPORTPCMState) {
+ case ACTIONS(PC0_OFF) :
+ stop_pcm_timer0(smc,phy) ;
+ outpw(PLC(np,PL_CNTRL_A),0) ;
+ CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ;
+ CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
+ sm_ph_lem_stop(smc,np) ; /* disable LEM */
+ phy->cf_loop = FALSE ;
+ phy->cf_join = FALSE ;
+ queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
+ plc_go_state(smc,np,PL_PCM_STOP) ;
+ mib->fddiPORTConnectState = PCM_DISABLED ;
+ ACTIONS_DONE() ;
+ break ;
+ case PC0_OFF:
+ /*PC09*/
+ if (cmd == PC_MAINT) {
+ GO_STATE(PC9_MAINT) ;
+ break ;
+ }
+ break ;
+ case ACTIONS(PC1_BREAK) :
+ /* Stop the LCT timer if we came from Signal state */
+ stop_pcm_timer0(smc,phy) ;
+ ACTIONS_DONE() ;
+ plc_go_state(smc,np,0) ;
+ CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ;
+ CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
+ sm_ph_lem_stop(smc,np) ; /* disable LEM */
+ /*
+ * if vector is already loaded, go to OFF to clear PCM_SIGNAL
+ */
+#if 0
+ if (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL) {
+ plc_go_state(smc,np,PL_PCM_STOP) ;
+ /* TB_MIN ? */
+ }
+#endif
+ /*
+ * Go to OFF state in any case.
+ */
+ plc_go_state(smc,np,PL_PCM_STOP) ;
+
+ if (mib->fddiPORTPC_Withhold == PC_WH_NONE)
+ mib->fddiPORTConnectState = PCM_CONNECTING ;
+ phy->cf_loop = FALSE ;
+ phy->cf_join = FALSE ;
+ queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
+ phy->ls_flag = FALSE ;
+ phy->pc_mode = PM_NONE ; /* needed by CFM */
+ phy->bitn = 0 ; /* bit signaling start bit */
+ for (i = 0 ; i < 3 ; i++)
+ pc_tcode_actions(smc,i,phy) ;
+
+ /* Set the non-active interrupt mask register */
+ outpw(PLC(np,PL_INTR_MASK),plc_imsk_na) ;
+
+ /*
+ * If the LCT was stopped. There might be a
+ * PCM_CODE interrupt event present.
+ * This must be cleared.
+ */
+ (void)inpw(PLC(np,PL_INTR_EVENT)) ;
+#ifndef MOT_ELM
+ /* Get the plc revision for revision dependent code */
+ plc_rev = inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK ;
+
+ if (plc_rev != PLC_REV_SN3)
+#endif /* MOT_ELM */
+ {
+ /*
+ * No supernet III PLC, so set Xmit verctor and
+ * length BEFORE starting the state machine.
+ */
+ if (plc_send_bits(smc,phy,3)) {
+ return ;
+ }
+ }
+
+ /*
+ * Now give the Start command.
+ * - The start command shall be done before setting the bits
+ * to be signaled. (In PLC-S description and PLCS in SN3.
+ * - The start command shall be issued AFTER setting the
+ * XMIT vector and the XMIT length register.
+ *
+ * We do it exactly according this specs for the old PLC and
+ * the new PLCS inside the SN3.
+ * For the usual PLCS we try it the way it is done for the
+ * old PLC and set the XMIT registers again, if the PLC is
+ * not in SIGNAL state. This is done according to an PLCS
+ * errata workaround.
+ */
+
+ plc_go_state(smc,np,PL_PCM_START) ;
+
+ /*
+ * workaround for PLC-S eng. sample errata
+ */
+#ifdef MOT_ELM
+ if (!(inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL))
+#else /* nMOT_ELM */
+ if (((inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK) !=
+ PLC_REVISION_A) &&
+ !(inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL))
+#endif /* nMOT_ELM */
+ {
+ /*
+ * Set register again (PLCS errata) or the first time
+ * (new SN3 PLCS).
+ */
+ (void) plc_send_bits(smc,phy,3) ;
+ }
+ /*
+ * end of workaround
+ */
+
+ GO_STATE(PC5_SIGNAL) ;
+ plc->p_state = PS_BIT3 ;
+ plc->p_bits = 3 ;
+ plc->p_start = 0 ;
+
+ break ;
+ case PC1_BREAK :
+ break ;
+ case ACTIONS(PC2_TRACE) :
+ plc_go_state(smc,np,PL_PCM_TRACE) ;
+ ACTIONS_DONE() ;
+ break ;
+ case PC2_TRACE :
+ break ;
+
+ case PC3_CONNECT : /* these states are done by hardware */
+ case PC4_NEXT :
+ break ;
+
+ case ACTIONS(PC5_SIGNAL) :
+ ACTIONS_DONE() ;
+ case PC5_SIGNAL :
+ if ((cmd != PC_SIGNAL) && (cmd != PC_TIMEOUT_LCT))
+ break ;
+ switch (plc->p_state) {
+ case PS_BIT3 :
+ for (i = 0 ; i <= 2 ; i++)
+ pc_rcode_actions(smc,i,phy) ;
+ pc_tcode_actions(smc,3,phy) ;
+ plc->p_state = PS_BIT4 ;
+ plc->p_bits = 1 ;
+ plc->p_start = 3 ;
+ phy->bitn = 3 ;
+ if (plc_send_bits(smc,phy,1)) {
+ return ;
+ }
+ break ;
+ case PS_BIT4 :
+ pc_rcode_actions(smc,3,phy) ;
+ for (i = 4 ; i <= 6 ; i++)
+ pc_tcode_actions(smc,i,phy) ;
+ plc->p_state = PS_BIT7 ;
+ plc->p_bits = 3 ;
+ plc->p_start = 4 ;
+ phy->bitn = 4 ;
+ if (plc_send_bits(smc,phy,3)) {
+ return ;
+ }
+ break ;
+ case PS_BIT7 :
+ for (i = 3 ; i <= 6 ; i++)
+ pc_rcode_actions(smc,i,phy) ;
+ plc->p_state = PS_LCT ;
+ plc->p_bits = 0 ;
+ plc->p_start = 7 ;
+ phy->bitn = 7 ;
+ sm_ph_lem_start(smc,np,(int)smc->s.lct_short) ; /* enable LEM */
+ /* start LCT */
+ i = inpw(PLC(np,PL_CNTRL_B)) & ~PL_PC_LOOP ;
+ outpw(PLC(np,PL_CNTRL_B),i) ; /* must be cleared */
+ outpw(PLC(np,PL_CNTRL_B),i | PL_RLBP) ;
+ break ;
+ case PS_LCT :
+ /* check for local LCT failure */
+ pc_tcode_actions(smc,7,phy) ;
+ /*
+ * set tval[7]
+ */
+ plc->p_state = PS_BIT8 ;
+ plc->p_bits = 1 ;
+ plc->p_start = 7 ;
+ phy->bitn = 7 ;
+ if (plc_send_bits(smc,phy,1)) {
+ return ;
+ }
+ break ;
+ case PS_BIT8 :
+ /* check for remote LCT failure */
+ pc_rcode_actions(smc,7,phy) ;
+ if (phy->t_val[7] || phy->r_val[7]) {
+ plc_go_state(smc,np,PL_PCM_STOP) ;
+ GO_STATE(PC1_BREAK) ;
+ break ;
+ }
+ for (i = 8 ; i <= 9 ; i++)
+ pc_tcode_actions(smc,i,phy) ;
+ plc->p_state = PS_JOIN ;
+ plc->p_bits = 2 ;
+ plc->p_start = 8 ;
+ phy->bitn = 8 ;
+ if (plc_send_bits(smc,phy,2)) {
+ return ;
+ }
+ break ;
+ case PS_JOIN :
+ for (i = 8 ; i <= 9 ; i++)
+ pc_rcode_actions(smc,i,phy) ;
+ plc->p_state = PS_ACTIVE ;
+ GO_STATE(PC6_JOIN) ;
+ break ;
+ }
+ break ;
+
+ case ACTIONS(PC6_JOIN) :
+ /*
+ * prevent mux error when going from WRAP_A to WRAP_B
+ */
+ if (smc->s.sas == SMT_DAS && np == PB &&
+ (smc->y[PA].pc_mode == PM_TREE ||
+ smc->y[PB].pc_mode == PM_TREE)) {
+ SETMASK(PLC(np,PL_CNTRL_A),
+ PL_SC_REM_LOOP,PL_SC_REM_LOOP) ;
+ SETMASK(PLC(np,PL_CNTRL_B),
+ PL_CONFIG_CNTRL,PL_CONFIG_CNTRL) ;
+ }
+ SETMASK(PLC(np,PL_CNTRL_B),PL_PC_JOIN,PL_PC_JOIN) ;
+ SETMASK(PLC(np,PL_CNTRL_B),PL_PC_JOIN,PL_PC_JOIN) ;
+ ACTIONS_DONE() ;
+ cmd = 0 ;
+ /* fall thru */
+ case PC6_JOIN :
+ switch (plc->p_state) {
+ case PS_ACTIVE:
+ /*PC88b*/
+ if (!phy->cf_join) {
+ phy->cf_join = TRUE ;
+ queue_event(smc,EVENT_CFM,CF_JOIN+np) ; ;
+ }
+ if (cmd == PC_JOIN)
+ GO_STATE(PC8_ACTIVE) ;
+ /*PC82*/
+ if (cmd == PC_TRACE) {
+ GO_STATE(PC2_TRACE) ;
+ break ;
+ }
+ break ;
+ }
+ break ;
+
+ case PC7_VERIFY :
+ break ;
+
+ case ACTIONS(PC8_ACTIVE) :
+ /*
+ * start LEM for SMT
+ */
+ sm_ph_lem_start(smc,(int)phy->np,LCT_LEM_MAX) ;
+
+ phy->tr_flag = FALSE ;
+ mib->fddiPORTConnectState = PCM_ACTIVE ;
+
+ /* Set the active interrupt mask register */
+ outpw(PLC(np,PL_INTR_MASK),plc_imsk_act) ;
+
+ ACTIONS_DONE() ;
+ break ;
+ case PC8_ACTIVE :
+ /*PC81 is done by PL_TNE_EXPIRED irq */
+ /*PC82*/
+ if (cmd == PC_TRACE) {
+ GO_STATE(PC2_TRACE) ;
+ break ;
+ }
+ /*PC88c: is done by TRACE_PROP irq */
+
+ break ;
+ case ACTIONS(PC9_MAINT) :
+ stop_pcm_timer0(smc,phy) ;
+ CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ;
+ CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
+ CLEAR(PLC(np,PL_INTR_MASK),PL_LE_CTR) ; /* disable LEM int. */
+ sm_ph_lem_stop(smc,np) ; /* disable LEM */
+ phy->cf_loop = FALSE ;
+ phy->cf_join = FALSE ;
+ queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
+ plc_go_state(smc,np,PL_PCM_STOP) ;
+ mib->fddiPORTConnectState = PCM_DISABLED ;
+ SETMASK(PLC(np,PL_CNTRL_B),PL_MAINT,PL_MAINT) ;
+ sm_ph_linestate(smc,np,(int) MIB2LS(mib->fddiPORTMaint_LS)) ;
+ outpw(PLC(np,PL_CNTRL_A),PL_SC_BYPASS) ;
+ ACTIONS_DONE() ;
+ break ;
+ case PC9_MAINT :
+ DB_PCMN(1,"PCM %c : MAINT\n",phy->phy_name,0) ;
+ /*PC90*/
+ if (cmd == PC_ENABLE) {
+ GO_STATE(PC0_OFF) ;
+ break ;
+ }
+ break ;
+
+ default:
+ SMT_PANIC(smc,SMT_E0118, SMT_E0118_MSG) ;
+ break ;
+ }
+}
+
+/*
+ * force line state on a PHY output (only in MAINT state)
+ */
+static void sm_ph_linestate(smc,phy,ls)
+struct s_smc *smc ;
+int phy;
+int ls;
+{
+ int cntrl ;
+
+ SK_UNUSED(smc) ;
+
+ cntrl = (inpw(PLC(phy,PL_CNTRL_B)) & ~PL_MAINT_LS) |
+ PL_PCM_STOP | PL_MAINT ;
+ switch(ls) {
+ case PC_QLS: /* Force Quiet */
+ cntrl |= PL_M_QUI0 ;
+ break ;
+ case PC_MLS: /* Force Master */
+ cntrl |= PL_M_MASTR ;
+ break ;
+ case PC_HLS: /* Force Halt */
+ cntrl |= PL_M_HALT ;
+ break ;
+ default :
+ case PC_ILS: /* Force Idle */
+ cntrl |= PL_M_IDLE ;
+ break ;
+ case PC_LS_PDR: /* Enable repeat filter */
+ cntrl |= PL_M_TPDR ;
+ break ;
+ }
+ outpw(PLC(phy,PL_CNTRL_B),cntrl) ;
+}
+
+
+static void reset_lem_struct(phy)
+struct s_phy *phy;
+{
+ struct lem_counter *lem = &phy->lem ;
+
+ phy->mib->fddiPORTLer_Estimate = 15 ;
+ lem->lem_float_ber = 15 * 100 ;
+}
+
+/*
+ * link error monitor
+ */
+static void lem_evaluate(smc,phy)
+struct s_smc *smc ;
+struct s_phy *phy;
+{
+ int ber ;
+ u_long errors ;
+ struct lem_counter *lem = &phy->lem ;
+ struct fddi_mib_p *mib ;
+ int cond ;
+
+ mib = phy->mib ;
+
+ if (!lem->lem_on)
+ return ;
+
+ errors = inpw(PLC(((int) phy->np),PL_LINK_ERR_CTR)) ;
+ lem->lem_errors += errors ;
+ mib->fddiPORTLem_Ct += errors ;
+
+ errors = lem->lem_errors ;
+ /*
+ * calculation is called on a intervall of 8 seconds
+ * -> this means, that one error in 8 sec. is one of 8*125*10E6
+ * the same as BER = 10E-9
+ * Please note:
+ * -> 9 errors in 8 seconds mean:
+ * BER = 9 * 10E-9 and this is
+ * < 10E-8, so the limit of 10E-8 is not reached!
+ */
+
+ if (!errors) ber = 15 ;
+ else if (errors <= 9) ber = 9 ;
+ else if (errors <= 99) ber = 8 ;
+ else if (errors <= 999) ber = 7 ;
+ else if (errors <= 9999) ber = 6 ;
+ else if (errors <= 99999) ber = 5 ;
+ else if (errors <= 999999) ber = 4 ;
+ else if (errors <= 9999999) ber = 3 ;
+ else if (errors <= 99999999) ber = 2 ;
+ else if (errors <= 999999999) ber = 1 ;
+ else ber = 0 ;
+
+ /*
+ * weighted average
+ */
+ ber *= 100 ;
+ lem->lem_float_ber = lem->lem_float_ber * 7 + ber * 3 ;
+ lem->lem_float_ber /= 10 ;
+ mib->fddiPORTLer_Estimate = lem->lem_float_ber / 100 ;
+ if (mib->fddiPORTLer_Estimate < 4) {
+ mib->fddiPORTLer_Estimate = 4 ;
+ }
+
+ if (lem->lem_errors) {
+ DB_PCMN(1,"LEM %c :\n",phy->np == PB? 'B' : 'A',0) ;
+ DB_PCMN(1,"errors : %ld\n",lem->lem_errors,0) ;
+ DB_PCMN(1,"sum_errors : %ld\n",mib->fddiPORTLem_Ct,0) ;
+ DB_PCMN(1,"current BER : 10E-%d\n",ber/100,0) ;
+ DB_PCMN(1,"float BER : 10E-(%d/100)\n",lem->lem_float_ber,0) ;
+ DB_PCMN(1,"avg. BER : 10E-%d\n",
+ mib->fddiPORTLer_Estimate,0) ;
+ }
+
+ lem->lem_errors = 0L ;
+
+#ifndef SLIM_SMT
+ cond = (mib->fddiPORTLer_Estimate <= mib->fddiPORTLer_Alarm) ?
+ TRUE : FALSE ;
+#ifdef SMT_EXT_CUTOFF
+ smt_ler_alarm_check(smc,phy,cond) ;
+#endif /* nSMT_EXT_CUTOFF */
+ if (cond != mib->fddiPORTLerFlag) {
+ smt_srf_event(smc,SMT_COND_PORT_LER,
+ (int) (INDEX_PORT+ phy->np) ,cond) ;
+ }
+#endif
+
+ if ( mib->fddiPORTLer_Estimate <= mib->fddiPORTLer_Cutoff) {
+ phy->pc_lem_fail = TRUE ; /* flag */
+ mib->fddiPORTLem_Reject_Ct++ ;
+ /*
+ * "forgive 10e-2" if we cutoff so we can come
+ * up again ..
+ */
+ lem->lem_float_ber += 2*100 ;
+
+ /*PC81b*/
+#ifdef CONCENTRATOR
+ DB_PCMN(1,"PCM: LER cutoff on port %d cutoff %d\n",
+ phy->np, mib->fddiPORTLer_Cutoff) ;
+#endif
+#ifdef SMT_EXT_CUTOFF
+ smt_port_off_event(smc,phy->np);
+#else /* nSMT_EXT_CUTOFF */
+ queue_event(smc,(int)(EVENT_PCM+phy->np),PC_START) ;
+#endif /* nSMT_EXT_CUTOFF */
+ }
+}
+
+/*
+ * called by SMT to calculate LEM bit error rate
+ */
+void sm_lem_evaluate(smc)
+struct s_smc *smc ;
+{
+ int np ;
+
+ for (np = 0 ; np < NUMPHYS ; np++)
+ lem_evaluate(smc,&smc->y[np]) ;
+}
+
+static void lem_check_lct(smc,phy)
+struct s_smc *smc ;
+struct s_phy *phy ;
+{
+ struct lem_counter *lem = &phy->lem ;
+ struct fddi_mib_p *mib ;
+ int errors ;
+
+ mib = phy->mib ;
+
+ phy->pc_lem_fail = FALSE ; /* flag */
+ errors = inpw(PLC(((int)phy->np),PL_LINK_ERR_CTR)) ;
+ lem->lem_errors += errors ;
+ mib->fddiPORTLem_Ct += errors ;
+ if (lem->lem_errors) {
+ switch(phy->lc_test) {
+ case LC_SHORT:
+ if (lem->lem_errors >= smc->s.lct_short)
+ phy->pc_lem_fail = TRUE ;
+ break ;
+ case LC_MEDIUM:
+ if (lem->lem_errors >= smc->s.lct_medium)
+ phy->pc_lem_fail = TRUE ;
+ break ;
+ case LC_LONG:
+ if (lem->lem_errors >= smc->s.lct_long)
+ phy->pc_lem_fail = TRUE ;
+ break ;
+ case LC_EXTENDED:
+ if (lem->lem_errors >= smc->s.lct_extended)
+ phy->pc_lem_fail = TRUE ;
+ break ;
+ }
+ DB_PCMN(1," >>errors : %d\n",lem->lem_errors,0) ;
+ }
+ if (phy->pc_lem_fail) {
+ mib->fddiPORTLCTFail_Ct++ ;
+ mib->fddiPORTLem_Reject_Ct++ ;
+ }
+ else
+ mib->fddiPORTLCTFail_Ct = 0 ;
+}
+
+/*
+ * LEM functions
+ */
+static void sm_ph_lem_start(smc,np,threshold)
+struct s_smc *smc ;
+int np;
+int threshold;
+{
+ struct lem_counter *lem = &smc->y[np].lem ;
+
+ lem->lem_on = 1 ;
+ lem->lem_errors = 0L ;
+
+ /* Do NOT reset mib->fddiPORTLer_Estimate here. It is called too
+ * often.
+ */
+
+ outpw(PLC(np,PL_LE_THRESHOLD),threshold) ;
+ (void)inpw(PLC(np,PL_LINK_ERR_CTR)) ; /* clear error counter */
+
+ /* enable LE INT */
+ SETMASK(PLC(np,PL_INTR_MASK),PL_LE_CTR,PL_LE_CTR) ;
+}
+
+static void sm_ph_lem_stop(smc,np)
+struct s_smc *smc ;
+int np;
+{
+ struct lem_counter *lem = &smc->y[np].lem ;
+
+ lem->lem_on = 0 ;
+ CLEAR(PLC(np,PL_INTR_MASK),PL_LE_CTR) ;
+}
+
+/* ARGSUSED */
+void sm_pm_ls_latch(smc,phy,on_off)
+struct s_smc *smc ;
+int phy;
+int on_off; /* en- or disable ident. ls */
+{
+ SK_UNUSED(smc) ;
+
+ phy = phy ; on_off = on_off ;
+}
+
+
+/*
+ * PCM pseudo code
+ * receive actions are called AFTER the bit n is received,
+ * i.e. if pc_rcode_actions(5) is called, bit 6 is the next bit to be received
+ */
+
+/*
+ * PCM pseudo code 5.1 .. 6.1
+ */
+static void pc_rcode_actions(smc,bit,phy)
+struct s_smc *smc ;
+int bit;
+struct s_phy *phy;
+{
+ struct fddi_mib_p *mib ;
+
+ mib = phy->mib ;
+
+ DB_PCMN(1,"SIG rec %x %x: \n", bit,phy->r_val[bit] ) ;
+ bit++ ;
+
+ switch(bit) {
+ case 0:
+ case 1:
+ case 2:
+ break ;
+ case 3 :
+ if (phy->r_val[1] == 0 && phy->r_val[2] == 0)
+ mib->fddiPORTNeighborType = TA ;
+ else if (phy->r_val[1] == 0 && phy->r_val[2] == 1)
+ mib->fddiPORTNeighborType = TB ;
+ else if (phy->r_val[1] == 1 && phy->r_val[2] == 0)
+ mib->fddiPORTNeighborType = TS ;
+ else if (phy->r_val[1] == 1 && phy->r_val[2] == 1)
+ mib->fddiPORTNeighborType = TM ;
+ break ;
+ case 4:
+ if (mib->fddiPORTMy_Type == TM &&
+ mib->fddiPORTNeighborType == TM) {
+ DB_PCMN(1,"PCM %c : E100 withhold M-M\n",
+ phy->phy_name,0) ;
+ mib->fddiPORTPC_Withhold = PC_WH_M_M ;
+ RS_SET(smc,RS_EVENT) ;
+ }
+ else if (phy->t_val[3] || phy->r_val[3]) {
+ mib->fddiPORTPC_Withhold = PC_WH_NONE ;
+ if (mib->fddiPORTMy_Type == TM ||
+ mib->fddiPORTNeighborType == TM)
+ phy->pc_mode = PM_TREE ;
+ else
+ phy->pc_mode = PM_PEER ;
+
+ /* reevaluate the selection criteria (wc_flag) */
+ all_selection_criteria (smc);
+
+ if (phy->wc_flag) {
+ mib->fddiPORTPC_Withhold = PC_WH_PATH ;
+ }
+ }
+ else {
+ mib->fddiPORTPC_Withhold = PC_WH_OTHER ;
+ RS_SET(smc,RS_EVENT) ;
+ DB_PCMN(1,"PCM %c : E101 withhold other\n",
+ phy->phy_name,0) ;
+ }
+ phy->twisted = ((mib->fddiPORTMy_Type != TS) &&
+ (mib->fddiPORTMy_Type != TM) &&
+ (mib->fddiPORTNeighborType ==
+ mib->fddiPORTMy_Type)) ;
+ if (phy->twisted) {
+ DB_PCMN(1,"PCM %c : E102 !!! TWISTED !!!\n",
+ phy->phy_name,0) ;
+ }
+ break ;
+ case 5 :
+ break ;
+ case 6:
+ if (phy->t_val[4] || phy->r_val[4]) {
+ if ((phy->t_val[4] && phy->t_val[5]) ||
+ (phy->r_val[4] && phy->r_val[5]) )
+ phy->lc_test = LC_EXTENDED ;
+ else
+ phy->lc_test = LC_LONG ;
+ }
+ else if (phy->t_val[5] || phy->r_val[5])
+ phy->lc_test = LC_MEDIUM ;
+ else
+ phy->lc_test = LC_SHORT ;
+ switch (phy->lc_test) {
+ case LC_SHORT : /* 50ms */
+ outpw(PLC((int)phy->np,PL_LC_LENGTH), TP_LC_LENGTH ) ;
+ phy->t_next[7] = smc->s.pcm_lc_short ;
+ break ;
+ case LC_MEDIUM : /* 500ms */
+ outpw(PLC((int)phy->np,PL_LC_LENGTH), TP_LC_LONGLN ) ;
+ phy->t_next[7] = smc->s.pcm_lc_medium ;
+ break ;
+ case LC_LONG :
+ SETMASK(PLC((int)phy->np,PL_CNTRL_B),PL_LONG,PL_LONG) ;
+ phy->t_next[7] = smc->s.pcm_lc_long ;
+ break ;
+ case LC_EXTENDED :
+ SETMASK(PLC((int)phy->np,PL_CNTRL_B),PL_LONG,PL_LONG) ;
+ phy->t_next[7] = smc->s.pcm_lc_extended ;
+ break ;
+ }
+ if (phy->t_next[7] > smc->s.pcm_lc_medium) {
+ start_pcm_timer0(smc,phy->t_next[7],PC_TIMEOUT_LCT,phy);
+ }
+ DB_PCMN(1,"LCT timer = %ld us\n", phy->t_next[7], 0) ;
+ phy->t_next[9] = smc->s.pcm_t_next_9 ;
+ break ;
+ case 7:
+ if (phy->t_val[6]) {
+ phy->cf_loop = TRUE ;
+ }
+ phy->td_flag = TRUE ;
+ break ;
+ case 8:
+ if (phy->t_val[7] || phy->r_val[7]) {
+ DB_PCMN(1,"PCM %c : E103 LCT fail %s\n",
+ phy->phy_name,phy->t_val[7]? "local":"remote") ;
+ queue_event(smc,(int)(EVENT_PCM+phy->np),PC_START) ;
+ }
+ break ;
+ case 9:
+ if (phy->t_val[8] || phy->r_val[8]) {
+ if (phy->t_val[8])
+ phy->cf_loop = TRUE ;
+ phy->td_flag = TRUE ;
+ }
+ break ;
+ case 10:
+ if (phy->r_val[9]) {
+ /* neighbor intends to have MAC on output */ ;
+ mib->fddiPORTMacIndicated.R_val = TRUE ;
+ }
+ else {
+ /* neighbor does not intend to have MAC on output */ ;
+ mib->fddiPORTMacIndicated.R_val = FALSE ;
+ }
+ break ;
+ }
+}
+
+/*
+ * PCM pseudo code 5.1 .. 6.1
+ */
+static void pc_tcode_actions(smc,bit,phy)
+struct s_smc *smc ;
+const int bit;
+struct s_phy *phy;
+{
+ int np = phy->np ;
+ struct fddi_mib_p *mib ;
+
+ mib = phy->mib ;
+
+ switch(bit) {
+ case 0:
+ phy->t_val[0] = 0 ; /* no escape used */
+ break ;
+ case 1:
+ if (mib->fddiPORTMy_Type == TS || mib->fddiPORTMy_Type == TM)
+ phy->t_val[1] = 1 ;
+ else
+ phy->t_val[1] = 0 ;
+ break ;
+ case 2 :
+ if (mib->fddiPORTMy_Type == TB || mib->fddiPORTMy_Type == TM)
+ phy->t_val[2] = 1 ;
+ else
+ phy->t_val[2] = 0 ;
+ break ;
+ case 3:
+ {
+ int type,ne ;
+ int policy ;
+
+ type = mib->fddiPORTMy_Type ;
+ ne = mib->fddiPORTNeighborType ;
+ policy = smc->mib.fddiSMTConnectionPolicy ;
+
+ phy->t_val[3] = 1 ; /* Accept connection */
+ switch (type) {
+ case TA :
+ if (
+ ((policy & POLICY_AA) && ne == TA) ||
+ ((policy & POLICY_AB) && ne == TB) ||
+ ((policy & POLICY_AS) && ne == TS) ||
+ ((policy & POLICY_AM) && ne == TM) )
+ phy->t_val[3] = 0 ; /* Reject */
+ break ;
+ case TB :
+ if (
+ ((policy & POLICY_BA) && ne == TA) ||
+ ((policy & POLICY_BB) && ne == TB) ||
+ ((policy & POLICY_BS) && ne == TS) ||
+ ((policy & POLICY_BM) && ne == TM) )
+ phy->t_val[3] = 0 ; /* Reject */
+ break ;
+ case TS :
+ if (
+ ((policy & POLICY_SA) && ne == TA) ||
+ ((policy & POLICY_SB) && ne == TB) ||
+ ((policy & POLICY_SS) && ne == TS) ||
+ ((policy & POLICY_SM) && ne == TM) )
+ phy->t_val[3] = 0 ; /* Reject */
+ break ;
+ case TM :
+ if ( ne == TM ||
+ ((policy & POLICY_MA) && ne == TA) ||
+ ((policy & POLICY_MB) && ne == TB) ||
+ ((policy & POLICY_MS) && ne == TS) ||
+ ((policy & POLICY_MM) && ne == TM) )
+ phy->t_val[3] = 0 ; /* Reject */
+ break ;
+ }
+#ifndef SLIM_SMT
+ /*
+ * detect undesirable connection attempt event
+ */
+ if ( (type == TA && ne == TA ) ||
+ (type == TA && ne == TS ) ||
+ (type == TB && ne == TB ) ||
+ (type == TB && ne == TS ) ||
+ (type == TS && ne == TA ) ||
+ (type == TS && ne == TB ) ) {
+ smt_srf_event(smc,SMT_EVENT_PORT_CONNECTION,
+ (int) (INDEX_PORT+ phy->np) ,0) ;
+ }
+#endif
+ }
+ break ;
+ case 4:
+ if (mib->fddiPORTPC_Withhold == PC_WH_NONE) {
+ if (phy->pc_lem_fail) {
+ phy->t_val[4] = 1 ; /* long */
+ phy->t_val[5] = 0 ;
+ }
+ else {
+ phy->t_val[4] = 0 ;
+ if (mib->fddiPORTLCTFail_Ct > 0)
+ phy->t_val[5] = 1 ; /* medium */
+ else
+ phy->t_val[5] = 0 ; /* short */
+
+ /*
+ * Implementers choice: use medium
+ * instead of short when undesired
+ * connection attempt is made.
+ */
+ if (phy->wc_flag)
+ phy->t_val[5] = 1 ; /* medium */
+ }
+ mib->fddiPORTConnectState = PCM_CONNECTING ;
+ }
+ else {
+ mib->fddiPORTConnectState = PCM_STANDBY ;
+ phy->t_val[4] = 1 ; /* extended */
+ phy->t_val[5] = 1 ;
+ }
+ break ;
+ case 5:
+ break ;
+ case 6:
+ /* we do NOT have a MAC for LCT */
+ phy->t_val[6] = 0 ;
+ break ;
+ case 7:
+ phy->cf_loop = FALSE ;
+ lem_check_lct(smc,phy) ;
+ if (phy->pc_lem_fail) {
+ DB_PCMN(1,"PCM %c : E104 LCT failed\n",
+ phy->phy_name,0) ;
+ phy->t_val[7] = 1 ;
+ }
+ else
+ phy->t_val[7] = 0 ;
+ break ;
+ case 8:
+ phy->t_val[8] = 0 ; /* Don't request MAC loopback */
+ break ;
+ case 9:
+ phy->cf_loop = 0 ;
+ if ((mib->fddiPORTPC_Withhold != PC_WH_NONE) ||
+ ((smc->s.sas == SMT_DAS) && (phy->wc_flag))) {
+ queue_event(smc,EVENT_PCM+np,PC_START) ;
+ break ;
+ }
+ phy->t_val[9] = FALSE ;
+ switch (smc->s.sas) {
+ case SMT_DAS :
+ /*
+ * MAC intended on output
+ */
+ if (phy->pc_mode == PM_TREE) {
+ if ((np == PB) || ((np == PA) &&
+ (smc->y[PB].mib->fddiPORTConnectState !=
+ PCM_ACTIVE)))
+ phy->t_val[9] = TRUE ;
+ }
+ else {
+ if (np == PB)
+ phy->t_val[9] = TRUE ;
+ }
+ break ;
+ case SMT_SAS :
+ if (np == PS)
+ phy->t_val[9] = TRUE ;
+ break ;
+#ifdef CONCENTRATOR
+ case SMT_NAC :
+ /*
+ * MAC intended on output
+ */
+ if (np == PB)
+ phy->t_val[9] = TRUE ;
+ break ;
+#endif
+ }
+ mib->fddiPORTMacIndicated.T_val = phy->t_val[9] ;
+ break ;
+ }
+ DB_PCMN(1,"SIG snd %x %x: \n", bit,phy->t_val[bit] ) ;
+}
+
+/*
+ * return status twisted (called by SMT)
+ */
+int pcm_status_twisted(smc)
+struct s_smc *smc ;
+{
+ int twist = 0 ;
+ if (smc->s.sas != SMT_DAS)
+ return(0) ;
+ if (smc->y[PA].twisted && (smc->y[PA].mib->fddiPORTPCMState == PC8_ACTIVE))
+ twist |= 1 ;
+ if (smc->y[PB].twisted && (smc->y[PB].mib->fddiPORTPCMState == PC8_ACTIVE))
+ twist |= 2 ;
+ return(twist) ;
+}
+
+/*
+ * return status (called by SMT)
+ * type
+ * state
+ * remote phy type
+ * remote mac yes/no
+ */
+void pcm_status_state(smc,np,type,state,remote,mac)
+struct s_smc *smc ;
+int np;
+int *type;
+int *state;
+int *remote;
+int *mac;
+{
+ struct s_phy *phy = &smc->y[np] ;
+ struct fddi_mib_p *mib ;
+
+ mib = phy->mib ;
+
+ /* remote PHY type and MAC - set only if active */
+ *mac = 0 ;
+ *type = mib->fddiPORTMy_Type ; /* our PHY type */
+ *state = mib->fddiPORTConnectState ;
+ *remote = mib->fddiPORTNeighborType ;
+
+ switch(mib->fddiPORTPCMState) {
+ case PC8_ACTIVE :
+ *mac = mib->fddiPORTMacIndicated.R_val ;
+ break ;
+ }
+}
+
+/*
+ * return rooted station status (called by SMT)
+ */
+int pcm_rooted_station(smc)
+struct s_smc *smc ;
+{
+ int n ;
+
+ for (n = 0 ; n < NUMPHYS ; n++) {
+ if (smc->y[n].mib->fddiPORTPCMState == PC8_ACTIVE &&
+ smc->y[n].mib->fddiPORTNeighborType == TM)
+ return(0) ;
+ }
+ return(1) ;
+}
+
+/*
+ * Interrupt actions for PLC & PCM events
+ */
+void plc_irq(smc,np,cmd)
+struct s_smc *smc ;
+int np; /* PHY index */
+unsigned int cmd;
+{
+ struct s_phy *phy = &smc->y[np] ;
+ struct s_plc *plc = &phy->plc ;
+ int n ;
+#ifdef SUPERNET_3
+ int corr_mask ;
+#endif /* SUPERNET_3 */
+ int i ;
+
+ if (np >= smc->s.numphys) {
+ plc->soft_err++ ;
+ return ;
+ }
+ if (cmd & PL_EBUF_ERR) { /* elastic buff. det. over-|underflow*/
+ /*
+ * Check whether the SRF Condition occured.
+ */
+ if (!plc->ebuf_cont && phy->mib->fddiPORTPCMState == PC8_ACTIVE){
+ /*
+ * This is the real Elasticity Error.
+ * More than one in a row are treated as a
+ * single one.
+ * Only count this in the active state.
+ */
+ phy->mib->fddiPORTEBError_Ct ++ ;
+
+ }
+
+ plc->ebuf_err++ ;
+ if (plc->ebuf_cont <= 1000) {
+ /*
+ * Prevent counter from being wrapped after
+ * hanging years in that interrupt.
+ */
+ plc->ebuf_cont++ ; /* Ebuf continous error */
+ }
+
+#ifdef SUPERNET_3
+ if (plc->ebuf_cont == 1000 &&
+ ((inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK) ==
+ PLC_REV_SN3)) {
+ /*
+ * This interrupt remeained high for at least
+ * 1000 consecutive interrupt calls.
+ *
+ * This is caused by a hardware error of the
+ * ORION part of the Supernet III chipset.
+ *
+ * Disable this bit from the mask.
+ */
+ corr_mask = (plc_imsk_na & ~PL_EBUF_ERR) ;
+ outpw(PLC(np,PL_INTR_MASK),corr_mask);
+
+ /*
+ * Disconnect from the ring.
+ * Call the driver with the reset indication.
+ */
+ queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
+
+ /*
+ * Make an error log entry.
+ */
+ SMT_ERR_LOG(smc,SMT_E0136, SMT_E0136_MSG) ;
+
+ /*
+ * Indicate the Reset.
+ */
+ drv_reset_indication(smc) ;
+ }
+#endif /* SUPERNET_3 */
+ } else {
+ /* Reset the continous error variable */
+ plc->ebuf_cont = 0 ; /* reset Ebuf continous error */
+ }
+ if (cmd & PL_PHYINV) { /* physical layer invalid signal */
+ plc->phyinv++ ;
+ }
+ if (cmd & PL_VSYM_CTR) { /* violation symbol counter has incr.*/
+ plc->vsym_ctr++ ;
+ }
+ if (cmd & PL_MINI_CTR) { /* dep. on PLC_CNTRL_A's MINI_CTR_INT*/
+ plc->mini_ctr++ ;
+ }
+ if (cmd & PL_LE_CTR) { /* link error event counter */
+ int j ;
+
+ /*
+ * note: PL_LINK_ERR_CTR MUST be read to clear it
+ */
+ j = inpw(PLC(np,PL_LE_THRESHOLD)) ;
+ i = inpw(PLC(np,PL_LINK_ERR_CTR)) ;
+
+ if (i < j) {
+ /* wrapped around */
+ i += 256 ;
+ }
+
+ if (phy->lem.lem_on) {
+ /* Note: Lem errors shall only be counted when
+ * link is ACTIVE or LCT is active.
+ */
+ phy->lem.lem_errors += i ;
+ phy->mib->fddiPORTLem_Ct += i ;
+ }
+ }
+ if (cmd & PL_TPC_EXPIRED) { /* TPC timer reached zero */
+ if (plc->p_state == PS_LCT) {
+ /*
+ * end of LCT
+ */
+ ;
+ }
+ plc->tpc_exp++ ;
+ }
+ if (cmd & PL_LS_MATCH) { /* LS == LS in PLC_CNTRL_B's MATCH_LS*/
+ switch (inpw(PLC(np,PL_CNTRL_B)) & PL_MATCH_LS) {
+ case PL_I_IDLE : phy->curr_ls = PC_ILS ; break ;
+ case PL_I_HALT : phy->curr_ls = PC_HLS ; break ;
+ case PL_I_MASTR : phy->curr_ls = PC_MLS ; break ;
+ case PL_I_QUIET : phy->curr_ls = PC_QLS ; break ;
+ }
+ }
+ if (cmd & PL_PCM_BREAK) { /* PCM has entered the BREAK state */
+ int reason;
+
+ reason = inpw(PLC(np,PL_STATUS_B)) & PL_BREAK_REASON ;
+
+ switch (reason) {
+ case PL_B_PCS : plc->b_pcs++ ; break ;
+ case PL_B_TPC : plc->b_tpc++ ; break ;
+ case PL_B_TNE : plc->b_tne++ ; break ;
+ case PL_B_QLS : plc->b_qls++ ; break ;
+ case PL_B_ILS : plc->b_ils++ ; break ;
+ case PL_B_HLS : plc->b_hls++ ; break ;
+ }
+
+ /*jd 05-Aug-1999 changed: Bug #10419 */
+ DB_PCMN(1,"PLC %d: MDcF = %x\n", np, smc->e.DisconnectFlag);
+ if (smc->e.DisconnectFlag == FALSE) {
+ DB_PCMN(1,"PLC %d: restart (reason %x)\n", np, reason);
+ queue_event(smc,EVENT_PCM+np,PC_START) ;
+ }
+ else {
+ DB_PCMN(1,"PLC %d: NO!! restart (reason %x)\n", np, reason);
+ }
+ return ;
+ }
+ /*
+ * If both CODE & ENABLE are set ignore enable
+ */
+ if (cmd & PL_PCM_CODE) { /* receive last sign.-bit | LCT complete */
+ queue_event(smc,EVENT_PCM+np,PC_SIGNAL) ;
+ n = inpw(PLC(np,PL_RCV_VECTOR)) ;
+ for (i = 0 ; i < plc->p_bits ; i++) {
+ phy->r_val[plc->p_start+i] = n & 1 ;
+ n >>= 1 ;
+ }
+ }
+ else if (cmd & PL_PCM_ENABLED) { /* asserted SC_JOIN, scrub.completed*/
+ queue_event(smc,EVENT_PCM+np,PC_JOIN) ;
+ }
+ if (cmd & PL_TRACE_PROP) { /* MLS while PC8_ACTIV || PC2_TRACE */
+ /*PC22b*/
+ if (!phy->tr_flag) {
+ DB_PCMN(1,"PCM : irq TRACE_PROP %d %d\n",
+ np,smc->mib.fddiSMTECMState) ;
+ phy->tr_flag = TRUE ;
+ smc->e.trace_prop |= ENTITY_BIT(ENTITY_PHY(np)) ;
+ queue_event(smc,EVENT_ECM,EC_TRACE_PROP) ;
+ }
+ }
+ /*
+ * filter PLC glitch ???
+ * QLS || HLS only while in PC2_TRACE state
+ */
+ if ((cmd & PL_SELF_TEST) && (phy->mib->fddiPORTPCMState == PC2_TRACE)) {
+ /*PC22a*/
+ if (smc->e.path_test == PT_PASSED) {
+ DB_PCMN(1,"PCM : state = %s %d\n", get_pcmstate(smc,np),
+ phy->mib->fddiPORTPCMState) ;
+
+ smc->e.path_test = PT_PENDING ;
+ queue_event(smc,EVENT_ECM,EC_PATH_TEST) ;
+ }
+ }
+ if (cmd & PL_TNE_EXPIRED) { /* TNE: length of noise events */
+ /* break_required (TNE > NS_Max) */
+ if (phy->mib->fddiPORTPCMState == PC8_ACTIVE) {
+ if (!phy->tr_flag) {
+ DB_PCMN(1,"PCM %c : PC81 %s\n",phy->phy_name,"NSE");
+ queue_event(smc,EVENT_PCM+np,PC_START) ;
+ return ;
+ }
+ }
+ }
+#if 0
+ if (cmd & PL_NP_ERR) { /* NP has requested to r/w an inv reg*/
+ /*
+ * It's a bug by AMD
+ */
+ plc->np_err++ ;
+ }
+ /* pin inactiv (GND) */
+ if (cmd & PL_PARITY_ERR) { /* p. error dedected on TX9-0 inp */
+ plc->parity_err++ ;
+ }
+ if (cmd & PL_LSDO) { /* carrier detected */
+ ;
+ }
+#endif
+}
+
+void pcm_set_lct_short(smc,n)
+struct s_smc *smc ;
+int n ;
+{
+ if (n <= 0 || n > 1000)
+ return ;
+ smc->s.lct_short = n ;
+}
+
+#ifdef DEBUG
+/*
+ * fill state struct
+ */
+void pcm_get_state(smc,state)
+struct s_smc *smc ;
+struct smt_state *state ;
+{
+ struct s_phy *phy ;
+ struct pcm_state *pcs ;
+ int i ;
+ int ii ;
+ short rbits ;
+ short tbits ;
+ struct fddi_mib_p *mib ;
+
+ for (i = 0, phy = smc->y, pcs = state->pcm_state ; i < NUMPHYS ;
+ i++ , phy++, pcs++ ) {
+ mib = phy->mib ;
+ pcs->pcm_type = (u_char) mib->fddiPORTMy_Type ;
+ pcs->pcm_state = (u_char) mib->fddiPORTPCMState ;
+ pcs->pcm_mode = phy->pc_mode ;
+ pcs->pcm_neighbor = (u_char) mib->fddiPORTNeighborType ;
+ pcs->pcm_bsf = mib->fddiPORTBS_Flag ;
+ pcs->pcm_lsf = phy->ls_flag ;
+ pcs->pcm_lct_fail = (u_char) mib->fddiPORTLCTFail_Ct ;
+ pcs->pcm_ls_rx = LS2MIB(sm_pm_get_ls(smc,i)) ;
+ for (ii = 0, rbits = tbits = 0 ; ii < NUMBITS ; ii++) {
+ rbits <<= 1 ;
+ tbits <<= 1 ;
+ if (phy->r_val[NUMBITS-1-ii])
+ rbits |= 1 ;
+ if (phy->t_val[NUMBITS-1-ii])
+ tbits |= 1 ;
+ }
+ pcs->pcm_r_val = rbits ;
+ pcs->pcm_t_val = tbits ;
+ }
+}
+
+int get_pcm_state(smc,np)
+struct s_smc *smc ;
+int np;
+{
+ int pcs ;
+
+ SK_UNUSED(smc) ;
+
+ switch (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_STATE) {
+ case PL_PC0 : pcs = PC_STOP ; break ;
+ case PL_PC1 : pcs = PC_START ; break ;
+ case PL_PC2 : pcs = PC_TRACE ; break ;
+ case PL_PC3 : pcs = PC_SIGNAL ; break ;
+ case PL_PC4 : pcs = PC_SIGNAL ; break ;
+ case PL_PC5 : pcs = PC_SIGNAL ; break ;
+ case PL_PC6 : pcs = PC_JOIN ; break ;
+ case PL_PC7 : pcs = PC_JOIN ; break ;
+ case PL_PC8 : pcs = PC_ENABLE ; break ;
+ case PL_PC9 : pcs = PC_MAINT ; break ;
+ default : pcs = PC_DISABLE ; break ;
+ }
+ return(pcs) ;
+}
+
+char *get_linestate(smc,np)
+struct s_smc *smc ;
+int np;
+{
+ char *ls = "" ;
+
+ SK_UNUSED(smc) ;
+
+ switch (inpw(PLC(np,PL_STATUS_A)) & PL_LINE_ST) {
+ case PL_L_NLS : ls = "NOISE" ; break ;
+ case PL_L_ALS : ls = "ACTIV" ; break ;
+ case PL_L_UND : ls = "UNDEF" ; break ;
+ case PL_L_ILS4: ls = "ILS 4" ; break ;
+ case PL_L_QLS : ls = "QLS" ; break ;
+ case PL_L_MLS : ls = "MLS" ; break ;
+ case PL_L_HLS : ls = "HLS" ; break ;
+ case PL_L_ILS16:ls = "ILS16" ; break ;
+#ifdef lint
+ default: ls = "unknown" ; break ;
+#endif
+ }
+ return(ls) ;
+}
+
+char *get_pcmstate(smc,np)
+struct s_smc *smc ;
+int np;
+{
+ char *pcs ;
+
+ SK_UNUSED(smc) ;
+
+ switch (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_STATE) {
+ case PL_PC0 : pcs = "OFF" ; break ;
+ case PL_PC1 : pcs = "BREAK" ; break ;
+ case PL_PC2 : pcs = "TRACE" ; break ;
+ case PL_PC3 : pcs = "CONNECT"; break ;
+ case PL_PC4 : pcs = "NEXT" ; break ;
+ case PL_PC5 : pcs = "SIGNAL" ; break ;
+ case PL_PC6 : pcs = "JOIN" ; break ;
+ case PL_PC7 : pcs = "VERIFY" ; break ;
+ case PL_PC8 : pcs = "ACTIV" ; break ;
+ case PL_PC9 : pcs = "MAINT" ; break ;
+ default : pcs = "UNKNOWN" ; break ;
+ }
+ return(pcs) ;
+}
+
+void list_phy(smc)
+struct s_smc *smc ;
+{
+ struct s_plc *plc ;
+ int np ;
+
+ for (np = 0 ; np < NUMPHYS ; np++) {
+ plc = &smc->y[np].plc ;
+ printf("PHY %d:\tERRORS\t\t\tBREAK_REASONS\t\tSTATES:\n",np) ;
+ printf("\tsoft_error: %ld \t\tPC_Start : %ld\n",
+ plc->soft_err,plc->b_pcs);
+ printf("\tparity_err: %ld \t\tTPC exp. : %ld\t\tLine: %s\n",
+ plc->parity_err,plc->b_tpc,get_linestate(smc,np)) ;
+ printf("\tebuf_error: %ld \t\tTNE exp. : %ld\n",
+ plc->ebuf_err,plc->b_tne) ;
+ printf("\tphyinvalid: %ld \t\tQLS det. : %ld\t\tPCM : %s\n",
+ plc->phyinv,plc->b_qls,get_pcmstate(smc,np)) ;
+ printf("\tviosym_ctr: %ld \t\tILS det. : %ld\n",
+ plc->vsym_ctr,plc->b_ils) ;
+ printf("\tmingap_ctr: %ld \t\tHLS det. : %ld\n",
+ plc->mini_ctr,plc->b_hls) ;
+ printf("\tnodepr_err: %ld\n",plc->np_err) ;
+ printf("\tTPC_exp : %ld\n",plc->tpc_exp) ;
+ printf("\tLEM_err : %ld\n",smc->y[np].lem.lem_errors) ;
+ }
+}
+
+
+#ifdef CONCENTRATOR
+void pcm_lem_dump(smc)
+struct s_smc *smc ;
+{
+ int i ;
+ struct s_phy *phy ;
+ struct fddi_mib_p *mib ;
+
+ char *entostring() ;
+
+ printf("PHY errors BER\n") ;
+ printf("----------------------\n") ;
+ for (i = 0,phy = smc->y ; i < NUMPHYS ; i++,phy++) {
+ if (!plc_is_installed(smc,i))
+ continue ;
+ mib = phy->mib ;
+ printf("%s\t%ld\t10E-%d\n",
+ entostring(smc,ENTITY_PHY(i)),
+ mib->fddiPORTLem_Ct,
+ mib->fddiPORTLer_Estimate) ;
+ }
+}
+#endif
+#endif
diff --git a/drivers/net/skfp/pmf.c b/drivers/net/skfp/pmf.c
new file mode 100644
index 000000000..d53355bac
--- /dev/null
+++ b/drivers/net/skfp/pmf.c
@@ -0,0 +1,1701 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ Parameter Management Frame processing for SMT 7.2
+*/
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/smt_p.h"
+
+#define KERNEL
+#include "h/smtstate.h"
+
+#ifndef SLIM_SMT
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)pmf.c 1.37 97/08/04 (C) SK " ;
+#endif
+
+static int smt_authorize() ;
+static int smt_check_set_count() ;
+static const struct s_p_tab *smt_get_ptab() ;
+static int smt_mib_phys() ;
+int smt_set_para() ;
+void smt_add_para() ;
+
+#define MOFFSS(e) ((int)&(((struct fddi_mib *)0)->e))
+#define MOFFSA(e) ((int) (((struct fddi_mib *)0)->e))
+
+#define MOFFMS(e) ((int)&(((struct fddi_mib_m *)0)->e))
+#define MOFFMA(e) ((int) (((struct fddi_mib_m *)0)->e))
+
+#define MOFFAS(e) ((int)&(((struct fddi_mib_a *)0)->e))
+#define MOFFAA(e) ((int) (((struct fddi_mib_a *)0)->e))
+
+#define MOFFPS(e) ((int)&(((struct fddi_mib_p *)0)->e))
+#define MOFFPA(e) ((int) (((struct fddi_mib_p *)0)->e))
+
+
+#define AC_G 0x01 /* Get */
+#define AC_GR 0x02 /* Get/Set */
+#define AC_S 0x04 /* Set */
+#define AC_NA 0x08
+#define AC_GROUP 0x10 /* Group */
+#define MS2BCLK(x) ((x)*12500L)
+/*
+ F LFag (byte)
+ B byte
+ S u_short 16 bit
+ C Counter 32 bit
+ L Long 32 bit
+ T Timer_2 32 bit
+ P TimeStamp ;
+ A LongAddress (6 byte)
+ E Enum 16 bit
+ R ResId 16 Bit
+*/
+static const struct s_p_tab {
+ u_short p_num ; /* parameter code */
+ u_char p_access ; /* access rights */
+ u_short p_offset ; /* offset in mib */
+ char p_swap[3] ; /* format string */
+} p_tab[] = {
+ /* StationIdGrp */
+ { SMT_P100A,AC_GROUP } ,
+ { SMT_P100B,AC_G, MOFFSS(fddiSMTStationId), "8" } ,
+ { SMT_P100D,AC_G, MOFFSS(fddiSMTOpVersionId), "S" } ,
+ { SMT_P100E,AC_G, MOFFSS(fddiSMTHiVersionId), "S" } ,
+ { SMT_P100F,AC_G, MOFFSS(fddiSMTLoVersionId), "S" } ,
+ { SMT_P1010,AC_G, MOFFSA(fddiSMTManufacturerData), "D" } ,
+ { SMT_P1011,AC_GR, MOFFSA(fddiSMTUserData), "D" } ,
+ { SMT_P1012,AC_G, MOFFSS(fddiSMTMIBVersionId), "S" } ,
+
+ /* StationConfigGrp */
+ { SMT_P1014,AC_GROUP } ,
+ { SMT_P1015,AC_G, MOFFSS(fddiSMTMac_Ct), "B" } ,
+ { SMT_P1016,AC_G, MOFFSS(fddiSMTNonMaster_Ct), "B" } ,
+ { SMT_P1017,AC_G, MOFFSS(fddiSMTMaster_Ct), "B" } ,
+ { SMT_P1018,AC_G, MOFFSS(fddiSMTAvailablePaths), "B" } ,
+ { SMT_P1019,AC_G, MOFFSS(fddiSMTConfigCapabilities),"S" } ,
+ { SMT_P101A,AC_GR, MOFFSS(fddiSMTConfigPolicy), "wS" } ,
+ { SMT_P101B,AC_GR, MOFFSS(fddiSMTConnectionPolicy),"wS" } ,
+ { SMT_P101D,AC_GR, MOFFSS(fddiSMTTT_Notify), "wS" } ,
+ { SMT_P101E,AC_GR, MOFFSS(fddiSMTStatRptPolicy), "bB" } ,
+ { SMT_P101F,AC_GR, MOFFSS(fddiSMTTrace_MaxExpiration),"lL" } ,
+ { SMT_P1020,AC_G, MOFFSA(fddiSMTPORTIndexes), "II" } ,
+ { SMT_P1021,AC_G, MOFFSS(fddiSMTMACIndexes), "I" } ,
+ { SMT_P1022,AC_G, MOFFSS(fddiSMTBypassPresent), "F" } ,
+
+ /* StatusGrp */
+ { SMT_P1028,AC_GROUP } ,
+ { SMT_P1029,AC_G, MOFFSS(fddiSMTECMState), "E" } ,
+ { SMT_P102A,AC_G, MOFFSS(fddiSMTCF_State), "E" } ,
+ { SMT_P102C,AC_G, MOFFSS(fddiSMTRemoteDisconnectFlag),"F" } ,
+ { SMT_P102D,AC_G, MOFFSS(fddiSMTStationStatus), "E" } ,
+ { SMT_P102E,AC_G, MOFFSS(fddiSMTPeerWrapFlag), "F" } ,
+
+ /* MIBOperationGrp */
+ { SMT_P1032,AC_GROUP } ,
+ { SMT_P1033,AC_G, MOFFSA(fddiSMTTimeStamp),"P" } ,
+ { SMT_P1034,AC_G, MOFFSA(fddiSMTTransitionTimeStamp),"P" } ,
+ /* NOTE : SMT_P1035 is already swapped ! SMT_P_SETCOUNT */
+ { SMT_P1035,AC_G, MOFFSS(fddiSMTSetCount),"4P" } ,
+ { SMT_P1036,AC_G, MOFFSS(fddiSMTLastSetStationId),"8" } ,
+
+ { SMT_P103C,AC_S, 0, "wS" } ,
+
+ /*
+ * PRIVATE EXTENSIONS
+ * only accessable locally to get/set passwd
+ */
+ { SMT_P10F0,AC_GR, MOFFSA(fddiPRPMFPasswd), "8" } ,
+ { SMT_P10F1,AC_GR, MOFFSS(fddiPRPMFStation), "8" } ,
+#ifdef ESS
+ { SMT_P10F2,AC_GR, MOFFSS(fddiESSPayload), "lL" } ,
+ { SMT_P10F3,AC_GR, MOFFSS(fddiESSOverhead), "lL" } ,
+ { SMT_P10F4,AC_GR, MOFFSS(fddiESSMaxTNeg), "lL" } ,
+ { SMT_P10F5,AC_GR, MOFFSS(fddiESSMinSegmentSize), "lL" } ,
+ { SMT_P10F6,AC_GR, MOFFSS(fddiESSCategory), "lL" } ,
+ { SMT_P10F7,AC_GR, MOFFSS(fddiESSSynchTxMode), "wS" } ,
+#endif
+#ifdef SBA
+ { SMT_P10F8,AC_GR, MOFFSS(fddiSBACommand), "bF" } ,
+ { SMT_P10F9,AC_GR, MOFFSS(fddiSBAAvailable), "bF" } ,
+#endif
+ /* MAC Attributes */
+ { SMT_P200A,AC_GROUP } ,
+ { SMT_P200B,AC_G, MOFFMS(fddiMACFrameStatusFunctions),"S" } ,
+ { SMT_P200D,AC_G, MOFFMS(fddiMACT_MaxCapabilitiy),"T" } ,
+ { SMT_P200E,AC_G, MOFFMS(fddiMACTVXCapabilitiy),"T" } ,
+
+ /* ConfigGrp */
+ { SMT_P2014,AC_GROUP } ,
+ { SMT_P2016,AC_G, MOFFMS(fddiMACAvailablePaths), "B" } ,
+ { SMT_P2017,AC_G, MOFFMS(fddiMACCurrentPath), "S" } ,
+ { SMT_P2018,AC_G, MOFFMS(fddiMACUpstreamNbr), "A" } ,
+ { SMT_P2019,AC_G, MOFFMS(fddiMACDownstreamNbr), "A" } ,
+ { SMT_P201A,AC_G, MOFFMS(fddiMACOldUpstreamNbr), "A" } ,
+ { SMT_P201B,AC_G, MOFFMS(fddiMACOldDownstreamNbr),"A" } ,
+ { SMT_P201D,AC_G, MOFFMS(fddiMACDupAddressTest), "E" } ,
+ { SMT_P2020,AC_GR, MOFFMS(fddiMACRequestedPaths), "wS" } ,
+ { SMT_P2021,AC_G, MOFFMS(fddiMACDownstreamPORTType),"E" } ,
+ { SMT_P2022,AC_G, MOFFMS(fddiMACIndex), "S" } ,
+
+ /* AddressGrp */
+ { SMT_P2028,AC_GROUP } ,
+ { SMT_P2029,AC_G, MOFFMS(fddiMACSMTAddress), "A" } ,
+
+ /* OperationGrp */
+ { SMT_P2032,AC_GROUP } ,
+ { SMT_P2033,AC_G, MOFFMS(fddiMACT_Req), "T" } ,
+ { SMT_P2034,AC_G, MOFFMS(fddiMACT_Neg), "T" } ,
+ { SMT_P2035,AC_G, MOFFMS(fddiMACT_Max), "T" } ,
+ { SMT_P2036,AC_G, MOFFMS(fddiMACTvxValue), "T" } ,
+ { SMT_P2038,AC_G, MOFFMS(fddiMACT_Pri0), "T" } ,
+ { SMT_P2039,AC_G, MOFFMS(fddiMACT_Pri1), "T" } ,
+ { SMT_P203A,AC_G, MOFFMS(fddiMACT_Pri2), "T" } ,
+ { SMT_P203B,AC_G, MOFFMS(fddiMACT_Pri3), "T" } ,
+ { SMT_P203C,AC_G, MOFFMS(fddiMACT_Pri4), "T" } ,
+ { SMT_P203D,AC_G, MOFFMS(fddiMACT_Pri5), "T" } ,
+ { SMT_P203E,AC_G, MOFFMS(fddiMACT_Pri6), "T" } ,
+
+
+ /* CountersGrp */
+ { SMT_P2046,AC_GROUP } ,
+ { SMT_P2047,AC_G, MOFFMS(fddiMACFrame_Ct), "C" } ,
+ { SMT_P2048,AC_G, MOFFMS(fddiMACCopied_Ct), "C" } ,
+ { SMT_P2049,AC_G, MOFFMS(fddiMACTransmit_Ct), "C" } ,
+ { SMT_P204A,AC_G, MOFFMS(fddiMACToken_Ct), "C" } ,
+ { SMT_P2051,AC_G, MOFFMS(fddiMACError_Ct), "C" } ,
+ { SMT_P2052,AC_G, MOFFMS(fddiMACLost_Ct), "C" } ,
+ { SMT_P2053,AC_G, MOFFMS(fddiMACTvxExpired_Ct), "C" } ,
+ { SMT_P2054,AC_G, MOFFMS(fddiMACNotCopied_Ct), "C" } ,
+ { SMT_P2056,AC_G, MOFFMS(fddiMACRingOp_Ct), "C" } ,
+
+ /* FrameErrorConditionGrp */
+ { SMT_P205A,AC_GROUP } ,
+ { SMT_P205F,AC_GR, MOFFMS(fddiMACFrameErrorThreshold),"wS" } ,
+ { SMT_P2060,AC_G, MOFFMS(fddiMACFrameErrorRatio), "S" } ,
+
+ /* NotCopiedConditionGrp */
+ { SMT_P2064,AC_GROUP } ,
+ { SMT_P2067,AC_GR, MOFFMS(fddiMACNotCopiedThreshold),"wS" } ,
+ { SMT_P2069,AC_G, MOFFMS(fddiMACNotCopiedRatio), "S" } ,
+
+ /* StatusGrp */
+ { SMT_P206E,AC_GROUP } ,
+ { SMT_P206F,AC_G, MOFFMS(fddiMACRMTState), "S" } ,
+ { SMT_P2070,AC_G, MOFFMS(fddiMACDA_Flag), "F" } ,
+ { SMT_P2071,AC_G, MOFFMS(fddiMACUNDA_Flag), "F" } ,
+ { SMT_P2072,AC_G, MOFFMS(fddiMACFrameErrorFlag), "F" } ,
+ { SMT_P2073,AC_G, MOFFMS(fddiMACNotCopiedFlag), "F" } ,
+ { SMT_P2074,AC_G, MOFFMS(fddiMACMA_UnitdataAvailable),"F" } ,
+ { SMT_P2075,AC_G, MOFFMS(fddiMACHardwarePresent), "F" } ,
+ { SMT_P2076,AC_GR, MOFFMS(fddiMACMA_UnitdataEnable),"bF" } ,
+
+ /*
+ * PRIVATE EXTENSIONS
+ * only accessable locally to get/set TMIN
+ */
+ { SMT_P20F0,AC_NA } ,
+ { SMT_P20F1,AC_GR, MOFFMS(fddiMACT_Min), "lT" } ,
+
+ /* Path Attributes */
+ /*
+ * DON't swap 320B,320F,3210: they are already swapped in swap_para()
+ */
+ { SMT_P320A,AC_GROUP } ,
+ { SMT_P320B,AC_G, MOFFAS(fddiPATHIndex), "r" } ,
+ { SMT_P320F,AC_GR, MOFFAS(fddiPATHSbaPayload), "l4" } ,
+ { SMT_P3210,AC_GR, MOFFAS(fddiPATHSbaOverhead), "l4" } ,
+ /* fddiPATHConfiguration */
+ { SMT_P3212,AC_G, 0, "" } ,
+ { SMT_P3213,AC_GR, MOFFAS(fddiPATHT_Rmode), "lT" } ,
+ { SMT_P3214,AC_GR, MOFFAS(fddiPATHSbaAvailable), "lL" } ,
+ { SMT_P3215,AC_GR, MOFFAS(fddiPATHTVXLowerBound), "lT" } ,
+ { SMT_P3216,AC_GR, MOFFAS(fddiPATHT_MaxLowerBound),"lT" } ,
+ { SMT_P3217,AC_GR, MOFFAS(fddiPATHMaxT_Req), "lT" } ,
+
+ /* Port Attributes */
+ /* ConfigGrp */
+ { SMT_P400A,AC_GROUP } ,
+ { SMT_P400C,AC_G, MOFFPS(fddiPORTMy_Type), "E" } ,
+ { SMT_P400D,AC_G, MOFFPS(fddiPORTNeighborType), "E" } ,
+ { SMT_P400E,AC_GR, MOFFPS(fddiPORTConnectionPolicies),"bB" } ,
+ { SMT_P400F,AC_G, MOFFPS(fddiPORTMacIndicated), "2" } ,
+ { SMT_P4010,AC_G, MOFFPS(fddiPORTCurrentPath), "E" } ,
+ { SMT_P4011,AC_GR, MOFFPA(fddiPORTRequestedPaths), "l4" } ,
+ { SMT_P4012,AC_G, MOFFPS(fddiPORTMACPlacement), "S" } ,
+ { SMT_P4013,AC_G, MOFFPS(fddiPORTAvailablePaths), "B" } ,
+ { SMT_P4016,AC_G, MOFFPS(fddiPORTPMDClass), "E" } ,
+ { SMT_P4017,AC_G, MOFFPS(fddiPORTConnectionCapabilities), "B"} ,
+ { SMT_P401D,AC_G, MOFFPS(fddiPORTIndex), "R" } ,
+
+ /* OperationGrp */
+ { SMT_P401E,AC_GROUP } ,
+ { SMT_P401F,AC_GR, MOFFPS(fddiPORTMaint_LS), "wE" } ,
+ { SMT_P4021,AC_G, MOFFPS(fddiPORTBS_Flag), "F" } ,
+ { SMT_P4022,AC_G, MOFFPS(fddiPORTPC_LS), "E" } ,
+
+ /* ErrorCtrsGrp */
+ { SMT_P4028,AC_GROUP } ,
+ { SMT_P4029,AC_G, MOFFPS(fddiPORTEBError_Ct), "C" } ,
+ { SMT_P402A,AC_G, MOFFPS(fddiPORTLCTFail_Ct), "C" } ,
+
+ /* LerGrp */
+ { SMT_P4032,AC_GROUP } ,
+ { SMT_P4033,AC_G, MOFFPS(fddiPORTLer_Estimate), "F" } ,
+ { SMT_P4034,AC_G, MOFFPS(fddiPORTLem_Reject_Ct), "C" } ,
+ { SMT_P4035,AC_G, MOFFPS(fddiPORTLem_Ct), "C" } ,
+ { SMT_P403A,AC_GR, MOFFPS(fddiPORTLer_Cutoff), "bB" } ,
+ { SMT_P403B,AC_GR, MOFFPS(fddiPORTLer_Alarm), "bB" } ,
+
+ /* StatusGrp */
+ { SMT_P403C,AC_GROUP } ,
+ { SMT_P403D,AC_G, MOFFPS(fddiPORTConnectState), "E" } ,
+ { SMT_P403E,AC_G, MOFFPS(fddiPORTPCMStateX), "E" } ,
+ { SMT_P403F,AC_G, MOFFPS(fddiPORTPC_Withhold), "E" } ,
+ { SMT_P4040,AC_G, MOFFPS(fddiPORTLerFlag), "F" } ,
+ { SMT_P4041,AC_G, MOFFPS(fddiPORTHardwarePresent),"F" } ,
+
+ { SMT_P4046,AC_S, 0, "wS" } ,
+
+ { 0, AC_GROUP } ,
+ { 0 }
+} ;
+
+
+static SMbuf *smt_build_pmf_response() ;
+
+void smt_pmf_received_pack(smc,mb,local)
+struct s_smc *smc ;
+SMbuf *mb ;
+int local ;
+{
+ struct smt_header *sm ;
+ SMbuf *reply ;
+
+ sm = smtod(mb,struct smt_header *) ;
+ DB_SMT("SMT: processing PMF frame at %x len %d\n",sm,mb->sm_len) ;
+#ifdef DEBUG
+ dump_smt(smc,sm,"PMF Received") ;
+#endif
+ /*
+ * Start the watchdog: It may be a long, long packet and
+ * maybe the watchdog occurs ...
+ */
+ smt_start_watchdog(smc) ;
+
+ if (sm->smt_class == SMT_PMF_GET ||
+ sm->smt_class == SMT_PMF_SET) {
+ reply = smt_build_pmf_response(smc,sm,
+ sm->smt_class == SMT_PMF_SET,local) ;
+ if (reply) {
+ sm = smtod(reply,struct smt_header *) ;
+#ifdef DEBUG
+ dump_smt(smc,sm,"PMF Reply") ;
+#endif
+ smt_send_frame(smc,reply,FC_SMT_INFO,local) ;
+ }
+ }
+}
+
+extern SMbuf *smt_get_mbuf() ;
+
+static SMbuf *smt_build_pmf_response(smc,req,set,local)
+struct s_smc *smc ;
+struct smt_header *req ;
+int set ;
+int local ;
+{
+ SMbuf *mb ;
+ struct smt_header *smt ;
+ struct smt_para *pa ;
+ struct smt_p_reason *res ;
+ const struct s_p_tab *pt ;
+ int len ;
+ int index ;
+ int idx_end ;
+ int error ;
+ int range ;
+ SK_LOC_DECL(struct s_pcon,pcon) ;
+ SK_LOC_DECL(struct s_pcon,set_pcon) ;
+
+ /*
+ * build SMT header
+ */
+ if (!(mb = smt_get_mbuf(smc)))
+ return(mb) ;
+
+ smt = smtod(mb, struct smt_header *) ;
+ smt->smt_dest = req->smt_source ; /* DA == source of request */
+ smt->smt_class = req->smt_class ; /* same class (GET/SET) */
+ smt->smt_type = SMT_REPLY ;
+ smt->smt_version = SMT_VID_2 ;
+ smt->smt_tid = req->smt_tid ; /* same TID */
+ smt->smt_pad = 0 ;
+ smt->smt_len = 0 ;
+
+ /*
+ * setup parameter status
+ */
+ pcon.pc_len = SMT_MAX_INFO_LEN ; /* max para length */
+ pcon.pc_err = 0 ; /* no error */
+ pcon.pc_badset = 0 ; /* no bad set count */
+ pcon.pc_p = (void *) (smt + 1) ; /* paras start here */
+
+ /*
+ * check authoriziation and set count
+ */
+ error = 0 ;
+ if (set) {
+ if (!local && smt_authorize(smc,req))
+ error = SMT_RDF_AUTHOR ;
+ else if (smt_check_set_count(smc,req))
+ pcon.pc_badset = SMT_RDF_BADSET ;
+ }
+ /*
+ * add reason code and all mandatory parameters
+ */
+ res = (struct smt_p_reason *) pcon.pc_p ;
+ smt_add_para(smc,&pcon,(u_short) SMT_P_REASON,0,0) ;
+ smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ;
+ /* update 1035 and 1036 later if set */
+ set_pcon = pcon ;
+ smt_add_para(smc,&pcon,(u_short) SMT_P1035,0,0) ;
+ smt_add_para(smc,&pcon,(u_short) SMT_P1036,0,0) ;
+
+ pcon.pc_err = error ;
+ len = req->smt_len ;
+ pa = (struct smt_para *) (req + 1) ;
+ /*
+ * process list of paras
+ */
+ while (!pcon.pc_err && len > 0 ) {
+ if (((u_short)len < pa->p_len + PARA_LEN) || (pa->p_len & 3)) {
+ pcon.pc_err = SMT_RDF_LENGTH ;
+ break ;
+ }
+
+ if (((range = (pa->p_type & 0xf000)) == 0x2000) ||
+ range == 0x3000 || range == 0x4000) {
+ /*
+ * get index for PART,MAC ad PATH group
+ */
+ index = *((u_char *)pa + PARA_LEN + 3) ;/* index */
+ idx_end = index ;
+ if (!set && (pa->p_len != 4)) {
+ pcon.pc_err = SMT_RDF_LENGTH ;
+ break ;
+ }
+ if (!index && !set) {
+ switch (range) {
+ case 0x2000 :
+ index = INDEX_MAC ;
+ idx_end = index - 1 + NUMMACS ;
+ break ;
+ case 0x3000 :
+ index = INDEX_PATH ;
+ idx_end = index - 1 + NUMPATHS ;
+ break ;
+ case 0x4000 :
+ index = INDEX_PORT ;
+ idx_end = index - 1 + NUMPHYS ;
+#ifndef CONCENTRATOR
+ if (smc->s.sas == SMT_SAS)
+ idx_end = INDEX_PORT ;
+#endif
+ break ;
+ }
+ }
+ }
+ else {
+ /*
+ * smt group has no index
+ */
+ if (!set && (pa->p_len != 0)) {
+ pcon.pc_err = SMT_RDF_LENGTH ;
+ break ;
+ }
+ index = 0 ;
+ idx_end = 0 ;
+ }
+ while (index <= idx_end) {
+ /*
+ * if group
+ * add all paras of group
+ */
+ pt = smt_get_ptab(pa->p_type) ;
+ if (pt && pt->p_access == AC_GROUP && !set) {
+ pt++ ;
+ while (pt->p_access == AC_G ||
+ pt->p_access == AC_GR) {
+ smt_add_para(smc,&pcon,pt->p_num,
+ index,local);
+ pt++ ;
+ }
+ }
+ /*
+ * ignore
+ * AUTHORIZATION in get/set
+ * SET COUNT in set
+ */
+ else if (pa->p_type != SMT_P_AUTHOR &&
+ (!set || (pa->p_type != SMT_P1035))) {
+ int st ;
+ if (pcon.pc_badset) {
+ smt_add_para(smc,&pcon,pa->p_type,
+ index,local) ;
+ }
+ else if (set) {
+ st = smt_set_para(smc,pa,index,local,1);
+ /*
+ * return para even if error
+ */
+ smt_add_para(smc,&pcon,pa->p_type,
+ index,local) ;
+ pcon.pc_err = st ;
+ }
+ else {
+ if (pt && pt->p_access == AC_S) {
+ pcon.pc_err =
+ SMT_RDF_ILLEGAL ;
+ }
+ smt_add_para(smc,&pcon,pa->p_type,
+ index,local) ;
+ }
+ }
+ if (pcon.pc_err)
+ break ;
+ index++ ;
+ }
+ len -= pa->p_len + PARA_LEN ;
+ pa = (struct smt_para *) ((char *)pa + pa->p_len + PARA_LEN) ;
+ }
+ smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ;
+ mb->sm_len = smt->smt_len + sizeof(struct smt_header) ;
+
+ /* update reason code */
+ res->rdf_reason = pcon.pc_badset ? pcon.pc_badset :
+ pcon.pc_err ? pcon.pc_err : SMT_RDF_SUCCESS ;
+ if (set && (res->rdf_reason == SMT_RDF_SUCCESS)) {
+ /*
+ * increment set count
+ * set time stamp
+ * store station id of last set
+ */
+ smc->mib.fddiSMTSetCount.count++ ;
+ smt_set_timestamp(smc,smc->mib.fddiSMTSetCount.timestamp) ;
+ smc->mib.fddiSMTLastSetStationId = req->smt_sid ;
+ smt_add_para(smc,&set_pcon,(u_short) SMT_P1035,0,0) ;
+ smt_add_para(smc,&set_pcon,(u_short) SMT_P1036,0,0) ;
+ }
+ return(mb) ;
+}
+
+extern void *sm_to_para() ;
+
+static int smt_authorize(smc,sm)
+struct s_smc *smc ;
+struct smt_header *sm ;
+{
+ struct smt_para *pa ;
+ int i ;
+ char *p ;
+
+ /*
+ * check source station id if not zero
+ */
+ p = (char *) &smc->mib.fddiPRPMFStation ;
+ for (i = 0 ; i < 8 && !p[i] ; i++)
+ ;
+ if (i != 8) {
+ if (memcmp((char *) &sm->smt_sid,
+ (char *) &smc->mib.fddiPRPMFStation,8))
+ return(1) ;
+ }
+ /*
+ * check authoriziation parameter if passwd not zero
+ */
+ p = (char *) smc->mib.fddiPRPMFPasswd ;
+ for (i = 0 ; i < 8 && !p[i] ; i++)
+ ;
+ if (i != 8) {
+ pa = (struct smt_para *) sm_to_para(smc,sm,SMT_P_AUTHOR) ;
+ if (!pa)
+ return(1) ;
+ if (pa->p_len != 8)
+ return(1) ;
+ if (memcmp((char *)(pa+1),(char *)smc->mib.fddiPRPMFPasswd,8))
+ return(1) ;
+ }
+ return(0) ;
+}
+
+static int smt_check_set_count(smc,sm)
+struct s_smc *smc ;
+struct smt_header *sm ;
+{
+ struct smt_para *pa ;
+ struct smt_p_setcount *sc ;
+
+ pa = (struct smt_para *) sm_to_para(smc,sm,SMT_P1035) ;
+ if (pa) {
+ sc = (struct smt_p_setcount *) pa ;
+ if ((smc->mib.fddiSMTSetCount.count != sc->count) ||
+ memcmp((char *) smc->mib.fddiSMTSetCount.timestamp,
+ (char *)sc->timestamp,8))
+ return(1) ;
+ }
+ return(0) ;
+}
+
+void smt_add_para(smc,pcon,para,index,local)
+struct s_smc *smc ;
+struct s_pcon *pcon ;
+u_short para ;
+int index ;
+int local ;
+{
+ struct smt_para *pa ;
+ const struct s_p_tab *pt ;
+ struct fddi_mib_m *mib_m = 0 ;
+ struct fddi_mib_p *mib_p = 0 ;
+ int len ;
+ int plen ;
+ char *from ;
+ char *to ;
+ const char *swap ;
+ char c ;
+ int range ;
+ char *mib_addr ;
+ int mac ;
+ int path ;
+ int port ;
+ int sp_len ;
+
+ /*
+ * skip if errror
+ */
+ if (pcon->pc_err)
+ return ;
+
+ /*
+ * actions don't have a value
+ */
+ pt = smt_get_ptab(para) ;
+ if (pt && pt->p_access == AC_S)
+ return ;
+
+ to = (char *) (pcon->pc_p) ; /* destination pointer */
+ len = pcon->pc_len ; /* free space */
+ plen = len ; /* remember start length */
+ pa = (struct smt_para *) to ; /* type/length pointer */
+ to += PARA_LEN ; /* skip smt_para */
+ len -= PARA_LEN ;
+ /*
+ * set index if required
+ */
+ if (((range = (para & 0xf000)) == 0x2000) ||
+ range == 0x3000 || range == 0x4000) {
+ if (len < 4)
+ goto wrong_error ;
+ to[0] = 0 ;
+ to[1] = 0 ;
+ to[2] = 0 ;
+ to[3] = index ;
+ len -= 4 ;
+ to += 4 ;
+ }
+ mac = index - INDEX_MAC ;
+ path = index - INDEX_PATH ;
+ port = index - INDEX_PORT ;
+ /*
+ * get pointer to mib
+ */
+ switch (range) {
+ case 0x1000 :
+ default :
+ mib_addr = (char *) (&smc->mib) ;
+ break ;
+ case 0x2000 :
+ if (mac < 0 || mac >= NUMMACS) {
+ pcon->pc_err = SMT_RDF_NOPARAM ;
+ return ;
+ }
+ mib_addr = (char *) (&smc->mib.m[mac]) ;
+ mib_m = (struct fddi_mib_m *) mib_addr ;
+ break ;
+ case 0x3000 :
+ if (path < 0 || path >= NUMPATHS) {
+ pcon->pc_err = SMT_RDF_NOPARAM ;
+ return ;
+ }
+ mib_addr = (char *) (&smc->mib.a[path]) ;
+ break ;
+ case 0x4000 :
+ if (port < 0 || port >= smt_mib_phys(smc)) {
+ pcon->pc_err = SMT_RDF_NOPARAM ;
+ return ;
+ }
+ mib_addr = (char *) (&smc->mib.p[port_to_mib(smc,port)]) ;
+ mib_p = (struct fddi_mib_p *) mib_addr ;
+ break ;
+ }
+ /*
+ * check special paras
+ */
+ swap = 0 ;
+ switch (para) {
+ case SMT_P10F0 :
+ case SMT_P10F1 :
+#ifdef ESS
+ case SMT_P10F2 :
+ case SMT_P10F3 :
+ case SMT_P10F4 :
+ case SMT_P10F5 :
+ case SMT_P10F6 :
+ case SMT_P10F7 :
+#endif
+#ifdef SBA
+ case SMT_P10F8 :
+ case SMT_P10F9 :
+#endif
+ case SMT_P20F1 :
+ if (!local) {
+ pcon->pc_err = SMT_RDF_NOPARAM ;
+ return ;
+ }
+ break ;
+ case SMT_P2034 :
+ case SMT_P2046 :
+ case SMT_P2047 :
+ case SMT_P204A :
+ case SMT_P2051 :
+ case SMT_P2052 :
+ mac_update_counter(smc) ;
+ break ;
+ case SMT_P4022:
+ mib_p->fddiPORTPC_LS = LS2MIB(
+ sm_pm_get_ls(smc,port_to_mib(smc,port))) ;
+ break ;
+ case SMT_P_REASON :
+ * (u_long *) to = 0 ;
+ sp_len = 4 ;
+ goto sp_done ;
+ case SMT_P1033 : /* time stamp */
+ smt_set_timestamp(smc,smc->mib.fddiSMTTimeStamp) ;
+ break ;
+
+ case SMT_P1020: /* port indexes */
+#if NUMPHYS == 12
+ swap = "IIIIIIIIIIII" ;
+#else
+#if NUMPHYS == 2
+ if (smc->s.sas == SMT_SAS)
+ swap = "I" ;
+ else
+ swap = "II" ;
+#else
+#if NUMPHYS == 24
+ swap = "IIIIIIIIIIIIIIIIIIIIIIII" ;
+#else
+ ????
+#endif
+#endif
+#endif
+ break ;
+ case SMT_P3212 :
+ {
+ sp_len = cem_build_path(smc,to,path) ;
+ goto sp_done ;
+ }
+ case SMT_P1048 : /* peer wrap condition */
+ {
+ struct smt_p_1048 *sp ;
+ sp = (struct smt_p_1048 *) to ;
+ sp->p1048_flag = smc->mib.fddiSMTPeerWrapFlag ;
+ sp->p1048_cf_state = smc->mib.fddiSMTCF_State ;
+ sp_len = sizeof(struct smt_p_1048) ;
+ goto sp_done ;
+ }
+ case SMT_P208C :
+ {
+ struct smt_p_208c *sp ;
+ sp = (struct smt_p_208c *) to ;
+ sp->p208c_flag =
+ smc->mib.m[MAC0].fddiMACDuplicateAddressCond ;
+ sp->p208c_dupcondition =
+ (mib_m->fddiMACDA_Flag ? SMT_ST_MY_DUPA : 0) |
+ (mib_m->fddiMACUNDA_Flag ? SMT_ST_UNA_DUPA : 0);
+ sp->p208c_fddilong =
+ mib_m->fddiMACSMTAddress ;
+ sp->p208c_fddiunalong =
+ mib_m->fddiMACUpstreamNbr ;
+ sp->p208c_pad = 0 ;
+ sp_len = sizeof(struct smt_p_208c) ;
+ goto sp_done ;
+ }
+ case SMT_P208D : /* frame error condition */
+ {
+ struct smt_p_208d *sp ;
+ sp = (struct smt_p_208d *) to ;
+ sp->p208d_flag =
+ mib_m->fddiMACFrameErrorFlag ;
+ sp->p208d_frame_ct =
+ mib_m->fddiMACFrame_Ct ;
+ sp->p208d_error_ct =
+ mib_m->fddiMACError_Ct ;
+ sp->p208d_lost_ct =
+ mib_m->fddiMACLost_Ct ;
+ sp->p208d_ratio =
+ mib_m->fddiMACFrameErrorRatio ;
+ sp_len = sizeof(struct smt_p_208d) ;
+ goto sp_done ;
+ }
+ case SMT_P208E : /* not copied condition */
+ {
+ struct smt_p_208e *sp ;
+ sp = (struct smt_p_208e *) to ;
+ sp->p208e_flag =
+ mib_m->fddiMACNotCopiedFlag ;
+ sp->p208e_not_copied =
+ mib_m->fddiMACNotCopied_Ct ;
+ sp->p208e_copied =
+ mib_m->fddiMACCopied_Ct ;
+ sp->p208e_not_copied_ratio =
+ mib_m->fddiMACNotCopiedRatio ;
+ sp_len = sizeof(struct smt_p_208e) ;
+ goto sp_done ;
+ }
+ case SMT_P208F : /* neighbor change event */
+ {
+ struct smt_p_208f *sp ;
+ sp = (struct smt_p_208f *) to ;
+ sp->p208f_multiple =
+ mib_m->fddiMACMultiple_N ;
+ sp->p208f_nacondition =
+ mib_m->fddiMACDuplicateAddressCond ;
+ sp->p208f_old_una =
+ mib_m->fddiMACOldUpstreamNbr ;
+ sp->p208f_new_una =
+ mib_m->fddiMACUpstreamNbr ;
+ sp->p208f_old_dna =
+ mib_m->fddiMACOldDownstreamNbr ;
+ sp->p208f_new_dna =
+ mib_m->fddiMACDownstreamNbr ;
+ sp->p208f_curren_path =
+ mib_m->fddiMACCurrentPath ;
+ sp->p208f_smt_address =
+ mib_m->fddiMACSMTAddress ;
+ sp_len = sizeof(struct smt_p_208f) ;
+ goto sp_done ;
+ }
+ case SMT_P2090 :
+ {
+ struct smt_p_2090 *sp ;
+ sp = (struct smt_p_2090 *) to ;
+ sp->p2090_multiple =
+ mib_m->fddiMACMultiple_P ;
+ sp->p2090_availablepaths =
+ mib_m->fddiMACAvailablePaths ;
+ sp->p2090_currentpath =
+ mib_m->fddiMACCurrentPath ;
+ sp->p2090_requestedpaths =
+ mib_m->fddiMACRequestedPaths ;
+ sp_len = sizeof(struct smt_p_2090) ;
+ goto sp_done ;
+ }
+ case SMT_P4050 :
+ {
+ struct smt_p_4050 *sp ;
+ sp = (struct smt_p_4050 *) to ;
+ sp->p4050_flag =
+ mib_p->fddiPORTLerFlag ;
+ sp->p4050_pad = 0 ;
+ sp->p4050_cutoff =
+ mib_p->fddiPORTLer_Cutoff ; ;
+ sp->p4050_alarm =
+ mib_p->fddiPORTLer_Alarm ; ;
+ sp->p4050_estimate =
+ mib_p->fddiPORTLer_Estimate ;
+ sp->p4050_reject_ct =
+ mib_p->fddiPORTLem_Reject_Ct ;
+ sp->p4050_ct =
+ mib_p->fddiPORTLem_Ct ;
+ sp_len = sizeof(struct smt_p_4050) ;
+ goto sp_done ;
+ }
+
+ case SMT_P4051 :
+ {
+ struct smt_p_4051 *sp ;
+ sp = (struct smt_p_4051 *) to ;
+ sp->p4051_multiple =
+ mib_p->fddiPORTMultiple_U ;
+ sp->p4051_porttype =
+ mib_p->fddiPORTMy_Type ;
+ sp->p4051_connectstate =
+ mib_p->fddiPORTConnectState ; ;
+ sp->p4051_pc_neighbor =
+ mib_p->fddiPORTNeighborType ;
+ sp->p4051_pc_withhold =
+ mib_p->fddiPORTPC_Withhold ;
+ sp_len = sizeof(struct smt_p_4051) ;
+ goto sp_done ;
+ }
+ case SMT_P4052 :
+ {
+ struct smt_p_4052 *sp ;
+ sp = (struct smt_p_4052 *) to ;
+ sp->p4052_flag =
+ mib_p->fddiPORTEB_Condition ;
+ sp->p4052_eberrorcount =
+ mib_p->fddiPORTEBError_Ct ;
+ sp_len = sizeof(struct smt_p_4052) ;
+ goto sp_done ;
+ }
+ case SMT_P4053 :
+ {
+ struct smt_p_4053 *sp ;
+ sp = (struct smt_p_4053 *) to ;
+ sp->p4053_multiple =
+ mib_p->fddiPORTMultiple_P ; ;
+ sp->p4053_availablepaths =
+ mib_p->fddiPORTAvailablePaths ;
+ sp->p4053_currentpath =
+ mib_p->fddiPORTCurrentPath ;
+ memcpy( (char *) &sp->p4053_requestedpaths,
+ (char *) mib_p->fddiPORTRequestedPaths,4) ;
+ sp->p4053_mytype =
+ mib_p->fddiPORTMy_Type ;
+ sp->p4053_neighbortype =
+ mib_p->fddiPORTNeighborType ;
+ sp_len = sizeof(struct smt_p_4053) ;
+ goto sp_done ;
+ }
+ default :
+ break ;
+ }
+ /*
+ * in table ?
+ */
+ if (!pt) {
+ pcon->pc_err = (para & 0xff00) ? SMT_RDF_NOPARAM :
+ SMT_RDF_ILLEGAL ;
+ return ;
+ }
+ /*
+ * check access rights
+ */
+ switch (pt->p_access) {
+ case AC_G :
+ case AC_GR :
+ break ;
+ default :
+ pcon->pc_err = SMT_RDF_ILLEGAL ;
+ return ;
+ }
+ from = mib_addr + pt->p_offset ;
+ if (!swap)
+ swap = pt->p_swap ; /* pointer to swap string */
+
+ /*
+ * copy values
+ */
+ while ((c = *swap++)) {
+ switch(c) {
+ case 'b' :
+ case 'w' :
+ case 'l' :
+ break ;
+ case 'S' :
+ case 'E' :
+ case 'R' :
+ case 'r' :
+ if (len < 4)
+ goto len_error ;
+ to[0] = 0 ;
+ to[1] = 0 ;
+#ifdef LITTLE_ENDIAN
+ if (c == 'r') {
+ to[2] = *from++ ;
+ to[3] = *from++ ;
+ }
+ else {
+ to[3] = *from++ ;
+ to[2] = *from++ ;
+ }
+#else
+ to[2] = *from++ ;
+ to[3] = *from++ ;
+#endif
+ to += 4 ;
+ len -= 4 ;
+ break ;
+ case 'I' : /* for SET of port indexes */
+ if (len < 2)
+ goto len_error ;
+#ifdef LITTLE_ENDIAN
+ to[1] = *from++ ;
+ to[0] = *from++ ;
+#else
+ to[0] = *from++ ;
+ to[1] = *from++ ;
+#endif
+ to += 2 ;
+ len -= 2 ;
+ break ;
+ case 'F' :
+ case 'B' :
+ if (len < 4)
+ goto len_error ;
+ len -= 4 ;
+ to[0] = 0 ;
+ to[1] = 0 ;
+ to[2] = 0 ;
+ to[3] = *from++ ;
+ to += 4 ;
+ break ;
+ case 'C' :
+ case 'T' :
+ case 'L' :
+ if (len < 4)
+ goto len_error ;
+#ifdef LITTLE_ENDIAN
+ to[3] = *from++ ;
+ to[2] = *from++ ;
+ to[1] = *from++ ;
+ to[0] = *from++ ;
+#else
+ to[0] = *from++ ;
+ to[1] = *from++ ;
+ to[2] = *from++ ;
+ to[3] = *from++ ;
+#endif
+ len -= 4 ;
+ to += 4 ;
+ break ;
+ case '2' : /* PortMacIndicated */
+ if (len < 4)
+ goto len_error ;
+ to[0] = 0 ;
+ to[1] = 0 ;
+ to[2] = *from++ ;
+ to[3] = *from++ ;
+ len -= 4 ;
+ to += 4 ;
+ break ;
+ case '4' :
+ if (len < 4)
+ goto len_error ;
+ to[0] = *from++ ;
+ to[1] = *from++ ;
+ to[2] = *from++ ;
+ to[3] = *from++ ;
+ len -= 4 ;
+ to += 4 ;
+ break ;
+ case 'A' :
+ if (len < 8)
+ goto len_error ;
+ to[0] = 0 ;
+ to[1] = 0 ;
+ memcpy((char *) to+2,(char *) from,6) ;
+ to += 8 ;
+ from += 8 ;
+ len -= 8 ;
+ break ;
+ case '8' :
+ if (len < 8)
+ goto len_error ;
+ memcpy((char *) to,(char *) from,8) ;
+ to += 8 ;
+ from += 8 ;
+ len -= 8 ;
+ break ;
+ case 'D' :
+ if (len < 32)
+ goto len_error ;
+ memcpy((char *) to,(char *) from,32) ;
+ to += 32 ;
+ from += 32 ;
+ len -= 32 ;
+ break ;
+ case 'P' : /* timestamp is NOT swapped */
+ if (len < 8)
+ goto len_error ;
+ to[0] = *from++ ;
+ to[1] = *from++ ;
+ to[2] = *from++ ;
+ to[3] = *from++ ;
+ to[4] = *from++ ;
+ to[5] = *from++ ;
+ to[6] = *from++ ;
+ to[7] = *from++ ;
+ to += 8 ;
+ len -= 8 ;
+ break ;
+ default :
+ SMT_PANIC(smc,SMT_E0119, SMT_E0119_MSG) ;
+ break ;
+ }
+ }
+
+done:
+ /*
+ * make it even (in case of 'I' encoding)
+ * note: len is DECREMENTED
+ */
+ if (len & 3) {
+ to[0] = 0 ;
+ to[1] = 0 ;
+ to += 4 - (len & 3 ) ;
+ len = len & ~ 3 ;
+ }
+
+ /* set type and length */
+ pa->p_type = para ;
+ pa->p_len = plen - len - PARA_LEN ;
+ /* return values */
+ pcon->pc_p = (void *) to ;
+ pcon->pc_len = len ;
+ return ;
+
+sp_done:
+ len -= sp_len ;
+ to += sp_len ;
+ goto done ;
+
+len_error:
+ /* parameter does not fit in frame */
+ pcon->pc_err = SMT_RDF_TOOLONG ;
+ return ;
+
+wrong_error:
+ pcon->pc_err = SMT_RDF_LENGTH ;
+}
+
+/*
+ * set parameter
+ */
+int smt_set_para(smc,pa,index,local,set)
+struct s_smc *smc ;
+struct smt_para *pa ;
+int index ;
+int local ;
+int set ;
+{
+#define IFSET(x) if (set) (x)
+
+ const struct s_p_tab *pt ;
+ int len ;
+ char *from ;
+ char *to ;
+ const char *swap ;
+ char c ;
+ char *mib_addr ;
+ struct fddi_mib *mib ;
+ struct fddi_mib_m *mib_m = 0 ;
+ struct fddi_mib_a *mib_a = 0 ;
+ struct fddi_mib_p *mib_p = 0 ;
+ int mac ;
+ int path ;
+ int port ;
+ SK_LOC_DECL(u_char,byte_val) ;
+ SK_LOC_DECL(u_short,word_val) ;
+ SK_LOC_DECL(u_long,long_val) ;
+
+ mac = index - INDEX_MAC ;
+ path = index - INDEX_PATH ;
+ port = index - INDEX_PORT ;
+ len = pa->p_len ;
+ from = (char *) (pa + 1 ) ;
+
+ mib = &smc->mib ;
+ switch (pa->p_type & 0xf000) {
+ case 0x1000 :
+ default :
+ mib_addr = (char *) mib ;
+ break ;
+ case 0x2000 :
+ if (mac < 0 || mac >= NUMMACS) {
+ return(SMT_RDF_NOPARAM) ;
+ }
+ mib_m = &smc->mib.m[mac] ;
+ mib_addr = (char *) mib_m ;
+ from += 4 ; /* skip index */
+ len -= 4 ;
+ break ;
+ case 0x3000 :
+ if (path < 0 || path >= NUMPATHS) {
+ return(SMT_RDF_NOPARAM) ;
+ }
+ mib_a = &smc->mib.a[path] ;
+ mib_addr = (char *) mib_a ;
+ from += 4 ; /* skip index */
+ len -= 4 ;
+ break ;
+ case 0x4000 :
+ if (port < 0 || port >= smt_mib_phys(smc)) {
+ return(SMT_RDF_NOPARAM) ;
+ }
+ mib_p = &smc->mib.p[port_to_mib(smc,port)] ;
+ mib_addr = (char *) mib_p ;
+ from += 4 ; /* skip index */
+ len -= 4 ;
+ break ;
+ }
+ switch (pa->p_type) {
+ case SMT_P10F0 :
+ case SMT_P10F1 :
+#ifdef ESS
+ case SMT_P10F2 :
+ case SMT_P10F3 :
+ case SMT_P10F4 :
+ case SMT_P10F5 :
+ case SMT_P10F6 :
+ case SMT_P10F7 :
+#endif
+#ifdef SBA
+ case SMT_P10F8 :
+ case SMT_P10F9 :
+#endif
+ case SMT_P20F1 :
+ if (!local) {
+ return(SMT_RDF_NOPARAM) ;
+ }
+ break ;
+ }
+ pt = smt_get_ptab(pa->p_type) ;
+ if (!pt) {
+ return( (pa->p_type & 0xff00) ? SMT_RDF_NOPARAM :
+ SMT_RDF_ILLEGAL ) ;
+ }
+ switch (pt->p_access) {
+ case AC_GR :
+ case AC_S :
+ break ;
+ default :
+ return(SMT_RDF_ILLEGAL) ;
+ }
+ to = mib_addr + pt->p_offset ;
+ swap = pt->p_swap ; /* pointer to swap string */
+
+ while (swap && (c = *swap++)) {
+ switch(c) {
+ case 'b' :
+ to = (char *) &byte_val ;
+ break ;
+ case 'w' :
+ to = (char *) &word_val ;
+ break ;
+ case 'l' :
+ to = (char *) &long_val ;
+ break ;
+ case 'S' :
+ case 'E' :
+ case 'R' :
+ case 'r' :
+ if (len < 4) {
+ goto len_error ;
+ }
+ if (from[0] | from[1])
+ goto val_error ;
+#ifdef LITTLE_ENDIAN
+ if (c == 'r') {
+ to[0] = from[2] ;
+ to[1] = from[3] ;
+ }
+ else {
+ to[1] = from[2] ;
+ to[0] = from[3] ;
+ }
+#else
+ to[0] = from[2] ;
+ to[1] = from[3] ;
+#endif
+ from += 4 ;
+ to += 2 ;
+ len -= 4 ;
+ break ;
+ case 'F' :
+ case 'B' :
+ if (len < 4) {
+ goto len_error ;
+ }
+ if (from[0] | from[1] | from[2])
+ goto val_error ;
+ to[0] = from[3] ;
+ len -= 4 ;
+ from += 4 ;
+ to += 4 ;
+ break ;
+ case 'C' :
+ case 'T' :
+ case 'L' :
+ if (len < 4) {
+ goto len_error ;
+ }
+#ifdef LITTLE_ENDIAN
+ to[3] = *from++ ;
+ to[2] = *from++ ;
+ to[1] = *from++ ;
+ to[0] = *from++ ;
+#else
+ to[0] = *from++ ;
+ to[1] = *from++ ;
+ to[2] = *from++ ;
+ to[3] = *from++ ;
+#endif
+ len -= 4 ;
+ to += 4 ;
+ break ;
+ case 'A' :
+ if (len < 8)
+ goto len_error ;
+ if (set)
+ memcpy((char *) to,(char *) from+2,6) ;
+ to += 8 ;
+ from += 8 ;
+ len -= 8 ;
+ break ;
+ case '4' :
+ if (len < 4)
+ goto len_error ;
+ if (set)
+ memcpy((char *) to,(char *) from,4) ;
+ to += 4 ;
+ from += 4 ;
+ len -= 4 ;
+ break ;
+ case '8' :
+ if (len < 8)
+ goto len_error ;
+ if (set)
+ memcpy((char *) to,(char *) from,8) ;
+ to += 8 ;
+ from += 8 ;
+ len -= 8 ;
+ break ;
+ case 'D' :
+ if (len < 32)
+ goto len_error ;
+ if (set)
+ memcpy((char *) to,(char *) from,32) ;
+ to += 32 ;
+ from += 32 ;
+ len -= 32 ;
+ break ;
+ case 'P' : /* timestamp is NOT swapped */
+ if (set) {
+ to[0] = *from++ ;
+ to[1] = *from++ ;
+ to[2] = *from++ ;
+ to[3] = *from++ ;
+ to[4] = *from++ ;
+ to[5] = *from++ ;
+ to[6] = *from++ ;
+ to[7] = *from++ ;
+ }
+ to += 8 ;
+ len -= 8 ;
+ break ;
+ default :
+ SMT_PANIC(smc,SMT_E0120, SMT_E0120_MSG) ;
+ return(SMT_RDF_ILLEGAL) ;
+ }
+ }
+ /*
+ * actions and internal updates
+ */
+ switch (pa->p_type) {
+ case SMT_P101A: /* fddiSMTConfigPolicy */
+ if (word_val & ~1)
+ goto val_error ;
+ IFSET(mib->fddiSMTConfigPolicy = word_val) ;
+ break ;
+ case SMT_P101B : /* fddiSMTConnectionPolicy */
+ if (!(word_val & POLICY_MM))
+ goto val_error ;
+ IFSET(mib->fddiSMTConnectionPolicy = word_val) ;
+ break ;
+ case SMT_P101D : /* fddiSMTTT_Notify */
+ if (word_val < 2 || word_val > 30)
+ goto val_error ;
+ IFSET(mib->fddiSMTTT_Notify = word_val) ;
+ break ;
+ case SMT_P101E : /* fddiSMTStatRptPolicy */
+ if (byte_val & ~1)
+ goto val_error ;
+ IFSET(mib->fddiSMTStatRptPolicy = byte_val) ;
+ break ;
+ case SMT_P101F : /* fddiSMTTrace_MaxExpiration */
+ /*
+ * note: lower limit trace_max = 6.001773... s
+ * NO upper limit
+ */
+ if (long_val < (long)0x478bf51L)
+ goto val_error ;
+ IFSET(mib->fddiSMTTrace_MaxExpiration = long_val) ;
+ break ;
+#ifdef ESS
+ case SMT_P10F2 : /* fddiESSPayload */
+ if (long_val > 1562)
+ goto val_error ;
+ if (set && smc->mib.fddiESSPayload != long_val) {
+ smc->ess.raf_act_timer_poll = TRUE ;
+ smc->mib.fddiESSPayload = long_val ;
+ }
+ break ;
+ case SMT_P10F3 : /* fddiESSOverhead */
+ if (long_val < 50 || long_val > 5000)
+ goto val_error ;
+ if (set && smc->mib.fddiESSPayload &&
+ smc->mib.fddiESSOverhead != long_val) {
+ smc->ess.raf_act_timer_poll = TRUE ;
+ smc->mib.fddiESSOverhead = long_val ;
+ }
+ break ;
+ case SMT_P10F4 : /* fddiESSMaxTNeg */
+ if (long_val > -MS2BCLK(5) || long_val < -MS2BCLK(165))
+ goto val_error ;
+ IFSET(mib->fddiESSMaxTNeg = long_val) ;
+ break ;
+ case SMT_P10F5 : /* fddiESSMinSegmentSize */
+ if (long_val < 1 || long_val > 4478)
+ goto val_error ;
+ IFSET(mib->fddiESSMinSegmentSize = long_val) ;
+ break ;
+ case SMT_P10F6 : /* fddiESSCategory */
+ if ((long_val & 0xffff) != 1)
+ goto val_error ;
+ IFSET(mib->fddiESSCategory = long_val) ;
+ break ;
+ case SMT_P10F7 : /* fddiESSSyncTxMode */
+ if (word_val > 1)
+ goto val_error ;
+ IFSET(mib->fddiESSSynchTxMode = word_val) ;
+ break ;
+#endif
+#ifdef SBA
+ case SMT_P10F8 : /* fddiSBACommand */
+ if (byte_val != SB_STOP && byte_val != SB_START)
+ goto val_error ;
+ IFSET(mib->fddiSBACommand = byte_val) ;
+ break ;
+ case SMT_P10F9 : /* fddiSBAAvailable */
+ if (byte_val > 100)
+ goto val_error ;
+ IFSET(mib->fddiSBAAvailable = byte_val) ;
+ break ;
+#endif
+ case SMT_P2020 : /* fddiMACRequestedPaths */
+ if ((word_val & (MIB_P_PATH_PRIM_PREFER |
+ MIB_P_PATH_PRIM_ALTER)) == 0 )
+ goto val_error ;
+ IFSET(mib_m->fddiMACRequestedPaths = word_val) ;
+ break ;
+ case SMT_P205F : /* fddiMACFrameErrorThreshold */
+ /* 0 .. ffff acceptable */
+ IFSET(mib_m->fddiMACFrameErrorThreshold = word_val) ;
+ break ;
+ case SMT_P2067 : /* fddiMACNotCopiedThreshold */
+ /* 0 .. ffff acceptable */
+ IFSET(mib_m->fddiMACNotCopiedThreshold = word_val) ;
+ break ;
+ case SMT_P2076: /* fddiMACMA_UnitdataEnable */
+ if (byte_val & ~1)
+ goto val_error ;
+ if (set) {
+ mib_m->fddiMACMA_UnitdataEnable = byte_val ;
+ queue_event(smc,EVENT_RMT,RM_ENABLE_FLAG) ;
+ }
+ break ;
+ case SMT_P20F1 : /* fddiMACT_Min */
+ IFSET(mib_m->fddiMACT_Min = long_val) ;
+ break ;
+ case SMT_P320F :
+ if (long_val > 1562)
+ goto val_error ;
+ IFSET(mib_a->fddiPATHSbaPayload = long_val) ;
+#ifdef ESS
+ if (set)
+ ess_para_change(smc) ;
+#endif
+ break ;
+ case SMT_P3210 :
+ if (long_val > 5000)
+ goto val_error ;
+
+ if (long_val != 0 && mib_a->fddiPATHSbaPayload == 0)
+ goto val_error ;
+
+ IFSET(mib_a->fddiPATHSbaOverhead = long_val) ;
+#ifdef ESS
+ if (set)
+ ess_para_change(smc) ;
+#endif
+ break ;
+ case SMT_P3213: /* fddiPATHT_Rmode */
+ /* no limit :
+ * 0 .. 343.597 => 0 .. 2e32 * 80nS
+ */
+ if (set) {
+ mib_a->fddiPATHT_Rmode = long_val ;
+ rtm_set_timer(smc) ;
+ }
+ break ;
+ case SMT_P3214 : /* fddiPATHSbaAvailable */
+ if (long_val > 0x00BEBC20L)
+ goto val_error ;
+#ifdef SBA
+ if (set && mib->fddiSBACommand == SB_STOP)
+ goto val_error ;
+#endif
+ IFSET(mib_a->fddiPATHSbaAvailable = long_val) ;
+ break ;
+ case SMT_P3215 : /* fddiPATHTVXLowerBound */
+ IFSET(mib_a->fddiPATHTVXLowerBound = long_val) ;
+ goto change_mac_para ;
+ case SMT_P3216 : /* fddiPATHT_MaxLowerBound */
+ IFSET(mib_a->fddiPATHT_MaxLowerBound = long_val) ;
+ goto change_mac_para ;
+ case SMT_P3217 : /* fddiPATHMaxT_Req */
+ IFSET(mib_a->fddiPATHMaxT_Req = long_val) ;
+
+change_mac_para:
+ if (set && smt_set_mac_opvalues(smc)) {
+ RS_SET(smc,RS_EVENT) ;
+ smc->sm.please_reconnect = 1 ;
+ queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
+ }
+ break ;
+ case SMT_P400E : /* fddiPORTConnectionPolicies */
+ if (byte_val > 1)
+ goto val_error ;
+ IFSET(mib_p->fddiPORTConnectionPolicies = byte_val) ;
+ break ;
+ case SMT_P4011 : /* fddiPORTRequestedPaths */
+ /* all 3*8 bits allowed */
+ IFSET(memcpy((char *)mib_p->fddiPORTRequestedPaths,
+ (char *)&long_val,4)) ;
+ break ;
+ case SMT_P401F: /* fddiPORTMaint_LS */
+ if (word_val > 4)
+ goto val_error ;
+ IFSET(mib_p->fddiPORTMaint_LS = word_val) ;
+ break ;
+ case SMT_P403A : /* fddiPORTLer_Cutoff */
+ if (byte_val < 4 || byte_val > 15)
+ goto val_error ;
+ IFSET(mib_p->fddiPORTLer_Cutoff = byte_val) ;
+ break ;
+ case SMT_P403B : /* fddiPORTLer_Alarm */
+ if (byte_val < 4 || byte_val > 15)
+ goto val_error ;
+ IFSET(mib_p->fddiPORTLer_Alarm = byte_val) ;
+ break ;
+
+ /*
+ * Actions
+ */
+ case SMT_P103C : /* fddiSMTStationAction */
+ if (smt_action(smc,SMT_STATION_ACTION, (int) word_val, 0))
+ goto val_error ;
+ break ;
+ case SMT_P4046: /* fddiPORTAction */
+ if (smt_action(smc,SMT_PORT_ACTION, (int) word_val,
+ port_to_mib(smc,port)))
+ goto val_error ;
+ break ;
+ default :
+ break ;
+ }
+ return(0) ;
+
+val_error:
+ /* parameter value in frame is out of range */
+ return(SMT_RDF_RANGE) ;
+
+len_error:
+ /* parameter value in frame is too short */
+ return(SMT_RDF_LENGTH) ;
+
+#if 0
+no_author_error:
+ /* parameter not setable, because the SBA is not active
+ * Please note: we give the return code 'not authorizeed
+ * because SBA denied is not a valid return code in the
+ * PMF protocol.
+ */
+ return(SMT_RDF_AUTHOR) ;
+#endif
+}
+
+static const struct s_p_tab *smt_get_ptab(para)
+u_short para ;
+{
+ const struct s_p_tab *pt ;
+ for (pt = p_tab ; pt->p_num && pt->p_num != para ; pt++)
+ ;
+ return(pt->p_num ? pt : 0) ;
+}
+
+static int smt_mib_phys(smc)
+struct s_smc *smc ;
+{
+#ifdef CONCENTRATOR
+ SK_UNUSED(smc) ;
+
+ return(NUMPHYS) ;
+#else
+ if (smc->s.sas == SMT_SAS)
+ return(1) ;
+ return(NUMPHYS) ;
+#endif
+}
+
+int port_to_mib(smc,p)
+struct s_smc *smc ;
+int p ;
+{
+#ifdef CONCENTRATOR
+ SK_UNUSED(smc) ;
+
+ return(p) ;
+#else
+ if (smc->s.sas == SMT_SAS)
+ return(PS) ;
+ return(p) ;
+#endif
+}
+
+
+#ifdef DEBUG
+#ifndef BOOT
+void dump_smt(smc,sm,text)
+struct s_smc *smc ;
+struct smt_header *sm ;
+char *text ;
+{
+ int len ;
+ struct smt_para *pa ;
+ char *c ;
+ int n ;
+ int nn ;
+#ifdef LITTLE_ENDIAN
+ int smtlen ;
+#endif
+
+ SK_UNUSED(smc) ;
+
+#ifdef DEBUG_BRD
+ if (smc->debug.d_smtf < 2)
+#else
+ if (debug.d_smtf < 2)
+#endif
+ return ;
+#ifdef LITTLE_ENDIAN
+ smtlen = sm->smt_len + sizeof(struct smt_header) ;
+#endif
+ printf("SMT Frame [%s]:\nDA ",text) ;
+ dump_hex((char *) &sm->smt_dest,6) ;
+ printf("\tSA ") ;
+ dump_hex((char *) &sm->smt_source,6) ;
+ printf(" Class %x Type %x Version %x\n",
+ sm->smt_class,sm->smt_type,sm->smt_version) ;
+ printf("TID %lx\t\tSID ",sm->smt_tid) ;
+ dump_hex((char *) &sm->smt_sid,8) ;
+ printf(" LEN %x\n",sm->smt_len) ;
+
+ len = sm->smt_len ;
+ pa = (struct smt_para *) (sm + 1) ;
+ while (len > 0 ) {
+ int plen ;
+#ifdef UNIX
+ printf("TYPE %x LEN %x VALUE\t",pa->p_type,pa->p_len) ;
+#else
+ printf("TYPE %04x LEN %2x VALUE\t",pa->p_type,pa->p_len) ;
+#endif
+ n = pa->p_len ;
+ if ( (n < 0 ) || (n > (int)(len - PARA_LEN))) {
+ n = len - PARA_LEN ;
+ printf(" BAD LENGTH\n") ;
+ break ;
+ }
+#ifdef LITTLE_ENDIAN
+ smt_swap_para(sm,smtlen,0) ;
+#endif
+ if (n < 24) {
+ dump_hex((char *)(pa+1),(int) n) ;
+ printf("\n") ;
+ }
+ else {
+ int first = 0 ;
+ c = (char *)(pa+1) ;
+ dump_hex(c,16) ;
+ printf("\n") ;
+ n -= 16 ;
+ c += 16 ;
+ while (n > 0) {
+ nn = (n > 16) ? 16 : n ;
+ if (n > 64) {
+ if (first == 0)
+ printf("\t\t\t...\n") ;
+ first = 1 ;
+ }
+ else {
+ printf("\t\t\t") ;
+ dump_hex(c,nn) ;
+ printf("\n") ;
+ }
+ n -= nn ;
+ c += 16 ;
+ }
+ }
+#ifdef LITTLE_ENDIAN
+ smt_swap_para(sm,smtlen,1) ;
+#endif
+ plen = (pa->p_len + PARA_LEN + 3) & ~3 ;
+ len -= plen ;
+ pa = (struct smt_para *)((char *)pa + plen) ;
+ }
+ printf("-------------------------------------------------\n\n") ;
+}
+
+void dump_hex(p,len)
+char *p ;
+int len ;
+{
+ int n = 0 ;
+ while (len--) {
+ n++ ;
+#ifdef UNIX
+ printf("%x%s",*p++ & 0xff,len ? ( (n & 7) ? " " : "-") : "") ;
+#else
+ printf("%02x%s",*p++ & 0xff,len ? ( (n & 7) ? " " : "-") : "") ;
+#endif
+ }
+}
+#endif /* no BOOT */
+#endif /* DEBUG */
+
+
+#endif /* no SLIM_SMT */
diff --git a/drivers/net/skfp/queue.c b/drivers/net/skfp/queue.c
new file mode 100644
index 000000000..e54b544ff
--- /dev/null
+++ b/drivers/net/skfp/queue.c
@@ -0,0 +1,185 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ SMT Event Queue Management
+*/
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)queue.c 2.9 97/08/04 (C) SK " ;
+#endif
+
+#define PRINTF(a,b,c)
+
+/*
+ * init event queue management
+ */
+void ev_init(smc)
+struct s_smc *smc ;
+{
+ smc->q.ev_put = smc->q.ev_get = smc->q.ev_queue ;
+}
+
+/*
+ * add event to queue
+ */
+void queue_event(smc,class,event)
+struct s_smc *smc ;
+int class ;
+int event ;
+{
+ PRINTF("queue class %d event %d\n",class,event) ;
+ smc->q.ev_put->class = class ;
+ smc->q.ev_put->event = event ;
+ if (++smc->q.ev_put == &smc->q.ev_queue[MAX_EVENT])
+ smc->q.ev_put = smc->q.ev_queue ;
+
+ if (smc->q.ev_put == smc->q.ev_get) {
+ SMT_ERR_LOG(smc,SMT_E0137, SMT_E0137_MSG) ;
+ }
+}
+
+/*
+ * timer_event is called from HW timer package.
+ */
+void timer_event(smc,token)
+struct s_smc *smc ;
+u_long token ;
+{
+ PRINTF("timer event class %d token %d\n",
+ EV_T_CLASS(token),
+ EV_T_EVENT(token)) ;
+ queue_event(smc,EV_T_CLASS(token),EV_T_EVENT(token));
+}
+
+/*
+ * event dispatcher
+ * while event queue is not empty
+ * get event from queue
+ * send command to state machine
+ * end
+ */
+void ev_dispatcher(smc)
+struct s_smc *smc ;
+{
+ struct event_queue *ev ; /* pointer into queue */
+ int class ;
+
+ ev = smc->q.ev_get ;
+ PRINTF("dispatch get %x put %x\n",ev,smc->q.ev_put) ;
+ while (ev != smc->q.ev_put) {
+ PRINTF("dispatch class %d event %d\n",ev->class,ev->event) ;
+ switch(class = ev->class) {
+ case EVENT_ECM : /* Entity Corordination Man. */
+ ecm(smc,(int)ev->event) ;
+ break ;
+ case EVENT_CFM : /* Configuration Man. */
+ cfm(smc,(int)ev->event) ;
+ break ;
+ case EVENT_RMT : /* Ring Man. */
+ rmt(smc,(int)ev->event) ;
+ break ;
+ case EVENT_SMT :
+ smt_event(smc,(int)ev->event) ;
+ break ;
+#ifdef CONCENTRATOR
+ case 99 :
+ timer_test_event(smc,(int)ev->event) ;
+ break ;
+#endif
+ case EVENT_PCMA : /* PHY A */
+ case EVENT_PCMB : /* PHY B */
+ default :
+ if (class >= EVENT_PCMA &&
+ class < EVENT_PCMA + NUMPHYS) {
+ pcm(smc,class - EVENT_PCMA,(int)ev->event) ;
+ break ;
+ }
+ SMT_PANIC(smc,SMT_E0121, SMT_E0121_MSG) ;
+ return ;
+ }
+
+ if (++ev == &smc->q.ev_queue[MAX_EVENT])
+ ev = smc->q.ev_queue ;
+
+ /* Renew get: it is used in queue_events to detect overruns */
+ smc->q.ev_get = ev;
+ }
+}
+
+/*
+ * smt_online connects to or disconnects from the ring
+ * MUST be called to initiate connection establishment
+ *
+ * on 0 disconnect
+ * on 1 connect
+ */
+u_short smt_online(smc,on)
+struct s_smc *smc ;
+int on ;
+{
+ queue_event(smc,EVENT_ECM,on ? EC_CONNECT : EC_DISCONNECT) ;
+ ev_dispatcher(smc) ;
+ return(smc->mib.fddiSMTCF_State) ;
+}
+
+/*
+ * set SMT flag to value
+ * flag flag name
+ * value flag value
+ * dump current flag setting
+ */
+#ifdef CONCENTRATOR
+void do_smt_flag(smc,flag,value)
+struct s_smc *smc ;
+char *flag ;
+int value ;
+{
+#ifdef DEBUG
+ struct smt_debug *deb;
+
+ SK_UNUSED(smc) ;
+
+#ifdef DEBUG_BRD
+ deb = &smc->debug;
+#else
+ deb = &debug;
+#endif
+ if (!strcmp(flag,"smt"))
+ deb->d_smt = value ;
+ else if (!strcmp(flag,"smtf"))
+ deb->d_smtf = value ;
+ else if (!strcmp(flag,"pcm"))
+ deb->d_pcm = value ;
+ else if (!strcmp(flag,"rmt"))
+ deb->d_rmt = value ;
+ else if (!strcmp(flag,"cfm"))
+ deb->d_cfm = value ;
+ else if (!strcmp(flag,"ecm"))
+ deb->d_ecm = value ;
+ printf("smt %d\n",deb->d_smt) ;
+ printf("smtf %d\n",deb->d_smtf) ;
+ printf("pcm %d\n",deb->d_pcm) ;
+ printf("rmt %d\n",deb->d_rmt) ;
+ printf("cfm %d\n",deb->d_cfm) ;
+ printf("ecm %d\n",deb->d_ecm) ;
+#endif /* DEBUG */
+}
+#endif
diff --git a/drivers/net/skfp/rmt.c b/drivers/net/skfp/rmt.c
new file mode 100644
index 000000000..473eb0c9c
--- /dev/null
+++ b/drivers/net/skfp/rmt.c
@@ -0,0 +1,674 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ SMT RMT
+ Ring Management
+*/
+
+/*
+ * Hardware independant state machine implemantation
+ * The following external SMT functions are referenced :
+ *
+ * queue_event()
+ * smt_timer_start()
+ * smt_timer_stop()
+ *
+ * The following external HW dependant functions are referenced :
+ * sm_ma_control()
+ * sm_mac_check_beacon_claim()
+ *
+ * The following HW dependant events are required :
+ * RM_RING_OP
+ * RM_RING_NON_OP
+ * RM_MY_BEACON
+ * RM_OTHER_BEACON
+ * RM_MY_CLAIM
+ * RM_TRT_EXP
+ * RM_VALID_CLAIM
+ *
+ */
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+
+#define KERNEL
+#include "h/smtstate.h"
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)rmt.c 2.13 99/07/02 (C) SK " ;
+#endif
+
+/*
+ * FSM Macros
+ */
+#define AFLAG 0x10
+#define GO_STATE(x) (smc->mib.m[MAC0].fddiMACRMTState = (x)|AFLAG)
+#define ACTIONS_DONE() (smc->mib.m[MAC0].fddiMACRMTState &= ~AFLAG)
+#define ACTIONS(x) (x|AFLAG)
+
+#define RM0_ISOLATED 0
+#define RM1_NON_OP 1 /* not operational */
+#define RM2_RING_OP 2 /* ring operational */
+#define RM3_DETECT 3 /* detect dupl addresses */
+#define RM4_NON_OP_DUP 4 /* dupl. addr detected */
+#define RM5_RING_OP_DUP 5 /* ring oper. with dupl. addr */
+#define RM6_DIRECTED 6 /* sending directed beacons */
+#define RM7_TRACE 7 /* trace initiated */
+
+#ifdef DEBUG
+/*
+ * symbolic state names
+ */
+static const char * const rmt_states[] = {
+ "RM0_ISOLATED","RM1_NON_OP","RM2_RING_OP","RM3_DETECT",
+ "RM4_NON_OP_DUP","RM5_RING_OP_DUP","RM6_DIRECTED",
+ "RM7_TRACE"
+} ;
+
+/*
+ * symbolic event names
+ */
+static const char * const rmt_events[] = {
+ "NONE","RM_RING_OP","RM_RING_NON_OP","RM_MY_BEACON",
+ "RM_OTHER_BEACON","RM_MY_CLAIM","RM_TRT_EXP","RM_VALID_CLAIM",
+ "RM_JOIN","RM_LOOP","RM_DUP_ADDR","RM_ENABLE_FLAG",
+ "RM_TIMEOUT_NON_OP","RM_TIMEOUT_T_STUCK",
+ "RM_TIMEOUT_ANNOUNCE","RM_TIMEOUT_T_DIRECT",
+ "RM_TIMEOUT_D_MAX","RM_TIMEOUT_POLL","RM_TX_STATE_CHANGE"
+} ;
+#endif
+
+/*
+ * Globals
+ * in struct s_rmt
+ */
+
+
+/*
+ * function declarations
+ */
+static void rmt_fsm() ;
+static void start_rmt_timer0() ;
+static void start_rmt_timer1() ;
+static void start_rmt_timer2() ;
+static void stop_rmt_timer0() ;
+static void stop_rmt_timer1() ;
+static void stop_rmt_timer2() ;
+static void rmt_dup_actions() ;
+static void rmt_reinsert_actions() ;
+static void rmt_leave_actions() ;
+static void rmt_new_dup_actions() ;
+
+#ifndef SUPERNET_3
+extern void restart_trt_for_dbcn() ;
+#endif /*SUPERNET_3*/
+
+/*
+ init RMT state machine
+ clear all RMT vars and flags
+*/
+void rmt_init(smc)
+struct s_smc *smc ;
+{
+ smc->mib.m[MAC0].fddiMACRMTState = ACTIONS(RM0_ISOLATED) ;
+ smc->r.dup_addr_test = DA_NONE ;
+ smc->r.da_flag = 0 ;
+ smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
+ smc->r.sm_ma_avail = FALSE ;
+ smc->r.loop_avail = 0 ;
+ smc->r.bn_flag = 0 ;
+ smc->r.jm_flag = 0 ;
+ smc->r.no_flag = TRUE ;
+}
+
+/*
+ RMT state machine
+ called by dispatcher
+
+ do
+ display state change
+ process event
+ until SM is stable
+*/
+void rmt(smc,event)
+struct s_smc *smc ;
+int event ;
+{
+ int state ;
+
+ do {
+ DB_RMT("RMT : state %s%s",
+ (smc->mib.m[MAC0].fddiMACRMTState & AFLAG) ? "ACTIONS " : "",
+ rmt_states[smc->mib.m[MAC0].fddiMACRMTState & ~AFLAG]) ;
+ DB_RMT(" event %s\n",rmt_events[event],0) ;
+ state = smc->mib.m[MAC0].fddiMACRMTState ;
+ rmt_fsm(smc,event) ;
+ event = 0 ;
+ } while (state != smc->mib.m[MAC0].fddiMACRMTState) ;
+ rmt_state_change(smc,(int)smc->mib.m[MAC0].fddiMACRMTState) ;
+}
+
+/*
+ process RMT event
+*/
+static void rmt_fsm(smc,cmd)
+struct s_smc *smc ;
+int cmd ;
+{
+ /*
+ * RM00-RM70 : from all states
+ */
+ if (!smc->r.rm_join && !smc->r.rm_loop &&
+ smc->mib.m[MAC0].fddiMACRMTState != ACTIONS(RM0_ISOLATED) &&
+ smc->mib.m[MAC0].fddiMACRMTState != RM0_ISOLATED) {
+ RS_SET(smc,RS_NORINGOP) ;
+ rmt_indication(smc,0) ;
+ GO_STATE(RM0_ISOLATED) ;
+ return ;
+ }
+
+ switch(smc->mib.m[MAC0].fddiMACRMTState) {
+ case ACTIONS(RM0_ISOLATED) :
+ stop_rmt_timer0(smc) ;
+ stop_rmt_timer1(smc) ;
+ stop_rmt_timer2(smc) ;
+
+ /*
+ * Disable MAC.
+ */
+ sm_ma_control(smc,MA_OFFLINE) ;
+ smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
+ smc->r.loop_avail = FALSE ;
+ smc->r.sm_ma_avail = FALSE ;
+ smc->r.no_flag = TRUE ;
+ DB_RMTN(1,"RMT : ISOLATED\n",0,0) ;
+ ACTIONS_DONE() ;
+ break ;
+ case RM0_ISOLATED :
+ /*RM01*/
+ if (smc->r.rm_join || smc->r.rm_loop) {
+ /*
+ * According to the standard the MAC must be reset
+ * here. The FORMAC will be initialized and Claim
+ * and Beacon Frames will be uploaded to the MAC.
+ * So any change of Treq will take effect NOW.
+ */
+ sm_ma_control(smc,MA_RESET) ;
+ GO_STATE(RM1_NON_OP) ;
+ break ;
+ }
+ break ;
+ case ACTIONS(RM1_NON_OP) :
+ start_rmt_timer0(smc,smc->s.rmt_t_non_op,RM_TIMEOUT_NON_OP) ;
+ stop_rmt_timer1(smc) ;
+ stop_rmt_timer2(smc) ;
+ sm_ma_control(smc,MA_BEACON) ;
+ DB_RMTN(1,"RMT : RING DOWN\n",0,0) ;
+ RS_SET(smc,RS_NORINGOP) ;
+ smc->r.sm_ma_avail = FALSE ;
+ rmt_indication(smc,0) ;
+ ACTIONS_DONE() ;
+ break ;
+ case RM1_NON_OP :
+ /*RM12*/
+ if (cmd == RM_RING_OP) {
+ RS_SET(smc,RS_RINGOPCHANGE) ;
+ GO_STATE(RM2_RING_OP) ;
+ break ;
+ }
+ /*RM13*/
+ else if (cmd == RM_TIMEOUT_NON_OP) {
+ smc->r.bn_flag = FALSE ;
+ smc->r.no_flag = TRUE ;
+ GO_STATE(RM3_DETECT) ;
+ break ;
+ }
+ break ;
+ case ACTIONS(RM2_RING_OP) :
+ stop_rmt_timer0(smc) ;
+ stop_rmt_timer1(smc) ;
+ stop_rmt_timer2(smc) ;
+ smc->r.no_flag = FALSE ;
+ if (smc->r.rm_loop)
+ smc->r.loop_avail = TRUE ;
+ if (smc->r.rm_join) {
+ smc->r.sm_ma_avail = TRUE ;
+ if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable)
+ smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ;
+ else
+ smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
+ }
+ DB_RMTN(1,"RMT : RING UP\n",0,0) ;
+ RS_CLEAR(smc,RS_NORINGOP) ;
+ RS_SET(smc,RS_RINGOPCHANGE) ;
+ rmt_indication(smc,1) ;
+ smt_stat_counter(smc,0) ;
+ ACTIONS_DONE() ;
+ break ;
+ case RM2_RING_OP :
+ /*RM21*/
+ if (cmd == RM_RING_NON_OP) {
+ smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
+ smc->r.loop_avail = FALSE ;
+ RS_SET(smc,RS_RINGOPCHANGE) ;
+ GO_STATE(RM1_NON_OP) ;
+ break ;
+ }
+ /*RM22a*/
+ else if (cmd == RM_ENABLE_FLAG) {
+ if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable)
+ smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ;
+ else
+ smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
+ }
+ /*RM25*/
+ else if (smc->r.dup_addr_test == DA_FAILED) {
+ smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
+ smc->r.loop_avail = FALSE ;
+ smc->r.da_flag = TRUE ;
+ GO_STATE(RM5_RING_OP_DUP) ;
+ break ;
+ }
+ break ;
+ case ACTIONS(RM3_DETECT) :
+ start_rmt_timer0(smc,smc->s.mac_d_max*2,RM_TIMEOUT_D_MAX) ;
+ start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ;
+ start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
+ sm_mac_check_beacon_claim(smc) ;
+ DB_RMTN(1,"RMT : RM3_DETECT\n",0,0) ;
+ ACTIONS_DONE() ;
+ break ;
+ case RM3_DETECT :
+ if (cmd == RM_TIMEOUT_POLL) {
+ start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
+ sm_mac_check_beacon_claim(smc) ;
+ break ;
+ }
+ if (cmd == RM_TIMEOUT_D_MAX) {
+ smc->r.timer0_exp = TRUE ;
+ }
+ /*
+ *jd(22-Feb-1999)
+ * We need a time ">= 2*mac_d_max" since we had finished
+ * Claim or Beacon state. So we will restart timer0 at
+ * every state change.
+ */
+ if (cmd == RM_TX_STATE_CHANGE) {
+ start_rmt_timer0(smc,
+ smc->s.mac_d_max*2,
+ RM_TIMEOUT_D_MAX) ;
+ }
+ /*RM32*/
+ if (cmd == RM_RING_OP) {
+ GO_STATE(RM2_RING_OP) ;
+ break ;
+ }
+ /*RM33a*/
+ else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON)
+ && smc->r.bn_flag) {
+ smc->r.bn_flag = FALSE ;
+ }
+ /*RM33b*/
+ else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) {
+ int tx ;
+ /*
+ * set bn_flag only if in state T4 or T5:
+ * only if we're the beaconer should we start the
+ * trace !
+ */
+ if ((tx = sm_mac_get_tx_state(smc)) == 4 || tx == 5) {
+ DB_RMTN(2,"RMT : DETECT && TRT_EXPIRED && T4/T5\n",0,0);
+ smc->r.bn_flag = TRUE ;
+ /*
+ * If one of the upstream stations beaconed
+ * and the link to the upstream neighbor is
+ * lost we need to restart the stuck timer to
+ * check the "stuck beacon" condition.
+ */
+ start_rmt_timer1(smc,smc->s.rmt_t_stuck,
+ RM_TIMEOUT_T_STUCK) ;
+ }
+ /*
+ * We do NOT need to clear smc->r.bn_flag in case of
+ * not being in state T4 or T5, because the flag
+ * must be cleared in order to get in this condition.
+ */
+
+ DB_RMTN(2,
+ "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)\n",
+ tx,smc->r.bn_flag) ;
+ }
+ /*RM34a*/
+ else if (cmd == RM_MY_CLAIM && smc->r.timer0_exp) {
+ rmt_new_dup_actions(smc) ;
+ GO_STATE(RM4_NON_OP_DUP) ;
+ break ;
+ }
+ /*RM34b*/
+ else if (cmd == RM_MY_BEACON && smc->r.timer0_exp) {
+ rmt_new_dup_actions(smc) ;
+ GO_STATE(RM4_NON_OP_DUP) ;
+ break ;
+ }
+ /*RM34c*/
+ else if (cmd == RM_VALID_CLAIM) {
+ rmt_new_dup_actions(smc) ;
+ GO_STATE(RM4_NON_OP_DUP) ;
+ break ;
+ }
+ /*RM36*/
+ else if (cmd == RM_TIMEOUT_T_STUCK &&
+ smc->r.rm_join && smc->r.bn_flag) {
+ GO_STATE(RM6_DIRECTED) ;
+ break ;
+ }
+ break ;
+ case ACTIONS(RM4_NON_OP_DUP) :
+ start_rmt_timer0(smc,smc->s.rmt_t_announce,RM_TIMEOUT_ANNOUNCE);
+ start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ;
+ start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
+ sm_mac_check_beacon_claim(smc) ;
+ DB_RMTN(1,"RMT : RM4_NON_OP_DUP\n",0,0) ;
+ ACTIONS_DONE() ;
+ break ;
+ case RM4_NON_OP_DUP :
+ if (cmd == RM_TIMEOUT_POLL) {
+ start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
+ sm_mac_check_beacon_claim(smc) ;
+ break ;
+ }
+ /*RM41*/
+ if (!smc->r.da_flag) {
+ GO_STATE(RM1_NON_OP) ;
+ break ;
+ }
+ /*RM44a*/
+ else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
+ smc->r.bn_flag) {
+ smc->r.bn_flag = FALSE ;
+ }
+ /*RM44b*/
+ else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) {
+ int tx ;
+ /*
+ * set bn_flag only if in state T4 or T5:
+ * only if we're the beaconer should we start the
+ * trace !
+ */
+ if ((tx = sm_mac_get_tx_state(smc)) == 4 || tx == 5) {
+ DB_RMTN(2,"RMT : NOPDUP && TRT_EXPIRED && T4/T5\n",0,0);
+ smc->r.bn_flag = TRUE ;
+ /*
+ * If one of the upstream stations beaconed
+ * and the link to the upstream neighbor is
+ * lost we need to restart the stuck timer to
+ * check the "stuck beacon" condition.
+ */
+ start_rmt_timer1(smc,smc->s.rmt_t_stuck,
+ RM_TIMEOUT_T_STUCK) ;
+ }
+ /*
+ * We do NOT need to clear smc->r.bn_flag in case of
+ * not being in state T4 or T5, because the flag
+ * must be cleared in order to get in this condition.
+ */
+
+ DB_RMTN(2,
+ "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)\n",
+ tx,smc->r.bn_flag) ;
+ }
+ /*RM44c*/
+ else if (cmd == RM_TIMEOUT_ANNOUNCE && !smc->r.bn_flag) {
+ rmt_dup_actions(smc) ;
+ }
+ /*RM45*/
+ else if (cmd == RM_RING_OP) {
+ smc->r.no_flag = FALSE ;
+ GO_STATE(RM5_RING_OP_DUP) ;
+ break ;
+ }
+ /*RM46*/
+ else if (cmd == RM_TIMEOUT_T_STUCK &&
+ smc->r.rm_join && smc->r.bn_flag) {
+ GO_STATE(RM6_DIRECTED) ;
+ break ;
+ }
+ break ;
+ case ACTIONS(RM5_RING_OP_DUP) :
+ stop_rmt_timer0(smc) ;
+ stop_rmt_timer1(smc) ;
+ stop_rmt_timer2(smc) ;
+ DB_RMTN(1,"RMT : RM5_RING_OP_DUP\n",0,0) ;
+ ACTIONS_DONE() ;
+ break;
+ case RM5_RING_OP_DUP :
+ /*RM52*/
+ if (smc->r.dup_addr_test == DA_PASSED) {
+ smc->r.da_flag = FALSE ;
+ GO_STATE(RM2_RING_OP) ;
+ break ;
+ }
+ /*RM54*/
+ else if (cmd == RM_RING_NON_OP) {
+ smc->r.jm_flag = FALSE ;
+ smc->r.bn_flag = FALSE ;
+ GO_STATE(RM4_NON_OP_DUP) ;
+ break ;
+ }
+ break ;
+ case ACTIONS(RM6_DIRECTED) :
+ start_rmt_timer0(smc,smc->s.rmt_t_direct,RM_TIMEOUT_T_DIRECT) ;
+ stop_rmt_timer1(smc) ;
+ start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
+ sm_ma_control(smc,MA_DIRECTED) ;
+ RS_SET(smc,RS_BEACON) ;
+ DB_RMTN(1,"RMT : RM6_DIRECTED\n",0,0) ;
+ ACTIONS_DONE() ;
+ break ;
+ case RM6_DIRECTED :
+ /*RM63*/
+ if (cmd == RM_TIMEOUT_POLL) {
+ start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
+ sm_mac_check_beacon_claim(smc) ;
+#ifndef SUPERNET_3
+ /* Because of problems with the Supernet II chip set
+ * sending of Directed Beacon will stop after 165ms
+ * therefore restart_trt_for_dbcn(smc) will be called
+ * to prevent this.
+ */
+ restart_trt_for_dbcn(smc) ;
+#endif /*SUPERNET_3*/
+ break ;
+ }
+ if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
+ !smc->r.da_flag) {
+ smc->r.bn_flag = FALSE ;
+ GO_STATE(RM3_DETECT) ;
+ break ;
+ }
+ /*RM64*/
+ else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
+ smc->r.da_flag) {
+ smc->r.bn_flag = FALSE ;
+ GO_STATE(RM4_NON_OP_DUP) ;
+ break ;
+ }
+ /*RM67*/
+ else if (cmd == RM_TIMEOUT_T_DIRECT) {
+ GO_STATE(RM7_TRACE) ;
+ break ;
+ }
+ break ;
+ case ACTIONS(RM7_TRACE) :
+ stop_rmt_timer0(smc) ;
+ stop_rmt_timer1(smc) ;
+ stop_rmt_timer2(smc) ;
+ smc->e.trace_prop |= ENTITY_BIT(ENTITY_MAC) ;
+ queue_event(smc,EVENT_ECM,EC_TRACE_PROP) ;
+ DB_RMTN(1,"RMT : RM7_TRACE\n",0,0) ;
+ ACTIONS_DONE() ;
+ break ;
+ case RM7_TRACE :
+ break ;
+ default:
+ SMT_PANIC(smc,SMT_E0122, SMT_E0122_MSG) ;
+ break;
+ }
+}
+
+/*
+ * (jd) RMT duplicate address actions
+ * leave the ring or reinsert just as configured
+ */
+static void rmt_dup_actions(smc)
+struct s_smc *smc ;
+{
+ if (smc->r.jm_flag) {
+ }
+ else {
+ if (smc->s.rmt_dup_mac_behavior) {
+ SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ;
+ rmt_reinsert_actions(smc) ;
+ }
+ else {
+ SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ;
+ rmt_leave_actions(smc) ;
+ }
+ }
+}
+
+/*
+ * Reconnect to the Ring
+ */
+static void rmt_reinsert_actions(smc)
+struct s_smc *smc ;
+{
+ queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
+ queue_event(smc,EVENT_ECM,EC_CONNECT) ;
+}
+
+/*
+ * duplicate address detected
+ */
+static void rmt_new_dup_actions(smc)
+struct s_smc *smc ;
+{
+ smc->r.da_flag = TRUE ;
+ smc->r.bn_flag = FALSE ;
+ smc->r.jm_flag = FALSE ;
+ /*
+ * we have three options : change address, jam or leave
+ * we leave the ring as default
+ * Optionally it's possible to reinsert after leaving the Ring
+ * but this will not conform with SMT Spec.
+ */
+ if (smc->s.rmt_dup_mac_behavior) {
+ SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ;
+ rmt_reinsert_actions(smc) ;
+ }
+ else {
+ SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ;
+ rmt_leave_actions(smc) ;
+ }
+}
+
+
+/*
+ * leave the ring
+ */
+static void rmt_leave_actions(smc)
+struct s_smc *smc ;
+{
+ queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
+ /*
+ * Note: Do NOT try again later. (with please reconnect)
+ * The station must be left from the ring!
+ */
+}
+
+/*
+ * SMT timer interface
+ * start RMT timer 0
+ */
+static void start_rmt_timer0(smc,value,event)
+struct s_smc *smc ;
+u_long value ;
+int event ;
+{
+ smc->r.timer0_exp = FALSE ; /* clear timer event flag */
+ smt_timer_start(smc,&smc->r.rmt_timer0,value,EV_TOKEN(EVENT_RMT,event));
+}
+
+/*
+ * SMT timer interface
+ * start RMT timer 1
+ */
+static void start_rmt_timer1(smc,value,event)
+struct s_smc *smc ;
+u_long value ;
+int event ;
+{
+ smc->r.timer1_exp = FALSE ; /* clear timer event flag */
+ smt_timer_start(smc,&smc->r.rmt_timer1,value,EV_TOKEN(EVENT_RMT,event));
+}
+
+/*
+ * SMT timer interface
+ * start RMT timer 2
+ */
+static void start_rmt_timer2(smc,value,event)
+struct s_smc *smc ;
+u_long value ;
+int event ;
+{
+ smc->r.timer2_exp = FALSE ; /* clear timer event flag */
+ smt_timer_start(smc,&smc->r.rmt_timer2,value,EV_TOKEN(EVENT_RMT,event));
+}
+
+/*
+ * SMT timer interface
+ * stop RMT timer 0
+ */
+static void stop_rmt_timer0(smc)
+struct s_smc *smc ;
+{
+ if (smc->r.rmt_timer0.tm_active)
+ smt_timer_stop(smc,&smc->r.rmt_timer0) ;
+}
+
+/*
+ * SMT timer interface
+ * stop RMT timer 1
+ */
+static void stop_rmt_timer1(smc)
+struct s_smc *smc ;
+{
+ if (smc->r.rmt_timer1.tm_active)
+ smt_timer_stop(smc,&smc->r.rmt_timer1) ;
+}
+
+/*
+ * SMT timer interface
+ * stop RMT timer 2
+ */
+static void stop_rmt_timer2(smc)
+struct s_smc *smc ;
+{
+ if (smc->r.rmt_timer2.tm_active)
+ smt_timer_stop(smc,&smc->r.rmt_timer2) ;
+}
diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
new file mode 100644
index 000000000..6aceec4d5
--- /dev/null
+++ b/drivers/net/skfp/skfddi.c
@@ -0,0 +1,2495 @@
+/*
+ * File Name:
+ * skfddi.c
+ *
+ * Copyright Information:
+ * Copyright SysKonnect 1998,1999.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ * Abstract:
+ * A Linux device driver supporting the SysKonnect FDDI PCI controller
+ * familie.
+ *
+ * Maintainers:
+ * CG Christoph Goos (cgoos@syskonnect.de)
+ *
+ * Address all question to:
+ * linux@syskonnect.de
+ *
+ * The technical manual for the adapters is available from SysKonnect's
+ * web pages: www.syskonnect.com
+ * Goto "Support" and search Knowledge Base for "manual".
+ *
+ * Driver Architecture:
+ * The driver architecture is based on the DEC FDDI driver by
+ * Lawrence V. Stefani and several ethernet drivers.
+ * I also used an existing Windows NT miniport driver.
+ * All hardware dependant fuctions are handled by the SysKonnect
+ * Hardware Module.
+ * The only headerfiles that are directly related to this source
+ * are skfddi.c, h/types.h, h/osdef1st.h, h/targetos.h.
+ * The others belong to the SysKonnect FDDI Hardware Module and
+ * should better not be changed.
+ * NOTE:
+ * Compiling this driver produces some warnings, but I did not fix
+ * this, because the Hardware Module source is used for different
+ * drivers, and fixing it for Linux might bring problems on other
+ * projects. To keep the source common for all those drivers (and
+ * thus simplify fixes to it), please do not clean it up!
+ *
+ * Modification History:
+ * Date Name Description
+ * 02-Mar-98 CG Created.
+ *
+ * 10-Mar-99 CG Support for 2.2.x added.
+ * 25-Mar-99 CG Corrected IRQ routing for SMP (APIC)
+ * 26-Oct-99 CG Fixed compilation error on 2.2.13
+ * 12-Nov-99 CG Source code release
+ * 22-Nov-99 CG Included in kernel source.
+ *
+ * Compilation options (-Dxxx):
+ * DRIVERDEBUG print lots of messages to log file
+ * DUMPPACKETS print received/transmitted packets to logfile
+ *
+ * Limitations:
+ * I changed the driver to support memory mapped I/O, so it
+ * might run on non-x86 architectures (not tested).
+ * But the hardware module does not yet support 64 bit OS'es.
+ */
+
+/* Version information string - should be updated prior to */
+/* each new release!!! */
+#define VERSION "2.05"
+
+static const char *boot_msg =
+ "SysKonnect FDDI PCI Adapter driver v" VERSION " for\n"
+ " SK-55xx/SK-58xx adapters (SK-NET FDDI-FP/UP/LP)";
+
+/* Include files */
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <asm/byteorder.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/ctype.h> // isdigit
+
+#include <linux/netdevice.h>
+#include <linux/fddidevice.h>
+#include <linux/skbuff.h>
+
+#include "h/types.h"
+#undef ADDR // undo Linux definition
+#include "h/skfbi.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/smtstate.h"
+
+
+// Define global routines
+int skfp_probe(struct net_device *dev);
+
+
+// Define module-wide (static) routines
+static struct net_device *alloc_device(struct net_device *dev, u_long iobase);
+static struct net_device *insert_device(struct net_device *dev,
+ int (*init) (struct net_device *));
+static int fddi_dev_index(unsigned char *s);
+static void init_dev(struct net_device *dev, u_long iobase);
+static void link_modules(struct net_device *dev, struct net_device *tmp);
+static int skfp_driver_init(struct net_device *dev);
+static int skfp_open(struct net_device *dev);
+static int skfp_close(struct net_device *dev);
+static void skfp_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static struct enet_statistics *skfp_ctl_get_stats(struct net_device *dev);
+static void skfp_ctl_set_multicast_list(struct net_device *dev);
+static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev);
+static int skfp_ctl_set_mac_address(struct net_device *dev, void *addr);
+static int skfp_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int skfp_send_pkt(struct sk_buff *skb, struct net_device *dev);
+static void send_queued_packets(struct s_smc *smc);
+static void CheckSourceAddress(unsigned char *frame, unsigned char *hw_addr);
+static void ResetAdapter(struct s_smc *smc);
+
+
+// Functions needed by the hardware module
+void *mac_drv_get_space(struct s_smc *smc, u_int size);
+void *mac_drv_get_desc_mem(struct s_smc *smc, u_int size);
+unsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt);
+unsigned long dma_master(struct s_smc *smc, void *virt, int len, int flag);
+void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr,
+ int flag);
+void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd);
+void llc_restart_tx(struct s_smc *smc);
+void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
+ int frag_count, int len);
+void mac_drv_requeue_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
+ int frag_count);
+void mac_drv_fill_rxd(struct s_smc *smc);
+void mac_drv_clear_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
+ int frag_count);
+int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead,
+ int la_len);
+void smt_timer_poll(struct s_smc *smc);
+void ring_status_indication(struct s_smc *smc, u_long status);
+unsigned long smt_get_time(void);
+void smt_stat_counter(struct s_smc *smc, int stat);
+void cfm_state_change(struct s_smc *smc, int c_state);
+void ecm_state_change(struct s_smc *smc, int e_state);
+void pcm_state_change(struct s_smc *smc, int plc, int p_state);
+void rmt_state_change(struct s_smc *smc, int r_state);
+void drv_reset_indication(struct s_smc *smc);
+void dump_data(unsigned char *Data, int length);
+
+
+// External functions from the hardware module
+extern u_int mac_drv_check_space();
+extern void read_address(struct s_smc *smc, u_char * mac_addr);
+extern void card_stop(struct s_smc *smc);
+extern int mac_drv_init(struct s_smc *smc);
+extern void hwm_tx_frag(struct s_smc *smc, char far * virt, u_long phys,
+ int len, int frame_status);
+extern int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count,
+ int frame_len, int frame_status);
+extern int init_smt(struct s_smc *smc, u_char * mac_addr);
+extern void fddi_isr(struct s_smc *smc);
+extern void hwm_rx_frag(struct s_smc *smc, char far * virt, u_long phys,
+ int len, int frame_status);
+extern void mac_drv_rx_mode(struct s_smc *smc, int mode);
+extern void mac_drv_clear_tx_queue(struct s_smc *smc);
+extern void mac_drv_clear_rx_queue(struct s_smc *smc);
+extern void mac_clear_multicast(struct s_smc *smc);
+extern void enable_tx_irq(struct s_smc *smc, u_short queue);
+extern void mac_drv_clear_txd(struct s_smc *smc);
+
+
+// Define module-wide (static) variables
+
+static int num_boards = 0; /* total number of adapters configured */
+static int num_fddi = 0;
+static int autoprobed = 0;
+
+#ifdef MODULE
+int init_module(void);
+void cleanup_module(void);
+static struct net_device *unlink_modules(struct net_device *p);
+static int loading_module = 1;
+#else
+static int loading_module = 0;
+#endif // MODULE
+
+#ifdef DRIVERDEBUG
+#define PRINTK(s, args...) printk(s, ## args)
+#else
+#define PRINTK(s, args...)
+#endif // DRIVERDEBUG
+
+#define PRIV(dev) (&(((struct s_smc *)dev->priv)->os))
+
+/*
+ * ==============
+ * = skfp_probe =
+ * ==============
+ *
+ * Overview:
+ * Probes for supported FDDI PCI controllers
+ *
+ * Returns:
+ * Condition code
+ *
+ * Arguments:
+ * dev - pointer to device information
+ *
+ * Functional Description:
+ * This routine is called by the OS for each FDDI device name (fddi0,
+ * fddi1,...,fddi6, fddi7) specified in drivers/net/Space.c.
+ * If loaded as a module, it will detect and initialize all
+ * adapters the first time it is called.
+ *
+ * Let's say that skfp_probe() is getting called to initialize fddi0.
+ * Furthermore, let's say there are three supported controllers in the
+ * system. Before skfp_probe() leaves, devices fddi0, fddi1, and fddi2
+ * will be initialized and a global flag will be set to indicate that
+ * skfp_probe() has already been called.
+ *
+ * However...the OS doesn't know that we've already initialized
+ * devices fddi1 and fddi2 so skfp_probe() gets called again and again
+ * until it reaches the end of the device list for FDDI (presently,
+ * fddi7). It's important that the driver "pretend" to probe for
+ * devices fddi1 and fddi2 and return success. Devices fddi3
+ * through fddi7 will return failure since they weren't initialized.
+ *
+ * This algorithm seems to work for the time being. As other FDDI
+ * drivers are written for Linux, a more generic approach (perhaps
+ * similar to the Ethernet card approach) may need to be implemented.
+ *
+ * Return Codes:
+ * 0 - This device (fddi0, fddi1, etc) configured successfully
+ * -ENODEV - No devices present, or no SysKonnect FDDI PCI device
+ * present for this device name
+ *
+ *
+ * Side Effects:
+ * Device structures for FDDI adapters (fddi0, fddi1, etc) are
+ * initialized and the board resources are read and stored in
+ * the device structure.
+ */
+int skfp_probe(struct net_device *dev)
+{
+ int i; /* used in for loops */
+ struct pci_dev *pdev = NULL; /* PCI device structure */
+#ifndef MEM_MAPPED_IO
+ u16 port; /* temporary I/O (port) address */
+ int port_len; /* length of port address range (in bytes) */
+#else
+ unsigned long port;
+#endif
+ u16 command; /* PCI Configuration space Command register val */
+ struct s_smc *smc; /* board pointer */
+ struct net_device *tmp = dev;
+ u8 first_dev_used = 0;
+ u16 SubSysId;
+
+ PRINTK(KERN_INFO "entering skfp_probe\n");
+
+ /*
+ * Verify whether we're going through skfp_probe() again
+ *
+ * If so, see if we're going through for a subsequent fddi device that
+ * we've already initialized. If we are, return success (0). If not,
+ * return failure (-ENODEV).
+ */
+
+ if (autoprobed) {
+ PRINTK(KERN_INFO "Already entered skfp_probe\n");
+ if (dev != NULL) {
+ if ((strncmp(dev->name, "fddi", 4) == 0) &&
+ (dev->base_addr != 0)) {
+ return (0);
+ }
+ return (-ENODEV);
+ }
+ }
+ autoprobed = 1; /* set global flag */
+
+ printk("%s\n", boot_msg);
+
+ /* Scan for Syskonnect FDDI PCI controllers */
+ if (!pci_present()) { /* is PCI BIOS even present? */
+ printk("no PCI BIOS present\n");
+ return (-ENODEV);
+ }
+ for (i = 0; i < SKFP_MAX_NUM_BOARDS; i++) { // scan for PCI cards
+ PRINTK(KERN_INFO "Check device %d\n", i);
+ if ((pdev=pci_find_device(PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP,
+ pdev)) == 0) {
+ break;
+ }
+
+#ifndef MEM_MAPPED_IO
+ /* Verify that I/O enable bit is set (PCI slot is enabled) */
+ pci_read_config_word(pdev, PCI_COMMAND, &command);
+ if ((command & PCI_COMMAND_IO) == 0) {
+ PRINTK("I/O enable bit not set!");
+ PRINTK(" Verify that slot is enabled\n");
+ continue;
+ }
+
+ /* Turn off memory mapped space and enable mastering */
+
+ PRINTK(KERN_INFO "Command Reg: %04x\n", command);
+ command |= PCI_COMMAND_MASTER;
+ command &= ~PCI_COMMAND_MEMORY;
+ pci_write_config_word(pdev, PCI_COMMAND, command);
+
+ /* Read I/O base address from PCI Configuration Space */
+
+ pci_read_config_word(pdev, PCI_BASE_ADDRESS_1, &port);
+ port &= PCI_BASE_ADDRESS_IO_MASK; // clear I/O bit (bit 0)
+
+ /* Verify port address range is not already being used */
+
+ port_len = FP_IO_LEN;
+ if (check_region(port, port_len) != 0) {
+ printk("I/O range allocated to adapter");
+ printk(" (0x%X-0x%X) is already being used!\n", port,
+ (port + port_len - 1));
+ continue;
+ }
+#else
+ /* Verify that MEM enable bit is set (PCI slot is enabled) */
+ pci_read_config_word(pdev, PCI_COMMAND, &command);
+ if ((command & PCI_COMMAND_MEMORY) == 0) {
+ PRINTK("MEMORY-I/O enable bit not set!");
+ PRINTK(" Verify that slot is enabled\n");
+ continue;
+ }
+
+ /* Turn off IO mapped space and enable mastering */
+
+ PRINTK(KERN_INFO "Command Reg: %04x\n", command);
+ command |= PCI_COMMAND_MASTER;
+ command &= ~PCI_COMMAND_IO;
+ pci_write_config_word(pdev, PCI_COMMAND, command);
+
+ port = pdev->resource[0].start;
+
+ port = (unsigned long)ioremap(port, 0x4000);
+ if (!port){
+ printk("skfp: Unable to map MEMORY register, "
+ "FDDI adapter will be disabled.\n");
+ break;
+ }
+#endif
+
+ if ((!loading_module) || first_dev_used) {
+ /* Allocate a device structure for this adapter */
+ tmp = alloc_device(dev, port);
+ }
+ first_dev_used = 1; // only significant first time
+
+ pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &SubSysId);
+
+ if (tmp != NULL) {
+ if (loading_module)
+ link_modules(dev, tmp);
+ dev = tmp;
+ init_dev(dev, port);
+ dev->irq = pdev->irq;
+
+ /* Initialize board structure with bus-specific info */
+
+ smc = (struct s_smc *) dev->priv;
+ smc->os.dev = dev;
+ smc->os.bus_type = SK_BUS_TYPE_PCI;
+ smc->os.pdev = *pdev;
+ smc->os.QueueSkb = MAX_TX_QUEUE_LEN;
+ smc->os.MaxFrameSize = MAX_FRAME_SIZE;
+ smc->os.dev = dev;
+ smc->hw.slot = -1;
+ smc->os.ResetRequested = FALSE;
+ skb_queue_head_init(&smc->os.SendSkbQueue);
+
+ if (skfp_driver_init(dev) == 0) {
+ // only increment global board
+ // count on success
+ num_boards++;
+ request_region(dev->base_addr,
+ FP_IO_LEN, dev->name);
+ if ((SubSysId & 0xff00) == 0x5500 ||
+ (SubSysId & 0xff00) == 0x5800) {
+ printk("%s: SysKonnect FDDI PCI adapter"
+ " found (SK-%04X)\n", dev->name,
+ SubSysId);
+ } else {
+ printk("%s: FDDI PCI adapter found\n",
+ dev->name);
+ }
+ } else {
+ kfree(dev);
+ i = SKFP_MAX_NUM_BOARDS; // stop search
+
+ }
+
+ } // if (dev != NULL)
+
+ } // for SKFP_MAX_NUM_BOARDS
+
+ /*
+ * If we're at this point we're going through skfp_probe() for the
+ * first time. Return success (0) if we've initialized 1 or more
+ * boards. Otherwise, return failure (-ENODEV).
+ */
+
+ if (num_boards > 0)
+ return (0);
+ else {
+ printk("no SysKonnect FDDI adapter found\n");
+ return (-ENODEV);
+ }
+} // skfp_probe
+
+
+/************************
+ *
+ * Search the entire 'fddi' device list for a fixed probe. If a match isn't
+ * found then check for an autoprobe or unused device location. If they
+ * are not available then insert a new device structure at the end of
+ * the current list.
+ *
+ ************************/
+static struct net_device *alloc_device(struct net_device *dev, u_long iobase)
+{
+ struct net_device *adev = NULL;
+ int fixed = 0, new_dev = 0;
+
+ PRINTK(KERN_INFO "entering alloc_device\n");
+ if (!dev)
+ return dev;
+
+ num_fddi = fddi_dev_index(dev->name);
+ if (loading_module) {
+ num_fddi++;
+ dev = insert_device(dev, skfp_probe);
+ return dev;
+ }
+ while (1) {
+ if (((dev->base_addr == NO_ADDRESS) ||
+ (dev->base_addr == 0)) && !adev) {
+ adev = dev;
+ } else if ((dev->priv == NULL) && (dev->base_addr == iobase)) {
+ fixed = 1;
+ } else {
+ if (dev->next == NULL) {
+ new_dev = 1;
+ } else if (strncmp(dev->next->name, "fddi", 4) != 0) {
+ new_dev = 1;
+ }
+ }
+ if ((dev->next == NULL) || new_dev || fixed)
+ break;
+ dev = dev->next;
+ num_fddi++;
+ } // while (1)
+
+ if (adev && !fixed) {
+ dev = adev;
+ num_fddi = fddi_dev_index(dev->name);
+ new_dev = 0;
+ }
+ if (((dev->next == NULL) && ((dev->base_addr != NO_ADDRESS) &&
+ (dev->base_addr != 0)) && !fixed) ||
+ new_dev) {
+ num_fddi++; /* New device */
+ dev = insert_device(dev, skfp_probe);
+ }
+ if (dev) {
+ if (!dev->priv) {
+ /* Allocate space for private board structure */
+ dev->priv = (void *) kmalloc(sizeof(struct s_smc),
+ GFP_KERNEL);
+ if (dev->priv == NULL) {
+ printk("%s: Could not allocate memory for",
+ dev->name);
+ printk(" private board structure!\n");
+ return (NULL);
+ }
+ /* clear structure */
+ memset(dev->priv, 0, sizeof(struct s_smc));
+ }
+ }
+ return dev;
+} // alloc_device
+
+
+
+/************************
+ *
+ * Initialize device structure
+ *
+ ************************/
+static void init_dev(struct net_device *dev, u_long iobase)
+{
+ /* Initialize new device structure */
+
+ dev->rmem_end = 0; /* shared memory isn't used */
+ dev->rmem_start = 0; /* shared memory isn't used */
+ dev->mem_end = 0; /* shared memory isn't used */
+ dev->mem_start = 0; /* shared memory isn't used */
+ dev->base_addr = iobase; /* save port (I/O) base address */
+ dev->if_port = 0; /* not applicable to FDDI adapters */
+ dev->dma = 0; /* Bus Master DMA doesn't require channel */
+ dev->irq = 0;
+
+ netif_start_queue(dev);
+
+ dev->get_stats = &skfp_ctl_get_stats;
+ dev->open = &skfp_open;
+ dev->stop = &skfp_close;
+ dev->hard_start_xmit = &skfp_send_pkt;
+ dev->hard_header = NULL; /* set in fddi_setup() */
+ dev->rebuild_header = NULL; /* set in fddi_setup() */
+ dev->set_multicast_list = &skfp_ctl_set_multicast_list;
+ dev->set_mac_address = &skfp_ctl_set_mac_address;
+ dev->do_ioctl = &skfp_ioctl;
+ dev->set_config = NULL; /* not supported for now &&& */
+ dev->header_cache_update = NULL; /* not supported */
+ dev->change_mtu = NULL; /* set in fddi_setup() */
+
+ /* Initialize remaining device structure information */
+ fddi_setup(dev);
+} // init_device
+
+
+/************************
+ *
+ * If at end of fddi device list and can't use current entry, malloc
+ * one up. If memory could not be allocated, print an error message.
+ *
+************************/
+static struct net_device *insert_device(struct net_device *dev,
+ int (*init) (struct net_device *))
+{
+ struct net_device *new;
+ int len;
+
+ PRINTK(KERN_INFO "entering insert_device\n");
+ len = sizeof(struct net_device) + 8 + sizeof(struct s_smc);
+ new = (struct net_device *) kmalloc(len, GFP_KERNEL);
+ if (new == NULL) {
+ printk("fddi%d: Device not initialised, insufficient memory\n",
+ num_fddi);
+ return NULL;
+ } else {
+ memset((char *) new, 0, len);
+ new->name = (char *) (new + 1);
+ new->priv = (struct s_smc *) (new->name + 8);
+ new->init = init; /* initialisation routine */
+ if (!loading_module) {
+ new->next = dev->next;
+ dev->next = new;
+ }
+ /* create new device name */
+ if (num_fddi > 999) {
+ sprintf(new->name, "fddi????");
+ } else {
+ sprintf(new->name, "fddi%d", num_fddi);
+ }
+ }
+ return new;
+} // insert_device
+
+
+/************************
+ *
+ * Get the number of a "fddiX" string
+ *
+ ************************/
+static int fddi_dev_index(unsigned char *s)
+{
+ int i = 0, j = 0;
+
+ for (; *s; s++) {
+ if (isdigit(*s)) {
+ j = 1;
+ i = (i * 10) + (*s - '0');
+ } else if (j)
+ break;
+ }
+ return i;
+} // fddi_dev_index
+
+
+/************************
+ *
+ * Used if loaded as module only. Link the device structures
+ * together. Needed to release them all at unload.
+ *
+************************/
+static void link_modules(struct net_device *dev, struct net_device *tmp)
+{
+ struct net_device *p = dev;
+
+ if (p) {
+ while (((struct s_smc *) (p->priv))->os.next_module) {
+ p = ((struct s_smc *) (p->priv))->os.next_module;
+ }
+
+ if (dev != tmp) {
+ ((struct s_smc *) (p->priv))->os.next_module = tmp;
+ } else {
+ ((struct s_smc *) (p->priv))->os.next_module = NULL;
+ }
+ }
+ return;
+} // link_modules
+
+
+
+/*
+ * ====================
+ * = skfp_driver_init =
+ * ====================
+ *
+ * Overview:
+ * Initializes remaining adapter board structure information
+ * and makes sure adapter is in a safe state prior to skfp_open().
+ *
+ * Returns:
+ * Condition code
+ *
+ * Arguments:
+ * dev - pointer to device information
+ *
+ * Functional Description:
+ * This function allocates additional resources such as the host memory
+ * blocks needed by the adapter.
+ * The adapter is also reset. The OS must call skfp_open() to open
+ * the adapter and bring it on-line.
+ *
+ * Return Codes:
+ * 0 - initialization succeeded
+ * -1 - initialization failed
+ */
+static int skfp_driver_init(struct net_device *dev)
+{
+ struct s_smc *smc = (struct s_smc *) dev->priv;
+ skfddi_priv *bp = PRIV(dev);
+ u8 val; /* used for I/O read/writes */
+
+ PRINTK(KERN_INFO "entering skfp_driver_init\n");
+
+ // set the io address in private structures
+ bp->base_addr = dev->base_addr;
+ smc->hw.iop = dev->base_addr;
+
+ // Get the interrupt level from the PCI Configuration Table
+ val = dev->irq;
+
+ smc->hw.irq = val;
+
+ spin_lock_init(&bp->DriverLock);
+
+ // Determine the required size of the 'shared' memory area.
+ bp->SharedMemSize = mac_drv_check_space();
+ PRINTK(KERN_INFO "Memory for HWM: %ld\n", bp->SharedMemSize);
+ if (bp->SharedMemSize > 0) {
+ bp->SharedMemSize += 16; // for descriptor alignment
+
+ bp->SharedMemAddr = kmalloc(bp->SharedMemSize, GFP_KERNEL);
+ if (!bp->SharedMemSize) {
+ printk("could not allocate mem for ");
+ printk("hardware module: %ld byte\n",
+ bp->SharedMemSize);
+ return (-1);
+ }
+ bp->SharedMemHeap = 0; // Nothing used yet.
+
+ } else {
+ bp->SharedMemAddr = NULL;
+ bp->SharedMemHeap = 0;
+ } // SharedMemSize > 0
+
+ memset(bp->SharedMemAddr, 0, bp->SharedMemSize);
+
+ card_stop(smc); // Reset adapter.
+
+ PRINTK(KERN_INFO "mac_drv_init()..\n");
+ if (mac_drv_init(smc) != 0) {
+ PRINTK(KERN_INFO "mac_drv_init() failed.\n");
+ return (-1);
+ }
+ read_address(smc, NULL);
+ PRINTK(KERN_INFO "HW-Addr: %02x %02x %02x %02x %02x %02x\n",
+ smc->hw.fddi_canon_addr.a[0],
+ smc->hw.fddi_canon_addr.a[1],
+ smc->hw.fddi_canon_addr.a[2],
+ smc->hw.fddi_canon_addr.a[3],
+ smc->hw.fddi_canon_addr.a[4],
+ smc->hw.fddi_canon_addr.a[5]);
+ memcpy(dev->dev_addr, smc->hw.fddi_canon_addr.a, 6);
+
+ smt_reset_defaults(smc, 0);
+
+ return (0);
+} // skfp_driver_init
+
+
+/*
+ * =============
+ * = skfp_open =
+ * =============
+ *
+ * Overview:
+ * Opens the adapter
+ *
+ * Returns:
+ * Condition code
+ *
+ * Arguments:
+ * dev - pointer to device information
+ *
+ * Functional Description:
+ * This function brings the adapter to an operational state.
+ *
+ * Return Codes:
+ * 0 - Adapter was successfully opened
+ * -EAGAIN - Could not register IRQ
+ */
+static int skfp_open(struct net_device *dev)
+{
+ struct s_smc *smc = (struct s_smc *) dev->priv;
+
+ PRINTK(KERN_INFO "entering skfp_open\n");
+ /* Register IRQ - support shared interrupts by passing device ptr */
+ if (request_irq(dev->irq, (void *) skfp_interrupt, SA_SHIRQ,
+ dev->name, dev)) {
+ printk("%s: Requested IRQ %d is busy\n", dev->name, dev->irq);
+ return (-EAGAIN);
+ }
+ /*
+ * Set current address to factory MAC address
+ *
+ * Note: We've already done this step in skfp_driver_init.
+ * However, it's possible that a user has set a node
+ * address override, then closed and reopened the
+ * adapter. Unless we reset the device address field
+ * now, we'll continue to use the existing modified
+ * address.
+ */
+ read_address(smc, NULL);
+ memcpy(dev->dev_addr, smc->hw.fddi_canon_addr.a, 6);
+
+ init_smt(smc, NULL);
+ smt_online(smc, 1);
+ STI_FBI();
+
+ MOD_INC_USE_COUNT;
+
+ /* Clear local multicast address tables */
+ mac_clear_multicast(smc);
+
+ /* Disable promiscuous filter settings */
+ mac_drv_rx_mode(smc, RX_DISABLE_PROMISC);
+
+ return (0);
+} // skfp_open
+
+
+/*
+ * ==============
+ * = skfp_close =
+ * ==============
+ *
+ * Overview:
+ * Closes the device/module.
+ *
+ * Returns:
+ * Condition code
+ *
+ * Arguments:
+ * dev - pointer to device information
+ *
+ * Functional Description:
+ * This routine closes the adapter and brings it to a safe state.
+ * The interrupt service routine is deregistered with the OS.
+ * The adapter can be opened again with another call to skfp_open().
+ *
+ * Return Codes:
+ * Always return 0.
+ *
+ * Assumptions:
+ * No further requests for this adapter are made after this routine is
+ * called. skfp_open() can be called to reset and reinitialize the
+ * adapter.
+ */
+static int skfp_close(struct net_device *dev)
+{
+ struct s_smc *smc = (struct s_smc *) dev->priv;
+ struct sk_buff *skb;
+ skfddi_priv *bp = PRIV(dev);
+
+ CLI_FBI();
+ smt_reset_defaults(smc, 1);
+ card_stop(smc);
+ mac_drv_clear_tx_queue(smc);
+ mac_drv_clear_rx_queue(smc);
+
+ netif_stop_queue(dev);
+ /* Deregister (free) IRQ */
+ free_irq(dev->irq, dev);
+
+ for (;;) {
+ skb = skb_dequeue(&bp->SendSkbQueue);
+ if (skb == NULL)
+ break;
+ bp->QueueSkb++;
+ dev_kfree_skb(skb);
+ }
+
+ MOD_DEC_USE_COUNT;
+
+ return (0);
+} // skfp_close
+
+
+/*
+ * ==================
+ * = skfp_interrupt =
+ * ==================
+ *
+ * Overview:
+ * Interrupt processing routine
+ *
+ * Returns:
+ * None
+ *
+ * Arguments:
+ * irq - interrupt vector
+ * dev_id - pointer to device information
+ * regs - pointer to registers structure
+ *
+ * Functional Description:
+ * This routine calls the interrupt processing routine for this adapter. It
+ * disables and reenables adapter interrupts, as appropriate. We can support
+ * shared interrupts since the incoming dev_id pointer provides our device
+ * structure context. All the real work is done in the hardware module.
+ *
+ * Return Codes:
+ * None
+ *
+ * Assumptions:
+ * The interrupt acknowledgement at the hardware level (eg. ACKing the PIC
+ * on Intel-based systems) is done by the operating system outside this
+ * routine.
+ *
+ * System interrupts are enabled through this call.
+ *
+ * Side Effects:
+ * Interrupts are disabled, then reenabled at the adapter.
+ */
+
+void skfp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *) dev_id;
+ struct s_smc *smc; /* private board structure pointer */
+ skfddi_priv *bp = PRIV(dev);
+
+
+ if (dev == NULL) {
+ printk("%s: irq %d for unknown device\n", dev->name, irq);
+ return;
+ }
+
+ smc = (struct s_smc *) dev->priv;
+
+ // IRQs enabled or disabled ?
+ if (inpd(ADDR(B0_IMSK)) == 0) {
+ // IRQs are disabled: must be shared interrupt
+ return;
+ }
+ // Note: At this point, IRQs are enabled.
+ if ((inpd(ISR_A) & smc->hw.is_imask) == 0) { // IRQ?
+ // Adapter did not issue an IRQ: must be shared interrupt
+ return;
+ }
+ CLI_FBI(); // Disable IRQs from our adapter.
+ spin_lock(&bp->DriverLock);
+
+ // Call interrupt handler in hardware module (HWM).
+ fddi_isr(smc);
+
+ if (smc->os.ResetRequested) {
+ ResetAdapter(smc);
+ smc->os.ResetRequested = FALSE;
+ }
+ spin_unlock(&bp->DriverLock);
+ STI_FBI(); // Enable IRQs from our adapter.
+
+ return;
+} // skfp_interrupt
+
+
+/*
+ * ======================
+ * = skfp_ctl_get_stats =
+ * ======================
+ *
+ * Overview:
+ * Get statistics for FDDI adapter
+ *
+ * Returns:
+ * Pointer to FDDI statistics structure
+ *
+ * Arguments:
+ * dev - pointer to device information
+ *
+ * Functional Description:
+ * Gets current MIB objects from adapter, then
+ * returns FDDI statistics structure as defined
+ * in if_fddi.h.
+ *
+ * Note: Since the FDDI statistics structure is
+ * still new and the device structure doesn't
+ * have an FDDI-specific get statistics handler,
+ * we'll return the FDDI statistics structure as
+ * a pointer to an Ethernet statistics structure.
+ * That way, at least the first part of the statistics
+ * structure can be decoded properly.
+ * We'll have to pay attention to this routine as the
+ * device structure becomes more mature and LAN media
+ * independent.
+ *
+ */
+struct enet_statistics *skfp_ctl_get_stats(struct net_device *dev)
+{
+ struct s_smc *bp = (struct s_smc *) dev->priv;
+
+ /* Fill the bp->stats structure with driver-maintained counters */
+
+ bp->os.MacStat.port_bs_flag[0] = 0x1234;
+ bp->os.MacStat.port_bs_flag[1] = 0x5678;
+// goos: need to fill out fddi statistic
+#if 0
+ /* Get FDDI SMT MIB objects */
+
+/* Fill the bp->stats structure with the SMT MIB object values */
+
+ memcpy(bp->stats.smt_station_id, &bp->cmd_rsp_virt->smt_mib_get.smt_station_id, sizeof(bp->cmd_rsp_virt->smt_mib_get.smt_station_id));
+ bp->stats.smt_op_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_op_version_id;
+ bp->stats.smt_hi_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_hi_version_id;
+ bp->stats.smt_lo_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_lo_version_id;
+ memcpy(bp->stats.smt_user_data, &bp->cmd_rsp_virt->smt_mib_get.smt_user_data, sizeof(bp->cmd_rsp_virt->smt_mib_get.smt_user_data));
+ bp->stats.smt_mib_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_mib_version_id;
+ bp->stats.smt_mac_cts = bp->cmd_rsp_virt->smt_mib_get.smt_mac_ct;
+ bp->stats.smt_non_master_cts = bp->cmd_rsp_virt->smt_mib_get.smt_non_master_ct;
+ bp->stats.smt_master_cts = bp->cmd_rsp_virt->smt_mib_get.smt_master_ct;
+ bp->stats.smt_available_paths = bp->cmd_rsp_virt->smt_mib_get.smt_available_paths;
+ bp->stats.smt_config_capabilities = bp->cmd_rsp_virt->smt_mib_get.smt_config_capabilities;
+ bp->stats.smt_config_policy = bp->cmd_rsp_virt->smt_mib_get.smt_config_policy;
+ bp->stats.smt_connection_policy = bp->cmd_rsp_virt->smt_mib_get.smt_connection_policy;
+ bp->stats.smt_t_notify = bp->cmd_rsp_virt->smt_mib_get.smt_t_notify;
+ bp->stats.smt_stat_rpt_policy = bp->cmd_rsp_virt->smt_mib_get.smt_stat_rpt_policy;
+ bp->stats.smt_trace_max_expiration = bp->cmd_rsp_virt->smt_mib_get.smt_trace_max_expiration;
+ bp->stats.smt_bypass_present = bp->cmd_rsp_virt->smt_mib_get.smt_bypass_present;
+ bp->stats.smt_ecm_state = bp->cmd_rsp_virt->smt_mib_get.smt_ecm_state;
+ bp->stats.smt_cf_state = bp->cmd_rsp_virt->smt_mib_get.smt_cf_state;
+ bp->stats.smt_remote_disconnect_flag = bp->cmd_rsp_virt->smt_mib_get.smt_remote_disconnect_flag;
+ bp->stats.smt_station_status = bp->cmd_rsp_virt->smt_mib_get.smt_station_status;
+ bp->stats.smt_peer_wrap_flag = bp->cmd_rsp_virt->smt_mib_get.smt_peer_wrap_flag;
+ bp->stats.smt_time_stamp = bp->cmd_rsp_virt->smt_mib_get.smt_msg_time_stamp.ls;
+ bp->stats.smt_transition_time_stamp = bp->cmd_rsp_virt->smt_mib_get.smt_transition_time_stamp.ls;
+ bp->stats.mac_frame_status_functions = bp->cmd_rsp_virt->smt_mib_get.mac_frame_status_functions;
+ bp->stats.mac_t_max_capability = bp->cmd_rsp_virt->smt_mib_get.mac_t_max_capability;
+ bp->stats.mac_tvx_capability = bp->cmd_rsp_virt->smt_mib_get.mac_tvx_capability;
+ bp->stats.mac_available_paths = bp->cmd_rsp_virt->smt_mib_get.mac_available_paths;
+ bp->stats.mac_current_path = bp->cmd_rsp_virt->smt_mib_get.mac_current_path;
+ memcpy(bp->stats.mac_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_upstream_nbr, FDDI_K_ALEN);
+ memcpy(bp->stats.mac_downstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_downstream_nbr, FDDI_K_ALEN);
+ memcpy(bp->stats.mac_old_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_old_upstream_nbr, FDDI_K_ALEN);
+ memcpy(bp->stats.mac_old_downstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_old_downstream_nbr, FDDI_K_ALEN);
+ bp->stats.mac_dup_address_test = bp->cmd_rsp_virt->smt_mib_get.mac_dup_address_test;
+ bp->stats.mac_requested_paths = bp->cmd_rsp_virt->smt_mib_get.mac_requested_paths;
+ bp->stats.mac_downstream_port_type = bp->cmd_rsp_virt->smt_mib_get.mac_downstream_port_type;
+ memcpy(bp->stats.mac_smt_address, &bp->cmd_rsp_virt->smt_mib_get.mac_smt_address, FDDI_K_ALEN);
+ bp->stats.mac_t_req = bp->cmd_rsp_virt->smt_mib_get.mac_t_req;
+ bp->stats.mac_t_neg = bp->cmd_rsp_virt->smt_mib_get.mac_t_neg;
+ bp->stats.mac_t_max = bp->cmd_rsp_virt->smt_mib_get.mac_t_max;
+ bp->stats.mac_tvx_value = bp->cmd_rsp_virt->smt_mib_get.mac_tvx_value;
+ bp->stats.mac_frame_error_threshold = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_threshold;
+ bp->stats.mac_frame_error_ratio = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_ratio;
+ bp->stats.mac_rmt_state = bp->cmd_rsp_virt->smt_mib_get.mac_rmt_state;
+ bp->stats.mac_da_flag = bp->cmd_rsp_virt->smt_mib_get.mac_da_flag;
+ bp->stats.mac_una_da_flag = bp->cmd_rsp_virt->smt_mib_get.mac_unda_flag;
+ bp->stats.mac_frame_error_flag = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_flag;
+ bp->stats.mac_ma_unitdata_available = bp->cmd_rsp_virt->smt_mib_get.mac_ma_unitdata_available;
+ bp->stats.mac_hardware_present = bp->cmd_rsp_virt->smt_mib_get.mac_hardware_present;
+ bp->stats.mac_ma_unitdata_enable = bp->cmd_rsp_virt->smt_mib_get.mac_ma_unitdata_enable;
+ bp->stats.path_tvx_lower_bound = bp->cmd_rsp_virt->smt_mib_get.path_tvx_lower_bound;
+ bp->stats.path_t_max_lower_bound = bp->cmd_rsp_virt->smt_mib_get.path_t_max_lower_bound;
+ bp->stats.path_max_t_req = bp->cmd_rsp_virt->smt_mib_get.path_max_t_req;
+ memcpy(bp->stats.path_configuration, &bp->cmd_rsp_virt->smt_mib_get.path_configuration, sizeof(bp->cmd_rsp_virt->smt_mib_get.path_configuration));
+ bp->stats.port_my_type[0] = bp->cmd_rsp_virt->smt_mib_get.port_my_type[0];
+ bp->stats.port_my_type[1] = bp->cmd_rsp_virt->smt_mib_get.port_my_type[1];
+ bp->stats.port_neighbor_type[0] = bp->cmd_rsp_virt->smt_mib_get.port_neighbor_type[0];
+ bp->stats.port_neighbor_type[1] = bp->cmd_rsp_virt->smt_mib_get.port_neighbor_type[1];
+ bp->stats.port_connection_policies[0] = bp->cmd_rsp_virt->smt_mib_get.port_connection_policies[0];
+ bp->stats.port_connection_policies[1] = bp->cmd_rsp_virt->smt_mib_get.port_connection_policies[1];
+ bp->stats.port_mac_indicated[0] = bp->cmd_rsp_virt->smt_mib_get.port_mac_indicated[0];
+ bp->stats.port_mac_indicated[1] = bp->cmd_rsp_virt->smt_mib_get.port_mac_indicated[1];
+ bp->stats.port_current_path[0] = bp->cmd_rsp_virt->smt_mib_get.port_current_path[0];
+ bp->stats.port_current_path[1] = bp->cmd_rsp_virt->smt_mib_get.port_current_path[1];
+ memcpy(&bp->stats.port_requested_paths[0 * 3], &bp->cmd_rsp_virt->smt_mib_get.port_requested_paths[0], 3);
+ memcpy(&bp->stats.port_requested_paths[1 * 3], &bp->cmd_rsp_virt->smt_mib_get.port_requested_paths[1], 3);
+ bp->stats.port_mac_placement[0] = bp->cmd_rsp_virt->smt_mib_get.port_mac_placement[0];
+ bp->stats.port_mac_placement[1] = bp->cmd_rsp_virt->smt_mib_get.port_mac_placement[1];
+ bp->stats.port_available_paths[0] = bp->cmd_rsp_virt->smt_mib_get.port_available_paths[0];
+ bp->stats.port_available_paths[1] = bp->cmd_rsp_virt->smt_mib_get.port_available_paths[1];
+ bp->stats.port_pmd_class[0] = bp->cmd_rsp_virt->smt_mib_get.port_pmd_class[0];
+ bp->stats.port_pmd_class[1] = bp->cmd_rsp_virt->smt_mib_get.port_pmd_class[1];
+ bp->stats.port_connection_capabilities[0] = bp->cmd_rsp_virt->smt_mib_get.port_connection_capabilities[0];
+ bp->stats.port_connection_capabilities[1] = bp->cmd_rsp_virt->smt_mib_get.port_connection_capabilities[1];
+ bp->stats.port_bs_flag[0] = bp->cmd_rsp_virt->smt_mib_get.port_bs_flag[0];
+ bp->stats.port_bs_flag[1] = bp->cmd_rsp_virt->smt_mib_get.port_bs_flag[1];
+ bp->stats.port_ler_estimate[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_estimate[0];
+ bp->stats.port_ler_estimate[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_estimate[1];
+ bp->stats.port_ler_cutoff[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_cutoff[0];
+ bp->stats.port_ler_cutoff[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_cutoff[1];
+ bp->stats.port_ler_alarm[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_alarm[0];
+ bp->stats.port_ler_alarm[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_alarm[1];
+ bp->stats.port_connect_state[0] = bp->cmd_rsp_virt->smt_mib_get.port_connect_state[0];
+ bp->stats.port_connect_state[1] = bp->cmd_rsp_virt->smt_mib_get.port_connect_state[1];
+ bp->stats.port_pcm_state[0] = bp->cmd_rsp_virt->smt_mib_get.port_pcm_state[0];
+ bp->stats.port_pcm_state[1] = bp->cmd_rsp_virt->smt_mib_get.port_pcm_state[1];
+ bp->stats.port_pc_withhold[0] = bp->cmd_rsp_virt->smt_mib_get.port_pc_withhold[0];
+ bp->stats.port_pc_withhold[1] = bp->cmd_rsp_virt->smt_mib_get.port_pc_withhold[1];
+ bp->stats.port_ler_flag[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_flag[0];
+ bp->stats.port_ler_flag[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_flag[1];
+ bp->stats.port_hardware_present[0] = bp->cmd_rsp_virt->smt_mib_get.port_hardware_present[0];
+ bp->stats.port_hardware_present[1] = bp->cmd_rsp_virt->smt_mib_get.port_hardware_present[1];
+
+
+ /* Fill the bp->stats structure with the FDDI counter values */
+
+ bp->stats.mac_frame_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.frame_cnt.ls;
+ bp->stats.mac_copied_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.copied_cnt.ls;
+ bp->stats.mac_transmit_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.transmit_cnt.ls;
+ bp->stats.mac_error_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.error_cnt.ls;
+ bp->stats.mac_lost_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.lost_cnt.ls;
+ bp->stats.port_lct_fail_cts[0] = bp->cmd_rsp_virt->cntrs_get.cntrs.lct_rejects[0].ls;
+ bp->stats.port_lct_fail_cts[1] = bp->cmd_rsp_virt->cntrs_get.cntrs.lct_rejects[1].ls;
+ bp->stats.port_lem_reject_cts[0] = bp->cmd_rsp_virt->cntrs_get.cntrs.lem_rejects[0].ls;
+ bp->stats.port_lem_reject_cts[1] = bp->cmd_rsp_virt->cntrs_get.cntrs.lem_rejects[1].ls;
+ bp->stats.port_lem_cts[0] = bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[0].ls;
+ bp->stats.port_lem_cts[1] = bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[1].ls;
+
+#endif
+ return ((struct enet_statistics *) &bp->os.MacStat);
+} // ctl_get_stat
+
+
+/*
+ * ==============================
+ * = skfp_ctl_set_multicast_list =
+ * ==============================
+ *
+ * Overview:
+ * Enable/Disable LLC frame promiscuous mode reception
+ * on the adapter and/or update multicast address table.
+ *
+ * Returns:
+ * None
+ *
+ * Arguments:
+ * dev - pointer to device information
+ *
+ * Functional Description:
+ * This function aquires the driver lock and only calls
+ * skfp_ctl_set_multicast_list_wo_lock then.
+ * This routine follows a fairly simple algorithm for setting the
+ * adapter filters and CAM:
+ *
+ * if IFF_PROMISC flag is set
+ * enable promiscuous mode
+ * else
+ * disable promiscuous mode
+ * if number of multicast addresses <= max. multicast number
+ * add mc addresses to adapter table
+ * else
+ * enable promiscuous mode
+ * update adapter filters
+ *
+ * Assumptions:
+ * Multicast addresses are presented in canonical (LSB) format.
+ *
+ * Side Effects:
+ * On-board adapter filters are updated.
+ */
+static void skfp_ctl_set_multicast_list(struct net_device *dev)
+{
+ skfddi_priv *bp = PRIV(dev);
+ unsigned long Flags;
+
+ spin_lock_irqsave(&bp->DriverLock, Flags);
+ skfp_ctl_set_multicast_list_wo_lock(dev);
+ spin_unlock_irqrestore(&bp->DriverLock, Flags);
+ return;
+} // skfp_ctl_set_multicast_list
+
+
+
+static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev)
+{
+ struct s_smc *smc = (struct s_smc *) dev->priv;
+ struct dev_mc_list *dmi; /* ptr to multicast addr entry */
+ int i;
+
+ /* Enable promiscuous mode, if necessary */
+ if (dev->flags & IFF_PROMISC) {
+ mac_drv_rx_mode(smc, RX_ENABLE_PROMISC);
+ PRINTK(KERN_INFO "PROMISCUOUS MODE ENABLED\n");
+ }
+ /* Else, update multicast address table */
+ else {
+ mac_drv_rx_mode(smc, RX_DISABLE_PROMISC);
+ PRINTK(KERN_INFO "PROMISCUOUS MODE DISABLED\n");
+
+ // Reset all MC addresses
+ mac_clear_multicast(smc);
+ mac_drv_rx_mode(smc, RX_DISABLE_ALLMULTI);
+
+ if (dev->flags & IFF_ALLMULTI) {
+ mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI);
+ PRINTK(KERN_INFO "ENABLE ALL MC ADDRESSES\n");
+ } else if (dev->mc_count > 0) {
+ if (dev->mc_count <= FPMAX_MULTICAST) {
+ /* use exact filtering */
+
+ // point to first multicast addr
+ dmi = dev->mc_list;
+
+ for (i = 0; i < dev->mc_count; i++) {
+ mac_add_multicast(smc,
+ dmi->dmi_addr, 1);
+ PRINTK(KERN_INFO "ENABLE MC ADDRESS:");
+ PRINTK(" %02x %02x %02x ",
+ dmi->dmi_addr[0],
+ dmi->dmi_addr[1],
+ dmi->dmi_addr[2]);
+ PRINTK("%02x %02x %02x\n",
+ dmi->dmi_addr[3],
+ dmi->dmi_addr[4],
+ dmi->dmi_addr[5]);
+ dmi = dmi->next;
+ } // for
+
+ } else { // more MC addresses than HW supports
+
+ mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI);
+ PRINTK(KERN_INFO "ENABLE ALL MC ADDRESSES\n");
+ }
+ } else { // no MC addresses
+
+ PRINTK(KERN_INFO "DISABLE ALL MC ADDRESSES\n");
+ }
+
+ /* Update adapter filters */
+ mac_update_multicast(smc);
+ }
+ return;
+} // skfp_ctl_set_multicast_list_wo_lock
+
+
+/*
+ * ===========================
+ * = skfp_ctl_set_mac_address =
+ * ===========================
+ *
+ * Overview:
+ * set new mac address on adapter and update dev_addr field in device table.
+ *
+ * Returns:
+ * None
+ *
+ * Arguments:
+ * dev - pointer to device information
+ * addr - pointer to sockaddr structure containing unicast address to set
+ *
+ * Assumptions:
+ * The address pointed to by addr->sa_data is a valid unicast
+ * address and is presented in canonical (LSB) format.
+ */
+static int skfp_ctl_set_mac_address(struct net_device *dev, void *addr)
+{
+ struct s_smc *smc = (struct s_smc *) dev->priv;
+ struct sockaddr *p_sockaddr = (struct sockaddr *) addr;
+ skfddi_priv *bp = (skfddi_priv *) & smc->os;
+ unsigned long Flags;
+
+
+ memcpy(dev->dev_addr, p_sockaddr->sa_data, FDDI_K_ALEN);
+ spin_lock_irqsave(&bp->DriverLock, Flags);
+ ResetAdapter(smc);
+ spin_unlock_irqrestore(&bp->DriverLock, Flags);
+
+ return (0); /* always return zero */
+} // skfp_ctl_set_mac_address
+
+
+/*
+ * ==============
+ * = skfp_ioctl =
+ * ==============
+ *
+ * Overview:
+ *
+ * Perform IOCTL call functions here. Some are privileged operations and the
+ * effective uid is checked in those cases.
+ *
+ * Returns:
+ * status value
+ * 0 - success
+ * other - failure
+ *
+ * Arguments:
+ * dev - pointer to device information
+ * rq - pointer to ioctl request structure
+ * cmd - ?
+ *
+ */
+
+
+static int skfp_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ skfddi_priv *lp = PRIV(dev);
+ struct s_skfp_ioctl ioc;
+ int status = 0;
+
+ copy_from_user(&ioc, rq->ifr_data, sizeof(struct s_skfp_ioctl));
+ switch (ioc.cmd) {
+ case SKFP_GET_STATS: /* Get the driver statistics */
+ ioc.len = sizeof(lp->MacStat);
+ copy_to_user(ioc.data, skfp_ctl_get_stats(dev), ioc.len);
+ break;
+ case SKFP_CLR_STATS: /* Zero out the driver statistics */
+ if (suser()) {
+ memset(&lp->MacStat, 0, sizeof(lp->MacStat));
+ } else {
+ status = -EPERM;
+ }
+ break;
+ default:
+ printk("ioctl for %s: unknow cmd: %04x\n", dev->name, ioc.cmd);
+ } // switch
+
+ return status;
+} // skfp_ioctl
+
+
+/*
+ * =====================
+ * = skfp_send_pkt =
+ * =====================
+ *
+ * Overview:
+ * Queues a packet for transmission and try to transmit it.
+ *
+ * Returns:
+ * Condition code
+ *
+ * Arguments:
+ * skb - pointer to sk_buff to queue for transmission
+ * dev - pointer to device information
+ *
+ * Functional Description:
+ * Here we assume that an incoming skb transmit request
+ * is contained in a single physically contiguous buffer
+ * in which the virtual address of the start of packet
+ * (skb->data) can be converted to a physical address
+ * by using virt_to_bus().
+ *
+ * We have an internal queue for packets we can not send
+ * immediately. Packets in this queue can be given to the
+ * adapter if transmit buffers are freed.
+ *
+ * We can't free the skb until after it's been DMA'd
+ * out by the adapter, so we'll keep it in the driver and
+ * return it in mac_drv_tx_complete.
+ *
+ * Return Codes:
+ * 0 - driver has queued and/or sent packet
+ * 1 - caller should requeue the sk_buff for later transmission
+ *
+ * Assumptions:
+ * The entire packet is stored in one physically
+ * contiguous buffer which is not cached and whose
+ * 32-bit physical address can be determined.
+ *
+ * It's vital that this routine is NOT reentered for the
+ * same board and that the OS is not in another section of
+ * code (eg. skfp_interrupt) for the same board on a
+ * different thread.
+ *
+ * Side Effects:
+ * None
+ */
+static int skfp_send_pkt(struct sk_buff *skb, struct net_device *dev)
+{
+ skfddi_priv *bp = PRIV(dev);
+
+ PRINTK(KERN_INFO "skfp_send_pkt\n");
+
+ /*
+ * Verify that incoming transmit request is OK
+ *
+ * Note: The packet size check is consistent with other
+ * Linux device drivers, although the correct packet
+ * size should be verified before calling the
+ * transmit routine.
+ */
+
+ if (!(skb->len >= FDDI_K_LLC_ZLEN && skb->len <= FDDI_K_LLC_LEN)) {
+ bp->MacStat.tx_errors++; /* bump error counter */
+ // dequeue packets from xmt queue and send them
+ netif_start_queue(dev);
+ dev_kfree_skb(skb);
+ return (0); /* return "success" */
+ }
+ if (bp->QueueSkb == 0) { // return with tbusy set: queue full
+
+ netif_stop_queue(dev);
+ return 1;
+ }
+ bp->QueueSkb--;
+ skb_queue_tail(&bp->SendSkbQueue, skb);
+ send_queued_packets((struct s_smc *) dev->priv);
+ if (bp->QueueSkb == 0) {
+ netif_stop_queue(dev);
+ }
+ dev->trans_start = jiffies;
+ return 0;
+
+} // skfp_send_pkt
+
+
+/*
+ * =======================
+ * = send_queued_packets =
+ * =======================
+ *
+ * Overview:
+ * Send packets from the driver queue as long as there are some and
+ * transmit resources are available.
+ *
+ * Returns:
+ * None
+ *
+ * Arguments:
+ * smc - pointer to smc (adapter) structure
+ *
+ * Functional Description:
+ * Take a packet from queue if there is any. If not, then we are done.
+ * Check if there are resources to send the packet. If not, requeue it
+ * and exit.
+ * Set packet descriptor flags and give packet to adapter.
+ * Check if any send resources can be freed (we do not use the
+ * transmit complete interrupt).
+ */
+static void send_queued_packets(struct s_smc *smc)
+{
+ skfddi_priv *bp = (skfddi_priv *) & smc->os;
+ struct sk_buff *skb;
+ unsigned char fc;
+ int queue;
+ struct s_smt_fp_txd *txd; // Current TxD.
+ unsigned long Flags;
+
+ int frame_status; // HWM tx frame status.
+
+ PRINTK(KERN_INFO "send queued packets\n");
+ for (;;) {
+ // send first buffer from queue
+ skb = skb_dequeue(&bp->SendSkbQueue);
+
+ if (!skb) {
+ PRINTK(KERN_INFO "queue empty\n");
+ return;
+ } // queue empty !
+
+ spin_lock_irqsave(&bp->DriverLock, Flags);
+ fc = skb->data[0];
+ queue = (fc & FC_SYNC_BIT) ? QUEUE_S : QUEUE_A0;
+#ifdef ESS
+ // Check if the frame may/must be sent as a synchronous frame.
+
+ if ((fc & ~(FC_SYNC_BIT | FC_LLC_PRIOR)) == FC_ASYNC_LLC) {
+ // It's an LLC frame.
+ if (!smc->ess.sync_bw_available)
+ fc &= ~FC_SYNC_BIT; // No bandwidth available.
+
+ else { // Bandwidth is available.
+
+ if (smc->mib.fddiESSSynchTxMode) {
+ // Send as sync. frame.
+ fc |= FC_SYNC_BIT;
+ }
+ }
+ }
+#endif // ESS
+ frame_status = hwm_tx_init(smc, fc, 1, skb->len, queue);
+
+ if ((frame_status & (LOC_TX | LAN_TX)) == 0) {
+ // Unable to send the frame.
+
+ if ((frame_status & RING_DOWN) != 0) {
+ // Ring is down.
+ PRINTK("Tx attempt while ring down.\n");
+ } else if ((frame_status & OUT_OF_TXD) != 0) {
+ PRINTK("%s: out of TXDs.\n", bp->dev->name);
+ } else {
+ PRINTK("%s: out of transmit resources",
+ bp->dev->name);
+ }
+
+ // Note: We will retry the operation as soon as
+ // transmit resources become available.
+ skb_queue_head(&bp->SendSkbQueue, skb);
+ spin_unlock_irqrestore(&bp->DriverLock, Flags);
+ return; // Packet has been queued.
+
+ } // if (unable to send frame)
+
+ bp->QueueSkb++; // one packet less in local queue
+
+ // source address in packet ?
+ CheckSourceAddress(skb->data, smc->hw.fddi_canon_addr.a);
+
+ txd = (struct s_smt_fp_txd *) HWM_GET_CURR_TXD(smc, queue);
+
+ if (frame_status & LAN_TX) {
+ txd->txd_os.skb = skb; // save skb
+ }
+ hwm_tx_frag(smc, skb->data, virt_to_bus(skb->data), skb->len,
+ frame_status | FIRST_FRAG | LAST_FRAG | EN_IRQ_EOF);
+
+ if (!(frame_status & LAN_TX)) { // local only frame
+ dev_kfree_skb_irq(skb);
+ }
+ spin_unlock_irqrestore(&bp->DriverLock, Flags);
+ } // for
+
+ return; // never reached
+
+} // send_queued_packets
+
+
+/************************
+ *
+ * CheckSourceAddress
+ *
+ * Verify if the source address is set. Insert it if necessary.
+ *
+ ************************/
+void CheckSourceAddress(unsigned char *frame, unsigned char *hw_addr)
+{
+ unsigned char SRBit;
+
+ if ((((unsigned long) frame[1 + 6]) & ~0x01) != 0) // source routing bit
+
+ return;
+ if ((unsigned short) frame[1 + 10] != 0)
+ return;
+ SRBit = frame[1 + 6] & 0x01;
+ memcpy(&frame[1 + 6], hw_addr, 6);
+ frame[8] |= SRBit;
+} // CheckSourceAddress
+
+
+/************************
+ *
+ * ResetAdapter
+ *
+ * Reset the adapter and bring it back to operational mode.
+ * Args
+ * smc - A pointer to the SMT context struct.
+ * Out
+ * Nothing.
+ *
+ ************************/
+static void ResetAdapter(struct s_smc *smc)
+{
+
+ PRINTK(KERN_INFO "[fddi: ResetAdapter]\n");
+
+ // Stop the adapter.
+
+ card_stop(smc); // Stop all activity.
+
+ // Clear the transmit and receive descriptor queues.
+ mac_drv_clear_tx_queue(smc);
+ mac_drv_clear_rx_queue(smc);
+
+ // Restart the adapter.
+
+ smt_reset_defaults(smc, 1); // Initialize the SMT module.
+
+ init_smt(smc, (smc->os.dev)->dev_addr); // Initialize the hardware.
+
+ smt_online(smc, 1); // Insert into the ring again.
+ STI_FBI();
+
+ // Restore original receive mode (multicasts, promiscuous, etc.).
+ skfp_ctl_set_multicast_list_wo_lock(smc->os.dev);
+} // ResetAdapter
+
+
+//--------------- functions called by hardware module ----------------
+
+/************************
+ *
+ * llc_restart_tx
+ *
+ * The hardware driver calls this routine when the transmit complete
+ * interrupt bits (end of frame) for the synchronous or asynchronous
+ * queue is set.
+ *
+ * NOTE The hardware driver calls this function also if no packets are queued.
+ * The routine must be able to handle this case.
+ * Args
+ * smc - A pointer to the SMT context struct.
+ * Out
+ * Nothing.
+ *
+ ************************/
+void llc_restart_tx(struct s_smc *smc)
+{
+ skfddi_priv *bp = (skfddi_priv *) & smc->os;
+
+ PRINTK(KERN_INFO "[llc_restart_tx]\n");
+
+ // Try to send queued packets
+ spin_unlock(&bp->DriverLock);
+ send_queued_packets(smc);
+ spin_lock(&bp->DriverLock);
+ netif_start_queue(bp->dev);// system may send again if it was blocked
+
+} // llc_restart_tx
+
+
+/************************
+ *
+ * mac_drv_get_space
+ *
+ * The hardware module calls this function to allocate the memory
+ * for the SMT MBufs if the define MB_OUTSIDE_SMC is specified.
+ * Args
+ * smc - A pointer to the SMT context struct.
+ *
+ * size - Size of memory in bytes to allocate.
+ * Out
+ * != 0 A pointer to the virtual address of the allocated memory.
+ * == 0 Allocation error.
+ *
+ ************************/
+void *mac_drv_get_space(struct s_smc *smc, unsigned int size)
+{
+ void *virt;
+
+ PRINTK(KERN_INFO "mac_drv_get_space\n");
+ virt = (void *) (smc->os.SharedMemAddr + smc->os.SharedMemHeap);
+
+ if ((smc->os.SharedMemHeap + size) > smc->os.SharedMemSize) {
+ printk("Unexpected SMT memory size requested: %d\n", size);
+ return (NULL);
+ }
+ smc->os.SharedMemHeap += size; // Move heap pointer.
+
+ PRINTK(KERN_INFO "mac_drv_get_space end\n");
+ PRINTK(KERN_INFO "virt addr: %08lx\n", (ulong) virt);
+ PRINTK(KERN_INFO "bus addr: %08lx\n", (ulong) virt_to_bus(virt));
+ return (virt);
+} // mac_drv_get_space
+
+
+/************************
+ *
+ * mac_drv_get_desc_mem
+ *
+ * This function is called by the hardware dependent module.
+ * It allocates the memory for the RxD and TxD descriptors.
+ *
+ * This memory must be non-cached, non-movable and non-swapable.
+ * This memory should start at a physical page boundary.
+ * Args
+ * smc - A pointer to the SMT context struct.
+ *
+ * size - Size of memory in bytes to allocate.
+ * Out
+ * != 0 A pointer to the virtual address of the allocated memory.
+ * == 0 Allocation error.
+ *
+ ************************/
+void *mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size)
+{
+
+ char *virt;
+
+ PRINTK(KERN_INFO "mac_drv_get_desc_mem\n");
+
+ // Descriptor memory must be aligned on 16-byte boundary.
+
+ virt = mac_drv_get_space(smc, size);
+
+ size = (u_int) ((0 - (unsigned int) virt) & 15);
+
+ PRINTK("Allocate %u bytes alignment gap ", size);
+ PRINTK("for descriptor memory.\n");
+
+ if (!mac_drv_get_space(smc, size)) {
+ printk("fddi: Unable to align descriptor memory.\n");
+ return (NULL);
+ }
+ return (virt + size);
+} // mac_drv_get_desc_mem
+
+
+/************************
+ *
+ * mac_drv_virt2phys
+ *
+ * Get the physical address of a given virtual address.
+ * Args
+ * smc - A pointer to the SMT context struct.
+ *
+ * virt - A (virtual) pointer into our 'shared' memory area.
+ * Out
+ * Physical address of the given virtual address.
+ *
+ ************************/
+unsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt)
+{
+ return virt_to_bus(virt);
+} // mac_drv_virt2phys
+
+
+/************************
+ *
+ * dma_master
+ *
+ * The HWM calls this function, when the driver leads through a DMA
+ * transfer. If the OS-specific module must prepare the system hardware
+ * for the DMA transfer, it should do it in this function.
+ *
+ * The hardware module calls this dma_master if it wants to send an SMT
+ * frame.
+ * Args
+ * smc - A pointer to the SMT context struct.
+ *
+ * virt - The virtual address of the data.
+ *
+ * len - The length in bytes of the data.
+ *
+ * flag - Indicates the transmit direction and the buffer type:
+ * DMA_RD (0x01) system RAM ==> adapter buffer memory
+ * DMA_WR (0x02) adapter buffer memory ==> system RAM
+ * SMT_BUF (0x80) SMT buffer
+ *
+ * >> NOTE: SMT_BUF and DMA_RD are always set for PCI. <<
+ * Out
+ * Returns the pyhsical address for the DMA transfer.
+ *
+ ************************/
+u_long dma_master(struct s_smc * smc, void *virt, int len, int flag)
+{
+ return (virt_to_bus(virt));
+} // dma_master
+
+
+/************************
+ *
+ * dma_complete
+ *
+ * The hardware module calls this routine when it has completed a DMA
+ * transfer. If the operating system dependant module has set up the DMA
+ * channel via dma_master() (e.g. Windows NT or AIX) it should clean up
+ * the DMA channel.
+ * Args
+ * smc - A pointer to the SMT context struct.
+ *
+ * descr - A pointer to a TxD or RxD, respectively.
+ *
+ * flag - Indicates the DMA transfer direction / SMT buffer:
+ * DMA_RD (0x01) system RAM ==> adapter buffer memory
+ * DMA_WR (0x02) adapter buffer memory ==> system RAM
+ * SMT_BUF (0x80) SMT buffer (managed by HWM)
+ * Out
+ * Nothing.
+ *
+ ************************/
+void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr, int flag)
+{
+ return;
+} // dma_complete
+
+
+/************************
+ *
+ * mac_drv_tx_complete
+ *
+ * Transmit of a packet is complete. Release the tx staging buffer.
+ *
+ * Args
+ * smc - A pointer to the SMT context struct.
+ *
+ * txd - A pointer to the last TxD which is used by the frame.
+ * Out
+ * Returns nothing.
+ *
+ ************************/
+void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd)
+{
+ struct sk_buff *skb;
+
+ PRINTK(KERN_INFO "entering mac_drv_tx_complete\n");
+ // Check if this TxD points to a skb
+
+ if (!(skb = txd->txd_os.skb)) {
+ PRINTK("TXD with no skb assigned.\n");
+ return;
+ }
+ txd->txd_os.skb = NULL;
+
+ smc->os.MacStat.tx_packets++; // Count transmitted packets.
+ smc->os.MacStat.tx_bytes+=skb->len; // Count bytes
+
+ // free the skb
+ dev_kfree_skb_irq(skb);
+
+ PRINTK(KERN_INFO "leaving mac_drv_tx_complete\n");
+} // mac_drv_tx_complete
+
+
+/************************
+ *
+ * dump packets to logfile
+ *
+ ************************/
+#ifdef DUMPPACKETS
+void dump_data(unsigned char *Data, int length)
+{
+ int i, j;
+ unsigned char s[255], sh[10];
+ if (length > 64) {
+ length = 64;
+ }
+ printk(KERN_INFO "---Packet start---\n");
+ for (i = 0, j = 0; i < length / 8; i++, j += 8)
+ printk(KERN_INFO "%02x %02x %02x %02x %02x %02x %02x %02x\n",
+ Data[j + 0], Data[j + 1], Data[j + 2], Data[j + 3],
+ Data[j + 4], Data[j + 5], Data[j + 6], Data[j + 7]);
+ strcpy(s, "");
+ for (i = 0; i < length % 8; i++) {
+ sprintf(sh, "%02x ", Data[j + i]);
+ strcat(s, sh);
+ }
+ printk(KERN_INFO "%s\n", s);
+ printk(KERN_INFO "------------------\n");
+} // dump_data
+#else
+#define dump_data(data,len)
+#endif // DUMPPACKETS
+
+/************************
+ *
+ * mac_drv_rx_complete
+ *
+ * The hardware module calls this function if an LLC frame is received
+ * in a receive buffer. Also the SMT, NSA, and directed beacon frames
+ * from the network will be passed to the LLC layer by this function
+ * if passing is enabled.
+ *
+ * mac_drv_rx_complete forwards the frame to the LLC layer if it should
+ * be received. It also fills the RxD ring with new receive buffers if
+ * some can be queued.
+ * Args
+ * smc - A pointer to the SMT context struct.
+ *
+ * rxd - A pointer to the first RxD which is used by the receive frame.
+ *
+ * frag_count - Count of RxDs used by the received frame.
+ *
+ * len - Frame length.
+ * Out
+ * Nothing.
+ *
+ ************************/
+void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
+ int frag_count, int len)
+{
+ skfddi_priv *bp = (skfddi_priv *) & smc->os;
+ struct sk_buff *skb;
+ unsigned char *virt, *cp;
+ unsigned short ri;
+ u_int RifLength;
+
+ PRINTK(KERN_INFO "entering mac_drv_rx_complete (len=%d)\n", len);
+ if (frag_count != 1) { // This is not allowed to happen.
+
+ printk("fddi: Multi-fragment receive!\n");
+ goto RequeueRxd; // Re-use the given RXD(s).
+
+ }
+ skb = rxd->rxd_os.skb;
+ if (!skb) {
+ PRINTK(KERN_INFO "No skb in rxd\n");
+ smc->os.MacStat.rx_errors++;
+ goto RequeueRxd;
+ }
+ virt = skb->data;
+
+ dump_data(skb->data, len);
+
+ /*
+ * FDDI Frame format:
+ * +-------+-------+-------+------------+--------+------------+
+ * | FC[1] | DA[6] | SA[6] | RIF[0..18] | LLC[3] | Data[0..n] |
+ * +-------+-------+-------+------------+--------+------------+
+ *
+ * FC = Frame Control
+ * DA = Destination Address
+ * SA = Source Address
+ * RIF = Routing Information Field
+ * LLC = Logical Link Control
+ */
+
+ // Remove Routing Information Field (RIF), if present.
+
+ if ((virt[1 + 6] & FDDI_RII) == 0)
+ RifLength = 0;
+ else {
+ int n;
+// goos: RIF removal has still to be tested
+ PRINTK(KERN_INFO "RIF found\n");
+ // Get RIF length from Routing Control (RC) field.
+ cp = virt + FDDI_MAC_HDR_LEN; // Point behind MAC header.
+
+ ri = ntohs(*((unsigned short *) cp));
+ RifLength = ri & FDDI_RCF_LEN_MASK;
+ if (len < (int) (FDDI_MAC_HDR_LEN + RifLength)) {
+ printk("fddi: Invalid RIF.\n");
+ goto RequeueRxd; // Discard the frame.
+
+ }
+ virt[1 + 6] &= ~FDDI_RII; // Clear RII bit.
+ // regions overlap
+
+ virt = cp + RifLength;
+ for (n = FDDI_MAC_HDR_LEN; n; n--)
+ *--virt = *--cp;
+ // adjust sbd->data pointer
+ skb_pull(skb, RifLength);
+ len -= RifLength;
+ RifLength = 0;
+ }
+
+ // Count statistics.
+ smc->os.MacStat.rx_packets++; // Count indicated receive packets.
+ smc->os.MacStat.rx_bytes+=len; // Count bytes
+
+ // virt points to header again
+ if (virt[1] & 0x01) { // Check group (multicast) bit.
+
+ smc->os.MacStat.multicast++;
+ }
+
+ // deliver frame to system
+ rxd->rxd_os.skb = NULL;
+ skb_trim(skb, len);
+ skb->protocol = fddi_type_trans(skb, bp->dev);
+ skb->dev = bp->dev; /* pass up device pointer */
+
+ netif_rx(skb);
+
+ HWM_RX_CHECK(smc, RX_LOW_WATERMARK);
+ return;
+
+ RequeueRxd:
+ PRINTK(KERN_INFO "Rx: re-queue RXD.\n");
+ mac_drv_requeue_rxd(smc, rxd, frag_count);
+ smc->os.MacStat.rx_errors++; // Count receive packets not indicated.
+
+} // mac_drv_rx_complete
+
+
+/************************
+ *
+ * mac_drv_requeue_rxd
+ *
+ * The hardware module calls this function to request the OS-specific
+ * module to queue the receive buffer(s) represented by the pointer
+ * to the RxD and the frag_count into the receive queue again. This
+ * buffer was filled with an invalid frame or an SMT frame.
+ * Args
+ * smc - A pointer to the SMT context struct.
+ *
+ * rxd - A pointer to the first RxD which is used by the receive frame.
+ *
+ * frag_count - Count of RxDs used by the received frame.
+ * Out
+ * Nothing.
+ *
+ ************************/
+void mac_drv_requeue_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
+ int frag_count)
+{
+ volatile struct s_smt_fp_rxd *next_rxd;
+ volatile struct s_smt_fp_rxd *src_rxd;
+ struct sk_buff *skb;
+ int MaxFrameSize;
+ unsigned char *v_addr;
+ unsigned long b_addr;
+
+ if (frag_count != 1) // This is not allowed to happen.
+
+ printk("fddi: Multi-fragment requeue!\n");
+
+ MaxFrameSize = ((skfddi_priv *) & smc->os)->MaxFrameSize;
+ src_rxd = rxd;
+ for (; frag_count > 0; frag_count--) {
+ next_rxd = src_rxd->rxd_next;
+ rxd = HWM_GET_CURR_RXD(smc);
+
+ skb = src_rxd->rxd_os.skb;
+ if (skb == NULL) { // this should not happen
+
+ PRINTK("Requeue with no skb in rxd!\n");
+ skb = alloc_skb(MaxFrameSize, GFP_ATOMIC);
+ if (skb) {
+ // we got a skb
+ rxd->rxd_os.skb = skb;
+ skb_put(skb, MaxFrameSize);
+ v_addr = skb->data;
+ b_addr = virt_to_bus(v_addr);
+ } else {
+ // no skb available, use local buffer
+ PRINTK("Queueing invalid buffer!\n");
+ rxd->rxd_os.skb = NULL;
+ v_addr = smc->os.LocalRxBuffer;
+ b_addr = virt_to_bus(v_addr);
+ }
+ } else {
+ // we use skb from old rxd
+ rxd->rxd_os.skb = skb;
+ v_addr = skb->data;
+ b_addr = virt_to_bus(v_addr);
+ }
+ hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize,
+ FIRST_FRAG | LAST_FRAG);
+
+ src_rxd = next_rxd;
+ }
+} // mac_drv_requeue_rxd
+
+
+/************************
+ *
+ * mac_drv_fill_rxd
+ *
+ * The hardware module calls this function at initialization time
+ * to fill the RxD ring with receive buffers. It is also called by
+ * mac_drv_rx_complete if rx_free is large enough to queue some new
+ * receive buffers into the RxD ring. mac_drv_fill_rxd queues new
+ * receive buffers as long as enough RxDs and receive buffers are
+ * available.
+ * Args
+ * smc - A pointer to the SMT context struct.
+ * Out
+ * Nothing.
+ *
+ ************************/
+void mac_drv_fill_rxd(struct s_smc *smc)
+{
+ int MaxFrameSize;
+ unsigned char *v_addr;
+ unsigned long b_addr;
+ struct sk_buff *skb;
+ volatile struct s_smt_fp_rxd *rxd;
+
+ PRINTK(KERN_INFO "entering mac_drv_fill_rxd\n");
+
+ // Walk through the list of free receive buffers, passing receive
+ // buffers to the HWM as long as RXDs are available.
+
+ MaxFrameSize = ((skfddi_priv *) & smc->os)->MaxFrameSize;
+ // Check if there is any RXD left.
+ while (HWM_GET_RX_FREE(smc) > 0) {
+ PRINTK(KERN_INFO ".\n");
+
+ rxd = HWM_GET_CURR_RXD(smc);
+ skb = alloc_skb(MaxFrameSize, GFP_ATOMIC);
+ if (skb) {
+ // we got a skb
+ skb_put(skb, MaxFrameSize);
+ v_addr = skb->data;
+ b_addr = virt_to_bus(v_addr);
+ } else {
+ // no skb available, use local buffer
+ // System has run out of buffer memory, but we want to
+ // keep the receiver running in hope of better times.
+ // Multiple descriptors may point to this local buffer,
+ // so data in it must be considered invalid.
+ PRINTK("Queueing invalid buffer!\n");
+ v_addr = smc->os.LocalRxBuffer;
+ b_addr = virt_to_bus(v_addr);
+ }
+
+ rxd->rxd_os.skb = skb;
+
+ // Pass receive buffer to HWM.
+ hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize,
+ FIRST_FRAG | LAST_FRAG);
+ }
+ PRINTK(KERN_INFO "leaving mac_drv_fill_rxd\n");
+} // mac_drv_fill_rxd
+
+
+/************************
+ *
+ * mac_drv_clear_rxd
+ *
+ * The hardware module calls this function to release unused
+ * receive buffers.
+ * Args
+ * smc - A pointer to the SMT context struct.
+ *
+ * rxd - A pointer to the first RxD which is used by the receive buffer.
+ *
+ * frag_count - Count of RxDs used by the receive buffer.
+ * Out
+ * Nothing.
+ *
+ ************************/
+void mac_drv_clear_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
+ int frag_count)
+{
+
+ struct sk_buff *skb;
+
+ PRINTK("entering mac_drv_clear_rxd\n");
+
+ if (frag_count != 1) // This is not allowed to happen.
+
+ printk("fddi: Multi-fragment clear!\n");
+
+ for (; frag_count > 0; frag_count--) {
+ skb = rxd->rxd_os.skb;
+ if (skb != NULL) {
+ dev_kfree_skb(skb);
+ rxd->rxd_os.skb = NULL;
+ }
+ rxd = rxd->rxd_next; // Next RXD.
+
+ }
+} // mac_drv_clear_rxd
+
+
+/************************
+ *
+ * mac_drv_rx_init
+ *
+ * The hardware module calls this routine when an SMT or NSA frame of the
+ * local SMT should be delivered to the LLC layer.
+ *
+ * It is necessary to have this function, because there is no other way to
+ * copy the contents of SMT MBufs into receive buffers.
+ *
+ * mac_drv_rx_init allocates the required target memory for this frame,
+ * and receives the frame fragment by fragment by calling mac_drv_rx_frag.
+ * Args
+ * smc - A pointer to the SMT context struct.
+ *
+ * len - The length (in bytes) of the received frame (FC, DA, SA, Data).
+ *
+ * fc - The Frame Control field of the received frame.
+ *
+ * look_ahead - A pointer to the lookahead data buffer (may be NULL).
+ *
+ * la_len - The length of the lookahead data stored in the lookahead
+ * buffer (may be zero).
+ * Out
+ * Always returns zero (0).
+ *
+ ************************/
+int mac_drv_rx_init(struct s_smc *smc, int len, int fc,
+ char *look_ahead, int la_len)
+{
+ struct sk_buff *skb;
+
+ PRINTK("entering mac_drv_rx_init(len=%d)\n", len);
+
+ // "Received" a SMT or NSA frame of the local SMT.
+
+ if (len != la_len || len < FDDI_MAC_HDR_LEN || !look_ahead) {
+ PRINTK("fddi: Discard invalid local SMT frame\n");
+ PRINTK(" len=%d, la_len=%d, (ULONG) look_ahead=%08lXh.\n",
+ len, la_len, (unsigned long) look_ahead);
+ return (0);
+ }
+ skb = alloc_skb(len, GFP_ATOMIC);
+ if (!skb) {
+ PRINTK("fddi: Local SMT: skb memory exhausted.\n");
+ return (0);
+ }
+ skb_put(skb, len);
+ memcpy(skb->data, look_ahead, len);
+
+ // deliver frame to system
+ skb->protocol = fddi_type_trans(skb, ((skfddi_priv *) & smc->os)->dev);
+ netif_rx(skb);
+
+ return (0);
+} // mac_drv_rx_init
+
+
+/************************
+ *
+ * smt_timer_poll
+ *
+ * This routine is called periodically by the SMT module to clean up the
+ * driver.
+ *
+ * Return any queued frames back to the upper protocol layers if the ring
+ * is down.
+ * Args
+ * smc - A pointer to the SMT context struct.
+ * Out
+ * Nothing.
+ *
+ ************************/
+void smt_timer_poll(struct s_smc *smc)
+{
+} // smt_timer_poll
+
+
+/************************
+ *
+ * ring_status_indication
+ *
+ * This function indicates a change of the ring state.
+ * Args
+ * smc - A pointer to the SMT context struct.
+ *
+ * status - The current ring status.
+ * Out
+ * Nothing.
+ *
+ ************************/
+void ring_status_indication(struct s_smc *smc, u_long status)
+{
+ PRINTK("ring_status_indication(%08lXh)\n", (unsigned long) status);
+} // ring_status_indication
+
+
+/************************
+ *
+ * smt_get_time
+ *
+ * Gets the current time from the system.
+ * Args
+ * None.
+ * Out
+ * The current time in TICKS_PER_SECOND.
+ *
+ * TICKS_PER_SECOND has the unit 'count of timer ticks per second'. It is
+ * defined in "targetos.h". The definition of TICKS_PER_SECOND must comply
+ * to the time returned by smt_get_time().
+ *
+ ************************/
+unsigned long smt_get_time(void)
+{
+ return jiffies;
+} // smt_get_time
+
+
+/************************
+ *
+ * smt_stat_counter
+ *
+ * Status counter update (ring_op, fifo full).
+ * Args
+ * smc - A pointer to the SMT context struct.
+ *
+ * stat - = 0: A ring operational change occurred.
+ * = 1: The FORMAC FIFO buffer is full / FIFO overflow.
+ * Out
+ * Nothing.
+ *
+ ************************/
+void smt_stat_counter(struct s_smc *smc, int stat)
+{
+// BOOLEAN RingIsUp ;
+
+ PRINTK(KERN_INFO "smt_stat_counter\n");
+ switch (stat) {
+ case 0:
+ PRINTK(KERN_INFO "Ring operational change.\n");
+ break;
+ case 1:
+ PRINTK(KERN_INFO "Receive fifo overflow.\n");
+ smc->os.MacStat.rx_errors++;
+ break;
+ default:
+ PRINTK(KERN_INFO "Unknown status (%d).\n", stat);
+ break;
+ }
+} // smt_stat_counter
+
+
+/************************
+ *
+ * cfm_state_change
+ *
+ * Sets CFM state in custom statistics.
+ * Args
+ * smc - A pointer to the SMT context struct.
+ *
+ * c_state - Possible values are:
+ *
+ * EC0_OUT, EC1_IN, EC2_TRACE, EC3_LEAVE, EC4_PATH_TEST,
+ * EC5_INSERT, EC6_CHECK, EC7_DEINSERT
+ * Out
+ * Nothing.
+ *
+ ************************/
+void cfm_state_change(struct s_smc *smc, int c_state)
+{
+#ifdef DRIVERDEBUG
+ char *s;
+
+ switch (c_state) {
+ case SC0_ISOLATED:
+ s = "SC0_ISOLATED";
+ break;
+ case SC1_WRAP_A:
+ s = "SC1_WRAP_A";
+ break;
+ case SC2_WRAP_B:
+ s = "SC2_WRAP_B";
+ break;
+ case SC4_THRU_A:
+ s = "SC4_THRU_A";
+ break;
+ case SC5_THRU_B:
+ s = "SC5_THRU_B";
+ break;
+ case SC7_WRAP_S:
+ s = "SC7_WRAP_S";
+ break;
+ default:
+ s = "unknown";
+ break;
+ }
+ PRINTK(KERN_INFO "cfm_state_change: %s\n", s);
+#endif // DRIVERDEBUG
+} // cfm_state_change
+
+
+/************************
+ *
+ * ecm_state_change
+ *
+ * Sets ECM state in custom statistics.
+ * Args
+ * smc - A pointer to the SMT context struct.
+ *
+ * e_state - Possible values are:
+ *
+ * SC0_ISOLATED, SC1_WRAP_A (5), SC2_WRAP_B (6), SC4_THRU_A (12),
+ * SC5_THRU_B (7), SC7_WRAP_S (8)
+ * Out
+ * Nothing.
+ *
+ ************************/
+void ecm_state_change(struct s_smc *smc, int e_state)
+{
+#ifdef DRIVERDEBUG
+ char *s;
+
+ switch (e_state) {
+ case EC0_OUT:
+ s = "EC0_OUT";
+ break;
+ case EC1_IN:
+ s = "EC1_IN";
+ break;
+ case EC2_TRACE:
+ s = "EC2_TRACE";
+ break;
+ case EC3_LEAVE:
+ s = "EC3_LEAVE";
+ break;
+ case EC4_PATH_TEST:
+ s = "EC4_PATH_TEST";
+ break;
+ case EC5_INSERT:
+ s = "EC5_INSERT";
+ break;
+ case EC6_CHECK:
+ s = "EC6_CHECK";
+ break;
+ case EC7_DEINSERT:
+ s = "EC7_DEINSERT";
+ break;
+ default:
+ s = "unknown";
+ break;
+ }
+ PRINTK(KERN_INFO "ecm_state_change: %s\n", s);
+#endif //DRIVERDEBUG
+} // ecm_state_change
+
+
+/************************
+ *
+ * rmt_state_change
+ *
+ * Sets RMT state in custom statistics.
+ * Args
+ * smc - A pointer to the SMT context struct.
+ *
+ * r_state - Possible values are:
+ *
+ * RM0_ISOLATED, RM1_NON_OP, RM2_RING_OP, RM3_DETECT,
+ * RM4_NON_OP_DUP, RM5_RING_OP_DUP, RM6_DIRECTED, RM7_TRACE
+ * Out
+ * Nothing.
+ *
+ ************************/
+void rmt_state_change(struct s_smc *smc, int r_state)
+{
+#ifdef DRIVERDEBUG
+ char *s;
+
+ switch (r_state) {
+ case RM0_ISOLATED:
+ s = "RM0_ISOLATED";
+ break;
+ case RM1_NON_OP:
+ s = "RM1_NON_OP - not operational";
+ break;
+ case RM2_RING_OP:
+ s = "RM2_RING_OP - ring operational";
+ break;
+ case RM3_DETECT:
+ s = "RM3_DETECT - detect dupl addresses";
+ break;
+ case RM4_NON_OP_DUP:
+ s = "RM4_NON_OP_DUP - dupl. addr detected";
+ break;
+ case RM5_RING_OP_DUP:
+ s = "RM5_RING_OP_DUP - ring oper. with dupl. addr";
+ break;
+ case RM6_DIRECTED:
+ s = "RM6_DIRECTED - sending directed beacons";
+ break;
+ case RM7_TRACE:
+ s = "RM7_TRACE - trace initiated";
+ break;
+ default:
+ s = "unknown";
+ break;
+ }
+ PRINTK(KERN_INFO "[rmt_state_change: %s]\n", s);
+#endif // DRIVERDEBUG
+} // rmt_state_change
+
+
+/************************
+ *
+ * drv_reset_indication
+ *
+ * This function is called by the SMT when it has detected a severe
+ * hardware problem. The driver should perform a reset on the adapter
+ * as soon as possible, but not from within this function.
+ * Args
+ * smc - A pointer to the SMT context struct.
+ * Out
+ * Nothing.
+ *
+ ************************/
+void drv_reset_indication(struct s_smc *smc)
+{
+ PRINTK(KERN_INFO "entering drv_reset_indication\n");
+
+ smc->os.ResetRequested = TRUE; // Set flag.
+
+} // drv_reset_indication
+
+
+
+//--------------- functions for use as a module ----------------
+
+#ifdef MODULE
+/************************
+ *
+ * Note now that module autoprobing is allowed under PCI. The
+ * IRQ lines will not be auto-detected; instead I'll rely on the BIOSes
+ * to "do the right thing".
+ *
+ ************************/
+#define LP(a) ((struct s_smc*)(a))
+static struct net_device *mdev = NULL;
+
+/************************
+ *
+ * init_module
+ *
+ * If compiled as a module, find
+ * adapters and initialize them.
+ *
+ ************************/
+int init_module(void)
+{
+ struct net_device *p;
+
+ PRINTK(KERN_INFO "FDDI init module\n");
+ if ((mdev = insert_device(NULL, skfp_probe)) == NULL)
+ return -ENOMEM;
+
+ for (p = mdev; p != NULL; p = LP(p->priv)->os.next_module) {
+ PRINTK(KERN_INFO "device to register: %s\n", p->name);
+ if (register_netdev(p) != 0) {
+ printk("skfddi init_module failed\n");
+ return -EIO;
+ }
+ }
+
+ PRINTK(KERN_INFO "+++++ exit with success +++++\n");
+ return 0;
+} // init_module
+
+/************************
+ *
+ * cleanup_module
+ *
+ * Release all resources claimed by this module.
+ *
+ ************************/
+void cleanup_module(void)
+{
+ PRINTK(KERN_INFO "cleanup_module\n");
+ while (mdev != NULL) {
+ mdev = unlink_modules(mdev);
+ }
+ return;
+} // cleanup_module
+
+
+/************************
+ *
+ * unlink_modules
+ *
+ * Unregister devices and release their memory.
+ *
+ ************************/
+static struct net_device *unlink_modules(struct net_device *p)
+{
+ struct net_device *next = NULL;
+
+ if (p->priv) { /* Private areas allocated? */
+ struct s_smc *lp = (struct s_smc *) p->priv;
+
+ next = lp->os.next_module;
+
+ if (lp->os.SharedMemAddr) {
+ kfree(lp->os.SharedMemAddr);
+ }
+ release_region(p->base_addr,
+ (lp->os.bus_type == SK_BUS_TYPE_PCI ? FP_IO_LEN : 0));
+ }
+ unregister_netdev(p);
+ printk("%s: unloaded\n", p->name);
+ kfree(p); /* Free the device structure */
+
+ return next;
+} // unlink_modules
+
+
+#endif /* MODULE */
diff --git a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c
new file mode 100644
index 000000000..ed8538958
--- /dev/null
+++ b/drivers/net/skfp/smt.c
@@ -0,0 +1,2225 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/smt_p.h"
+
+#define KERNEL
+#include "h/smtstate.h"
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)smt.c 2.43 98/11/23 (C) SK " ;
+#endif
+
+extern const u_char canonical[256] ;
+
+/*
+ * FC in SMbuf
+ */
+#define m_fc(mb) ((mb)->sm_data[0])
+
+#define SMT_TID_MAGIC 0x1f0a7b3c
+
+#ifdef DEBUG
+static const char *const smt_type_name[] = {
+ "SMT_00??", "SMT_INFO", "SMT_02??", "SMT_03??",
+ "SMT_04??", "SMT_05??", "SMT_06??", "SMT_07??",
+ "SMT_08??", "SMT_09??", "SMT_0A??", "SMT_0B??",
+ "SMT_0C??", "SMT_0D??", "SMT_0E??", "SMT_NSA"
+} ;
+
+static const char *const smt_class_name[] = {
+ "UNKNOWN","NIF","SIF_CONFIG","SIF_OPER","ECF","RAF","RDF",
+ "SRF","PMF_GET","PMF_SET","ESF"
+} ;
+#endif
+#define LAST_CLASS (SMT_PMF_SET)
+
+static const struct fddi_addr SMT_Unknown = {
+ 0,0,0x1f,0,0,0
+} ;
+
+/*
+ * external variables
+ */
+extern const struct fddi_addr fddi_broadcast ;
+
+/*
+ * external functions
+ */
+int pcm_status_twisted() ;
+void pcm_status_state() ;
+int pcm_status_type() ;
+
+extern SMbuf *smt_get_mbuf() ;
+
+#define EXPORT_PMF
+/*
+ * function prototypes
+ */
+u_long smt_get_tid() ;
+EXPORT_PMF SMbuf *smt_build_frame() ;
+EXPORT_PMF void *sm_to_para() ;
+#ifdef LITTLE_ENDIAN
+static int smt_swap_short() ;
+#endif
+static int mac_index() ;
+static int phy_index() ;
+static int mac_con_resource_index() ;
+static int phy_con_resource_index() ;
+EXPORT_PMF void smt_send_frame() ;
+EXPORT_PMF void smt_set_timestamp() ;
+static void smt_send_rdf() ;
+static void smt_send_nif() ;
+static void smt_send_ecf() ;
+static void smt_echo_test() ;
+static void smt_send_sif_config() ;
+static void smt_send_sif_operation() ;
+EXPORT_PMF void smt_swap_para() ;
+#ifdef LITTLE_ENDIAN
+static void smt_string_swap() ;
+#endif
+static void smt_add_frame_len() ;
+static void smt_fill_una() ;
+static void smt_fill_sde() ;
+static void smt_fill_state() ;
+static void smt_fill_timestamp() ;
+static void smt_fill_policy() ;
+static void smt_fill_latency() ;
+static void smt_fill_neighbor() ;
+static int smt_fill_path() ;
+static void smt_fill_mac_status() ;
+static void smt_fill_lem() ;
+static void smt_fill_version() ;
+static void smt_fill_fsc() ;
+static void smt_fill_mac_counter() ;
+static void smt_fill_mac_fnc() ;
+static void smt_fill_manufacturer() ;
+static void smt_fill_user() ;
+static void smt_fill_setcount() ;
+static void smt_fill_echo() ;
+int smt_check_para() ;
+
+void smt_clear_una_dna() ;
+static void smt_clear_old_una_dna() ;
+#ifdef CONCENTRATOR
+static int entity_to_index() ;
+#endif
+static void update_dac() ;
+static int div_ratio() ;
+#ifdef USE_CAN_ADDR
+void hwm_conv_can() ;
+#else
+#define hwm_conv_can(smc,data,len)
+#endif
+
+/*
+ * list of mandatory paras in frames
+ */
+static const u_short plist_nif[] = { SMT_P_UNA,SMT_P_SDE,SMT_P_STATE,0 } ;
+
+/*
+ * init SMT agent
+ */
+void smt_agent_init(smc)
+struct s_smc *smc ;
+{
+ int i ;
+
+ /*
+ * get MAC address
+ */
+ smc->mib.m[MAC0].fddiMACSMTAddress = smc->hw.fddi_home_addr ;
+
+ /*
+ * get OUI address from driver (bia == built-in-address)
+ */
+ smc->mib.fddiSMTStationId.sid_oem[0] = 0 ;
+ smc->mib.fddiSMTStationId.sid_oem[1] = 0 ;
+ driver_get_bia(smc,&smc->mib.fddiSMTStationId.sid_node) ;
+ for (i = 0 ; i < 6 ; i ++) {
+ smc->mib.fddiSMTStationId.sid_node.a[i] =
+ canonical[smc->mib.fddiSMTStationId.sid_node.a[i]] ;
+ }
+ smc->mib.fddiSMTManufacturerData[0] =
+ smc->mib.fddiSMTStationId.sid_node.a[0] ;
+ smc->mib.fddiSMTManufacturerData[1] =
+ smc->mib.fddiSMTStationId.sid_node.a[1] ;
+ smc->mib.fddiSMTManufacturerData[2] =
+ smc->mib.fddiSMTStationId.sid_node.a[2] ;
+ smc->sm.smt_tid = 0 ;
+ smc->mib.m[MAC0].fddiMACDupAddressTest = DA_NONE ;
+ smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ;
+#ifndef SLIM_SMT
+ smt_clear_una_dna(smc) ;
+ smt_clear_old_una_dna(smc) ;
+#endif
+ for (i = 0 ; i < SMT_MAX_TEST ; i++)
+ smc->sm.pend[i] = 0 ;
+ smc->sm.please_reconnect = 0 ;
+ smc->sm.uniq_ticks = 0 ;
+}
+
+/*
+ * SMT task
+ * forever
+ * delay 30 seconds
+ * send NIF
+ * check tvu & tvd
+ * end
+ */
+void smt_agent_task(smc)
+struct s_smc *smc ;
+{
+ smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L,
+ EV_TOKEN(EVENT_SMT,SM_TIMER)) ;
+ DB_SMT("SMT agent task\n",0,0) ;
+}
+
+void smt_please_reconnect(smc,reconn_time)
+struct s_smc *smc ; /* Pointer to SMT context */
+int reconn_time ; /* Wait for reconnect time in seconds */
+{
+ /*
+ * The please reconnect variable is used as a timer.
+ * It is decremented each time smt_event is called.
+ * This happens every second or when smt_force_irq is called.
+ * Note: smt_force_irq () is called on some packet receives and
+ * when a multicast address is changed. Since nothing
+ * is received during the disconnect and the multicast
+ * address changes can be viewed as not very often and
+ * the timer runs out close to its given value
+ * (reconn_time).
+ */
+ smc->sm.please_reconnect = reconn_time ;
+}
+
+#ifndef SMT_REAL_TOKEN_CT
+void smt_emulate_token_ct(smc, mac_index)
+struct s_smc *smc;
+int mac_index;
+{
+ u_long count;
+ u_long time;
+
+
+ time = smt_get_time();
+ count = ((time - smc->sm.last_tok_time[mac_index]) *
+ 100)/TICKS_PER_SECOND;
+
+ /*
+ * Only when ring is up we will have a token count. The
+ * flag is unfortunatly a single instance value. This
+ * doesn't matter now, because we currently have only
+ * one MAC instance.
+ */
+ if (smc->hw.mac_ring_is_up){
+ smc->mib.m[mac_index].fddiMACToken_Ct += count;
+ }
+
+ /* Remember current time */
+ smc->sm.last_tok_time[mac_index] = time;
+
+}
+#endif
+
+/*ARGSUSED1*/
+void smt_event(smc,event)
+struct s_smc *smc ;
+int event ;
+{
+ u_long time ;
+#ifndef SMT_REAL_TOKEN_CT
+ int i ;
+#endif
+
+
+ if (smc->sm.please_reconnect) {
+ smc->sm.please_reconnect -- ;
+ if (smc->sm.please_reconnect == 0) {
+ /* Counted down */
+ queue_event(smc,EVENT_ECM,EC_CONNECT) ;
+ }
+ }
+
+ if (event == SM_FAST)
+ return ;
+
+ /*
+ * timer for periodic cleanup in driver
+ * reset and start the watchdog (FM2)
+ * ESS timer
+ * SBA timer
+ */
+ smt_timer_poll(smc) ;
+ smt_start_watchdog(smc) ;
+#ifndef SLIM_SMT
+#ifndef BOOT
+#ifdef ESS
+ ess_timer_poll(smc) ;
+#endif
+#endif
+#ifdef SBA
+ sba_timer_poll(smc) ;
+#endif
+
+ smt_srf_event(smc,0,0,0) ;
+
+#endif /* no SLIM_SMT */
+
+ time = smt_get_time() ;
+
+ if (time - smc->sm.smt_last_lem >= TICKS_PER_SECOND*8) {
+ /*
+ * Use 8 sec. for the time intervall, it simplifies the
+ * LER estimation.
+ */
+ struct fddi_mib_m *mib ;
+ u_long upper ;
+ u_long lower ;
+ int cond ;
+ int port;
+ struct s_phy *phy ;
+ /*
+ * calculate LEM bit error rate
+ */
+ sm_lem_evaluate(smc) ;
+ smc->sm.smt_last_lem = time ;
+
+ /*
+ * check conditions
+ */
+#ifndef SLIM_SMT
+ mac_update_counter(smc) ;
+ mib = smc->mib.m ;
+ upper =
+ (mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) +
+ (mib->fddiMACError_Ct - mib->fddiMACOld_Error_Ct) ;
+ lower =
+ (mib->fddiMACFrame_Ct - mib->fddiMACOld_Frame_Ct) +
+ (mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) ;
+ mib->fddiMACFrameErrorRatio = div_ratio(upper,lower) ;
+
+ cond =
+ ((!mib->fddiMACFrameErrorThreshold &&
+ mib->fddiMACError_Ct != mib->fddiMACOld_Error_Ct) ||
+ (mib->fddiMACFrameErrorRatio >
+ mib->fddiMACFrameErrorThreshold)) ;
+
+ if (cond != mib->fddiMACFrameErrorFlag)
+ smt_srf_event(smc,SMT_COND_MAC_FRAME_ERROR,
+ INDEX_MAC,cond) ;
+
+ upper =
+ (mib->fddiMACNotCopied_Ct - mib->fddiMACOld_NotCopied_Ct) ;
+ lower =
+ upper +
+ (mib->fddiMACCopied_Ct - mib->fddiMACOld_Copied_Ct) ;
+ mib->fddiMACNotCopiedRatio = div_ratio(upper,lower) ;
+
+ cond =
+ ((!mib->fddiMACNotCopiedThreshold &&
+ mib->fddiMACNotCopied_Ct !=
+ mib->fddiMACOld_NotCopied_Ct)||
+ (mib->fddiMACNotCopiedRatio >
+ mib->fddiMACNotCopiedThreshold)) ;
+
+ if (cond != mib->fddiMACNotCopiedFlag)
+ smt_srf_event(smc,SMT_COND_MAC_NOT_COPIED,
+ INDEX_MAC,cond) ;
+
+ /*
+ * set old values
+ */
+ mib->fddiMACOld_Frame_Ct = mib->fddiMACFrame_Ct ;
+ mib->fddiMACOld_Copied_Ct = mib->fddiMACCopied_Ct ;
+ mib->fddiMACOld_Error_Ct = mib->fddiMACError_Ct ;
+ mib->fddiMACOld_Lost_Ct = mib->fddiMACLost_Ct ;
+ mib->fddiMACOld_NotCopied_Ct = mib->fddiMACNotCopied_Ct ;
+
+ /*
+ * Check port EBError Condition
+ */
+ for (port = 0; port < NUMPHYS; port ++) {
+ phy = &smc->y[port] ;
+
+ if (!phy->mib->fddiPORTHardwarePresent) {
+ continue;
+ }
+
+ cond = (phy->mib->fddiPORTEBError_Ct -
+ phy->mib->fddiPORTOldEBError_Ct > 5) ;
+
+ /* If ratio is more than 5 in 8 seconds
+ * Set the condition.
+ */
+ smt_srf_event(smc,SMT_COND_PORT_EB_ERROR,
+ (int) (INDEX_PORT+ phy->np) ,cond) ;
+
+ /*
+ * set old values
+ */
+ phy->mib->fddiPORTOldEBError_Ct =
+ phy->mib->fddiPORTEBError_Ct ;
+ }
+
+#endif /* no SLIM_SMT */
+ }
+
+#ifndef SLIM_SMT
+
+ if (time - smc->sm.smt_last_notify >= (u_long)
+ (smc->mib.fddiSMTTT_Notify * TICKS_PER_SECOND) ) {
+ /*
+ * we can either send an announcement or a request
+ * a request will trigger a reply so that we can update
+ * our dna
+ * note: same tid must be used until reply is received
+ */
+ if (!smc->sm.pend[SMT_TID_NIF])
+ smc->sm.pend[SMT_TID_NIF] = smt_get_tid(smc) ;
+ smt_send_nif(smc,&fddi_broadcast,FC_SMT_NSA,
+ smc->sm.pend[SMT_TID_NIF], SMT_REQUEST,0) ;
+ smc->sm.smt_last_notify = time ;
+ }
+
+ /*
+ * check timer
+ */
+ if (smc->sm.smt_tvu &&
+ time - smc->sm.smt_tvu > 228*TICKS_PER_SECOND) {
+ DB_SMT("SMT : UNA expired\n",0,0) ;
+ smc->sm.smt_tvu = 0 ;
+
+ if (!is_equal(&smc->mib.m[MAC0].fddiMACUpstreamNbr,
+ &SMT_Unknown)){
+ /* Do not update unknown address */
+ smc->mib.m[MAC0].fddiMACOldUpstreamNbr=
+ smc->mib.m[MAC0].fddiMACUpstreamNbr ;
+ }
+ smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ;
+ smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ;
+ /*
+ * Make sure the fddiMACUNDA_Flag = FALSE is
+ * included in the SRF so we don't generate
+ * a seperate SRF for the deassertion of this
+ * condition
+ */
+ update_dac(smc,0) ;
+ smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE,
+ INDEX_MAC,0) ;
+ }
+ if (smc->sm.smt_tvd &&
+ time - smc->sm.smt_tvd > 228*TICKS_PER_SECOND) {
+ DB_SMT("SMT : DNA expired\n",0,0) ;
+ smc->sm.smt_tvd = 0 ;
+ if (!is_equal(&smc->mib.m[MAC0].fddiMACDownstreamNbr,
+ &SMT_Unknown)){
+ /* Do not update unknown address */
+ smc->mib.m[MAC0].fddiMACOldDownstreamNbr=
+ smc->mib.m[MAC0].fddiMACDownstreamNbr ;
+ }
+ smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ;
+ smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE,
+ INDEX_MAC,0) ;
+ }
+
+#endif /* no SLIM_SMT */
+
+#ifndef SMT_REAL_TOKEN_CT
+ /*
+ * Token counter emulation section. If hardware supports the token
+ * count, the token counter will be updated in mac_update_counter.
+ */
+ for (i = MAC0; i < NUMMACS; i++ ){
+ if (time - smc->sm.last_tok_time[i] > 2*TICKS_PER_SECOND ){
+ smt_emulate_token_ct( smc, i );
+ }
+ }
+#endif
+
+ smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L,
+ EV_TOKEN(EVENT_SMT,SM_TIMER)) ;
+}
+
+static int div_ratio(upper,lower)
+u_long upper ;
+u_long lower ;
+{
+ if ((upper<<16L) < upper)
+ upper = 0xffff0000L ;
+ else
+ upper <<= 16L ;
+ if (!lower)
+ return(0) ;
+ return((int)(upper/lower)) ;
+}
+
+#ifndef SLIM_SMT
+
+/*
+ * receive packet handler
+ */
+void smt_received_pack(smc,mb,fs)
+struct s_smc *smc ;
+SMbuf *mb ;
+int fs ; /* frame status */
+{
+ struct smt_header *sm ;
+ int local ;
+
+ int illegal = 0 ;
+
+ switch (m_fc(mb)) {
+ case FC_SMT_INFO :
+ case FC_SMT_LAN_LOC :
+ case FC_SMT_LOC :
+ case FC_SMT_NSA :
+ break ;
+ default :
+ smt_free_mbuf(smc,mb) ;
+ return ;
+ }
+
+ smc->mib.m[MAC0].fddiMACSMTCopied_Ct++ ;
+ sm = smtod(mb,struct smt_header *) ;
+ local = ((fs & L_INDICATOR) != 0) ;
+ hwm_conv_can(smc,(char *)sm,12) ;
+
+ /* check destination address */
+ if (is_individual(&sm->smt_dest) && !is_my_addr(smc,&sm->smt_dest)) {
+ smt_free_mbuf(smc,mb) ;
+ return ;
+ }
+#if 0 /* for DUP recognition, do NOT filter them */
+ /* ignore loop back packets */
+ if (is_my_addr(smc,&sm->smt_source) && !local) {
+ smt_free_mbuf(smc,mb) ;
+ return ;
+ }
+#endif
+
+ smt_swap_para(sm,(int) mb->sm_len,1) ;
+ DB_SMT("SMT : received packet [%s] at 0x%x\n",
+ smt_type_name[m_fc(mb) & 0xf],sm) ;
+ DB_SMT("SMT : version %d, class %s\n",sm->smt_version,
+ smt_class_name[(sm->smt_class>LAST_CLASS)?0 : sm->smt_class]) ;
+
+#ifdef SBA
+ /*
+ * check if NSA frame
+ */
+ if (m_fc(mb) == FC_SMT_NSA && sm->smt_class == SMT_NIF &&
+ (sm->smt_type == SMT_ANNOUNCE || sm->smt_type == SMT_REQUEST)) {
+ smc->sba.sm = sm ;
+ sba(smc,NIF) ;
+ }
+#endif
+
+ /*
+ * ignore any packet with NSA and A-indicator set
+ */
+ if ( (fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) {
+ DB_SMT("SMT : ignoring NSA with A-indicator set from %s\n",
+ addr_to_string(&sm->smt_source),0) ;
+ smt_free_mbuf(smc,mb) ;
+ return ;
+ }
+
+ /*
+ * ignore frames with illegal length
+ */
+ if (((sm->smt_class == SMT_ECF) && (sm->smt_len > SMT_MAX_ECHO_LEN)) ||
+ ((sm->smt_class != SMT_ECF) && (sm->smt_len > SMT_MAX_INFO_LEN))) {
+ smt_free_mbuf(smc,mb) ;
+ return ;
+ }
+
+ /*
+ * check SMT version
+ */
+ switch (sm->smt_class) {
+ case SMT_NIF :
+ case SMT_SIF_CONFIG :
+ case SMT_SIF_OPER :
+ case SMT_ECF :
+ if (sm->smt_version != SMT_VID)
+ illegal = 1;
+ break ;
+ default :
+ if (sm->smt_version != SMT_VID_2)
+ illegal = 1;
+ break ;
+ }
+ if (illegal) {
+ DB_SMT("SMT : version = %d, dest = %s\n",
+ sm->smt_version,addr_to_string(&sm->smt_source)) ;
+ smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_VERSION,local) ;
+ smt_free_mbuf(smc,mb) ;
+ return ;
+ }
+ if ((sm->smt_len > mb->sm_len - sizeof(struct smt_header)) ||
+ ((sm->smt_len & 3) && (sm->smt_class != SMT_ECF))) {
+ DB_SMT("SMT: info length error, len = %d\n",sm->smt_len,0) ;
+ smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH,local) ;
+ smt_free_mbuf(smc,mb) ;
+ return ;
+ }
+ switch (sm->smt_class) {
+ case SMT_NIF :
+ if (smt_check_para(smc,sm,plist_nif)) {
+ DB_SMT("SMT: NIF with para problem, ignoring\n",0,0) ;
+ break ;
+ } ;
+ switch (sm->smt_type) {
+ case SMT_ANNOUNCE :
+ case SMT_REQUEST :
+ if (!(fs & C_INDICATOR) && m_fc(mb) == FC_SMT_NSA
+ && is_broadcast(&sm->smt_dest)) {
+ struct smt_p_state *st ;
+
+ /* set my UNA */
+ if (!is_equal(
+ &smc->mib.m[MAC0].fddiMACUpstreamNbr,
+ &sm->smt_source)) {
+ DB_SMT("SMT : updated my UNA = %s\n",
+ addr_to_string(&sm->smt_source),0) ;
+ if (!is_equal(&smc->mib.m[MAC0].
+ fddiMACUpstreamNbr,&SMT_Unknown)){
+ /* Do not update unknown address */
+ smc->mib.m[MAC0].fddiMACOldUpstreamNbr=
+ smc->mib.m[MAC0].fddiMACUpstreamNbr ;
+ }
+
+ smc->mib.m[MAC0].fddiMACUpstreamNbr =
+ sm->smt_source ;
+ smt_srf_event(smc,
+ SMT_EVENT_MAC_NEIGHBOR_CHANGE,
+ INDEX_MAC,0) ;
+ smt_echo_test(smc,0) ;
+ }
+ smc->sm.smt_tvu = smt_get_time() ;
+ st = (struct smt_p_state *)
+ sm_to_para(smc,sm,SMT_P_STATE) ;
+ if (st) {
+ smc->mib.m[MAC0].fddiMACUNDA_Flag =
+ (st->st_dupl_addr & SMT_ST_MY_DUPA) ?
+ TRUE : FALSE ;
+ update_dac(smc,1) ;
+ }
+ }
+ if ((sm->smt_type == SMT_REQUEST) &&
+ is_individual(&sm->smt_source) &&
+ ((!(fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) ||
+ (m_fc(mb) != FC_SMT_NSA))) {
+ DB_SMT("SMT : replying to NIF request %s\n",
+ addr_to_string(&sm->smt_source),0) ;
+ smt_send_nif(smc,&sm->smt_source,
+ FC_SMT_INFO,
+ sm->smt_tid,
+ SMT_REPLY,local) ;
+ }
+ break ;
+ case SMT_REPLY :
+ DB_SMT("SMT : received NIF response from %s\n",
+ addr_to_string(&sm->smt_source),0) ;
+ if (fs & A_INDICATOR) {
+ smc->sm.pend[SMT_TID_NIF] = 0 ;
+ DB_SMT("SMT : duplicate address\n",0,0) ;
+ smc->mib.m[MAC0].fddiMACDupAddressTest =
+ DA_FAILED ;
+ smc->r.dup_addr_test = DA_FAILED ;
+ queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;
+ smc->mib.m[MAC0].fddiMACDA_Flag = TRUE ;
+ update_dac(smc,1) ;
+ break ;
+ }
+ if (sm->smt_tid == smc->sm.pend[SMT_TID_NIF]) {
+ smc->sm.pend[SMT_TID_NIF] = 0 ;
+ /* set my DNA */
+ if (!is_equal(
+ &smc->mib.m[MAC0].fddiMACDownstreamNbr,
+ &sm->smt_source)) {
+ DB_SMT("SMT : updated my DNA\n",0,0) ;
+ if (!is_equal(&smc->mib.m[MAC0].
+ fddiMACDownstreamNbr, &SMT_Unknown)){
+ /* Do not update unknown address */
+ smc->mib.m[MAC0].fddiMACOldDownstreamNbr =
+ smc->mib.m[MAC0].fddiMACDownstreamNbr ;
+ }
+
+ smc->mib.m[MAC0].fddiMACDownstreamNbr =
+ sm->smt_source ;
+ smt_srf_event(smc,
+ SMT_EVENT_MAC_NEIGHBOR_CHANGE,
+ INDEX_MAC,0) ;
+ smt_echo_test(smc,1) ;
+ }
+ smc->mib.m[MAC0].fddiMACDA_Flag = FALSE ;
+ update_dac(smc,1) ;
+ smc->sm.smt_tvd = smt_get_time() ;
+ smc->mib.m[MAC0].fddiMACDupAddressTest =
+ DA_PASSED ;
+ if (smc->r.dup_addr_test != DA_PASSED) {
+ smc->r.dup_addr_test = DA_PASSED ;
+ queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;
+ }
+ }
+ else if (sm->smt_tid ==
+ smc->sm.pend[SMT_TID_NIF_TEST]) {
+ DB_SMT("SMT : NIF test TID ok\n",0,0) ;
+ }
+ else {
+ DB_SMT("SMT : expected TID %lx, got %lx\n",
+ smc->sm.pend[SMT_TID_NIF],sm->smt_tid) ;
+ }
+ break ;
+ default :
+ illegal = 2 ;
+ break ;
+ }
+ break ;
+ case SMT_SIF_CONFIG : /* station information */
+ if (sm->smt_type != SMT_REQUEST)
+ break ;
+ DB_SMT("SMT : replying to SIF Config request from %s\n",
+ addr_to_string(&sm->smt_source),0) ;
+ smt_send_sif_config(smc,&sm->smt_source,sm->smt_tid,local) ;
+ break ;
+ case SMT_SIF_OPER : /* station information */
+ if (sm->smt_type != SMT_REQUEST)
+ break ;
+ DB_SMT("SMT : replying to SIF Operation request from %s\n",
+ addr_to_string(&sm->smt_source),0) ;
+ smt_send_sif_operation(smc,&sm->smt_source,sm->smt_tid,local) ;
+ break ;
+ case SMT_ECF : /* echo frame */
+ switch (sm->smt_type) {
+ case SMT_REPLY :
+ smc->mib.priv.fddiPRIVECF_Reply_Rx++ ;
+ DB_SMT("SMT: received ECF reply from %s\n",
+ addr_to_string(&sm->smt_source),0) ;
+ if (sm_to_para(smc,sm,SMT_P_ECHODATA) == 0) {
+ DB_SMT("SMT: ECHODATA missing\n",0,0) ;
+ break ;
+ }
+ if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF]) {
+ DB_SMT("SMT : ECF test TID ok\n",0,0) ;
+ }
+ else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_UNA]) {
+ DB_SMT("SMT : ECF test UNA ok\n",0,0) ;
+ }
+ else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_DNA]) {
+ DB_SMT("SMT : ECF test DNA ok\n",0,0) ;
+ }
+ else {
+ DB_SMT("SMT : expected TID %lx, got %lx\n",
+ smc->sm.pend[SMT_TID_ECF],
+ sm->smt_tid) ;
+ }
+ break ;
+ case SMT_REQUEST :
+ smc->mib.priv.fddiPRIVECF_Req_Rx++ ;
+ {
+ if (sm->smt_len && !sm_to_para(smc,sm,SMT_P_ECHODATA)) {
+ DB_SMT("SMT: ECF with para problem,sending RDF\n",0,0) ;
+ smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH,
+ local) ;
+ break ;
+ }
+ DB_SMT("SMT - sending ECF reply to %s\n",
+ addr_to_string(&sm->smt_source),0) ;
+
+ /* set destination addr. & reply */
+ sm->smt_dest = sm->smt_source ;
+ sm->smt_type = SMT_REPLY ;
+ dump_smt(smc,sm,"ECF REPLY") ;
+ smc->mib.priv.fddiPRIVECF_Reply_Tx++ ;
+ smt_send_frame(smc,mb,FC_SMT_INFO,local) ;
+ return ; /* DON'T free mbuf */
+ }
+ default :
+ illegal = 1 ;
+ break ;
+ }
+ break ;
+#ifndef BOOT
+ case SMT_RAF : /* resource allocation */
+#ifdef ESS
+ DB_ESSN(2,"ESS: RAF frame received\n",0,0) ;
+ fs = ess_raf_received_pack(smc,mb,sm,fs) ;
+#endif
+
+#ifdef SBA
+ DB_SBAN(2,"SBA: RAF frame received\n",0,0) ;
+ sba_raf_received_pack(smc,sm,fs) ;
+#endif
+ break ;
+ case SMT_RDF : /* request denied */
+ smc->mib.priv.fddiPRIVRDF_Rx++ ;
+ break ;
+ case SMT_ESF : /* extended service - not supported */
+ if (sm->smt_type == SMT_REQUEST) {
+ DB_SMT("SMT - received ESF, sending RDF\n",0,0) ;
+ smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ;
+ }
+ break ;
+ case SMT_PMF_GET :
+ case SMT_PMF_SET :
+ if (sm->smt_type != SMT_REQUEST)
+ break ;
+ /* update statistics */
+ if (sm->smt_class == SMT_PMF_GET)
+ smc->mib.priv.fddiPRIVPMF_Get_Rx++ ;
+ else
+ smc->mib.priv.fddiPRIVPMF_Set_Rx++ ;
+ /*
+ * ignore PMF SET with I/G set
+ */
+ if ((sm->smt_class == SMT_PMF_SET) &&
+ !is_individual(&sm->smt_dest)) {
+ DB_SMT("SMT: ignoring PMF-SET with I/G set\n",0,0) ;
+ break ;
+ }
+ smt_pmf_received_pack(smc,mb, local) ;
+ break ;
+ case SMT_SRF :
+ dump_smt(smc,sm,"SRF received") ;
+ break ;
+ default :
+ if (sm->smt_type != SMT_REQUEST)
+ break ;
+ /*
+ * For frames with unknown class:
+ * we need to send a RDF frame according to 8.1.3.1.1,
+ * only if it is a REQUEST.
+ */
+ DB_SMT("SMT : class = %d, send RDF to %s\n",
+ sm->smt_class, addr_to_string(&sm->smt_source)) ;
+
+ smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ;
+ break ;
+#endif
+ }
+ if (illegal) {
+ DB_SMT("SMT: discarding illegal frame, reason = %d\n",
+ illegal,0) ;
+ }
+ smt_free_mbuf(smc,mb) ;
+}
+
+static void update_dac(smc,report)
+struct s_smc *smc ;
+int report ;
+{
+ int cond ;
+
+ cond = ( smc->mib.m[MAC0].fddiMACUNDA_Flag |
+ smc->mib.m[MAC0].fddiMACDA_Flag) != 0 ;
+ if (report && (cond != smc->mib.m[MAC0].fddiMACDuplicateAddressCond))
+ smt_srf_event(smc, SMT_COND_MAC_DUP_ADDR,INDEX_MAC,cond) ;
+ else
+ smc->mib.m[MAC0].fddiMACDuplicateAddressCond = cond ;
+}
+
+/*
+ * send SMT frame
+ * set source address
+ * set station ID
+ * send frame
+ */
+EXPORT_PMF void smt_send_frame(smc,mb,fc,local)
+struct s_smc *smc ;
+SMbuf *mb ; /* buffer to send */
+int fc ; /* FC value */
+int local ;
+{
+ struct smt_header *sm ;
+
+ if (!smc->r.sm_ma_avail && !local) {
+ smt_free_mbuf(smc,mb) ;
+ return ;
+ }
+ sm = smtod(mb,struct smt_header *) ;
+ sm->smt_source = smc->mib.m[MAC0].fddiMACSMTAddress ;
+ sm->smt_sid = smc->mib.fddiSMTStationId ;
+
+ smt_swap_para(sm,(int) mb->sm_len,0) ; /* swap para & header */
+ hwm_conv_can(smc,(char *)sm,12) ; /* convert SA and DA */
+ smc->mib.m[MAC0].fddiMACSMTTransmit_Ct++ ;
+ smt_send_mbuf(smc,mb,local ? FC_SMT_LOC : fc) ;
+}
+
+/*
+ * generate and send RDF
+ */
+static void smt_send_rdf(smc,rej,fc,reason,local)
+struct s_smc *smc ;
+SMbuf *rej ; /* mbuf of offending frame */
+int fc ; /* FC of denied frame */
+int reason ; /* reason code */
+int local ;
+{
+ SMbuf *mb ;
+ struct smt_header *sm ; /* header of offending frame */
+ struct smt_rdf *rdf ;
+ int len ;
+ int frame_len ;
+
+ sm = smtod(rej,struct smt_header *) ;
+ if (sm->smt_type != SMT_REQUEST)
+ return ;
+
+ DB_SMT("SMT: sending RDF to %s,reason = 0x%x\n",
+ addr_to_string(&sm->smt_source),reason) ;
+
+
+ /*
+ * note: get framelength from MAC length, NOT from SMT header
+ * smt header length is included in sm_len
+ */
+ frame_len = rej->sm_len ;
+
+ if (!(mb=smt_build_frame(smc,SMT_RDF,SMT_REPLY,sizeof(struct smt_rdf))))
+ return ;
+ rdf = smtod(mb,struct smt_rdf *) ;
+ rdf->smt.smt_tid = sm->smt_tid ; /* use TID from sm */
+ rdf->smt.smt_dest = sm->smt_source ; /* set dest = source */
+
+ /* set P12 */
+ rdf->reason.para.p_type = SMT_P_REASON ;
+ rdf->reason.para.p_len = sizeof(struct smt_p_reason) - PARA_LEN ;
+ rdf->reason.rdf_reason = reason ;
+
+ /* set P14 */
+ rdf->version.para.p_type = SMT_P_VERSION ;
+ rdf->version.para.p_len = sizeof(struct smt_p_version) - PARA_LEN ;
+ rdf->version.v_pad = 0 ;
+ rdf->version.v_n = 1 ;
+ rdf->version.v_index = 1 ;
+ rdf->version.v_version[0] = SMT_VID_2 ;
+ rdf->version.v_pad2 = 0 ;
+
+ /* set P13 */
+ if ((unsigned) frame_len <= SMT_MAX_INFO_LEN - sizeof(*rdf) +
+ 2*sizeof(struct smt_header))
+ len = frame_len ;
+ else
+ len = SMT_MAX_INFO_LEN - sizeof(*rdf) +
+ 2*sizeof(struct smt_header) ;
+ /* make length multiple of 4 */
+ len &= ~3 ;
+ rdf->refused.para.p_type = SMT_P_REFUSED ;
+ /* length of para is smt_frame + ref_fc */
+ rdf->refused.para.p_len = len + 4 ;
+ rdf->refused.ref_fc = fc ;
+
+ /* swap it back */
+ smt_swap_para(sm,frame_len,0) ;
+
+ memcpy((char *) &rdf->refused.ref_header,(char *) sm,len) ;
+
+ len -= sizeof(struct smt_header) ;
+ mb->sm_len += len ;
+ rdf->smt.smt_len += len ;
+
+ dump_smt(smc,(struct smt_header *)rdf,"RDF") ;
+ smc->mib.priv.fddiPRIVRDF_Tx++ ;
+ smt_send_frame(smc,mb,FC_SMT_INFO,local) ;
+}
+
+/*
+ * generate and send NIF
+ */
+static void smt_send_nif(smc,dest,fc,tid,type,local)
+struct s_smc *smc ;
+struct fddi_addr *dest ; /* dest address */
+int fc ; /* frame control */
+u_long tid ; /* transaction id */
+int type ; /* frame type */
+int local ;
+{
+ struct smt_nif *nif ;
+ SMbuf *mb ;
+
+ if (!(mb = smt_build_frame(smc,SMT_NIF,type,sizeof(struct smt_nif))))
+ return ;
+ nif = smtod(mb, struct smt_nif *) ;
+ smt_fill_una(smc,&nif->una) ; /* set UNA */
+ smt_fill_sde(smc,&nif->sde) ; /* set station descriptor */
+ smt_fill_state(smc,&nif->state) ; /* set state information */
+#ifdef SMT6_10
+ smt_fill_fsc(smc,&nif->fsc) ; /* set frame status cap. */
+#endif
+ nif->smt.smt_dest = *dest ; /* destination address */
+ nif->smt.smt_tid = tid ; /* transaction ID */
+ dump_smt(smc,(struct smt_header *)nif,"NIF") ;
+ smt_send_frame(smc,mb,fc,local) ;
+}
+
+#ifdef DEBUG
+/*
+ * send NIF request (test purpose)
+ */
+static void smt_send_nif_request(smc,dest)
+struct s_smc *smc ;
+struct fddi_addr *dest ;
+{
+ smc->sm.pend[SMT_TID_NIF_TEST] = smt_get_tid(smc) ;
+ smt_send_nif(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_NIF_TEST],
+ SMT_REQUEST,0) ;
+}
+
+/*
+ * send ECF request (test purpose)
+ */
+static void smt_send_ecf_request(smc,dest,len)
+struct s_smc *smc ;
+struct fddi_addr *dest ;
+int len ;
+{
+ smc->sm.pend[SMT_TID_ECF] = smt_get_tid(smc) ;
+ smt_send_ecf(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_ECF],
+ SMT_REQUEST,len) ;
+}
+#endif
+
+/*
+ * echo test
+ */
+static void smt_echo_test(smc,dna)
+struct s_smc *smc ;
+int dna ;
+{
+ u_long tid ;
+
+ smc->sm.pend[dna ? SMT_TID_ECF_DNA : SMT_TID_ECF_UNA] =
+ tid = smt_get_tid(smc) ;
+ smt_send_ecf(smc, dna ?
+ &smc->mib.m[MAC0].fddiMACDownstreamNbr :
+ &smc->mib.m[MAC0].fddiMACUpstreamNbr,
+ FC_SMT_INFO,tid, SMT_REQUEST, (SMT_TEST_ECHO_LEN & ~3)-8) ;
+}
+
+/*
+ * generate and send ECF
+ */
+static void smt_send_ecf(smc,dest,fc,tid,type,len)
+struct s_smc *smc ;
+struct fddi_addr *dest ; /* dest address */
+int fc ; /* frame control */
+u_long tid ; /* transaction id */
+int type ; /* frame type */
+int len ; /* frame length */
+{
+ struct smt_ecf *ecf ;
+ SMbuf *mb ;
+
+ if (!(mb = smt_build_frame(smc,SMT_ECF,type,SMT_ECF_LEN + len)))
+ return ;
+ ecf = smtod(mb, struct smt_ecf *) ;
+
+ smt_fill_echo(smc,&ecf->ec_echo,tid,len) ; /* set ECHO */
+ ecf->smt.smt_dest = *dest ; /* destination address */
+ ecf->smt.smt_tid = tid ; /* transaction ID */
+ smc->mib.priv.fddiPRIVECF_Req_Tx++ ;
+ smt_send_frame(smc,mb,fc,0) ;
+}
+
+/*
+ * generate and send SIF config response
+ */
+
+static void smt_send_sif_config(smc,dest,tid,local)
+struct s_smc *smc ;
+struct fddi_addr *dest ; /* dest address */
+u_long tid ; /* transaction id */
+int local ;
+{
+ struct smt_sif_config *sif ;
+ SMbuf *mb ;
+ int len ;
+ if (!(mb = smt_build_frame(smc,SMT_SIF_CONFIG,SMT_REPLY,
+ SIZEOF_SMT_SIF_CONFIG)))
+ return ;
+
+ sif = smtod(mb, struct smt_sif_config *) ;
+ smt_fill_timestamp(smc,&sif->ts) ; /* set time stamp */
+ smt_fill_sde(smc,&sif->sde) ; /* set station descriptor */
+ smt_fill_version(smc,&sif->version) ; /* set version information */
+ smt_fill_state(smc,&sif->state) ; /* set state information */
+ smt_fill_policy(smc,&sif->policy) ; /* set station policy */
+ smt_fill_latency(smc,&sif->latency); /* set station latency */
+ smt_fill_neighbor(smc,&sif->neighbor); /* set station neighbor */
+ smt_fill_setcount(smc,&sif->setcount) ; /* set count */
+ len = smt_fill_path(smc,&sif->path); /* set station path descriptor*/
+ sif->smt.smt_dest = *dest ; /* destination address */
+ sif->smt.smt_tid = tid ; /* transaction ID */
+ smt_add_frame_len(mb,len) ; /* adjust length fields */
+ dump_smt(smc,(struct smt_header *)sif,"SIF Configuration Reply") ;
+ smt_send_frame(smc,mb,FC_SMT_INFO,local) ;
+}
+
+/*
+ * generate and send SIF operation response
+ */
+
+static void smt_send_sif_operation(smc,dest,tid,local)
+struct s_smc *smc ;
+struct fddi_addr *dest ; /* dest address */
+u_long tid ; /* transaction id */
+int local ;
+{
+ struct smt_sif_operation *sif ;
+ SMbuf *mb ;
+ int ports ;
+ int i ;
+
+ ports = NUMPHYS ;
+#ifndef CONCENTRATOR
+ if (smc->s.sas == SMT_SAS)
+ ports = 1 ;
+#endif
+
+ if (!(mb = smt_build_frame(smc,SMT_SIF_OPER,SMT_REPLY,
+ SIZEOF_SMT_SIF_OPERATION+ports*sizeof(struct smt_p_lem))))
+ return ;
+ sif = smtod(mb, struct smt_sif_operation *) ;
+ smt_fill_timestamp(smc,&sif->ts) ; /* set time stamp */
+ smt_fill_mac_status(smc,&sif->status) ; /* set mac status */
+ smt_fill_mac_counter(smc,&sif->mc) ; /* set mac counter field */
+ smt_fill_mac_fnc(smc,&sif->fnc) ; /* set frame not copied counter */
+ smt_fill_manufacturer(smc,&sif->man) ; /* set manufacturer field */
+ smt_fill_user(smc,&sif->user) ; /* set user field */
+ smt_fill_setcount(smc,&sif->setcount) ; /* set count */
+ /*
+ * set link error mon information
+ */
+ if (ports == 1) {
+ smt_fill_lem(smc,sif->lem,PS) ;
+ }
+ else {
+ for (i = 0 ; i < ports ; i++) {
+ smt_fill_lem(smc,&sif->lem[i],i) ;
+ }
+ }
+
+ sif->smt.smt_dest = *dest ; /* destination address */
+ sif->smt.smt_tid = tid ; /* transaction ID */
+ dump_smt(smc,(struct smt_header *)sif,"SIF Operation Reply") ;
+ smt_send_frame(smc,mb,FC_SMT_INFO,local) ;
+}
+
+/*
+ * get and initialize SMT frame
+ */
+EXPORT_PMF SMbuf *smt_build_frame(smc,class,type,length)
+struct s_smc *smc ;
+int class ;
+int type ;
+int length ;
+{
+ SMbuf *mb ;
+ struct smt_header *smt ;
+
+#if 0
+ if (!smc->r.sm_ma_avail) {
+ return(0) ;
+ }
+#endif
+ if (!(mb = smt_get_mbuf(smc)))
+ return(mb) ;
+
+ mb->sm_len = length ;
+ smt = smtod(mb, struct smt_header *) ;
+ smt->smt_dest = fddi_broadcast ; /* set dest = broadcast */
+ smt->smt_class = class ;
+ smt->smt_type = type ;
+ switch (class) {
+ case SMT_NIF :
+ case SMT_SIF_CONFIG :
+ case SMT_SIF_OPER :
+ case SMT_ECF :
+ smt->smt_version = SMT_VID ;
+ break ;
+ default :
+ smt->smt_version = SMT_VID_2 ;
+ break ;
+ }
+ smt->smt_tid = smt_get_tid(smc) ; /* set transaction ID */
+ smt->smt_pad = 0 ;
+ smt->smt_len = length - sizeof(struct smt_header) ;
+ return(mb) ;
+}
+
+static void smt_add_frame_len(mb,len)
+SMbuf *mb ;
+int len ;
+{
+ struct smt_header *smt ;
+
+ smt = smtod(mb, struct smt_header *) ;
+ smt->smt_len += len ;
+ mb->sm_len += len ;
+}
+
+
+
+/*
+ * fill values in UNA parameter
+ */
+static void smt_fill_una(smc,una)
+struct s_smc *smc ;
+struct smt_p_una *una ;
+{
+ SMTSETPARA(una,SMT_P_UNA) ;
+ una->una_pad = 0 ;
+ una->una_node = smc->mib.m[MAC0].fddiMACUpstreamNbr ;
+}
+
+/*
+ * fill values in SDE parameter
+ */
+static void smt_fill_sde(smc,sde)
+struct s_smc *smc ;
+struct smt_p_sde *sde ;
+{
+ SMTSETPARA(sde,SMT_P_SDE) ;
+ sde->sde_non_master = smc->mib.fddiSMTNonMaster_Ct ;
+ sde->sde_master = smc->mib.fddiSMTMaster_Ct ;
+ sde->sde_mac_count = NUMMACS ; /* only 1 MAC */
+#ifdef CONCENTRATOR
+ sde->sde_type = SMT_SDE_CONCENTRATOR ;
+#else
+ sde->sde_type = SMT_SDE_STATION ;
+#endif
+}
+
+/*
+ * fill in values in station state parameter
+ */
+static void smt_fill_state(smc,state)
+struct s_smc *smc ;
+struct smt_p_state *state ;
+{
+ int top ;
+ int twist ;
+
+ SMTSETPARA(state,SMT_P_STATE) ;
+ state->st_pad = 0 ;
+
+ /* determine topology */
+ top = 0 ;
+ if (smc->mib.fddiSMTPeerWrapFlag) {
+ top |= SMT_ST_WRAPPED ; /* state wrapped */
+ }
+#ifdef CONCENTRATOR
+ if (cfm_status_unattached(smc)) {
+ top |= SMT_ST_UNATTACHED ; /* unattached concentrator */
+ }
+#endif
+ if ((twist = pcm_status_twisted(smc)) & 1) {
+ top |= SMT_ST_TWISTED_A ; /* twisted cable */
+ }
+ if (twist & 2) {
+ top |= SMT_ST_TWISTED_B ; /* twisted cable */
+ }
+#ifdef OPT_SRF
+ top |= SMT_ST_SRF ;
+#endif
+ if (pcm_rooted_station(smc))
+ top |= SMT_ST_ROOTED_S ;
+ if (smc->mib.a[0].fddiPATHSbaPayload != 0)
+ top |= SMT_ST_SYNC_SERVICE ;
+ state->st_topology = top ;
+ state->st_dupl_addr =
+ ((smc->mib.m[MAC0].fddiMACDA_Flag ? SMT_ST_MY_DUPA : 0 ) |
+ (smc->mib.m[MAC0].fddiMACUNDA_Flag ? SMT_ST_UNA_DUPA : 0)) ;
+}
+
+/*
+ * fill values in timestamp parameter
+ */
+static void smt_fill_timestamp(smc,ts)
+struct s_smc *smc ;
+struct smt_p_timestamp *ts ;
+{
+
+ SMTSETPARA(ts,SMT_P_TIMESTAMP) ;
+ smt_set_timestamp(smc,ts->ts_time) ;
+}
+
+EXPORT_PMF void smt_set_timestamp(smc,p)
+struct s_smc *smc ;
+u_char *p ;
+{
+ u_long time ;
+ u_long utime ;
+
+ /*
+ * timestamp is 64 bits long ; resolution is 80 nS
+ * our clock resolution is 10mS
+ * 10mS/80ns = 125000 ~ 2^17 = 131072
+ */
+ utime = smt_get_time() ;
+ time = utime * 100 ;
+ time /= TICKS_PER_SECOND ;
+ p[0] = 0 ;
+ p[1] = (u_char)((time>>(8+8+8+8-1)) & 1) ;
+ p[2] = (u_char)(time>>(8+8+8-1)) ;
+ p[3] = (u_char)(time>>(8+8-1)) ;
+ p[4] = (u_char)(time>>(8-1)) ;
+ p[5] = (u_char)(time<<1) ;
+ p[6] = (u_char)(smc->sm.uniq_ticks>>8) ;
+ p[7] = (u_char)smc->sm.uniq_ticks ;
+ /*
+ * make sure we don't wrap: restart whenever the upper digits change
+ */
+ if (utime != smc->sm.uniq_time) {
+ smc->sm.uniq_ticks = 0 ;
+ }
+ smc->sm.uniq_ticks++ ;
+ smc->sm.uniq_time = utime ;
+}
+
+/*
+ * fill values in station policy parameter
+ */
+static void smt_fill_policy(smc,policy)
+struct s_smc *smc ;
+struct smt_p_policy *policy ;
+{
+ int i ;
+ u_char *map ;
+ u_short in ;
+ u_short out ;
+
+ /*
+ * MIB para 101b (fddiSMTConnectionPolicy) coding
+ * is different from 0005 coding
+ */
+ static u_char ansi_weirdness[16] = {
+ 0,7,5,3,8,1,6,4,9,10,2,11,12,13,14,15
+ } ;
+ SMTSETPARA(policy,SMT_P_POLICY) ;
+
+ out = 0 ;
+ in = smc->mib.fddiSMTConnectionPolicy ;
+ for (i = 0, map = ansi_weirdness ; i < 16 ; i++) {
+ if (in & 1)
+ out |= (1<<*map) ;
+ in >>= 1 ;
+ map++ ;
+ }
+ policy->pl_config = smc->mib.fddiSMTConfigPolicy ;
+ policy->pl_connect = out ;
+}
+
+/*
+ * fill values in latency equivalent parameter
+ */
+static void smt_fill_latency(smc,latency)
+struct s_smc *smc ;
+struct smt_p_latency *latency ;
+{
+ SMTSETPARA(latency,SMT_P_LATENCY) ;
+
+ latency->lt_phyout_idx1 = phy_index(smc,0) ;
+ latency->lt_latency1 = 10 ; /* in octets (byte clock) */
+ /*
+ * note: latency has two phy entries by definition
+ * for a SAS, the 2nd one is null
+ */
+ if (smc->s.sas == SMT_DAS) {
+ latency->lt_phyout_idx2 = phy_index(smc,1) ;
+ latency->lt_latency2 = 10 ; /* in octets (byte clock) */
+ }
+ else {
+ latency->lt_phyout_idx2 = 0 ;
+ latency->lt_latency2 = 0 ;
+ }
+}
+
+/*
+ * fill values in MAC neighbors parameter
+ */
+static void smt_fill_neighbor(smc,neighbor)
+struct s_smc *smc ;
+struct smt_p_neighbor *neighbor ;
+{
+ SMTSETPARA(neighbor,SMT_P_NEIGHBORS) ;
+
+ neighbor->nb_mib_index = INDEX_MAC ;
+ neighbor->nb_mac_index = mac_index(smc,1) ;
+ neighbor->nb_una = smc->mib.m[MAC0].fddiMACUpstreamNbr ;
+ neighbor->nb_dna = smc->mib.m[MAC0].fddiMACDownstreamNbr ;
+}
+
+/*
+ * fill values in path descriptor
+ */
+#ifdef CONCENTRATOR
+#define ALLPHYS NUMPHYS
+#else
+#define ALLPHYS ((smc->s.sas == SMT_SAS) ? 1 : 2)
+#endif
+
+static int smt_fill_path(smc,path)
+struct s_smc *smc ;
+struct smt_p_path *path ;
+{
+ SK_LOC_DECL(int,type) ;
+ SK_LOC_DECL(int,state) ;
+ SK_LOC_DECL(int,remote) ;
+ SK_LOC_DECL(int,mac) ;
+ int len ;
+ int p ;
+ int physp ;
+ struct smt_phy_rec *phy ;
+ struct smt_mac_rec *pd_mac ;
+
+ len = PARA_LEN +
+ sizeof(struct smt_mac_rec) * NUMMACS +
+ sizeof(struct smt_phy_rec) * ALLPHYS ;
+ path->para.p_type = SMT_P_PATH ;
+ path->para.p_len = len - PARA_LEN ;
+
+ /* PHYs */
+ for (p = 0,phy = path->pd_phy ; p < ALLPHYS ; p++, phy++) {
+ physp = p ;
+#ifndef CONCENTRATOR
+ if (smc->s.sas == SMT_SAS)
+ physp = PS ;
+#endif
+ pcm_status_state(smc,physp,&type,&state,&remote,&mac) ;
+#ifdef LITTLE_ENDIAN
+ phy->phy_mib_index = smt_swap_short((u_short)p+INDEX_PORT) ;
+#else
+ phy->phy_mib_index = p+INDEX_PORT ;
+#endif
+ phy->phy_type = type ;
+ phy->phy_connect_state = state ;
+ phy->phy_remote_type = remote ;
+ phy->phy_remote_mac = mac ;
+ phy->phy_resource_idx = phy_con_resource_index(smc,p) ;
+ }
+
+ /* MAC */
+ pd_mac = (struct smt_mac_rec *) phy ;
+ pd_mac->mac_addr = smc->mib.m[MAC0].fddiMACSMTAddress ;
+ pd_mac->mac_resource_idx = mac_con_resource_index(smc,1) ;
+ return(len) ;
+}
+
+/*
+ * fill values in mac status
+ */
+static void smt_fill_mac_status(smc,st)
+struct s_smc *smc ;
+struct smt_p_mac_status *st ;
+{
+ SMTSETPARA(st,SMT_P_MAC_STATUS) ;
+
+ st->st_mib_index = INDEX_MAC ;
+ st->st_mac_index = mac_index(smc,1) ;
+
+ mac_update_counter(smc) ;
+ /*
+ * timer values are represented in SMT as 2's complement numbers
+ * units : internal : 2's complement BCLK
+ */
+ st->st_t_req = smc->mib.m[MAC0].fddiMACT_Req ;
+ st->st_t_neg = smc->mib.m[MAC0].fddiMACT_Neg ;
+ st->st_t_max = smc->mib.m[MAC0].fddiMACT_Max ;
+ st->st_tvx_value = smc->mib.m[MAC0].fddiMACTvxValue ;
+ st->st_t_min = smc->mib.m[MAC0].fddiMACT_Min ;
+
+ st->st_sba = smc->mib.a[PATH0].fddiPATHSbaPayload ;
+ st->st_frame_ct = smc->mib.m[MAC0].fddiMACFrame_Ct ;
+ st->st_error_ct = smc->mib.m[MAC0].fddiMACError_Ct ;
+ st->st_lost_ct = smc->mib.m[MAC0].fddiMACLost_Ct ;
+}
+
+/*
+ * fill values in LEM status
+ */
+
+static void smt_fill_lem(smc,lem,phy)
+struct s_smc *smc ;
+struct smt_p_lem *lem ;
+int phy ;
+{
+ struct fddi_mib_p *mib ;
+
+ mib = smc->y[phy].mib ;
+
+ SMTSETPARA(lem,SMT_P_LEM) ;
+ lem->lem_mib_index = phy+INDEX_PORT ;
+ lem->lem_phy_index = phy_index(smc,phy) ;
+ lem->lem_pad2 = 0 ;
+ lem->lem_cutoff = mib->fddiPORTLer_Cutoff ;
+ lem->lem_alarm = mib->fddiPORTLer_Alarm ;
+ /* long term bit error rate */
+ lem->lem_estimate = mib->fddiPORTLer_Estimate ;
+ /* # of rejected connections */
+ lem->lem_reject_ct = mib->fddiPORTLem_Reject_Ct ;
+ lem->lem_ct = mib->fddiPORTLem_Ct ; /* total number of errors */
+}
+
+/*
+ * fill version parameter
+ */
+static void smt_fill_version(smc,vers)
+struct s_smc *smc ;
+struct smt_p_version *vers ;
+{
+ SK_UNUSED(smc) ;
+ SMTSETPARA(vers,SMT_P_VERSION) ;
+ vers->v_pad = 0 ;
+ vers->v_n = 1 ; /* one version is enough .. */
+ vers->v_index = 1 ;
+ vers->v_version[0] = SMT_VID_2 ;
+ vers->v_pad2 = 0 ;
+}
+
+#ifdef SMT6_10
+/*
+ * fill frame status capabilities
+ */
+/*
+ * note: this para 200B is NOT in swap table, because it's also set in
+ * PMF add_para
+ */
+static void smt_fill_fsc(smc,fsc)
+struct s_smc *smc ;
+struct smt_p_fsc *fsc ;
+{
+ SK_UNUSED(smc) ;
+ SMTSETPARA(fsc,SMT_P_FSC) ;
+ fsc->fsc_pad0 = 0 ;
+ fsc->fsc_mac_index = INDEX_MAC ; /* this is MIB ; MIB is NOT
+ * mac_index ()i !
+ */
+ fsc->fsc_pad1 = 0 ;
+ fsc->fsc_value = FSC_TYPE0 ; /* "normal" node */
+#ifdef LITTLE_ENDIAN
+ fsc->fsc_mac_index = smt_swap_short(INDEX_MAC) ;
+ fsc->fsc_value = smt_swap_short(FSC_TYPE0) ;
+#endif
+}
+#endif
+
+/*
+ * fill mac counter field
+ */
+static void smt_fill_mac_counter(smc,mc)
+struct s_smc *smc ;
+struct smt_p_mac_counter *mc ;
+{
+ SMTSETPARA(mc,SMT_P_MAC_COUNTER) ;
+ mc->mc_mib_index = INDEX_MAC ;
+ mc->mc_index = mac_index(smc,1) ;
+ mc->mc_receive_ct = smc->mib.m[MAC0].fddiMACCopied_Ct ;
+ mc->mc_transmit_ct = smc->mib.m[MAC0].fddiMACTransmit_Ct ;
+}
+
+/*
+ * fill mac frame not copied counter
+ */
+static void smt_fill_mac_fnc(smc,fnc)
+struct s_smc *smc ;
+struct smt_p_mac_fnc *fnc ;
+{
+ SMTSETPARA(fnc,SMT_P_MAC_FNC) ;
+ fnc->nc_mib_index = INDEX_MAC ;
+ fnc->nc_index = mac_index(smc,1) ;
+ fnc->nc_counter = smc->mib.m[MAC0].fddiMACNotCopied_Ct ;
+}
+
+
+/*
+ * fill manufacturer field
+ */
+static void smt_fill_manufacturer(smc,man)
+struct s_smc *smc ;
+struct smp_p_manufacturer *man ;
+{
+ SMTSETPARA(man,SMT_P_MANUFACTURER) ;
+ memcpy((char *) man->mf_data,
+ (char *) smc->mib.fddiSMTManufacturerData,
+ sizeof(man->mf_data)) ;
+}
+
+/*
+ * fill user field
+ */
+static void smt_fill_user(smc,user)
+struct s_smc *smc ;
+struct smp_p_user *user ;
+{
+ SMTSETPARA(user,SMT_P_USER) ;
+ memcpy((char *) user->us_data,
+ (char *) smc->mib.fddiSMTUserData,
+ sizeof(user->us_data)) ;
+}
+
+
+
+/*
+ * fill set count
+ */
+static void smt_fill_setcount(smc,setcount)
+struct s_smc *smc ;
+struct smt_p_setcount *setcount ;
+{
+ SK_UNUSED(smc) ;
+ SMTSETPARA(setcount,SMT_P_SETCOUNT) ;
+ setcount->count = smc->mib.fddiSMTSetCount.count ;
+ memcpy((char *)setcount->timestamp,
+ (char *)smc->mib.fddiSMTSetCount.timestamp,8) ;
+}
+
+/*
+ * fill echo data
+ */
+static void smt_fill_echo(smc,echo,seed,len)
+struct s_smc *smc ;
+struct smt_p_echo *echo ;
+u_long seed ;
+int len ;
+{
+
+ u_char *p ;
+
+ SK_UNUSED(smc) ;
+ SMTSETPARA(echo,SMT_P_ECHODATA) ;
+ echo->para.p_len = len ;
+ for (p = echo->ec_data ; len ; len--) {
+ *p++ = (u_char) seed ;
+ seed += 13 ;
+ }
+}
+
+/*
+ * clear DNA and UNA
+ * called from CFM if configuration changes
+ */
+void smt_clear_una_dna(smc)
+struct s_smc *smc ;
+{
+ smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ;
+ smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ;
+}
+
+static void smt_clear_old_una_dna(smc)
+struct s_smc *smc ;
+{
+ smc->mib.m[MAC0].fddiMACOldUpstreamNbr = SMT_Unknown ;
+ smc->mib.m[MAC0].fddiMACOldDownstreamNbr = SMT_Unknown ;
+}
+
+u_long smt_get_tid(smc)
+struct s_smc *smc ;
+{
+ u_long tid ;
+ while ((tid = ++(smc->sm.smt_tid) ^ SMT_TID_MAGIC) == 0)
+ ;
+ return(tid & 0x3fffffffL) ;
+}
+
+
+/*
+ * table of parameter lengths
+ */
+static const struct smt_pdef {
+ int ptype ;
+ int plen ;
+ const char *pswap ;
+} smt_pdef[] = {
+ { SMT_P_UNA, sizeof(struct smt_p_una) ,
+ SWAP_SMT_P_UNA } ,
+ { SMT_P_SDE, sizeof(struct smt_p_sde) ,
+ SWAP_SMT_P_SDE } ,
+ { SMT_P_STATE, sizeof(struct smt_p_state) ,
+ SWAP_SMT_P_STATE } ,
+ { SMT_P_TIMESTAMP,sizeof(struct smt_p_timestamp) ,
+ SWAP_SMT_P_TIMESTAMP } ,
+ { SMT_P_POLICY, sizeof(struct smt_p_policy) ,
+ SWAP_SMT_P_POLICY } ,
+ { SMT_P_LATENCY, sizeof(struct smt_p_latency) ,
+ SWAP_SMT_P_LATENCY } ,
+ { SMT_P_NEIGHBORS,sizeof(struct smt_p_neighbor) ,
+ SWAP_SMT_P_NEIGHBORS } ,
+ { SMT_P_PATH, sizeof(struct smt_p_path) ,
+ SWAP_SMT_P_PATH } ,
+ { SMT_P_MAC_STATUS,sizeof(struct smt_p_mac_status) ,
+ SWAP_SMT_P_MAC_STATUS } ,
+ { SMT_P_LEM, sizeof(struct smt_p_lem) ,
+ SWAP_SMT_P_LEM } ,
+ { SMT_P_MAC_COUNTER,sizeof(struct smt_p_mac_counter) ,
+ SWAP_SMT_P_MAC_COUNTER } ,
+ { SMT_P_MAC_FNC,sizeof(struct smt_p_mac_fnc) ,
+ SWAP_SMT_P_MAC_FNC } ,
+ { SMT_P_PRIORITY,sizeof(struct smt_p_priority) ,
+ SWAP_SMT_P_PRIORITY } ,
+ { SMT_P_EB,sizeof(struct smt_p_eb) ,
+ SWAP_SMT_P_EB } ,
+ { SMT_P_MANUFACTURER,sizeof(struct smp_p_manufacturer) ,
+ SWAP_SMT_P_MANUFACTURER } ,
+ { SMT_P_REASON, sizeof(struct smt_p_reason) ,
+ SWAP_SMT_P_REASON } ,
+ { SMT_P_REFUSED, sizeof(struct smt_p_refused) ,
+ SWAP_SMT_P_REFUSED } ,
+ { SMT_P_VERSION, sizeof(struct smt_p_version) ,
+ SWAP_SMT_P_VERSION } ,
+#ifdef ESS
+ { SMT_P0015, sizeof(struct smt_p_0015) , SWAP_SMT_P0015 } ,
+ { SMT_P0016, sizeof(struct smt_p_0016) , SWAP_SMT_P0016 } ,
+ { SMT_P0017, sizeof(struct smt_p_0017) , SWAP_SMT_P0017 } ,
+ { SMT_P0018, sizeof(struct smt_p_0018) , SWAP_SMT_P0018 } ,
+ { SMT_P0019, sizeof(struct smt_p_0019) , SWAP_SMT_P0019 } ,
+ { SMT_P001A, sizeof(struct smt_p_001a) , SWAP_SMT_P001A } ,
+ { SMT_P001B, sizeof(struct smt_p_001b) , SWAP_SMT_P001B } ,
+ { SMT_P001C, sizeof(struct smt_p_001c) , SWAP_SMT_P001C } ,
+ { SMT_P001D, sizeof(struct smt_p_001d) , SWAP_SMT_P001D } ,
+#endif
+#if 0
+ { SMT_P_FSC, sizeof(struct smt_p_fsc) ,
+ SWAP_SMT_P_FSC } ,
+#endif
+
+ { SMT_P_SETCOUNT,0, SWAP_SMT_P_SETCOUNT } ,
+ { SMT_P1048, 0, SWAP_SMT_P1048 } ,
+ { SMT_P208C, 0, SWAP_SMT_P208C } ,
+ { SMT_P208D, 0, SWAP_SMT_P208D } ,
+ { SMT_P208E, 0, SWAP_SMT_P208E } ,
+ { SMT_P208F, 0, SWAP_SMT_P208F } ,
+ { SMT_P2090, 0, SWAP_SMT_P2090 } ,
+#ifdef ESS
+ { SMT_P320B, sizeof(struct smt_p_320b) , SWAP_SMT_P320B } ,
+ { SMT_P320F, sizeof(struct smt_p_320f) , SWAP_SMT_P320F } ,
+ { SMT_P3210, sizeof(struct smt_p_3210) , SWAP_SMT_P3210 } ,
+#endif
+ { SMT_P4050, 0, SWAP_SMT_P4050 } ,
+ { SMT_P4051, 0, SWAP_SMT_P4051 } ,
+ { SMT_P4052, 0, SWAP_SMT_P4052 } ,
+ { SMT_P4053, 0, SWAP_SMT_P4053 } ,
+} ;
+
+#define N_SMT_PLEN (sizeof(smt_pdef)/sizeof(smt_pdef[0]))
+
+int smt_check_para(smc,sm,list)
+struct s_smc *smc ;
+struct smt_header *sm ;
+const u_short list[] ;
+{
+ const u_short *p = list ;
+ while (*p) {
+ if (!sm_to_para(smc,sm,(int) *p)) {
+ DB_SMT("SMT: smt_check_para - missing para %x\n",*p,0);
+ return(-1) ;
+ }
+ p++ ;
+ }
+ return(0) ;
+}
+
+EXPORT_PMF void *sm_to_para(smc,sm,para)
+struct s_smc *smc ;
+struct smt_header *sm ;
+int para ;
+{
+ char *p ;
+ int len ;
+ int plen ;
+ void *found = 0 ;
+
+ SK_UNUSED(smc) ;
+
+ len = sm->smt_len ;
+ p = (char *)(sm+1) ; /* pointer to info */
+ while (len > 0 ) {
+ if (((struct smt_para *)p)->p_type == para)
+ found = (void *) p ;
+ plen = ((struct smt_para *)p)->p_len + PARA_LEN ;
+ p += plen ;
+ len -= plen ;
+ if (len < 0) {
+ DB_SMT("SMT : sm_to_para - length error %d\n",plen,0) ;
+ return(0) ;
+ }
+ if ((plen & 3) && (para != SMT_P_ECHODATA)) {
+ DB_SMT("SMT : sm_to_para - odd length %d\n",plen,0) ;
+ return(0) ;
+ }
+ if (found)
+ return(found) ;
+ }
+ return(0) ;
+}
+
+int is_my_addr(smc,addr)
+struct s_smc *smc ;
+struct fddi_addr *addr ;
+{
+ return(*(short *)(&addr->a[0]) ==
+ *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[0])
+ && *(short *)(&addr->a[2]) ==
+ *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[2])
+ && *(short *)(&addr->a[4]) ==
+ *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[4])) ;
+}
+
+int is_zero(addr)
+struct fddi_addr *addr ;
+{
+ return(*(short *)(&addr->a[0]) == 0 &&
+ *(short *)(&addr->a[2]) == 0 &&
+ *(short *)(&addr->a[4]) == 0 ) ;
+}
+
+int is_broadcast(addr)
+struct fddi_addr *addr ;
+{
+ return(*(u_short *)(&addr->a[0]) == 0xffff &&
+ *(u_short *)(&addr->a[2]) == 0xffff &&
+ *(u_short *)(&addr->a[4]) == 0xffff ) ;
+}
+
+int is_individual(addr)
+struct fddi_addr *addr ;
+{
+ return(!(addr->a[0] & GROUP_ADDR)) ;
+}
+
+int is_equal(addr1,addr2)
+struct fddi_addr *addr1 ;
+struct fddi_addr *addr2 ;
+{
+ return(*(u_short *)(&addr1->a[0]) == *(u_short *)(&addr2->a[0]) &&
+ *(u_short *)(&addr1->a[2]) == *(u_short *)(&addr2->a[2]) &&
+ *(u_short *)(&addr1->a[4]) == *(u_short *)(&addr2->a[4]) ) ;
+}
+
+
+#if 0
+/*
+ * send ANTC data test frame
+ */
+void fddi_send_antc(smc,dest)
+struct s_smc *smc ;
+struct fddi_addr *dest ;
+{
+ SK_UNUSED(smc) ;
+ SK_UNUSED(dest) ;
+#if 0
+ SMbuf *mb ;
+ struct smt_header *smt ;
+ int i ;
+ char *p ;
+
+ mb = smt_get_mbuf() ;
+ mb->sm_len = 3000+12 ;
+ p = smtod(mb, char *) + 12 ;
+ for (i = 0 ; i < 3000 ; i++)
+ *p++ = 1 << (i&7) ;
+
+ smt = smtod(mb, struct smt_header *) ;
+ smt->smt_dest = *dest ;
+ smt->smt_source = smc->mib.m[MAC0].fddiMACSMTAddress ;
+ smt_send_mbuf(smc,mb,FC_ASYNC_LLC) ;
+#endif
+}
+#endif
+
+#ifdef DEBUG
+#define hextoasc(x) "0123456789abcdef"[x]
+
+char *addr_to_string(addr)
+struct fddi_addr *addr ;
+{
+ int i ;
+ static char string[6*3] = "****" ;
+
+ for (i = 0 ; i < 6 ; i++) {
+ string[i*3] = hextoasc((addr->a[i]>>4)&0xf) ;
+ string[i*3+1] = hextoasc((addr->a[i])&0xf) ;
+ string[i*3+2] = ':' ;
+ }
+ string[5*3+2] = 0 ;
+ return(string) ;
+}
+#endif
+
+#ifdef AM29K
+smt_ifconfig(argc,argv)
+int argc ;
+char *argv[] ;
+{
+ if (argc >= 2 && !strcmp(argv[0],"opt_bypass") &&
+ !strcmp(argv[1],"yes")) {
+ smc->mib.fddiSMTBypassPresent = 1 ;
+ return(0) ;
+ }
+ return(amdfddi_config(0,argc,argv)) ;
+}
+#endif
+
+/*
+ * return static mac index
+ */
+static int mac_index(smc,mac)
+struct s_smc *smc ;
+int mac ;
+{
+ SK_UNUSED(mac) ;
+#ifdef CONCENTRATOR
+ SK_UNUSED(smc) ;
+ return(NUMPHYS+1) ;
+#else
+ return((smc->s.sas == SMT_SAS) ? 2 : 3) ;
+#endif
+}
+
+/*
+ * return static phy index
+ */
+static int phy_index(smc,phy)
+struct s_smc *smc ;
+int phy ;
+{
+ SK_UNUSED(smc) ;
+ return(phy+1);
+}
+
+/*
+ * return dynamic mac connection resource index
+ */
+static int mac_con_resource_index(smc,mac)
+struct s_smc *smc ;
+int mac ;
+{
+#ifdef CONCENTRATOR
+ SK_UNUSED(smc) ;
+ SK_UNUSED(mac) ;
+ return(entity_to_index(smc,cem_get_downstream(smc,ENTITY_MAC))) ;
+#else
+ SK_UNUSED(mac) ;
+ switch (smc->mib.fddiSMTCF_State) {
+ case SC9_C_WRAP_A :
+ case SC5_THRU_B :
+ case SC11_C_WRAP_S :
+ return(1) ;
+ case SC10_C_WRAP_B :
+ case SC4_THRU_A :
+ return(2) ;
+ }
+ return(smc->s.sas == SMT_SAS ? 2 : 3) ;
+#endif
+}
+
+/*
+ * return dynamic phy connection resource index
+ */
+static int phy_con_resource_index(smc,phy)
+struct s_smc *smc ;
+int phy ;
+{
+#ifdef CONCENTRATOR
+ return(entity_to_index(smc,cem_get_downstream(smc,ENTITY_PHY(phy)))) ;
+#else
+ switch (smc->mib.fddiSMTCF_State) {
+ case SC9_C_WRAP_A :
+ return(phy == PA ? 3 : 2) ;
+ case SC10_C_WRAP_B :
+ return(phy == PA ? 1 : 3) ;
+ case SC4_THRU_A :
+ return(phy == PA ? 3 : 1) ;
+ case SC5_THRU_B :
+ return(phy == PA ? 2 : 3) ;
+ case SC11_C_WRAP_S :
+ return(2) ;
+ }
+ return(phy) ;
+#endif
+}
+
+#ifdef CONCENTRATOR
+static int entity_to_index(smc,e)
+struct s_smc *smc ;
+int e ;
+{
+ if (e == ENTITY_MAC)
+ return(mac_index(smc,1)) ;
+ else
+ return(phy_index(smc,e - ENTITY_PHY(0))) ;
+}
+#endif
+
+#ifdef LITTLE_ENDIAN
+static int smt_swap_short(s)
+u_short s ;
+{
+ return(((s>>8)&0xff)|((s&0xff)<<8)) ;
+}
+
+void smt_swap_para(sm,len,direction)
+struct smt_header *sm ;
+int len ;
+int direction ; /* 0 encode 1 decode */
+{
+ struct smt_para *pa ;
+ const struct smt_pdef *pd ;
+ char *p ;
+ int plen ;
+ int type ;
+ int i ;
+
+/* printf("smt_swap_para sm %x len %d dir %d\n",
+ sm,len,direction) ;
+ */
+ smt_string_swap((char *)sm,SWAP_SMTHEADER,len) ;
+
+ /* swap args */
+ len -= sizeof(struct smt_header) ;
+
+ p = (char *) (sm + 1) ;
+ while (len > 0) {
+ pa = (struct smt_para *) p ;
+ plen = pa->p_len ;
+ type = pa->p_type ;
+ pa->p_type = smt_swap_short(pa->p_type) ;
+ pa->p_len = smt_swap_short(pa->p_len) ;
+ if (direction) {
+ plen = pa->p_len ;
+ type = pa->p_type ;
+ }
+ /*
+ * note: paras can have 0 length !
+ */
+ if (plen < 0)
+ break ;
+ plen += PARA_LEN ;
+ for (i = N_SMT_PLEN, pd = smt_pdef; i ; i--,pd++) {
+ if (pd->ptype == type)
+ break ;
+ }
+ if (i && pd->pswap) {
+ smt_string_swap(p+PARA_LEN,pd->pswap,len) ;
+ }
+ len -= plen ;
+ p += plen ;
+ }
+}
+
+static void smt_string_swap(data,format,len)
+char *data ;
+const char *format ;
+int len ;
+{
+ const char *open_paren = 0 ;
+ int x ;
+
+ while (len > 0 && *format) {
+ switch (*format) {
+ case '[' :
+ open_paren = format ;
+ break ;
+ case ']' :
+ format = open_paren ;
+ break ;
+ case '1' :
+ case '2' :
+ case '3' :
+ case '4' :
+ case '5' :
+ case '6' :
+ case '7' :
+ case '8' :
+ case '9' :
+ data += *format - '0' ;
+ len -= *format - '0' ;
+ break ;
+ case 'c':
+ data++ ;
+ len-- ;
+ break ;
+ case 's' :
+ x = data[0] ;
+ data[0] = data[1] ;
+ data[1] = x ;
+ data += 2 ;
+ len -= 2 ;
+ break ;
+ case 'l' :
+ x = data[0] ;
+ data[0] = data[3] ;
+ data[3] = x ;
+ x = data[1] ;
+ data[1] = data[2] ;
+ data[2] = x ;
+ data += 4 ;
+ len -= 4 ;
+ break ;
+ }
+ format++ ;
+ }
+}
+#else
+void smt_swap_para(sm,len,direction)
+struct smt_header *sm ;
+int len ;
+int direction ; /* 0 encode 1 decode */
+{
+ SK_UNUSED(sm) ;
+ SK_UNUSED(len) ;
+ SK_UNUSED(direction) ;
+}
+#endif
+
+/*
+ * PMF actions
+ */
+int smt_action(smc,class,code,index)
+struct s_smc *smc ;
+int class ;
+int code ;
+int index ;
+{
+ int event ;
+ int port ;
+ DB_SMT("SMT: action %d code %d\n",class,code) ;
+ switch(class) {
+ case SMT_STATION_ACTION :
+ switch(code) {
+ case SMT_STATION_ACTION_CONNECT :
+ smc->mib.fddiSMTRemoteDisconnectFlag = FALSE ;
+ queue_event(smc,EVENT_ECM,EC_CONNECT) ;
+ break ;
+ case SMT_STATION_ACTION_DISCONNECT :
+ queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
+ smc->mib.fddiSMTRemoteDisconnectFlag = TRUE ;
+ RS_SET(smc,RS_DISCONNECT) ;
+ AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
+ FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_DISCONNECT,
+ smt_get_event_word(smc));
+ break ;
+ case SMT_STATION_ACTION_PATHTEST :
+ AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
+ FDDI_SMT_EVENT, (u_long) FDDI_PATH_TEST,
+ smt_get_event_word(smc));
+ break ;
+ case SMT_STATION_ACTION_SELFTEST :
+ AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
+ FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_SELF_TEST,
+ smt_get_event_word(smc));
+ break ;
+ case SMT_STATION_ACTION_DISABLE_A :
+ if (smc->y[PA].pc_mode == PM_PEER) {
+ RS_SET(smc,RS_EVENT) ;
+ queue_event(smc,EVENT_PCM+PA,PC_DISABLE) ;
+ }
+ break ;
+ case SMT_STATION_ACTION_DISABLE_B :
+ if (smc->y[PB].pc_mode == PM_PEER) {
+ RS_SET(smc,RS_EVENT) ;
+ queue_event(smc,EVENT_PCM+PB,PC_DISABLE) ;
+ }
+ break ;
+ case SMT_STATION_ACTION_DISABLE_M :
+ for (port = 0 ; port < NUMPHYS ; port++) {
+ if (smc->mib.p[port].fddiPORTMy_Type != TM)
+ continue ;
+ RS_SET(smc,RS_EVENT) ;
+ queue_event(smc,EVENT_PCM+port,PC_DISABLE) ;
+ }
+ break ;
+ default :
+ return(1) ;
+ }
+ break ;
+ case SMT_PORT_ACTION :
+ switch(code) {
+ case SMT_PORT_ACTION_ENABLE :
+ event = PC_ENABLE ;
+ break ;
+ case SMT_PORT_ACTION_DISABLE :
+ event = PC_DISABLE ;
+ break ;
+ case SMT_PORT_ACTION_MAINT :
+ event = PC_MAINT ;
+ break ;
+ case SMT_PORT_ACTION_START :
+ event = PC_START ;
+ break ;
+ case SMT_PORT_ACTION_STOP :
+ event = PC_STOP ;
+ break ;
+ default :
+ return(1) ;
+ }
+ queue_event(smc,EVENT_PCM+index,event) ;
+ break ;
+ default :
+ return(1) ;
+ }
+ return(0) ;
+}
+
+/*
+ * change tneg
+ * set T_Req in MIB (Path Attribute)
+ * calculate new values for MAC
+ * if change required
+ * disconnect
+ * set reconnect
+ * end
+ */
+void smt_change_t_neg(smc,tneg)
+struct s_smc *smc ;
+u_long tneg ;
+{
+ smc->mib.a[PATH0].fddiPATHMaxT_Req = tneg ;
+
+ if (smt_set_mac_opvalues(smc)) {
+ RS_SET(smc,RS_EVENT) ;
+ smc->sm.please_reconnect = 1 ;
+ queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
+ }
+}
+
+/*
+ * canonical conversion of <len> bytes beginning form *data
+ */
+#ifdef USE_CAN_ADDR
+void hwm_conv_can(smc,data,len)
+struct s_smc *smc ;
+char *data ;
+int len ;
+{
+ int i ;
+
+ SK_UNUSED(smc) ;
+
+ for (i = len; i ; i--, data++) {
+ *data = canonical[*(u_char *)data] ;
+ }
+}
+#endif
+
+#endif /* no SLIM_SMT */
diff --git a/drivers/net/skfp/smtdef.c b/drivers/net/skfp/smtdef.c
new file mode 100644
index 000000000..221b0334c
--- /dev/null
+++ b/drivers/net/skfp/smtdef.c
@@ -0,0 +1,371 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ SMT/CMT defaults
+*/
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+
+#ifndef OEM_USER_DATA
+#define OEM_USER_DATA "SK-NET FDDI V2.0 Userdata"
+#endif
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)smtdef.c 2.53 99/08/11 (C) SK " ;
+#endif
+
+/*
+ * defaults
+ */
+#define TTMS(x) ((u_long)(x)*1000L)
+#define TTS(x) ((u_long)(x)*1000000L)
+#define TTUS(x) ((u_long)(x))
+
+#define DEFAULT_TB_MIN TTMS(5)
+#define DEFAULT_TB_MAX TTMS(50)
+#define DEFAULT_C_MIN TTUS(1600)
+#define DEFAULT_T_OUT TTMS(100+5)
+#define DEFAULT_TL_MIN TTUS(30)
+#define DEFAULT_LC_SHORT TTMS(50+5)
+#define DEFAULT_LC_MEDIUM TTMS(500+20)
+#define DEFAULT_LC_LONG TTS(5)+TTMS(50)
+#define DEFAULT_LC_EXTENDED TTS(50)+TTMS(50)
+#define DEFAULT_T_NEXT_9 TTMS(200+10)
+#define DEFAULT_NS_MAX TTUS(1310)
+#define DEFAULT_I_MAX TTMS(25)
+#define DEFAULT_IN_MAX TTMS(40)
+#define DEFAULT_TD_MIN TTMS(5)
+#define DEFAULT_T_NON_OP TTS(1)
+#define DEFAULT_T_STUCK TTS(8)
+#define DEFAULT_T_DIRECT TTMS(370)
+#define DEFAULT_T_JAM TTMS(370)
+#define DEFAULT_T_ANNOUNCE TTMS(2500)
+#define DEFAULT_D_MAX TTUS(1617)
+#define DEFAULT_LEM_ALARM (8)
+#define DEFAULT_LEM_CUTOFF (7)
+#define DEFAULT_TEST_DONE TTS(1)
+#define DEFAULT_CHECK_POLL TTS(1)
+#define DEFAULT_POLL TTMS(50)
+
+/*
+ * LCT errors threshold
+ */
+#define DEFAULT_LCT_SHORT 1
+#define DEFAULT_LCT_MEDIUM 3
+#define DEFAULT_LCT_LONG 5
+#define DEFAULT_LCT_EXTEND 50
+
+/* Forward declarations */
+extern void smt_reset_defaults ();
+static void smt_init_mib ();
+
+static int set_min_max() ;
+
+void smt_set_defaults(smc)
+struct s_smc *smc ;
+{
+ smt_reset_defaults(smc,0) ;
+}
+
+#define MS2BCLK(x) ((x)*12500L)
+#define US2BCLK(x) ((x)*1250L)
+
+void smt_reset_defaults(smc,level)
+struct s_smc *smc ;
+int level ;
+{
+ struct smt_config *smt ;
+ int i ;
+ u_long smt_boot_time;
+
+
+ smt_init_mib(smc,level) ;
+
+ smc->os.smc_version = SMC_VERSION ;
+ smt_boot_time = smt_get_time();
+ for( i = 0; i < NUMMACS; i++ )
+ smc->sm.last_tok_time[i] = smt_boot_time ;
+ smt = &smc->s ;
+ smt->attach_s = 0 ;
+ smt->build_ring_map = 1 ;
+ smt->sas = SMT_DAS ;
+ smt->numphys = NUMPHYS ;
+ smt->pcm_tb_min = DEFAULT_TB_MIN ;
+ smt->pcm_tb_max = DEFAULT_TB_MAX ;
+ smt->pcm_c_min = DEFAULT_C_MIN ;
+ smt->pcm_t_out = DEFAULT_T_OUT ;
+ smt->pcm_tl_min = DEFAULT_TL_MIN ;
+ smt->pcm_lc_short = DEFAULT_LC_SHORT ;
+ smt->pcm_lc_medium = DEFAULT_LC_MEDIUM ;
+ smt->pcm_lc_long = DEFAULT_LC_LONG ;
+ smt->pcm_lc_extended = DEFAULT_LC_EXTENDED ;
+ smt->pcm_t_next_9 = DEFAULT_T_NEXT_9 ;
+ smt->pcm_ns_max = DEFAULT_NS_MAX ;
+ smt->ecm_i_max = DEFAULT_I_MAX ;
+ smt->ecm_in_max = DEFAULT_IN_MAX ;
+ smt->ecm_td_min = DEFAULT_TD_MIN ;
+ smt->ecm_test_done = DEFAULT_TEST_DONE ;
+ smt->ecm_check_poll = DEFAULT_CHECK_POLL ;
+ smt->rmt_t_non_op = DEFAULT_T_NON_OP ;
+ smt->rmt_t_stuck = DEFAULT_T_STUCK ;
+ smt->rmt_t_direct = DEFAULT_T_DIRECT ;
+ smt->rmt_t_jam = DEFAULT_T_JAM ;
+ smt->rmt_t_announce = DEFAULT_T_ANNOUNCE ;
+ smt->rmt_t_poll = DEFAULT_POLL ;
+ smt->rmt_dup_mac_behavior = FALSE ; /* See Struct smt_config */
+ smt->mac_d_max = DEFAULT_D_MAX ;
+
+ smt->lct_short = DEFAULT_LCT_SHORT ;
+ smt->lct_medium = DEFAULT_LCT_MEDIUM ;
+ smt->lct_long = DEFAULT_LCT_LONG ;
+ smt->lct_extended = DEFAULT_LCT_EXTEND ;
+
+#ifndef SLIM_SMT
+#ifdef ESS
+ if (level == 0) {
+ smc->ess.sync_bw_available = FALSE ;
+ smc->mib.fddiESSPayload = 0 ;
+ smc->mib.fddiESSOverhead = 0 ;
+ smc->mib.fddiESSMaxTNeg = (u_long)(- MS2BCLK(25)) ;
+ smc->mib.fddiESSMinSegmentSize = 1 ;
+ smc->mib.fddiESSCategory = SB_STATIC ;
+ smc->mib.fddiESSSynchTxMode = FALSE ;
+ smc->ess.raf_act_timer_poll = FALSE ;
+ smc->ess.timer_count = 7 ; /* first RAF alc req after 3s */
+ }
+ smc->ess.local_sba_active = FALSE ;
+ smc->ess.sba_reply_pend = NULL ;
+#endif
+#ifdef SBA
+ smt_init_sba(smc,level) ;
+#endif
+#endif /* no SLIM_SMT */
+#ifdef TAG_MODE
+ if (level == 0) {
+ smc->hw.pci_fix_value = 0 ;
+ }
+#endif
+}
+
+/*
+ * manufacturer data
+ */
+static const char man_data[32] =
+/* 01234567890123456789012345678901 */
+ "xxxSK-NET FDDI SMT 7.3 - V2.8.8" ;
+
+static void smt_init_mib(smc,level)
+struct s_smc *smc ;
+int level ;
+{
+ struct fddi_mib *mib ;
+ struct fddi_mib_p *pm ;
+ int port ;
+ int path ;
+
+ mib = &smc->mib ;
+ if (level == 0) {
+ /*
+ * set EVERYTHING to ZERO
+ * EXCEPT hw and os
+ */
+ memset(((char *)smc)+
+ sizeof(struct s_smt_os)+sizeof(struct s_smt_hw), 0,
+ sizeof(struct s_smc) -
+ sizeof(struct s_smt_os) - sizeof(struct s_smt_hw)) ;
+ }
+ else {
+ mib->fddiSMTRemoteDisconnectFlag = 0 ;
+ mib->fddiSMTPeerWrapFlag = 0 ;
+ }
+
+ mib->fddiSMTOpVersionId = 2 ;
+ mib->fddiSMTHiVersionId = 2 ;
+ mib->fddiSMTLoVersionId = 2 ;
+ memcpy((char *) mib->fddiSMTManufacturerData,man_data,32) ;
+ if (level == 0) {
+ strcpy(mib->fddiSMTUserData,OEM_USER_DATA) ;
+ }
+ mib->fddiSMTMIBVersionId = 1 ;
+ mib->fddiSMTMac_Ct = NUMMACS ;
+ mib->fddiSMTConnectionPolicy = POLICY_MM | POLICY_AA | POLICY_BB ;
+
+ /*
+ * fddiSMTNonMaster_Ct and fddiSMTMaster_Ct are set in smt_fixup_mib
+ * s.sas is not set yet (is set in init driver)
+ */
+ mib->fddiSMTAvailablePaths = MIB_PATH_P | MIB_PATH_S ;
+
+ mib->fddiSMTConfigCapabilities = 0 ; /* no hold,no wrap_ab*/
+ mib->fddiSMTTT_Notify = 10 ;
+ mib->fddiSMTStatRptPolicy = TRUE ;
+ mib->fddiSMTTrace_MaxExpiration = SEC2MIB(7) ;
+ mib->fddiSMTMACIndexes = INDEX_MAC ;
+ mib->fddiSMTStationStatus = MIB_SMT_STASTA_SEPA ; /* seperated */
+
+ mib->m[MAC0].fddiMACIndex = INDEX_MAC ;
+ mib->m[MAC0].fddiMACFrameStatusFunctions = FSC_TYPE0 ;
+ mib->m[MAC0].fddiMACRequestedPaths =
+ MIB_P_PATH_LOCAL |
+ MIB_P_PATH_SEC_ALTER |
+ MIB_P_PATH_PRIM_ALTER ;
+ mib->m[MAC0].fddiMACAvailablePaths = MIB_PATH_P ;
+ mib->m[MAC0].fddiMACCurrentPath = MIB_PATH_PRIMARY ;
+ mib->m[MAC0].fddiMACT_MaxCapabilitiy = (u_long)(- MS2BCLK(165)) ;
+ mib->m[MAC0].fddiMACTVXCapabilitiy = (u_long)(- US2BCLK(52)) ;
+ if (level == 0) {
+ mib->m[MAC0].fddiMACTvxValue = (u_long)(- US2BCLK(27)) ;
+ mib->m[MAC0].fddiMACTvxValueMIB = (u_long)(- US2BCLK(27)) ;
+ mib->m[MAC0].fddiMACT_Req = (u_long)(- MS2BCLK(165)) ;
+ mib->m[MAC0].fddiMACT_ReqMIB = (u_long)(- MS2BCLK(165)) ;
+ mib->m[MAC0].fddiMACT_Max = (u_long)(- MS2BCLK(165)) ;
+ mib->m[MAC0].fddiMACT_MaxMIB = (u_long)(- MS2BCLK(165)) ;
+ mib->m[MAC0].fddiMACT_Min = (u_long)(- MS2BCLK(4)) ;
+ }
+ mib->m[MAC0].fddiMACHardwarePresent = TRUE ;
+ mib->m[MAC0].fddiMACMA_UnitdataEnable = TRUE ;
+ mib->m[MAC0].fddiMACFrameErrorThreshold = 1 ;
+ mib->m[MAC0].fddiMACNotCopiedThreshold = 1 ;
+ /*
+ * Path attributes
+ */
+ for (path = 0 ; path < NUMPATHS ; path++) {
+ mib->a[path].fddiPATHIndex = INDEX_PATH + path ;
+ if (level == 0) {
+ mib->a[path].fddiPATHTVXLowerBound =
+ (u_long)(- US2BCLK(27)) ;
+ mib->a[path].fddiPATHT_MaxLowerBound =
+ (u_long)(- MS2BCLK(165)) ;
+ mib->a[path].fddiPATHMaxT_Req =
+ (u_long)(- MS2BCLK(165)) ;
+ }
+ }
+
+
+ /*
+ * Port attributes
+ */
+ pm = mib->p ;
+ for (port = 0 ; port < NUMPHYS ; port++) {
+ /*
+ * set MIB pointer in phy
+ */
+ /* Attention: don't initialize mib pointer here! */
+ /* It must be initialized during phase 2 */
+ smc->y[port].mib = 0 ;
+ mib->fddiSMTPORTIndexes[port] = port+INDEX_PORT ;
+
+ pm->fddiPORTIndex = port+INDEX_PORT ;
+ pm->fddiPORTHardwarePresent = TRUE ;
+ if (level == 0) {
+ pm->fddiPORTLer_Alarm = DEFAULT_LEM_ALARM ;
+ pm->fddiPORTLer_Cutoff = DEFAULT_LEM_CUTOFF ;
+ }
+ /*
+ * fddiPORTRequestedPaths are set in pcmplc.c
+ * we don't know the port type yet !
+ */
+ pm->fddiPORTRequestedPaths[1] = 0 ;
+ pm->fddiPORTRequestedPaths[2] = 0 ;
+ pm->fddiPORTRequestedPaths[3] = 0 ;
+ pm->fddiPORTAvailablePaths = MIB_PATH_P ;
+ pm->fddiPORTPMDClass = MIB_PMDCLASS_MULTI ;
+ pm++ ;
+ }
+
+ (void) smt_set_mac_opvalues(smc) ;
+}
+
+int smt_set_mac_opvalues(smc)
+struct s_smc *smc ;
+{
+ int st ;
+ int st2 ;
+
+ st = set_min_max(1,smc->mib.m[MAC0].fddiMACTvxValueMIB,
+ smc->mib.a[PATH0].fddiPATHTVXLowerBound,
+ &smc->mib.m[MAC0].fddiMACTvxValue) ;
+ st |= set_min_max(0,smc->mib.m[MAC0].fddiMACT_MaxMIB,
+ smc->mib.a[PATH0].fddiPATHT_MaxLowerBound,
+ &smc->mib.m[MAC0].fddiMACT_Max) ;
+ st |= (st2 = set_min_max(0,smc->mib.m[MAC0].fddiMACT_ReqMIB,
+ smc->mib.a[PATH0].fddiPATHMaxT_Req,
+ &smc->mib.m[MAC0].fddiMACT_Req)) ;
+ if (st2) {
+ /* Treq attribute changed remotely. So send an AIX_EVENT to the
+ * user
+ */
+ AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
+ FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_T_REQ,
+ smt_get_event_word(smc));
+ }
+ return(st) ;
+}
+
+void smt_fixup_mib(smc)
+struct s_smc *smc ;
+{
+#ifdef CONCENTRATOR
+ switch (smc->s.sas) {
+ case SMT_SAS :
+ smc->mib.fddiSMTNonMaster_Ct = 1 ;
+ break ;
+ case SMT_DAS :
+ smc->mib.fddiSMTNonMaster_Ct = 2 ;
+ break ;
+ case SMT_NAC :
+ smc->mib.fddiSMTNonMaster_Ct = 0 ;
+ break ;
+ }
+ smc->mib.fddiSMTMaster_Ct = NUMPHYS - smc->mib.fddiSMTNonMaster_Ct ;
+#else
+ switch (smc->s.sas) {
+ case SMT_SAS :
+ smc->mib.fddiSMTNonMaster_Ct = 1 ;
+ break ;
+ case SMT_DAS :
+ smc->mib.fddiSMTNonMaster_Ct = 2 ;
+ break ;
+ }
+ smc->mib.fddiSMTMaster_Ct = 0 ;
+#endif
+}
+
+/*
+ * determine new setting for operational value
+ * if limit is lower than mib
+ * use limit
+ * else
+ * use mib
+ * NOTE : numbers are negative, negate comparison !
+ */
+static int set_min_max(maxflag,mib,limit,oper)
+int maxflag ;
+u_long mib ;
+u_long limit ;
+u_long *oper ;
+{
+ u_long old ;
+ old = *oper ;
+ if ((limit > mib) ^ maxflag)
+ *oper = limit ;
+ else
+ *oper = mib ;
+ return(old != *oper) ;
+}
diff --git a/drivers/net/skfp/smtinit.c b/drivers/net/skfp/smtinit.c
new file mode 100644
index 000000000..c4b5af9b5
--- /dev/null
+++ b/drivers/net/skfp/smtinit.c
@@ -0,0 +1,126 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ Init SMT
+ call all module level initialization routines
+*/
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)smtinit.c 1.15 97/05/06 (C) SK " ;
+#endif
+
+extern void init_fddi_driver() ;
+
+/* define global debug variable */
+#if defined(DEBUG) && !defined(DEBUG_BRD)
+struct smt_debug debug;
+#endif
+
+#ifndef MULT_OEM
+#define OEMID(smc,i) oem_id[i]
+ extern u_char oem_id[] ;
+#else /* MULT_OEM */
+#define OEMID(smc,i) smc->hw.oem_id->oi_mark[i]
+ extern struct s_oem_ids oem_ids[] ;
+#endif /* MULT_OEM */
+
+/*
+ * Set OEM specific values
+ *
+ * Can not be called in smt_reset_defaults, because it is not sure that
+ * the OEM ID is already defined.
+ */
+static void set_oem_spec_val(smc)
+struct s_smc *smc ;
+{
+ struct fddi_mib *mib ;
+
+ mib = &smc->mib ;
+
+ /*
+ * set IBM specific values
+ */
+ if (OEMID(smc,0) == 'I') {
+ mib->fddiSMTConnectionPolicy = POLICY_MM ;
+ }
+}
+
+/*
+ * Init SMT
+ */
+int init_smt(smc,mac_addr)
+struct s_smc *smc ;
+u_char *mac_addr ; /* canonical address or NULL */
+{
+ int p ;
+
+#if defined(DEBUG) && !defined(DEBUG_BRD)
+ debug.d_smt = 0 ;
+ debug.d_smtf = 0 ;
+ debug.d_rmt = 0 ;
+ debug.d_ecm = 0 ;
+ debug.d_pcm = 0 ;
+ debug.d_cfm = 0 ;
+
+ debug.d_plc = 0 ;
+#ifdef ESS
+ debug.d_ess = 0 ;
+#endif
+#ifdef SBA
+ debug.d_sba = 0 ;
+#endif
+#endif /* DEBUG && !DEBUG_BRD */
+
+ /* First initialize the ports mib->pointers */
+ for ( p = 0; p < NUMPHYS; p ++ ) {
+ smc->y[p].mib = & smc->mib.p[p] ;
+ }
+
+ set_oem_spec_val(smc) ;
+ (void) smt_set_mac_opvalues(smc) ;
+ init_fddi_driver(smc,mac_addr) ; /* HW driver */
+ smt_fixup_mib(smc) ; /* update values that depend on s.sas */
+
+ ev_init(smc) ; /* event queue */
+#ifndef SLIM_SMT
+ smt_init_evc(smc) ; /* evcs in MIB */
+#endif /* no SLIM_SMT */
+ smt_timer_init(smc) ; /* timer package */
+ smt_agent_init(smc) ; /* SMT frame manager */
+
+ pcm_init(smc) ; /* PCM state machine */
+ ecm_init(smc) ; /* ECM state machine */
+ cfm_init(smc) ; /* CFM state machine */
+ rmt_init(smc) ; /* RMT state machine */
+
+ for (p = 0 ; p < NUMPHYS ; p++) {
+ pcm(smc,p,0) ; /* PCM A state machine */
+ }
+ ecm(smc,0) ; /* ECM state machine */
+ cfm(smc,0) ; /* CFM state machine */
+ rmt(smc,0) ; /* RMT state machine */
+
+ smt_agent_task(smc) ; /* NIF FSM etc */
+
+ PNMI_INIT(smc) ; /* PNMI initialization */
+
+ return(0) ;
+}
diff --git a/drivers/net/skfp/smtparse.c b/drivers/net/skfp/smtparse.c
new file mode 100644
index 000000000..0b4a2274d
--- /dev/null
+++ b/drivers/net/skfp/smtparse.c
@@ -0,0 +1,475 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+
+/*
+ parser for SMT parameters
+*/
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/smt_p.h"
+
+#define KERNEL
+#include "h/smtstate.h"
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)smtparse.c 1.12 98/10/06 (C) SK " ;
+#endif
+
+#ifdef sun
+#define _far
+#endif
+
+/*
+ * convert to BCLK units
+ */
+#define MS2BCLK(x) ((x)*12500L)
+#define US2BCLK(x) ((x/10)*125L)
+
+/*
+ * parameter table
+ */
+static struct s_ptab {
+ char *pt_name ;
+ u_short pt_num ;
+ u_short pt_type ;
+ u_long pt_min ;
+ u_long pt_max ;
+} ptab[] = {
+ { "PMFPASSWD",0, 0 } ,
+ { "USERDATA",1, 0 } ,
+ { "LERCUTOFFA",2, 1, 4, 15 } ,
+ { "LERCUTOFFB",3, 1, 4, 15 } ,
+ { "LERALARMA",4, 1, 4, 15 } ,
+ { "LERALARMB",5, 1, 4, 15 } ,
+ { "TMAX",6, 1, 5, 165 } ,
+ { "TMIN",7, 1, 5, 165 } ,
+ { "TREQ",8, 1, 5, 165 } ,
+ { "TVX",9, 1, 2500, 10000 } ,
+#ifdef ESS
+ { "SBAPAYLOAD",10, 1, 0, 1562 } ,
+ { "SBAOVERHEAD",11, 1, 50, 5000 } ,
+ { "MAXTNEG",12, 1, 5, 165 } ,
+ { "MINSEGMENTSIZE",13, 1, 0, 4478 } ,
+ { "SBACATEGORY",14, 1, 0, 0xffff } ,
+ { "SYNCHTXMODE",15, 0 } ,
+#endif
+#ifdef SBA
+ { "SBACOMMAND",16, 0 } ,
+ { "SBAAVAILABLE",17, 1, 0, 100 } ,
+#endif
+ { 0 }
+} ;
+
+/* Define maximum string size for values and keybuffer */
+#define MAX_VAL 40
+
+/*
+ * local function declarations
+ */
+static u_long parse_num() ;
+static int parse_word() ;
+
+#ifdef SIM
+#define DB_MAIN(a,b,c) printf(a,b,c)
+#else
+#define DB_MAIN(a,b,c)
+#endif
+
+/*
+ * BEGIN_MANUAL_ENTRY()
+ *
+ * int smt_parse_arg(struct s_smc *,char _far *keyword,int type,
+ char _far *value)
+ *
+ * parse SMT parameter
+ * *keyword
+ * pointer to keyword, must be \0, \n or \r terminated
+ * *value pointer to value, either char * or u_long *
+ * if char *
+ * pointer to value, must be \0, \n or \r terminated
+ * if u_long *
+ * contains binary value
+ *
+ * type 0: integer
+ * 1: string
+ * return
+ * 0 parameter parsed ok
+ * != 0 error
+ * NOTE:
+ * function can be called with DS != SS
+ *
+ *
+ * END_MANUAL_ENTRY()
+ */
+int smt_parse_arg(smc,keyword,type,value)
+struct s_smc *smc ;
+char _far *keyword ;
+int type ;
+char _far *value ;
+{
+ char keybuf[MAX_VAL+1];
+ char valbuf[MAX_VAL+1];
+ char c ;
+ char *p ;
+ char *v ;
+ char *d ;
+ u_long val = 0 ;
+ struct s_ptab *pt ;
+ int st ;
+ int i ;
+
+ /*
+ * parse keyword
+ */
+ if ((st = parse_word(keybuf,keyword)))
+ return(st) ;
+ /*
+ * parse value if given as string
+ */
+ if (type == 1) {
+ if ((st = parse_word(valbuf,value)))
+ return(st) ;
+ }
+ /*
+ * search in table
+ */
+ st = 0 ;
+ for (pt = ptab ; (v = pt->pt_name) ; pt++) {
+ for (p = keybuf ; (c = *p) ; p++,v++) {
+ if (c != *v)
+ break ;
+ }
+ if (!c && !*v)
+ break ;
+ }
+ if (!v)
+ return(-1) ;
+#if 0
+ printf("=>%s<==>%s<=\n",pt->pt_name,valbuf) ;
+#endif
+ /*
+ * set value in MIB
+ */
+ if (pt->pt_type)
+ val = parse_num(type,value,valbuf,pt->pt_min,pt->pt_max,1) ;
+ switch (pt->pt_num) {
+ case 0 :
+ v = valbuf ;
+ d = (char *) smc->mib.fddiPRPMFPasswd ;
+ for (i = 0 ; i < (signed)sizeof(smc->mib.fddiPRPMFPasswd) ; i++)
+ *d++ = *v++ ;
+ DB_MAIN("SET %s = %s\n",pt->pt_name,smc->mib.fddiPRPMFPasswd) ;
+ break ;
+ case 1 :
+ v = valbuf ;
+ d = (char *) smc->mib.fddiSMTUserData ;
+ for (i = 0 ; i < (signed)sizeof(smc->mib.fddiSMTUserData) ; i++)
+ *d++ = *v++ ;
+ DB_MAIN("SET %s = %s\n",pt->pt_name,smc->mib.fddiSMTUserData) ;
+ break ;
+ case 2 :
+ smc->mib.p[PA].fddiPORTLer_Cutoff = (u_char) val ;
+ DB_MAIN("SET %s = %d\n",
+ pt->pt_name,smc->mib.p[PA].fddiPORTLer_Cutoff) ;
+ break ;
+ case 3 :
+ smc->mib.p[PB].fddiPORTLer_Cutoff = (u_char) val ;
+ DB_MAIN("SET %s = %d\n",
+ pt->pt_name,smc->mib.p[PB].fddiPORTLer_Cutoff) ;
+ break ;
+ case 4 :
+ smc->mib.p[PA].fddiPORTLer_Alarm = (u_char) val ;
+ DB_MAIN("SET %s = %d\n",
+ pt->pt_name,smc->mib.p[PA].fddiPORTLer_Alarm) ;
+ break ;
+ case 5 :
+ smc->mib.p[PB].fddiPORTLer_Alarm = (u_char) val ;
+ DB_MAIN("SET %s = %d\n",
+ pt->pt_name,smc->mib.p[PB].fddiPORTLer_Alarm) ;
+ break ;
+ case 6 : /* TMAX */
+ DB_MAIN("SET %s = %d\n",pt->pt_name,val) ;
+ smc->mib.a[PATH0].fddiPATHT_MaxLowerBound =
+ (u_long) -MS2BCLK((long)val) ;
+ break ;
+ case 7 : /* TMIN */
+ DB_MAIN("SET %s = %d\n",pt->pt_name,val) ;
+ smc->mib.m[MAC0].fddiMACT_Min =
+ (u_long) -MS2BCLK((long)val) ;
+ break ;
+ case 8 : /* TREQ */
+ DB_MAIN("SET %s = %d\n",pt->pt_name,val) ;
+ smc->mib.a[PATH0].fddiPATHMaxT_Req =
+ (u_long) -MS2BCLK((long)val) ;
+ break ;
+ case 9 : /* TVX */
+ DB_MAIN("SET %s = %d \n",pt->pt_name,val) ;
+ smc->mib.a[PATH0].fddiPATHTVXLowerBound =
+ (u_long) -US2BCLK((long)val) ;
+ break ;
+#ifdef ESS
+ case 10 : /* SBAPAYLOAD */
+ DB_MAIN("SET %s = %d\n",pt->pt_name,val) ;
+ if (smc->mib.fddiESSPayload != val) {
+ smc->ess.raf_act_timer_poll = TRUE ;
+ smc->mib.fddiESSPayload = val ;
+ }
+ break ;
+ case 11 : /* SBAOVERHEAD */
+ DB_MAIN("SET %s = %d\n",pt->pt_name,val) ;
+ smc->mib.fddiESSOverhead = val ;
+ break ;
+ case 12 : /* MAXTNEG */
+ DB_MAIN("SET %s = %d\n",pt->pt_name,val) ;
+ smc->mib.fddiESSMaxTNeg = (u_long) -MS2BCLK((long)val) ;
+ break ;
+ case 13 : /* MINSEGMENTSIZE */
+ DB_MAIN("SET %s = %d\n",pt->pt_name,val) ;
+ smc->mib.fddiESSMinSegmentSize = val ;
+ break ;
+ case 14 : /* SBACATEGORY */
+ DB_MAIN("SET %s = %d\n",pt->pt_name,val) ;
+ smc->mib.fddiESSCategory =
+ (smc->mib.fddiESSCategory & 0xffff) |
+ ((u_long)(val << 16)) ;
+ break ;
+ case 15 : /* SYNCHTXMODE */
+ /* do not use memcmp(valbuf,"ALL",3) because DS != SS */
+ if (valbuf[0] == 'A' && valbuf[1] == 'L' && valbuf[2] == 'L') {
+ smc->mib.fddiESSSynchTxMode = TRUE ;
+ DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ;
+ }
+ /* if (!memcmp(valbuf,"SPLIT",5)) { */
+ if (valbuf[0] == 'S' && valbuf[1] == 'P' && valbuf[2] == 'L' &&
+ valbuf[3] == 'I' && valbuf[4] == 'T') {
+ DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ;
+ smc->mib.fddiESSSynchTxMode = FALSE ;
+ }
+ break ;
+#endif
+#ifdef SBA
+ case 16 : /* SBACOMMAND */
+ /* if (!memcmp(valbuf,"START",5)) { */
+ if (valbuf[0] == 'S' && valbuf[1] == 'T' && valbuf[2] == 'A' &&
+ valbuf[3] == 'R' && valbuf[4] == 'T') {
+ DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ;
+ smc->mib.fddiSBACommand = SB_START ;
+ }
+ /* if (!memcmp(valbuf,"STOP",4)) { */
+ if (valbuf[0] == 'S' && valbuf[1] == 'T' && valbuf[2] == 'O' &&
+ valbuf[3] == 'P') {
+ DB_MAIN("SET %s = %s\n",pt->pt_name,valbuf) ;
+ smc->mib.fddiSBACommand = SB_STOP ;
+ }
+ break ;
+ case 17 : /* SBAAVAILABLE */
+ DB_MAIN("SET %s = %d\n",pt->pt_name,val) ;
+ smc->mib.fddiSBAAvailable = (u_char) val ;
+ break ;
+#endif
+ }
+ return(0) ;
+}
+
+static int parse_word(buf,text)
+char *buf ;
+char _far *text ;
+{
+ char c ;
+ char *p ;
+ int p_len ;
+ int quote ;
+ int i ;
+ int ok ;
+
+ /*
+ * skip leading white space
+ */
+ p = buf ;
+ for (i = 0 ; i < MAX_VAL ; i++)
+ *p++ = 0 ;
+ p = buf ;
+ p_len = 0 ;
+ ok = 0 ;
+ while ( (c = *text++) && (c != '\n') && (c != '\r')) {
+ if ((c != ' ') && (c != '\t')) {
+ ok = 1 ;
+ break ;
+ }
+ }
+ if (!ok)
+ return(-1) ;
+ if (c == '"') {
+ quote = 1 ;
+ }
+ else {
+ quote = 0 ;
+ text-- ;
+ }
+ /*
+ * parse valbuf
+ */
+ ok = 0 ;
+ while (!ok && p_len < MAX_VAL-1 && (c = *text++) && (c != '\n')
+ && (c != '\r')) {
+ switch (quote) {
+ case 0 :
+ if ((c == ' ') || (c == '\t') || (c == '=')) {
+ ok = 1 ;
+ break ;
+ }
+ *p++ = c ;
+ p_len++ ;
+ break ;
+ case 2 :
+ *p++ = c ;
+ p_len++ ;
+ quote = 1 ;
+ break ;
+ case 1 :
+ switch (c) {
+ case '"' :
+ ok = 1 ;
+ break ;
+ case '\\' :
+ quote = 2 ;
+ break ;
+ default :
+ *p++ = c ;
+ p_len++ ;
+ }
+ }
+ }
+ *p++ = 0 ;
+ for (p = buf ; (c = *p) ; p++) {
+ if (c >= 'a' && c <= 'z')
+ *p = c + 'A' - 'a' ;
+ }
+ return(0) ;
+}
+
+static u_long parse_num(type,value,v,mn,mx,scale)
+int type ;
+char _far *value ;
+char *v ;
+u_long mn ;
+u_long mx ;
+int scale ;
+{
+ u_long x = 0 ;
+ char c ;
+
+ if (type == 0) { /* integer */
+ u_long _far *l ;
+ u_long u1 ;
+
+ l = (u_long _far *) value ;
+ u1 = *l ;
+ /*
+ * if the value is negative take the lower limit
+ */
+ if ((long)u1 < 0) {
+ if (- ((long)u1) > (long) mx) {
+ u1 = 0 ;
+ }
+ else {
+ u1 = (u_long) - ((long)u1) ;
+ }
+ }
+ x = u1 ;
+ }
+ else { /* string */
+ int sign = 0 ;
+
+ if (*v == '-') {
+ sign = 1 ;
+ }
+ while ((c = *v++) && (c >= '0') && (c <= '9')) {
+ x = x * 10 + c - '0' ;
+ }
+ if (scale == 10) {
+ x *= 10 ;
+ if (c == '.') {
+ if ((c = *v++) && (c >= '0') && (c <= '9')) {
+ x += c - '0' ;
+ }
+ }
+ }
+ if (sign)
+ x = (u_long) - ((long)x) ;
+ }
+ /*
+ * if the value is negative
+ * and the absolute value is outside the limits
+ * take the lower limit
+ * else
+ * take the absoute value
+ */
+ if ((long)x < 0) {
+ if (- ((long)x) > (long) mx) {
+ x = 0 ;
+ }
+ else {
+ x = (u_long) - ((long)x) ;
+ }
+ }
+ if (x < mn)
+ return(mn) ;
+ else if (x > mx)
+ return(mx) ;
+ return(x) ;
+}
+
+#if 0
+struct s_smc SMC ;
+main()
+{
+ char *p ;
+ char *v ;
+ char buf[100] ;
+ int toggle = 0 ;
+
+ while (gets(buf)) {
+ p = buf ;
+ while (*p && ((*p == ' ') || (*p == '\t')))
+ p++ ;
+
+ while (*p && ((*p != ' ') && (*p != '\t')))
+ p++ ;
+
+ v = p ;
+ while (*v && ((*v == ' ') || (*v == '\t')))
+ v++ ;
+ if ((*v >= '0') && (*v <= '9')) {
+ toggle = !toggle ;
+ if (toggle) {
+ u_long l ;
+ l = atol(v) ;
+ smt_parse_arg(&SMC,buf,0,(char _far *)&l) ;
+ }
+ else
+ smt_parse_arg(&SMC,buf,1,(char _far *)p) ;
+ }
+ else {
+ smt_parse_arg(&SMC,buf,1,(char _far *)p) ;
+ }
+ }
+ exit(0) ;
+}
+#endif
diff --git a/drivers/net/skfp/smttimer.c b/drivers/net/skfp/smttimer.c
new file mode 100644
index 000000000..9d7b71e26
--- /dev/null
+++ b/drivers/net/skfp/smttimer.c
@@ -0,0 +1,173 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ SMT timer
+*/
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)smttimer.c 2.4 97/08/04 (C) SK " ;
+#endif
+
+/*
+ * external function declarations
+ */
+extern u_long hwt_read() ;
+extern void hwt_stop() ;
+extern void hwt_start() ;
+
+static void timer_done() ;
+
+
+void smt_timer_init(smc)
+struct s_smc *smc ;
+{
+ smc->t.st_queue = 0 ;
+ smc->t.st_fast.tm_active = FALSE ;
+ smc->t.st_fast.tm_next = 0 ;
+ hwt_init(smc) ;
+}
+
+void smt_timer_stop(smc,timer)
+struct s_smc *smc ;
+struct smt_timer *timer ;
+{
+ struct smt_timer **prev ;
+ struct smt_timer *tm ;
+
+ /*
+ * remove timer from queue
+ */
+ timer->tm_active = FALSE ;
+ if (smc->t.st_queue == timer && !timer->tm_next) {
+ hwt_stop(smc) ;
+ }
+ for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
+ if (tm == timer) {
+ *prev = tm->tm_next ;
+ if (tm->tm_next) {
+ tm->tm_next->tm_delta += tm->tm_delta ;
+ }
+ return ;
+ }
+ }
+}
+
+void smt_timer_start(smc,timer,time,token)
+struct s_smc *smc ;
+struct smt_timer *timer ;
+u_long time ;
+u_long token ;
+{
+ struct smt_timer **prev ;
+ struct smt_timer *tm ;
+ u_long delta = 0 ;
+
+ time /= 16 ; /* input is uS, clock ticks are 16uS */
+ if (!time)
+ time = 1 ;
+ smt_timer_stop(smc,timer) ;
+ timer->tm_smc = smc ;
+ timer->tm_token = token ;
+ timer->tm_active = TRUE ;
+ if (!smc->t.st_queue) {
+ smc->t.st_queue = timer ;
+ timer->tm_next = 0 ;
+ timer->tm_delta = time ;
+ hwt_start(smc,time) ;
+ return ;
+ }
+ /*
+ * timer correction
+ */
+ timer_done(smc,0) ;
+
+ /*
+ * find position in queue
+ */
+ delta = 0 ;
+ for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
+ if (delta + tm->tm_delta > time) {
+ break ;
+ }
+ delta += tm->tm_delta ;
+ }
+ /* insert in queue */
+ *prev = timer ;
+ timer->tm_next = tm ;
+ timer->tm_delta = time - delta ;
+ if (tm)
+ tm->tm_delta -= timer->tm_delta ;
+ /*
+ * start new with first
+ */
+ hwt_start(smc,smc->t.st_queue->tm_delta) ;
+}
+
+void smt_force_irq(smc)
+struct s_smc *smc ;
+{
+ smt_timer_start(smc,&smc->t.st_fast,32L, EV_TOKEN(EVENT_SMT,SM_FAST));
+}
+
+void smt_timer_done(smc)
+struct s_smc *smc ;
+{
+ timer_done(smc,1) ;
+}
+
+static void timer_done(smc,restart)
+struct s_smc *smc ;
+int restart ;
+{
+ u_long delta ;
+ struct smt_timer *tm ;
+ struct smt_timer *next ;
+ struct smt_timer **last ;
+ int done = 0 ;
+
+ delta = hwt_read(smc) ;
+ last = &smc->t.st_queue ;
+ tm = smc->t.st_queue ;
+ while (tm && !done) {
+ if (delta >= tm->tm_delta) {
+ tm->tm_active = FALSE ;
+ delta -= tm->tm_delta ;
+ last = &tm->tm_next ;
+ tm = tm->tm_next ;
+ }
+ else {
+ tm->tm_delta -= delta ;
+ delta = 0 ;
+ done = 1 ;
+ }
+ }
+ *last = 0 ;
+ next = smc->t.st_queue ;
+ smc->t.st_queue = tm ;
+
+ for ( tm = next ; tm ; tm = next) {
+ next = tm->tm_next ;
+ timer_event(smc,tm->tm_token) ;
+ }
+
+ if (restart && smc->t.st_queue)
+ hwt_start(smc,smc->t.st_queue->tm_delta) ;
+}
diff --git a/drivers/net/skfp/srf.c b/drivers/net/skfp/srf.c
new file mode 100644
index 000000000..79bbfedc6
--- /dev/null
+++ b/drivers/net/skfp/srf.c
@@ -0,0 +1,441 @@
+/******************************************************************************
+ *
+ * (C)Copyright 1998,1999 SysKonnect,
+ * a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ * See the file "skfddi.c" for further information.
+ *
+ * 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.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ SMT 7.2 Status Response Frame Implementation
+ SRF state machine and frame generation
+*/
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/smt_p.h"
+
+#define KERNEL
+#include "h/smtstate.h"
+
+#ifndef SLIM_SMT
+#ifndef BOOT
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)srf.c 1.18 97/08/04 (C) SK " ;
+#endif
+
+
+/*
+ * function declarations
+ */
+static void clear_all_rep() ;
+static void clear_reported() ;
+static void smt_send_srf() ;
+static struct s_srf_evc *smt_get_evc() ;
+
+#define MAX_EVCS (sizeof(smc->evcs)/sizeof(smc->evcs[0]))
+
+struct evc_init {
+ u_char code ;
+ u_char index ;
+ u_char n ;
+ u_short para ;
+} ;
+
+static const struct evc_init evc_inits[] = {
+ { SMT_COND_SMT_PEER_WRAP, 0,1,SMT_P1048 } ,
+
+ { SMT_COND_MAC_DUP_ADDR, INDEX_MAC, NUMMACS,SMT_P208C } ,
+ { SMT_COND_MAC_FRAME_ERROR, INDEX_MAC, NUMMACS,SMT_P208D } ,
+ { SMT_COND_MAC_NOT_COPIED, INDEX_MAC, NUMMACS,SMT_P208E } ,
+ { SMT_EVENT_MAC_NEIGHBOR_CHANGE, INDEX_MAC, NUMMACS,SMT_P208F } ,
+ { SMT_EVENT_MAC_PATH_CHANGE, INDEX_MAC, NUMMACS,SMT_P2090 } ,
+
+ { SMT_COND_PORT_LER, INDEX_PORT,NUMPHYS,SMT_P4050 } ,
+ { SMT_COND_PORT_EB_ERROR, INDEX_PORT,NUMPHYS,SMT_P4052 } ,
+ { SMT_EVENT_PORT_CONNECTION, INDEX_PORT,NUMPHYS,SMT_P4051 } ,
+ { SMT_EVENT_PORT_PATH_CHANGE, INDEX_PORT,NUMPHYS,SMT_P4053 } ,
+} ;
+
+#define MAX_INIT_EVC (sizeof(evc_inits)/sizeof(evc_inits[0]))
+
+void smt_init_evc(smc)
+struct s_smc *smc ;
+{
+ struct s_srf_evc *evc ;
+ const struct evc_init *init ;
+ int i ;
+ int index ;
+ int offset ;
+
+ static u_char fail_safe = FALSE ;
+
+ memset((char *)smc->evcs,0,sizeof(smc->evcs)) ;
+
+ evc = smc->evcs ;
+ init = evc_inits ;
+
+ for (i = 0 ; (unsigned) i < MAX_INIT_EVC ; i++) {
+ for (index = 0 ; index < init->n ; index++) {
+ evc->evc_code = init->code ;
+ evc->evc_para = init->para ;
+ evc->evc_index = init->index + index ;
+#ifndef DEBUG
+ evc->evc_multiple = &fail_safe ;
+ evc->evc_cond_state = &fail_safe ;
+#endif
+ evc++ ;
+ }
+ init++ ;
+ }
+
+ if ((unsigned) (evc - smc->evcs) > MAX_EVCS) {
+ SMT_PANIC(smc,SMT_E0127, SMT_E0127_MSG) ;
+ }
+
+ /*
+ * conditions
+ */
+ smc->evcs[0].evc_cond_state = &smc->mib.fddiSMTPeerWrapFlag ;
+ smc->evcs[1].evc_cond_state =
+ &smc->mib.m[MAC0].fddiMACDuplicateAddressCond ;
+ smc->evcs[2].evc_cond_state =
+ &smc->mib.m[MAC0].fddiMACFrameErrorFlag ;
+ smc->evcs[3].evc_cond_state =
+ &smc->mib.m[MAC0].fddiMACNotCopiedFlag ;
+
+ /*
+ * events
+ */
+ smc->evcs[4].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_N ;
+ smc->evcs[5].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_P ;
+
+ offset = 6 ;
+ for (i = 0 ; i < NUMPHYS ; i++) {
+ /*
+ * conditions
+ */
+ smc->evcs[offset + 0*NUMPHYS].evc_cond_state =
+ &smc->mib.p[i].fddiPORTLerFlag ;
+ smc->evcs[offset + 1*NUMPHYS].evc_cond_state =
+ &smc->mib.p[i].fddiPORTEB_Condition ;
+
+ /*
+ * events
+ */
+ smc->evcs[offset + 2*NUMPHYS].evc_multiple =
+ &smc->mib.p[i].fddiPORTMultiple_U ;
+ smc->evcs[offset + 3*NUMPHYS].evc_multiple =
+ &smc->mib.p[i].fddiPORTMultiple_P ;
+ offset++ ;
+ }
+#ifdef DEBUG
+ for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
+ if (SMT_IS_CONDITION(evc->evc_code)) {
+ if (!evc->evc_cond_state) {
+ SMT_PANIC(smc,SMT_E0128, SMT_E0128_MSG) ;
+ }
+ evc->evc_multiple = &fail_safe ;
+ }
+ else {
+ if (!evc->evc_multiple) {
+ SMT_PANIC(smc,SMT_E0129, SMT_E0129_MSG) ;
+ }
+ evc->evc_cond_state = &fail_safe ;
+ }
+ }
+#endif
+ smc->srf.TSR = smt_get_time() ;
+ smc->srf.sr_state = SR0_WAIT ;
+}
+
+static struct s_srf_evc *smt_get_evc(smc,code,index)
+struct s_smc *smc ;
+int code ;
+int index ;
+{
+ int i ;
+ struct s_srf_evc *evc ;
+
+ for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
+ if (evc->evc_code == code && evc->evc_index == index)
+ return(evc) ;
+ }
+ return(0) ;
+}
+
+#define THRESHOLD_2 (2*TICKS_PER_SECOND)
+#define THRESHOLD_32 (32*TICKS_PER_SECOND)
+
+#ifdef DEBUG
+static const char * const srf_names[] = {
+ "None","MACPathChangeEvent", "MACNeighborChangeEvent",
+ "PORTPathChangeEvent", "PORTUndesiredConnectionAttemptEvent",
+ "SMTPeerWrapCondition", "SMTHoldCondition",
+ "MACFrameErrorCondition", "MACDuplicateAddressCondition",
+ "MACNotCopiedCondition", "PORTEBErrorCondition",
+ "PORTLerCondition"
+} ;
+#endif
+
+void smt_srf_event(smc,code,index,cond)
+struct s_smc *smc ;
+int code ;
+int index ;
+int cond ;
+{
+ struct s_srf_evc *evc ;
+ int cond_asserted = 0 ;
+ int cond_deasserted = 0 ;
+ int event_occured = 0 ;
+ int tsr ;
+ int T_Limit = 2*TICKS_PER_SECOND ;
+
+ if (code == SMT_COND_MAC_DUP_ADDR && cond) {
+ RS_SET(smc,RS_DUPADDR) ;
+ }
+
+ if (code) {
+ DB_SMT("SRF: %s index %d\n",srf_names[code],index) ;
+
+ if (!(evc = smt_get_evc(smc,code,index))) {
+ DB_SMT("SRF : smt_get_evc() failed\n",0,0) ;
+ return ;
+ }
+ /*
+ * ignore condition if no change
+ */
+ if (SMT_IS_CONDITION(code)) {
+ if (*evc->evc_cond_state == cond)
+ return ;
+ }
+
+ /*
+ * set transition time stamp
+ */
+ smt_set_timestamp(smc,smc->mib.fddiSMTTransitionTimeStamp) ;
+ if (SMT_IS_CONDITION(code)) {
+ DB_SMT("SRF: condition is %s\n",cond ? "ON":"OFF",0) ;
+ if (cond) {
+ *evc->evc_cond_state = TRUE ;
+ evc->evc_rep_required = TRUE ;
+ smc->srf.any_report = TRUE ;
+ cond_asserted = TRUE ;
+ }
+ else {
+ *evc->evc_cond_state = FALSE ;
+ cond_deasserted = TRUE ;
+ }
+ }
+ else {
+ if (evc->evc_rep_required) {
+ *evc->evc_multiple = TRUE ;
+ }
+ else {
+ evc->evc_rep_required = TRUE ;
+ *evc->evc_multiple = FALSE ;
+ }
+ smc->srf.any_report = TRUE ;
+ event_occured = TRUE ;
+ }
+#ifdef FDDI_MIB
+ snmp_srf_event(smc,evc) ;
+#endif /* FDDI_MIB */
+ }
+ tsr = smt_get_time() - smc->srf.TSR ;
+
+ switch (smc->srf.sr_state) {
+ case SR0_WAIT :
+ /* SR01a */
+ if (cond_asserted && tsr < T_Limit) {
+ smc->srf.SRThreshold = THRESHOLD_2 ;
+ smc->srf.sr_state = SR1_HOLDOFF ;
+ break ;
+ }
+ /* SR01b */
+ if (cond_deasserted && tsr < T_Limit) {
+ smc->srf.sr_state = SR1_HOLDOFF ;
+ break ;
+ }
+ /* SR01c */
+ if (event_occured && tsr < T_Limit) {
+ smc->srf.sr_state = SR1_HOLDOFF ;
+ break ;
+ }
+ /* SR00b */
+ if (cond_asserted && tsr >= T_Limit) {
+ smc->srf.SRThreshold = THRESHOLD_2 ;
+ smc->srf.TSR = smt_get_time() ;
+ smt_send_srf(smc) ;
+ break ;
+ }
+ /* SR00c */
+ if (cond_deasserted && tsr >= T_Limit) {
+ smc->srf.TSR = smt_get_time() ;
+ smt_send_srf(smc) ;
+ break ;
+ }
+ /* SR00d */
+ if (event_occured && tsr >= T_Limit) {
+ smc->srf.TSR = smt_get_time() ;
+ smt_send_srf(smc) ;
+ break ;
+ }
+ /* SR00e */
+ if (smc->srf.any_report && (u_long) tsr >=
+ smc->srf.SRThreshold) {
+ smc->srf.SRThreshold *= 2 ;
+ if (smc->srf.SRThreshold > THRESHOLD_32)
+ smc->srf.SRThreshold = THRESHOLD_32 ;
+ smc->srf.TSR = smt_get_time() ;
+ smt_send_srf(smc) ;
+ break ;
+ }
+ /* SR02 */
+ if (!smc->mib.fddiSMTStatRptPolicy) {
+ smc->srf.sr_state = SR2_DISABLED ;
+ break ;
+ }
+ break ;
+ case SR1_HOLDOFF :
+ /* SR10b */
+ if (tsr >= T_Limit) {
+ smc->srf.sr_state = SR0_WAIT ;
+ smc->srf.TSR = smt_get_time() ;
+ smt_send_srf(smc) ;
+ break ;
+ }
+ /* SR11a */
+ if (cond_asserted) {
+ smc->srf.SRThreshold = THRESHOLD_2 ;
+ }
+ /* SR11b */
+ /* SR11c */
+ /* handled above */
+ /* SR12 */
+ if (!smc->mib.fddiSMTStatRptPolicy) {
+ smc->srf.sr_state = SR2_DISABLED ;
+ break ;
+ }
+ break ;
+ case SR2_DISABLED :
+ if (smc->mib.fddiSMTStatRptPolicy) {
+ smc->srf.sr_state = SR0_WAIT ;
+ smc->srf.TSR = smt_get_time() ;
+ smc->srf.SRThreshold = THRESHOLD_2 ;
+ clear_all_rep(smc) ;
+ break ;
+ }
+ break ;
+ }
+}
+
+static void clear_all_rep(smc)
+struct s_smc *smc ;
+{
+ struct s_srf_evc *evc ;
+ int i ;
+
+ for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
+ evc->evc_rep_required = FALSE ;
+ if (SMT_IS_CONDITION(evc->evc_code))
+ *evc->evc_cond_state = FALSE ;
+ }
+ smc->srf.any_report = FALSE ;
+}
+
+static void clear_reported(smc)
+struct s_smc *smc ;
+{
+ struct s_srf_evc *evc ;
+ int i ;
+
+ smc->srf.any_report = FALSE ;
+ for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
+ if (SMT_IS_CONDITION(evc->evc_code)) {
+ if (*evc->evc_cond_state == FALSE)
+ evc->evc_rep_required = FALSE ;
+ else
+ smc->srf.any_report = TRUE ;
+ }
+ else {
+ evc->evc_rep_required = FALSE ;
+ *evc->evc_multiple = FALSE ;
+ }
+ }
+}
+
+extern SMbuf *smt_build_frame() ;
+
+/*
+ * build and send SMT SRF frame
+ */
+static void smt_send_srf(smc)
+struct s_smc *smc ;
+{
+
+ struct smt_header *smt ;
+ struct s_srf_evc *evc ;
+ SK_LOC_DECL(struct s_pcon,pcon) ;
+ SMbuf *mb ;
+ int i ;
+
+ static const struct fddi_addr SMT_SRF_DA = {
+ 0x80, 0x01, 0x43, 0x00, 0x80, 0x08
+ } ;
+
+ /*
+ * build SMT header
+ */
+ if (!smc->r.sm_ma_avail)
+ return ;
+ if (!(mb = smt_build_frame(smc,SMT_SRF,SMT_ANNOUNCE,0)))
+ return ;
+
+ RS_SET(smc,RS_SOFTERROR) ;
+
+ smt = smtod(mb, struct smt_header *) ;
+ smt->smt_dest = SMT_SRF_DA ; /* DA == SRF multicast */
+
+ /*
+ * setup parameter status
+ */
+ pcon.pc_len = SMT_MAX_INFO_LEN ; /* max para length */
+ pcon.pc_err = 0 ; /* no error */
+ pcon.pc_badset = 0 ; /* no bad set count */
+ pcon.pc_p = (void *) (smt + 1) ; /* paras start here */
+
+ smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ;
+ smt_add_para(smc,&pcon,(u_short) SMT_P1034,0,0) ;
+
+ for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
+ if (evc->evc_rep_required) {
+ smt_add_para(smc,&pcon,evc->evc_para,
+ (int)evc->evc_index,0) ;
+ }
+ }
+ smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ;
+ mb->sm_len = smt->smt_len + sizeof(struct smt_header) ;
+
+ DB_SMT("SRF: sending SRF at %x, len %d \n",smt,mb->sm_len) ;
+ DB_SMT("SRF: state SR%d Threshold %d\n",
+ smc->srf.sr_state,smc->srf.SRThreshold/TICKS_PER_SECOND) ;
+#ifdef DEBUG
+ dump_smt(smc,smt,"SRF Send") ;
+#endif
+ smt_send_frame(smc,mb,FC_SMT_INFO,0) ;
+ clear_reported(smc) ;
+}
+
+#endif /* no BOOT */
+#endif /* no SLIM_SMT */
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 749e8e150..620b1cc46 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -449,7 +449,7 @@ static void slip_write_wakeup(struct tty_struct *tty)
struct slip *sl = (struct slip *) tty->disc_data;
/* First make sure we're connected. */
- if (!sl || sl->magic != SLIP_MAGIC || !test_bit(LINK_STATE_START, &sl->dev->state)) {
+ if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev)) {
return;
}
if (sl->xleft <= 0) {
@@ -472,10 +472,10 @@ static void sl_tx_timeout(struct net_device *dev)
spin_lock(&sl->lock);
- if (test_bit(LINK_STATE_XOFF, &dev->state)) {
+ if (netif_queue_stopped(dev)) {
struct slip *sl = (struct slip*)(dev->priv);
- if (!test_bit(LINK_STATE_START, &dev->state))
+ if (!netif_running(dev))
goto out;
/* May be we must check transmitter timeout here ?
@@ -507,7 +507,7 @@ sl_xmit(struct sk_buff *skb, struct net_device *dev)
struct slip *sl = (struct slip*)(dev->priv);
spin_lock(&sl->lock);
- if (!test_bit(LINK_STATE_START, &dev->state)) {
+ if (!netif_running(dev)) {
spin_unlock(&sl->lock);
printk("%s: xmit call when iface is down\n", dev->name);
dev_kfree_skb(skb);
@@ -679,7 +679,7 @@ static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp, ch
struct slip *sl = (struct slip *) tty->disc_data;
if (!sl || sl->magic != SLIP_MAGIC ||
- !test_bit(LINK_STATE_START, &sl->dev->state))
+ !netif_running(sl->dev))
return;
/* Read the characters out of the buffer */
@@ -1468,7 +1468,7 @@ static void sl_outfill(unsigned long sls)
unsigned char s = END;
#endif
/* put END into tty queue. Is it right ??? */
- if (!test_bit(LINK_STATE_XOFF, &sl->dev->state))
+ if (!netif_queue_stopped(sl->dev))
{
/* if device busy no outfill */
sl->tty->driver.write(sl->tty, 0, &s, 1);
diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
index 23644ef1d..ab1664fec 100644
--- a/drivers/net/smc-mca.c
+++ b/drivers/net/smc-mca.c
@@ -414,9 +414,8 @@ static int ultramca_close_card(struct net_device *dev)
{
int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
- dev->start = 0;
- dev->tbusy = 1;
-
+ netif_stop_queue(dev);
+
if (ei_debug > 1)
printk("%s: Shutting down ethercard.\n", dev->name);
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index 6a5555983..217159ea7 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -403,8 +403,7 @@ ultra_close_card(struct net_device *dev)
{
int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* CMDREG */
- dev->start = 0;
- dev->tbusy = 1;
+ netif_stop_queue(dev);
if (ei_debug > 1)
printk("%s: Shutting down ethercard.\n", dev->name);
diff --git a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c
index 4657500f0..22fdc6505 100644
--- a/drivers/net/smc-ultra32.c
+++ b/drivers/net/smc-ultra32.c
@@ -265,9 +265,8 @@ static int ultra32_close(struct net_device *dev)
{
int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* CMDREG */
- dev->start = 0;
- dev->tbusy = 1;
-
+ netif_stop_queue(dev);
+
if (ei_debug > 1)
printk("%s: Shutting down ethercard.\n", dev->name);
diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c
index 944ad87c3..661c1b363 100644
--- a/drivers/net/smc9194.c
+++ b/drivers/net/smc9194.c
@@ -50,11 +50,8 @@
static const char *version =
"smc9194.c:v0.12 03/06/96 by Erik Stahlman (erik@vt.edu)\n";
-#ifdef MODULE
#include <linux/module.h>
#include <linux/version.h>
-#endif
-
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
@@ -82,22 +79,6 @@ static const char *version =
-------------------------------------------------------------------------*/
/*
- . this is for kernels > 1.2.70
-*/
-#define REALLY_NEW_KERNEL
-#ifndef REALLY_NEW_KERNEL
-#define free_irq( x, y ) free_irq( x )
-#define request_irq( x, y, z, u, v ) request_irq( x, y, z, u )
-#endif
-
-/*
- . Do you want to use this with old kernels.
- . WARNING: this is not well tested.
-#define SUPPORT_OLD_KERNEL
-*/
-
-
-/*
. Do you want to use 32 bit xfers? This should work on all chips, as
. the chipset is designed to accommodate them.
*/
@@ -108,9 +89,10 @@ static const char *version =
.for a slightly different card, you can add it to the array. Keep in
.mind that the array must end in zero.
*/
-static unsigned int smc_portlist[] __initdata =
- { 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
- 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0};
+static unsigned int smc_portlist[] __initdata = {
+ 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
+ 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0
+};
/*
. Wait time for memory to be free. This probably shouldn't be
@@ -149,12 +131,6 @@ static unsigned int smc_portlist[] __initdata =
#endif
-/* the older versions of the kernel cannot support autoprobing */
-#ifdef SUPPORT_OLD_KERNEL
-#define NO_AUTOPROBE
-#endif
-
-
/*------------------------------------------------------------------------
.
. The internal workings of the driver. If you are changing anything
@@ -164,9 +140,6 @@ static unsigned int smc_portlist[] __initdata =
-------------------------------------------------------------------------*/
#define CARDNAME "SMC9194"
-#ifdef SUPPORT_OLD_KERNEL
-char kernel_version[] = UTS_RELEASE;
-#endif
/* store this information for the driver.. */
struct smc_local {
@@ -217,6 +190,11 @@ int smc_init(struct net_device *dev);
static int smc_open(struct net_device *dev);
/*
+ . Our watchdog timed out. Called by the networking layer
+*/
+static void smc_timeout(struct net_device *dev);
+
+/*
. This is called by the kernel to send a packet out into the net. it's
. responsible for doing a best-effort send, but if it's simply not possible
. to send it, the packet gets dropped.
@@ -240,12 +218,12 @@ static struct net_device_stats * smc_query_statistics( struct net_device *dev);
. Finally, a call to set promiscuous mode ( for TCPDUMP and related
. programs ) and multicast modes.
*/
-#ifdef SUPPORT_OLD_KERNEL
-static void smc_set_multicast_list(struct net_device *dev, int num_addrs,
- void *addrs);
-#else
static void smc_set_multicast_list(struct net_device *dev);
-#endif
+
+/*
+ . CRC compute
+ */
+static int crc32( char * s, int length );
/*---------------------------------------------------------------
.
@@ -256,11 +234,7 @@ static void smc_set_multicast_list(struct net_device *dev);
/*
. Handles the actual interrupt
*/
-#ifdef REALLY_NEW_KERNEL
static void smc_interrupt(int irq, void *, struct pt_regs *regs);
-#else
-static void smc_interrupt(int irq, struct pt_regs *regs);
-#endif
/*
. This is a separate procedure to handle the receipt of a packet, to
. leave the interrupt code looking slightly cleaner
@@ -321,25 +295,9 @@ static void smc_enable( int ioaddr );
/* this puts the device in an inactive state */
static void smc_shutdown( int ioaddr );
-#ifndef NO_AUTOPROBE
/* This routine will find the IRQ of the driver if one is not
. specified in the input to the device. */
static int smc_findirq( int ioaddr );
-#endif
-
-/*
- this routine will set the hardware multicast table to the specified
- values given it by the higher level routines
-*/
-#ifndef SUPPORT_OLD_KERNEL
-static void smc_setmulticast( int ioaddr, int count, struct dev_mc_list * );
-static int crc32( char *, int );
-#endif
-
-#ifdef SUPPORT_OLD_KERNEL
-extern struct net_device *init_etherdev(struct net_device *dev, int sizeof_private,
- unsigned long *mem_startp );
-#endif
/*
. Function: smc_reset( int ioaddr )
@@ -442,7 +400,6 @@ static void smc_shutdown( int ioaddr )
}
-#ifndef SUPPORT_OLD_KERNEL
/*
. Function: smc_setmulticast( int ioaddr, int count, dev_mc_list * adds )
. Purpose:
@@ -525,8 +482,6 @@ static int crc32( char * s, int length ) {
return crc_value;
}
-#endif
-
/*
. Function: smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * )
@@ -575,6 +530,7 @@ static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * de
dev_kfree_skb (skb);
lp->saved_skb = NULL;
/* this IS an error, but, i don't want the skb saved */
+ netif_wake_queue(dev);
return 0;
}
/* either way, a packet is waiting now */
@@ -616,7 +572,7 @@ static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * de
}
/* or YES! I can send the packet now.. */
smc_hardware_send_packet(dev);
-
+ netif_wake_queue(dev);
return 0;
}
@@ -663,7 +619,7 @@ static void smc_hardware_send_packet( struct net_device * dev )
printk(KERN_DEBUG CARDNAME": Memory allocation failed. \n");
kfree(skb);
lp->saved_skb = NULL;
- dev->tbusy = 0;
+ netif_wake_queue(dev);
return;
}
@@ -729,8 +685,7 @@ static void smc_hardware_send_packet( struct net_device * dev )
dev->trans_start = jiffies;
/* we can send another packet */
- dev->tbusy = 0;
-
+ netif_wake_queue(dev);
return;
}
@@ -787,7 +742,6 @@ int __init smc_init(struct net_device *dev)
return -ENODEV;
}
-#ifndef NO_AUTOPROBE
/*----------------------------------------------------------------------
. smc_findirq
.
@@ -860,7 +814,6 @@ int __init smc_findirq( int ioaddr )
/* and return what I found */
return autoirq_report( 0 );
}
-#endif
/*----------------------------------------------------------------------
. Function: smc_probe( int ioaddr )
@@ -962,14 +915,7 @@ static int __init smc_initcard(struct net_device *dev, int ioaddr)
/* see if I need to initialize the ethernet card structure */
if (dev == NULL) {
-#ifdef SUPPORT_OLD_KERNEL
-#ifndef MODULE
-/* note: the old module interface does not support this call */
- dev = init_etherdev( 0, sizeof( struct smc_local ), 0 );
-#endif
-#else
dev = init_etherdev(0, 0);
-#endif
if (dev == NULL)
return -ENOMEM;
}
@@ -1043,7 +989,6 @@ static int __init smc_initcard(struct net_device *dev, int ioaddr)
. what (s)he is doing. No checking is done!!!!
.
*/
-#ifndef NO_AUTOPROBE
if ( dev->irq < 2 ) {
int trials;
@@ -1060,13 +1005,6 @@ static int __init smc_initcard(struct net_device *dev, int ioaddr)
printk(CARDNAME": Couldn't autodetect your IRQ. Use irq=xx.\n");
return -ENODEV;
}
-#else
- if (dev->irq == 0 ) {
- printk(CARDNAME
- ": Autoprobing IRQs is not supported for old kernels.\n");
- return -ENODEV;
- }
-#endif
if (dev->irq == 2) {
/* Fixup for users that don't know that IRQ 2 is really IRQ 9,
* or don't know which one to set.
@@ -1114,10 +1052,10 @@ static int __init smc_initcard(struct net_device *dev, int ioaddr)
dev->open = smc_open;
dev->stop = smc_close;
dev->hard_start_xmit = smc_send_packet;
+ dev->tx_timeout = smc_timeout;
+ dev->watchdog_timeo = HZ/20;
dev->get_stats = smc_query_statistics;
-#ifdef HAVE_MULTICAST
- dev->set_multicast_list = &smc_set_multicast_list;
-#endif
+ dev->set_multicast_list = smc_set_multicast_list;
return 0;
}
@@ -1174,12 +1112,7 @@ static int smc_open(struct net_device *dev)
/* clear out all the junk that was put here before... */
memset(dev->priv, 0, sizeof(struct smc_local));
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
-#ifdef MODULE
MOD_INC_USE_COUNT;
-#endif
/* reset the hardware */
@@ -1211,6 +1144,8 @@ static int smc_open(struct net_device *dev)
address |= dev->dev_addr[ i ];
outw( address, ioaddr + ADDR0 + i );
}
+
+ netif_start_queue(dev);
return 0;
}
@@ -1220,38 +1155,29 @@ static int smc_open(struct net_device *dev)
. skeleton.c, from Becker.
.--------------------------------------------------------
*/
-static int smc_send_packet(struct sk_buff *skb, struct net_device *dev)
+
+static void smc_timeout(struct net_device *dev)
{
- if (dev->tbusy) {
- /* If we get here, some higher level has decided we are broken.
- There should really be a "kick me" function call instead. */
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 5)
- return 1;
- printk(KERN_WARNING CARDNAME": transmit timed out, %s?\n",
- tx_done(dev) ? "IRQ conflict" :
- "network cable problem");
- /* "kick" the adaptor */
- smc_reset( dev->base_addr );
- smc_enable( dev->base_addr );
-
- dev->tbusy = 0;
- dev->trans_start = jiffies;
- /* clear anything saved */
- ((struct smc_local *)dev->priv)->saved_skb = NULL;
- }
+ /* If we get here, some higher level has decided we are broken.
+ There should really be a "kick me" function call instead. */
+ printk(KERN_WARNING CARDNAME": transmit timed out, %s?\n",
+ tx_done(dev) ? "IRQ conflict" :
+ "network cable problem");
+ /* "kick" the adaptor */
+ smc_reset( dev->base_addr );
+ smc_enable( dev->base_addr );
+ dev->trans_start = jiffies;
+ /* clear anything saved */
+ ((struct smc_local *)dev->priv)->saved_skb = NULL;
+ netif_wake_queue(dev);
+}
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
- printk(KERN_WARNING CARDNAME": Transmitter access conflict.\n");
- dev_kfree_skb (skb);
- } else {
- /* Well, I want to send the packet.. but I don't know
- if I can send it right now... */
- return smc_wait_to_send_packet( skb, dev );
- }
- return 0;
+static int smc_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+ netif_stop_queue(dev);
+ /* Well, I want to send the packet.. but I don't know
+ if I can send it right now... */
+ return smc_wait_to_send_packet( skb, dev );
}
/*--------------------------------------------------------------------
@@ -1266,11 +1192,8 @@ static int smc_send_packet(struct sk_buff *skb, struct net_device *dev)
. and finally restore state.
.
---------------------------------------------------------------------*/
-#ifdef REALLY_NEW_KERNEL
+
static void smc_interrupt(int irq, void * dev_id, struct pt_regs * regs)
-#else
-static void smc_interrupt(int irq, struct pt_regs * regs)
-#endif
{
struct net_device *dev = dev_id;
int ioaddr = dev->base_addr;
@@ -1288,20 +1211,6 @@ static void smc_interrupt(int irq, struct pt_regs * regs)
PRINTK3((CARDNAME": SMC interrupt started \n"));
- if (dev == NULL) {
- printk(KERN_WARNING CARDNAME": irq %d for unknown device.\n",
- irq);
- return;
- }
-
-/* will Linux let this happen ?? If not, this costs some speed */
- if ( dev->interrupt ) {
- printk(KERN_WARNING CARDNAME": interrupt inside interrupt.\n");
- return;
- }
-
- dev->interrupt = 1;
-
saved_bank = inw( ioaddr + BANK_SELECT );
SMC_SELECT_BANK(2);
@@ -1346,12 +1255,7 @@ static void smc_interrupt(int irq, struct pt_regs * regs)
lp->stats.collisions += card_stats & 0xF;
/* these are for when linux supports these statistics */
-#if 0
- card_stats >>= 4;
- /* deferred */
- card_stats >>= 4;
- /* excess deferred */
-#endif
+
SMC_SELECT_BANK( 2 );
PRINTK2((KERN_WARNING CARDNAME
": TX_BUFFER_EMPTY handled\n"));
@@ -1372,8 +1276,8 @@ static void smc_interrupt(int irq, struct pt_regs * regs)
mask |= ( IM_TX_EMPTY_INT | IM_TX_INT );
/* and let the card send more packets to me */
- mark_bh( NET_BH );
-
+ netif_wake_queue(dev);
+
PRINTK2((CARDNAME": Handoff done successfully.\n"));
} else if (status & IM_RX_OVRN_INT ) {
lp->stats.rx_errors++;
@@ -1397,7 +1301,6 @@ static void smc_interrupt(int irq, struct pt_regs * regs)
SMC_SELECT_BANK( saved_bank );
- dev->interrupt = 0;
PRINTK3((CARDNAME ": Interrupt done\n"));
return;
}
@@ -1462,11 +1365,7 @@ static void smc_rcv(struct net_device *dev)
if ( status & RS_MULTICAST )
lp->stats.multicast++;
-#ifdef SUPPORT_OLD_KERNEL
- skb = alloc_skb( packet_length + 5, GFP_ATOMIC );
-#else
skb = dev_alloc_skb( packet_length + 5);
-#endif
if ( skb == NULL ) {
printk(KERN_NOTICE CARDNAME
@@ -1478,18 +1377,12 @@ static void smc_rcv(struct net_device *dev)
! This should work without alignment, but it could be
! in the worse case
*/
-#ifndef SUPPORT_OLD_KERNEL
- /* TODO: Should I use 32bit alignment here ? */
+
skb_reserve( skb, 2 ); /* 16 bit alignment */
-#endif
skb->dev = dev;
-#ifdef SUPPORT_OLD_KERNEL
- skb->len = packet_length;
- data = skb->data;
-#else
data = skb_put( skb, packet_length);
-#endif
+
#ifdef USE_32_BIT
/* QUESTION: Like in the TX routine, do I want
to send the DWORDs or the bytes first, or some
@@ -1516,9 +1409,7 @@ static void smc_rcv(struct net_device *dev)
print_packet( data, packet_length );
#endif
-#ifndef SUPPORT_OLD_KERNEL
skb->protocol = eth_type_trans(skb, dev );
-#endif
netif_rx(skb);
lp->stats.rx_packets++;
} else {
@@ -1616,17 +1507,12 @@ static void smc_tx( struct net_device * dev )
-----------------------------------------------------*/
static int smc_close(struct net_device *dev)
{
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
/* clear everything */
smc_shutdown( dev->base_addr );
/* Update the statistics here. */
-#ifdef MODULE
MOD_DEC_USE_COUNT;
-#endif
-
return 0;
}
@@ -1648,21 +1534,12 @@ static struct net_device_stats* smc_query_statistics(struct net_device *dev) {
. promiscuous mode ( for TCPDUMP and cousins ) or accept
. a select set of multicast packets
*/
-#ifdef SUPPORT_OLD_KERNEL
-static void smc_set_multicast_list( struct net_device * dev,
- int num_addrs, void * addrs )
-#else
static void smc_set_multicast_list(struct net_device *dev)
-#endif
{
short ioaddr = dev->base_addr;
SMC_SELECT_BANK(0);
-#ifdef SUPPORT_OLD_KERNEL
- if ( num_addrs < 0 )
-#else
if ( dev->flags & IFF_PROMISC )
-#endif
outw( inw(ioaddr + RCR ) | RCR_PROMISC, ioaddr + RCR );
/* BUG? I never disable promiscuous mode if multicasting was turned on.
@@ -1674,27 +1551,12 @@ static void smc_set_multicast_list(struct net_device *dev)
I don't need to zero the multicast table, because the flag is
checked before the table is
*/
-#ifdef SUPPORT_OLD_KERNEL
- else if ( num_addrs > 20 ) /* arbitrary constant */
-#else
else if (dev->flags & IFF_ALLMULTI)
-#endif
outw( inw(ioaddr + RCR ) | RCR_ALMUL, ioaddr + RCR );
/* We just get all multicast packets even if we only want them
. from one source. This will be changed at some future
. point. */
-#ifdef SUPPORT_OLD_KERNEL
- else if (num_addrs > 0 ) {
-/* the old kernel support will not have hardware multicast support. It would
- involve more kludges, and make the multicast setting code even worse.
- Instead, just use the ALMUL method. This is reasonable, considering that
- it is seldom used
-*/
- outw( inw( ioaddr + RCR ) & ~RCR_PROMISC, ioaddr + RCR );
- outw( inw( ioadddr + RCR ) | RCR_ALMUL, ioadddr + RCR );
- }
-#else
else if (dev->mc_count ) {
/* support hardware multicasting */
@@ -1705,7 +1567,6 @@ static void smc_set_multicast_list(struct net_device *dev)
last thing called. The bank is set to zero at the top */
smc_setmulticast( ioaddr, dev->mc_count, dev->mc_list );
}
-#endif
else {
outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL),
ioaddr + RCR );
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 30e9e5b3d..de0856020 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -813,7 +813,7 @@ static void init_ring(struct net_device *dev)
np->rx_info[i].skb = skb;
if (skb == NULL)
break;
- np->rx_info[i].mapping = pci_map_single(np->pdev, skb->tail, np->rx_buf_sz);
+ np->rx_info[i].mapping = pci_map_single(np->pdev, skb->tail, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
skb->dev = dev; /* Mark as being used by this device. */
/* Grrr, we cannot offset to correctly align the IP header. */
np->rx_ring[i].rxaddr = cpu_to_le32(np->rx_info[i].mapping | RxDescValid);
@@ -859,7 +859,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
np->tx_info[entry].skb = skb;
np->tx_info[entry].mapping =
- pci_map_single(np->pdev, skb->data, skb->len);
+ pci_map_single(np->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
np->tx_ring[entry].addr = cpu_to_le32(np->tx_info[entry].mapping);
/* Add |TxDescIntr to generate Tx-done interrupts. */
@@ -959,10 +959,10 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
skb = np->tx_info[entry].skb;
pci_unmap_single(np->pdev,
np->tx_info[entry].mapping,
- skb->len);
+ skb->len, PCI_DMA_TODEVICE);
/* Scavenge the descriptor. */
- kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
np->tx_info[entry].skb = NULL;
np->tx_info[entry].mapping = 0;
np->dirty_tx++;
@@ -1044,7 +1044,7 @@ static int netdev_rx(struct net_device *dev)
skb_reserve(skb, 2); /* 16 byte align the IP header */
pci_dma_sync_single(np->pdev,
np->rx_info[entry].mapping,
- pkt_len);
+ pkt_len, PCI_DMA_FROMDEVICE);
#if HAS_IP_COPYSUM /* Call copy + cksum if available. */
eth_copy_and_sum(skb, np->rx_info[entry].skb->tail, pkt_len, 0);
skb_put(skb, pkt_len);
@@ -1055,7 +1055,7 @@ static int netdev_rx(struct net_device *dev)
} else {
char *temp;
- pci_unmap_single(np->pdev, np->rx_info[entry].mapping, np->rx_buf_sz);
+ pci_unmap_single(np->pdev, np->rx_info[entry].mapping, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
skb = np->rx_info[entry].skb;
temp = skb_put(skb, pkt_len);
np->rx_info[entry].skb = NULL;
@@ -1099,7 +1099,7 @@ static int netdev_rx(struct net_device *dev)
if (skb == NULL)
break; /* Better luck next round. */
np->rx_info[entry].mapping =
- pci_map_single(np->pdev, skb->tail, np->rx_buf_sz);
+ pci_map_single(np->pdev, skb->tail, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
skb->dev = dev; /* Mark as being used by this device. */
np->rx_ring[entry].rxaddr =
cpu_to_le32(np->rx_info[entry].mapping | RxDescValid);
@@ -1324,8 +1324,8 @@ static int netdev_close(struct net_device *dev)
for (i = 0; i < RX_RING_SIZE; i++) {
np->rx_ring[i].rxaddr = cpu_to_le32(0xBADF00D0); /* An invalid address. */
if (np->rx_info[i].skb != NULL) {
- pci_unmap_single(np->pdev, np->rx_info[i].mapping, np->rx_buf_sz);
- kfree_skb(np->rx_info[i].skb);
+ pci_unmap_single(np->pdev, np->rx_info[i].mapping, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(np->rx_info[i].skb);
}
np->rx_info[i].skb = NULL;
np->rx_info[i].mapping = 0;
@@ -1335,8 +1335,8 @@ static int netdev_close(struct net_device *dev)
if (skb != NULL) {
pci_unmap_single(np->pdev,
np->tx_info[i].mapping,
- skb->len);
- kfree_skb(skb);
+ skb->len, PCI_DMA_TODEVICE);
+ dev_kfree_skb(skb);
}
np->tx_info[i].skb = NULL;
np->tx_info[i].mapping = 0;
diff --git a/drivers/net/strip.c b/drivers/net/strip.c
index 2f3eb9076..0d754ed31 100644
--- a/drivers/net/strip.c
+++ b/drivers/net/strip.c
@@ -1036,9 +1036,7 @@ static void strip_unlock(struct strip *strip_info)
*/
strip_info->idle_timer.expires = jiffies + 1*HZ;
add_timer(&strip_info->idle_timer);
- if (!test_and_clear_bit(0, (void *)&strip_info->dev.tbusy))
- printk(KERN_ERR "%s: trying to unlock already unlocked device!\n",
- strip_info->dev.name);
+ netif_wake_queue(&strip_info->dev);
}
@@ -1355,7 +1353,8 @@ static void strip_write_some_more(struct tty_struct *tty)
struct strip *strip_info = (struct strip *) tty->disc_data;
/* First make sure we're connected. */
- if (!strip_info || strip_info->magic != STRIP_MAGIC || !strip_info->dev.start)
+ if (!strip_info || strip_info->magic != STRIP_MAGIC ||
+ !netif_running(&strip_info->dev))
return;
if (strip_info->tx_left > 0)
@@ -1387,7 +1386,6 @@ static void strip_write_some_more(struct tty_struct *tty)
{
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
strip_unlock(strip_info);
- mark_bh(NET_BH);
}
}
@@ -1646,12 +1644,14 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct strip *strip_info = (struct strip *)(dev->priv);
- if (!dev->start)
+ if (!netif_running(dev))
{
printk(KERN_ERR "%s: xmit call when iface is down\n", dev->name);
return(1);
}
- if (test_and_set_bit(0, (void *) &strip_info->dev.tbusy)) return(1);
+
+ netif_stop_queue(dev);
+
del_timer(&strip_info->idle_timer);
/* See if someone has been ifconfigging */
@@ -1687,7 +1687,8 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev)
strip_send(strip_info, skb);
- if (skb) dev_kfree_skb(skb);
+ if (skb)
+ dev_kfree_skb(skb);
return(0);
}
@@ -2336,7 +2337,8 @@ strip_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int
struct strip *strip_info = (struct strip *) tty->disc_data;
const unsigned char *end = cp + count;
- if (!strip_info || strip_info->magic != STRIP_MAGIC || !strip_info->dev.start)
+ if (!strip_info || strip_info->magic != STRIP_MAGIC
+ || !netif_running(&strip_info->dev))
return;
/* Argh! mtu change time! - costs us the packet part received at the change */
@@ -2507,13 +2509,11 @@ static int strip_open_low(struct net_device *dev)
if (in_dev->ifa_list->ifa_address == 0)
in_dev->ifa_list->ifa_address = ntohl(0xC0A80001);
#endif
- dev->tbusy = 0;
- dev->start = 1;
-
printk(KERN_INFO "%s: Initializing Radio.\n", strip_info->dev.name);
ResetRadio(strip_info);
strip_info->idle_timer.expires = jiffies + 1*HZ;
add_timer(&strip_info->idle_timer);
+ netif_wake_queue(dev);
return(0);
}
@@ -2529,9 +2529,9 @@ static int strip_close_low(struct net_device *dev)
if (strip_info->tty == NULL)
return -EBUSY;
strip_info->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue(dev);
+
/*
* Free all STRIP frame buffers.
*/
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 11efd3d4d..6a773b66d 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -1,4 +1,4 @@
-/* $Id: sunbmac.c,v 1.14 2000/02/09 11:15:35 davem Exp $
+/* $Id: sunbmac.c,v 1.18 2000/02/18 13:49:21 davem Exp $
* sunbmac.c: Driver for Sparc BigMAC 100baseT ethernet adapters.
*
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
@@ -190,20 +190,14 @@ static void bigmac_clean_rings(struct bigmac *bp)
for (i = 0; i < RX_RING_SIZE; i++) {
if (bp->rx_skbs[i] != NULL) {
- if (in_irq())
- dev_kfree_skb_irq(bp->rx_skbs[i]);
- else
- dev_kfree_skb(bp->rx_skbs[i]);
+ dev_kfree_skb_any(bp->rx_skbs[i]);
bp->rx_skbs[i] = NULL;
}
}
for (i = 0; i < TX_RING_SIZE; i++) {
if (bp->tx_skbs[i] != NULL) {
- if (in_irq())
- dev_kfree_skb_irq(bp->tx_skbs[i]);
- else
- dev_kfree_skb(bp->tx_skbs[i]);
+ dev_kfree_skb_any(bp->tx_skbs[i]);
bp->tx_skbs[i] = NULL;
}
}
@@ -240,7 +234,8 @@ static void bigmac_init_rings(struct bigmac *bp, int from_irq)
bb->be_rxd[i].rx_addr =
sbus_map_single(bp->bigmac_sdev, skb->data,
- RX_BUF_ALLOC_SIZE - 34);
+ RX_BUF_ALLOC_SIZE - 34,
+ SBUS_DMA_FROMDEVICE);
bb->be_rxd[i].rx_flags =
(RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH));
}
@@ -776,7 +771,8 @@ static void bigmac_tx(struct bigmac *bp)
bp->enet_stats.tx_packets++;
bp->enet_stats.tx_bytes += skb->len;
sbus_unmap_single(bp->bigmac_sdev,
- this->tx_addr, skb->len);
+ this->tx_addr, skb->len,
+ SBUS_DMA_TODEVICE);
DTX(("skb(%p) ", skb));
bp->tx_skbs[elem] = NULL;
@@ -787,7 +783,7 @@ static void bigmac_tx(struct bigmac *bp)
DTX((" DONE, tx_old=%d\n", elem));
bp->tx_old = elem;
- if (test_bit(LINK_STATE_XOFF, &dev->state) &&
+ if (netif_queue_stopped(dev) &&
TX_BUFFS_AVAIL(bp) > 0)
netif_wake_queue(bp->dev);
@@ -831,14 +827,16 @@ static void bigmac_rx(struct bigmac *bp)
}
sbus_unmap_single(bp->bigmac_sdev,
this->rx_addr,
- RX_BUF_ALLOC_SIZE - 34);
+ RX_BUF_ALLOC_SIZE - 34,
+ SBUS_DMA_FROMDEVICE);
bp->rx_skbs[elem] = new_skb;
new_skb->dev = bp->dev;
skb_put(new_skb, ETH_FRAME_LEN);
skb_reserve(new_skb, 34);
this->rx_addr = sbus_map_single(bp->bigmac_sdev,
new_skb->data,
- RX_BUF_ALLOC_SIZE - 34);
+ RX_BUF_ALLOC_SIZE - 34,
+ SBUS_DMA_FROMDEVICE);
this->rx_flags =
(RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH));
@@ -855,7 +853,7 @@ static void bigmac_rx(struct bigmac *bp)
skb_reserve(copy_skb, 2);
skb_put(copy_skb, len);
sbus_dma_sync_single(bp->bigmac_sdev,
- this->rx_addr, len);
+ this->rx_addr, len, SBUS_DMA_FROMDEVICE);
eth_copy_and_sum(copy_skb, (unsigned char *)skb->data, len, 0);
/* Reuse original ring buffer. */
@@ -951,7 +949,7 @@ static int bigmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
u32 mapping;
len = skb->len;
- mapping = sbus_map_single(bp->bigmac_sdev, skb->data, len);
+ mapping = sbus_map_single(bp->bigmac_sdev, skb->data, len, SBUS_DMA_TODEVICE);
/* Avoid a race... */
spin_lock_irq(&bp->lock);
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 8766c1dc4..344e682f8 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -1,4 +1,4 @@
-/* $Id: sunhme.c,v 1.86 2000/02/09 11:15:36 davem Exp $
+/* $Id: sunhme.c,v 1.92 2000/02/18 13:49:22 davem Exp $
* sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching,
* auto carrier detecting ethernet driver. Also known as the
* "Happy Meal Ethernet" found on SunSwift SBUS cards.
@@ -152,6 +152,13 @@ static __inline__ void tx_dump_ring(struct happy_meal *hp)
#define DEFAULT_IPG2 4 /* For all modes */
#define DEFAULT_JAMSIZE 4 /* Toe jam */
+/* NOTE: In the descriptor writes one _must_ write the address
+ * member _first_. The card must not be allowed to see
+ * the updated descriptor flags until the address is
+ * correct. I've added a write memory barrier between
+ * the two stores so that I can sleep well at night... -DaveM
+ */
+
#if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
static void sbus_hme_write32(unsigned long reg, u32 val)
{
@@ -166,13 +173,15 @@ static u32 sbus_hme_read32(unsigned long reg)
static void sbus_hme_write_rxd(struct happy_meal_rxd *rxd, u32 flags, u32 addr)
{
rxd->rx_addr = addr;
+ wmb();
rxd->rx_flags = flags;
}
static void sbus_hme_write_txd(struct happy_meal_txd *txd, u32 flags, u32 addr)
{
- txd->tx_flags = flags;
txd->tx_addr = addr;
+ wmb();
+ txd->tx_flags = flags;
}
static u32 sbus_hme_read_desc32(u32 *p)
@@ -193,18 +202,20 @@ static u32 pci_hme_read32(unsigned long reg)
static void pci_hme_write_rxd(struct happy_meal_rxd *rxd, u32 flags, u32 addr)
{
rxd->rx_addr = cpu_to_le32(addr);
+ wmb();
rxd->rx_flags = cpu_to_le32(flags);
}
static void pci_hme_write_txd(struct happy_meal_txd *txd, u32 flags, u32 addr)
{
- txd->tx_flags = cpu_to_le32(flags);
txd->tx_addr = cpu_to_le32(addr);
+ wmb();
+ txd->tx_flags = cpu_to_le32(flags);
}
static u32 pci_hme_read_desc32(u32 *p)
{
- return cpu_to_le32(*p);
+ return cpu_to_le32p(p);
}
#define hme_write32(__hp, __reg, __val) \
@@ -217,12 +228,12 @@ static u32 pci_hme_read_desc32(u32 *p)
((__hp)->write_txd((__txd), (__flags), (__addr)))
#define hme_read_desc32(__hp, __p) \
((__hp)->read_desc32(__p))
-#define hme_dma_map(__hp, __ptr, __size) \
- ((__hp)->dma_map((__hp)->happy_dev, (__ptr), (__size)))
-#define hme_dma_unmap(__hp, __addr, __size) \
- ((__hp)->dma_unmap((__hp)->happy_dev, (__addr), (__size)))
-#define hme_dma_sync(__hp, __addr, __size) \
- ((__hp)->dma_sync((__hp)->happy_dev, (__addr), (__size)))
+#define hme_dma_map(__hp, __ptr, __size, __dir) \
+ ((__hp)->dma_map((__hp)->happy_dev, (__ptr), (__size), (__dir)))
+#define hme_dma_unmap(__hp, __addr, __size, __dir) \
+ ((__hp)->dma_unmap((__hp)->happy_dev, (__addr), (__size), (__dir)))
+#define hme_dma_sync(__hp, __addr, __size, __dir) \
+ ((__hp)->dma_sync((__hp)->happy_dev, (__addr), (__size), (__dir)))
#else
#ifdef CONFIG_SBUS
/* SBUS only compilation */
@@ -232,19 +243,21 @@ static u32 pci_hme_read_desc32(u32 *p)
sbus_readl(__reg)
#define hme_write_rxd(__hp, __rxd, __flags, __addr) \
do { (__rxd)->rx_addr = (__addr); \
+ wmb(); \
(__rxd)->rx_flags = (__flags); \
} while(0)
#define hme_write_txd(__hp, __txd, __flags, __addr) \
do { (__txd)->tx_addr = (__addr); \
+ wmb(); \
(__txd)->tx_flags = (__flags); \
} while(0)
#define hme_read_desc32(__hp, __p) (*(__p))
-#define hme_dma_map(__hp, __ptr, __size) \
- sbus_map_single((__hp)->happy_dev, (__ptr), (__size))
+#define hme_dma_map(__hp, __ptr, __size, __dir) \
+ sbus_map_single((__hp)->happy_dev, (__ptr), (__size), (__dir))
#define hme_dma_unmap(__hp, __addr, __size) \
- sbus_unmap_single((__hp)->happy_dev, (__addr), (__size))
-#define hme_dma_sync(__hp, __addr, __size) \
- sbus_dma_sync_single((__hp)->happy_dev, (__addr), (__size))
+ sbus_unmap_single((__hp)->happy_dev, (__addr), (__size), (__dir))
+#define hme_dma_sync(__hp, __addr, __size, __dir) \
+ sbus_dma_sync_single((__hp)->happy_dev, (__addr), (__size), (__dir))
#else
/* PCI only compilation */
#define hme_write32(__hp, __reg, __val) \
@@ -253,22 +266,28 @@ do { (__txd)->tx_addr = (__addr); \
readl(__reg)
#define hme_write_rxd(__hp, __rxd, __flags, __addr) \
do { (__rxd)->rx_addr = cpu_to_le32(__addr); \
+ wmb(); \
(__rxd)->rx_flags = cpu_to_le32(__flags); \
} while(0)
#define hme_write_txd(__hp, __txd, __flags, __addr) \
do { (__txd)->tx_addr = cpu_to_le32(__addr); \
+ wmb(); \
(__txd)->tx_flags = cpu_to_le32(__flags); \
} while(0)
-#define hme_read_desc32(__hp, __p) cpu_to_le32(*(__p))
-#define hme_dma_map(__hp, __ptr, __size) \
- pci_map_single((__hp)->happy_dev, (__ptr), (__size))
-#define hme_dma_unmap(__hp, __addr, __size) \
- pci_unmap_single((__hp)->happy_dev, (__addr), (__size))
-#define hme_dma_sync(__hp, __addr, __size) \
- pci_dma_sync_single((__hp)->happy_dev, (__addr), (__size))
+#define hme_read_desc32(__hp, __p) cpu_to_le32p(__p)
+#define hme_dma_map(__hp, __ptr, __size, __dir) \
+ pci_map_single((__hp)->happy_dev, (__ptr), (__size), (__dir))
+#define hme_dma_unmap(__hp, __addr, __size, __dir) \
+ pci_unmap_single((__hp)->happy_dev, (__addr), (__size), (__dir))
+#define hme_dma_sync(__hp, __addr, __size, __dir) \
+ pci_dma_sync_single((__hp)->happy_dev, (__addr), (__size), (__dir))
#endif
#endif
+#define DMA_BIDIRECTIONAL SBUS_DMA_BIDIRECTIONAL
+#define DMA_FROMDEVICE SBUS_DMA_FROMDEVICE
+#define DMA_TODEVICE SBUS_DMA_TODEVICE
+
/* Oh yes, the MIF BitBang is mighty fun to program. BitBucket is more like it. */
static void BB_PUT_BIT(struct happy_meal *hp, unsigned long tregs, int bit)
{
@@ -1193,11 +1212,8 @@ static void happy_meal_clean_rings(struct happy_meal *hp)
rxd = &hp->happy_block->happy_meal_rxd[i];
dma_addr = hme_read_desc32(hp, &rxd->rx_addr);
- hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE);
- if (in_irq())
- dev_kfree_skb_irq(skb);
- else
- dev_kfree_skb(skb);
+ hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE);
+ dev_kfree_skb_any(skb);
hp->rx_skbs[i] = NULL;
}
}
@@ -1210,11 +1226,8 @@ static void happy_meal_clean_rings(struct happy_meal *hp)
txd = &hp->happy_block->happy_meal_txd[i];
dma_addr = hme_read_desc32(hp, &txd->tx_addr);
- hme_dma_unmap(hp, dma_addr, skb->len);
- if (in_irq())
- dev_kfree_skb_irq(skb);
- else
- dev_kfree_skb(skb);
+ hme_dma_unmap(hp, dma_addr, skb->len, DMA_TODEVICE);
+ dev_kfree_skb_any(skb);
hp->tx_skbs[i] = NULL;
}
}
@@ -1253,7 +1266,7 @@ static void happy_meal_init_rings(struct happy_meal *hp, int from_irq)
skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET));
hme_write_rxd(hp, &hb->happy_meal_rxd[i],
(RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)),
- hme_dma_map(hp, skb->data, RX_BUF_ALLOC_SIZE));
+ hme_dma_map(hp, skb->data, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE));
skb_reserve(skb, RX_OFFSET);
}
@@ -1895,7 +1908,7 @@ static void happy_meal_tx(struct happy_meal *hp)
break;
dma_addr = hme_read_desc32(hp, &this->tx_addr);
skb = hp->tx_skbs[elem];
- hme_dma_unmap(hp, dma_addr, skb->len);
+ hme_dma_unmap(hp, dma_addr, skb->len, DMA_TODEVICE);
hp->tx_skbs[elem] = NULL;
hp->net_stats.tx_bytes += skb->len;
@@ -1907,7 +1920,7 @@ static void happy_meal_tx(struct happy_meal *hp)
hp->tx_old = elem;
TXD((">"));
- if (test_bit(LINK_STATE_XOFF, &dev->state) &&
+ if (netif_queue_stopped(dev) &&
TX_BUFFS_AVAIL(hp) > 0)
netif_wake_queue(dev);
@@ -1973,13 +1986,13 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev)
drops++;
goto drop_it;
}
- hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE);
+ hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE);
hp->rx_skbs[elem] = new_skb;
new_skb->dev = dev;
skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET));
hme_write_rxd(hp, this,
(RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
- hme_dma_map(hp, new_skb->data, RX_BUF_ALLOC_SIZE));
+ hme_dma_map(hp, new_skb->data, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE));
skb_reserve(new_skb, RX_OFFSET);
/* Trim the original skb for the netif. */
@@ -1995,7 +2008,7 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev)
copy_skb->dev = dev;
skb_reserve(copy_skb, 2);
skb_put(copy_skb, len);
- hme_dma_sync(hp, dma_addr, len);
+ hme_dma_sync(hp, dma_addr, len, DMA_FROMDEVICE);
memcpy(copy_skb->data, skb->data, len);
/* Reuse original ring buffer. */
@@ -2178,7 +2191,7 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
u32 mapping;
len = skb->len;
- mapping = hme_dma_map(hp, skb->data, len);
+ mapping = hme_dma_map(hp, skb->data, len, DMA_TODEVICE);
spin_lock_irq(&hp->happy_lock);
@@ -2192,10 +2205,11 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (TX_BUFFS_AVAIL(hp) <= 0)
netif_stop_queue(dev);
- spin_unlock_irq(&hp->happy_lock);
-
/* Get it going. */
hme_write32(hp, hp->etxregs + ETX_PENDING, ETX_TP_DMAWAKEUP);
+
+ spin_unlock_irq(&hp->happy_lock);
+
dev->trans_start = jiffies;
tx_add_log(hp, TXLOG_ACTION_TXMIT, 0);
@@ -2642,9 +2656,9 @@ static int __init happy_meal_sbus_init(struct net_device *dev,
hp->read_desc32 = sbus_hme_read_desc32;
hp->write_txd = sbus_hme_write_txd;
hp->write_rxd = sbus_hme_write_rxd;
- hp->dma_map = (u32 (*)(void *, void *, long))sbus_map_single;
- hp->dma_unmap = (void (*)(void *, u32, long))sbus_unmap_single;
- hp->dma_sync = (void (*)(void *, u32, long))sbus_dma_sync_single;
+ hp->dma_map = (u32 (*)(void *, void *, long, int))sbus_map_single;
+ hp->dma_unmap = (void (*)(void *, u32, long, int))sbus_unmap_single;
+ hp->dma_sync = (void (*)(void *, u32, long, int))sbus_dma_sync_single;
hp->read32 = sbus_hme_read32;
hp->write32 = sbus_hme_write32;
#endif
@@ -2817,9 +2831,9 @@ static int __init happy_meal_pci_init(struct net_device *dev, struct pci_dev *pd
hp->read_desc32 = pci_hme_read_desc32;
hp->write_txd = pci_hme_write_txd;
hp->write_rxd = pci_hme_write_rxd;
- hp->dma_map = (u32 (*)(void *, void *, long))pci_map_single;
- hp->dma_unmap = (void (*)(void *, u32, long))pci_unmap_single;
- hp->dma_sync = (void (*)(void *, u32, long))pci_dma_sync_single;
+ hp->dma_map = (u32 (*)(void *, void *, long, int))pci_map_single;
+ hp->dma_unmap = (void (*)(void *, u32, long, int))pci_unmap_single;
+ hp->dma_sync = (void (*)(void *, u32, long, int))pci_dma_sync_single;
hp->read32 = pci_hme_read32;
hp->write32 = pci_hme_write32;
#endif
diff --git a/drivers/net/sunhme.h b/drivers/net/sunhme.h
index 3708515e3..57b5d7f5e 100644
--- a/drivers/net/sunhme.h
+++ b/drivers/net/sunhme.h
@@ -1,4 +1,4 @@
-/* $Id: sunhme.h,v 1.29 2000/02/09 11:15:40 davem Exp $
+/* $Id: sunhme.h,v 1.30 2000/02/18 13:49:26 davem Exp $
* sunhme.h: Definitions for Sparc HME/BigMac 10/100baseT ethernet driver.
* Also known as the "Happy Meal".
*
@@ -502,9 +502,9 @@ struct happy_meal {
u32 (*read_desc32)(u32 *);
void (*write_txd)(struct happy_meal_txd *, u32, u32);
void (*write_rxd)(struct happy_meal_rxd *, u32, u32);
- u32 (*dma_map)(void *, void *, long);
- void (*dma_unmap)(void *, u32, long);
- void (*dma_sync)(void *, u32, long);
+ u32 (*dma_map)(void *, void *, long, int);
+ void (*dma_unmap)(void *, u32, long, int);
+ void (*dma_sync)(void *, u32, long, int);
#endif
/* This is either a sbus_dev or a pci_dev. */
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index c7630dba3..e17304fd0 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -1,4 +1,4 @@
-/* $Id: sunlance.c,v 1.94 2000/02/09 11:15:40 davem Exp $
+/* $Id: sunlance.c,v 1.99 2000/02/16 10:36:14 davem Exp $
* lance.c: Linux/Sparc/Lance driver
*
* Written 1995, 1996 by Miguel de Icaza
@@ -602,7 +602,7 @@ static void lance_tx_dvma(struct net_device *dev)
lp->init_ring(dev);
load_csrs(lp);
init_restart_lance(lp);
- return;
+ goto out;
}
}
@@ -618,7 +618,7 @@ static void lance_tx_dvma(struct net_device *dev)
lp->init_ring(dev);
load_csrs(lp);
init_restart_lance(lp);
- return;
+ goto out;
}
} else if ((bits & LE_T1_POK) == LE_T1_POK) {
/*
@@ -640,8 +640,8 @@ static void lance_tx_dvma(struct net_device *dev)
j = TX_NEXT(j);
}
lp->tx_old = j;
-
- if (test_bit(LINK_STATE_XOFF, &dev->state) &&
+out:
+ if (netif_queue_stopped(dev) &&
TX_BUFFS_AVAIL > 0)
netif_wake_queue(dev);
@@ -773,7 +773,7 @@ static void lance_tx_pio(struct net_device *dev)
lp->init_ring(dev);
load_csrs(lp);
init_restart_lance(lp);
- return;
+ goto out;
}
}
@@ -789,7 +789,7 @@ static void lance_tx_pio(struct net_device *dev)
lp->init_ring(dev);
load_csrs(lp);
init_restart_lance(lp);
- return;
+ goto out;
}
} else if ((bits & LE_T1_POK) == LE_T1_POK) {
/*
@@ -812,10 +812,10 @@ static void lance_tx_pio(struct net_device *dev)
}
lp->tx_old = j;
- if (test_bit(LINK_STATE_XOFF, &dev->state) &&
+ if (netif_queue_stopped(dev) &&
TX_BUFFS_AVAIL > 0)
netif_wake_queue(dev);
-
+out:
spin_unlock(&lp->lock);
}
@@ -1014,7 +1014,7 @@ static int lance_reset(struct net_device *dev)
return status;
}
-static void lance_piocopy_from_skb(volatile void *dest, char *src, int len)
+static void lance_piocopy_from_skb(volatile void *dest, unsigned char *src, int len)
{
unsigned long piobuf = (unsigned long) dest;
u32 *p32;
@@ -1128,10 +1128,10 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
- lp->stats.tx_bytes += len;
-
spin_lock_irq(&lp->lock);
+ lp->stats.tx_bytes += len;
+
entry = lp->tx_new & TX_RING_MOD_MASK;
if (lp->pio_buffer) {
sbus_writew((-len) | 0xf000, &ib->btx_ring[entry].length);
@@ -1154,19 +1154,20 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (TX_BUFFS_AVAIL <= 0)
netif_stop_queue(dev);
- spin_unlock_irq(&lp->lock);
-
/* Kick the lance: transmit now */
sbus_writew(LE_C0_INEA | LE_C0_TDMD, lp->lregs + RDP);
- dev->trans_start = jiffies;
- dev_kfree_skb(skb);
-
+
/* Read back CSR to invalidate the E-Cache.
* This is needed, because DMA_DSBL_WR_INV is set.
*/
if (lp->dregs)
sbus_readw(lp->lregs + RDP);
+ spin_unlock_irq(&lp->lock);
+
+ dev->trans_start = jiffies;
+ dev_kfree_skb(skb);
+
return 0;
}
@@ -1246,7 +1247,7 @@ static void lance_set_multicast(struct net_device *dev)
volatile struct lance_init_block *ib = lp->init_block;
u16 mode;
- if (!test_bit(LINK_STATE_START, &dev->state))
+ if (!netif_running(dev))
return;
if (lp->tx_old != lp->tx_new) {
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index ed538b5a7..62fac115f 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -1,4 +1,4 @@
-/* $Id: sunqe.c,v 1.43 2000/02/09 21:11:19 davem Exp $
+/* $Id: sunqe.c,v 1.45 2000/02/16 10:36:20 davem Exp $
* sunqe.c: Sparc QuadEthernet 10baseT SBUS card driver.
* Once again I am out to prove that every ethernet
* controller out there can be most efficiently programmed
@@ -481,7 +481,7 @@ static void qec_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
if (qe_status & CREG_STAT_RXIRQ)
qe_rx(qep);
- if (test_bit(LINK_STATE_XOFF, &qep->dev->state) &&
+ if (netif_queue_stopped(qep->dev) &&
(qe_status & CREG_STAT_TXIRQ)) {
spin_lock(&qep->lock);
qe_tx_reclaim(qep);
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index 9b21a13ea..a699391da 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -62,6 +62,10 @@
* driver (almost)
* - Other minor stuff
*
+ * v1.4 Feb 10, 2000 - Updated with more changes required after Dave's
+ * network cleanup in 2.3.43pre7 (Tigran & myself)
+ * - Minor stuff.
+ *
*******************************************************************************/
@@ -102,7 +106,7 @@ static int bbuf = 0;
static u8 *TLanPadBuffer;
static char TLanSignature[] = "TLAN";
static int TLanVersionMajor = 1;
-static int TLanVersionMinor = 3;
+static int TLanVersionMinor = 4;
static TLanAdapterEntry TLanAdapterList[] __initdata = {
@@ -361,7 +365,7 @@ static int __init tlan_probe(void)
u32 io_base, index;
int found;
- printk(KERN_INFO "ThunderLAN driver v%d.%d:\n",
+ printk(KERN_INFO "ThunderLAN driver v%d.%d\n",
TLanVersionMajor,
TLanVersionMinor);
@@ -461,7 +465,7 @@ module_exit(tlan_exit);
*
**************************************************************/
-int TLan_PciProbe(u8 *pci_dfn, u8 *pci_irq, u8 *pci_rev, u32 *pci_io_base, u32 *dl_ix )
+static int __init TLan_PciProbe(u8 *pci_dfn, u8 *pci_irq, u8 *pci_rev, u32 *pci_io_base, u32 *dl_ix )
{
static int dl_index = 0;
static struct pci_dev * pdev = NULL;
@@ -626,7 +630,7 @@ static int TLan_Init( struct net_device *dev )
*
**************************************************************/
-int TLan_Open( struct net_device *dev )
+static int TLan_Open( struct net_device *dev )
{
TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
int err;
@@ -642,7 +646,7 @@ int TLan_Open( struct net_device *dev )
}
netif_start_queue(dev);
-
+
/* NOTE: It might not be necessary to read the stats before a
reset if you don't care what the values are.
*/
@@ -680,7 +684,7 @@ int TLan_Open( struct net_device *dev )
*
**************************************************************/
-int TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
+static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
{
TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
TLanList *tail_list;
@@ -690,7 +694,7 @@ int TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
if ( ! priv->phyOnline ) {
TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: %s PHY is not ready\n", dev->name );
- dev_kfree_skb( skb );
+ dev_kfree_skb_any(skb);
return 0;
}
@@ -747,9 +751,8 @@ int TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
CIRC_INC( priv->txTail, TLAN_NUM_TX_LISTS );
- if ( bbuf ) {
- dev_kfree_skb( skb );
- }
+ if ( bbuf )
+ dev_kfree_skb_any(skb);
dev->trans_start = jiffies;
return 0;
@@ -780,7 +783,7 @@ int TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
*
**************************************************************/
-void TLan_HandleInterrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void TLan_HandleInterrupt(int irq, void *dev_id, struct pt_regs *regs)
{
u32 ack;
struct net_device *dev;
@@ -828,7 +831,7 @@ void TLan_HandleInterrupt(int irq, void *dev_id, struct pt_regs *regs)
*
**************************************************************/
-int TLan_Close(struct net_device *dev)
+static int TLan_Close(struct net_device *dev)
{
TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
@@ -866,7 +869,7 @@ int TLan_Close(struct net_device *dev)
*
**************************************************************/
-struct net_device_stats *TLan_GetStats( struct net_device *dev )
+static struct net_device_stats *TLan_GetStats( struct net_device *dev )
{
TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
int i;
@@ -914,7 +917,7 @@ struct net_device_stats *TLan_GetStats( struct net_device *dev )
*
**************************************************************/
-void TLan_SetMulticastList( struct net_device *dev )
+static void TLan_SetMulticastList( struct net_device *dev )
{
struct dev_mc_list *dmi = dev->mc_list;
u32 hash1 = 0;
@@ -1033,7 +1036,7 @@ u32 TLan_HandleTxEOF( struct net_device *dev, u16 host_int )
head_list = priv->txList + priv->txHead;
if ( ! bbuf ) {
- dev_kfree_skb( (struct sk_buff *) head_list->buffer[9].address );
+ dev_kfree_skb_irq( (struct sk_buff *) head_list->buffer[9].address );
head_list->buffer[9].address = 0;
}
@@ -1046,7 +1049,9 @@ u32 TLan_HandleTxEOF( struct net_device *dev, u16 host_int )
priv->stats.tx_bytes += head_list->frameSize;
head_list->cStat = TLAN_CSTAT_UNUSED;
+
netif_start_queue(dev);
+
CIRC_INC( priv->txHead, TLAN_NUM_TX_LISTS );
if ( eoc ) {
TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: Handling TX EOC (Head=%d Tail=%d)\n", priv->txHead, priv->txTail );
@@ -1614,7 +1619,7 @@ void TLan_FreeLists( struct net_device *dev )
list = priv->txList + i;
skb = (struct sk_buff *) list->buffer[9].address;
if ( skb ) {
- dev_kfree_skb( skb );
+ dev_kfree_skb_any( skb );
list->buffer[9].address = 0;
}
}
@@ -1623,7 +1628,7 @@ void TLan_FreeLists( struct net_device *dev )
list = priv->rxList + i;
skb = (struct sk_buff *) list->buffer[9].address;
if ( skb ) {
- dev_kfree_skb( skb );
+ dev_kfree_skb_any( skb );
list->buffer[9].address = 0;
}
}
@@ -2413,6 +2418,7 @@ int TLan_MiiReadReg( struct net_device *dev, u16 phy, u16 reg, u16 *val )
*val = tmp;
spin_unlock_irqrestore(&priv->lock, flags);
+
return err;
} /* TLan_MiiReadReg */
@@ -2552,6 +2558,7 @@ void TLan_MiiWriteReg( struct net_device *dev, u16 phy, u16 reg, u16 val )
TLan_SetBit( TLAN_NET_SIO_MINTEN, sio );
spin_unlock_irqrestore(&priv->lock, flags);
+
} /* TLan_MiiWriteReg */
@@ -2775,9 +2782,9 @@ int TLan_EeReadByte( struct net_device *dev, u8 ee_addr, u8 *data )
goto fail;
}
TLan_EeReceiveByte( dev->base_addr, data, TLAN_EEPROM_STOP );
-
fail:
spin_unlock_irqrestore(&priv->lock, flags);
+
return ret;
} /* TLan_EeReadByte */
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index 26956af06..b81815e25 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -833,11 +833,8 @@ static int tok_open(struct net_device *dev)
if (ti->open_status==IN_PROGRESS) sleep_on(&ti->wait_for_reset);
if (ti->open_status==SUCCESS) {
- dev->tbusy=0;
- dev->interrupt=0;
- dev->start=1;
/* NEED to see smem size *AND* reset high 512 bytes if needed */
-
+ netif_start_queue(dev);
MOD_INC_USE_COUNT;
return 0;
@@ -850,6 +847,8 @@ static int tok_close(struct net_device *dev)
struct tok_info *ti=(struct tok_info *) dev->priv;
+ netif_stop_queue(dev);
+
isa_writeb(DIR_CLOSE_ADAPTER,
ti->srb + offsetof(struct srb_close_adapter, command));
isa_writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
@@ -862,7 +861,6 @@ static int tok_close(struct net_device *dev)
DPRINTK("close adapter failed: %02X\n",
(int)isa_readb(ti->srb + offsetof(struct srb_close_adapter, ret_code)));
- dev->start = 0;
#ifdef PCMCIA
ti->sram = 0 ;
#endif
@@ -886,7 +884,6 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs)
spin_lock(&(ti->lock));
/* Disable interrupts till processing is finished */
- dev->interrupt=1;
isa_writeb((~INT_ENABLE), ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN);
/* Reset interrupt for ISA boards */
@@ -911,7 +908,6 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs)
{
DPRINTK("PCMCIA card removed.\n");
spin_unlock(&(ti->lock));
- dev->interrupt = 0;
return;
}
@@ -920,7 +916,6 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs)
{
DPRINTK("PCMCIA card removed.\n");
spin_unlock(&(ti->lock));
- dev->interrupt = 0;
return;
}
#endif
@@ -941,7 +936,6 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs)
isa_writeb((~ADAP_CHK_INT), ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD);
isa_writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN);
- dev->interrupt=0;
} else if (isa_readb(ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN)
& (TCR_INT | ERR_INT | ACCESS_INT)) {
@@ -951,7 +945,6 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs)
isa_writeb(~(TCR_INT | ERR_INT | ACCESS_INT),
ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN);
isa_writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN);
- dev->interrupt=0;
} else if (status
& (SRB_RESP_INT | ASB_FREE_INT | ARB_CMD_INT | SSB_RESP_INT)) {
@@ -972,7 +965,7 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs)
dev_kfree_skb(ti->current_skb);
ti->current_skb=NULL;
}
- dev->tbusy=0;
+ netif_wake_queue(dev);
if (ti->readlog_pending) ibmtr_readlog(dev);
}
}
@@ -989,8 +982,9 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs)
dev_kfree_skb(ti->current_skb);
ti->current_skb=NULL;
}
- dev->tbusy=0;
- if (ti->readlog_pending) ibmtr_readlog(dev);
+ netif_wake_queue(dev);
+ if (ti->readlog_pending)
+ ibmtr_readlog(dev);
}
}
break;
@@ -1115,7 +1109,7 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs)
(int)isa_readb(ti->srb+offsetof(struct srb_read_log,
token_errors)));
}
- dev->tbusy=0;
+ netif_wake_queue(dev);
break;
default:
@@ -1183,7 +1177,7 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs)
DPRINTK("New ring status: %02X\n", ring_status);
if (ring_status & LOG_OVERFLOW) {
- if (dev->tbusy)
+ if (netif_queue_stopped(dev))
ti->readlog_pending = 1;
else
ibmtr_readlog(dev);
@@ -1235,7 +1229,6 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs)
} /* SRB, ARB, ASB or SSB response */
- dev->interrupt=0;
isa_writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN);
break;
@@ -1330,7 +1323,7 @@ static int tok_init_card(struct net_device *dev)
ti->do_tok_int=FIRST_INT;
/* Reset adapter */
- dev->tbusy=1; /* nothing can be done before reset and open completed */
+ netif_stop_queue(dev);
#ifdef ENABLE_PAGING
if(ti->page_mask)
@@ -1498,10 +1491,9 @@ static void tr_tx(struct net_device *dev)
isa_writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
ti->tr_stats.tx_bytes+=ti->current_skb->len;
- dev->tbusy=0;
dev_kfree_skb(ti->current_skb);
ti->current_skb=NULL;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
if (ti->readlog_pending) ibmtr_readlog(dev);
}
@@ -1661,38 +1653,22 @@ static void tr_rx(struct net_device *dev)
static int tok_send_packet(struct sk_buff *skb, struct net_device *dev)
{
struct tok_info *ti;
+ unsigned long flags;
ti=(struct tok_info *) dev->priv;
- if (dev->tbusy) {
- int ticks_waited;
-
- ticks_waited=jiffies - dev->trans_start;
- if (ticks_waited<TR_BUSY_INTERVAL) return 1;
-
- DPRINTK("Arrg. Transmitter busy.\n");
- dev->trans_start+=5; /* we fake the transmission start time... */
- return 1;
- }
-
- if (test_and_set_bit(0,(void *)&dev->tbusy)!=0)
- DPRINTK("Transmitter access conflict\n");
- else {
- int flags;
-
- /* lock against other CPUs */
- spin_lock_irqsave(&(ti->lock), flags);
-
- /* Save skb; we'll need it when the adapter asks for the data */
- ti->current_skb=skb;
- isa_writeb(XMIT_UI_FRAME, ti->srb + offsetof(struct srb_xmit, command));
- isa_writew(ti->exsap_station_id, ti->srb
- +offsetof(struct srb_xmit, station_id));
- isa_writeb(CMD_IN_SRB, (ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD));
- spin_unlock_irqrestore(&(ti->lock), flags);
-
- dev->trans_start=jiffies;
- }
-
+ netif_stop_queue(dev);
+
+ /* lock against other CPUs */
+ spin_lock_irqsave(&(ti->lock), flags);
+
+ /* Save skb; we'll need it when the adapter asks for the data */
+ ti->current_skb=skb;
+ isa_writeb(XMIT_UI_FRAME, ti->srb + offsetof(struct srb_xmit, command));
+ isa_writew(ti->exsap_station_id, ti->srb
+ +offsetof(struct srb_xmit, station_id));
+ isa_writeb(CMD_IN_SRB, (ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD));
+ spin_unlock_irqrestore(&(ti->lock), flags);
+ dev->trans_start=jiffies;
return 0;
}
@@ -1712,7 +1688,8 @@ void ibmtr_readlog(struct net_device *dev) {
isa_writeb(DIR_READ_LOG, ti->srb);
isa_writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN);
isa_writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
- dev->tbusy=1; /* really srb busy... */
+
+ netif_stop_queue(dev);
}
/* tok_get_stats(): Basically a scaffold routine which will return
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
index fcb3ccd76..5f80fc5eb 100644
--- a/drivers/net/tokenring/olympic.c
+++ b/drivers/net/tokenring/olympic.c
@@ -615,10 +615,7 @@ static int olympic_open(struct net_device *dev)
#endif
- dev->start = 1;
- dev->interrupt=0;
- dev->tbusy=0;
-
+ netif_start_queue(dev);
MOD_INC_USE_COUNT ;
return 0;
@@ -762,11 +759,6 @@ static void olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs)
spin_lock(&olympic_priv->olympic_lock);
- if (dev->interrupt)
- printk(KERN_WARNING "%s: Re-entering interrupt \n",dev->name) ;
-
- dev->interrupt = 1 ;
-
if (sisr & (SISR_SRB_REPLY | SISR_TX1_EOF | SISR_RX_STATUS | SISR_ADAPTER_CHECK |
SISR_ASB_FREE | SISR_ARB_CMD | SISR_TRB_REPLY | SISR_RX_NOBUF)) {
@@ -788,11 +780,7 @@ static void olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs)
dev_kfree_skb(olympic_priv->tx_ring_skb[olympic_priv->tx_ring_last_status]);
olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_last_status].buffer=0xdeadbeef;
olympic_priv->olympic_tx_status_ring[olympic_priv->tx_ring_last_status].status=0;
-
- if(dev->tbusy) {
- dev->tbusy=0;
- mark_bh(NET_BH);
- }
+ netif_wake_queue(dev);
} /* SISR_TX1_EOF */
if (sisr & SISR_RX_STATUS) {
@@ -804,7 +792,6 @@ static void olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs)
writel(readl(olympic_mmio+LAPWWO),olympic_mmio+LAPA);
adapter_check_area = (__u8 *)(olympic_mmio+LAPWWO) ;
printk(KERN_WARNING "%s: Bytes %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, readb(adapter_check_area+0), readb(adapter_check_area+1), readb(adapter_check_area+2), readb(adapter_check_area+3), readb(adapter_check_area+4), readb(adapter_check_area+5), readb(adapter_check_area+6), readb(adapter_check_area+7)) ;
- dev->interrupt = 0 ;
free_irq(dev->irq, dev) ;
} /* SISR_ADAPTER_CHECK */
@@ -837,8 +824,6 @@ static void olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs)
printk(KERN_WARNING "%s: SISR_MASK: %x\n",dev->name, readl(olympic_mmio+SISR_MASK)) ;
} /* One if the interrupts we want */
- dev->interrupt = 0 ;
-
writel(SISR_MI,olympic_mmio+SISR_MASK_SUM);
spin_unlock(&olympic_priv->olympic_lock) ;
@@ -852,11 +837,8 @@ static int olympic_xmit(struct sk_buff *skb, struct net_device *dev)
spin_lock_irqsave(&olympic_priv->olympic_lock, flags);
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
- spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
- return 1;
- }
-
+ netif_stop_queue(dev);
+
if(olympic_priv->free_tx_ring_entries) {
olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].buffer=virt_to_bus(skb->data);
olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].status_length=skb->len | (0x80000000);
@@ -869,7 +851,7 @@ static int olympic_xmit(struct sk_buff *skb, struct net_device *dev)
writew((((readw(olympic_mmio+TXENQ_1)) & 0x8000) ^ 0x8000) | 1,olympic_mmio+TXENQ_1);
- dev->tbusy=0;
+ netif_wake_queue(dev);
spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
return 0;
} else {
@@ -887,6 +869,8 @@ static int olympic_close(struct net_device *dev)
unsigned long flags;
int i;
+ netif_stop_queue(dev);
+
writel(olympic_priv->srb,olympic_mmio+LAPA);
srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800));
@@ -936,7 +920,6 @@ static int olympic_close(struct net_device *dev)
printk("%x ",readb(srb+i));
printk("\n");
#endif
- dev->start = 0;
free_irq(dev->irq,dev);
MOD_DEC_USE_COUNT ;
@@ -1169,7 +1152,7 @@ static int olympic_set_mac_address (struct net_device *dev, void *addr)
struct sockaddr *saddr = addr ;
struct olympic_private *olympic_priv = (struct olympic_private *)dev->priv ;
- if (dev->start) {
+ if (netif_running(dev)) {
printk(KERN_WARNING "%s: Cannot set mac/laa address while card is open\n", dev->name) ;
return -EIO ;
}
@@ -1304,9 +1287,7 @@ static void olympic_arb_cmd(struct net_device *dev)
writel(readl(olympic_mmio+BCTL)|(3<<13),olympic_mmio+BCTL);
udelay(1);
writel(readl(olympic_mmio+BCTL)&~(3<<13),olympic_mmio+BCTL);
- dev->tbusy = 1 ;
- dev->interrupt = 1 ;
- dev->start = 0 ;
+ netif_stop_queue(dev);
olympic_priv->srb = readw(olympic_priv->olympic_lap + LAPWWO) ;
free_irq(dev->irq,dev);
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
index 5e4093b14..739c3cf2f 100644
--- a/drivers/net/tokenring/smctr.c
+++ b/drivers/net/tokenring/smctr.c
@@ -131,7 +131,6 @@ static int smctr_get_upstream_neighbor_addr(struct net_device *dev);
/* H */
static int smctr_hardware_send_packet(struct net_device *dev,
struct net_local *tp);
-
/* I */
static int smctr_init_acbs(struct net_device *dev);
static int smctr_init_adapter(struct net_device *dev);
@@ -282,6 +281,7 @@ static char *smctr_malloc(struct net_device *dev, __u16 size);
static int smctr_status_chg(struct net_device *dev);
/* T */
+static void smctr_timeout(struct net_device *dev);
static int smctr_trc_send_packet(struct net_device *dev, FCBlock *fcb,
__u16 queue);
static __u16 smctr_tx_complete(struct net_device *dev, __u16 queue);
@@ -730,9 +730,8 @@ static int smctr_close(struct net_device *dev)
struct sk_buff *skb;
int err;
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
+
#ifdef MODULE
MOD_DEC_USE_COUNT;
#endif
@@ -2030,13 +2029,9 @@ static void smctr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
return;
}
- dev->interrupt = 1;
-
ioaddr = dev->base_addr;
tp = (struct net_local *)dev->priv;
- dev->interrupt = 0;
-
if(tp->status == NOT_INITIALIZED)
return;
@@ -3749,6 +3744,8 @@ static int __init smctr_probe1(struct net_device *dev, int ioaddr)
dev->open = smctr_open;
dev->stop = smctr_close;
dev->hard_start_xmit = smctr_send_packet;
+ dev->tx_timeout = smctr_timeout;
+ dev->watchdog_timeo = HZ;
dev->get_stats = smctr_get_stats;
dev->set_multicast_list = &smctr_set_multicast_list;
@@ -4723,6 +4720,20 @@ static int smctr_send_dat(struct net_device *dev)
return (0);
}
+static void smctr_timeout(struct net_device *dev)
+{
+ /*
+ * If we get here, some higher level has decided we are broken.
+ * There should really be a "kick me" function call instead.
+ *
+ * Resetting the token ring adapter takes a long time so just
+ * fake transmission time and go on trying. Our own timeout
+ * routine is in sktr_timer_chk()
+ */
+ dev->trans_start = jiffies;
+ netif_wake_queue(dev);
+}
+
/*
* Gets skb from system, queues it and checks if it can be sent
*/
@@ -4733,37 +4744,11 @@ static int smctr_send_packet(struct sk_buff *skb, struct net_device *dev)
if(smctr_debug > 10)
printk("%s: smctr_send_packet\n", dev->name);
- if(dev->tbusy)
- {
- /*
- * If we get here, some higher level has decided we are broken.
- * There should really be a "kick me" function call instead.
- *
- * Resetting the token ring adapter takes a long time so just
- * fake transmission time and go on trying. Our own timeout
- * routine is in sktr_timer_chk()
- */
- dev->tbusy = 0;
- dev->trans_start = jiffies;
- return (1);
- }
-
- /*
- * If some higher layer thinks we've missed an tx-done interrupt we
- * are passed NULL.
- */
- if(skb == NULL)
- return (0);
-
/*
- * Block a timer-based transmit from overlapping. This could better be
- * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
+ * Block a transmit overlap
*/
- if(test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- {
- printk("%s: Transmitter access conflict.\n", dev->name);
- return (1);
- }
+
+ netif_stop_queue(dev);
if(tp->QueueSkb == 0)
return (1); /* Return with tbusy set: queue full */
@@ -4772,8 +4757,8 @@ static int smctr_send_packet(struct sk_buff *skb, struct net_device *dev)
skb_queue_tail(&tp->SendSkbQueue, skb);
smctr_hardware_send_packet(dev, tp);
if(tp->QueueSkb > 0)
- dev->tbusy = 0;
-
+ netif_wake_queue(dev);
+
return (0);
}
@@ -5749,7 +5734,7 @@ static int smctr_update_tx_chain(struct net_device *dev, FCBlock *fcb,
tp->num_tx_fcbs_used[queue]--;
fcb->frame_status = 0;
tp->tx_fcb_end[queue] = fcb->next_ptr;
-
+ netif_wake_queue(dev);
return (0);
}
}
diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
index 7e1933895..417cc7c29 100644
--- a/drivers/net/tokenring/tms380tr.c
+++ b/drivers/net/tokenring/tms380tr.c
@@ -280,10 +280,8 @@ int tms380tr_open(struct net_device *dev)
tms380tr_enable_interrupts(dev);
tms380tr_open_adapter(dev);
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 0;
-
+ netif_start_queue(dev);
+
/* Wait for interrupt from hardware. If interrupt does not come,
* there will be a timeout from the timer.
*/
@@ -298,8 +296,6 @@ int tms380tr_open(struct net_device *dev)
return (-1);
}
- dev->start = 1;
-
tp->StartTime = jiffies;
/* Start function control timer */
@@ -571,6 +567,20 @@ static void tms380tr_exec_cmd(struct net_device *dev, unsigned short Command)
return;
}
+static void tms380tr_timeout(struct net_device *dev)
+{
+ /*
+ * If we get here, some higher level has decided we are broken.
+ * There should really be a "kick me" function call instead.
+ *
+ * Resetting the token ring adapter takes a long time so just
+ * fake transmission time and go on trying. Our own timeout
+ * routine is in tms380tr_timer_chk()
+ */
+ dev->trans_start = jiffies;
+ netif_wake_queue(dev);
+}
+
/*
* Gets skb from system, queues it and checks if it can be sent
*/
@@ -578,38 +588,12 @@ static int tms380tr_send_packet(struct sk_buff *skb, struct net_device *dev)
{
struct net_local *tp = (struct net_local *)dev->priv;
- if(dev->tbusy)
- {
- /*
- * If we get here, some higher level has decided we are broken.
- * There should really be a "kick me" function call instead.
- *
- * Resetting the token ring adapter takes a long time so just
- * fake transmission time and go on trying. Our own timeout
- * routine is in tms380tr_timer_chk()
- */
- dev->tbusy = 0;
- dev->trans_start = jiffies;
- return (1);
- }
-
/*
- * If some higher layer thinks we've missed an tx-done interrupt we
- * are passed NULL.
+ * Block transmits from overlapping.
*/
- if(skb == NULL)
- return (0);
-
- /*
- * Block a timer-based transmit from overlapping. This could better be
- * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
- */
- if(test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- {
- printk("%s: Transmitter access conflict.\n", dev->name);
- return (1);
- }
-
+
+ netif_stop_queue(dev);
+
if(tp->QueueSkb == 0)
return (1); /* Return with tbusy set: queue full */
@@ -617,8 +601,7 @@ static int tms380tr_send_packet(struct sk_buff *skb, struct net_device *dev)
skb_queue_tail(&tp->SendSkbQueue, skb);
tms380tr_hardware_send_packet(dev, tp);
if(tp->QueueSkb > 0)
- dev->tbusy = 0;
-
+ netif_wake_queue(dev);
return (0);
}
@@ -773,8 +756,6 @@ void tms380tr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
return;
}
- dev->interrupt = 1;
-
tp = (struct net_local *)dev->priv;
irq_type = SIFREADW(SIFSTS);
@@ -854,8 +835,6 @@ void tms380tr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
irq_type = SIFREADW(SIFSTS);
}
- dev->interrupt = 0;
-
return;
}
@@ -1148,9 +1127,8 @@ static void tms380tr_cmd_status_irq(struct net_device *dev)
int tms380tr_close(struct net_device *dev)
{
struct net_local *tp = (struct net_local *)dev->priv;
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
+
del_timer(&tp->timer);
/* Flush the Tx and disable Rx here. */
@@ -2081,10 +2059,9 @@ static void tms380tr_tx_status_irq(struct net_device *dev)
tpl->BusyFlag = 0; /* "free" TPL */
}
- dev->tbusy = 0;
+ netif_wake_queue(dev);
if(tp->QueueSkb < MAX_TX_QUEUE)
tms380tr_hardware_send_packet(dev, tp);
-
return;
}
@@ -2367,6 +2344,8 @@ int tmsdev_init(struct net_device *dev)
dev->stop = tms380tr_close;
dev->do_ioctl = NULL;
dev->hard_start_xmit = tms380tr_send_packet;
+ dev->tx_timeout = tms380tr_timeout;
+ dev->watchdog_timeo = HZ;
dev->get_stats = tms380tr_get_stats;
dev->set_multicast_list = &tms380tr_set_multicast_list;
dev->set_mac_address = tms380tr_set_mac_address;
diff --git a/drivers/net/tulip.c b/drivers/net/tulip.c
index fa4e9dc62..5619b961d 100644
--- a/drivers/net/tulip.c
+++ b/drivers/net/tulip.c
@@ -1,146 +1,53 @@
/* tulip.c: A DEC 21040-family ethernet driver for Linux. */
/*
- Written 1994-1998 by Donald Becker.
+ Copyright 2000 The Linux Kernel Team
+ Written/copyright 1994-1999 by Donald Becker.
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
- This driver is for the Digital "Tulip" ethernet adapter interface.
+ This driver is for the Digital "Tulip" Ethernet adapter interface.
It should work with most DEC 21*4*-based chips/ethercards, as well as
- PNIC and MXIC chips.
+ with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and ASIX.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
- Support and updates available at
+ Additional information available at
http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html
-*/
-
-#define SMP_CHECK
-static const char version[] = "tulip.c:v0.89H 5/23/98 becker@cesdis.gsfc.nasa.gov\n";
-
-/* A few user-configurable values. */
-
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 25;
-
-#define MAX_UNITS 8
-/* Used to pass the full-duplex flag, etc. */
-static int full_duplex[MAX_UNITS] = {0, };
-static int options[MAX_UNITS] = {0, };
-static int mtu[MAX_UNITS] = {0, }; /* Jumbo MTU for interfaces. */
-
-/* The possible media types that can be set in options[] are: */
-static const char * const medianame[] = {
- "10baseT", "10base2", "AUI", "100baseTx",
- "10baseT-FD", "100baseTx-FD", "100baseT4", "100baseFx",
- "100baseFx-FD", "MII 10baseT", "MII 10baseT-FD", "MII",
- "10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FD", "MII 100baseT4",
-};
-
-/* Set if the PCI BIOS detects the chips on a multiport board backwards. */
-#ifdef REVERSE_PROBE_ORDER
-static int reverse_probe = 1;
-#else
-static int reverse_probe = 0;
-#endif
-
-/* Keep the ring sizes a power of two for efficiency.
- Making the Tx ring too large decreases the effectiveness of channel
- bonding and packet priority.
- There are no ill effects from too-large receive rings. */
-#define TX_RING_SIZE 16
-#define RX_RING_SIZE 32
-
-/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
-#ifdef __alpha__
-static int rx_copybreak = 1518;
-#else
-static int rx_copybreak = 100;
-#endif
-
-/* Operational parameters that usually are not changed. */
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT (4*HZ)
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/malloc.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-
-#include <asm/processor.h> /* Processor type for cache alignment. */
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-/* Kernel compatibility defines, common to David Hind's PCMCIA package.
- This is only in the support-all-kernels source code. */
-#include <linux/version.h> /* Evil, but neccessary */
-
-#define RUN_AT(x) (jiffies + (x))
-#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2)
-
-#define NEW_MULTICAST
-#include <linux/delay.h>
-
-#ifdef SA_SHIRQ
-#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
-#else
-#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs)
-#endif
-
-/* This my implementation of shared IRQs, now only used for 1.2.13. */
-#ifdef HAVE_SHARED_IRQ
-#define USE_SHARED_IRQ
-#include <linux/shared_irq.h>
-#endif
-
-/* The total size is unusually large: The 21040 aligns each of its 16
- longword-wide registers on a quadword boundary. */
-#define TULIP_TOTAL_SIZE 0x80
-
-#ifdef HAVE_DEVLIST
-struct netdev_entry tulip_drv =
-{"Tulip", tulip_pci_probe, TULIP_TOTAL_SIZE, NULL};
-#endif
+
+ For this specific driver variant please use linux-kernel for
+ bug reports.
-#ifdef TULIP_DEBUG
-int tulip_debug = TULIP_DEBUG;
-#else
-int tulip_debug = 1;
-#endif
-/*
Theory of Operation
I. Board Compatibility
This device driver is designed for the DECchip "Tulip", Digital's
single-chip ethernet controllers for PCI. Supported members of the family
-are the 21040, 21041, 21140, 21140A, 21142, and 21143. These chips are used on
-many PCI boards including the SMC EtherPower series.
+are the 21040, 21041, 21140, 21140A, 21142, and 21143. Similar work-alike
+chips from Lite-On, Macronics, ASIX, Compex and other listed below are also
+supported.
+These chips are used on at least 140 unique PCI board designs. The great
+number of chips and board designs supported is the reason for the
+driver size and complexity. Almost of the increasing complexity is in the
+board configuration and media selection code. There is very little
+increasing in the operational critical path length.
II. Board-specific settings
PCI bus devices are configured by the system at boot time, so no jumpers
need to be set on the board. The system BIOS preferably should assign the
PCI INTA signal to an otherwise unused system IRQ line.
-Note: Kernel versions earlier than 1.3.73 do not support shared PCI
-interrupt lines.
+
+Some boards have EEPROMs tables with default media entry. The factory default
+is usually "autoselect". This should only be overridden when using
+transceiver connections without link beat e.g. 10base2 or AUI, or (rarely!)
+for forcing full-duplex when used with old link partners that do not do
+autonegotiation.
III. Driver operation
@@ -188,111 +95,261 @@ tx_full and tbusy flags.
IV. Notes
-Thanks to Duke Kamstra of SMC for providing an EtherPower board.
+Thanks to Duke Kamstra of SMC for long ago providing an EtherPower board.
+Greg LaPolla at Linksys provided PNIC and other Linksys boards.
+Znyx provided a four-port card for testing.
IVb. References
http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
http://www.digital.com (search for current 21*4* datasheets and "21X4 SROM")
-http://www.national.com/pf/DP/DP83840.html
+http://www.national.com/pf/DP/DP83840A.html
+http://www.asix.com.tw/pmac.htm
+http://www.admtek.com.tw/
IVc. Errata
-The DEC databook doesn't document which Rx filter settings accept broadcast
-packets. Nor does it document how to configure the part to configure the
-serial subsystem for normal (vs. loopback) operation or how to have it
-autoswitch between internal 10baseT, SIA and AUI transceivers.
-
+The old DEC databooks were light on details.
The 21040 databook claims that CSR13, CSR14, and CSR15 should each be the last
-register of the set CSR12-15 written. Hmmm, now how is that possible? */
+register of the set CSR12-15 written. Hmmm, now how is that possible?
+The DEC SROM format is very badly designed not precisely defined, leading to
+part of the media selection junkheap below. Some boards do not have EEPROM
+media tables and need to be patched up. Worse, other boards use the DEC
+design kit media table when it isn't correct for their board.
-/* A few values that may be tweaked. */
-#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
+We cannot use MII interrupts because there is no defined GPIO pin to attach
+them. The MII transceiver status is polled using an kernel timer.
+
+*/
+static const char version[] = "Linux Tulip driver version 0.9.2 (Feb 15, 2000)\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <asm/processor.h> /* Processor type for cache alignment. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/unaligned.h>
+#include <asm/delay.h>
+
+
+/* A few user-configurable values. */
+
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static int max_interrupt_work = 25;
+
+#define MAX_UNITS 8
+/* Used to pass the full-duplex flag, etc. */
+static int full_duplex[MAX_UNITS] = {0, };
+static int options[MAX_UNITS] = {0, };
+static int mtu[MAX_UNITS] = {0, }; /* Jumbo MTU for interfaces. */
+
+/* The possible media types that can be set in options[] are: */
+static const char * const medianame[] = {
+ "10baseT", "10base2", "AUI", "100baseTx",
+ "10baseT-FD", "100baseTx-FD", "100baseT4", "100baseFx",
+ "100baseFx-FD", "MII 10baseT", "MII 10baseT-FD", "MII",
+ "10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FD", "MII 100baseT4",
+};
+
+/* Set if the PCI BIOS detects the chips on a multiport board backwards. */
+#ifdef REVERSE_PROBE_ORDER
+static int reverse_probe = 1;
+#else
+static int reverse_probe = 0;
+#endif
+
+/* Keep the ring sizes a power of two for efficiency.
+ Making the Tx ring too large decreases the effectiveness of channel
+ bonding and packet priority.
+ There are no ill effects from too-large receive rings. */
+#define TX_RING_SIZE 16
+#define RX_RING_SIZE 32
+
+/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
+#ifdef __alpha__
+static int rx_copybreak = 1518;
+#else
+static int rx_copybreak = 100;
+#endif
+
+/*
+ Set the bus performance register.
+ Typical: Set 16 longword cache alignment, no burst limit.
+ Cache alignment bits 15:14 Burst length 13:8
+ 0000 No alignment 0x00000000 unlimited 0800 8 longwords
+ 4000 8 longwords 0100 1 longword 1000 16 longwords
+ 8000 16 longwords 0200 2 longwords 2000 32 longwords
+ C000 32 longwords 0400 4 longwords
+ Warning: many older 486 systems are broken and require setting 0x00A04800
+ 8 longword cache alignment, 8 longword burst.
+ ToDo: Non-Intel setting could be better.
+*/
+
+#if defined(__alpha__)
+static int csr0 = 0x01A00000 | 0xE000;
+#elif defined(__i386__) || defined(__powerpc__) || defined(__sparc__)
+static int csr0 = 0x01A00000 | 0x8000;
+#else
+#warning Processor architecture undefined!
+static int csr0 = 0x00A00000 | 0x4800;
+#endif
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT (4*HZ)
+#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
/* This is a mysterious value that can be written to CSR11 in the 21040 (only)
to support a pre-NWay full-duplex signaling mechanism using short frames.
No one knows what it should be, but if left at its default value some
10base2(!) packets trigger a full-duplex-request interrupt. */
#define FULL_DUPLEX_MAGIC 0x6969
-#ifndef PCI_VENDOR_ID_DEC /* Now defined in linux/pci.h */
-#define PCI_VENDOR_ID_DEC 0x1011
-#define PCI_DEVICE_ID_TULIP 0x0002 /* 21040. */
-#define PCI_DEVICE_ID_TULIP_FAST 0x0009 /* 21140. */
-#endif
-#ifndef PCI_DEVICE_ID_DEC_TULIP_PLUS
-#define PCI_DEVICE_ID_DEC_TULIP_PLUS 0x0014 /* 21041. */
-#endif
-#ifndef PCI_DEVICE_ID_DEC_TULIP_21142
-#define PCI_DEVICE_ID_DEC_TULIP_21142 0x0019
-#endif
+/* Kernel compatibility defines, some common to David Hind's PCMCIA package.
+ This is only in the support-all-kernels source code. */
-#ifndef PCI_VENDOR_ID_LITEON
-#define PCI_VENDOR_ID_LITEON 0x11AD
-#endif
+MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
+MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver");
+MODULE_PARM(debug, "i");
+MODULE_PARM(max_interrupt_work, "i");
+MODULE_PARM(reverse_probe, "i");
+MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(csr0, "i");
+MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+
+#define TULIP_MODULE_NAME "tulip"
+#define PFX TULIP_MODULE_NAME ": "
+
+#define RUN_AT(x) (jiffies + (x))
-#ifndef PCI_VENDOR_ID_MXIC
-#define PCI_VENDOR_ID_MXIC 0x10d9
-#define PCI_DEVICE_ID_MX98713 0x0512
-#define PCI_DEVICE_ID_MX98715 0x0531
-#define PCI_DEVICE_ID_MX98725 0x0531
+/* Condensed operations for readability. */
+#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
+#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
+
+#define tulip_debug debug
+#ifdef TULIP_DEBUG
+static int tulip_debug = TULIP_DEBUG;
+#else
+static int tulip_debug = 1;
#endif
-/* The rest of these values should never change. */
+
+
+/* This table use during operation for capabilities and media timer. */
static void tulip_timer(unsigned long data);
static void t21142_timer(unsigned long data);
static void mxic_timer(unsigned long data);
static void pnic_timer(unsigned long data);
+static void comet_timer(unsigned long data);
-/* A table describing the chip types. */
-enum tbl_flag { HAS_MII=1, HAS_MEDIA_TABLE = 2, CSR12_IN_SROM = 4,};
+enum tbl_flag {
+ HAS_MII=1, HAS_MEDIA_TABLE=2, CSR12_IN_SROM=4, ALWAYS_CHECK_MII=8,
+ HAS_ACPI=0x10, MC_HASH_ONLY=0x20, /* Hash-only multicast filter. */
+ HAS_PNICNWAY=0x80, HAS_NWAY143=0x40, /* Uses internal NWay xcvr. */
+ HAS_8023X=0x100,
+};
static struct tulip_chip_table {
- int vendor_id, device_id;
char *chip_name;
int io_size;
int valid_intrs; /* CSR7 interrupt enable settings */
int flags;
void (*media_timer)(unsigned long data);
} tulip_tbl[] = {
- { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP,
- "Digital DC21040 Tulip", 128, 0x0001ebef, 0, tulip_timer },
- { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS,
- "Digital DC21041 Tulip", 128, 0x0001ebef, HAS_MEDIA_TABLE, tulip_timer },
- { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST,
- "Digital DS21140 Tulip", 128, 0x0001ebef,
- HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM,
- tulip_timer },
- { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_21142,
- "Digital DS21142/3 Tulip", 128, 0x0801fbff,
- HAS_MII | HAS_MEDIA_TABLE, t21142_timer },
- { PCI_VENDOR_ID_LITEON, 0x0002,
- "Lite-On 82c168 PNIC", 256, 0x0001ebef, HAS_MII, pnic_timer },
- { PCI_VENDOR_ID_MXIC, PCI_DEVICE_ID_MX98713,
- "Macronix 98713 PMAC", 128, 0x0001ebef,
- HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, tulip_timer /* Tulip-like! */ },
- { PCI_VENDOR_ID_MXIC, PCI_DEVICE_ID_MX98715,
- "Macronix 98715 PMAC", 256, 0x0001ebef, HAS_MEDIA_TABLE, mxic_timer },
- { PCI_VENDOR_ID_MXIC, PCI_DEVICE_ID_MX98725,
- "Macronix 98725 PMAC", 256, 0x0001ebef, HAS_MEDIA_TABLE, mxic_timer },
- { 0x125B, 0x1400, "ASIX AX88140", 128, 0x0001fbff,
+ { "Digital DC21040 Tulip", 128, 0x0001ebef, 0, tulip_timer },
+ { "Digital DC21041 Tulip", 128, 0x0001ebff, HAS_MEDIA_TABLE, tulip_timer },
+ { "Digital DS21140 Tulip", 128, 0x0001ebef,
HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, tulip_timer },
- {0, 0, 0, 0},
+ { "Digital DS21143 Tulip", 128, 0x0801fbff,
+ HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | HAS_NWAY143,
+ t21142_timer },
+ { "Lite-On 82c168 PNIC", 256, 0x0001ebef,
+ HAS_MII | HAS_PNICNWAY, pnic_timer },
+ { "Macronix 98713 PMAC", 128, 0x0001ebef,
+ HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer },
+ { "Macronix 98715 PMAC", 256, 0x0001ebef,
+ HAS_MEDIA_TABLE, mxic_timer },
+ { "Macronix 98725 PMAC", 256, 0x0001ebef,
+ HAS_MEDIA_TABLE, mxic_timer },
+ { "ASIX AX88140", 128, 0x0001fbff,
+ HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY, tulip_timer },
+ { "Lite-On PNIC-II", 256, 0x0801fbff,
+ HAS_MII | HAS_NWAY143 | HAS_8023X, t21142_timer },
+ { "ADMtek Comet", 256, 0x0001abef,
+ MC_HASH_ONLY, comet_timer },
+ { "Compex 9881 PMAC", 128, 0x0001ebef,
+ HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer },
+ { "Intel DS21145 Tulip", 128, 0x0801fbff,
+ HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_NWAY143,
+ t21142_timer },
+ { "Xircom tulip work-alike", 128, 0x0801fbff,
+ HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | HAS_NWAY143,
+ t21142_timer },
+ {0},
+};
+/* This matches the table above. Note 21142 == 21143. */
+enum chips {
+ DC21040=0,
+ DC21041=1,
+ DC21140=2,
+ DC21142=3, DC21143=3,
+ LC82C168,
+ MX98713,
+ MX98715,
+ MX98725,
+ AX88140,
+ PNIC2,
+ COMET,
+ COMPEX9881,
+ I21145,
+ X3201_3,
+};
+
+
+static struct pci_device_id tulip_pci_tbl[] __devinitdata = {
+ { 0x1011, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21040 },
+ { 0x1011, 0x0014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21041 },
+ { 0x1011, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21140 },
+ { 0x1011, 0x0019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21143 },
+ { 0x11AD, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, LC82C168 },
+ { 0x10d9, 0x0512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98713 },
+ { 0x10d9, 0x0531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 },
+ { 0x10d9, 0x0531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98725 },
+ { 0x125B, 0x1400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AX88140 },
+ { 0x11AD, 0xc115, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PNIC2 },
+ { 0x1317, 0x0981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+ { 0x11F6, 0x9881, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMPEX9881 },
+ { 0x8086, 0x0039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, I21145 },
+ { 0x115d, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, X3201_3 },
+ {0},
};
-/* This matches the table above. */
-enum chips { DC21040=0, DC21041=1, DC21140=2, DC21142=3, DC21143=3,
- LC82C168, MX98713, MX98715, MX98725};
+MODULE_DEVICE_TABLE(pci,tulip_pci_tbl);
+
/* A full-duplex map for media types. */
-enum MediaIs {MediaIsFD = 1, MediaAlwaysFD=2, MediaIsMII=4, MediaIsFx=8,
- MediaIs100=16};
+enum MediaIs {
+ MediaIsFD = 1, MediaAlwaysFD=2, MediaIsMII=4, MediaIsFx=8,
+ MediaIs100=16};
static const char media_cap[] =
{0,0,0,16, 3,19,16,24, 27,4,7,5, 0,20,23,20 };
+static u8 t21040_csr13[] = {2,0x0C,8,4, 4,0,0,0, 0,0,0,0, 4,0,0,0};
/* 21041 transceiver register settings: 10-T, 10-2, AUI, 10-T, 10T-FD*/
-static u16 t21041_csr13[] = { 0xEF05, 0xEF09, 0xEF09, 0xEF01, 0xEF09, };
-static u16 t21041_csr14[] = { 0x7F3F, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, };
+static u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, };
+static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, };
static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
static u16 t21142_csr13[] = { 0x0001, 0x0009, 0x0009, 0x0000, 0x0001, };
@@ -308,16 +365,12 @@ enum tulip_offsets {
/* The bits in the CSR5 status registers, mostly interrupt sources. */
enum status_bits {
- TimerInt=0x800, TPLnkFail=0x1000, TPLnkPass=0x10,
+ TimerInt=0x800, SytemError=0x2000, TPLnkFail=0x1000, TPLnkPass=0x10,
NormalIntr=0x10000, AbnormalIntr=0x8000,
RxJabber=0x200, RxDied=0x100, RxNoBuf=0x80, RxIntr=0x40,
TxFIFOUnderflow=0x20, TxJabber=0x08, TxNoBuf=0x04, TxDied=0x02, TxIntr=0x01,
};
-enum desc_status_bits {
- DescOwned=0x80000000, RxDescFatalErr=0x8000, RxWholePkt=0x0300,
-};
-
/* The Tulip Rx and Tx buffer descriptors. */
struct tulip_rx_desc {
s32 status;
@@ -331,6 +384,22 @@ struct tulip_tx_desc {
u32 buffer1, buffer2; /* We use only buffer 1. */
};
+enum desc_status_bits {
+ DescOwned=0x80000000, RxDescFatalErr=0x8000, RxWholePkt=0x0300,
+};
+
+/* Ring-wrap flag in length field, use for last ring entry.
+ 0x01000000 means chain on buffer2 address,
+ 0x02000000 means use the ring start address in CSR2/3.
+ Note: Some work-alike chips do not function correctly in chained mode.
+ The ASIX chip works only in chained mode.
+ Thus we indicates ring mode, but always write the 'next' field for
+ chained mode as well.
+*/
+#define DESC_RING_WRAP 0x02000000
+
+#define EEPROM_SIZE 128 /* 2 << EEPROM_ADDRLEN */
+
struct medialeaf {
u8 type;
u8 media;
@@ -340,7 +409,8 @@ struct medialeaf {
struct mediatable {
u16 defaultmedia;
u8 leafcount, csr12dir; /* General purpose pin directions. */
- unsigned has_mii:1, has_nonmii:1;
+ unsigned has_mii:1, has_nonmii:1, has_reset:6;
+ u32 csr15dir, csr15val; /* 21143 NWay setting. */
struct medialeaf mleaf[0];
};
@@ -362,12 +432,13 @@ struct tulip_private {
/* The addresses of receive-in-place skbuffs. */
struct sk_buff* rx_skbuff[RX_RING_SIZE];
char *rx_buffs; /* Address of temporary Rx buffers. */
- u32 setup_frame[48]; /* Pseudo-Tx frame to init address table. */
+ u16 setup_frame[96]; /* Pseudo-Tx frame to init address table. */
int chip_id;
int revision;
+ int flags;
struct net_device_stats stats;
struct timer_list timer; /* Media selection timer. */
- spinlock_t tx_lock;
+ spinlock_t tx_lock;
unsigned int cur_rx, cur_tx; /* The next free ring entry */
unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
unsigned int tx_full:1; /* The Tx queue is full. */
@@ -378,411 +449,52 @@ struct tulip_private {
unsigned int media2:4; /* Secondary monitored media port. */
unsigned int medialock:1; /* Don't sense media type. */
unsigned int mediasense:1; /* Media sensing in progress. */
+ unsigned int nway:1, nwayset:1; /* 21143 internal NWay. */
+ unsigned int csr0; /* CSR0 setting. */
unsigned int csr6; /* Current CSR6 control settings. */
- unsigned char eeprom[128]; /* Serial EEPROM contents. */
+ unsigned char eeprom[EEPROM_SIZE]; /* Serial EEPROM contents. */
+ void (*link_change)(struct net_device *dev, int csr5);
u16 to_advertise; /* NWay capabilities advertised. */
+ u16 lpar; /* 21143 Link partner ability. */
u16 advertising[4];
signed char phys[4], mii_cnt; /* MII device addresses. */
struct mediatable *mtable;
int cur_index; /* Current media index. */
- unsigned char pci_bus, pci_dev_fn;
+ int saved_if_port;
+ struct pci_dev *pdev;
+ int ttimer;
+ int susp_rx;
+ unsigned long nir;
+ unsigned long base_addr;
int pad0, pad1; /* Used for 8-byte alignment */
};
-static struct net_device *tulip_probe1(int pci_bus, int pci_devfn,
- int chip_id, int options);
static void parse_eeprom(struct net_device *dev);
-static int read_eeprom(long ioaddr, int location);
+static int read_eeprom(long ioaddr, int location, int addr_len);
static int mdio_read(struct net_device *dev, int phy_id, int location);
static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
static void select_media(struct net_device *dev, int startup);
-static int tulip_open(struct net_device *dev);
-static void tulip_timer(unsigned long data);
+/* Chip-specific media selection (timer functions prototyped above). */
+static void t21142_lnk_change(struct net_device *dev, int csr5);
+static void t21142_start_nway(struct net_device *dev);
+static void pnic_lnk_change(struct net_device *dev, int csr5);
+static void pnic_do_nway(struct net_device *dev);
+
static void tulip_tx_timeout(struct net_device *dev);
static void tulip_init_ring(struct net_device *dev);
static int tulip_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int tulip_refill_rx(struct net_device *dev);
static int tulip_rx(struct net_device *dev);
-static void tulip_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs);
+static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static int tulip_open(struct net_device *dev);
static int tulip_close(struct net_device *dev);
-static struct enet_statistics *tulip_get_stats(struct net_device *dev);
-#ifdef HAVE_PRIVATE_IOCTL
+static void tulip_up(struct net_device *dev);
+static void tulip_down(struct net_device *dev);
+static struct net_device_stats *tulip_get_stats(struct net_device *dev);
static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-#endif
-#ifdef NEW_MULTICAST
static void set_rx_mode(struct net_device *dev);
-#else
-static void set_rx_mode(struct net_device *dev, int num_addrs, void *addrs);
-#endif
-
-
-
-/* A list of all installed Tulip devices, for removing the driver module. */
-static struct net_device *root_tulip_dev = NULL;
-
-/* This 21040 probe no longer uses a large fixed contiguous Rx buffer region,
- but now receives directly into full-sized skbuffs that are allocated
- at open() time.
- This allows the probe routine to use the old driver initialization
- interface. */
-
-static int __init tulip_probe(void)
-{
- int cards_found = 0;
- static int pci_index = 0; /* Static, for multiple probe calls. */
- unsigned char pci_bus, pci_device_fn;
-
- /* Ideally we would detect all network cards in slot order. That would
- be best done a central PCI probe dispatch, which wouldn't work
- well with the current structure. So instead we detect just the
- Tulip cards in slot order. */
-
- if (! pci_present())
- return -ENODEV;
- for (;pci_index < 0xff; pci_index++) {
- u16 vendor, device, pci_command, new_command;
- unsigned long pci_ioaddr = 0;
- int chip_idx = 0;
- struct pci_dev *pdev;
-
- if (pcibios_find_class
- (PCI_CLASS_NETWORK_ETHERNET << 8,
- reverse_probe ? 0xfe - pci_index : pci_index,
- &pci_bus, &pci_device_fn) != PCIBIOS_SUCCESSFUL)
- {
- if (reverse_probe)
- continue;
- else
- break;
- }
-
- pdev = pci_find_slot (pci_bus, pci_device_fn);
- vendor = pdev->vendor;
- device = pdev->device;
-
- for (chip_idx = 0; tulip_tbl[chip_idx].chip_name; chip_idx++)
- if (vendor == tulip_tbl[chip_idx].vendor_id &&
- device == tulip_tbl[chip_idx].device_id)
- break;
- if (tulip_tbl[chip_idx].chip_name == 0) {
- if (vendor == PCI_VENDOR_ID_DEC ||
- vendor == PCI_VENDOR_ID_LITEON)
- printk(KERN_INFO "Unknown Tulip-style PCI ethernet chip type"
- " %4.4x %4.4x"" detected: not configured.\n",
- vendor, device);
- continue;
- }
- pci_ioaddr = pci_find_slot(pci_bus, pci_device_fn)->resource[0].start;
- /* Remove I/O space marker in bit 0. */
- pci_ioaddr &= ~3;
- if (tulip_debug > 2)
- printk(KERN_DEBUG "Found %s at I/O %#lx.\n",
- tulip_tbl[chip_idx].chip_name, pci_ioaddr);
-
- if (check_region(pci_ioaddr, tulip_tbl[chip_idx].io_size))
- continue;
-
- pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
- new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
- if (pci_command != new_command) {
- printk(KERN_INFO " The PCI BIOS has not enabled this"
- " device! Updating PCI command %4.4x->%4.4x.\n",
- pci_command, new_command);
- pci_write_config_word(pdev, PCI_COMMAND, new_command);
- }
-
- if(tulip_probe1(pci_bus, pci_device_fn, chip_idx, cards_found))
- {
- /* Get and check the bus-master and latency values. */
- unsigned char pci_latency;
- pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
- if (pci_latency < 10) {
- printk(KERN_INFO " PCI latency timer (CFLT) is "
- "unreasonably low at %d. Setting to 64 clocks.\n",
- pci_latency);
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
- } else if (tulip_debug > 1)
- printk(KERN_INFO " PCI latency timer (CFLT) is %#x, "
- " PCI command is %4.4x.\n",
- pci_latency, new_command);
- /* Bring the 21143 out power-down mode. */
- if (device == PCI_DEVICE_ID_DEC_TULIP_21142)
- pci_write_config_dword(pdev, 0x40, 0x40000000);
- cards_found++;
- }
- }
-
- return cards_found ? 0 : -ENODEV;
-}
-
-static struct net_device *tulip_probe1(int pci_bus, int pci_device_fn,
- int chip_id, int board_idx)
-{
- struct net_device *dev;
- static int did_version = 0; /* Already printed version info. */
- struct tulip_private *tp;
- long ioaddr;
- int irq;
- /* See note below on the multiport cards. */
- static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'};
- static int last_irq = 0;
- static int multiport_cnt = 0; /* For four-port boards w/one EEPROM */
- int i;
- unsigned short sum;
-
- if (tulip_debug > 0 && did_version++ == 0)
- printk(KERN_INFO "%s", version);
- dev = init_etherdev(NULL, 0);
-
- irq = pci_find_slot(pci_bus, pci_device_fn)->irq;
- ioaddr = pci_find_slot(pci_bus, pci_device_fn)->resource[0].start;
-
- printk(KERN_INFO "%s: %s at %#3lx,",
- dev->name, tulip_tbl[chip_id].chip_name, ioaddr);
-
- /* Stop the chip's Tx and Rx processes. */
- outl(inl(ioaddr + CSR6) & ~0x2002, ioaddr + CSR6);
- /* Clear the missed-packet counter. */
- (volatile int)inl(ioaddr + CSR8);
-
- if (chip_id == DC21041) {
- if (inl(ioaddr + CSR9) & 0x8000) {
- printk(" 21040 compatible mode,");
- chip_id = DC21040;
- } else {
- printk(" 21041 mode,");
- }
- }
-
- /* The station address ROM is read byte serially. The register must
- be polled, waiting for the value to be read bit serially from the
- EEPROM.
- */
- sum = 0;
- if (chip_id == DC21040) {
- outl(0, ioaddr + CSR9); /* Reset the pointer with a dummy write. */
- for (i = 0; i < 6; i++) {
- int value, boguscnt = 100000;
- do
- value = inl(ioaddr + CSR9);
- while (value < 0 && --boguscnt > 0);
- dev->dev_addr[i] = value;
- sum += value & 0xff;
- }
- } else if (chip_id == LC82C168) {
- for (i = 0; i < 3; i++) {
- int value, boguscnt = 100000;
- outl(0x600 | i, ioaddr + 0x98);
- do
- value = inl(ioaddr + CSR9);
- while (value < 0 && --boguscnt > 0);
- ((u16*)dev->dev_addr)[i] = value;
- sum += value & 0xffff;
- }
- } else { /* Must be a new chip, with a serial EEPROM interface. */
- /* We read the whole EEPROM, and sort it out later. DEC has a
- specification _Digital Semiconductor 21X4 Serial ROM Format_
- but early vendor boards just put the address in the first six
- EEPROM locations. */
- unsigned char ee_data[128];
- int sa_offset = 0;
-
- for (i = 0; i < sizeof(ee_data)/2; i++)
- ((u16 *)ee_data)[i] = read_eeprom(ioaddr, i);
-
- /* Detect the simple EEPROM format by the duplicated station addr. */
- for (i = 0; i < 8; i ++)
- if (ee_data[i] != ee_data[16+i])
- sa_offset = 20;
- if (ee_data[0] == 0xff && ee_data[1] == 0xff && ee_data[2] == 0) {
- sa_offset = 2; /* Grrr, damn Matrox boards. */
- multiport_cnt = 4;
- }
- for (i = 0; i < 6; i ++) {
- dev->dev_addr[i] = ee_data[i + sa_offset];
- sum += ee_data[i + sa_offset];
- }
- }
- /* Lite-On boards have the address byte-swapped. */
- if (dev->dev_addr[0] == 0xA0 && dev->dev_addr[1] == 0x00)
- for (i = 0; i < 6; i+=2) {
- char tmp = dev->dev_addr[i];
- dev->dev_addr[i] = dev->dev_addr[i+1];
- dev->dev_addr[i+1] = tmp;
- }
- /* On the Zynx 315 Etherarray and other multiport boards only the
- first Tulip has an EEPROM.
- The addresses of the subsequent ports are derived from the first.
- Many PCI BIOSes also incorrectly report the IRQ line, so we correct
- that here as well. */
- if (sum == 0 || sum == 6*0xff) {
- printk(" EEPROM not present,");
- for (i = 0; i < 5; i++)
- dev->dev_addr[i] = last_phys_addr[i];
- dev->dev_addr[i] = last_phys_addr[i] + 1;
-#if defined(__i386__) /* This BIOS bug doesn't exist on Alphas. */
- irq = last_irq;
-#endif
- }
-
- for (i = 0; i < 6; i++)
- printk(" %2.2x", last_phys_addr[i] = dev->dev_addr[i]);
- printk(", IRQ %d.\n", irq);
- last_irq = irq;
-
- /* We do a request_region() only to register /proc/ioports info. */
- /* Note that proper size is tulip_tbl[chip_id].chip_name, but... */
- request_region(ioaddr, TULIP_TOTAL_SIZE, dev->name);
-
- dev->base_addr = ioaddr;
- dev->irq = irq;
-
- /* Make certain the data structures are quadword aligned. */
- tp = (void *)(((long)kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA) + 7) & ~7);
- memset(tp, 0, sizeof(*tp));
- dev->priv = tp;
-
- tp->next_module = root_tulip_dev;
- root_tulip_dev = dev;
-
- tp->pci_bus = pci_bus;
- tp->pci_dev_fn = pci_device_fn;
- tp->chip_id = chip_id;
-
-#ifdef TULIP_FULL_DUPLEX
- tp->full_duplex = 1;
- tp->full_duplex_lock = 1;
-#endif
-#ifdef TULIP_DEFAULT_MEDIA
- tp->default_port = TULIP_DEFAULT_MEDIA;
-#endif
-#ifdef TULIP_NO_MEDIA_SWITCH
- tp->medialock = 1;
-#endif
-
- /* The lower four bits are the media type. */
- if (board_idx >= 0 && board_idx < MAX_UNITS) {
- tp->default_port = options[board_idx] & 15;
- if ((options[board_idx] & 0x90) || full_duplex[board_idx] > 0)
- tp->full_duplex = 1;
- if (mtu[board_idx] > 0)
- dev->mtu = mtu[board_idx];
- }
- if (dev->mem_start)
- tp->default_port = dev->mem_start;
- if (tp->default_port) {
- tp->medialock = 1;
- if (media_cap[tp->default_port] & MediaAlwaysFD)
- tp->full_duplex = 1;
- }
- if (tp->full_duplex)
- tp->full_duplex_lock = 1;
-
- /* This is logically part of probe1(), but too complex to write inline. */
- if (tulip_tbl[chip_id].flags & HAS_MEDIA_TABLE)
- parse_eeprom(dev);
-
- if (media_cap[tp->default_port] & MediaIsMII) {
- u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 };
- tp->to_advertise = media2advert[tp->default_port - 9];
- } else
- tp->to_advertise = 0x03e1;
-
- if ((tp->mtable && tp->mtable->has_mii) ||
- ( ! tp->mtable && (tulip_tbl[tp->chip_id].flags & HAS_MII))) {
- int phy, phy_idx;
- /* Find the connected MII xcvrs.
- Doing this in open() would allow detecting external xcvrs later,
- but takes much time. */
- for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
- phy++) {
- int mii_status = mdio_read(dev, phy, 1);
- if (mii_status != 0xffff && mii_status != 0x0000) {
- int mii_reg0 = mdio_read(dev, phy, 0);
- int reg4 = ((mii_status>>6) & tp->to_advertise) | 1;
- tp->phys[phy_idx] = phy;
- tp->advertising[phy_idx++] = reg4;
- printk(KERN_INFO "%s: MII transceiver found at MDIO address "
- "%d, config %4.4x status %4.4x.\n",
- dev->name, phy, mii_reg0, mii_status);
- if (1 || (media_cap[tp->default_port] & MediaIsMII)) {
- printk(KERN_DEBUG "%s: Advertising %4.4x on PHY %d,"
- " previously advertising %4.4x.\n",
- dev->name, reg4, phy, mdio_read(dev, phy, 4));
- mdio_write(dev, phy, 4, reg4);
- }
- /* Enable autonegotiation: some boards default to off. */
- mdio_write(dev, phy, 0, mii_reg0 |
- (tp->full_duplex ? 0x1100 : 0x1000) |
- (media_cap[tp->default_port]&MediaIs100 ? 0x2000:0));
- }
- }
- tp->mii_cnt = phy_idx;
- if (tp->mtable && tp->mtable->has_mii && phy_idx == 0) {
- printk(KERN_INFO "%s: ***WARNING***: No MII transceiver found!\n",
- dev->name);
- tp->phys[0] = 1;
- }
- }
-
- /* The Tulip-specific entries in the device structure. */
- dev->open = &tulip_open;
- dev->hard_start_xmit = &tulip_start_xmit;
- dev->tx_timeout = &tulip_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
- dev->stop = &tulip_close;
- dev->get_stats = &tulip_get_stats;
-#ifdef HAVE_PRIVATE_IOCTL
- dev->do_ioctl = &private_ioctl;
-#endif
-#ifdef HAVE_MULTICAST
- dev->set_multicast_list = &set_rx_mode;
-#endif
-
- /* Reset the xcvr interface and turn on heartbeat. */
- switch (chip_id) {
- case DC21041:
- outl(0x00000000, ioaddr + CSR13);
- outl(0xFFFFFFFF, ioaddr + CSR14);
- outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */
- outl(inl(ioaddr + CSR6) | 0x0200, ioaddr + CSR6);
- outl(0x0000EF05, ioaddr + CSR13);
- break;
- case DC21040:
- outl(0x00000000, ioaddr + CSR13);
- outl(0x00000004, ioaddr + CSR13);
- break;
- case DC21140: default:
- if (tp->mtable)
- outl(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
- break;
- case DC21142:
- outl(0x82420200, ioaddr + CSR6);
- outl(0x0001, ioaddr + CSR13);
- outl(0x0003FFFF, ioaddr + CSR14);
- outl(0x0008, ioaddr + CSR15);
- outl(0x0001, ioaddr + CSR13);
- outl(0x1301, ioaddr + CSR12); /* Start NWay. */
- break;
- case LC82C168:
- if ( ! tp->mii_cnt) {
- outl(0x00420000, ioaddr + CSR6);
- outl(0x30, ioaddr + CSR12);
- outl(0x0001F078, ioaddr + 0xB8);
- outl(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */
- }
- break;
- case MX98713: case MX98715: case MX98725:
- outl(0x00000000, ioaddr + CSR6);
- outl(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */
- outl(0x00000001, ioaddr + CSR13);
- break;
- }
-
- return dev;
-}
-
/* Serial EEPROM section. */
/* The main routine to parse the very complicated SROM structure.
Search www.digital.com for "21X4 SROM" to get details.
@@ -798,29 +510,37 @@ static struct fixups {
} eeprom_fixups[] = {
{"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c,
0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }},
- {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x021f,
+ {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x041f,
0x0000, 0x009E, /* 10baseT */
- 0x0903, 0x006D, /* 100baseTx */ }},
- {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x033f,
+ 0x0004, 0x009E, /* 10baseT-FD */
+ 0x0903, 0x006D, /* 100baseTx */
+ 0x0905, 0x006D, /* 100baseTx-FD */ }},
+ {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x063f,
0x0107, 0x8021, /* 100baseFx */
0x0108, 0x8021, /* 100baseFx-FD */
- 0x0103, 0x006D, /* 100baseTx */ }},
- {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0313,
+ 0x0100, 0x009E, /* 10baseT */
+ 0x0104, 0x009E, /* 10baseT-FD */
+ 0x0103, 0x006D, /* 100baseTx */
+ 0x0105, 0x006D, /* 100baseTx-FD */ }},
+ {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0513,
0x1001, 0x009E, /* 10base2, CSR12 0x10*/
0x0000, 0x009E, /* 10baseT */
- 0x0303, 0x006D, /* 100baseTx, CSR12 0x03 */ }},
- {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x031F,
- 0x1B01, 0x0000, /* 10base2, CSR12 0x1B */
- 0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */
- 0x0B00, 0x009E, /* 10baseT, CSR12 0x0B */
+ 0x0004, 0x009E, /* 10baseT-FD */
+ 0x0303, 0x006D, /* 100baseTx, CSR12 0x03 */
+ 0x0305, 0x006D, /* 100baseTx-FD CSR12 0x03 */}},
+ {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x051F,
+ 0x1B01, 0x0000, /* 10base2, CSR12 0x1B */
+ 0x0B00, 0x009E, /* 10baseT, CSR12 0x0B */
+ 0x0B04, 0x009E, /* 10baseT-FD,CSR12 0x0B */
+ 0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */
+ 0x1B05, 0x006D, /* 100baseTx-FD CSR12 0x1B */
}},
{0, 0, 0, 0, {}}};
static const char * block_name[] = {"21140 non-MII", "21140 MII PHY",
"21142 Serial PHY", "21142 MII PHY", "21143 SYM PHY", "21143 reset method"};
-#define EEPROM_SIZE 128
-#if defined(__i386__)
+#if defined(__i386__) /* AKA get_unaligned() */
#define get_u16(ptr) (*(u16 *)(ptr))
#else
#define get_u16(ptr) (((u8*)(ptr))[0] + (((u8*)(ptr))[1]<<8))
@@ -833,14 +553,10 @@ static void parse_eeprom(struct net_device *dev)
static unsigned char *last_ee_data = NULL;
static int controller_index = 0;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- long ioaddr = dev->base_addr;
unsigned char *ee_data = tp->eeprom;
int i;
tp->mtable = 0;
- for (i = 0; i < EEPROM_SIZE/2; i++)
- ((u16 *)ee_data)[i] = read_eeprom(ioaddr, i);
-
/* Detect an old-style (SA only) EEPROM layout:
memcmp(eedata, eedata+16, 8). */
for (i = 0; i < 8; i ++)
@@ -877,20 +593,13 @@ static void parse_eeprom(struct net_device *dev)
}
}
if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
- printk(KERN_INFO "%s: Old style EEPROM -- no media selection information.\n",
+ printk(KERN_INFO "%s: Old style EEPROM with no media selection "
+ "information.\n",
dev->name);
return;
}
}
- if (tulip_debug > 1) {
- printk(KERN_DEBUG "read_eeprom:");
- for (i = 0; i < 64; i++) {
- printk("%s%4.4x", (i & 7) == 0 ? "\n" KERN_DEBUG : " ",
- read_eeprom(ioaddr, i));
- }
- printk("\n");
- }
-
+
controller_index = 0;
if (ee_data[19] > 1) { /* Multiport board. */
last_ee_data = ee_data;
@@ -900,42 +609,29 @@ subsequent_board:
if (ee_data[27] == 0) { /* No valid media table. */
} else if (tp->chip_id == DC21041) {
unsigned char *p = (void *)ee_data + ee_data[27 + controller_index*3];
- short media;
- int count;
+ int media = get_u16(p);
+ int count = p[2];
+ p += 3;
- media = get_u16(p);
- p += 2;
- count = *p++;
-
- printk(KERN_INFO "%s:21041 Media information at %d, default media "
- "%4.4x (%s).\n", dev->name, ee_data[27], media,
+ printk(KERN_INFO "%s: 21041 Media table, default media %4.4x (%s).\n",
+ dev->name, media,
media & 0x0800 ? "Autosense" : medianame[media & 15]);
for (i = 0; i < count; i++) {
unsigned char media_code = *p++;
- u16 csrvals[3];
- int idx;
- for (idx = 0; idx < 3; idx++) {
- csrvals[idx] = get_u16(p);
- p += 2;
- }
- if (media_code & 0x40) {
- printk(KERN_INFO "%s: 21041 media %2.2x (%s),"
- " csr13 %4.4x csr14 %4.4x csr15 %4.4x.\n",
- dev->name, media_code & 15, medianame[media_code & 15],
- csrvals[0], csrvals[1], csrvals[2]);
- } else
- printk(KERN_INFO "%s: 21041 media #%d, %s.\n",
- dev->name, media_code & 15, medianame[media_code & 15]);
+ if (media_code & 0x40)
+ p += 6;
+ printk(KERN_INFO "%s: 21041 media #%d, %s.\n",
+ dev->name, media_code & 15, medianame[media_code & 15]);
}
} else {
unsigned char *p = (void *)ee_data + ee_data[27];
unsigned char csr12dir = 0;
- int count;
+ int count, new_advertise = 0;
struct mediatable *mtable;
u16 media = get_u16(p);
p += 2;
- if (tulip_tbl[tp->chip_id].flags & CSR12_IN_SROM)
+ if (tp->flags & CSR12_IN_SROM)
csr12dir = *p++;
count = *p++;
mtable = (struct mediatable *)
@@ -947,13 +643,14 @@ subsequent_board:
mtable->defaultmedia = media;
mtable->leafcount = count;
mtable->csr12dir = csr12dir;
- mtable->has_nonmii = mtable->has_mii = 0;
+ mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
+ mtable->csr15dir = mtable->csr15val = 0;
printk(KERN_INFO "%s: EEPROM default media type %s.\n", dev->name,
media & 0x0800 ? "Autosense" : medianame[media & 15]);
for (i = 0; i < count; i++) {
struct medialeaf *leaf = &mtable->mleaf[i];
-
+
if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */
leaf->type = 0;
leaf->media = p[0] & 0x3f;
@@ -963,12 +660,34 @@ subsequent_board:
p += 4;
} else {
leaf->type = p[1];
- if (p[1] & 1) {
+ if (p[1] == 0x05) {
+ mtable->has_reset = i;
+ leaf->media = p[2] & 0x0f;
+ } else if (p[1] & 1) {
mtable->has_mii = 1;
leaf->media = 11;
} else {
mtable->has_nonmii = 1;
leaf->media = p[2] & 0x0f;
+ switch (leaf->media) {
+ case 0: new_advertise |= 0x0020; break;
+ case 4: new_advertise |= 0x0040; break;
+ case 3: new_advertise |= 0x0080; break;
+ case 5: new_advertise |= 0x0100; break;
+ case 6: new_advertise |= 0x0200; break;
+ }
+ if (p[1] == 2 && leaf->media == 0) {
+ if (p[2] & 0x40) {
+ u32 base15 = get_unaligned((u16*)&p[7]);
+ mtable->csr15dir =
+ (get_unaligned((u16*)&p[9])<<16) + base15;
+ mtable->csr15val =
+ (get_unaligned((u16*)&p[11])<<16) + base15;
+ } else {
+ mtable->csr15dir = get_unaligned((u16*)&p[3])<<16;
+ mtable->csr15val = get_unaligned((u16*)&p[5])<<16;
+ }
+ }
}
leaf->leafdata = p + 2;
p += (p[0] & 0x3f) + 1;
@@ -977,7 +696,7 @@ subsequent_board:
unsigned char *bp = leaf->leafdata;
printk(KERN_INFO "%s: MII interface PHY %d, setup/reset "
"sequences %d/%d long, capabilities %2.2x %2.2x.\n",
- dev->name, bp[0], bp[1], bp[1 + bp[1]*2],
+ dev->name, bp[0], bp[1], bp[2 + bp[1]*2],
bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]);
}
printk(KERN_INFO "%s: Index #%d - Media %s (#%d) described "
@@ -985,6 +704,8 @@ subsequent_board:
dev->name, i, medianame[leaf->media], leaf->media,
block_name[leaf->type], leaf->type);
}
+ if (new_advertise)
+ tp->to_advertise = new_advertise;
}
}
/* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
@@ -992,54 +713,48 @@ subsequent_board:
/* EEPROM_Ctrl bits. */
#define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */
#define EE_CS 0x01 /* EEPROM chip select. */
-#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
+#define EE_DATA_WRITE 0x04 /* Data from the Tulip to EEPROM. */
#define EE_WRITE_0 0x01
#define EE_WRITE_1 0x05
-#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
+#define EE_DATA_READ 0x08 /* Data from the EEPROM chip. */
#define EE_ENB (0x4800 | EE_CS)
/* Delay between EEPROM clock transitions.
- The 1.2 code is a "nasty" timing loop, but PC compatible machines are
- *supposed* to delay an ISA-compatible period for the SLOW_DOWN_IO macro. */
-#ifdef _LINUX_DELAY_H
-#define eeprom_delay(nanosec) udelay((nanosec + 999)/1000)
-#else
-#define eeprom_delay(nanosec) do { int _i = 3; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
-#endif
+ Even at 33Mhz current PCI implementations don't overrun the EEPROM clock.
+ We add a bus turn-around to insure that this remains true. */
+#define eeprom_delay() inl(ee_addr)
/* The EEPROM commands include the alway-set leading bit. */
-#define EE_WRITE_CMD (5 << 6)
-#define EE_READ_CMD (6 << 6)
-#define EE_ERASE_CMD (7 << 6)
+#define EE_READ_CMD (6)
-static int read_eeprom(long ioaddr, int location)
+/* Note: this routine returns extra data bits for size detection. */
+static int __devinit read_eeprom(long ioaddr, int location, int addr_len)
{
int i;
- unsigned short retval = 0;
+ unsigned retval = 0;
long ee_addr = ioaddr + CSR9;
- int read_cmd = location | EE_READ_CMD;
-
+ int read_cmd = location | (EE_READ_CMD << addr_len);
+
outl(EE_ENB & ~EE_CS, ee_addr);
outl(EE_ENB, ee_addr);
-
+
/* Shift the read command bits out. */
- for (i = 10; i >= 0; i--) {
+ for (i = 4 + addr_len; i >= 0; i--) {
short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
outl(EE_ENB | dataval, ee_addr);
- eeprom_delay(100);
+ eeprom_delay();
outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
- eeprom_delay(150);
- outl(EE_ENB | dataval, ee_addr); /* Finish EEPROM a clock tick. */
- eeprom_delay(250);
+ eeprom_delay();
+ retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
}
outl(EE_ENB, ee_addr);
-
+
for (i = 16; i > 0; i--) {
outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
- eeprom_delay(100);
+ eeprom_delay();
retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
outl(EE_ENB, ee_addr);
- eeprom_delay(100);
+ eeprom_delay();
}
/* Terminate the EEPROM access. */
@@ -1073,19 +788,33 @@ static int mdio_read(struct net_device *dev, int phy_id, int location)
int i;
int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
int retval = 0;
- long mdio_addr = dev->base_addr + CSR9;
+ long ioaddr = dev->base_addr;
+ long mdio_addr = ioaddr + CSR9;
if (tp->chip_id == LC82C168) {
- long ioaddr = dev->base_addr;
int i = 1000;
outl(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0);
+ inl(ioaddr + 0xA0);
+ inl(ioaddr + 0xA0);
while (--i > 0)
if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000))
return retval & 0xffff;
return 0xffff;
}
- /* Establish sync by sending at least 32 logic ones. */
+ if (tp->chip_id == COMET) {
+ if (phy_id == 1) {
+ if (location < 7)
+ return inl(ioaddr + 0xB4 + (location<<2));
+ else if (location == 17)
+ return inl(ioaddr + 0xD0);
+ else if (location >= 29 && location <= 31)
+ return inl(ioaddr + 0xD4 + ((location-29)<<2));
+ }
+ return 0xffff;
+ }
+
+ /* Establish sync by sending at least 32 logic ones. */
for (i = 32; i >= 0; i--) {
outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
mdio_delay();
@@ -1117,10 +846,10 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
struct tulip_private *tp = (struct tulip_private *)dev->priv;
int i;
int cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
- long mdio_addr = dev->base_addr + CSR9;
+ long ioaddr = dev->base_addr;
+ long mdio_addr = ioaddr + CSR9;
if (tp->chip_id == LC82C168) {
- long ioaddr = dev->base_addr;
int i = 1000;
outl(cmd, ioaddr + 0xA0);
do
@@ -1130,7 +859,19 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
return;
}
- /* Establish sync by sending 32 logic ones. */
+ if (tp->chip_id == COMET) {
+ if (phy_id != 1)
+ return;
+ if (location < 7)
+ outl(value, ioaddr + 0xB4 + (location<<2));
+ else if (location == 17)
+ outl(value, ioaddr + 0xD0);
+ else if (location >= 29 && location <= 31)
+ outl(value, ioaddr + 0xD4 + ((location-29)<<2));
+ return;
+ }
+
+ /* Establish sync by sending 32 logic ones. */
for (i = 32; i >= 0; i--) {
outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
mdio_delay();
@@ -1155,99 +896,114 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
return;
}
-
-static int
-tulip_open(struct net_device *dev)
+
+/* The Xircom cards are picky about when certain bits in CSR6 can be
+ manipulated. Keith Owens <kaos@ocs.com.au>. */
+
+static void outl_CSR6 (struct tulip_private *tp, u32 newcsr6)
+{
+ long ioaddr = tp->base_addr;
+ const int strict_bits = 0x0060e202;
+ int csr5, csr5_22_20, csr5_19_17, currcsr6, attempts = 200;
+ long flags;
+
+ /* really a hw lock */
+ spin_lock_irqsave (&tp->tx_lock, flags);
+
+ if (tp->chip_id != X3201_3)
+ goto out_write;
+
+ newcsr6 &= 0x726cfeca; /* mask out the reserved CSR6 bits that always */
+ /* read 0 on the Xircom cards */
+ newcsr6 |= 0x320c0000; /* or in the reserved bits that always read 1 */
+ currcsr6 = inl (ioaddr + CSR6);
+ if (((newcsr6 & strict_bits) == (currcsr6 & strict_bits)) ||
+ ((currcsr6 & ~0x2002) == 0))
+ goto out_write;
+
+ /* make sure the transmitter and receiver are stopped first */
+ currcsr6 &= ~0x2002;
+ while (1) {
+ csr5 = inl (ioaddr + CSR5);
+ if (csr5 == 0xffffffff)
+ break; /* cannot read csr5, card removed? */
+ csr5_22_20 = csr5 & 0x700000;
+ csr5_19_17 = csr5 & 0x0e0000;
+ if ((csr5_22_20 == 0 || csr5_22_20 == 0x600000) &&
+ (csr5_19_17 == 0 || csr5_19_17 == 0x80000 || csr5_19_17 == 0xc0000))
+ break; /* both are stopped or suspended */
+ if (!--attempts) {
+ printk (KERN_INFO "tulip.c: outl_CSR6 too many attempts,"
+ "csr5=0x%08x\n", csr5);
+ goto out_write;
+ }
+ outl (currcsr6, ioaddr + CSR6);
+ udelay (1);
+ }
+
+out_write:
+ /* now it is safe to change csr6 */
+ outl (newcsr6, ioaddr + CSR6);
+
+ spin_unlock_irqrestore (&tp->lock, flags);
+}
+
+
+static void tulip_up(struct net_device *dev)
{
struct tulip_private *tp = (struct tulip_private *)dev->priv;
long ioaddr = dev->base_addr;
- int i = 0;
+ int next_tick = 3*HZ;
+ int i;
+
+ /* Wake the chip from sleep/snooze mode. */
+ if (tp->flags & HAS_ACPI)
+ pci_write_config_dword(tp->pdev, 0x40, 0);
/* On some chip revs we must set the MII/SYM port before the reset!? */
if (tp->mii_cnt || (tp->mtable && tp->mtable->has_mii))
- outl(0x00040000, ioaddr + CSR6);
+ outl_CSR6 (tp, 0x00040000);
/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
outl(0x00000001, ioaddr + CSR0);
-#ifdef _LINUX_DELAY_H
- udelay(2);
-#else
- SLOW_DOWN_IO;
-#endif
+
/* Deassert reset.
- 486: Set 8 longword cache alignment, 8 longword burst.
- 586: Set 16 longword cache alignment, no burst limit.
- Cache alignment bits 15:14 Burst length 13:8
- 0000 No alignment 0x00000000 unlimited 0800 8 longwords
- 4000 8 longwords 0100 1 longword 1000 16 longwords
- 8000 16 longwords 0200 2 longwords 2000 32 longwords
- C000 32 longwords 0400 4 longwords
Wait the specified 50 PCI cycles after a reset by initializing
Tx and Rx queues and the address filter list. */
-#if defined(__alpha__)
- /* ToDo: Alpha setting could be better. */
- outl(0x01A00000 | 0xE000, ioaddr + CSR0);
-#elif defined(__powerpc__)
- outl(0x01A00080 | 0x8000, ioaddr + CSR0);
-#elif defined(__i386__)
-#if defined(MODULE)
- /* When a module we don't have 'x86' to check. */
- outl(0x01A00000 | 0x4800, ioaddr + CSR0);
-#else
-#define x86 boot_cpu_data.x86
- outl(0x01A00000 | (x86 <= 4 ? 0x4800 : 0x8000), ioaddr + CSR0);
- if (x86 <= 4)
- printk(KERN_INFO "%s: This is a 386/486 PCI system, setting cache "
- "alignment to %x.\n", dev->name,
- 0x01A00000 | (x86 <= 4 ? 0x4800 : 0x8000));
-#endif
-#else
- outl(0x01A00000 | 0x4800, ioaddr + CSR0);
-#warning Processor architecture undefined!
-#endif
-
-#ifdef SA_SHIRQ
- if (request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev)) {
- return -EAGAIN;
- }
-#else
- if (irq2dev_map[dev->irq] != NULL
- || (irq2dev_map[dev->irq] = dev) == NULL
- || dev->irq == 0
- || request_irq(dev->irq, &tulip_interrupt, 0,
- tulip_tbl[tp->chip_id].chip_name)) {
- return -EAGAIN;
- }
-#endif
+ outl(tp->csr0, ioaddr + CSR0);
if (tulip_debug > 1)
printk(KERN_DEBUG "%s: tulip_open() irq %d.\n", dev->name, dev->irq);
- MOD_INC_USE_COUNT;
-
- spin_lock_init(&tp->tx_lock);
- tulip_init_ring(dev);
-
- /* This is set_rx_mode(), but without starting the transmitter. */
- /* Fill the whole address filter table with our physical address. */
- {
- u16 *eaddrs = (u16 *)dev->dev_addr;
- u32 *setup_frm = tp->setup_frame, i;
-
- /* You must add the broadcast address when doing perfect filtering! */
- *setup_frm++ = 0xffff;
- *setup_frm++ = 0xffff;
- *setup_frm++ = 0xffff;
- /* Fill the rest of the accept table with our physical address. */
- for (i = 1; i < 16; i++) {
- *setup_frm++ = eaddrs[0];
- *setup_frm++ = eaddrs[1];
- *setup_frm++ = eaddrs[2];
+ if (tp->flags & MC_HASH_ONLY) {
+ u32 addr_low = cpu_to_le32(get_unaligned((u32 *)dev->dev_addr));
+ u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(dev->dev_addr+4)));
+ if (tp->chip_id == AX88140) {
+ outl(0, ioaddr + CSR13);
+ outl(addr_low, ioaddr + CSR14);
+ outl(1, ioaddr + CSR13);
+ outl(addr_high, ioaddr + CSR14);
+ } else if (tp->chip_id == COMET) {
+ outl(addr_low, ioaddr + 0xA4);
+ outl(addr_high, ioaddr + 0xA8);
+ outl(0, ioaddr + 0xAC);
+ outl(0, ioaddr + 0xB0);
}
+ } else {
+ /* This is set_rx_mode(), but without starting the transmitter. */
+ u16 *eaddrs = (u16 *)dev->dev_addr;
+ u16 *setup_frm = &tp->setup_frame[15*6];
+
+ /* 21140 bug: you must add the broadcast address. */
+ memset(tp->setup_frame, 0xff, sizeof(tp->setup_frame));
+ /* Fill the final entry of the table with our physical address. */
+ *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];
+ *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];
+ *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];
/* Put the setup frame on the Tx list. */
- tp->tx_ring[0].length = 0x08000000 | 192;
- tp->tx_ring[0].buffer1 = virt_to_bus(tp->setup_frame);
- tp->tx_ring[0].status = 0x80000000;
+ tp->tx_ring[0].length = cpu_to_le32(0x08000000 | 192);
+ tp->tx_ring[0].buffer1 = virt_to_le32desc(tp->setup_frame);
+ tp->tx_ring[0].status = cpu_to_le32(DescOwned);
tp->cur_tx++;
}
@@ -1255,13 +1011,12 @@ tulip_open(struct net_device *dev)
outl(virt_to_bus(tp->rx_ring), ioaddr + CSR3);
outl(virt_to_bus(tp->tx_ring), ioaddr + CSR4);
+ tp->saved_if_port = dev->if_port;
if (dev->if_port == 0)
dev->if_port = tp->default_port;
- if (tp->chip_id == DC21041 && dev->if_port > 4)
- /* Invalid: Select initial TP, autosense, autonegotiate. */
- dev->if_port = 4;
/* Allow selecting a default media. */
+ i = 0;
if (tp->mtable == NULL)
goto media_picked;
if (dev->if_port) {
@@ -1274,42 +1029,91 @@ tulip_open(struct net_device *dev)
goto media_picked;
}
}
- if ((tp->mtable->defaultmedia & 0x0800) == 0)
+ if ((tp->mtable->defaultmedia & 0x0800) == 0) {
+ int looking_for = tp->mtable->defaultmedia & 15;
for (i = 0; i < tp->mtable->leafcount; i++)
- if (tp->mtable->mleaf[i].media == (tp->mtable->defaultmedia & 15)) {
- printk(KERN_INFO "%s: Using EEPROM-set media %s.\n",
- dev->name, medianame[tp->mtable->mleaf[i].media]);
- goto media_picked;
- }
+ if (tp->mtable->mleaf[i].media == looking_for) {
+ printk(KERN_INFO "%s: Using EEPROM-set media %s.\n",
+ dev->name, medianame[looking_for]);
+ goto media_picked;
+ }
+ }
/* Start sensing first non-full-duplex media. */
for (i = tp->mtable->leafcount - 1;
(media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--)
- ;
+ ;
media_picked:
tp->csr6 = 0;
tp->cur_index = i;
+ tp->nwayset = 0;
+ if (dev->if_port == 0 && tp->chip_id == DC21041) {
+ tp->nway = 1;
+ }
if (dev->if_port == 0 && tp->chip_id == DC21142) {
- tp->csr6 = 0x82420200;
- outl(0x0003FFFF, ioaddr + CSR14);
+ if (tp->mii_cnt) {
+ select_media(dev, 1);
+ if (tulip_debug > 1)
+ printk(KERN_INFO "%s: Using MII transceiver %d, status "
+ "%4.4x.\n",
+ dev->name, tp->phys[0], mdio_read(dev, tp->phys[0], 1));
+ outl_CSR6(tp, 0x82020000);
+ tp->csr6 = 0x820E0000;
+ dev->if_port = 11;
+ outl(0x0000, ioaddr + CSR13);
+ outl(0x0000, ioaddr + CSR14);
+ } else
+ t21142_start_nway(dev);
+ } else if (tp->chip_id == PNIC2) {
+ t21142_start_nway(dev);
+ } else if (tp->chip_id == LC82C168 && ! tp->medialock) {
+ if (tp->mii_cnt) {
+ dev->if_port = 11;
+ tp->csr6 = 0x814C0000 | (tp->full_duplex ? 0x0200 : 0);
+ outl(0x0001, ioaddr + CSR15);
+ } else if (inl(ioaddr + CSR5) & TPLnkPass)
+ pnic_do_nway(dev);
+ else {
+ /* Start with 10mbps to do autonegotiation. */
+ outl(0x32, ioaddr + CSR12);
+ tp->csr6 = 0x00420000;
+ outl(0x0001B078, ioaddr + 0xB8);
+ outl(0x0201B078, ioaddr + 0xB8);
+ next_tick = 1*HZ;
+ }
+ } else if ((tp->chip_id == MX98713 || tp->chip_id == COMPEX9881)
+ && ! tp->medialock) {
+ dev->if_port = 0;
+ tp->csr6 = 0x01880000 | (tp->full_duplex ? 0x0200 : 0);
+ outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
+ } else if (tp->chip_id == MX98715 || tp->chip_id == MX98725) {
+ /* Provided by BOLO, Macronix - 12/10/1998. */
+ dev->if_port = 0;
+ tp->csr6 = 0x01a80200;
+ outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
+ outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0);
+ } else if (tp->chip_id == DC21143 &&
+ media_cap[dev->if_port] & MediaIsMII) {
+ /* We must reset the media CSRs when we force-select MII mode. */
+ outl(0x0000, ioaddr + CSR13);
+ outl(0x0000, ioaddr + CSR14);
outl(0x0008, ioaddr + CSR15);
- outl(0x0001, ioaddr + CSR13);
- outl(0x1301, ioaddr + CSR12);
- } else if (tp->chip_id == LC82C168 && tp->mii_cnt && ! tp->medialock) {
- dev->if_port = 11;
- tp->csr6 = 0x816C0000 | (tp->full_duplex ? 0x0200 : 0);
- outl(0x0001, ioaddr + CSR15);
+ } else if (tp->chip_id == COMET) {
+ dev->if_port = 0;
+ tp->csr6 = 0x00040000;
+ } else if (tp->chip_id == AX88140) {
+ tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100;
} else
select_media(dev, 1);
/* Start the chip's Tx to process setup frame. */
- outl(tp->csr6, ioaddr + CSR6);
- outl(tp->csr6 | 0x2000, ioaddr + CSR6);
+ outl_CSR6(tp, tp->csr6);
+ outl_CSR6(tp, tp->csr6 | 0x2000);
/* Enable interrupts by setting the interrupt mask. */
outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5);
outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
- outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+ outl_CSR6(tp, tp->csr6 | 0x2002);
outl(0, ioaddr + CSR2); /* Rx poll demand */
if (tulip_debug > 2) {
@@ -1320,16 +1124,33 @@ media_picked:
/* Set the timer to switch to check for link beat and perhaps switch
to an alternate media type. */
init_timer(&tp->timer);
- tp->timer.expires = RUN_AT(5*HZ);
+ tp->timer.expires = RUN_AT(next_tick);
tp->timer.data = (unsigned long)dev;
tp->timer.function = tulip_tbl[tp->chip_id].media_timer;
add_timer(&tp->timer);
- netif_start_queue(dev);
+ netif_device_attach(dev);
+}
+
+static int
+tulip_open(struct net_device *dev)
+{
+ MOD_INC_USE_COUNT;
+
+ if (request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev)) {
+ MOD_DEC_USE_COUNT;
+ return -EBUSY;
+ }
+
+ tulip_init_ring (dev);
+
+ tulip_up (dev);
+
return 0;
}
+
/* Set up the transceiver control registers for the selected media type. */
static void select_media(struct net_device *dev, int startup)
{
@@ -1337,7 +1158,7 @@ static void select_media(struct net_device *dev, int startup)
struct tulip_private *tp = (struct tulip_private *)dev->priv;
struct mediatable *mtable = tp->mtable;
u32 new_csr6;
- int check_mii =0, i;
+ int i;
if (mtable) {
struct medialeaf *mleaf = &mtable->mleaf[tp->cur_index];
@@ -1355,33 +1176,56 @@ static void select_media(struct net_device *dev, int startup)
new_csr6 = 0x02000000 | ((p[2] & 0x71) << 18);
break;
case 2: case 4: {
- u16 setup[3];
- for (i = 0; i < 3; i++)
+ u16 setup[5];
+ u32 csr13val, csr14val, csr15dir, csr15val;
+ for (i = 0; i < 5; i++)
setup[i] = get_u16(&p[i*2 + 1]);
dev->if_port = p[0] & 15;
+ if (media_cap[dev->if_port] & MediaAlwaysFD)
+ tp->full_duplex = 1;
+
+ if (startup && mtable->has_reset) {
+ struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset];
+ unsigned char *rst = rleaf->leafdata;
+ if (tulip_debug > 1)
+ printk(KERN_DEBUG "%s: Resetting the transceiver.\n",
+ dev->name);
+ for (i = 0; i < rst[0]; i++)
+ outl(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15);
+ }
if (tulip_debug > 1)
- printk(KERN_DEBUG "%s: 21142 non-MII %s transceiver control %4.4x/%4.4x.\n",
+ printk(KERN_DEBUG "%s: 21143 non-MII %s transceiver control "
+ "%4.4x/%4.4x.\n",
dev->name, medianame[dev->if_port], setup[0], setup[1]);
if (p[0] & 0x40) { /* SIA (CSR13-15) setup values are provided. */
+ csr13val = setup[0];
+ csr14val = setup[1];
+ csr15dir = (setup[3]<<16) | setup[2];
+ csr15val = (setup[4]<<16) | setup[2];
outl(0, ioaddr + CSR13);
- outl(setup[1], ioaddr + CSR14);
- outl(setup[2], ioaddr + CSR15);
- outl(setup[0], ioaddr + CSR13);
- for (i = 0; i < 3; i++) /* Re-fill setup[] */
- setup[i] = get_u16(&p[i*2 + 7]);
- } else if (dev->if_port <= 4) {
- outl(0, ioaddr + CSR13);
- outl(t21142_csr14[dev->if_port], ioaddr + CSR14);
- outl(t21142_csr15[dev->if_port], ioaddr + CSR15);
- outl(t21142_csr13[dev->if_port], ioaddr + CSR13);
+ outl(csr14val, ioaddr + CSR14);
+ outl(csr15dir, ioaddr + CSR15); /* Direction */
+ outl(csr15val, ioaddr + CSR15); /* Data */
+ outl(csr13val, ioaddr + CSR13);
} else {
- outl(0, ioaddr + CSR14);
- outl(8, ioaddr + CSR15);
- outl(0, ioaddr + CSR13);
+ csr13val = 1;
+ csr14val = 0x0003FF7F;
+ csr15dir = (setup[0]<<16) | 0x0008;
+ csr15val = (setup[1]<<16) | 0x0008;
+ if (dev->if_port <= 4)
+ csr14val = t21142_csr14[dev->if_port];
+ if (startup) {
+ outl(0, ioaddr + CSR13);
+ outl(csr14val, ioaddr + CSR14);
+ }
+ outl(csr15dir, ioaddr + CSR15); /* Direction */
+ outl(csr15val, ioaddr + CSR15); /* Data */
+ if (startup) outl(csr13val, ioaddr + CSR13);
}
- outl(setup[0]<<16, ioaddr + CSR15); /* Direction */
- outl(setup[1]<<16, ioaddr + CSR15); /* Data */
+ if (tulip_debug > 1)
+ printk(KERN_DEBUG "%s: Setting CSR15 to %8.8x/%8.8x.\n",
+ dev->name, csr15dir, csr15val);
if (mleaf->type == 4)
new_csr6 = 0x82020000 | ((setup[2] & 0x71) << 18);
else
@@ -1395,7 +1239,6 @@ static void select_media(struct net_device *dev, int startup)
u16 to_advertise;
dev->if_port = 11;
- check_mii = 1;
new_csr6 = 0x020E0000;
if (mleaf->type == 3) { /* 21142 */
u16 *init_sequence = (u16*)(p+2);
@@ -1422,7 +1265,7 @@ static void select_media(struct net_device *dev, int startup)
}
to_advertise = (get_u16(&misc_info[1]) & tp->to_advertise) | 1;
tp->advertising[phy_num] = to_advertise;
- if (tulip_debug > 1 || 1)
+ if (tulip_debug > 1)
printk(KERN_DEBUG "%s: Advertising %4.4x on PHY %d (%d).\n",
dev->name, to_advertise, phy_num, tp->phys[phy_num]);
/* Bogus: put in by a committee? */
@@ -1430,32 +1273,33 @@ static void select_media(struct net_device *dev, int startup)
break;
}
default:
- new_csr6 = 0x020E0000;
+ printk(KERN_DEBUG "%s: Invalid media table selection %d.\n",
+ dev->name, mleaf->type);
+ new_csr6 = 0x020E0000;
}
if (tulip_debug > 1)
printk(KERN_DEBUG "%s: Using media type %s, CSR12 is %2.2x.\n",
dev->name, medianame[dev->if_port],
inl(ioaddr + CSR12) & 0xff);
} else if (tp->chip_id == DC21041) {
+ int port = dev->if_port <= 4 ? dev->if_port : 0;
if (tulip_debug > 1)
printk(KERN_DEBUG "%s: 21041 using media %s, CSR12 is %4.4x.\n",
- dev->name, medianame[dev->if_port & 15],
- inl(ioaddr + CSR12) & 0xffff);
+ dev->name, medianame[port == 3 ? 12: port],
+ inl(ioaddr + CSR12));
outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */
- outl(t21041_csr14[dev->if_port], ioaddr + CSR14);
- outl(t21041_csr15[dev->if_port], ioaddr + CSR15);
- outl(t21041_csr13[dev->if_port], ioaddr + CSR13);
+ outl(t21041_csr14[port], ioaddr + CSR14);
+ outl(t21041_csr15[port], ioaddr + CSR15);
+ outl(t21041_csr13[port], ioaddr + CSR13);
new_csr6 = 0x80020000;
} else if (tp->chip_id == LC82C168) {
if (startup && ! tp->medialock)
dev->if_port = tp->mii_cnt ? 11 : 0;
if (tulip_debug > 1)
- printk(KERN_DEBUG "%s: PNIC PHY status is %3.3x, CSR12 %4.4x,"
- " media %s.\n",
- dev->name, inl(ioaddr + 0xB8), inl(ioaddr + CSR12),
- medianame[dev->if_port]);
+ printk(KERN_DEBUG "%s: PNIC PHY status is %3.3x, media %s.\n",
+ dev->name, inl(ioaddr + 0xB8), medianame[dev->if_port]);
if (tp->mii_cnt) {
- new_csr6 = 0x812C0000;
+ new_csr6 = 0x810C0000;
outl(0x0001, ioaddr + CSR15);
outl(0x0201B07A, ioaddr + 0xB8);
} else if (startup) {
@@ -1467,10 +1311,8 @@ static void select_media(struct net_device *dev, int startup)
} else if (dev->if_port == 3 || dev->if_port == 5) {
outl(0x33, ioaddr + CSR12);
new_csr6 = 0x01860000;
- if (startup)
- outl(0x0201F868, ioaddr + 0xB8); /* Trigger autonegotiation. */
- else
- outl(0x1F868, ioaddr + 0xB8);
+ /* Trigger autonegotiation. */
+ outl(startup ? 0x0201F868 : 0x0001F868, ioaddr + 0xB8);
} else {
outl(0x32, ioaddr + CSR12);
new_csr6 = 0x00420000;
@@ -1481,20 +1323,24 @@ static void select_media(struct net_device *dev, int startup)
int csr12 = inl(ioaddr + CSR12);
if (tulip_debug > 1)
printk(KERN_DEBUG "%s: 21040 media type is %s, CSR12 is %2.2x.\n",
- dev->name, dev->if_port ? "AUI" : "10baseT", csr12);
- new_csr6 = (dev->if_port ? 0x01860000 : 0x00420000);
+ dev->name, medianame[dev->if_port], csr12);
+ if (media_cap[dev->if_port] & MediaAlwaysFD)
+ tp->full_duplex = 1;
+ new_csr6 = 0x20000;
/* Set the full duplux match frame. */
outl(FULL_DUPLEX_MAGIC, ioaddr + CSR11);
outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */
- outl(dev->if_port ? 0x0000000C : 0x00000004, ioaddr + CSR13);
+ if (t21040_csr13[dev->if_port] & 8) {
+ outl(0x0705, ioaddr + CSR14);
+ outl(0x0006, ioaddr + CSR15);
+ } else {
+ outl(0xffff, ioaddr + CSR14);
+ outl(0x0000, ioaddr + CSR15);
+ }
+ outl(0x8f01 | t21040_csr13[dev->if_port], ioaddr + CSR13);
} else { /* Unknown chip type with no media table. */
if (tp->default_port == 0)
- {
- if (tp->mii_cnt)
- dev->if_port = 11;
- else
- dev->if_port = 3;
- }
+ dev->if_port = tp->mii_cnt ? 11 : 3;
if (media_cap[dev->if_port] & MediaIsMII) {
new_csr6 = 0x020E0000;
} else if (media_cap[dev->if_port] & MediaIsFx) {
@@ -1512,28 +1358,79 @@ static void select_media(struct net_device *dev, int startup)
return;
}
+/*
+ Check the MII negotiated duplex, and change the CSR6 setting if
+ required.
+ Return 0 if everything is OK.
+ Return < 0 if the transceiver is missing or has no link beat.
+ */
+static int check_duplex(struct net_device *dev)
+{
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ int mii_reg1, mii_reg5, negotiated, duplex;
+
+ if (tp->full_duplex_lock)
+ return 0;
+ mii_reg1 = mdio_read(dev, tp->phys[0], 1);
+ mii_reg5 = mdio_read(dev, tp->phys[0], 5);
+ if (tulip_debug > 1)
+ printk(KERN_INFO "%s: MII status %4.4x, Link partner report "
+ "%4.4x.\n", dev->name, mii_reg1, mii_reg5);
+ if (mii_reg1 == 0xffff)
+ return -2;
+ if ((mii_reg1 & 0x0004) == 0) {
+ int new_reg1 = mdio_read(dev, tp->phys[0], 1);
+ if ((new_reg1 & 0x0004) == 0) {
+ if (tulip_debug > 1)
+ printk(KERN_INFO "%s: No link beat on the MII interface,"
+ " status %4.4x.\n", dev->name, new_reg1);
+ return -1;
+ }
+ }
+ negotiated = mii_reg5 & tp->advertising[0];
+ duplex = ((negotiated & 0x0300) == 0x0100
+ || (negotiated & 0x00C0) == 0x0040);
+ /* 100baseTx-FD or 10T-FD, but not 100-HD */
+ if (tp->full_duplex != duplex) {
+ tp->full_duplex = duplex;
+ if (negotiated & 0x038) /* 100mbps. */
+ tp->csr6 &= ~0x00400000;
+ if (tp->full_duplex) tp->csr6 |= 0x0200;
+ else tp->csr6 &= ~0x0200;
+ outl_CSR6(tp, tp->csr6 | 0x0002);
+ outl_CSR6(tp, tp->csr6 | 0x2002);
+ if (tulip_debug > 0)
+ printk(KERN_INFO "%s: Setting %s-duplex based on MII"
+ "#%d link partner capability of %4.4x.\n",
+ dev->name, tp->full_duplex ? "full" : "half",
+ tp->phys[0], mii_reg5);
+ return 1;
+ }
+ return 0;
+}
+
static void tulip_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
long ioaddr = dev->base_addr;
u32 csr12 = inl(ioaddr + CSR12);
- int next_tick = 0;
+ int next_tick = 2*HZ;
- if (tulip_debug > 3) {
- printk(KERN_DEBUG "%s: Media selection tick, status %8.8x mode %8.8x "
- "SIA %8.8x %8.8x %8.8x %8.8x.\n",
- dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR6),
- csr12, inl(ioaddr + CSR13),
+ if (tulip_debug > 2) {
+ printk(KERN_DEBUG "%s: Media selection tick, %s, status %8.8x mode"
+ " %8.8x SIA %8.8x %8.8x %8.8x %8.8x.\n",
+ dev->name, medianame[dev->if_port], inl(ioaddr + CSR5),
+ inl(ioaddr + CSR6), csr12, inl(ioaddr + CSR13),
inl(ioaddr + CSR14), inl(ioaddr + CSR15));
}
switch (tp->chip_id) {
case DC21040:
- if (csr12 & 0x0002) { /* Network error */
- printk(KERN_INFO "%s: No 10baseT link beat found, switching to %s media.\n",
- dev->name, dev->if_port ? "10baseT" : "AUI");
- dev->if_port ^= 1;
- outl(dev->if_port ? 0x0000000C : 0x00000004, ioaddr + CSR13);
+ if (!tp->medialock && csr12 & 0x0002) { /* Network error */
+ printk(KERN_INFO "%s: No link beat found.\n",
+ dev->name);
+ dev->if_port = (dev->if_port == 2 ? 0 : 2);
+ select_media(dev, 0);
dev->trans_start = jiffies;
}
break;
@@ -1541,6 +1438,7 @@ static void tulip_timer(unsigned long data)
if (tulip_debug > 2)
printk(KERN_DEBUG "%s: 21041 media tick CSR12 %8.8x.\n",
dev->name, csr12);
+ if (tp->medialock) break;
switch (dev->if_port) {
case 0: case 3: case 4:
if (csr12 & 0x0004) { /*LnkFail */
@@ -1562,25 +1460,26 @@ static void tulip_timer(unsigned long data)
break;
case 1: /* 10base2 */
case 2: /* AUI */
- if (csr12 & 0x0100) {
- next_tick = (30*HZ); /* 30 sec. */
- tp->mediasense = 0;
- } else if ((csr12 & 0x0004) == 0) {
- printk(KERN_INFO "%s: 21041 media switched to 10baseT.\n", dev->name);
- dev->if_port = 0;
- select_media(dev, 0);
- next_tick = (24*HZ)/10; /* 2.4 sec. */
- } else if (tp->mediasense || (csr12 & 0x0002)) {
- dev->if_port = 3 - dev->if_port; /* Swap ports. */
- select_media(dev, 0);
- next_tick = 20*HZ;
- } else {
- next_tick = 20*HZ;
- }
- break;
+ if (csr12 & 0x0100) {
+ next_tick = (30*HZ); /* 30 sec. */
+ tp->mediasense = 0;
+ } else if ((csr12 & 0x0004) == 0) {
+ printk(KERN_INFO "%s: 21041 media switched to 10baseT.\n",
+ dev->name);
+ dev->if_port = 0;
+ select_media(dev, 0);
+ next_tick = (24*HZ)/10; /* 2.4 sec. */
+ } else if (tp->mediasense || (csr12 & 0x0002)) {
+ dev->if_port = 3 - dev->if_port; /* Swap ports. */
+ select_media(dev, 0);
+ next_tick = 20*HZ;
+ } else {
+ next_tick = 20*HZ;
+ }
+ break;
}
break;
- case DC21140: case DC21142: case MX98713: default: {
+ case DC21140: case DC21142: case MX98713: case COMPEX9881: default: {
struct medialeaf *mleaf;
unsigned char *p;
if (tp->mtable == NULL) { /* No EEPROM info, use generic code. */
@@ -1644,58 +1543,16 @@ static void tulip_timer(unsigned long data)
medianame[tp->mtable->mleaf[tp->cur_index].media]);
select_media(dev, 0);
/* Restart the transmit process. */
- outl(tp->csr6 | 0x0002, ioaddr + CSR6);
- outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+ outl_CSR6(tp, tp->csr6 | 0x0002);
+ outl_CSR6(tp, tp->csr6 | 0x2002);
next_tick = (24*HZ)/10;
break;
}
- case 1: case 3: { /* 21140, 21142 MII */
- int mii_reg1, mii_reg5;
+ case 1: case 3: /* 21140, 21142 MII */
actually_mii:
- mii_reg1 = mdio_read(dev, tp->phys[0], 1);
- mii_reg5 = mdio_read(dev, tp->phys[0], 5);
- if (tulip_debug > 1)
- printk(KERN_INFO "%s: MII status %4.4x, Link partner report "
- "%4.4x, CSR12 %2.2x, %cD.\n",
- dev->name, mii_reg1, mii_reg5, csr12,
- tp->full_duplex ? 'F' : 'H');
- if (mii_reg1 != 0xffff && (mii_reg1 & 0x0004) == 0) {
- int new_reg1 = mdio_read(dev, tp->phys[0], 1);
- if ((new_reg1 & 0x0004) == 0) {
- printk(KERN_INFO "%s: No link beat on the MII interface,"
- " status then %4.4x now %4.4x.\n",
- dev->name, mii_reg1, new_reg1);
- if (tp->mtable && tp->mtable->has_nonmii)
- goto select_next_media;
- }
- }
- if (mii_reg5 == 0xffff || mii_reg5 == 0x0000)
- ; /* No MII device or no link partner report */
- else if (tp->full_duplex_lock)
- ;
- else {
- int negotiated = mii_reg5 & tp->advertising[0];
- int duplex = ((negotiated & 0x0100) != 0
- || (negotiated & 0x00C0) == 0x0040);
- /* 100baseTx-FD or 10T-FD, but not 100-HD */
- if (tp->full_duplex != duplex) {
- tp->full_duplex = duplex;
- if (tp->full_duplex)
- tp->csr6 |= 0x0200;
- else
- tp->csr6 &= ~0x0200;
- outl(tp->csr6 | 0x0002, ioaddr + CSR6);
- outl(tp->csr6 | 0x2002, ioaddr + CSR6);
- if (tulip_debug > 0) /* Gurppp, should be >1 */
- printk(KERN_INFO "%s: Setting %s-duplex based on MII"
- " Xcvr #%d parter capability of %4.4x.\n",
- dev->name, tp->full_duplex ? "full" : "half",
- tp->phys[0], mii_reg5);
- }
- }
+ check_duplex(dev);
next_tick = 60*HZ;
break;
- }
case 2: /* 21142 serial block has no link beat. */
default:
break;
@@ -1703,12 +1560,11 @@ static void tulip_timer(unsigned long data)
}
break;
}
- if (next_tick) {
- tp->timer.expires = RUN_AT(next_tick);
- add_timer(&tp->timer);
- }
+ tp->timer.expires = RUN_AT(next_tick);
+ add_timer(&tp->timer);
}
+
/* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list
of available transceivers. */
static void t21142_timer(unsigned long data)
@@ -1720,111 +1576,204 @@ static void t21142_timer(unsigned long data)
int next_tick = 60*HZ;
int new_csr6 = 0;
- if (tulip_debug > 1)
- printk(KERN_INFO"%s: 21142 negotiation status %8.8x, %s.\n",
+ if (tulip_debug > 2)
+ printk(KERN_INFO"%s: 21143 negotiation status %8.8x, %s.\n",
dev->name, csr12, medianame[dev->if_port]);
- if (dev->if_port == 3) {
- if (csr12 & 2) { /* No 100mbps link beat, revert to 10mbps. */
- new_csr6 = 0x82420200;
- outl(new_csr6, ioaddr + CSR6);
- outl(0x0000, ioaddr + CSR13);
- outl(0x0003FFFF, ioaddr + CSR14);
- outl(0x0008, ioaddr + CSR15);
- outl(0x0001, ioaddr + CSR13);
- outl(0x1301, ioaddr + CSR12); /* Start NWay. */
+ if (media_cap[dev->if_port] & MediaIsMII) {
+ check_duplex(dev);
+ next_tick = 60*HZ;
+ } else if (tp->nwayset) {
+ /* Don't screw up a negotiated session! */
+ if (tulip_debug > 1)
+ printk(KERN_INFO"%s: Using NWay-set %s media, csr12 %8.8x.\n",
+ dev->name, medianame[dev->if_port], csr12);
+ } else if (tp->medialock) {
+ ;
+ } else if (dev->if_port == 3) {
+ if (csr12 & 2) { /* No 100mbps link beat, revert to 10mbps. */
+ if (tulip_debug > 1)
+ printk(KERN_INFO"%s: No 21143 100baseTx link beat, %8.8x, "
+ "trying NWay.\n", dev->name, csr12);
+ t21142_start_nway(dev);
+ next_tick = 3*HZ;
}
} else if ((csr12 & 0x7000) != 0x5000) {
/* Negotiation failed. Search media types. */
if (tulip_debug > 1)
- printk(KERN_INFO"%s: 21142 negotiation failed, status %8.8x.\n",
+ printk(KERN_INFO"%s: 21143 negotiation failed, status %8.8x.\n",
dev->name, csr12);
if (!(csr12 & 4)) { /* 10mbps link beat good. */
new_csr6 = 0x82420000;
dev->if_port = 0;
outl(0, ioaddr + CSR13);
outl(0x0003FFFF, ioaddr + CSR14);
- outl(t21142_csr15[dev->if_port], ioaddr + CSR15);
+ outw(t21142_csr15[dev->if_port], ioaddr + CSR15);
outl(t21142_csr13[dev->if_port], ioaddr + CSR13);
- } else if (csr12 & 0x100) {
- new_csr6 = 0x82420200;
- dev->if_port = 2;
- outl(0, ioaddr + CSR13);
- outl(0x0003FFFF, ioaddr + CSR14);
- outl(0x0008, ioaddr + CSR15);
- outl(0x0001, ioaddr + CSR13);
} else {
/* Select 100mbps port to check for link beat. */
new_csr6 = 0x83860000;
dev->if_port = 3;
outl(0, ioaddr + CSR13);
outl(0x0003FF7F, ioaddr + CSR14);
- outl(8, ioaddr + CSR15);
+ outw(8, ioaddr + CSR15);
outl(1, ioaddr + CSR13);
}
if (tulip_debug > 1)
- printk(KERN_INFO"%s: Testing new 21142 media %s.\n",
+ printk(KERN_INFO"%s: Testing new 21143 media %s.\n",
dev->name, medianame[dev->if_port]);
if (new_csr6 != (tp->csr6 & ~0x00D5)) {
tp->csr6 &= 0x00D5;
tp->csr6 |= new_csr6;
outl(0x0301, ioaddr + CSR12);
- outl(tp->csr6 | 0x0002, ioaddr + CSR6);
- outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+ outl_CSR6(tp, tp->csr6 | 0x0002);
+ outl_CSR6(tp, tp->csr6 | 0x2002);
}
+ next_tick = 3*HZ;
}
+
tp->timer.expires = RUN_AT(next_tick);
add_timer(&tp->timer);
}
-static void t21142_lnk_change( struct net_device *dev)
+
+static void t21142_start_nway(struct net_device *dev)
+{
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ int csr14 = ((tp->to_advertise & 0x0780) << 9) |
+ ((tp->to_advertise&0x0020)<<1) | 0xffbf;
+
+ dev->if_port = 0;
+ tp->nway = tp->mediasense = 1;
+ tp->nwayset = tp->lpar = 0;
+ if (debug > 1)
+ printk(KERN_DEBUG "%s: Restarting 21143 autonegotiation, %8.8x.\n",
+ dev->name, csr14);
+ outl(0x0001, ioaddr + CSR13);
+ outl(csr14, ioaddr + CSR14);
+ tp->csr6 = 0x82420000 | (tp->to_advertise & 0x0040 ? 0x0200 : 0);
+ outl_CSR6(tp, tp->csr6);
+ if (tp->mtable && tp->mtable->csr15dir) {
+ outl(tp->mtable->csr15dir, ioaddr + CSR15);
+ outl(tp->mtable->csr15val, ioaddr + CSR15);
+ } else
+ outw(0x0008, ioaddr + CSR15);
+ outl(0x1301, ioaddr + CSR12); /* Trigger NWAY. */
+}
+
+
+static void t21142_lnk_change(struct net_device *dev, int csr5)
{
struct tulip_private *tp = (struct tulip_private *)dev->priv;
long ioaddr = dev->base_addr;
int csr12 = inl(ioaddr + CSR12);
if (tulip_debug > 1)
- printk(KERN_INFO"%s: 21142 link status interrupt %8.8x, CSR5 %x.\n",
- dev->name, csr12, inl(ioaddr + CSR5));
-
- if ((csr12 & 0x7000) == 0x5000) {
- if (csr12 & 0x01800000) {
- /* Switch to 100mbps mode. */
- outl(tp->csr6 | 0x0002, ioaddr + CSR6);
- if (csr12 & 0x01000000) {
- dev->if_port = 5;
- tp->csr6 = 0x83860200;
- } else {
+ printk(KERN_INFO"%s: 21143 link status interrupt %8.8x, CSR5 %x, "
+ "%8.8x.\n", dev->name, csr12, csr5, inl(ioaddr + CSR14));
+
+ /* If NWay finished and we have a negotiated partner capability. */
+ if (tp->nway && !tp->nwayset && (csr12 & 0x7000) == 0x5000) {
+ int setup_done = 0;
+ int negotiated = tp->to_advertise & (csr12 >> 16);
+ tp->lpar = csr12 >> 16;
+ tp->nwayset = 1;
+ if (negotiated & 0x0100) dev->if_port = 5;
+ else if (negotiated & 0x0080) dev->if_port = 3;
+ else if (negotiated & 0x0040) dev->if_port = 4;
+ else if (negotiated & 0x0020) dev->if_port = 0;
+ else {
+ tp->nwayset = 0;
+ if ((csr12 & 2) == 0 && (tp->to_advertise & 0x0180))
dev->if_port = 3;
- tp->csr6 = 0x83860000;
- }
- outl(tp->csr6 | 0x2002, ioaddr + CSR6);
- } /* Else 10baseT-FD is handled automatically. */
- } else if (dev->if_port == 3) {
- if (!(csr12 & 2))
- printk(KERN_INFO"%s: 21142 100baseTx link beat good.\n",
- dev->name);
- else
- dev->if_port = 0;
- } else if (dev->if_port == 0) {
- if (!(csr12 & 4))
- printk(KERN_INFO"%s: 21142 10baseT link beat good.\n",
+ }
+ tp->full_duplex = (media_cap[dev->if_port] & MediaAlwaysFD) ? 1:0;
+
+ if (tulip_debug > 1) {
+ if (tp->nwayset)
+ printk(KERN_INFO "%s: Switching to %s based on link "
+ "negotiation %4.4x & %4.4x = %4.4x.\n",
+ dev->name, medianame[dev->if_port], tp->to_advertise,
+ tp->lpar, negotiated);
+ else
+ printk(KERN_INFO "%s: Autonegotiation failed, using %s,"
+ " link beat status %4.4x.\n",
+ dev->name, medianame[dev->if_port], csr12);
+ }
+
+ if (tp->mtable) {
+ int i;
+ for (i = 0; i < tp->mtable->leafcount; i++)
+ if (tp->mtable->mleaf[i].media == dev->if_port) {
+ tp->cur_index = i;
+ select_media(dev, 0);
+ setup_done = 1;
+ break;
+ }
+ }
+ if ( ! setup_done) {
+ tp->csr6 = dev->if_port & 1 ? 0x83860000 : 0x82420000;
+ if (tp->full_duplex)
+ tp->csr6 |= 0x0200;
+ outl(1, ioaddr + CSR13);
+ }
+#if 0 /* Restart shouldn't be needed. */
+ outl_CSR6(tp, tp->csr6 | 0x0000);
+ if (debug > 2)
+ printk(KERN_DEBUG "%s: Restarting Tx and Rx, CSR5 is %8.8x.\n",
+ dev->name, inl(ioaddr + CSR5));
+#endif
+ outl_CSR6(tp, tp->csr6 | 0x2002);
+ if (debug > 2)
+ printk(KERN_DEBUG "%s: Setting CSR6 %8.8x/%x CSR12 %8.8x.\n",
+ dev->name, tp->csr6, inl(ioaddr + CSR6),
+ inl(ioaddr + CSR12));
+ } else if ((tp->nwayset && (csr5 & 0x08000000)
+ && (dev->if_port == 3 || dev->if_port == 5)
+ && (csr12 & 2) == 2) ||
+ (tp->nway && (csr5 & (TPLnkFail)))) {
+ /* Link blew? Maybe restart NWay. */
+ del_timer(&tp->timer);
+ t21142_start_nway(dev);
+ tp->timer.expires = RUN_AT(3*HZ);
+ add_timer(&tp->timer);
+ } else if (dev->if_port == 3 || dev->if_port == 5) {
+ if (tulip_debug > 1)
+ printk(KERN_INFO"%s: 21143 %s link beat %s.\n",
+ dev->name, medianame[dev->if_port],
+ (csr12 & 2) ? "failed" : "good");
+ if ((csr12 & 2) && ! tp->medialock) {
+ del_timer(&tp->timer);
+ t21142_start_nway(dev);
+ tp->timer.expires = RUN_AT(3*HZ);
+ add_timer(&tp->timer);
+ }
+ } else if (dev->if_port == 0 || dev->if_port == 4) {
+ if ((csr12 & 4) == 0)
+ printk(KERN_INFO"%s: 21143 10baseT link beat good.\n",
dev->name);
} else if (!(csr12 & 4)) { /* 10mbps link beat good. */
- printk(KERN_INFO"%s: 21142 10mpbs sensed media.\n",
+ if (tulip_debug)
+ printk(KERN_INFO"%s: 21143 10mbps sensed media.\n",
+ dev->name);
+ dev->if_port = 0;
+ } else if (tp->nwayset) {
+ if (tulip_debug)
+ printk(KERN_INFO"%s: 21143 using NWay-set %s, csr6 %8.8x.\n",
+ dev->name, medianame[dev->if_port], tp->csr6);
+ } else { /* 100mbps link beat good. */
+ if (tulip_debug)
+ printk(KERN_INFO"%s: 21143 100baseTx sensed media.\n",
dev->name);
- dev->if_port = 0;
- } else { /* 100mbps link beat good. */
- printk(KERN_INFO"%s: 21142 100baseTx sensed media.\n",
- dev->name);
dev->if_port = 3;
tp->csr6 = 0x83860000;
outl(0x0003FF7F, ioaddr + CSR14);
outl(0x0301, ioaddr + CSR12);
- outl(tp->csr6 | 0x0002, ioaddr + CSR6);
- outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+ outl_CSR6(tp, tp->csr6 | 0x0002);
+ outl_CSR6(tp, tp->csr6 | 0x2002);
}
}
-
+
static void mxic_timer(unsigned long data)
{
@@ -1843,57 +1792,104 @@ static void mxic_timer(unsigned long data)
}
}
+
+static void pnic_do_nway(struct net_device *dev)
+{
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ u32 phy_reg = inl(ioaddr + 0xB8);
+ u32 new_csr6 = tp->csr6 & ~0x40C40200;
+
+ if (phy_reg & 0x78000000) { /* Ignore baseT4 */
+ if (phy_reg & 0x20000000) dev->if_port = 5;
+ else if (phy_reg & 0x40000000) dev->if_port = 3;
+ else if (phy_reg & 0x10000000) dev->if_port = 4;
+ else if (phy_reg & 0x08000000) dev->if_port = 0;
+ tp->nwayset = 1;
+ new_csr6 = (dev->if_port & 1) ? 0x01860000 : 0x00420000;
+ outl(0x32 | (dev->if_port & 1), ioaddr + CSR12);
+ if (dev->if_port & 1)
+ outl(0x1F868, ioaddr + 0xB8);
+ if (phy_reg & 0x30000000) {
+ tp->full_duplex = 1;
+ new_csr6 |= 0x00000200;
+ }
+ if (tulip_debug > 1)
+ printk(KERN_DEBUG "%s: PNIC autonegotiated status %8.8x, %s.\n",
+ dev->name, phy_reg, medianame[dev->if_port]);
+ if (tp->csr6 != new_csr6) {
+ tp->csr6 = new_csr6;
+ /* Restart Tx */
+ outl_CSR6(tp, tp->csr6 | 0x0002);
+ outl_CSR6(tp, tp->csr6 | 0x2002);
+ dev->trans_start = jiffies;
+ }
+ }
+}
+
+
+static void pnic_lnk_change(struct net_device *dev, int csr5)
+{
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ int phy_reg = inl(ioaddr + 0xB8);
+
+ if (tulip_debug > 1)
+ printk(KERN_DEBUG "%s: PNIC link changed state %8.8x, CSR5 %8.8x.\n",
+ dev->name, phy_reg, csr5);
+ if (inl(ioaddr + CSR5) & TPLnkFail) {
+ outl((inl(ioaddr + CSR7) & ~TPLnkFail) | TPLnkPass, ioaddr + CSR7);
+ if (! tp->nwayset || jiffies - dev->trans_start > 1*HZ) {
+ tp->csr6 = 0x00420000 | (tp->csr6 & 0x0000fdff);
+ outl_CSR6(tp, tp->csr6);
+ outl(0x30, ioaddr + CSR12);
+ outl(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */
+ dev->trans_start = jiffies;
+ }
+ } else if (inl(ioaddr + CSR5) & TPLnkPass) {
+ pnic_do_nway(dev);
+ outl((inl(ioaddr + CSR7) & ~TPLnkPass) | TPLnkFail, ioaddr + CSR7);
+ }
+}
+
+
static void pnic_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
long ioaddr = dev->base_addr;
- int csr12 = inl(ioaddr + CSR12);
int next_tick = 60*HZ;
- int new_csr6 = tp->csr6 & ~0x40C40200;
if (media_cap[dev->if_port] & MediaIsMII) {
- int negotiated = mdio_read(dev, tp->phys[0], 5) & tp->advertising[0];
-
- if (tulip_debug > 1)
- printk(KERN_DEBUG "%s: LC82C168 negotiated capability %8.8x, "
- "CSR5 %8.8x.\n",
- dev->name, negotiated, inl(ioaddr + CSR5));
-
- if (negotiated & 0x0380) /* 10 vs 100mbps */
- new_csr6 |= 0x812E0000;
- else
- new_csr6 |= 0x816E0000;
- if (((negotiated & 0x0300) == 0x0100) /* Duplex */
- || (negotiated & 0x00C0) == 0x0040
- || tp->full_duplex_lock) {
- tp->full_duplex = 1;
- new_csr6 |= 0x0200;
- }
- if (tulip_debug > 1)
- printk(KERN_DEBUG "%s: LC82C168 MII PHY status %4.4x, Link "
- "partner report %4.4x, csr6 %8.8x/%8.8x.\n",
- dev->name, mdio_read(dev, tp->phys[0], 1), negotiated,
- tp->csr6, inl(ioaddr + CSR6));
+ if (check_duplex(dev) > 0)
+ next_tick = 3*HZ;
} else {
+ int csr12 = inl(ioaddr + CSR12);
+ int new_csr6 = tp->csr6 & ~0x40C40200;
int phy_reg = inl(ioaddr + 0xB8);
int csr5 = inl(ioaddr + CSR5);
if (tulip_debug > 1)
- printk(KERN_DEBUG "%s: LC82C168 phy status %8.8x, CSR5 %8.8x.\n",
- dev->name, phy_reg, csr5);
-
+ printk(KERN_DEBUG "%s: PNIC timer PHY status %8.8x, %s "
+ "CSR5 %8.8x.\n",
+ dev->name, phy_reg, medianame[dev->if_port], csr5);
if (phy_reg & 0x04000000) { /* Remote link fault */
- /*outl(0x0201F078, ioaddr + 0xB8);*/
- next_tick = 3*HZ;
- }
- if (inl(ioaddr + CSR5) & TPLnkFail) { /* 100baseTx link beat */
+ outl(0x0201F078, ioaddr + 0xB8);
+ next_tick = 1*HZ;
+ tp->nwayset = 0;
+ } else if (phy_reg & 0x78000000) { /* Ignore baseT4 */
+ pnic_do_nway(dev);
+ next_tick = 60*HZ;
+ } else if (csr5 & TPLnkFail) { /* 100baseTx link beat */
if (tulip_debug > 1)
printk(KERN_DEBUG "%s: %s link beat failed, CSR12 %4.4x, "
"CSR5 %8.8x, PHY %3.3x.\n",
dev->name, medianame[dev->if_port], csr12,
inl(ioaddr + CSR5), inl(ioaddr + 0xB8));
+ next_tick = 3*HZ;
if (tp->medialock) {
+ } else if (tp->nwayset && (dev->if_port & 1)) {
+ next_tick = 1*HZ;
} else if (dev->if_port == 0) {
dev->if_port = 3;
outl(0x33, ioaddr + CSR12);
@@ -1905,125 +1901,145 @@ static void pnic_timer(unsigned long data)
new_csr6 = 0x00420000;
outl(0x1F078, ioaddr + 0xB8);
}
- new_csr6 |= (tp->csr6 & 0xfdff);
- next_tick = 3*HZ;
- } else
- new_csr6 = tp->csr6;
- if (tp->full_duplex_lock || (phy_reg & 0x30000000) != 0) {
- tp->full_duplex = 1;
- new_csr6 |= 0x00000200;
+ if (tp->csr6 != new_csr6) {
+ tp->csr6 = new_csr6;
+ /* Restart Tx */
+ outl_CSR6(tp, tp->csr6 | 0x0002);
+ outl_CSR6(tp, tp->csr6 | 0x2002);
+ dev->trans_start = jiffies;
+ if (tulip_debug > 1)
+ printk(KERN_INFO "%s: Changing PNIC configuration to %s "
+ "%s-duplex, CSR6 %8.8x.\n",
+ dev->name, medianame[dev->if_port],
+ tp->full_duplex ? "full" : "half", new_csr6);
+ }
}
}
- if (tp->csr6 != new_csr6) {
- tp->csr6 = new_csr6;
- outl(tp->csr6 | 0x0002, ioaddr + CSR6); /* Restart Tx */
- outl(tp->csr6 | 0x2002, ioaddr + CSR6);
- dev->trans_start = jiffies;
- if (tulip_debug > 0) /* Gurppp, should be >1 */
- printk(KERN_INFO "%s: Changing PNIC configuration to %s-duplex, "
- "CSR6 %8.8x.\n",
- dev->name, tp->full_duplex ? "full" : "half", new_csr6);
- }
+ tp->timer.expires = RUN_AT(next_tick);
+ add_timer(&tp->timer);
+}
+
+static void comet_timer(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ int next_tick = 60*HZ;
+
+ if (tulip_debug > 1)
+ printk(KERN_DEBUG "%s: Comet link status %4.4x partner capability "
+ "%4.4x.\n",
+ dev->name, inl(ioaddr + 0xB8), inl(ioaddr + 0xC8));
tp->timer.expires = RUN_AT(next_tick);
add_timer(&tp->timer);
}
static void tulip_tx_timeout(struct net_device *dev)
{
- struct tulip_private *tp = (struct tulip_private *)dev->priv;
- long ioaddr = dev->base_addr;
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ long ioaddr = dev->base_addr;
- printk("%s: transmit timed out\n", dev->name);
+ if (media_cap[dev->if_port] & MediaIsMII) {
+ /* Do nothing -- the media monitor should handle this. */
+ if (tulip_debug > 1)
+ printk(KERN_WARNING "%s: Transmit timeout using MII device.\n",
+ dev->name);
+ } else if (tp->chip_id == DC21040) {
+ if ( !tp->medialock && inl(ioaddr + CSR12) & 0x0002) {
+ dev->if_port = (dev->if_port == 2 ? 0 : 2);
+ printk(KERN_INFO "%s: transmit timed out, switching to "
+ "%s.\n",
+ dev->name, medianame[dev->if_port]);
+ select_media(dev, 0);
+ }
+ dev->trans_start = jiffies;
+ return;
+ } else if (tp->chip_id == DC21041) {
+ int csr12 = inl(ioaddr + CSR12);
- if (media_cap[dev->if_port] & MediaIsMII) {
- /* Do nothing -- the media monitor should handle this. */
-#if 0
- if (tulip_debug > 1)
+ printk(KERN_WARNING "%s: 21041 transmit timed out, status %8.8x, "
+ "CSR12 %8.8x, CSR13 %8.8x, CSR14 %8.8x, resetting...\n",
+ dev->name, inl(ioaddr + CSR5), csr12,
+ inl(ioaddr + CSR13), inl(ioaddr + CSR14));
+ tp->mediasense = 1;
+ if ( ! tp->medialock) {
+ if (dev->if_port == 1 || dev->if_port == 2)
+ if (csr12 & 0x0004) {
+ dev->if_port = 2 - dev->if_port;
+ } else
+ dev->if_port = 0;
+ else
+ dev->if_port = 1;
+ select_media(dev, 0);
+ }
+ } else if (tp->chip_id == DC21140 || tp->chip_id == DC21142
+ || tp->chip_id == MX98713 || tp->chip_id == COMPEX9881) {
+ printk(KERN_WARNING "%s: 21140 transmit timed out, status %8.8x, "
+ "SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n",
+ dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12),
+ inl(ioaddr + CSR13), inl(ioaddr + CSR14), inl(ioaddr + CSR15));
+ if ( ! tp->medialock && tp->mtable) {
+ do
+ --tp->cur_index;
+ while (tp->cur_index >= 0
+ && (media_cap[tp->mtable->mleaf[tp->cur_index].media]
+ & MediaIsFD));
+ if (--tp->cur_index < 0) {
+ /* We start again, but should instead look for default. */
+ tp->cur_index = tp->mtable->leafcount - 1;
+ }
+ select_media(dev, 0);
+ printk(KERN_WARNING "%s: transmit timed out, switching to %s "
+ "media.\n", dev->name, medianame[dev->if_port]);
+ }
+ } else {
+ printk(KERN_WARNING "%s: Transmit timed out, status %8.8x, CSR12 "
+ "%8.8x, resetting...\n",
+ dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12));
+ dev->if_port = 0;
+ }
+
+#if defined(way_too_many_messages)
+ if (tulip_debug > 3) {
+ int i;
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ u8 *buf = (u8 *)(tp->rx_ring[i].buffer1);
+ int j;
+ printk(KERN_DEBUG "%2d: %8.8x %8.8x %8.8x %8.8x "
+ "%2.2x %2.2x %2.2x.\n",
+ i, (unsigned int)tp->rx_ring[i].status,
+ (unsigned int)tp->rx_ring[i].length,
+ (unsigned int)tp->rx_ring[i].buffer1,
+ (unsigned int)tp->rx_ring[i].buffer2,
+ buf[0], buf[1], buf[2]);
+ for (j = 0; buf[j] != 0xee && j < 1600; j++)
+ if (j < 100) printk(" %2.2x", buf[j]);
+ printk(" j=%d.\n", j);
+ }
+ printk(KERN_DEBUG " Rx ring %8.8x: ", (int)tp->rx_ring);
+ for (i = 0; i < RX_RING_SIZE; i++)
+ printk(" %8.8x", (unsigned int)tp->rx_ring[i].status);
+ printk("\n" KERN_DEBUG " Tx ring %8.8x: ", (int)tp->tx_ring);
+ for (i = 0; i < TX_RING_SIZE; i++)
+ printk(" %8.8x", (unsigned int)tp->tx_ring[i].status);
+ printk("\n");
+ }
#endif
- printk(KERN_WARNING "%s: Transmit timeout using MII device.\n",
- dev->name);
- dev->trans_start = jiffies;
- return;
- } else if (tp->chip_id == DC21040) {
- if (inl(ioaddr + CSR12) & 0x0002) {
- printk(KERN_INFO "%s: transmit timed out, switching to %s media.\n",
- dev->name, dev->if_port ? "10baseT" : "AUI");
- dev->if_port ^= 1;
- outl(dev->if_port ? 0x0000000C : 0x00000004, ioaddr + CSR13);
- }
- dev->trans_start = jiffies;
- return;
- } else if (tp->chip_id == DC21041) {
- u32 csr12 = inl(ioaddr + CSR12);
- printk(KERN_WARNING "%s: 21041 transmit timed out, status %8.8x, CSR12 %8.8x,"
- " CSR13 %8.8x, CSR14 %8.8x, resetting...\n",
- dev->name, inl(ioaddr + CSR5), csr12,
- inl(ioaddr + CSR13), inl(ioaddr + CSR14));
- tp->mediasense = 1;
- if (dev->if_port == 1 || dev->if_port == 2)
- if (csr12 & 0x0004) {
- dev->if_port = 2 - dev->if_port;
- } else
- dev->if_port = 0;
- else
- dev->if_port = 1;
- select_media(dev, 0);
- tp->stats.tx_errors++;
+ /* Stop and restart the chip's Tx processes . */
+ outl_CSR6(tp, tp->csr6 | 0x0002);
+ outl_CSR6(tp, tp->csr6 | 0x2002);
+ /* Trigger an immediate transmit demand. */
+ outl(0, ioaddr + CSR1);
+
dev->trans_start = jiffies;
+ tp->stats.tx_errors++;
return;
- } else if (tp->chip_id == DC21140 || tp->chip_id == DC21142
- || tp->chip_id == MX98713) {
- /* Stop the transmit process. */
- outl(tp->csr6 | 0x0002, ioaddr + CSR6);
- printk(KERN_WARNING "%s: 21140 transmit timed out, status %8.8x, "
- "SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n",
- dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12),
- inl(ioaddr + CSR13), inl(ioaddr + CSR14), inl(ioaddr + CSR15));
- if (tp->mtable) {
- if (--tp->cur_index < 0) {
- /* We start again, but should instead look for default. */
- tp->cur_index = tp->mtable->leafcount - 1;
- }
- select_media(dev, 0);
- printk(KERN_WARNING "%s: transmit timed out, switching to %s media.\n",
- dev->name, dev->if_port ? "100baseTx" : "10baseT");
- }
- outl(tp->csr6 | 0x2002, ioaddr + CSR6);
- tp->stats.tx_errors++;
- dev->trans_start = jiffies;
- return;
- } else
- printk(KERN_WARNING "%s: transmit timed out, status %8.8x, CSR12 %8.8x,"
- " resetting...\n",
- dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12));
-#ifdef way_too_many_messages
- printk(" Rx ring %8.8x: ", (int)tp->rx_ring);
- for (i = 0; i < RX_RING_SIZE; i++)
- printk(" %8.8x", (unsigned int)tp->rx_ring[i].status);
- printk("\n Tx ring %8.8x: ", (int)tp->tx_ring);
- for (i = 0; i < TX_RING_SIZE; i++)
- printk(" %8.8x", (unsigned int)tp->tx_ring[i].status);
- printk("\n");
-#endif
-
- /* Perhaps we should reinitialize the hardware here. */
- dev->if_port = 0;
- /* Stop and restart the chip's Tx processes . */
- outl(tp->csr6 | 0x0002, ioaddr + CSR6);
- outl(tp->csr6 | 0x2002, ioaddr + CSR6);
- /* Trigger an immediate transmit demand. */
- outl(0, ioaddr + CSR1);
-
- dev->trans_start = jiffies;
- tp->stats.tx_errors++;
- return;
}
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
-static void
-tulip_init_ring(struct net_device *dev)
+static void tulip_init_ring(struct net_device *dev)
{
struct tulip_private *tp = (struct tulip_private *)dev->priv;
int i;
@@ -2031,36 +2047,42 @@ tulip_init_ring(struct net_device *dev)
tp->tx_full = 0;
tp->cur_rx = tp->cur_tx = 0;
tp->dirty_rx = tp->dirty_tx = 0;
+ tp->susp_rx = 0;
+ tp->ttimer = 0;
+ tp->nir = 0;
for (i = 0; i < RX_RING_SIZE; i++) {
- tp->rx_ring[i].status = 0x80000000; /* Owned by Tulip chip */
- tp->rx_ring[i].length = PKT_BUF_SZ;
- {
- /* Note the receive buffer must be longword aligned.
- dev_alloc_skb() provides 16 byte alignment. But do *not*
- use skb_reserve() to align the IP header! */
- struct sk_buff *skb;
- skb = DEV_ALLOC_SKB(PKT_BUF_SZ);
- tp->rx_skbuff[i] = skb;
- if (skb == NULL)
- break; /* Bad news! */
- skb->dev = dev; /* Mark as being used by this device. */
- tp->rx_ring[i].buffer1 = virt_to_bus(skb->tail);
- }
- tp->rx_ring[i].buffer2 = virt_to_bus(&tp->rx_ring[i+1]);
+ tp->rx_ring[i].status = 0x00000000;
+ tp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ);
+ tp->rx_ring[i].buffer2 = virt_to_le32desc(&tp->rx_ring[i+1]);
+ tp->rx_skbuff[i] = NULL;
}
/* Mark the last entry as wrapping the ring. */
- tp->rx_ring[i-1].length = PKT_BUF_SZ | 0x02000000;
- tp->rx_ring[i-1].buffer2 = virt_to_bus(&tp->rx_ring[0]);
+ tp->rx_ring[i-1].length = cpu_to_le32(PKT_BUF_SZ | DESC_RING_WRAP);
+ tp->rx_ring[i-1].buffer2 = virt_to_le32desc(&tp->rx_ring[0]);
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ /* Note the receive buffer must be longword aligned.
+ dev_alloc_skb() provides 16 byte alignment. But do *not*
+ use skb_reserve() to align the IP header! */
+ struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ);
+ tp->rx_skbuff[i] = skb;
+ if (skb == NULL)
+ break;
+ skb->dev = dev; /* Mark as being used by this device. */
+ tp->rx_ring[i].status = cpu_to_le32(DescOwned); /* Owned by Tulip chip */
+ tp->rx_ring[i].buffer1 = virt_to_le32desc(skb->tail);
+ }
+ tp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
/* The Tx buffer descriptor is filled in as needed, but we
do need to clear the ownership bit. */
for (i = 0; i < TX_RING_SIZE; i++) {
tp->tx_skbuff[i] = 0;
tp->tx_ring[i].status = 0x00000000;
- tp->tx_ring[i].buffer2 = virt_to_bus(&tp->tx_ring[i+1]);
+ tp->tx_ring[i].buffer2 = virt_to_le32desc(&tp->tx_ring[i+1]);
}
- tp->tx_ring[i-1].buffer2 = virt_to_bus(&tp->tx_ring[0]);
+ tp->tx_ring[i-1].buffer2 = virt_to_le32desc(&tp->tx_ring[0]);
}
static int
@@ -2071,8 +2093,8 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev)
u32 flag;
unsigned long cpuflags;
- /* Caution: the write order is important here, set the base address
- with the "ownership" bits last. */
+ /* Caution: the write order is important here, set the field
+ with the ownership bits last. */
spin_lock_irqsave(&tp->tx_lock, cpuflags);
@@ -2080,25 +2102,24 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev)
entry = tp->cur_tx % TX_RING_SIZE;
tp->tx_skbuff[entry] = skb;
- tp->tx_ring[entry].buffer1 = virt_to_bus(skb->data);
+ tp->tx_ring[entry].buffer1 = virt_to_le32desc(skb->data);
if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
- flag = 0x60000000; /* No interrupt */
+ flag = 0x60000000; /* No interrupt */
} else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) {
- flag = 0xe0000000; /* Tx-done intr. */
+ flag = 0xe0000000; /* Tx-done intr. */
} else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) {
- flag = 0x60000000; /* No Tx-done intr. */
- } else {
- /* Leave room for set_rx_mode() to fill entries. */
- flag = 0xe0000000; /* Tx-done intr. */
- tp->tx_full = 1;
- netif_stop_queue(dev);
+ flag = 0x60000000; /* No Tx-done intr. */
+ } else { /* Leave room for set_rx_mode() to fill entries. */
+ tp->tx_full = 1;
+ flag = 0xe0000000; /* Tx-done intr. */
+ netif_stop_queue(dev);
}
if (entry == TX_RING_SIZE-1)
- flag |= 0xe2000000;
+ flag = 0xe0000000 | DESC_RING_WRAP;
- tp->tx_ring[entry].length = skb->len | flag;
- tp->tx_ring[entry].status = 0x80000000; /* Pass ownership to the chip. */
+ tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag);
+ tp->tx_ring[entry].status = cpu_to_le32(DescOwned);
tp->cur_tx++;
spin_unlock_irqrestore(&tp->tx_lock, cpuflags);
@@ -2112,26 +2133,22 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* The interrupt handler does all of the Rx thread work and cleans up
after the Tx thread. */
-static void tulip_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs)
+static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
{
-#ifdef SA_SHIRQ /* Use the now-standard shared IRQ implementation. */
struct net_device *dev = (struct net_device *)dev_instance;
-#else
- struct net_device *dev = (struct net_device *)(irq2dev_map[irq]);
-#endif
-
- struct tulip_private *tp;
- long ioaddr;
- int csr5, work_budget = max_interrupt_work;
-
- if (dev == NULL) {
- printk (KERN_ERR" tulip_interrupt(): irq %d for unknown device.\n",
- irq);
- return;
- }
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ int csr5;
+ int entry;
+ int missed;
+ int rx = 0;
+ int tx = 0;
+ int oi = 0;
+ int maxrx = RX_RING_SIZE;
+ int maxtx = TX_RING_SIZE;
+ int maxoi = TX_RING_SIZE;
- ioaddr = dev->base_addr;
- tp = (struct tulip_private *)dev->priv;
+ tp->nir++;
do {
csr5 = inl(ioaddr + CSR5);
@@ -2145,25 +2162,27 @@ static void tulip_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *reg
if ((csr5 & (NormalIntr|AbnormalIntr)) == 0)
break;
- if (csr5 & (RxIntr | RxNoBuf))
- work_budget -= tulip_rx(dev);
-
- spin_lock(&tp->tx_lock);
+ if (csr5 & (RxIntr | RxNoBuf)) {
+ rx += tulip_rx(dev);
+ tulip_refill_rx(dev);
+ }
- if (csr5 & (TxNoBuf | TxDied | TxIntr)) {
+ if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) {
unsigned int dirty_tx;
+ spin_lock(&tp->tx_lock);
+
for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0;
dirty_tx++) {
int entry = dirty_tx % TX_RING_SIZE;
- int status = tp->tx_ring[entry].status;
+ int status = le32_to_cpu(tp->tx_ring[entry].status);
if (status < 0)
- break; /* It still hasn't been Txed */
+ break; /* It still has not been Txed */
/* Check for Rx filter setup frames. */
if (tp->tx_skbuff[entry] == NULL)
continue;
-
+
if (status & 0x8000) {
/* There was an major error, log it. */
#ifndef final_version
@@ -2185,7 +2204,7 @@ static void tulip_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *reg
#ifdef ETHER_STATS
if (status & 0x0001) tp->stats.tx_deferred++;
#endif
- tp->stats.tx_bytes += tp->tx_ring[entry].length & 0x7ff;
+ tp->stats.tx_bytes += tp->tx_skbuff[entry]->len;
tp->stats.collisions += (status >> 3) & 15;
tp->stats.tx_packets++;
}
@@ -2193,6 +2212,7 @@ static void tulip_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *reg
/* Free the original skb. */
dev_kfree_skb_irq(tp->tx_skbuff[entry]);
tp->tx_skbuff[entry] = 0;
+ tx++;
}
#ifndef final_version
@@ -2210,20 +2230,21 @@ static void tulip_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *reg
}
tp->dirty_tx = dirty_tx;
-
if (csr5 & TxDied) {
- if (tulip_debug > 1)
- printk(KERN_WARNING "%s: The transmitter stopped!"
- " CSR5 is %x, CSR6 %x.\n",
- dev->name, csr5, inl(ioaddr + CSR6));
- outl(tp->csr6 | 0x0002, ioaddr + CSR6);
- outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+ if (tulip_debug > 2)
+ printk(KERN_WARNING "%s: The transmitter stopped."
+ " CSR5 is %x, CSR6 %x, new CSR6 %x.\n",
+ dev->name, csr5, inl(ioaddr + CSR6), tp->csr6);
+ outl_CSR6(tp, tp->csr6 | 0x0002);
+ outl_CSR6(tp, tp->csr6 | 0x2002);
}
+ spin_unlock(&tp->tx_lock);
}
- spin_unlock(&tp->tx_lock);
/* Log errors. */
if (csr5 & AbnormalIntr) { /* Abnormal error summary bit. */
+ if (csr5 == 0xffffffff)
+ break;
if (csr5 & TxJabber) tp->stats.tx_errors++;
if (csr5 & TxFIFOUnderflow) {
if ((tp->csr6 & 0xC000) != 0xC000)
@@ -2231,119 +2252,179 @@ static void tulip_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *reg
else
tp->csr6 |= 0x00200000; /* Store-n-forward. */
/* Restart the transmit process. */
- outl(tp->csr6 | 0x0002, ioaddr + CSR6);
- outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+ outl_CSR6(tp, tp->csr6 | 0x0002);
+ outl_CSR6(tp, tp->csr6 | 0x2002);
+ outl(0, ioaddr + CSR1);
}
if (csr5 & RxDied) { /* Missed a Rx frame. */
tp->stats.rx_errors++;
tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
+ outl_CSR6(tp, tp->csr6 | 0x2002);
}
- if (csr5 & TimerInt) {
- printk(KERN_ERR "%s: Something Wicked happened! %8.8x.\n",
- dev->name, csr5);
- /* Hmmmmm, it's not clear what to do here. */
+ if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) {
+ if (tp->link_change)
+ (tp->link_change)(dev, csr5);
}
- if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)
- && tp->chip_id == DC21142) {
- if (tulip_debug > 1)
- printk(KERN_INFO"%s: 21142 link change, CSR5 = %8.8x.\n",
- dev->name, csr5);
- t21142_lnk_change(dev);
+ if (csr5 & SytemError) {
+ printk(KERN_ERR "%s: (%lu) System Error occured\n", dev->name, tp->nir);
}
/* Clear all error sources, included undocumented ones! */
outl(0x0800f7ba, ioaddr + CSR5);
+ oi++;
}
- if (--work_budget < 0) {
+ if (csr5 & TimerInt) {
+#if 0
+ if (tulip_debug > 2)
+ printk(KERN_ERR "%s: Re-enabling interrupts, %8.8x.\n",
+ dev->name, csr5);
+ outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
+#endif
+ tp->ttimer = 0;
+ oi++;
+ }
+ if (tx > maxtx || rx > maxrx || oi > maxoi) {
if (tulip_debug > 1)
- printk(KERN_WARNING "%s: Too much work at interrupt, "
- "csr5=0x%8.8x.\n", dev->name, csr5);
+ printk(KERN_WARNING "%s: Too much work during an interrupt, "
+ "csr5=0x%8.8x. (%lu) (%d,%d,%d)\n", dev->name, csr5, tp->nir, tx, rx, oi);
/* Acknowledge all interrupt sources. */
- outl(0x8001ffff, ioaddr + CSR5);
-#ifdef notdef
- /* Clear all but standard interrupt sources. */
- outl((~csr5) & 0x0001ebef, ioaddr + CSR7);
+#if 0
+ /* Clear all interrupting sources, set timer to re-enable. */
+ outl(((~csr5) & 0x0001ebef) | NormalIntr | AbnormalIntr | TimerInt,
+ ioaddr + CSR7);
+ outl(12, ioaddr + CSR11);
+ tp->ttimer = 1;
#endif
break;
}
} while (1);
- if (tulip_debug > 3)
+ tulip_refill_rx(dev);
+
+ /* check if we card is in suspend mode */
+ entry = tp->dirty_rx % RX_RING_SIZE;
+ if (tp->rx_skbuff[entry] == NULL) {
+ if (tulip_debug > 1)
+ printk(KERN_WARNING "%s: in rx suspend mode: (%lu) (tp->cur_rx = %u, ttimer = %d, rx = %d) go/stay in suspend mode\n", dev->name, tp->nir, tp->cur_rx, tp->ttimer, rx);
+ if (tp->ttimer == 0 || (inl(ioaddr + CSR11) & 0xffff) == 0) {
+ if (tulip_debug > 1)
+ printk(KERN_WARNING "%s: in rx suspend mode: (%lu) set timer\n", dev->name, tp->nir);
+ outl(tulip_tbl[tp->chip_id].valid_intrs | TimerInt,
+ ioaddr + CSR7);
+ outl(TimerInt, ioaddr + CSR5);
+ outl(12, ioaddr + CSR11);
+ tp->ttimer = 1;
+ }
+ }
+
+ if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) {
+ tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;
+ }
+
+ if (tulip_debug > 4)
printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",
dev->name, inl(ioaddr + CSR5));
- return;
}
-static int
-tulip_rx(struct net_device *dev)
+static int tulip_refill_rx(struct net_device *dev)
+{
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ int entry;
+ int refilled = 0;
+
+ /* Refill the Rx ring buffers. */
+ for (; tp->cur_rx - tp->dirty_rx > 0; tp->dirty_rx++) {
+ entry = tp->dirty_rx % RX_RING_SIZE;
+ if (tp->rx_skbuff[entry] == NULL) {
+ struct sk_buff *skb;
+ skb = tp->rx_skbuff[entry] = dev_alloc_skb(PKT_BUF_SZ);
+ if (skb == NULL)
+ break;
+ skb->dev = dev; /* Mark as being used by this device. */
+ tp->rx_ring[entry].buffer1 = virt_to_le32desc(skb->tail);
+ refilled++;
+ }
+ tp->rx_ring[entry].status = cpu_to_le32(DescOwned);
+ }
+ return refilled;
+}
+
+static int tulip_rx(struct net_device *dev)
{
struct tulip_private *tp = (struct tulip_private *)dev->priv;
int entry = tp->cur_rx % RX_RING_SIZE;
int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx;
- int work_done = 0;
+ int received = 0;
if (tulip_debug > 4)
printk(KERN_DEBUG " In tulip_rx(), entry %d %8.8x.\n", entry,
tp->rx_ring[entry].status);
- /* If we own the next entry, it's a new packet. Send it up. */
- while (tp->rx_ring[entry].status >= 0) {
- s32 status = tp->rx_ring[entry].status;
+ /* If we own the next entry, it is a new packet. Send it up. */
+ while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
+ s32 status = le32_to_cpu(tp->rx_ring[entry].status);
+ if (tulip_debug > 5)
+ printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n",
+ dev->name, entry, status);
if (--rx_work_limit < 0)
break;
- if ((status & 0x0300) != 0x0300) {
- if ((status & 0xffff) != 0x7fff) { /* Ingore earlier buffers. */
- if (tulip_debug > 1)
- printk(KERN_WARNING "%s: Oversized Ethernet frame spanned "
- "multiple buffers, status %8.8x!\n",
+ if ((status & 0x38008300) != 0x0300) {
+ if ((status & 0x38000300) != 0x0300) {
+ /* Ingore earlier buffers. */
+ if ((status & 0xffff) != 0x7fff) {
+ if (tulip_debug > 1)
+ printk(KERN_WARNING "%s: Oversized Ethernet frame "
+ "spanned multiple buffers, status %8.8x!\n",
+ dev->name, status);
+ tp->stats.rx_length_errors++;
+ }
+ } else if (status & RxDescFatalErr) {
+ /* There was a fatal error. */
+ if (tulip_debug > 2)
+ printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n",
dev->name, status);
- tp->stats.rx_length_errors++;
+ tp->stats.rx_errors++; /* end of a packet.*/
+ if (status & 0x0890) tp->stats.rx_length_errors++;
+ if (status & 0x0004) tp->stats.rx_frame_errors++;
+ if (status & 0x0002) tp->stats.rx_crc_errors++;
+ if (status & 0x0001) tp->stats.rx_fifo_errors++;
}
- } else if (status & 0x8000) {
- /* There was a fatal error. */
- if (tulip_debug > 2)
- printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n",
- dev->name, status);
- tp->stats.rx_errors++; /* end of a packet.*/
- if (status & 0x0890) tp->stats.rx_length_errors++;
- if (status & 0x0004) tp->stats.rx_frame_errors++;
- if (status & 0x0002) tp->stats.rx_crc_errors++;
- if (status & 0x0001) tp->stats.rx_fifo_errors++;
} else {
/* Omit the four octet CRC from the length. */
- short pkt_len = (status >> 16) - 4;
+ short pkt_len = ((status >> 16) & 0x7ff) - 4;
struct sk_buff *skb;
- /* Check if the packet is long enough to just accept without
- copying to a properly sized skbuff. */
+#ifndef final_version
+ if (pkt_len > 1518) {
+ printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
+ dev->name, pkt_len, pkt_len);
+ pkt_len = 1518;
+ tp->stats.rx_length_errors++;
+ }
+#endif
+ /* Check if the packet is long enough to accept without copying
+ to a minimally-sized skbuff. */
if (pkt_len < rx_copybreak
- && (skb = DEV_ALLOC_SKB(pkt_len+2)) != NULL) {
+ && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
skb->dev = dev;
skb_reserve(skb, 2); /* 16 byte align the IP header */
-#if LINUX_VERSION_CODE < 0x20200 || defined(__alpha__)
- memcpy(skb_put(skb, pkt_len),
- bus_to_virt(tp->rx_ring[entry].buffer1), pkt_len);
-#else
- eth_copy_and_sum(skb, bus_to_virt(tp->rx_ring[entry].buffer1),
- pkt_len, 0);
+#if ! defined(__alpha__)
+ eth_copy_and_sum(skb, tp->rx_skbuff[entry]->tail, pkt_len, 0);
skb_put(skb, pkt_len);
+#else
+ memcpy(skb_put(skb, pkt_len), tp->rx_skbuff[entry]->tail,
+ pkt_len);
#endif
- work_done++;
} else { /* Pass up the skb already on the Rx ring. */
- skb = tp->rx_skbuff[entry];
+ char *temp = skb_put(skb = tp->rx_skbuff[entry], pkt_len);
tp->rx_skbuff[entry] = NULL;
#ifndef final_version
- {
- void *temp = skb_put(skb, pkt_len);
- if (bus_to_virt(tp->rx_ring[entry].buffer1) != temp)
- printk(KERN_ERR "%s: Internal consistency error! The "
- "skbuff addresses do not match in tulip_rx:"
- " %p vs. %p / %p.\n", dev->name,
- bus_to_virt(tp->rx_ring[entry].buffer1),
- skb->head, temp);
- }
-#else
- skb_put(skb, pkt_len);
+ if (le32desc_to_virt(tp->rx_ring[entry].buffer1) != temp)
+ printk(KERN_ERR "%s: Internal fault: The skbuff addresses "
+ "do not match in tulip_rx: %p vs. %p / %p.\n",
+ dev->name,
+ le32desc_to_virt(tp->rx_ring[entry].buffer1),
+ skb->head, temp);
#endif
}
skb->protocol = eth_type_trans(skb, dev);
@@ -2352,95 +2433,92 @@ tulip_rx(struct net_device *dev)
tp->stats.rx_packets++;
tp->stats.rx_bytes += pkt_len;
}
+ received++;
entry = (++tp->cur_rx) % RX_RING_SIZE;
}
- /* Refill the Rx ring buffers. */
- for (; tp->cur_rx - tp->dirty_rx > 0; tp->dirty_rx++) {
- entry = tp->dirty_rx % RX_RING_SIZE;
- if (tp->rx_skbuff[entry] == NULL) {
- struct sk_buff *skb;
- skb = tp->rx_skbuff[entry] = DEV_ALLOC_SKB(PKT_BUF_SZ);
- if (skb == NULL)
- break;
- skb->dev = dev; /* Mark as being used by this device. */
- tp->rx_ring[entry].buffer1 = virt_to_bus(skb->tail);
- work_done++;
- }
- tp->rx_ring[entry].status = 0x80000000;
- }
-
- return work_done;
+ return received;
}
-static int
-tulip_close(struct net_device *dev)
+
+static void tulip_down (struct net_device *dev)
{
long ioaddr = dev->base_addr;
- struct tulip_private *tp = (struct tulip_private *)dev->priv;
- int i;
+ struct tulip_private *tp = (struct tulip_private *) dev->priv;
- netif_stop_queue(dev);
+ netif_device_detach (dev);
- if (tulip_debug > 1)
- printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
- dev->name, inl(ioaddr + CSR5));
+ del_timer (&tp->timer);
/* Disable interrupts by clearing the interrupt mask. */
- outl(0x00000000, ioaddr + CSR7);
- /* Stop the chip's Tx and Rx processes. */
- outl(inl(ioaddr + CSR6) & ~0x2002, ioaddr + CSR6);
+ outl (0x00000000, ioaddr + CSR7);
+
+ /* Stop the Tx and Rx processes. */
+ outl_CSR6 (tp, inl (ioaddr + CSR6) & ~0x2002);
+
/* 21040 -- Leave the card in 10baseT state. */
if (tp->chip_id == DC21040)
- outl(0x00000004, ioaddr + CSR13);
+ outl (0x00000004, ioaddr + CSR13);
- tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
+ if (inl (ioaddr + CSR6) != 0xffffffff)
+ tp->stats.rx_missed_errors += inl (ioaddr + CSR8) & 0xffff;
- del_timer(&tp->timer);
+ dev->if_port = tp->saved_if_port;
-#ifdef SA_SHIRQ
- free_irq(dev->irq, dev);
-#else
- free_irq(dev->irq);
- irq2dev_map[dev->irq] = 0;
-#endif
+ /* Leave the driver in snooze, not sleep, mode. */
+ if (tp->flags & HAS_ACPI)
+ pci_write_config_dword (tp->pdev, 0x40, 0x40000000);
+}
+
+
+static int tulip_close (struct net_device *dev)
+{
+ long ioaddr = dev->base_addr;
+ struct tulip_private *tp = (struct tulip_private *) dev->priv;
+ int i;
+
+ tulip_down (dev);
+
+ if (tulip_debug > 1)
+ printk (KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
+ dev->name, inl (ioaddr + CSR5));
+
+ free_irq (dev->irq, dev);
/* Free all the skbuffs in the Rx queue. */
for (i = 0; i < RX_RING_SIZE; i++) {
struct sk_buff *skb = tp->rx_skbuff[i];
tp->rx_skbuff[i] = 0;
- tp->rx_ring[i].status = 0; /* Not owned by Tulip chip. */
+ tp->rx_ring[i].status = 0; /* Not owned by Tulip chip. */
tp->rx_ring[i].length = 0;
- tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */
+ tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */
if (skb) {
- dev_kfree_skb(skb);
+ dev_kfree_skb (skb);
}
}
for (i = 0; i < TX_RING_SIZE; i++) {
if (tp->tx_skbuff[i])
- dev_kfree_skb(tp->tx_skbuff[i]);
+ dev_kfree_skb (tp->tx_skbuff[i]);
tp->tx_skbuff[i] = 0;
}
-
MOD_DEC_USE_COUNT;
return 0;
}
-static struct enet_statistics *
-tulip_get_stats(struct net_device *dev)
+static struct enet_statistics *tulip_get_stats(struct net_device *dev)
{
struct tulip_private *tp = (struct tulip_private *)dev->priv;
long ioaddr = dev->base_addr;
- if (test_bit(LINK_STATE_START, &dev->state))
+ if (netif_running(dev))
tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
return &tp->stats;
}
-#ifdef HAVE_PRIVATE_IOCTL
+
/* Provide ioctl() calls to examine the MII xcvr state. */
static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
@@ -2452,31 +2530,32 @@ static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
switch(cmd) {
case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
- if (tp->mtable && tp->mtable->has_mii)
+ if (tp->mii_cnt)
data[0] = phy;
- else if (tp->chip_id == DC21142)
+ else if (tp->flags & HAS_NWAY143)
data[0] = 32;
+ else if (tp->chip_id == COMET)
+ data[0] = 1;
else
return -ENODEV;
- return 0;
case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
- if (data[0] == 32) { /* 21142 pseudo-MII */
+ if (data[0] == 32 && (tp->flags & HAS_NWAY143)) {
int csr12 = inl(ioaddr + CSR12);
int csr14 = inl(ioaddr + CSR14);
switch (data[1]) {
case 0: {
- data[3] = ((csr14<<13)&0x4000) + ((csr14<<5)&0x1000);
+ data[3] = (csr14<<5) & 0x1000;
break; }
case 1:
data[3] = 0x7848 + ((csr12&0x7000) == 0x5000 ? 0x20 : 0)
+ (csr12&0x06 ? 0x04 : 0);
break;
case 4: {
- int csr14 = inl(ioaddr + CSR14);
- data[3] = ((csr14>>9)&0x0380) + ((csr14>>1)&0x20) + 1;
+ data[3] = ((csr14>>9)&0x07C0) +
+ ((inl(ioaddr + CSR6)>>3)&0x0040) + ((csr14>>1)&0x20) + 1;
break;
}
- case 5: data[3] = inl(ioaddr + CSR12) >> 16; break;
+ case 5: data[3] = csr12 >> 16; break;
default: data[3] = 0; break;
}
} else {
@@ -2487,9 +2566,11 @@ static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
return 0;
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
- if (data[0] == 32) { /* 21142 pseudo-MII */
+ if (data[0] == 32 && (tp->flags & HAS_NWAY143)) {
+ if (data[1] == 5)
+ tp->to_advertise = data[2];
} else {
save_flags(flags);
cli();
@@ -2503,7 +2584,7 @@ static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return -EOPNOTSUPP;
}
-#endif /* HAVE_PRIVATE_IOCTL */
+
/* Set or clear the multicast filter for this adaptor.
Note that we only use exclusion around actually queueing the
@@ -2514,9 +2595,9 @@ static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
N.B. Do not use for bulk data, use a table-based routine instead.
This is common code and should be moved to net/core/crc.c */
static unsigned const ethernet_polynomial_le = 0xedb88320U;
-static inline unsigned ether_crc_le(int length, unsigned char *data)
+static inline u32 ether_crc_le(int length, unsigned char *data)
{
- unsigned int crc = 0xffffffff; /* Initial value. */
+ u32 crc = 0xffffffff; /* Initial value. */
while(--length >= 0) {
unsigned char current_octet = *data++;
int bit;
@@ -2530,223 +2611,549 @@ static inline unsigned ether_crc_le(int length, unsigned char *data)
}
return crc;
}
+static unsigned const ethernet_polynomial = 0x04c11db7U;
+static inline u32 ether_crc(int length, unsigned char *data)
+{
+ int crc = -1;
+
+ while(--length >= 0) {
+ unsigned char current_octet = *data++;
+ int bit;
+ for (bit = 0; bit < 8; bit++, current_octet >>= 1)
+ crc = (crc << 1) ^
+ ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);
+ }
+ return crc;
+}
-#ifdef NEW_MULTICAST
static void set_rx_mode(struct net_device *dev)
-#else
-static void set_rx_mode(struct net_device *dev, int num_addrs, void *addrs)
-#endif
{
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
long ioaddr = dev->base_addr;
int csr6 = inl(ioaddr + CSR6) & ~0x00D5;
- struct tulip_private *tp = (struct tulip_private *)dev->priv;
unsigned long cpuflags;
tp->csr6 &= ~0x00D5;
if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
- outl(csr6 | 0x00C0, ioaddr + CSR6);
+ tp->csr6 |= 0x00C0;
+ csr6 |= 0x00C0;
/* Unconditionally log net taps. */
printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
- tp->csr6 |= 0xC0;
} else if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) {
- /* Too many to filter perfectly -- accept all multicasts. */
- outl(csr6 | 0x0080, ioaddr + CSR6);
- tp->csr6 |= 0x80;
+ /* Too many to filter well -- accept all multicasts. */
+ tp->csr6 |= 0x0080;
+ csr6 |= 0x0080;
+ } else if (tp->flags & MC_HASH_ONLY) {
+ /* Some work-alikes have only a 64-entry hash filter table. */
+ /* Should verify correctness on big-endian/__powerpc__ */
+ struct dev_mc_list *mclist;
+ int i;
+ u32 mc_filter[2]; /* Multicast hash filter */
+ if (dev->mc_count > 64) { /* Arbitrary non-effective limit. */
+ tp->csr6 |= 0x0080;
+ csr6 |= 0x0080;
+ } else {
+ mc_filter[1] = mc_filter[0] = 0;
+ for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+ i++, mclist = mclist->next)
+ set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr)>>26, mc_filter);
+ if (tp->chip_id == AX88140) {
+ outl(2, ioaddr + CSR13);
+ outl(mc_filter[0], ioaddr + CSR14);
+ outl(3, ioaddr + CSR13);
+ outl(mc_filter[1], ioaddr + CSR14);
+ } else if (tp->chip_id == COMET) { /* Has a simple hash filter. */
+ outl(mc_filter[0], ioaddr + 0xAC);
+ outl(mc_filter[1], ioaddr + 0xB0);
+ }
+ }
} else {
- u32 *setup_frm = tp->setup_frame;
+ u16 *eaddrs, *setup_frm = tp->setup_frame;
struct dev_mc_list *mclist;
- u16 *eaddrs;
- u32 tx_flags;
+ u32 tx_flags = 0x08000000 | 192;
int i;
+ /* Note that only the low-address shortword of setup_frame is valid!
+ The values are doubled for big-endian architectures. */
if (dev->mc_count > 14) { /* Must use a multicast hash table. */
- u16 hash_table[32];
- memset(hash_table, 0, sizeof(hash_table));
- /* This should work on big-endian machines as well. */
- for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
- i++, mclist = mclist->next)
- set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff,
- hash_table);
- /* Copy the hash table to the setup frame.
- NOTE that only the LOW SHORTWORD of setup_frame[] is valid! */
- for (i = 0; i < 32; i++)
- *setup_frm++ = hash_table[i];
- setup_frm += 7;
- tx_flags = 0x08400000 | 192;
- /* Too clever: i > 15 for fall-though. */
+ u16 hash_table[32];
+ tx_flags = 0x08400000 | 192; /* Use hash filter. */
+ memset(hash_table, 0, sizeof(hash_table));
+ set_bit(255, hash_table); /* Broadcast entry */
+ /* This should work on big-endian machines as well. */
+ for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+ i++, mclist = mclist->next)
+ set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff,
+ hash_table);
+ for (i = 0; i < 32; i++)
+ *setup_frm++ = *setup_frm++ = hash_table[i];
+ setup_frm = &tp->setup_frame[13*6];
} else {
- /* We have <= 15 addresses so we can use the wonderful
- 16 address perfect filtering of the Tulip. */
- for (i = 0, mclist = dev->mc_list; i < dev->mc_count;
- i++, mclist = mclist->next) {
- /* Note that only the low shortword of setup_frame[] is valid!
- This code may require tweaking for non-x86 architectures! */
- eaddrs = (u16 *)mclist->dmi_addr;
- *setup_frm++ = *eaddrs++;
- *setup_frm++ = *eaddrs++;
- *setup_frm++ = *eaddrs++;
- }
- /* Fill the rest of the table with our physical address.
- Once again, only the low shortword or setup_frame[] is valid! */
- *setup_frm++ = 0xffff;
- *setup_frm++ = 0xffff;
- *setup_frm++ = 0xffff;
- tx_flags = 0x08000000 | 192;
+ /* We have <= 14 addresses so we can use the wonderful
+ 16 address perfect filtering of the Tulip. */
+ for (i = 0, mclist = dev->mc_list; i < dev->mc_count;
+ i++, mclist = mclist->next) {
+ eaddrs = (u16 *)mclist->dmi_addr;
+ *setup_frm++ = *setup_frm++ = *eaddrs++;
+ *setup_frm++ = *setup_frm++ = *eaddrs++;
+ *setup_frm++ = *setup_frm++ = *eaddrs++;
+ }
+ /* Fill the unused entries with the broadcast address. */
+ memset(setup_frm, 0xff, (15-i)*12);
+ setup_frm = &tp->setup_frame[15*6];
}
+ /* Fill the final entry with our physical address. */
eaddrs = (u16 *)dev->dev_addr;
- do {
- *setup_frm++ = eaddrs[0];
- *setup_frm++ = eaddrs[1];
- *setup_frm++ = eaddrs[2];
- } while (++i < 15);
+ *setup_frm++ = *setup_frm++ = eaddrs[0];
+ *setup_frm++ = *setup_frm++ = eaddrs[1];
+ *setup_frm++ = *setup_frm++ = eaddrs[2];
/* Now add this frame to the Tx list. */
spin_lock_irqsave(&tp->tx_lock, cpuflags);
if (tp->cur_tx - tp->dirty_tx > TX_RING_SIZE - 2) {
/* Same setup recently queued, we need not add it. */
} else {
- unsigned int entry, dummy = 0;
+ unsigned long flags;
+ unsigned int entry;
+ save_flags(flags); cli();
entry = tp->cur_tx++ % TX_RING_SIZE;
if (entry != 0) {
/* Avoid a chip errata by prefixing a dummy entry. */
tp->tx_skbuff[entry] = 0;
tp->tx_ring[entry].length =
- (entry == TX_RING_SIZE-1) ? 0x02000000 : 0;
+ (entry == TX_RING_SIZE-1) ? cpu_to_le32(DESC_RING_WRAP) : 0;
tp->tx_ring[entry].buffer1 = 0;
- /* race with chip, set DescOwned later */
- dummy = entry;
+ tp->tx_ring[entry].status = cpu_to_le32(DescOwned);
entry = tp->cur_tx++ % TX_RING_SIZE;
}
tp->tx_skbuff[entry] = 0;
/* Put the setup frame on the Tx list. */
if (entry == TX_RING_SIZE-1)
- tx_flags |= 0x02000000; /* Wrap ring. */
- tp->tx_ring[entry].length = tx_flags;
- tp->tx_ring[entry].buffer1 = virt_to_bus(tp->setup_frame);
- tp->tx_ring[entry].status = 0x80000000;
+ tx_flags |= DESC_RING_WRAP; /* Wrap ring. */
+ tp->tx_ring[entry].length = cpu_to_le32(tx_flags);
+ tp->tx_ring[entry].buffer1 = virt_to_le32desc(tp->setup_frame);
+ tp->tx_ring[entry].status = cpu_to_le32(DescOwned);
if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) {
netif_stop_queue(dev);
tp->tx_full = 1;
}
- if (dummy >= 0)
- tp->tx_ring[dummy].status = DescOwned;
spin_unlock_irqrestore(&tp->tx_lock, cpuflags);
/* Trigger an immediate transmit demand. */
outl(0, ioaddr + CSR1);
}
- outl(csr6 | 0x0000, ioaddr + CSR6);
}
+ outl_CSR6(tp, csr6 | 0x0000);
}
-
-#ifdef CARDBUS
-#include <pcmcia/driver_ops.h>
-static dev_node_t *tulip_attach(dev_locator_t *loc)
+static int __devinit tulip_init_one (struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
- u16 dev_id;
- u32 io;
- u8 bus, devfn;
+ static int did_version = 0; /* Already printed version info. */
+ struct tulip_private *tp;
+ /* See note below on the multiport cards. */
+ static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'};
+ static int last_irq = 0;
+ static int multiport_cnt = 0; /* For four-port boards w/one EEPROM */
+ u8 chip_rev;
+ int i, irq;
+ unsigned short sum;
+ u8 ee_data[EEPROM_SIZE];
struct net_device *dev;
- struct pci_dev *pdev;
+ long ioaddr;
+ static int board_idx = -1;
+ int chip_idx = ent->driver_data;
+
+ board_idx++;
- if (loc->bus != LOC_PCI) return NULL;
- pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn);
- if (!pdev) return NULL;
- printk(KERN_INFO "tulip_attach(bus %d, function %d)\n", bus, devfn);
- io = pdev->resource[0].start;
- dev_id = pdev->device;
- io &= ~3;
- dev = tulip_probe1(bus, devfn, DC21142, -1);
- if (dev) {
- dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
- strcpy(node->dev_name, dev->name);
- node->major = node->minor = 0;
- node->next = NULL;
- MOD_INC_USE_COUNT;
- return node;
+ if (tulip_debug > 0 && did_version++ == 0)
+ printk (KERN_INFO "%s", version);
+
+ if( pdev->subsystem_vendor == 0x1376 ){
+ printk (KERN_ERR PFX "skipping LMC card.\n");
+ return -ENODEV;
}
- return NULL;
-}
+
+ ioaddr = pci_resource_start (pdev, 0);
+ irq = pdev->irq;
-static void tulip_detach(dev_node_t *node)
-{
- struct net_device **devp, **next;
- printk(KERN_INFO "tulip_detach(%s)\n", node->dev_name);
- for (devp = &root_tulip_dev; *devp; devp = next) {
- next = &((struct tulip_private *)(*devp)->priv)->next_module;
- if (strcmp((*devp)->name, node->dev_name) == 0) break;
+ /* Make certain the data structures are quadword aligned. */
+ dev = init_etherdev (NULL, sizeof (*tp));
+ if (!dev) {
+ printk (KERN_ERR PFX "unable to allocate ether device, aborting\n");
+ return -ENOMEM;
}
- if (*devp) {
- unregister_netdev(*devp);
- kfree(*devp);
- *devp = *next;
- kfree(node);
- MOD_DEC_USE_COUNT;
+
+ /* We do a request_region() only to register /proc/ioports info. */
+ /* Note that proper size is tulip_tbl[chip_idx].chip_name, but... */
+ if (!request_region (ioaddr, tulip_tbl[chip_idx].io_size, dev->name)) {
+ printk (KERN_ERR PFX "unable to allocate ether device, aborting\n");
+ goto err_out_free_netdev;
}
-}
-struct driver_operations tulip_ops = {
- "tulip_cb", tulip_attach, NULL, NULL, tulip_detach
-};
+ if (pci_enable_device(pdev)) {
+ printk (KERN_ERR PFX "cannot enable PCI device (id %04x:%04x, bus %d, devfn %d), aborting\n",
+ pdev->vendor, pdev->device,
+ pdev->bus->number, pdev->devfn);
+ goto err_out_free_netdev;
+ }
-#endif /* Cardbus support */
+ pci_set_master(pdev);
-MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
-MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver");
-MODULE_PARM(debug, "i");
-MODULE_PARM(max_interrupt_work, "i");
-MODULE_PARM(reverse_probe, "i");
-MODULE_PARM(rx_copybreak, "i");
-MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+ tp = dev->priv;
+ memset(tp, 0, sizeof(*tp));
-/* An additional parameter that may be passed in... */
-static int debug = -1;
+ pci_read_config_byte (pdev, PCI_REVISION_ID, &chip_rev);
-static int __init tulip_init_module (void)
-{
- if (debug >= 0)
- tulip_debug = debug;
+ printk(KERN_INFO "%s: %s rev %d at %#3lx,",
+ dev->name, tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr);
-#ifdef CARDBUS
- register_driver(&tulip_ops);
- return 0;
-#else
- return tulip_probe();
+ /* Stop the chip's Tx and Rx processes. */
+ outl_CSR6(tp, inl(ioaddr + CSR6) & ~0x2002);
+ /* Clear the missed-packet counter. */
+ (volatile int)inl(ioaddr + CSR8);
+
+ if (chip_idx == DC21041 && inl(ioaddr + CSR9) & 0x8000) {
+ printk(" 21040 compatible mode,");
+ chip_idx = DC21040;
+ }
+
+ /* The station address ROM is read byte serially. The register must
+ be polled, waiting for the value to be read bit serially from the
+ EEPROM.
+ */
+ sum = 0;
+ if (chip_idx == DC21040) {
+ outl(0, ioaddr + CSR9); /* Reset the pointer with a dummy write. */
+ for (i = 0; i < 6; i++) {
+ int value, boguscnt = 100000;
+ do
+ value = inl(ioaddr + CSR9);
+ while (value < 0 && --boguscnt > 0);
+ dev->dev_addr[i] = value;
+ sum += value & 0xff;
+ }
+ } else if (chip_idx == LC82C168) {
+ for (i = 0; i < 3; i++) {
+ int value, boguscnt = 100000;
+ outl(0x600 | i, ioaddr + 0x98);
+ do
+ value = inl(ioaddr + CSR9);
+ while (value < 0 && --boguscnt > 0);
+ put_unaligned(le16_to_cpu(value), ((u16*)dev->dev_addr) + i);
+ sum += value & 0xffff;
+ }
+ } else if (chip_idx == COMET) {
+ /* No need to read the EEPROM. */
+ put_unaligned(inl(ioaddr + 0xA4), (u32 *)dev->dev_addr);
+ put_unaligned(inl(ioaddr + 0xA8), (u16 *)(dev->dev_addr + 4));
+ for (i = 0; i < 6; i ++)
+ sum += dev->dev_addr[i];
+ } else {
+ /* A serial EEPROM interface, we read now and sort it out later. */
+ int sa_offset = 0;
+ int ee_addr_size = read_eeprom(ioaddr, 0xff, 8) & 0x40000 ? 8 : 6;
+
+ for (i = 0; i < sizeof(ee_data)/2; i++)
+ ((u16 *)ee_data)[i] =
+ le16_to_cpu(read_eeprom(ioaddr, i, ee_addr_size));
+
+ /* DEC now has a specification (see Notes) but early board makers
+ just put the address in the first EEPROM locations. */
+ /* This does memcmp(eedata, eedata+16, 8) */
+ for (i = 0; i < 8; i ++)
+ if (ee_data[i] != ee_data[16+i])
+ sa_offset = 20;
+ if (ee_data[0] == 0xff && ee_data[1] == 0xff && ee_data[2] == 0) {
+ sa_offset = 2; /* Grrr, damn Matrox boards. */
+ multiport_cnt = 4;
+ }
+ for (i = 0; i < 6; i ++) {
+ dev->dev_addr[i] = ee_data[i + sa_offset];
+ sum += ee_data[i + sa_offset];
+ }
+ }
+ /* Lite-On boards have the address byte-swapped. */
+ if ((dev->dev_addr[0] == 0xA0 || dev->dev_addr[0] == 0xC0)
+ && dev->dev_addr[1] == 0x00)
+ for (i = 0; i < 6; i+=2) {
+ char tmp = dev->dev_addr[i];
+ dev->dev_addr[i] = dev->dev_addr[i+1];
+ dev->dev_addr[i+1] = tmp;
+ }
+ /* On the Zynx 315 Etherarray and other multiport boards only the
+ first Tulip has an EEPROM.
+ The addresses of the subsequent ports are derived from the first.
+ Many PCI BIOSes also incorrectly report the IRQ line, so we correct
+ that here as well. */
+ if (sum == 0 || sum == 6*0xff) {
+ printk(" EEPROM not present,");
+ for (i = 0; i < 5; i++)
+ dev->dev_addr[i] = last_phys_addr[i];
+ dev->dev_addr[i] = last_phys_addr[i] + 1;
+#if defined(__i386__) /* Patch up x86 BIOS bug. */
+ if (last_irq)
+ irq = last_irq;
+#endif
+ }
+
+ for (i = 0; i < 6; i++)
+ printk("%c%2.2X", i ? ':' : ' ', last_phys_addr[i] = dev->dev_addr[i]);
+ printk(", IRQ %d.\n", irq);
+ last_irq = irq;
+
+ pdev->driver_data = dev;
+ dev->base_addr = ioaddr;
+ dev->irq = irq;
+
+ tp->chip_id = chip_idx;
+ tp->revision = chip_rev;
+ tp->flags = tulip_tbl[chip_idx].flags;
+ tp->csr0 = csr0;
+ tp->pdev = pdev;
+ tp->base_addr = dev->base_addr;
+
+ /* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles.
+ And the ASIX must have a burst limit or horrible things happen. */
+ if (chip_idx == DC21143 && chip_rev == 65)
+ tp->csr0 &= ~0x01000000;
+ else if (chip_idx == AX88140)
+ tp->csr0 |= 0x2000;
+
+#ifdef TULIP_FULL_DUPLEX
+ tp->full_duplex = 1;
+ tp->full_duplex_lock = 1;
+#endif
+#ifdef TULIP_DEFAULT_MEDIA
+ tp->default_port = TULIP_DEFAULT_MEDIA;
+#endif
+#ifdef TULIP_NO_MEDIA_SWITCH
+ tp->medialock = 1;
#endif
+ tp->tx_lock = SPIN_LOCK_UNLOCKED;
+
+ /* The lower four bits are the media type. */
+ if (board_idx >= 0 && board_idx < MAX_UNITS) {
+ tp->default_port = options[board_idx] & 15;
+ if ((options[board_idx] & 0x90) || full_duplex[board_idx] > 0)
+ tp->full_duplex = 1;
+ if (mtu[board_idx] > 0)
+ dev->mtu = mtu[board_idx];
+ }
+ if (dev->mem_start)
+ tp->default_port = dev->mem_start;
+ if (tp->default_port) {
+ tp->medialock = 1;
+ if (media_cap[tp->default_port] & MediaAlwaysFD)
+ tp->full_duplex = 1;
+ }
+ if (tp->full_duplex)
+ tp->full_duplex_lock = 1;
+
+ if (media_cap[tp->default_port] & MediaIsMII) {
+ u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 };
+ tp->to_advertise = media2advert[tp->default_port - 9];
+ } else if (tp->flags & HAS_8023X)
+ tp->to_advertise = 0x05e1;
+ else
+ tp->to_advertise = 0x01e1;
+
+ /* This is logically part of probe1(), but too complex to write inline. */
+ if (tp->flags & HAS_MEDIA_TABLE) {
+ memcpy(tp->eeprom, ee_data, sizeof(tp->eeprom));
+ parse_eeprom(dev);
+ }
+
+ if ((tp->flags & ALWAYS_CHECK_MII) ||
+ (tp->mtable && tp->mtable->has_mii) ||
+ ( ! tp->mtable && (tp->flags & HAS_MII))) {
+ int phy, phy_idx;
+ if (tp->mtable && tp->mtable->has_mii) {
+ for (i = 0; i < tp->mtable->leafcount; i++)
+ if (tp->mtable->mleaf[i].media == 11) {
+ tp->cur_index = i;
+ tp->saved_if_port = dev->if_port;
+ select_media(dev, 1);
+ dev->if_port = tp->saved_if_port;
+ break;
+ }
+ }
+ /* Find the connected MII xcvrs.
+ Doing this in open() would allow detecting external xcvrs later,
+ but takes much time. */
+ for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
+ phy++) {
+ int mii_status = mdio_read(dev, phy, 1);
+ if ((mii_status & 0x8301) == 0x8001 ||
+ ((mii_status & 0x8000) == 0 && (mii_status & 0x7800) != 0)) {
+ int mii_reg0 = mdio_read(dev, phy, 0);
+ int mii_advert = mdio_read(dev, phy, 4);
+ int reg4 = ((mii_status>>6) & tp->to_advertise) | 1;
+ tp->phys[phy_idx] = phy;
+ tp->advertising[phy_idx++] = reg4;
+ printk(KERN_INFO "%s: MII transceiver #%d "
+ "config %4.4x status %4.4x advertising %4.4x.\n",
+ dev->name, phy, mii_reg0, mii_status, mii_advert);
+ /* Fixup for DLink with miswired PHY. */
+ if (mii_advert != reg4) {
+ printk(KERN_DEBUG "%s: Advertising %4.4x on PHY %d,"
+ " previously advertising %4.4x.\n",
+ dev->name, reg4, phy, mii_advert);
+ printk(KERN_DEBUG "%s: Advertising %4.4x (to advertise"
+ " is %4.4x).\n",
+ dev->name, reg4, tp->to_advertise);
+ mdio_write(dev, phy, 4, reg4);
+ }
+ /* Enable autonegotiation: some boards default to off. */
+ mdio_write(dev, phy, 0, mii_reg0 |
+ (tp->full_duplex ? 0x1100 : 0x1000) |
+ (media_cap[tp->default_port]&MediaIs100 ? 0x2000:0));
+ }
+ }
+ tp->mii_cnt = phy_idx;
+ if (tp->mtable && tp->mtable->has_mii && phy_idx == 0) {
+ printk(KERN_INFO "%s: ***WARNING***: No MII transceiver found!\n",
+ dev->name);
+ tp->phys[0] = 1;
+ }
+ }
+
+ /* The Tulip-specific entries in the device structure. */
+ dev->open = tulip_open;
+ dev->hard_start_xmit = tulip_start_xmit;
+ dev->tx_timeout = tulip_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+ dev->stop = tulip_close;
+ dev->get_stats = tulip_get_stats;
+ dev->do_ioctl = private_ioctl;
+ dev->set_multicast_list = set_rx_mode;
+
+ if ((tp->flags & HAS_NWAY143) || tp->chip_id == DC21041)
+ tp->link_change = t21142_lnk_change;
+ else if (tp->flags & HAS_PNICNWAY)
+ tp->link_change = pnic_lnk_change;
+
+ /* Reset the xcvr interface and turn on heartbeat. */
+ switch (chip_idx) {
+ case DC21041:
+ tp->to_advertise = 0x0061;
+ outl(0x00000000, ioaddr + CSR13);
+ outl(0xFFFFFFFF, ioaddr + CSR14);
+ outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */
+ outl_CSR6(tp, inl(ioaddr + CSR6) | 0x0200);
+ outl(0x0000EF05, ioaddr + CSR13);
+ break;
+ case DC21040:
+ outl(0x00000000, ioaddr + CSR13);
+ outl(0x00000004, ioaddr + CSR13);
+ break;
+ case DC21140: default:
+ if (tp->mtable)
+ outl(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
+ break;
+ case DC21142:
+ case PNIC2:
+ if (tp->mii_cnt || media_cap[dev->if_port] & MediaIsMII) {
+ outl_CSR6(tp, 0x82020000);
+ outl(0x0000, ioaddr + CSR13);
+ outl(0x0000, ioaddr + CSR14);
+ outl_CSR6(tp, 0x820E0000);
+ } else
+ t21142_start_nway(dev);
+ break;
+ case LC82C168:
+ if ( ! tp->mii_cnt) {
+ tp->nway = 1;
+ tp->nwayset = 0;
+ outl_CSR6(tp, 0x00420000);
+ outl(0x30, ioaddr + CSR12);
+ outl_CSR6(tp, 0x0001F078);
+ outl_CSR6(tp, 0x0201F078); /* Turn on autonegotiation. */
+ }
+ break;
+ case MX98713: case COMPEX9881:
+ outl_CSR6(tp, 0x00000000);
+ outl(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */
+ outl(0x00000001, ioaddr + CSR13);
+ break;
+ case MX98715: case MX98725:
+ outl_CSR6(tp, 0x01a80000);
+ outl(0xFFFFFFFF, ioaddr + CSR14);
+ outl(0x00001000, ioaddr + CSR12);
+ break;
+ case COMET:
+ /* No initialization necessary. */
+ break;
+ }
+
+ /* put the chip in snooze mode until opened */
+ if (tulip_tbl[chip_idx].flags & HAS_ACPI)
+ pci_write_config_dword(pdev, 0x40, 0x40000000);
+
+ return 0;
+
+err_out_free_netdev:
+ unregister_netdev (dev);
+ kfree (dev);
+ return -ENODEV;
}
-static void __exit tulip_cleanup_module (void)
+
+static void tulip_suspend (struct pci_dev *pdev)
{
- struct net_device *next_dev;
+ struct net_device *dev = pdev->driver_data;
-#ifdef CARDBUS
- unregister_driver(&tulip_ops);
-#endif
+ if (dev && netif_device_present (dev))
+ tulip_down (dev);
+}
+
+
+static void tulip_resume (struct pci_dev *pdev)
+{
+ struct net_device *dev = pdev->driver_data;
- /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
- while (root_tulip_dev) {
- next_dev = ((struct tulip_private *)root_tulip_dev->priv)->next_module;
- unregister_netdev(root_tulip_dev);
- release_region(root_tulip_dev->base_addr, TULIP_TOTAL_SIZE);
- kfree(root_tulip_dev);
- root_tulip_dev = next_dev;
+ if (dev && !netif_device_present (dev))
+ tulip_up (dev);
+}
+
+
+static void __devexit tulip_remove_one (struct pci_dev *pdev)
+{
+ struct net_device *dev = pdev->driver_data;
+
+ if (dev) {
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ unregister_netdev(dev);
+ release_region(dev->base_addr,
+ tulip_tbl[tp->chip_id].io_size);
+ kfree(dev);
}
}
-module_init(tulip_init_module);
-module_exit(tulip_cleanup_module);
+
+static struct pci_driver tulip_driver = {
+ name: TULIP_MODULE_NAME,
+ id_table: tulip_pci_tbl,
+ probe: tulip_init_one,
+ remove: tulip_remove_one,
+ suspend: tulip_suspend,
+ resume: tulip_resume,
+};
-/*
- * Local variables:
- * SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c tulip.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
- * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c tulip.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
- * c-indent-level: 4
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+static int __init tulip_init (void)
+{
+ return pci_module_init (&tulip_driver);
+}
+
+
+static void __exit tulip_cleanup (void)
+{
+ pci_unregister_driver (&tulip_driver);
+}
+
+
+module_init(tulip_init);
+module_exit(tulip_cleanup);
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 5d412d161..abfde3e8a 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -865,11 +865,11 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
np->stats.tx_packets++;
}
/* Free the original skb. */
- kfree_skb(np->tx_skbuff[entry]);
+ dev_kfree_skb_irq(np->tx_skbuff[entry]);
np->tx_skbuff[entry] = 0;
}
if (np->tx_full &&
- test_bit(LINK_STATE_XOFF, &dev->flags) &&
+ netif_queue_stopped(dev) &&
np->cur_tx - np->dirty_tx < TX_RING_SIZE - 4) {
/* The ring is no longer full, clear tbusy. */
np->tx_full = 0;
@@ -1147,13 +1147,13 @@ static int netdev_close(struct net_device *dev)
np->rx_ring[i].rx_length = 0;
np->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */
if (np->rx_skbuff[i]) {
- kfree_skb(np->rx_skbuff[i]);
+ dev_kfree_skb(np->rx_skbuff[i]);
}
np->rx_skbuff[i] = 0;
}
for (i = 0; i < TX_RING_SIZE; i++) {
if (np->tx_skbuff[i])
- kfree_skb(np->tx_skbuff[i]);
+ dev_kfree_skb(np->tx_skbuff[i]);
np->tx_skbuff[i] = 0;
}
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 6883aa69f..873a561ef 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -84,6 +84,7 @@
#include <linux/malloc.h>
#include <linux/poll.h>
#include <linux/fs.h>
+#include <linux/devfs_fs_kernel.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
@@ -359,6 +360,8 @@ static void debug_status_out(struct cosa_data *cosa, int status);
/* ---------- Initialization stuff ---------- */
+static devfs_handle_t devfs_handle = NULL;
+
#ifdef MODULE
int init_module(void)
#else
@@ -366,18 +369,19 @@ static int __init cosa_init(void)
#endif
{
int i;
+
printk(KERN_INFO "cosa v1.06 (c) 1997-8 Jan Kasprzak <kas@fi.muni.cz>\n");
#ifdef __SMP__
printk(KERN_INFO "cosa: SMP found. Please mail any success/failure reports to the author.\n");
#endif
if (cosa_major > 0) {
- if (register_chrdev(cosa_major, "cosa", &cosa_fops)) {
+ if (devfs_register_chrdev(cosa_major, "cosa", &cosa_fops)) {
printk(KERN_WARNING "cosa: unable to get major %d\n",
cosa_major);
return -EIO;
}
} else {
- if (!(cosa_major=register_chrdev(0, "cosa", &cosa_fops))) {
+ if (!(cosa_major=devfs_register_chrdev(0, "cosa", &cosa_fops))) {
printk(KERN_WARNING "cosa: unable to register chardev\n");
return -EIO;
}
@@ -386,9 +390,14 @@ static int __init cosa_init(void)
cosa_cards[i].num = -1;
for (i=0; io[i] != 0 && i < MAX_CARDS; i++)
cosa_probe(io[i], irq[i], dma[i]);
+ devfs_handle = devfs_mk_dir (NULL, "cosa", 4, NULL);
+ devfs_register_series (devfs_handle, "%u", nr_cards, DEVFS_FL_DEFAULT,
+ cosa_major, 0,
+ S_IFCHR | S_IRUSR | S_IWUSR, 0, 0,
+ &cosa_fops, NULL);
if (!nr_cards) {
printk(KERN_WARNING "cosa: no devices found.\n");
- unregister_chrdev(cosa_major, "cosa");
+ devfs_unregister_chrdev(cosa_major, "cosa");
return -ENODEV;
}
return 0;
@@ -397,9 +406,11 @@ static int __init cosa_init(void)
#ifdef MODULE
void cleanup_module (void)
{
+ int i;
struct cosa_data *cosa;
printk(KERN_INFO "Unloading the cosa module\n");
+ devfs_unregister (devfs_handle);
for (cosa=cosa_cards; nr_cards--; cosa++) {
int i;
/* Clean up the per-channel data */
@@ -414,7 +425,7 @@ void cleanup_module (void)
free_dma(cosa->dma);
release_region(cosa->datareg,is_8bit(cosa)?2:4);
}
- unregister_chrdev(cosa_major, "cosa");
+ devfs_unregister_chrdev(cosa_major, "cosa");
}
#endif
diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
index e11c9bcfe..e56125734 100644
--- a/drivers/net/wan/cycx_x25.c
+++ b/drivers/net/wan/cycx_x25.c
@@ -93,6 +93,9 @@
/* This is an extension of the 'struct net_device' we create for each network
interface to keep the rest of X.25 channel-specific data. */
typedef struct x25_channel {
+ /* This member must be first. */
+ struct net_device *slave; /* WAN slave */
+
char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */
char addr[WAN_ADDRESS_SZ+1]; /* media address, ASCIIZ */
char *local_addr; /* local media address, ASCIIZ -
@@ -502,12 +505,10 @@ static int if_open (struct net_device *dev)
x25_channel_t *chan = dev->priv;
cycx_t *card = chan->card;
- if (dev->start)
+ if (netif_running(dev))
return -EBUSY; /* only one open is allowed */
- dev->interrupt = 0;
- dev->tbusy = 0;
- dev->start = 1;
+ netif_start_queue(dev);
cyclomx_mod_inc_use_count(card);
return 0;
@@ -521,8 +522,8 @@ static int if_close (struct net_device *dev)
x25_channel_t *chan = dev->priv;
cycx_t *card = chan->card;
- dev->start = 0;
-
+ netif_stop_queue(dev);
+
if (chan->state == WAN_CONNECTED || chan->state == WAN_CONNECTING)
chan_disconnect(dev);
@@ -556,7 +557,7 @@ static int if_rebuild_hdr (struct sk_buff *skb)
}
/* Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission).
+ * o set busy flag (marks start of the transmission).
* o check link state. If link is not up, then drop the packet.
* o check channel status. If it's down then initiate a call.
* o pass a packet to corresponding WAN device.
@@ -575,11 +576,6 @@ static int if_send (struct sk_buff *skb, struct net_device *dev)
x25_channel_t *chan = dev->priv;
cycx_t *card = chan->card;
- if (dev->tbusy) {
- ++chan->ifstats.rx_dropped;
- return -EBUSY;
- }
-
if (!chan->svc)
chan->protocol = skb->protocol;
@@ -595,14 +591,14 @@ static int if_send (struct sk_buff *skb, struct net_device *dev)
switch (chan->state) {
case WAN_DISCONNECTED:
if (chan_connect(dev)) {
- dev->tbusy = 1;
+ netif_stop_queue(dev);
return -EBUSY;
}
/* fall thru */
case WAN_CONNECTED:
reset_timer(dev);
dev->trans_start = jiffies;
- dev->tbusy = 1;
+ netif_stop_queue(dev);
if (chan_send(dev, skb))
return -EBUSY;
@@ -632,8 +628,8 @@ static int if_send (struct sk_buff *skb, struct net_device *dev)
skb_pull(skb, 1); /* Remove control byte */
reset_timer(dev);
dev->trans_start = jiffies;
- dev->tbusy = 1;
-
+ netif_stop_queue(dev);
+
if (chan_send(dev, skb)) {
/* prepare for future retransmissions */
skb_push(skb, 1);
@@ -705,9 +701,6 @@ static void cyx_isr (cycx_t *card)
cycx_poke(&card->hw, 0, &z, sizeof(z));
cycx_poke(&card->hw, X25_RXMBOX_OFFS, &z, sizeof(z));
card->in_isr = 0;
-
- if (card->buff_int_mode_unbusy)
- mark_bh(NET_BH);
}
/* Transmit interrupt handler.
@@ -724,7 +717,7 @@ static void tx_intr (cycx_t *card, TX25Cmd *cmd)
/* unbusy device and then dev_tint(); */
if ((dev = get_dev_by_lcn(wandev, lcn)) != NULL) {
card->buff_int_mode_unbusy = 1;
- dev->tbusy = 0;
+ netif_wake_queue(dev);
} else
printk(KERN_ERR "%s:ackvc for inexistent lcn %d\n",
card->devname, lcn);
@@ -1263,11 +1256,13 @@ static int x25_send (cycx_t *card, u8 link, u8 lcn, u8 bitm, int len, void *buf)
static struct net_device *get_dev_by_lcn (wan_device_t *wandev, s16 lcn)
{
struct net_device *dev = wandev->dev;
+ x25_channel_t *chan;
- for (; dev; dev = dev->slave)
- if (((x25_channel_t*)dev->priv)->lcn == lcn)
+ while (dev) {
+ if (chan->lcn == lcn)
break;
-
+ dev = chan->slave;
+ }
return dev;
}
@@ -1275,11 +1270,13 @@ static struct net_device *get_dev_by_lcn (wan_device_t *wandev, s16 lcn)
static struct net_device *get_dev_by_dte_addr (wan_device_t *wandev, char *dte)
{
struct net_device *dev = wandev->dev;
+ x25_channel_t *chan;
- for (; dev; dev = dev->slave)
- if (!strcmp(((x25_channel_t*)dev->priv)->addr, dte))
+ while (dev) {
+ if (!strcmp(chan->addr, dte))
break;
-
+ dev = chan->slave;
+ }
return dev;
}
@@ -1357,7 +1354,7 @@ static void set_chan_state (struct net_device *dev, u8 state)
case WAN_CONNECTED:
string_state = "connected!";
*(u16*)dev->dev_addr = htons(chan->lcn);
- dev->tbusy = 0;
+ netif_wake_queue(dev);
reset_timer(dev);
if (chan->protocol == ETH_P_X25)
@@ -1384,7 +1381,7 @@ static void set_chan_state (struct net_device *dev, u8 state)
if (chan->protocol == ETH_P_X25)
chan_x25_send_event(dev, 2);
- dev->tbusy = 0;
+ netif_wake_queue(dev);
break;
}
@@ -1560,15 +1557,16 @@ static void x25_dump_devs(wan_device_t *wandev)
struct net_device *dev = wandev->dev;
printk(KERN_INFO "X.25 dev states\n");
- printk(KERN_INFO "name: addr: tbusy: protocol:\n");
+ printk(KERN_INFO "name: addr: txoff: protocol:\n");
printk(KERN_INFO "---------------------------------------\n");
- for (; dev; dev = dev->slave) {
+ while(dev) {
x25_channel_t *chan = dev->priv;
- printk(KERN_INFO "%-5.5s %-15.15s %ld ETH_P_%s\n",
- chan->name, chan->addr, dev->tbusy,
+ printk(KERN_INFO "%-5.5s %-15.15s %d ETH_P_%s\n",
+ chan->name, chan->addr, netif_queue_stopped(dev),
chan->protocol == ETH_P_IP ? "IP" : "X25");
+ dev = chan->slave;
}
}
diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
index a8c52f0d6..362e7a36e 100644
--- a/drivers/net/wan/dlci.c
+++ b/drivers/net/wan/dlci.c
@@ -244,43 +244,34 @@ static int dlci_transmit(struct sk_buff *skb, struct net_device *dev)
if (!skb || !dev)
return(0);
- if (dev->tbusy)
- return(1);
-
dlp = dev->priv;
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk(KERN_WARNING "%s: transmitter access conflict.\n", dev->name);
- else
+ netif_stop_queue(dev);
+
+ ret = dlp->slave->hard_start_xmit(skb, dlp->slave);
+ switch (ret)
{
- ret = dlp->slave->hard_start_xmit(skb, dlp->slave);
- switch (ret)
- {
- case DLCI_RET_OK:
- dlp->stats.tx_packets++;
- ret = 0;
- break;
-
+ case DLCI_RET_OK:
+ dlp->stats.tx_packets++;
+ ret = 0;
+ break;
case DLCI_RET_ERR:
- dlp->stats.tx_errors++;
- ret = 0;
- break;
-
+ dlp->stats.tx_errors++;
+ ret = 0;
+ break;
case DLCI_RET_DROP:
- dlp->stats.tx_dropped++;
- ret = 1;
- break;
- }
-
- /* Alan Cox recommends always returning 0, and always freeing the packet */
- /* experience suggest a slightly more conservative approach */
-
- if (!ret)
- dev_kfree_skb(skb);
-
- dev->tbusy = 0;
+ dlp->stats.tx_dropped++;
+ ret = 1;
+ break;
}
+ /* Alan Cox recommends always returning 0, and always freeing the packet */
+ /* experience suggest a slightly more conservative approach */
+ if (!ret)
+ {
+ dev_kfree_skb(skb);
+ netif_wake_queue(dev);
+ }
return(ret);
}
@@ -370,19 +361,16 @@ static int dlci_open(struct net_device *dev)
if (!*(short *)(dev->dev_addr))
return(-EINVAL);
- if (!dlp->slave->start)
+ if (!netif_running(dlp->slave))
return(-ENOTCONN);
- dev->flags = 0;
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
-
flp = dlp->slave->priv;
err = (*flp->activate)(dlp->slave, dev);
if (err)
return(err);
+ netif_start_queue(dev);
+
return 0;
}
@@ -392,14 +380,13 @@ static int dlci_close(struct net_device *dev)
struct frad_local *flp;
int err;
+ netif_stop_queue(dev);
+
dlp = dev->priv;
flp = dlp->slave->priv;
err = (*flp->deactivate)(dlp->slave, dev);
- dev->start = 0;
- dev->tbusy = 1;
-
return 0;
}
@@ -508,7 +495,7 @@ int dlci_del(struct dlci_add *dlci)
if (!master)
return(-ENODEV);
- if (master->start)
+ if (netif_running(master))
return(-EBUSY);
dlp = master->priv;
diff --git a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c
index d5c7ebd5e..6220d7fdd 100644
--- a/drivers/net/wan/hostess_sv11.c
+++ b/drivers/net/wan/hostess_sv11.c
@@ -122,7 +122,8 @@ static int hostess_open(struct net_device *d)
/*
* Go go go
*/
- d->tbusy=0;
+
+ netif_start_queue(d);
MOD_INC_USE_COUNT;
return 0;
}
@@ -141,8 +142,8 @@ static int hostess_close(struct net_device *d)
/*
* Link layer down
*/
- d->tbusy=1;
-
+ netif_stop_queue(d);
+
switch(dma)
{
case 0:
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index a4564afcb..1fa07475b 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -163,7 +163,7 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
dev = lapbeth_get_x25_dev(dev);
- if (dev == NULL || dev->start == 0) {
+ if (dev == NULL || !netif_running(dev)) {
kfree_skb(skb);
return 0;
}
@@ -215,7 +215,7 @@ static int lapbeth_xmit(struct sk_buff *skb, struct net_device *dev)
* Just to be *really* sure not to send anything if the interface
* is down, the ethernet device may have gone.
*/
- if (!dev->start) {
+ if (!netif_running(dev)) {
lapbeth_check_devices(dev);
kfree_skb(skb);
return -ENODEV;
@@ -360,9 +360,6 @@ static int lapbeth_open(struct net_device *dev)
if (lapbeth_check_devices(dev))
return -ENODEV; /* oops, it's gone */
- dev->tbusy = 0;
- dev->start = 1;
-
lapbeth = (struct lapbethdev *)dev->priv;
lapbeth_callbacks.connect_confirmation = lapbeth_connected;
@@ -374,12 +371,11 @@ static int lapbeth_open(struct net_device *dev)
if ((err = lapb_register(lapbeth, &lapbeth_callbacks)) != LAPB_OK) {
printk(KERN_ERR "lapbeth: lapb_register error - %d\n", err);
- dev->tbusy = 1;
- dev->start = 0;
return -ENODEV;
}
MOD_INC_USE_COUNT;
+ netif_start_queue(dev);
return 0;
}
@@ -389,9 +385,8 @@ static int lapbeth_close(struct net_device *dev)
struct lapbethdev *lapbeth;
int err;
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
+
lapbeth = (struct lapbethdev *)dev->priv;
if ((err = lapb_unregister(lapbeth)) != LAPB_OK)
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index 4cf0c05a1..b161fbabc 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -59,11 +59,6 @@
#include <linux/version.h>
-#if LINUX_VERSION_CODE >=0x020200
-#define v22
-#endif
-
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -74,6 +69,7 @@
#include <linux/malloc.h>
#include <linux/string.h>
#include <linux/errno.h>
+#include <linux/spinlock.h>
#include <asm/io.h>
#include <asm/types.h>
@@ -88,12 +84,8 @@
#include <net/arp.h>
-
-
-#ifdef v22
#include <asm/uaccess.h>
#include <linux/init.h>
-#endif
#include "sbni.h"
@@ -523,6 +515,7 @@ static int __init sbni_probe1(struct net_device *dev, int ioaddr)
dev->hard_header_cache = sbni_header_cache;
dev->header_cache_update = sbni_header_cache_update;
+ spin_lock_init(&lp->lock);
lp->m=dev;
lp->me=dev;
lp->next_lp=NULL;
@@ -538,15 +531,15 @@ static int sbni_open(struct net_device *dev)
{
struct net_local* lp = (struct net_local*)dev->priv;
struct timer_list* watchdog = &lp->watchdog;
-
+ unsigned long flags;
DP( printk("%s: sbni_open\n", dev->name); )
+ save_flags(flags);
cli();
lp->currframe = NULL;
card_start(dev);
- dev->start = 1;
/* set timer watchdog */
init_timer(watchdog);
watchdog->expires = jiffies + SBNI_TIMEOUT;
@@ -555,8 +548,9 @@ static int sbni_open(struct net_device *dev)
add_timer(watchdog);
DP( printk("%s: sbni timer watchdog initialized\n", dev->name); );
- sti();
-
+ restore_flags(flags);
+
+ netif_start_queue(dev);
MOD_INC_USE_COUNT;
return 0;
}
@@ -566,21 +560,18 @@ static int sbni_close(struct net_device *dev)
int ioaddr = dev->base_addr;
struct net_local* lp = (struct net_local*) dev->priv;
struct timer_list* watchdog = &lp->watchdog;
-
-
+ unsigned long flags;
+
DP( printk("%s: sbni_close\n", dev->name); )
+ netif_stop_queue(dev);
+
+ save_flags(flags);
cli();
-
sbni_drop_tx_queue(dev);
-
- dev->tbusy = 1;
- dev->start = 0;
-
del_timer(watchdog);
-
outb(0, ioaddr + CSR0);
- sti();
+ restore_flags(flags);
MOD_DEC_USE_COUNT;
return 0;
@@ -590,6 +581,7 @@ static int sbni_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct net_local *lp = (struct net_local*)dev->priv;
struct sbni_hard_header *hh=(struct sbni_hard_header *)skb->data;
+ unsigned long flags;
#ifdef KATYUSHA
struct net_local *nl;
@@ -602,13 +594,6 @@ static int sbni_start_xmit(struct sk_buff *skb, struct net_device *dev)
if(lp->me != dev)
panic("sbni: lp->me != dev !!!\nMail to developer (xenon@granch.ru) if you noticed this error\n");
- if(dev->interrupt)
- {
- DP( printk("sbni_xmit_start: interrupt\n"); )
- /* May be unloading, don't stamp on */
- return 1; /* the packet buffer this time */
- }
-
hh->number = 1;
hh->reserv = 0;
@@ -623,6 +608,7 @@ static int sbni_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb->len - sizeof(struct sbni_hard_header),
hh->crc);
+ spin_lock_irqsave(&lp->lock, flags);
#ifdef KATYUSHA
/* looking for first idle device */
for (stop=0,nl=lp; nl && !stop; nl=nl->next_lp)
@@ -657,6 +643,7 @@ static int sbni_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* set request for transmit */
outb(inb(dev->base_addr + CSR0) | TR_REQ, dev->base_addr + CSR0);
#endif
+ spin_unlock_irqrestore(&lp->lock, flags);
return 0;
}
@@ -677,9 +664,6 @@ void card_start(struct net_device *dev)
lp->waitack=0;
skb_queue_head_init(&lp->queue);
sbni_drop_tx_queue(dev);
- dev->tbusy = 0;
-
- dev->interrupt = 0;
/* Reset the card and set start parameters */
outb(PR_RES | *(char*)&lp->csr1, dev->base_addr + CSR1);
outb(EN_INT, dev->base_addr + CSR0);
@@ -776,8 +760,7 @@ static inline unsigned short sbni_recv(struct net_device *dev)
/*
* reset output active flags
*/
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
/*} if */
}
case PACKET_RESEND:
@@ -920,17 +903,12 @@ static void sbni_interrupt(int irq, void *dev_id, struct pt_regs *regs)
return;
}
- if(dev->interrupt)
- {
- printk("%s: Reentering the interrupt driver!\n", dev->name);
- return;
- }
- dev->interrupt = 1;
-
csr0 = inb(dev->base_addr + CSR0);
DP( printk("%s: entering interrupt handler, CSR0 = %02x\n", dev->name, csr0); )
lp=dev->priv;
+
+ spin_lock(&lp->lock);
if(!lp->carrier)
lp->carrier=1;
@@ -971,7 +949,7 @@ static void sbni_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*/
outb(csr0 | EN_INT, dev->base_addr + CSR0);
- dev->interrupt = 0;
+ spin_unlock(&lp->lock);
}
static struct enet_statistics *sbni_get_stats(struct net_device *dev)
@@ -1103,7 +1081,7 @@ static void sbni_watchdog(unsigned long arg)
}
sti();
outb(csr0 | RC_CHK, dev->base_addr + CSR0);
- if(dev->start)
+ if(netif_running(dev))
{
struct timer_list* watchdog = &lp->watchdog;
init_timer(watchdog);
@@ -1167,9 +1145,8 @@ static void sbni_drop_tx_queue(struct net_device *dev)
}
}
lp->waitack=0;
- dev->tbusy = 0;
-
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
+
DP( printk("%s: queue dropping stoped\n",dev->name); );
}
@@ -1194,7 +1171,7 @@ static int sbni_set_mac_address(struct net_device *dev, void *addr)
/* struct net_local *lp = (struct net_local *)dev->priv; */
struct sockaddr *saddr = addr;
- if(dev->start)
+ if(netif_running(dev))
{
/* Only possible while card isn't started */
return -EBUSY;
@@ -1400,13 +1377,11 @@ static int rxl[SBNI_MAX_NUM_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
static int baud[SBNI_MAX_NUM_CARDS] = { 0 };
static long mac[SBNI_MAX_NUM_CARDS] = { 0 };
-#ifdef v22
MODULE_PARM(io, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i");
MODULE_PARM(rxl, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i");
MODULE_PARM(baud, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i");
MODULE_PARM(mac, "1-" __MODULE_STRING(SBNI_MAX_NUM_CARDS) "i");
-#endif
static int sbniautodetect = -1;
diff --git a/drivers/net/wan/sbni.h b/drivers/net/wan/sbni.h
index 2e34d8d34..56550d8f2 100644
--- a/drivers/net/wan/sbni.h
+++ b/drivers/net/wan/sbni.h
@@ -146,7 +146,7 @@ struct net_local {
int carrier;
-
+ spinlock_t lock;
};
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index 29bedf8f9..64165cd0e 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -510,7 +510,7 @@ int sdla_activate(struct net_device *slave, struct net_device *master)
flp->dlci[i] = abs(flp->dlci[i]);
- if (slave->start && (flp->config.station == FRAD_STATION_NODE))
+ if (netif_running(slave) && (flp->config.station == FRAD_STATION_NODE))
sdla_cmd(slave, SDLA_ACTIVATE_DLCI, 0, 0, &flp->dlci[i], sizeof(short), NULL, NULL);
return(0);
@@ -532,7 +532,7 @@ int sdla_deactivate(struct net_device *slave, struct net_device *master)
flp->dlci[i] = -abs(flp->dlci[i]);
- if (slave->start && (flp->config.station == FRAD_STATION_NODE))
+ if (netif_running(slave) && (flp->config.station == FRAD_STATION_NODE))
sdla_cmd(slave, SDLA_DEACTIVATE_DLCI, 0, 0, &flp->dlci[i], sizeof(short), NULL, NULL);
return(0);
@@ -565,7 +565,7 @@ int sdla_assoc(struct net_device *slave, struct net_device *master)
flp->dlci[i] = -*(short *)(master->dev_addr);
master->mtu = slave->mtu;
- if (slave->start) {
+ if (netif_running(dev)) {
if (flp->config.station == FRAD_STATION_CPE)
sdla_reconfig(slave);
else
@@ -594,7 +594,7 @@ int sdla_deassoc(struct net_device *slave, struct net_device *master)
MOD_DEC_USE_COUNT;
- if (slave->start) {
+ if (netif_running(slave)) {
if (flp->config.station == FRAD_STATION_CPE)
sdla_reconfig(slave);
else
@@ -624,7 +624,7 @@ int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
ret = SDLA_RET_OK;
len = sizeof(struct dlci_conf);
- if (slave->start) {
+ if (netif_running(slave)) {
if (get)
ret = sdla_cmd(slave, SDLA_READ_DLCI_CONFIGURATION, abs(flp->dlci[i]), 0,
NULL, 0, &dlp->config, &len);
@@ -646,7 +646,7 @@ int sdla_dlci_conf(struct net_device *slave, struct net_device *master, int get)
static int sdla_transmit(struct sk_buff *skb, struct net_device *dev)
{
struct frad_local *flp;
- int ret, addr, accept;
+ int ret, addr, accept, i;
short size;
unsigned long flags;
struct buf_entry *pbuf;
@@ -655,90 +655,80 @@ static int sdla_transmit(struct sk_buff *skb, struct net_device *dev)
ret = 0;
accept = 1;
- if (dev->tbusy)
- return(1);
+ netif_stop_queue(dev);
- if (skb == NULL)
- return(0);
+ /*
+ * stupid GateD insists on setting up the multicast router thru us
+ * and we're ill equipped to handle a non Frame Relay packet at this
+ * time!
+ */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk(KERN_WARNING "%s: transmitter access conflict.\n", dev->name);
- else
+ accept = 1;
+ switch (dev->type)
{
- /*
- * stupid GateD insists on setting up the multicast router thru us
- * and we're ill equipped to handle a non Frame Relay packet at this
- * time!
- */
-
- accept = 1;
- switch (dev->type)
+ case ARPHRD_FRAD:
+ if (skb->dev->type != ARPHRD_DLCI)
+ {
+ printk(KERN_WARNING "%s: Non DLCI device, type %i, tried to send on FRAD module.\n", dev->name, skb->dev->type);
+ accept = 0;
+ }
+ break;
+ default:
+ printk(KERN_WARNING "%s: unknown firmware type 0x%4.4X\n", dev->name, dev->type);
+ accept = 0;
+ break;
+ }
+ if (accept)
+ {
+ /* this is frame specific, but till there's a PPP module, it's the default */
+ switch (flp->type)
{
- case ARPHRD_FRAD:
- if (skb->dev->type != ARPHRD_DLCI)
+ case SDLA_S502A:
+ case SDLA_S502E:
+ ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, skb->data, skb->len, NULL, NULL);
+ break;
+ case SDLA_S508:
+ size = sizeof(addr);
+ ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, NULL, skb->len, &addr, &size);
+ if (ret == SDLA_RET_OK)
{
- printk(KERN_WARNING "%s: Non DLCI device, type %i, tried to send on FRAD module.\n", dev->name, skb->dev->type);
- accept = 0;
+ save_flags(flags);
+ cli();
+ SDLA_WINDOW(dev, addr);
+ pbuf = (void *)(((int) dev->mem_start) + (addr & SDLA_ADDR_MASK));
+ sdla_write(dev, pbuf->buf_addr, skb->data, skb->len);
+ SDLA_WINDOW(dev, addr);
+ pbuf->opp_flag = 1;
+ restore_flags(flags);
}
break;
-
- default:
- printk(KERN_WARNING "%s: unknown firmware type 0x%4.4X\n", dev->name, dev->type);
- accept = 0;
- break;
}
-
- if (accept)
+ switch (ret)
{
- /* this is frame specific, but till there's a PPP module, it's the default */
- switch (flp->type)
- {
- case SDLA_S502A:
- case SDLA_S502E:
- ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, skb->data, skb->len, NULL, NULL);
- break;
-
- case SDLA_S508:
- size = sizeof(addr);
- ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, NULL, skb->len, &addr, &size);
- if (ret == SDLA_RET_OK)
- {
- save_flags(flags);
- cli();
- SDLA_WINDOW(dev, addr);
- pbuf = (void *)(((int) dev->mem_start) + (addr & SDLA_ADDR_MASK));
-
- sdla_write(dev, pbuf->buf_addr, skb->data, skb->len);
-
- SDLA_WINDOW(dev, addr);
- pbuf->opp_flag = 1;
- restore_flags(flags);
- }
- break;
- }
-
- switch (ret)
- {
- case SDLA_RET_OK:
- flp->stats.tx_packets++;
- ret = DLCI_RET_OK;
- break;
+ case SDLA_RET_OK:
+ flp->stats.tx_packets++;
+ ret = DLCI_RET_OK;
+ break;
- case SDLA_RET_CIR_OVERFLOW:
- case SDLA_RET_BUF_OVERSIZE:
- case SDLA_RET_NO_BUFS:
- flp->stats.tx_dropped++;
- ret = DLCI_RET_DROP;
- break;
+ case SDLA_RET_CIR_OVERFLOW:
+ case SDLA_RET_BUF_OVERSIZE:
+ case SDLA_RET_NO_BUFS:
+ flp->stats.tx_dropped++;
+ ret = DLCI_RET_DROP;
+ break;
- default:
- flp->stats.tx_errors++;
- ret = DLCI_RET_ERR;
- break;
- }
+ default:
+ flp->stats.tx_errors++;
+ ret = DLCI_RET_ERR;
+ break;
}
- dev->tbusy = 0;
}
+ netif_wake_queue(dev);
+ for(i=0;i<CONFIG_DLCI_MAX;i++)
+ {
+ if(flp->master[i]!=NULL)
+ netif_wake_queue(flp->master[i]);
+ }
return(ret);
}
@@ -892,7 +882,6 @@ static void sdla_isr(int irq, void *dev_id, struct pt_regs * regs)
return;
}
- dev->interrupt = 1;
byte = sdla_byte(dev, flp->type == SDLA_S508 ? SDLA_508_IRQ_INTERFACE : SDLA_502_IRQ_INTERFACE);
switch (byte)
{
@@ -925,7 +914,6 @@ static void sdla_isr(int irq, void *dev_id, struct pt_regs * regs)
/* this clears the byte, informing the Z80 we're done */
byte = 0;
sdla_write(dev, flp->type == SDLA_S508 ? SDLA_508_IRQ_INTERFACE : SDLA_502_IRQ_INTERFACE, &byte, sizeof(byte));
- dev->interrupt = 0;
}
static void sdla_poll(unsigned long device)
@@ -992,9 +980,8 @@ static int sdla_close(struct net_device *dev)
sdla_cmd(dev, SDLA_DISABLE_COMMUNICATIONS, 0, 0, NULL, 0, NULL, NULL);
- dev->tbusy = 1;
- dev->start = 0;
-
+ netif_stop_queue(dev);
+
MOD_DEC_USE_COUNT;
return(0);
@@ -1096,10 +1083,8 @@ static int sdla_open(struct net_device *dev)
sdla_cmd(dev, SDLA_SET_DLCI_CONFIGURATION, abs(flp->dlci[i]), 0, &dlp->config, sizeof(struct dlci_conf), NULL, NULL);
}
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
-
+ netif_start_queue(dev);
+
MOD_INC_USE_COUNT;
return(0);
@@ -1119,7 +1104,7 @@ static int sdla_config(struct net_device *dev, struct frad_conf *conf, int get)
if (!get)
{
- if (dev->start)
+ if (netif_running(dev))
return(-EBUSY);
if(copy_from_user(&data.config, conf, sizeof(struct frad_conf)))
@@ -1182,7 +1167,7 @@ static int sdla_config(struct net_device *dev, struct frad_conf *conf, int get)
else
{
/* no sense reading if the CPU isn't started */
- if (dev->start)
+ if (netif_running(dev))
{
size = sizeof(data);
if (sdla_cmd(dev, SDLA_READ_DLCI_CONFIGURATION, 0, 0, NULL, 0, &data, &size) != SDLA_RET_OK)
@@ -1331,7 +1316,7 @@ int sdla_change_mtu(struct net_device *dev, int new_mtu)
flp = dev->priv;
- if (dev->start)
+ if (netif_running(dev))
return(-EBUSY);
/* for now, you can't change the MTU! */
diff --git a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c
index 3df910ea1..c0b419afa 100644
--- a/drivers/net/wan/sdla_chdlc.c
+++ b/drivers/net/wan/sdla_chdlc.c
@@ -74,6 +74,9 @@
typedef struct chdlc_private_area
{
+ /* This member must be first. */
+ struct net_device *slave; /* WAN slave */
+
sdla_t *card;
int TracingEnabled; /* For enabling Tracing */
unsigned long curr_trace_addr; /* Used for Tracing */
diff --git a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c
index 0c7f7e8f0..f4431c9dc 100644
--- a/drivers/net/wan/sdla_fr.c
+++ b/drivers/net/wan/sdla_fr.c
@@ -167,6 +167,9 @@
*/
typedef struct fr_channel
{
+ /* This member must be first. */
+ struct net_device *slave; /* WAN slave */
+
char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */
unsigned dlci_configured ; /* check whether configured or not */
unsigned cir_status; /* check whether CIR enabled or not */
@@ -1960,7 +1963,9 @@ goto L4;
// Used to send inarp request at given interval
if (card->wandev.state == WAN_CONNECTED) {
int num_remaining = 0;
- for (dev=card->wandev.dev;dev;dev=dev->slave) {
+
+ dev = card->wandev.dev;
+ while (dev) {
fr_channel_t *chan = dev->priv;
if (chan->inarp == INARP_REQUEST &&
@@ -1972,6 +1977,7 @@ goto L4;
chan->inarp_tick = jiffies;
}
}
+ dev = chan->slave;
}
if (!num_remaining) { // no more to process
flags->imask &= ~FR_INTR_TIMER;
@@ -2135,65 +2141,68 @@ static void process_route (sdla_t* card)
/* Dynamic Route adding/removing */
- for (dev = card->wandev.dev; dev ; dev = dev->slave) {
- if ( ((fr_channel_t*)dev->priv)->route_flag == ADD_ROUTE ||
- ((fr_channel_t*)dev->priv)->route_flag == REMOVE_ROUTE ) {
- fs = get_fs();
+ dev = card->wandev.dev;
+ while (dev) {
+ fr_channel_t *chan = dev->priv;
+
+ if (chan->route_flag == ADD_ROUTE ||
+ chan->route_flag == REMOVE_ROUTE ) {
+ fs = get_fs();
- in_dev = dev->ip_ptr;
-
- if( in_dev != NULL && in_dev->ifa_list != NULL) {
- memset(&route, 0, sizeof(route));
- route.rt_dev = dev->name;
- route.rt_flags = 0;
-
- ((struct sockaddr_in *) &(route.rt_dst)) ->
- sin_addr.s_addr=in_dev->ifa_list->ifa_address;
- ((struct sockaddr_in *) &(route.rt_dst)) ->
- sin_family = AF_INET;
- ((struct sockaddr_in *) &(route.rt_genmask)) ->
- sin_addr.s_addr = 0xFFFFFFFF;
- ((struct sockaddr_in *) &(route.rt_genmask)) ->
- sin_family = AF_INET;
-
- switch(((fr_channel_t*)dev->priv)->route_flag) {
-
- case ADD_ROUTE:
- set_fs(get_ds()); /* get user space block */
- err = ip_rt_ioctl( SIOCADDRT, &route);
- set_fs(fs); /* restore old block */
-
- if (err) {
- printk(KERN_INFO "%s: Adding of route failed. Error: %d\n", card->devname,err);
- printk(KERN_INFO "%s: Address: %s\n",
- ((fr_channel_t*)dev->priv)->name,
- in_ntoa(in_dev->ifa_list->ifa_address) );
- }
- else {
- ((fr_channel_t*)dev->priv)->
- route_flag = ROUTE_ADDED;
- }
- break;
+ in_dev = dev->ip_ptr;
+
+ if( in_dev != NULL && in_dev->ifa_list != NULL) {
+ memset(&route, 0, sizeof(route));
+ route.rt_dev = dev->name;
+ route.rt_flags = 0;
+
+ ((struct sockaddr_in *) &(route.rt_dst)) ->
+ sin_addr.s_addr=in_dev->ifa_list->ifa_address;
+ ((struct sockaddr_in *) &(route.rt_dst)) ->
+ sin_family = AF_INET;
+ ((struct sockaddr_in *) &(route.rt_genmask)) ->
+ sin_addr.s_addr = 0xFFFFFFFF;
+ ((struct sockaddr_in *) &(route.rt_genmask)) ->
+ sin_family = AF_INET;
+
+ switch(chan->route_flag) {
+
+ case ADD_ROUTE:
+ set_fs(get_ds()); /* get user space block */
+ err = ip_rt_ioctl( SIOCADDRT, &route);
+ set_fs(fs); /* restore old block */
+
+ if (err) {
+ printk(KERN_INFO "%s: Adding of route failed. Error: %d\n", card->devname,err);
+ printk(KERN_INFO "%s: Address: %s\n",
+ chan->name,
+ in_ntoa(in_dev->ifa_list->ifa_address) );
+ } else {
+ chan->route_flag = ROUTE_ADDED;
+ }
+ break;
- case REMOVE_ROUTE:
- set_fs(get_ds()); /* get user space block */
- err = ip_rt_ioctl( SIOCDELRT, &route);
- set_fs(fs); /* restore old block */
+ case REMOVE_ROUTE:
+ set_fs(get_ds()); /* get user space block */
+ err = ip_rt_ioctl( SIOCDELRT, &route);
+ set_fs(fs); /* restore old block */
+
+ if (err) {
+ printk(KERN_INFO "%s: Deleting of route failed. Error: %d\n", card->devname,err);
+ printk(KERN_INFO "%s: Address: %s\n",
+ dev->name,in_ntoa(in_dev->ifa_list->ifa_address) );
+ } else {
+ printk(KERN_INFO "%s: Removed route.\n",
+ chan->name);
+ chan->route_flag = NO_ROUTE;
+ }
+ break;
+ } /* Case Statement */
+ }
+ } /* If ADD/DELETE ROUTE */
- if (err) {
- printk(KERN_INFO "%s: Deleting of route failed. Error: %d\n", card->devname,err);
- printk(KERN_INFO "%s: Address: %s\n",
- dev->name,in_ntoa(in_dev->ifa_list->ifa_address) );
- } else {
- printk(KERN_INFO "%s: Removed route.\n",
- ((fr_channel_t*)dev->priv)->name);
- ((fr_channel_t*)dev->priv)->route_flag = NO_ROUTE;
- }
- break;
- } /* Case Statement */
- }
- } /* If ADD/DELETE ROUTE */
- } /* Device 'For' Loop */
+ dev = chan->slave;
+ } /* Device 'While' Loop */
card->poll = NULL;
}
@@ -2568,7 +2577,8 @@ static int fr_event (sdla_t *card, int event, fr_mbox_t* mbox)
struct net_device *dev;
/* Remove all routes from associated DLCI's */
- for (dev = card->wandev.dev; dev; dev = dev->slave) {
+ dev = card->wandev.dev;
+ while (dev) {
fr_channel_t *chan = dev->priv;
if (chan->route_flag == ROUTE_ADDED) {
chan->route_flag = REMOVE_ROUTE;
@@ -2578,6 +2588,8 @@ static int fr_event (sdla_t *card, int event, fr_mbox_t* mbox)
if (chan->inarp == INARP_CONFIGURED) {
chan->inarp = INARP_REQUEST;
}
+
+ dev = chan->slave;
}
wanpipe_set_state(card, WAN_DISCONNECTED);
@@ -2590,12 +2602,14 @@ static int fr_event (sdla_t *card, int event, fr_mbox_t* mbox)
int num_requests = 0;
/* Remove all routes from associated DLCI's */
- for (dev = card->wandev.dev; dev; dev = dev->slave) {
+ dev = card->wandev.dev;
+ while (dev) {
fr_channel_t *chan = dev->priv;
if( chan->inarp == INARP_REQUEST ){
num_requests++;
chan->inarp_tick = jiffies;
}
+ dev = chan->slave;
}
/* Allow timer interrupts */
@@ -2731,8 +2745,8 @@ static int fr_dlci_change (sdla_t *card, fr_mbox_t* mbox)
}
}
- for (dev2 =card->wandev.dev; dev2; dev2 = dev2->slave){
-
+ dev2 = card->wandev.dev;
+ while (dev2) {
chan = dev2->priv;
if (chan->dlci_configured == DLCI_CONFIG_PENDING) {
@@ -2741,6 +2755,7 @@ static int fr_dlci_change (sdla_t *card, fr_mbox_t* mbox)
}
}
+ dev2 = chan->slave;
}
return 1;
}
diff --git a/drivers/net/wan/sdla_ppp.c b/drivers/net/wan/sdla_ppp.c
index 1b900fc62..f3dcc129b 100644
--- a/drivers/net/wan/sdla_ppp.c
+++ b/drivers/net/wan/sdla_ppp.c
@@ -155,6 +155,9 @@
typedef struct ppp_private_area
{
+ /* This member must be first. */
+ struct net_device *slave; /* WAN slave */
+
sdla_t* card;
unsigned long router_start_time; /*router start time in sec */
unsigned long tick_counter; /*used for 5 second counter*/
diff --git a/drivers/net/wan/sdla_x25.c b/drivers/net/wan/sdla_x25.c
index 270c5a59f..dfb5d36a5 100644
--- a/drivers/net/wan/sdla_x25.c
+++ b/drivers/net/wan/sdla_x25.c
@@ -75,6 +75,9 @@
*/
typedef struct x25_channel
{
+ /* This member must be first. */
+ struct net_device *slave; /* WAN slave */
+
char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */
char addr[WAN_ADDRESS_SZ+1]; /* media address, ASCIIZ */
unsigned lcn; /* logical channel number */
@@ -708,11 +711,13 @@ static int if_send (struct sk_buff* skb, struct net_device* dev)
return dev->tbusy;
}
printk(KERN_INFO "%s: Transmit time out %s!\n",
- card->devname, dev->name)
- ;
- for( dev2 = card->wandev.dev; dev2; dev2 = dev2->slave)
- {
+ card->devname, dev->name);
+
+ dev2 = card->wandev.dev;
+ while (dev2) {
+ x25_channel_t *chan2 = dev2->priv;
dev2->tbusy = 0;
+ dev2 = chan2->slave;
}
}
chan->tick_counter = jiffies;
@@ -898,13 +903,17 @@ static void wpx_isr (sdla_t* card)
if(card->buff_int_mode_unbusy)
{
- for(dev = card->wandev.dev; dev; dev = dev->slave)
- {
- if(((x25_channel_t*)dev->priv)->devtint)
- {
+ x25_channel_t *chan;
+
+ dev = card->wandev.dev;
+ while (dev) {
+ chan = dev->priv;
+ if(chan->devtint) {
mark_bh(NET_BH);
return;
}
+
+ dev = chan->slave;
}
}
}
@@ -1042,12 +1051,15 @@ static void rx_intr (sdla_t* card)
static void tx_intr (sdla_t* card)
{
struct net_device *dev;
+ x25_channel_t *chan;
/* unbusy all devices and then dev_tint(); */
- for(dev = card->wandev.dev; dev; dev = dev->slave)
- {
- ((x25_channel_t*)dev->priv)->devtint = dev->tbusy;
+ dev = card->wandev.dev;
+ while (dev) {
+ chan->devtint = dev->tbusy;
dev->tbusy = 0;
+
+ dev = chan->slave;
}
}
@@ -1170,8 +1182,8 @@ static void poll_active (sdla_t* card)
/* Fetch X.25 asynchronous events */
x25_fetch_events(card);
- for (dev = card->wandev.dev; dev; dev = dev->slave)
- {
+ dev = card->wandev.dev;
+ while (dev) {
x25_channel_t* chan = dev->priv;
struct sk_buff* skb = chan->tx_skb;
@@ -1199,6 +1211,8 @@ static void poll_active (sdla_t* card)
chan_disc(dev);
}
}
+
+ dev = chan->slave;
}
}
@@ -1785,8 +1799,8 @@ static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
card->devname, new_lcn, mb->data);
/* Find available channel */
- for (dev = wandev->dev; dev; dev = dev->slave)
- {
+ dev = wandev->dev;
+ while (dev) {
chan = dev->priv;
if (!chan->svc || (chan->state != WAN_DISCONNECTED))
@@ -1796,6 +1810,8 @@ static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
/* If just an '@' is specified, accept all incoming calls */
if (strcmp(chan->addr, "") == 0)
break;
+
+ dev = chan->slave;
}
if (dev == NULL)
@@ -1912,8 +1928,14 @@ static int restart_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
card->devname, mb->cmd.cause, mb->cmd.diagn);
/* down all logical channels */
- for (dev = wandev->dev; dev; dev = dev->slave)
+ dev = wandev->dev;
+ while (dev) {
+ x25_channel_t *chan = dev->priv;
+
set_chan_state(dev, WAN_DISCONNECTED);
+ dev = chan->slave;
+ }
+
return (cmd == X25_WRITE) ? 0 : 1;
}
@@ -1979,10 +2001,14 @@ static int disconnect (sdla_t* card)
static struct net_device* get_dev_by_lcn (wan_device_t* wandev, unsigned lcn)
{
struct net_device* dev;
+ x25_channel_t *chan;
- for (dev = wandev->dev; dev; dev = dev->slave)
- if (((x25_channel_t*)dev->priv)->lcn == lcn)
+ dev = wandev->dev;
+ while (dev) {
+ if (chan->lcn == lcn)
break;
+ dev = chan->slave;
+ }
return dev;
}
diff --git a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c
index 90cccf81d..8fd2ff105 100644
--- a/drivers/net/wan/sealevel.c
+++ b/drivers/net/wan/sealevel.c
@@ -119,7 +119,7 @@ static int sealevel_open(struct net_device *d)
/*
* Go go go
*/
- d->tbusy=0;
+ netif_start_queue(d);
MOD_INC_USE_COUNT;
return 0;
}
@@ -142,8 +142,9 @@ static int sealevel_close(struct net_device *d)
/*
* Link layer down
*/
- d->tbusy=1;
-
+
+ netif_stop_queue(d);
+
switch(unit)
{
case 0:
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index e50865d97..7b647d663 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -205,8 +205,7 @@ static void x25_asy_changed_mtu(struct x25_asy *sl)
static inline void x25_asy_lock(struct x25_asy *sl)
{
- if (test_and_set_bit(0, (void *) &sl->dev->tbusy))
- printk("%s: trying to lock already locked device!\n", sl->dev->name);
+ netif_stop_queue(sl->dev);
}
@@ -214,8 +213,7 @@ static inline void x25_asy_lock(struct x25_asy *sl)
static inline void x25_asy_unlock(struct x25_asy *sl)
{
- if (!test_and_clear_bit(0, (void *)&sl->dev->tbusy))
- printk("%s: trying to unlock already unlocked device!\n", sl->dev->name);
+ netif_wake_queue(sl->dev);
}
/* Send one completely decapsulated IP datagram to the IP layer. */
@@ -303,7 +301,7 @@ static void x25_asy_write_wakeup(struct tty_struct *tty)
struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
/* First make sure we're connected. */
- if (!sl || sl->magic != X25_ASY_MAGIC || !sl->dev->start)
+ if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev))
return;
if (sl->xleft <= 0)
@@ -313,7 +311,6 @@ static void x25_asy_write_wakeup(struct tty_struct *tty)
sl->tx_packets++;
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
x25_asy_unlock(sl);
- mark_bh(NET_BH);
return;
}
@@ -322,6 +319,20 @@ static void x25_asy_write_wakeup(struct tty_struct *tty)
sl->xhead += actual;
}
+static void x25_asy_timeout(struct net_device *dev)
+{
+ struct x25_asy *sl = (struct x25_asy*)(dev->priv);
+ /* May be we must check transmitter timeout here ?
+ * 14 Oct 1994 Dmitry Gorodchanin.
+ */
+ printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
+ (sl->tty->driver.chars_in_buffer(sl->tty) || sl->xleft) ?
+ "bad line quality" : "driver error");
+ sl->xleft = 0;
+ sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+ x25_asy_unlock(sl);
+}
+
/* Encapsulate an IP datagram and kick it into a TTY queue. */
static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -329,7 +340,7 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
struct x25_asy *sl = (struct x25_asy*)(dev->priv);
int err;
- if (!dev->start)
+ if (!netif_running(sl->dev))
{
printk("%s: xmit call when iface is down\n", dev->name);
return 1;
@@ -361,25 +372,6 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
* So, no queues !
* 14 Oct 1994 Dmitry Gorodchanin.
*/
- if (dev->tbusy) {
- /* May be we must check transmitter timeout here ?
- * 14 Oct 1994 Dmitry Gorodchanin.
- */
-#ifdef SL_CHECK_TRANSMIT
- if (jiffies - dev->trans_start < 20 * HZ) {
- /* 20 sec timeout not reached */
- return 1;
- }
- printk("%s: transmit timed out, %s?\n", dev->name,
- (sl->tty->driver.chars_in_buffer(sl->tty) || sl->xleft) ?
- "bad line quality" : "driver error");
- sl->xleft = 0;
- sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
- x25_asy_unlock(sl);
-#else
- return 1;
-#endif
- }
if((err=lapb_data_request(sl,skb))!=LAPB_OK)
{
@@ -414,7 +406,7 @@ static void x25_asy_data_indication(void *token, struct sk_buff *skb)
static void x25_asy_data_transmit(void *token, struct sk_buff *skb)
{
struct x25_asy *sl=token;
- if(sl->dev->tbusy)
+ if (netif_queue_stopped(sl->dev))
{
printk(KERN_ERR "x25_asy: tbusy drop\n");
kfree_skb(skb);
@@ -514,10 +506,8 @@ static int x25_asy_open(struct net_device *dev)
sl->xleft = 0;
sl->flags &= (1 << SLF_INUSE); /* Clear ESCAPE & ERROR flags */
- dev->tbusy = 0;
-/* dev->flags |= IFF_UP; */
- dev->start = 1;
-
+ netif_start_queue(dev);
+
/*
* Now attach LAPB
*/
@@ -551,12 +541,9 @@ static int x25_asy_close(struct net_device *dev)
return -EBUSY;
sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue(dev);
if((err=lapb_unregister(sl))!=LAPB_OK)
printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",err);
-
-/* dev->flags &= ~IFF_UP; */
return 0;
}
@@ -576,7 +563,7 @@ static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp,
{
struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
- if (!sl || sl->magic != X25_ASY_MAGIC || !sl->dev->start)
+ if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev))
return;
/*
@@ -876,6 +863,8 @@ int x25_asy_init(struct net_device *dev)
dev->mtu = SL_MTU;
dev->hard_start_xmit = x25_asy_xmit;
+ dev->tx_timeout = x25_asy_timeout;
+ dev->watchdog_timeo = HZ*20;
dev->open = x25_asy_open_dev;
dev->stop = x25_asy_close;
dev->get_stats = x25_asy_get_stats;
@@ -914,7 +903,7 @@ cleanup_module(void)
* VSV = if dev->start==0, then device
* unregistered while close proc.
*/
- if (x25_asy_ctrls[i]->dev.start)
+ if (netif_running(&(x25_asy_ctrls[i]->dev)))
unregister_netdev(&(x25_asy_ctrls[i]->dev));
kfree(x25_asy_ctrls[i]);
diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c
index f6b385de5..2ff818b04 100644
--- a/drivers/net/wan/z85230.c
+++ b/drivers/net/wan/z85230.c
@@ -54,12 +54,23 @@
static spinlock_t z8530_buffer_lock = SPIN_LOCK_UNLOCKED;
-/*
+/**
+ * z8530_read_port:
+ * @p: port to read
+ *
* Provided port access methods. The Comtrol SV11 requires no delays
* between accesses and uses PC I/O. Some drivers may need a 5uS delay
+ *
+ * In the longer term this should become an architecture specific
+ * section so that this can become a generic driver interface for all
+ * platforms. For now we only handle PC I/O ports with or without the
+ * dread 5uS sanity delay.
+ *
+ * The caller must hold sufficient locks to avoid violating the horrible
+ * 5uS delay rule.
*/
-extern __inline__ int z8530_read_port(int p)
+extern __inline__ int z8530_read_port(unsigned long p)
{
u8 r=inb(Z8530_PORT_OF(p));
if(p&Z8530_PORT_SLEEP) /* gcc should figure this out efficiently ! */
@@ -67,7 +78,23 @@ extern __inline__ int z8530_read_port(int p)
return r;
}
-extern __inline__ void z8530_write_port(int p, u8 d)
+/**
+ * z8530_write_port:
+ * @p: port to write
+ * @d: value to write
+ *
+ * Write a value to a port with delays if need be. Note that the
+ * caller must hold locks to avoid read/writes from other contexts
+ * violating the 5uS rule
+ *
+ * In the longer term this should become an architecture specific
+ * section so that this can become a generic driver interface for all
+ * platforms. For now we only handle PC I/O ports with or without the
+ * dread 5uS sanity delay.
+ */
+
+
+extern __inline__ void z8530_write_port(unsigned long p, u8 d)
{
outb(d,Z8530_PORT_OF(p));
if(p&Z8530_PORT_SLEEP)
@@ -80,8 +107,16 @@ static void z8530_rx_done(struct z8530_channel *c);
static void z8530_tx_done(struct z8530_channel *c);
-/*
- * Port accesses
+/**
+ * read_zsreg:
+ * @c: Z8530 channel to read from (2 per chip)
+ * @reg: Register to read
+ * FIXME: Use a spinlock.
+ *
+ * Most of the Z8530 registers are indexed off the control registers.
+ * A read is done by writing to the control register and reading the
+ * register back. We do the locking needed to protect this
+ * operation.
*/
extern inline u8 read_zsreg(struct z8530_channel *c, u8 reg)
@@ -97,6 +132,14 @@ extern inline u8 read_zsreg(struct z8530_channel *c, u8 reg)
return r;
}
+/**
+ * read_zsdata:
+ * @c: The Z8530 channel to read the data port from
+ *
+ * The data port provides fast access to some things. We still
+ * have all the 5uS delays to worry about.
+ */
+
extern inline u8 read_zsdata(struct z8530_channel *c)
{
u8 r;
@@ -104,6 +147,17 @@ extern inline u8 read_zsdata(struct z8530_channel *c)
return r;
}
+/**
+ * write_zsreg:
+ * @c: The Z8530 channel
+ * @reg: Register number
+ * @val: Value to write
+ *
+ * Write a value to an indexed register. Perform the locking needed
+ * to honour the irritating delay rules. We know about register 0
+ * being fast to access.
+ */
+
extern inline void write_zsreg(struct z8530_channel *c, u8 reg, u8 val)
{
unsigned long flags;
@@ -194,8 +248,16 @@ u8 z8530_hdlc_kilostream_85230[]=
EXPORT_SYMBOL(z8530_hdlc_kilostream_85230);
-/*
- * Flush the FIFO
+/**
+ * z8530_flush_fifo:
+ * @c: Channel to flush
+ *
+ * Flush the receive FIFO. There is no specific option for this, we
+ * blindly read bytes and discard them. Reading when there is no data
+ * is harmless. The 8530 has a 4 byte FIFO, the 85230 has 8 bytes.
+ *
+ * All locking is handled for the caller. On return data may still be
+ * present if it arrived during the flush.
*/
static void z8530_flush_fifo(struct z8530_channel *c)
@@ -213,7 +275,16 @@ static void z8530_flush_fifo(struct z8530_channel *c)
}
}
-/* Sets or clears DTR/RTS on the requested line */
+/**
+ * z8530_rtsdtr:
+ * @c: The Z8530 channel to contro;
+ * @set: 1 to set, 0 to clear
+ *
+ * Sets or clears DTR/RTS on the requested line. All locking is handled
+ * for the caller. For now we assume all boards use the actual RTS/DTR
+ * on the chip. Apparently one or two don't. We'll scream about them
+ * later.
+ */
static void z8530_rtsdtr(struct z8530_channel *c, int set)
{
@@ -224,9 +295,12 @@ static void z8530_rtsdtr(struct z8530_channel *c, int set)
write_zsreg(c, R5, c->regs[5]);
}
-/*
- * Receive handler. This is much like the async one but not quite the
- * same or as complex
+/**
+ * z8530_rx:
+ * @c: Z8530 channel to process
+ *
+ * Receive handler for receiving in PIO mode. This is much like the
+ * async one but not quite the same or as complex
*
* Note: Its intended that this handler can easily be separated from
* the main code to run realtime. That'll be needed for some machines
@@ -238,9 +312,9 @@ static void z8530_rtsdtr(struct z8530_channel *c, int set)
* other code - this is true in the RT case too.
*
* We only cover the sync cases for this. If you want 2Mbit async
- * do it yourself but consider medical assistance first.
- *
- * This non DMA synchronous mode is portable code.
+ * do it yourself but consider medical assistance first. This non DMA
+ * synchronous mode is portable code. The DMA mode assumes PCI like
+ * ISA DMA
*/
static void z8530_rx(struct z8530_channel *c)
@@ -303,8 +377,14 @@ static void z8530_rx(struct z8530_channel *c)
}
-/*
- * Z8530 transmit interrupt handler
+/**
+ * z8530_tx:
+ * @c: Z8530 channel to process
+ *
+ * Z8530 transmit interrupt handler for the PIO mode. The basic
+ * idea is to attempt to keep the FIFO fed. We fill as many bytes
+ * in as possible, its quite possible that we won't keep up with the
+ * data rate otherwise.
*/
static void z8530_tx(struct z8530_channel *c)
@@ -340,6 +420,17 @@ static void z8530_tx(struct z8530_channel *c)
write_zsctrl(c, RES_H_IUS);
}
+/**
+ * z8530_status:
+ * @chan: Z8530 channel to process
+ *
+ * A status event occured in PIO synchronous mode. There are several
+ * reasons the chip will bother us here. A transmit underrun means we
+ * failed to feed the chip fast enough and just broke a packet. A DCD
+ * change is a line up or down. We communicate that back to the protocol
+ * layer for synchronous PPP to renegotiate.
+ */
+
static void z8530_status(struct z8530_channel *chan)
{
u8 status=read_zsreg(chan, R0);
@@ -387,9 +478,14 @@ struct z8530_irqhandler z8530_sync=
EXPORT_SYMBOL(z8530_sync);
-/*
+/**
+ * z8530_dma_rx:
+ * @chan: Channel to handle
+ *
* Non bus mastering DMA interfaces for the Z8x30 devices. This
- * is really pretty PC specific.
+ * is really pretty PC specific. The DMA mode means that most receive
+ * events are handled by the DMA hardware. We get a kick here only if
+ * a frame ended.
*/
static void z8530_dma_rx(struct z8530_channel *chan)
@@ -417,6 +513,14 @@ static void z8530_dma_rx(struct z8530_channel *chan)
}
}
+/**
+ * z8530_dma_tx:
+ * @chan: The Z8530 channel to handle
+ *
+ * We have received an interrupt while doing DMA transmissions. It
+ * shouldn't happen. Scream loudly if it does.
+ */
+
static void z8530_dma_tx(struct z8530_channel *chan)
{
if(!chan->dma_tx)
@@ -430,6 +534,17 @@ static void z8530_dma_tx(struct z8530_channel *chan)
z8530_tx(chan);
}
+/**
+ * z8530_dma_status:
+ * @chan: Z8530 channel to process
+ *
+ * A status event occured on the Z8530. We receive these for two reasons
+ * when in DMA mode. Firstly if we finished a packet transfer we get one
+ * and kick the next packet out. Secondly we may see a DCD change and
+ * have to poke the protocol layer.
+ *
+ */
+
static void z8530_dma_status(struct z8530_channel *chan)
{
unsigned long flags;
@@ -490,8 +605,11 @@ struct z8530_irqhandler z8530_txdma_sync=
EXPORT_SYMBOL(z8530_txdma_sync);
-/*
- * Interrupt vectors for a Z8530 that is in 'parked' mode.
+/**
+ * z8530_rx_clear:
+ * @c: Z8530 channel to shut up
+ *
+ * Receive interrupt vectors for a Z8530 that is in 'parked' mode.
* For machines with PCI Z85x30 cards, or level triggered interrupts
* (eg the MacII) we must clear the interrupt cause or die.
*/
@@ -516,12 +634,30 @@ static void z8530_rx_clear(struct z8530_channel *c)
write_zsctrl(c, RES_H_IUS);
}
+/**
+ * z8530_tx_clear:
+ * @c: Z8530 channel to shut up
+ *
+ * Transmit interrupt vectors for a Z8530 that is in 'parked' mode.
+ * For machines with PCI Z85x30 cards, or level triggered interrupts
+ * (eg the MacII) we must clear the interrupt cause or die.
+ */
+
static void z8530_tx_clear(struct z8530_channel *c)
{
write_zsctrl(c, RES_Tx_P);
write_zsctrl(c, RES_H_IUS);
}
+/**
+ * z8530_status_clear:
+ * @chan: Z8530 channel to shut up
+ *
+ * Status interrupt vectors for a Z8530 that is in 'parked' mode.
+ * For machines with PCI Z85x30 cards, or level triggered interrupts
+ * (eg the MacII) we must clear the interrupt cause or die.
+ */
+
static void z8530_status_clear(struct z8530_channel *chan)
{
u8 status=read_zsreg(chan, R0);
@@ -541,8 +677,17 @@ struct z8530_irqhandler z8530_nop=
EXPORT_SYMBOL(z8530_nop);
-/*
- * A Z85[2]30 device has stuck its hand in the air for attention
+/**
+ * z8530_interrupt:
+ * @irq: Interrupt number
+ * @dev_id: The Z8530 device that is interrupting.
+ * @regs: unused
+ *
+ * A Z85[2]30 device has stuck its hand in the air for attention.
+ * We scan both the channels on the chip for events and then call
+ * the channel specific call backs for each channel that has events.
+ * We have to use callback functions because the two channels can be
+ * in different modes.
*/
void z8530_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -612,6 +757,15 @@ static char reg_init[16]=
};
+/**
+ * z8530_sync_open:
+ * @dev: The network interface we are using
+ * @c: The Z8530 channel to open in synchronous PIO mode
+ *
+ * Switch a Z8530 into synchronous mode without DMA assist. We
+ * raise the RTS/DTR and commence network operation.
+ */
+
int z8530_sync_open(struct net_device *dev, struct z8530_channel *c)
{
c->sync = 1;
@@ -634,9 +788,19 @@ int z8530_sync_open(struct net_device *dev, struct z8530_channel *c)
EXPORT_SYMBOL(z8530_sync_open);
+/**
+ * z8530_sync_close:
+ * @dev: Network device to close
+ * @c: Z8530 channel to disassociate and move to idle
+ *
+ * Close down a Z8530 interface and switch its interrupt handlers
+ * to discard future events.
+ */
+
int z8530_sync_close(struct net_device *dev, struct z8530_channel *c)
{
u8 chk;
+
c->irqs = &z8530_nop;
c->max = 0;
c->sync = 0;
@@ -649,6 +813,16 @@ int z8530_sync_close(struct net_device *dev, struct z8530_channel *c)
EXPORT_SYMBOL(z8530_sync_close);
+/**
+ * z8530_sync_dma_open:
+ * @dev: The network device to attach
+ * @c: The Z8530 channel to configure in sync DMA mode.
+ *
+ * Set up a Z85x30 device for synchronous DMA in both directions. Two
+ * ISA DMA channels must be available for this to work. We assume ISA
+ * DMA driven I/O and PC limits on access.
+ */
+
int z8530_sync_dma_open(struct net_device *dev, struct z8530_channel *c)
{
unsigned long flags;
@@ -753,11 +927,21 @@ int z8530_sync_dma_open(struct net_device *dev, struct z8530_channel *c)
c->irqs = &z8530_dma_sync;
z8530_rtsdtr(c,1);
write_zsreg(c, R3, c->regs[R3]|RxENABLE);
+
return 0;
}
EXPORT_SYMBOL(z8530_sync_dma_open);
+/**
+ * z8530_sync_dma_close:
+ * @dev: Network device to detach
+ * @c: Z8530 channel to move into discard mode
+ *
+ * Shut down a DMA mode synchronous interface. Halt the DMA, and
+ * free the buffers.
+ */
+
int z8530_sync_dma_close(struct net_device *dev, struct z8530_channel *c)
{
u8 chk;
@@ -814,6 +998,16 @@ int z8530_sync_dma_close(struct net_device *dev, struct z8530_channel *c)
EXPORT_SYMBOL(z8530_sync_dma_close);
+/**
+ * z8530_sync_txdma_open:
+ * @dev: The network device to attach
+ * @c: The Z8530 channel to configure in sync DMA mode.
+ *
+ * Set up a Z85x30 device for synchronous DMA tranmission. One
+ * ISA DMA channel must be available for this to work. The receive
+ * side is run in PIO mode, but then it has the bigger FIFO.
+ */
+
int z8530_sync_txdma_open(struct net_device *dev, struct z8530_channel *c)
{
unsigned long flags;
@@ -898,15 +1092,26 @@ int z8530_sync_txdma_open(struct net_device *dev, struct z8530_channel *c)
z8530_rtsdtr(c,1);
printk("Rx interrupts ON\n");
write_zsreg(c, R3, c->regs[R3]|RxENABLE);
+
return 0;
}
EXPORT_SYMBOL(z8530_sync_txdma_open);
-
+
+/**
+ * z8530_sync_txdma_close:
+ * @dev: Network device to detach
+ * @c: Z8530 channel to move into discard mode
+ *
+ * Shut down a DMA/PIO split mode synchronous interface. Halt the DMA,
+ * and free the buffers.
+ */
+
int z8530_sync_txdma_close(struct net_device *dev, struct z8530_channel *c)
{
unsigned long flags;
u8 chk;
+
c->irqs = &z8530_nop;
c->max = 0;
c->sync = 0;
@@ -950,21 +1155,32 @@ int z8530_sync_txdma_close(struct net_device *dev, struct z8530_channel *c)
EXPORT_SYMBOL(z8530_sync_txdma_close);
+
/*
- * Describe a Z8530 in a standard format. We must pass the I/O as
- * the port offset isnt predictable. The main reason for this function
- * is to try and get a common format of report.
+ * Name strings for Z8530 chips. SGI claim to have a 130, Zilog deny
+ * it exists...
*/
-
+
static char *z8530_type_name[]={
"Z8530",
"Z85C30",
"Z85230"
};
-void z8530_describe(struct z8530_dev *dev, char *mapping, int io)
+/**
+ * z8530_describe:
+ * @dev: Z8530 device to describe
+ * @mapping: string holding mapping type (eg "I/O" or "Mem")
+ * @io: the port value in question
+ *
+ * Describe a Z8530 in a standard format. We must pass the I/O as
+ * the port offset isnt predictable. The main reason for this function
+ * is to try and get a common format of report.
+ */
+
+void z8530_describe(struct z8530_dev *dev, char *mapping, unsigned long io)
{
- printk(KERN_INFO "%s: %s found at %s 0x%X, IRQ %d.\n",
+ printk(KERN_INFO "%s: %s found at %s 0x%lX, IRQ %d.\n",
dev->name,
z8530_type_name[dev->type],
mapping,
@@ -974,8 +1190,21 @@ void z8530_describe(struct z8530_dev *dev, char *mapping, int io)
EXPORT_SYMBOL(z8530_describe);
-/*
- * Configure up a Z8530
+/**
+ * z8530_init:
+ * @dev: Z8530 device to initialise.
+ *
+ * Configure up a Z8530/Z85C30 or Z85230 chip. We check the device
+ * is present, identify the type and then program it to hopefully
+ * keep quite and behave. This matters a lot, a Z8530 in the wrong
+ * state will sometimes get into stupid modes generating 10Khz
+ * interrupt streams and the like.
+ *
+ * We set the interrupt handler up to discard any events, in case
+ * we get them during reset or setp.
+ *
+ * Return 0 for success, or a negative value indicating the problem
+ * in errno form.
*/
@@ -1043,6 +1272,15 @@ int z8530_init(struct z8530_dev *dev)
EXPORT_SYMBOL(z8530_init);
+/**
+ * z8530_shutdown:
+ * @dev: The Z8530 chip to shutdown
+ *
+ * We set the interrupt handlers to silence any interrupts. We then
+ * reset the chip and wait 100uS to be sure the reset completed. Just
+ * in case the caller then tries to do stuff.
+ */
+
int z8530_shutdown(struct z8530_dev *dev)
{
/* Reset the chip */
@@ -1055,9 +1293,15 @@ int z8530_shutdown(struct z8530_dev *dev)
EXPORT_SYMBOL(z8530_shutdown);
-/*
- * Load a Z8530 channel up from the system data
- * We use +16 to indicate the 'prime' registers
+/**
+ * z8530_channel_load:
+ * @c: Z8530 channel to configure
+ * @rtable: Table of register, value pairs
+ * FIXME: ioctl to allow user uploaded tables
+ *
+ * Load a Z8530 channel up from the system data> We use +16 to
+ * indicate the 'prime' registers. The value 255 terminates the
+ * table
*/
int z8530_channel_load(struct z8530_channel *c, u8 *rtable)
@@ -1088,8 +1332,16 @@ int z8530_channel_load(struct z8530_channel *c, u8 *rtable)
EXPORT_SYMBOL(z8530_channel_load);
-/*
- * Higher level shovelling - transmit chains
+/**
+ * z8530_tx_begin:
+ * @c: The Z8530 channel to kick
+ *
+ * This is the speed sensitive side of transmission. If we are called
+ * and no buffer is being transmitted we commence the next buffer. If
+ * nothing is queued we idle the sync.
+ *
+ * Note: We are handling this code path in the interrupt path, keep it
+ * fast or bad things will happen.
*/
static void z8530_tx_begin(struct z8530_channel *c)
@@ -1102,7 +1354,7 @@ static void z8530_tx_begin(struct z8530_channel *c)
c->tx_next_skb=NULL;
c->tx_ptr=c->tx_next_ptr;
- mark_bh(NET_BH);
+ netif_wake_queue(c->netdevice);
if(c->tx_skb==NULL)
{
/* Idle on */
@@ -1176,7 +1428,15 @@ static void z8530_tx_begin(struct z8530_channel *c)
}
}
}
-
+
+/**
+ * z8530_tx_done:
+ * @c: The channel that completed a transmit.
+ *
+ * This is called when we complete a packet send. We wake the queue,
+ * start the next packet going and then free the buffer of the existing
+ * packet. This code is fairly timing sensitive.
+ */
static void z8530_tx_done(struct z8530_channel *c)
{
@@ -1184,7 +1444,7 @@ static void z8530_tx_done(struct z8530_channel *c)
struct sk_buff *skb;
spin_lock_irqsave(&z8530_buffer_lock, flags);
- c->netdevice->tbusy=0;
+ netif_wake_queue(c->netdevice);
/* Actually this can happen.*/
if(c->tx_skb==NULL)
{
@@ -1197,11 +1457,16 @@ static void z8530_tx_done(struct z8530_channel *c)
spin_unlock_irqrestore(&z8530_buffer_lock, flags);
c->stats.tx_packets++;
c->stats.tx_bytes+=skb->len;
- dev_kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
}
-/*
- * Higher level shovelling - receive chains
+/**
+ * z8530_null_rx:
+ * @c: The channel the packet arrived on
+ * @skb: The buffer
+ *
+ * We point the receive handler at this function when idle. Instead
+ * of syncppp processing the frames we get to throw them away.
*/
void z8530_null_rx(struct z8530_channel *c, struct sk_buff *skb)
@@ -1211,6 +1476,17 @@ void z8530_null_rx(struct z8530_channel *c, struct sk_buff *skb)
EXPORT_SYMBOL(z8530_null_rx);
+/**
+ * z8530_rx_done:
+ * @c: The channel that completed a receive
+ *
+ * A new packet is complete. Our goal here is to get back into receive
+ * mode as fast as possible. On the Z85230 we could change to using
+ * ESCC mode, but on the older chips we have no choice. We flip to the
+ * new buffer immediately in DMA mode so that the DMA of the next
+ * frame can occur while we are copying the previous buffer to an sk_buff
+ */
+
static void z8530_rx_done(struct z8530_channel *c)
{
struct sk_buff *skb;
@@ -1265,7 +1541,7 @@ static void z8530_rx_done(struct z8530_channel *c)
else
/* Can't occur as we dont reenable the DMA irq until
after the flip is done */
- printk("DMA flip overrun!\n");
+ printk(KERN_WARNING "%s: DMA flip overrun!\n", c->netdevice->name);
release_dma_lock(flags);
@@ -1353,8 +1629,12 @@ static void z8530_rx_done(struct z8530_channel *c)
}
}
-/*
- * Cannot DMA over a 64K boundary on a PC
+/**
+ * spans_boundary:
+ * @skb: The buffer to check
+ *
+ * Returns true if the buffer cross a DMA boundary on a PC. The poor
+ * thing can only DMA within a 64K block not across the edges of it.
*/
extern inline int spans_boundary(struct sk_buff *skb)
@@ -1369,7 +1649,11 @@ extern inline int spans_boundary(struct sk_buff *skb)
return 0;
}
-/*
+/**
+ * z8530_queue_xmit:
+ * @c: The channel to use
+ * @skb: The packet to kick down the channel
+ *
* Queue a packet for transmission. Because we have rather
* hard to hit interrupt latencies for the Z85230 per packet
* even in DMA mode we do the flip to DMA buffer if needed here
@@ -1379,9 +1663,10 @@ extern inline int spans_boundary(struct sk_buff *skb)
int z8530_queue_xmit(struct z8530_channel *c, struct sk_buff *skb)
{
unsigned long flags;
+
+ netif_stop_queue(c->netdevice);
if(c->tx_next_skb)
{
- skb->dev->tbusy=1;
return 1;
}
@@ -1414,11 +1699,21 @@ int z8530_queue_xmit(struct z8530_channel *c, struct sk_buff *skb)
spin_lock_irqsave(&z8530_buffer_lock, flags);
z8530_tx_begin(c);
spin_unlock_irqrestore(&z8530_buffer_lock, flags);
+
+ netif_wake_queue(c->netdevice);
return 0;
}
EXPORT_SYMBOL(z8530_queue_xmit);
+/**
+ * z8530_get_stats:
+ * @c: The channel to use
+ *
+ * Get the statistics block. We keep the statistics in software as
+ * the chip doesn't do it for us.
+ */
+
struct net_device_stats *z8530_get_stats(struct z8530_channel *c)
{
return &c->stats;
diff --git a/drivers/net/wan/z85230.h b/drivers/net/wan/z85230.h
index dcad711b0..8dc92a535 100644
--- a/drivers/net/wan/z85230.h
+++ b/drivers/net/wan/z85230.h
@@ -304,8 +304,8 @@ struct z8530_channel
*/
struct z8530_dev *dev; /* Z85230 chip instance we are from */
- int ctrlio; /* I/O ports */
- int dataio;
+ unsigned long ctrlio; /* I/O ports */
+ unsigned long dataio;
/*
* For PC we encode this way.
@@ -395,7 +395,7 @@ extern u8 z8530_dead_port[];
extern u8 z8530_hdlc_kilostream_85230[];
extern u8 z8530_hdlc_kilostream[];
extern void z8530_interrupt(int, void *, struct pt_regs *);
-extern void z8530_describe(struct z8530_dev *, char *mapping,int io);
+extern void z8530_describe(struct z8530_dev *, char *mapping, unsigned long io);
extern int z8530_init(struct z8530_dev *);
extern int z8530_shutdown(struct z8530_dev *);
extern int z8530_sync_open(struct net_device *, struct z8530_channel *);
diff --git a/drivers/net/wavelan.c b/drivers/net/wavelan.c
index 73771fc96..cd5b7caa0 100644
--- a/drivers/net/wavelan.c
+++ b/drivers/net/wavelan.c
@@ -6,9 +6,9 @@
* Reorganisation and extension of the driver.
* Original copyright follows (also see the end of this file).
* See wavelan.p.h for details.
- */
-
-/*
+ *
+ *
+ *
* AT&T GIS (nee NCR) WaveLAN card:
* An Ethernet-like radio transceiver
* controlled by an Intel 82586 coprocessor.
@@ -26,54 +26,49 @@
/*
* Wrapper for disabling interrupts.
*/
-static inline unsigned long
-wv_splhi(void)
-{
- unsigned long flags;
- save_flags(flags);
- cli();
-
- return(flags);
+static inline unsigned long wv_splhi(void)
+{
+ unsigned long flags;
+ save_flags(flags);
+ cli();
+ return (flags);
}
/*------------------------------------------------------------------*/
/*
* Wrapper for re-enabling interrupts.
*/
-static inline void
-wv_splx(unsigned long flags)
+static inline void wv_splx(unsigned long flags)
{
- restore_flags(flags);
+ restore_flags(flags);
}
/*------------------------------------------------------------------*/
/*
* Translate irq number to PSA irq parameter
*/
-static u_char
-wv_irq_to_psa(int irq)
+static u8 wv_irq_to_psa(int irq)
{
- if(irq < 0 || irq >= NELS(irqvals))
- return 0;
+ if (irq < 0 || irq >= NELS(irqvals))
+ return 0;
- return irqvals[irq];
+ return irqvals[irq];
}
/*------------------------------------------------------------------*/
/*
* Translate PSA irq parameter to irq number
*/
-static int __init
-wv_psa_to_irq(u_char irqval)
+static int __init wv_psa_to_irq(u8 irqval)
{
- int irq;
+ int irq;
- for(irq = 0; irq < NELS(irqvals); irq++)
- if(irqvals[irq] == irqval)
- return irq;
+ for (irq = 0; irq < NELS(irqvals); irq++)
+ if (irqvals[irq] == irqval)
+ return irq;
- return -1;
+ return -1;
}
#ifdef STRUCT_CHECK
@@ -82,21 +77,20 @@ wv_psa_to_irq(u_char irqval)
* Sanity routine to verify the sizes of the various WaveLAN interface
* structures.
*/
-static char *
-wv_struct_check(void)
+static char *wv_struct_check(void)
{
#define SC(t,s,n) if (sizeof(t) != s) return(n);
- SC(psa_t, PSA_SIZE, "psa_t");
- SC(mmw_t, MMW_SIZE, "mmw_t");
- SC(mmr_t, MMR_SIZE, "mmr_t");
- SC(ha_t, HA_SIZE, "ha_t");
+ SC(psa_t, PSA_SIZE, "psa_t");
+ SC(mmw_t, MMW_SIZE, "mmw_t");
+ SC(mmr_t, MMR_SIZE, "mmr_t");
+ SC(ha_t, HA_SIZE, "ha_t");
#undef SC
- return((char *) NULL);
-} /* wv_struct_check */
-#endif /* STRUCT_CHECK */
+ return ((char *) NULL);
+} /* wv_struct_check */
+#endif /* STRUCT_CHECK */
/********************* HOST ADAPTER SUBROUTINES *********************/
/*
@@ -111,120 +105,106 @@ wv_struct_check(void)
/*
* Read from card's Host Adaptor Status Register.
*/
-static inline u_short
-hasr_read(u_long ioaddr)
+static inline u16 hasr_read(unsigned long ioaddr)
{
- return(inw(HASR(ioaddr)));
-} /* hasr_read */
+ return (inw(HASR(ioaddr)));
+} /* hasr_read */
/*------------------------------------------------------------------*/
/*
* Write to card's Host Adapter Command Register.
*/
-static inline void
-hacr_write(u_long ioaddr,
- u_short hacr)
+static inline void hacr_write(unsigned long ioaddr, u16 hacr)
{
- outw(hacr, HACR(ioaddr));
-} /* hacr_write */
+ outw(hacr, HACR(ioaddr));
+} /* hacr_write */
/*------------------------------------------------------------------*/
/*
* Write to card's Host Adapter Command Register. Include a delay for
* those times when it is needed.
*/
-static inline void
-hacr_write_slow(u_long ioaddr,
- u_short hacr)
+static inline void hacr_write_slow(unsigned long ioaddr, u16 hacr)
{
- hacr_write(ioaddr, hacr);
- /* delay might only be needed sometimes */
- mdelay(1);
-} /* hacr_write_slow */
+ hacr_write(ioaddr, hacr);
+ /* delay might only be needed sometimes */
+ mdelay(1);
+} /* hacr_write_slow */
/*------------------------------------------------------------------*/
/*
* Set the channel attention bit.
*/
-static inline void
-set_chan_attn(u_long ioaddr,
- u_short hacr)
+static inline void set_chan_attn(unsigned long ioaddr, u16 hacr)
{
- hacr_write(ioaddr, hacr | HACR_CA);
-} /* set_chan_attn */
+ hacr_write(ioaddr, hacr | HACR_CA);
+} /* set_chan_attn */
/*------------------------------------------------------------------*/
/*
* Reset, and then set host adaptor into default mode.
*/
-static inline void
-wv_hacr_reset(u_long ioaddr)
+static inline void wv_hacr_reset(unsigned long ioaddr)
{
- hacr_write_slow(ioaddr, HACR_RESET);
- hacr_write(ioaddr, HACR_DEFAULT);
-} /* wv_hacr_reset */
+ hacr_write_slow(ioaddr, HACR_RESET);
+ hacr_write(ioaddr, HACR_DEFAULT);
+} /* wv_hacr_reset */
/*------------------------------------------------------------------*/
/*
* Set the I/O transfer over the ISA bus to 8-bit mode
*/
-static inline void
-wv_16_off(u_long ioaddr,
- u_short hacr)
+static inline void wv_16_off(unsigned long ioaddr, u16 hacr)
{
- hacr &= ~HACR_16BITS;
- hacr_write(ioaddr, hacr);
-} /* wv_16_off */
+ hacr &= ~HACR_16BITS;
+ hacr_write(ioaddr, hacr);
+} /* wv_16_off */
/*------------------------------------------------------------------*/
/*
* Set the I/O transfer over the ISA bus to 8-bit mode
*/
-static inline void
-wv_16_on(u_long ioaddr,
- u_short hacr)
+static inline void wv_16_on(unsigned long ioaddr, u16 hacr)
{
- hacr |= HACR_16BITS;
- hacr_write(ioaddr, hacr);
-} /* wv_16_on */
+ hacr |= HACR_16BITS;
+ hacr_write(ioaddr, hacr);
+} /* wv_16_on */
/*------------------------------------------------------------------*/
/*
* Disable interrupts on the WaveLAN hardware.
*/
-static inline void
-wv_ints_off(device * dev)
+static inline void wv_ints_off(device * dev)
{
- net_local * lp = (net_local *)dev->priv;
- u_long ioaddr = dev->base_addr;
- u_long x;
-
- x = wv_splhi();
+ net_local *lp = (net_local *) dev->priv;
+ unsigned long ioaddr = dev->base_addr;
+ unsigned long flags;
- lp->hacr &= ~HACR_INTRON;
- hacr_write(ioaddr, lp->hacr);
+ save_flags(flags);
+ cli();
+
+ lp->hacr &= ~HACR_INTRON;
+ hacr_write(ioaddr, lp->hacr);
- wv_splx(x);
-} /* wv_ints_off */
+ restore_flags(flags);
+} /* wv_ints_off */
/*------------------------------------------------------------------*/
/*
* Enable interrupts on the WaveLAN hardware.
*/
-static inline void
-wv_ints_on(device * dev)
+static inline void wv_ints_on(device * dev)
{
- net_local * lp = (net_local *)dev->priv;
- u_long ioaddr = dev->base_addr;
- u_long x;
-
- x = wv_splhi();
-
- lp->hacr |= HACR_INTRON;
- hacr_write(ioaddr, lp->hacr);
+ net_local *lp = (net_local *) dev->priv;
+ unsigned long ioaddr = dev->base_addr;
+ unsigned long flags;
- wv_splx(x);
-} /* wv_ints_on */
+ save_flags(flags);
+ cli();
+ lp->hacr |= HACR_INTRON;
+ hacr_write(ioaddr, lp->hacr);
+ restore_flags(flags);
+} /* wv_ints_on */
/******************* MODEM MANAGEMENT SUBROUTINES *******************/
/*
@@ -238,57 +218,48 @@ wv_ints_on(device * dev)
/*
* Read bytes from the PSA.
*/
-static void
-psa_read(u_long ioaddr,
- u_short hacr,
- int o, /* offset in PSA */
- u_char * b, /* buffer to fill */
- int n) /* size to read */
-{
- wv_16_off(ioaddr, hacr);
-
- while(n-- > 0)
- {
- outw(o, PIOR2(ioaddr));
- o++;
- *b++ = inb(PIOP2(ioaddr));
- }
+static void psa_read(unsigned long ioaddr, u16 hacr, int o, /* offset in PSA */
+ u8 * b, /* buffer to fill */
+ int n)
+{ /* size to read */
+ wv_16_off(ioaddr, hacr);
+
+ while (n-- > 0) {
+ outw(o, PIOR2(ioaddr));
+ o++;
+ *b++ = inb(PIOP2(ioaddr));
+ }
- wv_16_on(ioaddr, hacr);
-} /* psa_read */
+ wv_16_on(ioaddr, hacr);
+} /* psa_read */
/*------------------------------------------------------------------*/
/*
* Write the Parameter Storage Area to the WaveLAN card's memory.
*/
-static void
-psa_write(u_long ioaddr,
- u_short hacr,
- int o, /* Offset in PSA */
- u_char * b, /* Buffer in memory */
- int n) /* Length of buffer */
-{
- int count = 0;
+static void psa_write(unsigned long ioaddr, u16 hacr, int o, /* Offset in PSA */
+ u8 * b, /* Buffer in memory */
+ int n)
+{ /* Length of buffer */
+ int count = 0;
- wv_16_off(ioaddr, hacr);
+ wv_16_off(ioaddr, hacr);
- while(n-- > 0)
- {
- outw(o, PIOR2(ioaddr));
- o++;
+ while (n-- > 0) {
+ outw(o, PIOR2(ioaddr));
+ o++;
- outb(*b, PIOP2(ioaddr));
- b++;
+ outb(*b, PIOP2(ioaddr));
+ b++;
- /* Wait for the memory to finish its write cycle */
- count = 0;
- while((count++ < 100) &&
- (hasr_read(ioaddr) & HASR_PSA_BUSY))
- mdelay(1);
- }
+ /* Wait for the memory to finish its write cycle */
+ count = 0;
+ while ((count++ < 100) &&
+ (hasr_read(ioaddr) & HASR_PSA_BUSY)) mdelay(1);
+ }
- wv_16_on(ioaddr, hacr);
-} /* psa_write */
+ wv_16_on(ioaddr, hacr);
+} /* psa_write */
#ifdef SET_PSA_CRC
/*------------------------------------------------------------------*/
@@ -301,88 +272,80 @@ psa_write(u_long ioaddr,
* The Windows drivers don't use the CRC, but the AP and the PtP tool
* depend on it.
*/
-static inline u_short
-psa_crc(u_char * psa, /* The PSA */
- int size) /* Number of short for CRC */
-{
- int byte_cnt; /* Loop on the PSA */
- u_short crc_bytes = 0; /* Data in the PSA */
- int bit_cnt; /* Loop on the bits of the short */
-
- for(byte_cnt = 0; byte_cnt < size; byte_cnt++ )
- {
- crc_bytes ^= psa[byte_cnt]; /* Its an xor */
-
- for(bit_cnt = 1; bit_cnt < 9; bit_cnt++ )
- {
- if(crc_bytes & 0x0001)
- crc_bytes = (crc_bytes >> 1) ^ 0xA001;
- else
- crc_bytes >>= 1 ;
- }
- }
+static inline u16 psa_crc(u8 * psa, /* The PSA */
+ int size)
+{ /* Number of short for CRC */
+ int byte_cnt; /* Loop on the PSA */
+ u16 crc_bytes = 0; /* Data in the PSA */
+ int bit_cnt; /* Loop on the bits of the short */
+
+ for (byte_cnt = 0; byte_cnt < size; byte_cnt++) {
+ crc_bytes ^= psa[byte_cnt]; /* Its an xor */
+
+ for (bit_cnt = 1; bit_cnt < 9; bit_cnt++) {
+ if (crc_bytes & 0x0001)
+ crc_bytes = (crc_bytes >> 1) ^ 0xA001;
+ else
+ crc_bytes >>= 1;
+ }
+ }
- return crc_bytes;
-} /* psa_crc */
-#endif /* SET_PSA_CRC */
+ return crc_bytes;
+} /* psa_crc */
+#endif /* SET_PSA_CRC */
/*------------------------------------------------------------------*/
/*
* update the checksum field in the Wavelan's PSA
*/
-static void
-update_psa_checksum(device * dev,
- u_long ioaddr,
- u_short hacr)
+static void update_psa_checksum(device * dev, unsigned long ioaddr, u16 hacr)
{
#ifdef SET_PSA_CRC
- psa_t psa;
- u_short crc;
+ psa_t psa;
+ u16 crc;
- /* read the parameter storage area */
- psa_read(ioaddr, hacr, 0, (unsigned char *) &psa, sizeof(psa));
+ /* read the parameter storage area */
+ psa_read(ioaddr, hacr, 0, (unsigned char *) &psa, sizeof(psa));
- /* update the checksum */
- crc = psa_crc((unsigned char *) &psa,
- sizeof(psa) - sizeof(psa.psa_crc[0]) - sizeof(psa.psa_crc[1])
- - sizeof(psa.psa_crc_status));
+ /* update the checksum */
+ crc = psa_crc((unsigned char *) &psa,
+ sizeof(psa) - sizeof(psa.psa_crc[0]) -
+ sizeof(psa.psa_crc[1])
+ - sizeof(psa.psa_crc_status));
- psa.psa_crc[0] = crc & 0xFF;
- psa.psa_crc[1] = (crc & 0xFF00) >> 8;
+ psa.psa_crc[0] = crc & 0xFF;
+ psa.psa_crc[1] = (crc & 0xFF00) >> 8;
- /* Write it ! */
- psa_write(ioaddr, hacr, (char *)&psa.psa_crc - (char *)&psa,
- (unsigned char *)&psa.psa_crc, 2);
+ /* Write it ! */
+ psa_write(ioaddr, hacr, (char *) &psa.psa_crc - (char *) &psa,
+ (unsigned char *) &psa.psa_crc, 2);
#ifdef DEBUG_IOCTL_INFO
- printk (KERN_DEBUG "%s: update_psa_checksum(): crc = 0x%02x%02x\n",
- dev->name, psa.psa_crc[0], psa.psa_crc[1]);
+ printk(KERN_DEBUG "%s: update_psa_checksum(): crc = 0x%02x%02x\n",
+ dev->name, psa.psa_crc[0], psa.psa_crc[1]);
- /* Check again (luxury !) */
- crc = psa_crc ((unsigned char *) &psa,
- sizeof(psa) - sizeof(psa.psa_crc_status));
+ /* Check again (luxury !) */
+ crc = psa_crc((unsigned char *) &psa,
+ sizeof(psa) - sizeof(psa.psa_crc_status));
- if(crc != 0)
- printk(KERN_WARNING "%s: update_psa_checksum(): CRC does not agree with PSA data (even after recalculating)\n", dev->name);
-#endif /* DEBUG_IOCTL_INFO */
-#endif /* SET_PSA_CRC */
-} /* update_psa_checksum */
+ if (crc != 0)
+ printk(KERN_WARNING
+ "%s: update_psa_checksum(): CRC does not agree with PSA data (even after recalculating)\n",
+ dev->name);
+#endif /* DEBUG_IOCTL_INFO */
+#endif /* SET_PSA_CRC */
+} /* update_psa_checksum */
/*------------------------------------------------------------------*/
/*
* Write 1 byte to the MMC.
*/
-static inline void
-mmc_out(u_long ioaddr,
- u_short o,
- u_char d)
+static inline void mmc_out(unsigned long ioaddr, u16 o, u8 d)
{
- /* Wait for MMC to go idle */
- while(inw(HASR(ioaddr)) & HASR_MMC_BUSY)
- ;
+ /* Wait for MMC to go idle */
+ while (inw(HASR(ioaddr)) & HASR_MMC_BUSY);
- outw((u_short) (((u_short) d << 8) | (o << 1) | 1),
- MMCR(ioaddr));
+ outw((u16) (((u16) d << 8) | (o << 1) | 1), MMCR(ioaddr));
}
/*------------------------------------------------------------------*/
@@ -390,35 +353,27 @@ mmc_out(u_long ioaddr,
* Routine to write bytes to the Modem Management Controller.
* We start at the end because it is the way it should be!
*/
-static inline void
-mmc_write(u_long ioaddr,
- u_char o,
- u_char * b,
- int n)
+static inline void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n)
{
- o += n;
- b += n;
+ o += n;
+ b += n;
- while(n-- > 0 )
- mmc_out(ioaddr, --o, *(--b));
-} /* mmc_write */
+ while (n-- > 0)
+ mmc_out(ioaddr, --o, *(--b));
+} /* mmc_write */
/*------------------------------------------------------------------*/
/*
* Read a byte from the MMC.
* Optimised version for 1 byte, avoid using memory.
*/
-static inline u_char
-mmc_in(u_long ioaddr,
- u_short o)
+static inline u8 mmc_in(unsigned long ioaddr, u16 o)
{
- while(inw(HASR(ioaddr)) & HASR_MMC_BUSY)
- ;
- outw(o << 1, MMCR(ioaddr));
+ while (inw(HASR(ioaddr)) & HASR_MMC_BUSY);
+ outw(o << 1, MMCR(ioaddr));
- while(inw(HASR(ioaddr)) & HASR_MMC_BUSY)
- ;
- return (u_char) (inw(MMCR(ioaddr)) >> 8);
+ while (inw(HASR(ioaddr)) & HASR_MMC_BUSY);
+ return (u8) (inw(MMCR(ioaddr)) >> 8);
}
/*------------------------------------------------------------------*/
@@ -429,33 +384,28 @@ mmc_in(u_long ioaddr,
* (code has just been moved in the above function)
* We start at the end because it is the way it should be!
*/
-static inline void
-mmc_read(u_long ioaddr,
- u_char o,
- u_char * b,
- int n)
+static inline void mmc_read(unsigned long ioaddr, u8 o, u8 * b, int n)
{
- o += n;
- b += n;
+ o += n;
+ b += n;
- while(n-- > 0)
- *(--b) = mmc_in(ioaddr, --o);
-} /* mmc_read */
+ while (n-- > 0)
+ *(--b) = mmc_in(ioaddr, --o);
+} /* mmc_read */
/*------------------------------------------------------------------*/
/*
* Get the type of encryption available.
*/
-static inline int
-mmc_encr(u_long ioaddr) /* I/O port of the card */
-{
- int temp;
-
- temp = mmc_in(ioaddr, mmroff(0, mmr_des_avail));
- if((temp != MMR_DES_AVAIL_DES) && (temp != MMR_DES_AVAIL_AES))
- return 0;
- else
- return temp;
+static inline int mmc_encr(unsigned long ioaddr)
+{ /* I/O port of the card */
+ int temp;
+
+ temp = mmc_in(ioaddr, mmroff(0, mmr_des_avail));
+ if ((temp != MMR_DES_AVAIL_DES) && (temp != MMR_DES_AVAIL_AES))
+ return 0;
+ else
+ return temp;
}
/*------------------------------------------------------------------*/
@@ -463,49 +413,47 @@ mmc_encr(u_long ioaddr) /* I/O port of the card */
* Wait for the frequency EEPROM to complete a command.
* I hope this one will be optimally inlined.
*/
-static inline void
-fee_wait(u_long ioaddr, /* I/O port of the card */
- int delay, /* Base delay to wait for */
- int number) /* Number of time to wait */
-{
- int count = 0; /* Wait only a limited time */
-
- while((count++ < number) &&
- (mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & MMR_FEE_STATUS_BUSY))
- udelay(delay);
+static inline void fee_wait(unsigned long ioaddr, /* I/O port of the card */
+ int delay, /* Base delay to wait for */
+ int number)
+{ /* Number of time to wait */
+ int count = 0; /* Wait only a limited time */
+
+ while ((count++ < number) &&
+ (mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
+ MMR_FEE_STATUS_BUSY)) udelay(delay);
}
/*------------------------------------------------------------------*/
/*
* Read bytes from the Frequency EEPROM (frequency select cards).
*/
-static void
-fee_read(u_long ioaddr, /* I/O port of the card */
- u_short o, /* destination offset */
- u_short * b, /* data buffer */
- int n) /* number of registers */
-{
- b += n; /* Position at the end of the area */
-
- /* Write the address */
- mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1);
-
- /* Loop on all buffer */
- while(n-- > 0)
- {
- /* Write the read command */
- mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_READ);
-
- /* Wait until EEPROM is ready (should be quick). */
- fee_wait(ioaddr, 10, 100);
-
- /* Read the value. */
- *--b = ((mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)) << 8) |
- mmc_in(ioaddr, mmroff(0, mmr_fee_data_l)));
- }
+static void fee_read(unsigned long ioaddr, /* I/O port of the card */
+ u16 o, /* destination offset */
+ u16 * b, /* data buffer */
+ int n)
+{ /* number of registers */
+ b += n; /* Position at the end of the area */
+
+ /* Write the address */
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1);
+
+ /* Loop on all buffer */
+ while (n-- > 0) {
+ /* Write the read command */
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl),
+ MMW_FEE_CTRL_READ);
+
+ /* Wait until EEPROM is ready (should be quick). */
+ fee_wait(ioaddr, 10, 100);
+
+ /* Read the value. */
+ *--b = ((mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)) << 8) |
+ mmc_in(ioaddr, mmroff(0, mmr_fee_data_l)));
+ }
}
-#ifdef WIRELESS_EXT /* if the wireless extension exists in the kernel */
+#ifdef WIRELESS_EXT /* if the wireless extension exists in the kernel */
/*------------------------------------------------------------------*/
/*
@@ -514,83 +462,82 @@ fee_read(u_long ioaddr, /* I/O port of the card */
* be unprotected and the write enabled.
* Jean II
*/
-static void
-fee_write(u_long ioaddr, /* I/O port of the card */
- u_short o, /* destination offset */
- u_short * b, /* data buffer */
- int n) /* number of registers */
-{
- b += n; /* Position at the end of the area. */
+static void fee_write(unsigned long ioaddr, /* I/O port of the card */
+ u16 o, /* destination offset */
+ u16 * b, /* data buffer */
+ int n)
+{ /* number of registers */
+ b += n; /* Position at the end of the area. */
#ifdef EEPROM_IS_PROTECTED /* disabled */
#ifdef DOESNT_SEEM_TO_WORK /* disabled */
- /* Ask to read the protected register */
- mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRREAD);
+ /* Ask to read the protected register */
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRREAD);
- fee_wait(ioaddr, 10, 100);
+ fee_wait(ioaddr, 10, 100);
- /* Read the protected register. */
- printk("Protected 2: %02X-%02X\n",
- mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)),
- mmc_in(ioaddr, mmroff(0, mmr_fee_data_l)));
-#endif /* DOESNT_SEEM_TO_WORK */
+ /* Read the protected register. */
+ printk("Protected 2: %02X-%02X\n",
+ mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)),
+ mmc_in(ioaddr, mmroff(0, mmr_fee_data_l)));
+#endif /* DOESNT_SEEM_TO_WORK */
- /* Enable protected register. */
- mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN);
- mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PREN);
+ /* Enable protected register. */
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN);
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PREN);
- fee_wait(ioaddr, 10, 100);
+ fee_wait(ioaddr, 10, 100);
- /* Unprotect area. */
- mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n);
- mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE);
+ /* Unprotect area. */
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n);
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE);
#ifdef DOESNT_SEEM_TO_WORK /* disabled */
- /* or use: */
- mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRCLEAR);
-#endif /* DOESNT_SEEM_TO_WORK */
+ /* or use: */
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRCLEAR);
+#endif /* DOESNT_SEEM_TO_WORK */
- fee_wait(ioaddr, 10, 100);
-#endif /* EEPROM_IS_PROTECTED */
+ fee_wait(ioaddr, 10, 100);
+#endif /* EEPROM_IS_PROTECTED */
- /* Write enable. */
- mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN);
- mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WREN);
+ /* Write enable. */
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN);
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WREN);
- fee_wait(ioaddr, 10, 100);
+ fee_wait(ioaddr, 10, 100);
- /* Write the EEPROM address. */
- mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1);
+ /* Write the EEPROM address. */
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1);
- /* Loop on all buffer */
- while(n-- > 0)
- {
- /* Write the value. */
- mmc_out(ioaddr, mmwoff(0, mmw_fee_data_h), (*--b) >> 8);
- mmc_out(ioaddr, mmwoff(0, mmw_fee_data_l), *b & 0xFF);
+ /* Loop on all buffer */
+ while (n-- > 0) {
+ /* Write the value. */
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_data_h), (*--b) >> 8);
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_data_l), *b & 0xFF);
- /* Write the write command. */
- mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WRITE);
+ /* Write the write command. */
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl),
+ MMW_FEE_CTRL_WRITE);
- /* WaveLAN documentation says to wait at least 10 ms for EEBUSY = 0 */
- mdelay(10);
- fee_wait(ioaddr, 10, 100);
- }
+ /* WaveLAN documentation says to wait at least 10 ms for EEBUSY = 0 */
+ mdelay(10);
+ fee_wait(ioaddr, 10, 100);
+ }
- /* Write disable. */
- mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_DS);
- mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WDS);
+ /* Write disable. */
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_DS);
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WDS);
- fee_wait(ioaddr, 10, 100);
+ fee_wait(ioaddr, 10, 100);
#ifdef EEPROM_IS_PROTECTED /* disabled */
- /* Reprotect EEPROM. */
- mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x00);
- mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE);
+ /* Reprotect EEPROM. */
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x00);
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE);
- fee_wait(ioaddr, 10, 100);
-#endif /* EEPROM_IS_PROTECTED */
+ fee_wait(ioaddr, 10, 100);
+#endif /* EEPROM_IS_PROTECTED */
}
-#endif /* WIRELESS_EXT */
+#endif /* WIRELESS_EXT */
/************************ I82586 SUBROUTINES *************************/
/*
@@ -602,68 +549,61 @@ fee_write(u_long ioaddr, /* I/O port of the card */
* Read bytes from the on-board RAM.
* Why does inlining this function make it fail?
*/
-static /*inline*/ void
-obram_read(u_long ioaddr,
- u_short o,
- u_char * b,
- int n)
+static /*inline */ void obram_read(unsigned long ioaddr,
+ u16 o, u8 * b, int n)
{
- outw(o, PIOR1(ioaddr));
- insw(PIOP1(ioaddr), (unsigned short *) b, (n + 1) >> 1);
+ outw(o, PIOR1(ioaddr));
+ insw(PIOP1(ioaddr), (unsigned short *) b, (n + 1) >> 1);
}
/*------------------------------------------------------------------*/
/*
* Write bytes to the on-board RAM.
*/
-static inline void
-obram_write(u_long ioaddr,
- u_short o,
- u_char * b,
- int n)
+static inline void obram_write(unsigned long ioaddr, u16 o, u8 * b, int n)
{
- outw(o, PIOR1(ioaddr));
- outsw(PIOP1(ioaddr), (unsigned short *) b, (n + 1) >> 1);
+ outw(o, PIOR1(ioaddr));
+ outsw(PIOP1(ioaddr), (unsigned short *) b, (n + 1) >> 1);
}
/*------------------------------------------------------------------*/
/*
* Acknowledge the reading of the status issued by the i82586.
*/
-static void
-wv_ack(device * dev)
+static void wv_ack(device * dev)
{
- net_local * lp = (net_local *)dev->priv;
- u_long ioaddr = dev->base_addr;
- u_short scb_cs;
- int i;
+ net_local *lp = (net_local *) dev->priv;
+ unsigned long ioaddr = dev->base_addr;
+ u16 scb_cs;
+ int i;
- obram_read(ioaddr, scboff(OFFSET_SCB, scb_status),
- (unsigned char *) &scb_cs, sizeof(scb_cs));
- scb_cs &= SCB_ST_INT;
+ obram_read(ioaddr, scboff(OFFSET_SCB, scb_status),
+ (unsigned char *) &scb_cs, sizeof(scb_cs));
+ scb_cs &= SCB_ST_INT;
- if(scb_cs == 0)
- return;
+ if (scb_cs == 0)
+ return;
- obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
- (unsigned char *) &scb_cs, sizeof(scb_cs));
+ obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
+ (unsigned char *) &scb_cs, sizeof(scb_cs));
- set_chan_attn(ioaddr, lp->hacr);
+ set_chan_attn(ioaddr, lp->hacr);
- for(i = 1000; i > 0; i--)
- {
- obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs));
- if(scb_cs == 0)
- break;
+ for (i = 1000; i > 0; i--) {
+ obram_read(ioaddr, scboff(OFFSET_SCB, scb_command),
+ (unsigned char *) &scb_cs, sizeof(scb_cs));
+ if (scb_cs == 0)
+ break;
- udelay(10);
- }
- udelay(100);
+ udelay(10);
+ }
+ udelay(100);
#ifdef DEBUG_CONFIG_ERROR
- if(i <= 0)
- printk(KERN_INFO "%s: wv_ack(): board not accepting command.\n",
- dev->name);
+ if (i <= 0)
+ printk(KERN_INFO
+ "%s: wv_ack(): board not accepting command.\n",
+ dev->name);
#endif
}
@@ -672,48 +612,45 @@ wv_ack(device * dev)
* Set channel attention bit and busy wait until command has
* completed, then acknowledge completion of the command.
*/
-static inline int
-wv_synchronous_cmd(device * dev,
- const char * str)
+static inline int wv_synchronous_cmd(device * dev, const char *str)
{
- net_local * lp = (net_local *)dev->priv;
- u_long ioaddr = dev->base_addr;
- u_short scb_cmd;
- ach_t cb;
- int i;
-
- scb_cmd = SCB_CMD_CUC & SCB_CMD_CUC_GO;
- obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
- (unsigned char *) &scb_cmd, sizeof(scb_cmd));
-
- set_chan_attn(ioaddr, lp->hacr);
-
- for (i = 1000; i > 0; i--)
- {
- obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb));
- if (cb.ac_status & AC_SFLD_C)
- break;
-
- udelay(10);
- }
- udelay(100);
-
- if(i <= 0 || !(cb.ac_status & AC_SFLD_OK))
- {
+ net_local *lp = (net_local *) dev->priv;
+ unsigned long ioaddr = dev->base_addr;
+ u16 scb_cmd;
+ ach_t cb;
+ int i;
+
+ scb_cmd = SCB_CMD_CUC & SCB_CMD_CUC_GO;
+ obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
+ (unsigned char *) &scb_cmd, sizeof(scb_cmd));
+
+ set_chan_attn(ioaddr, lp->hacr);
+
+ for (i = 1000; i > 0; i--) {
+ obram_read(ioaddr, OFFSET_CU, (unsigned char *) &cb,
+ sizeof(cb));
+ if (cb.ac_status & AC_SFLD_C)
+ break;
+
+ udelay(10);
+ }
+ udelay(100);
+
+ if (i <= 0 || !(cb.ac_status & AC_SFLD_OK)) {
#ifdef DEBUG_CONFIG_ERROR
- printk(KERN_INFO "%s: %s failed; status = 0x%x\n",
- dev->name, str, cb.ac_status);
+ printk(KERN_INFO "%s: %s failed; status = 0x%x\n",
+ dev->name, str, cb.ac_status);
#endif
#ifdef DEBUG_I82586_SHOW
- wv_scb_show(ioaddr);
+ wv_scb_show(ioaddr);
#endif
- return -1;
- }
+ return -1;
+ }
- /* Ack the status */
- wv_ack(dev);
+ /* Ack the status */
+ wv_ack(dev);
- return 0;
+ return 0;
}
/*------------------------------------------------------------------*/
@@ -722,60 +659,64 @@ wv_synchronous_cmd(device * dev,
* Check if done, and if OK.
*/
static inline int
-wv_config_complete(device * dev,
- u_long ioaddr,
- net_local * lp)
+wv_config_complete(device * dev, unsigned long ioaddr, net_local * lp)
{
- unsigned short mcs_addr;
- unsigned short status;
- int ret;
+ unsigned short mcs_addr;
+ unsigned short status;
+ int ret;
#ifdef DEBUG_INTERRUPT_TRACE
- printk(KERN_DEBUG "%s: ->wv_config_complete()\n", dev->name);
+ printk(KERN_DEBUG "%s: ->wv_config_complete()\n", dev->name);
#endif
- mcs_addr = lp->tx_first_in_use + sizeof(ac_tx_t) + sizeof(ac_nop_t)
- + sizeof(tbd_t) + sizeof(ac_cfg_t) + sizeof(ac_ias_t);
+ mcs_addr = lp->tx_first_in_use + sizeof(ac_tx_t) + sizeof(ac_nop_t)
+ + sizeof(tbd_t) + sizeof(ac_cfg_t) + sizeof(ac_ias_t);
- /* Read the status of the last command (set mc list). */
- obram_read(ioaddr, acoff(mcs_addr, ac_status), (unsigned char *)&status, sizeof(status));
+ /* Read the status of the last command (set mc list). */
+ obram_read(ioaddr, acoff(mcs_addr, ac_status),
+ (unsigned char *) &status, sizeof(status));
- /* If not completed -> exit */
- if((status & AC_SFLD_C) == 0)
- ret = 0; /* Not ready to be scrapped */
- else
- {
+ /* If not completed -> exit */
+ if ((status & AC_SFLD_C) == 0)
+ ret = 0; /* Not ready to be scrapped */
+ else {
#ifdef DEBUG_CONFIG_ERROR
- unsigned short cfg_addr;
- unsigned short ias_addr;
-
- /* Check mc_config command */
- if((status & AC_SFLD_OK) != AC_SFLD_OK)
- printk(KERN_INFO "%s: wv_config_complete(): set_multicast_address failed; status = 0x%x\n",
- dev->name, status);
-
- /* check ia-config command */
- ias_addr = mcs_addr - sizeof(ac_ias_t);
- obram_read(ioaddr, acoff(ias_addr, ac_status), (unsigned char *)&status, sizeof(status));
- if((status & AC_SFLD_OK) != AC_SFLD_OK)
- printk(KERN_INFO "%s: wv_config_complete(): set_MAC_address failed; status = 0x%x\n",
- dev->name, status);
-
- /* Check config command. */
- cfg_addr = ias_addr - sizeof(ac_cfg_t);
- obram_read(ioaddr, acoff(cfg_addr, ac_status), (unsigned char *)&status, sizeof(status));
- if((status & AC_SFLD_OK) != AC_SFLD_OK)
- printk(KERN_INFO "%s: wv_config_complete(): configure failed; status = 0x%x\n",
- dev->name, status);
-#endif /* DEBUG_CONFIG_ERROR */
-
- ret = 1; /* Ready to be scrapped */
- }
+ unsigned short cfg_addr;
+ unsigned short ias_addr;
+
+ /* Check mc_config command */
+ if ((status & AC_SFLD_OK) != AC_SFLD_OK)
+ printk(KERN_INFO
+ "%s: wv_config_complete(): set_multicast_address failed; status = 0x%x\n",
+ dev->name, status);
+
+ /* check ia-config command */
+ ias_addr = mcs_addr - sizeof(ac_ias_t);
+ obram_read(ioaddr, acoff(ias_addr, ac_status),
+ (unsigned char *) &status, sizeof(status));
+ if ((status & AC_SFLD_OK) != AC_SFLD_OK)
+ printk(KERN_INFO
+ "%s: wv_config_complete(): set_MAC_address failed; status = 0x%x\n",
+ dev->name, status);
+
+ /* Check config command. */
+ cfg_addr = ias_addr - sizeof(ac_cfg_t);
+ obram_read(ioaddr, acoff(cfg_addr, ac_status),
+ (unsigned char *) &status, sizeof(status));
+ if ((status & AC_SFLD_OK) != AC_SFLD_OK)
+ printk(KERN_INFO
+ "%s: wv_config_complete(): configure failed; status = 0x%x\n",
+ dev->name, status);
+#endif /* DEBUG_CONFIG_ERROR */
+
+ ret = 1; /* Ready to be scrapped */
+ }
#ifdef DEBUG_INTERRUPT_TRACE
- printk(KERN_DEBUG "%s: <-wv_config_complete() - %d\n", dev->name, ret);
+ printk(KERN_DEBUG "%s: <-wv_config_complete() - %d\n", dev->name,
+ ret);
#endif
- return ret;
+ return ret;
}
/*------------------------------------------------------------------*/
@@ -783,141 +724,137 @@ wv_config_complete(device * dev,
* Command completion interrupt.
* Reclaim as many freed tx buffers as we can.
*/
-static int
-wv_complete(device * dev,
- u_long ioaddr,
- net_local * lp)
+static int wv_complete(device * dev, unsigned long ioaddr, net_local * lp)
{
- int nreaped = 0;
+ int nreaped = 0;
#ifdef DEBUG_INTERRUPT_TRACE
- printk(KERN_DEBUG "%s: ->wv_complete()\n", dev->name);
+ printk(KERN_DEBUG "%s: ->wv_complete()\n", dev->name);
#endif
- /* Loop on all the transmit buffers */
- while(lp->tx_first_in_use != I82586NULL)
- {
- unsigned short tx_status;
+ /* Loop on all the transmit buffers */
+ while (lp->tx_first_in_use != I82586NULL) {
+ unsigned short tx_status;
- /* Read the first transmit buffer */
- obram_read(ioaddr, acoff(lp->tx_first_in_use, ac_status), (unsigned char *)&tx_status, sizeof(tx_status));
+ /* Read the first transmit buffer */
+ obram_read(ioaddr, acoff(lp->tx_first_in_use, ac_status),
+ (unsigned char *) &tx_status,
+ sizeof(tx_status));
- /* If not completed -> exit */
- if((tx_status & AC_SFLD_C) == 0)
- break;
+ /* If not completed -> exit */
+ if ((tx_status & AC_SFLD_C) == 0)
+ break;
- /* Hack for reconfiguration */
- if(tx_status == 0xFFFF)
- if(!wv_config_complete(dev, ioaddr, lp))
- break; /* Not completed */
+ /* Hack for reconfiguration */
+ if (tx_status == 0xFFFF)
+ if (!wv_config_complete(dev, ioaddr, lp))
+ break; /* Not completed */
- /* We now remove this buffer */
- nreaped++;
- --lp->tx_n_in_use;
+ /* We now remove this buffer */
+ nreaped++;
+ --lp->tx_n_in_use;
/*
if (lp->tx_n_in_use > 0)
printk("%c", "0123456789abcdefghijk"[lp->tx_n_in_use]);
*/
- /* Was it the last one? */
- if(lp->tx_n_in_use <= 0)
- lp->tx_first_in_use = I82586NULL;
- else
- {
- /* Next one in the chain */
- lp->tx_first_in_use += TXBLOCKZ;
- if(lp->tx_first_in_use >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)
- lp->tx_first_in_use -= NTXBLOCKS * TXBLOCKZ;
- }
-
- /* Hack for reconfiguration */
- if(tx_status == 0xFFFF)
- continue;
-
- /* Now, check status of the finished command */
- if(tx_status & AC_SFLD_OK)
- {
- int ncollisions;
-
- lp->stats.tx_packets++;
- ncollisions = tx_status & AC_SFLD_MAXCOL;
- lp->stats.collisions += ncollisions;
+ /* Was it the last one? */
+ if (lp->tx_n_in_use <= 0)
+ lp->tx_first_in_use = I82586NULL;
+ else {
+ /* Next one in the chain */
+ lp->tx_first_in_use += TXBLOCKZ;
+ if (lp->tx_first_in_use >=
+ OFFSET_CU +
+ NTXBLOCKS * TXBLOCKZ) lp->tx_first_in_use -=
+ NTXBLOCKS * TXBLOCKZ;
+ }
+
+ /* Hack for reconfiguration */
+ if (tx_status == 0xFFFF)
+ continue;
+
+ /* Now, check status of the finished command */
+ if (tx_status & AC_SFLD_OK) {
+ int ncollisions;
+
+ lp->stats.tx_packets++;
+ ncollisions = tx_status & AC_SFLD_MAXCOL;
+ lp->stats.collisions += ncollisions;
#ifdef DEBUG_TX_INFO
- if(ncollisions > 0)
- printk(KERN_DEBUG "%s: wv_complete(): tx completed after %d collisions.\n",
- dev->name, ncollisions);
+ if (ncollisions > 0)
+ printk(KERN_DEBUG
+ "%s: wv_complete(): tx completed after %d collisions.\n",
+ dev->name, ncollisions);
#endif
- }
- else
- {
- lp->stats.tx_errors++;
- if(tx_status & AC_SFLD_S10)
- {
- lp->stats.tx_carrier_errors++;
+ } else {
+ lp->stats.tx_errors++;
+ if (tx_status & AC_SFLD_S10) {
+ lp->stats.tx_carrier_errors++;
#ifdef DEBUG_TX_FAIL
- printk(KERN_DEBUG "%s: wv_complete(): tx error: no CS.\n",
- dev->name);
+ printk(KERN_DEBUG
+ "%s: wv_complete(): tx error: no CS.\n",
+ dev->name);
#endif
- }
- if(tx_status & AC_SFLD_S9)
- {
- lp->stats.tx_carrier_errors++;
+ }
+ if (tx_status & AC_SFLD_S9) {
+ lp->stats.tx_carrier_errors++;
#ifdef DEBUG_TX_FAIL
- printk(KERN_DEBUG "%s: wv_complete(): tx error: lost CTS.\n",
- dev->name);
+ printk(KERN_DEBUG
+ "%s: wv_complete(): tx error: lost CTS.\n",
+ dev->name);
#endif
- }
- if(tx_status & AC_SFLD_S8)
- {
- lp->stats.tx_fifo_errors++;
+ }
+ if (tx_status & AC_SFLD_S8) {
+ lp->stats.tx_fifo_errors++;
#ifdef DEBUG_TX_FAIL
- printk(KERN_DEBUG "%s: wv_complete(): tx error: slow DMA.\n",
- dev->name);
+ printk(KERN_DEBUG
+ "%s: wv_complete(): tx error: slow DMA.\n",
+ dev->name);
#endif
- }
- if(tx_status & AC_SFLD_S6)
- {
- lp->stats.tx_heartbeat_errors++;
+ }
+ if (tx_status & AC_SFLD_S6) {
+ lp->stats.tx_heartbeat_errors++;
#ifdef DEBUG_TX_FAIL
- printk(KERN_DEBUG "%s: wv_complete(): tx error: heart beat.\n",
- dev->name);
+ printk(KERN_DEBUG
+ "%s: wv_complete(): tx error: heart beat.\n",
+ dev->name);
#endif
- }
- if(tx_status & AC_SFLD_S5)
- {
- lp->stats.tx_aborted_errors++;
+ }
+ if (tx_status & AC_SFLD_S5) {
+ lp->stats.tx_aborted_errors++;
#ifdef DEBUG_TX_FAIL
- printk(KERN_DEBUG "%s: wv_complete(): tx error: too many collisions.\n",
- dev->name);
+ printk(KERN_DEBUG
+ "%s: wv_complete(): tx error: too many collisions.\n",
+ dev->name);
#endif
- }
- }
+ }
+ }
#ifdef DEBUG_TX_INFO
- printk(KERN_DEBUG "%s: wv_complete(): tx completed, tx_status 0x%04x\n",
- dev->name, tx_status);
+ printk(KERN_DEBUG
+ "%s: wv_complete(): tx completed, tx_status 0x%04x\n",
+ dev->name, tx_status);
#endif
- }
+ }
#ifdef DEBUG_INTERRUPT_INFO
- if(nreaped > 1)
- printk(KERN_DEBUG "%s: wv_complete(): reaped %d\n", dev->name, nreaped);
+ if (nreaped > 1)
+ printk(KERN_DEBUG "%s: wv_complete(): reaped %d\n",
+ dev->name, nreaped);
#endif
- /*
- * Inform upper layers.
- */
- if(lp->tx_n_in_use < NTXBLOCKS - 1)
- {
- dev->tbusy = 0;
- mark_bh(NET_BH);
- }
-
+ /*
+ * Inform upper layers.
+ */
+ if (lp->tx_n_in_use < NTXBLOCKS - 1) {
+ netif_wake_queue(dev);
+ }
#ifdef DEBUG_INTERRUPT_TRACE
- printk(KERN_DEBUG "%s: <-wv_complete()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wv_complete()\n", dev->name);
#endif
- return nreaped;
+ return nreaped;
}
/*------------------------------------------------------------------*/
@@ -929,22 +866,20 @@ if (lp->tx_n_in_use > 0)
* wavelan_interrupt is not an option), so you may experience
* delays sometimes.
*/
-static inline void
-wv_82586_reconfig(device * dev)
+static inline void wv_82586_reconfig(device * dev)
{
- net_local * lp = (net_local *)dev->priv;
+ net_local *lp = (net_local *) dev->priv;
- /* Check if we can do it now ! */
- if(!(dev->start) || (test_and_set_bit(0, (void *)&dev->tbusy) != 0))
- {
- lp->reconfig_82586 = 1;
+ /* Check if we can do it now ! */
+ if (!netif_running(dev) && netif_queue_stopped(dev)) {
+ lp->reconfig_82586 = 1;
#ifdef DEBUG_CONFIG_INFO
- printk(KERN_DEBUG "%s: wv_82586_reconfig(): delayed (busy = %ld, start = %d)\n",
- dev->name, dev->tbusy, dev->start);
+ printk(KERN_DEBUG
+ "%s: wv_82586_reconfig(): delayed (state = %lX)\n",
+ dev->name, dev->state);
#endif
- }
- else
- wv_82586_config(dev);
+ } else
+ wv_82586_config(dev);
}
/********************* DEBUG & INFO SUBROUTINES *********************/
@@ -958,89 +893,73 @@ wv_82586_reconfig(device * dev)
/*
* Print the formatted contents of the Parameter Storage Area.
*/
-static void
-wv_psa_show(psa_t * p)
+static void wv_psa_show(psa_t * p)
{
- printk(KERN_DEBUG "##### WaveLAN PSA contents: #####\n");
- printk(KERN_DEBUG "psa_io_base_addr_1: 0x%02X %02X %02X %02X\n",
- p->psa_io_base_addr_1,
- p->psa_io_base_addr_2,
- p->psa_io_base_addr_3,
- p->psa_io_base_addr_4);
- printk(KERN_DEBUG "psa_rem_boot_addr_1: 0x%02X %02X %02X\n",
- p->psa_rem_boot_addr_1,
- p->psa_rem_boot_addr_2,
- p->psa_rem_boot_addr_3);
- printk(KERN_DEBUG "psa_holi_params: 0x%02x, ", p->psa_holi_params);
- printk("psa_int_req_no: %d\n", p->psa_int_req_no);
+ printk(KERN_DEBUG "##### WaveLAN PSA contents: #####\n");
+ printk(KERN_DEBUG "psa_io_base_addr_1: 0x%02X %02X %02X %02X\n",
+ p->psa_io_base_addr_1,
+ p->psa_io_base_addr_2,
+ p->psa_io_base_addr_3, p->psa_io_base_addr_4);
+ printk(KERN_DEBUG "psa_rem_boot_addr_1: 0x%02X %02X %02X\n",
+ p->psa_rem_boot_addr_1,
+ p->psa_rem_boot_addr_2, p->psa_rem_boot_addr_3);
+ printk(KERN_DEBUG "psa_holi_params: 0x%02x, ", p->psa_holi_params);
+ printk("psa_int_req_no: %d\n", p->psa_int_req_no);
#ifdef DEBUG_SHOW_UNUSED
- printk(KERN_DEBUG "psa_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
- p->psa_unused0[0],
- p->psa_unused0[1],
- p->psa_unused0[2],
- p->psa_unused0[3],
- p->psa_unused0[4],
- p->psa_unused0[5],
- p->psa_unused0[6]);
-#endif /* DEBUG_SHOW_UNUSED */
- printk(KERN_DEBUG "psa_univ_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x\n",
- p->psa_univ_mac_addr[0],
- p->psa_univ_mac_addr[1],
- p->psa_univ_mac_addr[2],
- p->psa_univ_mac_addr[3],
- p->psa_univ_mac_addr[4],
- p->psa_univ_mac_addr[5]);
- printk(KERN_DEBUG "psa_local_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x\n",
- p->psa_local_mac_addr[0],
- p->psa_local_mac_addr[1],
- p->psa_local_mac_addr[2],
- p->psa_local_mac_addr[3],
- p->psa_local_mac_addr[4],
- p->psa_local_mac_addr[5]);
- printk(KERN_DEBUG "psa_univ_local_sel: %d, ", p->psa_univ_local_sel);
- printk("psa_comp_number: %d, ", p->psa_comp_number);
- printk("psa_thr_pre_set: 0x%02x\n", p->psa_thr_pre_set);
- printk(KERN_DEBUG "psa_feature_select/decay_prm: 0x%02x, ",
- p->psa_feature_select);
- printk("psa_subband/decay_update_prm: %d\n", p->psa_subband);
- printk(KERN_DEBUG "psa_quality_thr: 0x%02x, ", p->psa_quality_thr);
- printk("psa_mod_delay: 0x%02x\n", p->psa_mod_delay);
- printk(KERN_DEBUG "psa_nwid: 0x%02x%02x, ", p->psa_nwid[0], p->psa_nwid[1]);
- printk("psa_nwid_select: %d\n", p->psa_nwid_select);
- printk(KERN_DEBUG "psa_encryption_select: %d, ", p->psa_encryption_select);
- printk("psa_encryption_key[]: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
- p->psa_encryption_key[0],
- p->psa_encryption_key[1],
- p->psa_encryption_key[2],
- p->psa_encryption_key[3],
- p->psa_encryption_key[4],
- p->psa_encryption_key[5],
- p->psa_encryption_key[6],
- p->psa_encryption_key[7]);
- printk(KERN_DEBUG "psa_databus_width: %d\n", p->psa_databus_width);
- printk(KERN_DEBUG "psa_call_code/auto_squelch: 0x%02x, ",
- p->psa_call_code[0]);
- printk("psa_call_code[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
- p->psa_call_code[0],
- p->psa_call_code[1],
- p->psa_call_code[2],
- p->psa_call_code[3],
- p->psa_call_code[4],
- p->psa_call_code[5],
- p->psa_call_code[6],
- p->psa_call_code[7]);
+ printk(KERN_DEBUG
+ "psa_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
+ p->psa_unused0[0], p->psa_unused0[1], p->psa_unused0[2],
+ p->psa_unused0[3], p->psa_unused0[4], p->psa_unused0[5],
+ p->psa_unused0[6]);
+#endif /* DEBUG_SHOW_UNUSED */
+ printk(KERN_DEBUG
+ "psa_univ_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ p->psa_univ_mac_addr[0], p->psa_univ_mac_addr[1],
+ p->psa_univ_mac_addr[2], p->psa_univ_mac_addr[3],
+ p->psa_univ_mac_addr[4], p->psa_univ_mac_addr[5]);
+ printk(KERN_DEBUG
+ "psa_local_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ p->psa_local_mac_addr[0], p->psa_local_mac_addr[1],
+ p->psa_local_mac_addr[2], p->psa_local_mac_addr[3],
+ p->psa_local_mac_addr[4], p->psa_local_mac_addr[5]);
+ printk(KERN_DEBUG "psa_univ_local_sel: %d, ",
+ p->psa_univ_local_sel);
+ printk("psa_comp_number: %d, ", p->psa_comp_number);
+ printk("psa_thr_pre_set: 0x%02x\n", p->psa_thr_pre_set);
+ printk(KERN_DEBUG "psa_feature_select/decay_prm: 0x%02x, ",
+ p->psa_feature_select);
+ printk("psa_subband/decay_update_prm: %d\n", p->psa_subband);
+ printk(KERN_DEBUG "psa_quality_thr: 0x%02x, ", p->psa_quality_thr);
+ printk("psa_mod_delay: 0x%02x\n", p->psa_mod_delay);
+ printk(KERN_DEBUG "psa_nwid: 0x%02x%02x, ", p->psa_nwid[0],
+ p->psa_nwid[1]);
+ printk("psa_nwid_select: %d\n", p->psa_nwid_select);
+ printk(KERN_DEBUG "psa_encryption_select: %d, ",
+ p->psa_encryption_select);
+ printk
+ ("psa_encryption_key[]: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ p->psa_encryption_key[0], p->psa_encryption_key[1],
+ p->psa_encryption_key[2], p->psa_encryption_key[3],
+ p->psa_encryption_key[4], p->psa_encryption_key[5],
+ p->psa_encryption_key[6], p->psa_encryption_key[7]);
+ printk(KERN_DEBUG "psa_databus_width: %d\n", p->psa_databus_width);
+ printk(KERN_DEBUG "psa_call_code/auto_squelch: 0x%02x, ",
+ p->psa_call_code[0]);
+ printk
+ ("psa_call_code[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
+ p->psa_call_code[0], p->psa_call_code[1], p->psa_call_code[2],
+ p->psa_call_code[3], p->psa_call_code[4], p->psa_call_code[5],
+ p->psa_call_code[6], p->psa_call_code[7]);
#ifdef DEBUG_SHOW_UNUSED
- printk(KERN_DEBUG "psa_reserved[]: %02X:%02X:%02X:%02X\n",
- p->psa_reserved[0],
- p->psa_reserved[1],
- p->psa_reserved[2],
- p->psa_reserved[3]);
-#endif /* DEBUG_SHOW_UNUSED */
- printk(KERN_DEBUG "psa_conf_status: %d, ", p->psa_conf_status);
- printk("psa_crc: 0x%02x%02x, ", p->psa_crc[0], p->psa_crc[1]);
- printk("psa_crc_status: 0x%02x\n", p->psa_crc_status);
-} /* wv_psa_show */
-#endif /* DEBUG_PSA_SHOW */
+ printk(KERN_DEBUG "psa_reserved[]: %02X:%02X:%02X:%02X\n",
+ p->psa_reserved[0],
+ p->psa_reserved[1], p->psa_reserved[2], p->psa_reserved[3]);
+#endif /* DEBUG_SHOW_UNUSED */
+ printk(KERN_DEBUG "psa_conf_status: %d, ", p->psa_conf_status);
+ printk("psa_crc: 0x%02x%02x, ", p->psa_crc[0], p->psa_crc[1]);
+ printk("psa_crc_status: 0x%02x\n", p->psa_crc_status);
+} /* wv_psa_show */
+#endif /* DEBUG_PSA_SHOW */
#ifdef DEBUG_MMC_SHOW
/*------------------------------------------------------------------*/
@@ -1048,411 +967,432 @@ wv_psa_show(psa_t * p)
* Print the formatted status of the Modem Management Controller.
* This function needs to be completed.
*/
-static void
-wv_mmc_show(device * dev)
+static void wv_mmc_show(device * dev)
{
- u_long ioaddr = dev->base_addr;
- net_local * lp = (net_local *)dev->priv;
- mmr_t m;
-
- /* Basic check */
- if(hasr_read(ioaddr) & HASR_NO_CLK)
- {
- printk(KERN_WARNING "%s: wv_mmc_show: modem not connected\n",
- dev->name);
- return;
- }
-
- /* Read the mmc */
- mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1);
- mmc_read(ioaddr, 0, (u_char *)&m, sizeof(m));
- mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
-
-#ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */
- /* Don't forget to update statistics */
- lp->wstats.discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
-#endif /* WIRELESS_EXT */
-
- printk(KERN_DEBUG "##### WaveLAN modem status registers: #####\n");
+ unsigned long ioaddr = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv;
+ mmr_t m;
+
+ /* Basic check */
+ if (hasr_read(ioaddr) & HASR_NO_CLK) {
+ printk(KERN_WARNING
+ "%s: wv_mmc_show: modem not connected\n",
+ dev->name);
+ return;
+ }
+
+ /* Read the mmc */
+ mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1);
+ mmc_read(ioaddr, 0, (u8 *) & m, sizeof(m));
+ mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
+
+#ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */
+ /* Don't forget to update statistics */
+ lp->wstats.discard.nwid +=
+ (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
+#endif /* WIRELESS_EXT */
+
+ printk(KERN_DEBUG "##### WaveLAN modem status registers: #####\n");
#ifdef DEBUG_SHOW_UNUSED
- printk(KERN_DEBUG "mmc_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
- m.mmr_unused0[0],
- m.mmr_unused0[1],
- m.mmr_unused0[2],
- m.mmr_unused0[3],
- m.mmr_unused0[4],
- m.mmr_unused0[5],
- m.mmr_unused0[6],
- m.mmr_unused0[7]);
-#endif /* DEBUG_SHOW_UNUSED */
- printk(KERN_DEBUG "Encryption algorithm: %02X - Status: %02X\n",
- m.mmr_des_avail, m.mmr_des_status);
+ printk(KERN_DEBUG
+ "mmc_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
+ m.mmr_unused0[0], m.mmr_unused0[1], m.mmr_unused0[2],
+ m.mmr_unused0[3], m.mmr_unused0[4], m.mmr_unused0[5],
+ m.mmr_unused0[6], m.mmr_unused0[7]);
+#endif /* DEBUG_SHOW_UNUSED */
+ printk(KERN_DEBUG "Encryption algorithm: %02X - Status: %02X\n",
+ m.mmr_des_avail, m.mmr_des_status);
#ifdef DEBUG_SHOW_UNUSED
- printk(KERN_DEBUG "mmc_unused1[]: %02X:%02X:%02X:%02X:%02X\n",
- m.mmr_unused1[0],
- m.mmr_unused1[1],
- m.mmr_unused1[2],
- m.mmr_unused1[3],
- m.mmr_unused1[4]);
-#endif /* DEBUG_SHOW_UNUSED */
- printk(KERN_DEBUG "dce_status: 0x%x [%s%s%s%s]\n",
- m.mmr_dce_status,
- (m.mmr_dce_status & MMR_DCE_STATUS_RX_BUSY) ? "energy detected,":"",
- (m.mmr_dce_status & MMR_DCE_STATUS_LOOPT_IND) ?
- "loop test indicated," : "",
- (m.mmr_dce_status & MMR_DCE_STATUS_TX_BUSY) ? "transmitter on," : "",
- (m.mmr_dce_status & MMR_DCE_STATUS_JBR_EXPIRED) ?
- "jabber timer expired," : "");
- printk(KERN_DEBUG "Dsp ID: %02X\n",
- m.mmr_dsp_id);
+ printk(KERN_DEBUG "mmc_unused1[]: %02X:%02X:%02X:%02X:%02X\n",
+ m.mmr_unused1[0],
+ m.mmr_unused1[1],
+ m.mmr_unused1[2], m.mmr_unused1[3], m.mmr_unused1[4]);
+#endif /* DEBUG_SHOW_UNUSED */
+ printk(KERN_DEBUG "dce_status: 0x%x [%s%s%s%s]\n",
+ m.mmr_dce_status,
+ (m.
+ mmr_dce_status & MMR_DCE_STATUS_RX_BUSY) ?
+ "energy detected," : "",
+ (m.
+ mmr_dce_status & MMR_DCE_STATUS_LOOPT_IND) ?
+ "loop test indicated," : "",
+ (m.
+ mmr_dce_status & MMR_DCE_STATUS_TX_BUSY) ?
+ "transmitter on," : "",
+ (m.
+ mmr_dce_status & MMR_DCE_STATUS_JBR_EXPIRED) ?
+ "jabber timer expired," : "");
+ printk(KERN_DEBUG "Dsp ID: %02X\n", m.mmr_dsp_id);
#ifdef DEBUG_SHOW_UNUSED
- printk(KERN_DEBUG "mmc_unused2[]: %02X:%02X\n",
- m.mmr_unused2[0],
- m.mmr_unused2[1]);
-#endif /* DEBUG_SHOW_UNUSED */
- printk(KERN_DEBUG "# correct_nwid: %d, # wrong_nwid: %d\n",
- (m.mmr_correct_nwid_h << 8) | m.mmr_correct_nwid_l,
- (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l);
- printk(KERN_DEBUG "thr_pre_set: 0x%x [current signal %s]\n",
- m.mmr_thr_pre_set & MMR_THR_PRE_SET,
- (m.mmr_thr_pre_set & MMR_THR_PRE_SET_CUR) ? "above" : "below");
- printk(KERN_DEBUG "signal_lvl: %d [%s], ",
- m.mmr_signal_lvl & MMR_SIGNAL_LVL,
- (m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) ? "new msg" : "no new msg");
- printk("silence_lvl: %d [%s], ", m.mmr_silence_lvl & MMR_SILENCE_LVL,
- (m.mmr_silence_lvl & MMR_SILENCE_LVL_VALID) ? "update done" : "no new update");
- printk("sgnl_qual: 0x%x [%s]\n",
- m.mmr_sgnl_qual & MMR_SGNL_QUAL,
- (m.mmr_sgnl_qual & MMR_SGNL_QUAL_ANT) ? "Antenna 1" : "Antenna 0");
+ printk(KERN_DEBUG "mmc_unused2[]: %02X:%02X\n",
+ m.mmr_unused2[0], m.mmr_unused2[1]);
+#endif /* DEBUG_SHOW_UNUSED */
+ printk(KERN_DEBUG "# correct_nwid: %d, # wrong_nwid: %d\n",
+ (m.mmr_correct_nwid_h << 8) | m.mmr_correct_nwid_l,
+ (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l);
+ printk(KERN_DEBUG "thr_pre_set: 0x%x [current signal %s]\n",
+ m.mmr_thr_pre_set & MMR_THR_PRE_SET,
+ (m.
+ mmr_thr_pre_set & MMR_THR_PRE_SET_CUR) ? "above" :
+ "below");
+ printk(KERN_DEBUG "signal_lvl: %d [%s], ",
+ m.mmr_signal_lvl & MMR_SIGNAL_LVL,
+ (m.
+ mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) ? "new msg" :
+ "no new msg");
+ printk("silence_lvl: %d [%s], ",
+ m.mmr_silence_lvl & MMR_SILENCE_LVL,
+ (m.
+ mmr_silence_lvl & MMR_SILENCE_LVL_VALID) ? "update done" :
+ "no new update");
+ printk("sgnl_qual: 0x%x [%s]\n", m.mmr_sgnl_qual & MMR_SGNL_QUAL,
+ (m.
+ mmr_sgnl_qual & MMR_SGNL_QUAL_ANT) ? "Antenna 1" :
+ "Antenna 0");
#ifdef DEBUG_SHOW_UNUSED
- printk(KERN_DEBUG "netw_id_l: %x\n", m.mmr_netw_id_l);
-#endif /* DEBUG_SHOW_UNUSED */
-} /* wv_mmc_show */
-#endif /* DEBUG_MMC_SHOW */
+ printk(KERN_DEBUG "netw_id_l: %x\n", m.mmr_netw_id_l);
+#endif /* DEBUG_SHOW_UNUSED */
+} /* wv_mmc_show */
+#endif /* DEBUG_MMC_SHOW */
#ifdef DEBUG_I82586_SHOW
/*------------------------------------------------------------------*/
/*
* Print the last block of the i82586 memory.
*/
-static void
-wv_scb_show(u_long ioaddr)
+static void wv_scb_show(unsigned long ioaddr)
{
- scb_t scb;
-
- obram_read(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb));
-
- printk(KERN_DEBUG "##### WaveLAN system control block: #####\n");
-
- printk(KERN_DEBUG "status: ");
- printk("stat 0x%x[%s%s%s%s] ",
- (scb.scb_status & (SCB_ST_CX | SCB_ST_FR | SCB_ST_CNA | SCB_ST_RNR)) >> 12,
- (scb.scb_status & SCB_ST_CX) ? "command completion interrupt," : "",
- (scb.scb_status & SCB_ST_FR) ? "frame received," : "",
- (scb.scb_status & SCB_ST_CNA) ? "command unit not active," : "",
- (scb.scb_status & SCB_ST_RNR) ? "receiving unit not ready," : "");
- printk("cus 0x%x[%s%s%s] ",
- (scb.scb_status & SCB_ST_CUS) >> 8,
- ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_IDLE) ? "idle" : "",
- ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_SUSP) ? "suspended" : "",
- ((scb.scb_status & SCB_ST_CUS) == SCB_ST_CUS_ACTV) ? "active" : "");
- printk("rus 0x%x[%s%s%s%s]\n",
- (scb.scb_status & SCB_ST_RUS) >> 4,
- ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_IDLE) ? "idle" : "",
- ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_SUSP) ? "suspended" : "",
- ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_NRES) ? "no resources" : "",
- ((scb.scb_status & SCB_ST_RUS) == SCB_ST_RUS_RDY) ? "ready" : "");
-
- printk(KERN_DEBUG "command: ");
- printk("ack 0x%x[%s%s%s%s] ",
- (scb.scb_command & (SCB_CMD_ACK_CX | SCB_CMD_ACK_FR | SCB_CMD_ACK_CNA | SCB_CMD_ACK_RNR)) >> 12,
- (scb.scb_command & SCB_CMD_ACK_CX) ? "ack cmd completion," : "",
- (scb.scb_command & SCB_CMD_ACK_FR) ? "ack frame received," : "",
- (scb.scb_command & SCB_CMD_ACK_CNA) ? "ack CU not active," : "",
- (scb.scb_command & SCB_CMD_ACK_RNR) ? "ack RU not ready," : "");
- printk("cuc 0x%x[%s%s%s%s%s] ",
- (scb.scb_command & SCB_CMD_CUC) >> 8,
- ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_NOP) ? "nop" : "",
- ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_GO) ? "start cbl_offset" : "",
- ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_RES) ? "resume execution" : "",
- ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_SUS) ? "suspend execution" : "",
- ((scb.scb_command & SCB_CMD_CUC) == SCB_CMD_CUC_ABT) ? "abort execution" : "");
- printk("ruc 0x%x[%s%s%s%s%s]\n",
- (scb.scb_command & SCB_CMD_RUC) >> 4,
- ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_NOP) ? "nop" : "",
- ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_GO) ? "start rfa_offset" : "",
- ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_RES) ? "resume reception" : "",
- ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_SUS) ? "suspend reception" : "",
- ((scb.scb_command & SCB_CMD_RUC) == SCB_CMD_RUC_ABT) ? "abort reception" : "");
-
- printk(KERN_DEBUG "cbl_offset 0x%x ", scb.scb_cbl_offset);
- printk("rfa_offset 0x%x\n", scb.scb_rfa_offset);
-
- printk(KERN_DEBUG "crcerrs %d ", scb.scb_crcerrs);
- printk("alnerrs %d ", scb.scb_alnerrs);
- printk("rscerrs %d ", scb.scb_rscerrs);
- printk("ovrnerrs %d\n", scb.scb_ovrnerrs);
+ scb_t scb;
+
+ obram_read(ioaddr, OFFSET_SCB, (unsigned char *) &scb,
+ sizeof(scb));
+
+ printk(KERN_DEBUG "##### WaveLAN system control block: #####\n");
+
+ printk(KERN_DEBUG "status: ");
+ printk("stat 0x%x[%s%s%s%s] ",
+ (scb.
+ scb_status & (SCB_ST_CX | SCB_ST_FR | SCB_ST_CNA |
+ SCB_ST_RNR)) >> 12,
+ (scb.
+ scb_status & SCB_ST_CX) ? "command completion interrupt," :
+ "", (scb.scb_status & SCB_ST_FR) ? "frame received," : "",
+ (scb.
+ scb_status & SCB_ST_CNA) ? "command unit not active," : "",
+ (scb.
+ scb_status & SCB_ST_RNR) ? "receiving unit not ready," :
+ "");
+ printk("cus 0x%x[%s%s%s] ", (scb.scb_status & SCB_ST_CUS) >> 8,
+ ((scb.scb_status & SCB_ST_CUS) ==
+ SCB_ST_CUS_IDLE) ? "idle" : "",
+ ((scb.scb_status & SCB_ST_CUS) ==
+ SCB_ST_CUS_SUSP) ? "suspended" : "",
+ ((scb.scb_status & SCB_ST_CUS) ==
+ SCB_ST_CUS_ACTV) ? "active" : "");
+ printk("rus 0x%x[%s%s%s%s]\n", (scb.scb_status & SCB_ST_RUS) >> 4,
+ ((scb.scb_status & SCB_ST_RUS) ==
+ SCB_ST_RUS_IDLE) ? "idle" : "",
+ ((scb.scb_status & SCB_ST_RUS) ==
+ SCB_ST_RUS_SUSP) ? "suspended" : "",
+ ((scb.scb_status & SCB_ST_RUS) ==
+ SCB_ST_RUS_NRES) ? "no resources" : "",
+ ((scb.scb_status & SCB_ST_RUS) ==
+ SCB_ST_RUS_RDY) ? "ready" : "");
+
+ printk(KERN_DEBUG "command: ");
+ printk("ack 0x%x[%s%s%s%s] ",
+ (scb.
+ scb_command & (SCB_CMD_ACK_CX | SCB_CMD_ACK_FR |
+ SCB_CMD_ACK_CNA | SCB_CMD_ACK_RNR)) >> 12,
+ (scb.
+ scb_command & SCB_CMD_ACK_CX) ? "ack cmd completion," : "",
+ (scb.
+ scb_command & SCB_CMD_ACK_FR) ? "ack frame received," : "",
+ (scb.
+ scb_command & SCB_CMD_ACK_CNA) ? "ack CU not active," : "",
+ (scb.
+ scb_command & SCB_CMD_ACK_RNR) ? "ack RU not ready," : "");
+ printk("cuc 0x%x[%s%s%s%s%s] ",
+ (scb.scb_command & SCB_CMD_CUC) >> 8,
+ ((scb.scb_command & SCB_CMD_CUC) ==
+ SCB_CMD_CUC_NOP) ? "nop" : "",
+ ((scb.scb_command & SCB_CMD_CUC) ==
+ SCB_CMD_CUC_GO) ? "start cbl_offset" : "",
+ ((scb.scb_command & SCB_CMD_CUC) ==
+ SCB_CMD_CUC_RES) ? "resume execution" : "",
+ ((scb.scb_command & SCB_CMD_CUC) ==
+ SCB_CMD_CUC_SUS) ? "suspend execution" : "",
+ ((scb.scb_command & SCB_CMD_CUC) ==
+ SCB_CMD_CUC_ABT) ? "abort execution" : "");
+ printk("ruc 0x%x[%s%s%s%s%s]\n",
+ (scb.scb_command & SCB_CMD_RUC) >> 4,
+ ((scb.scb_command & SCB_CMD_RUC) ==
+ SCB_CMD_RUC_NOP) ? "nop" : "",
+ ((scb.scb_command & SCB_CMD_RUC) ==
+ SCB_CMD_RUC_GO) ? "start rfa_offset" : "",
+ ((scb.scb_command & SCB_CMD_RUC) ==
+ SCB_CMD_RUC_RES) ? "resume reception" : "",
+ ((scb.scb_command & SCB_CMD_RUC) ==
+ SCB_CMD_RUC_SUS) ? "suspend reception" : "",
+ ((scb.scb_command & SCB_CMD_RUC) ==
+ SCB_CMD_RUC_ABT) ? "abort reception" : "");
+
+ printk(KERN_DEBUG "cbl_offset 0x%x ", scb.scb_cbl_offset);
+ printk("rfa_offset 0x%x\n", scb.scb_rfa_offset);
+
+ printk(KERN_DEBUG "crcerrs %d ", scb.scb_crcerrs);
+ printk("alnerrs %d ", scb.scb_alnerrs);
+ printk("rscerrs %d ", scb.scb_rscerrs);
+ printk("ovrnerrs %d\n", scb.scb_ovrnerrs);
}
/*------------------------------------------------------------------*/
/*
* Print the formatted status of the i82586's receive unit.
*/
-static void
-wv_ru_show(device * dev)
+static void wv_ru_show(device * dev)
{
- /* net_local *lp = (net_local *) dev->priv; */
+ /* net_local *lp = (net_local *) dev->priv; */
- printk(KERN_DEBUG "##### WaveLAN i82586 receiver unit status: #####\n");
- printk(KERN_DEBUG "ru:");
- /*
- * Not implemented yet
- */
- printk("\n");
-} /* wv_ru_show */
+ printk(KERN_DEBUG
+ "##### WaveLAN i82586 receiver unit status: #####\n");
+ printk(KERN_DEBUG "ru:");
+ /*
+ * Not implemented yet
+ */
+ printk("\n");
+} /* wv_ru_show */
/*------------------------------------------------------------------*/
/*
* Display info about one control block of the i82586 memory.
*/
-static void
-wv_cu_show_one(device * dev,
- net_local * lp,
- int i,
- u_short p)
+static void wv_cu_show_one(device * dev, net_local * lp, int i, u16 p)
{
- u_long ioaddr;
- ac_tx_t actx;
+ unsigned long ioaddr;
+ ac_tx_t actx;
- ioaddr = dev->base_addr;
+ ioaddr = dev->base_addr;
- printk("%d: 0x%x:", i, p);
+ printk("%d: 0x%x:", i, p);
- obram_read(ioaddr, p, (unsigned char *)&actx, sizeof(actx));
- printk(" status=0x%x,", actx.tx_h.ac_status);
- printk(" command=0x%x,", actx.tx_h.ac_command);
+ obram_read(ioaddr, p, (unsigned char *) &actx, sizeof(actx));
+ printk(" status=0x%x,", actx.tx_h.ac_status);
+ printk(" command=0x%x,", actx.tx_h.ac_command);
- /*
- {
- tbd_t tbd;
+ /*
+ {
+ tbd_t tbd;
- obram_read(ioaddr, actx.tx_tbd_offset, (unsigned char *)&tbd, sizeof(tbd));
- printk(" tbd_status=0x%x,", tbd.tbd_status);
- }
- */
+ obram_read(ioaddr, actx.tx_tbd_offset, (unsigned char *)&tbd, sizeof(tbd));
+ printk(" tbd_status=0x%x,", tbd.tbd_status);
+ }
+ */
- printk("|");
+ printk("|");
}
/*------------------------------------------------------------------*/
/*
* Print status of the command unit of the i82586.
*/
-static void
-wv_cu_show(device * dev)
+static void wv_cu_show(device * dev)
{
- net_local * lp = (net_local *)dev->priv;
- unsigned int i;
- u_short p;
-
- printk(KERN_DEBUG "##### WaveLAN i82586 command unit status: #####\n");
-
- printk(KERN_DEBUG);
- for(i = 0, p = lp->tx_first_in_use; i < NTXBLOCKS; i++)
- {
- wv_cu_show_one(dev, lp, i, p);
-
- p += TXBLOCKZ;
- if(p >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)
- p -= NTXBLOCKS * TXBLOCKZ;
- }
- printk("\n");
+ net_local *lp = (net_local *) dev->priv;
+ unsigned int i;
+ u16 p;
+
+ printk(KERN_DEBUG
+ "##### WaveLAN i82586 command unit status: #####\n");
+
+ printk(KERN_DEBUG);
+ for (i = 0, p = lp->tx_first_in_use; i < NTXBLOCKS; i++) {
+ wv_cu_show_one(dev, lp, i, p);
+
+ p += TXBLOCKZ;
+ if (p >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)
+ p -= NTXBLOCKS * TXBLOCKZ;
+ }
+ printk("\n");
}
-#endif /* DEBUG_I82586_SHOW */
+#endif /* DEBUG_I82586_SHOW */
#ifdef DEBUG_DEVICE_SHOW
/*------------------------------------------------------------------*/
/*
* Print the formatted status of the WaveLAN PCMCIA device driver.
*/
-static void
-wv_dev_show(device * dev)
+static void wv_dev_show(device * dev)
{
- printk(KERN_DEBUG "dev:");
- printk(" start=%d,", dev->start);
- printk(" tbusy=%ld,", dev->tbusy);
- printk(" interrupt=%d,", dev->interrupt);
- printk(" trans_start=%ld,", dev->trans_start);
- printk(" flags=0x%x,", dev->flags);
- printk("\n");
-} /* wv_dev_show */
+ printk(KERN_DEBUG "dev:");
+ printk(" state=%lX,", dev->state);
+ printk(" trans_start=%ld,", dev->trans_start);
+ printk(" flags=0x%x,", dev->flags);
+ printk("\n");
+} /* wv_dev_show */
/*------------------------------------------------------------------*/
/*
* Print the formatted status of the WaveLAN PCMCIA device driver's
* private information.
*/
-static void
-wv_local_show(device * dev)
+static void wv_local_show(device * dev)
{
- net_local *lp;
+ net_local *lp;
- lp = (net_local *)dev->priv;
+ lp = (net_local *) dev->priv;
- printk(KERN_DEBUG "local:");
- printk(" tx_n_in_use=%d,", lp->tx_n_in_use);
- printk(" hacr=0x%x,", lp->hacr);
- printk(" rx_head=0x%x,", lp->rx_head);
- printk(" rx_last=0x%x,", lp->rx_last);
- printk(" tx_first_free=0x%x,", lp->tx_first_free);
- printk(" tx_first_in_use=0x%x,", lp->tx_first_in_use);
- printk("\n");
-} /* wv_local_show */
-#endif /* DEBUG_DEVICE_SHOW */
+ printk(KERN_DEBUG "local:");
+ printk(" tx_n_in_use=%d,", lp->tx_n_in_use);
+ printk(" hacr=0x%x,", lp->hacr);
+ printk(" rx_head=0x%x,", lp->rx_head);
+ printk(" rx_last=0x%x,", lp->rx_last);
+ printk(" tx_first_free=0x%x,", lp->tx_first_free);
+ printk(" tx_first_in_use=0x%x,", lp->tx_first_in_use);
+ printk("\n");
+} /* wv_local_show */
+#endif /* DEBUG_DEVICE_SHOW */
#if defined(DEBUG_RX_INFO) || defined(DEBUG_TX_INFO)
/*------------------------------------------------------------------*/
/*
* Dump packet header (and content if necessary) on the screen
*/
-static inline void
-wv_packet_info(u_char * p, /* Packet to dump */
- int length, /* Length of the packet */
- char * msg1, /* Name of the device */
- char * msg2) /* Name of the function */
-{
- int i;
- int maxi;
-
- printk(KERN_DEBUG "%s: %s(): dest %02X:%02X:%02X:%02X:%02X:%02X, length %d\n",
- msg1, msg2, p[0], p[1], p[2], p[3], p[4], p[5], length);
- printk(KERN_DEBUG "%s: %s(): src %02X:%02X:%02X:%02X:%02X:%02X, type 0x%02X%02X\n",
- msg1, msg2, p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13]);
+static inline void wv_packet_info(u8 * p, /* Packet to dump */
+ int length, /* Length of the packet */
+ char *msg1, /* Name of the device */
+ char *msg2)
+{ /* Name of the function */
+ int i;
+ int maxi;
+
+ printk(KERN_DEBUG
+ "%s: %s(): dest %02X:%02X:%02X:%02X:%02X:%02X, length %d\n",
+ msg1, msg2, p[0], p[1], p[2], p[3], p[4], p[5], length);
+ printk(KERN_DEBUG
+ "%s: %s(): src %02X:%02X:%02X:%02X:%02X:%02X, type 0x%02X%02X\n",
+ msg1, msg2, p[6], p[7], p[8], p[9], p[10], p[11], p[12],
+ p[13]);
#ifdef DEBUG_PACKET_DUMP
- printk(KERN_DEBUG "data=\"");
-
- if((maxi = length) > DEBUG_PACKET_DUMP)
- maxi = DEBUG_PACKET_DUMP;
- for(i = 14; i < maxi; i++)
- if(p[i] >= ' ' && p[i] <= '~')
- printk(" %c", p[i]);
- else
- printk("%02X", p[i]);
- if(maxi < length)
- printk("..");
- printk("\"\n");
- printk(KERN_DEBUG "\n");
-#endif /* DEBUG_PACKET_DUMP */
+ printk(KERN_DEBUG "data=\"");
+
+ if ((maxi = length) > DEBUG_PACKET_DUMP)
+ maxi = DEBUG_PACKET_DUMP;
+ for (i = 14; i < maxi; i++)
+ if (p[i] >= ' ' && p[i] <= '~')
+ printk(" %c", p[i]);
+ else
+ printk("%02X", p[i]);
+ if (maxi < length)
+ printk("..");
+ printk("\"\n");
+ printk(KERN_DEBUG "\n");
+#endif /* DEBUG_PACKET_DUMP */
}
-#endif /* defined(DEBUG_RX_INFO) || defined(DEBUG_TX_INFO) */
+#endif /* defined(DEBUG_RX_INFO) || defined(DEBUG_TX_INFO) */
/*------------------------------------------------------------------*/
/*
* This is the information which is displayed by the driver at startup.
* There are lots of flags for configuring it to your liking.
*/
-static inline void
-wv_init_info(device * dev)
+static inline void wv_init_info(device * dev)
{
- short ioaddr = dev->base_addr;
- net_local * lp = (net_local *)dev->priv;
- psa_t psa;
- int i;
+ short ioaddr = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv;
+ psa_t psa;
+ int i;
- /* Read the parameter storage area */
- psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa));
+ /* Read the parameter storage area */
+ psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa));
#ifdef DEBUG_PSA_SHOW
- wv_psa_show(&psa);
+ wv_psa_show(&psa);
#endif
#ifdef DEBUG_MMC_SHOW
- wv_mmc_show(dev);
+ wv_mmc_show(dev);
#endif
#ifdef DEBUG_I82586_SHOW
- wv_cu_show(dev);
+ wv_cu_show(dev);
#endif
#ifdef DEBUG_BASIC_SHOW
- /* Now, let's go for the basic stuff. */
- printk(KERN_NOTICE "%s: WaveLAN at %#x,", dev->name, ioaddr);
- for(i = 0; i < WAVELAN_ADDR_SIZE; i++)
- printk("%s%02X", (i == 0) ? " " : ":", dev->dev_addr[i]);
- printk(", IRQ %d", dev->irq);
-
- /* Print current network ID. */
- if(psa.psa_nwid_select)
- printk(", nwid 0x%02X-%02X", psa.psa_nwid[0], psa.psa_nwid[1]);
- else
- printk(", nwid off");
-
- /* If 2.00 card */
- if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
- (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
- {
- unsigned short freq;
-
- /* Ask the EEPROM to read the frequency from the first area. */
- fee_read(ioaddr, 0x00, &freq, 1);
-
- /* Print frequency */
- printk(", 2.00, %ld", (freq >> 6) + 2400L);
-
- /* Hack! */
- if(freq & 0x20)
- printk(".5");
- }
- else
- {
- printk(", PC");
- switch(psa.psa_comp_number)
- {
- case PSA_COMP_PC_AT_915:
- case PSA_COMP_PC_AT_2400:
- printk("-AT");
- break;
- case PSA_COMP_PC_MC_915:
- case PSA_COMP_PC_MC_2400:
- printk("-MC");
- break;
- case PSA_COMP_PCMCIA_915:
- printk("MCIA");
- break;
- default:
- printk("?");
+ /* Now, let's go for the basic stuff. */
+ printk(KERN_NOTICE "%s: WaveLAN at %#x,", dev->name, ioaddr);
+ for (i = 0; i < WAVELAN_ADDR_SIZE; i++)
+ printk("%s%02X", (i == 0) ? " " : ":", dev->dev_addr[i]);
+ printk(", IRQ %d", dev->irq);
+
+ /* Print current network ID. */
+ if (psa.psa_nwid_select)
+ printk(", nwid 0x%02X-%02X", psa.psa_nwid[0],
+ psa.psa_nwid[1]);
+ else
+ printk(", nwid off");
+
+ /* If 2.00 card */
+ if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
+ (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
+ unsigned short freq;
+
+ /* Ask the EEPROM to read the frequency from the first area. */
+ fee_read(ioaddr, 0x00, &freq, 1);
+
+ /* Print frequency */
+ printk(", 2.00, %ld", (freq >> 6) + 2400L);
+
+ /* Hack! */
+ if (freq & 0x20)
+ printk(".5");
+ } else {
+ printk(", PC");
+ switch (psa.psa_comp_number) {
+ case PSA_COMP_PC_AT_915:
+ case PSA_COMP_PC_AT_2400:
+ printk("-AT");
+ break;
+ case PSA_COMP_PC_MC_915:
+ case PSA_COMP_PC_MC_2400:
+ printk("-MC");
+ break;
+ case PSA_COMP_PCMCIA_915:
+ printk("MCIA");
+ break;
+ default:
+ printk("?");
+ }
+ printk(", ");
+ switch (psa.psa_subband) {
+ case PSA_SUBBAND_915:
+ printk("915");
+ break;
+ case PSA_SUBBAND_2425:
+ printk("2425");
+ break;
+ case PSA_SUBBAND_2460:
+ printk("2460");
+ break;
+ case PSA_SUBBAND_2484:
+ printk("2484");
+ break;
+ case PSA_SUBBAND_2430_5:
+ printk("2430.5");
+ break;
+ default:
+ printk("?");
+ }
}
- printk(", ");
- switch (psa.psa_subband)
- {
- case PSA_SUBBAND_915:
- printk("915");
- break;
- case PSA_SUBBAND_2425:
- printk("2425");
- break;
- case PSA_SUBBAND_2460:
- printk("2460");
- break;
- case PSA_SUBBAND_2484:
- printk("2484");
- break;
- case PSA_SUBBAND_2430_5:
- printk("2430.5");
- break;
- default:
- printk("?");
- }
- }
- printk(" MHz\n");
-#endif /* DEBUG_BASIC_SHOW */
+ printk(" MHz\n");
+#endif /* DEBUG_BASIC_SHOW */
#ifdef DEBUG_VERSION_SHOW
- /* Print version information */
- printk(KERN_NOTICE "%s", version);
+ /* Print version information */
+ printk(KERN_NOTICE "%s", version);
#endif
-} /* wv_init_info */
+} /* wv_init_info */
/********************* IOCTL, STATS & RECONFIG *********************/
/*
@@ -1468,14 +1408,13 @@ wv_init_info(device * dev)
* card open or closed.
* Used when the user read /proc/net/dev
*/
-static en_stats *
-wavelan_get_stats(device * dev)
+static en_stats *wavelan_get_stats(device * dev)
{
#ifdef DEBUG_IOCTL_TRACE
- printk(KERN_DEBUG "%s: <>wavelan_get_stats()\n", dev->name);
+ printk(KERN_DEBUG "%s: <>wavelan_get_stats()\n", dev->name);
#endif
- return(&((net_local *) dev->priv)->stats);
+ return (&((net_local *) dev->priv)->stats);
}
/*------------------------------------------------------------------*/
@@ -1486,76 +1425,70 @@ wavelan_get_stats(device * dev)
* num_addrs > 0 Multicast mode, receive normal and MC packets,
* and do best-effort filtering.
*/
-static void
-wavelan_set_multicast_list(device * dev)
+static void wavelan_set_multicast_list(device * dev)
{
- net_local * lp = (net_local *) dev->priv;
+ net_local *lp = (net_local *) dev->priv;
#ifdef DEBUG_IOCTL_TRACE
- printk(KERN_DEBUG "%s: ->wavelan_set_multicast_list()\n", dev->name);
+ printk(KERN_DEBUG "%s: ->wavelan_set_multicast_list()\n",
+ dev->name);
#endif
#ifdef DEBUG_IOCTL_INFO
- printk(KERN_DEBUG "%s: wavelan_set_multicast_list(): setting Rx mode %02X to %d addresses.\n",
- dev->name, dev->flags, dev->mc_count);
+ printk(KERN_DEBUG
+ "%s: wavelan_set_multicast_list(): setting Rx mode %02X to %d addresses.\n",
+ dev->name, dev->flags, dev->mc_count);
#endif
- /* Are we asking for promiscuous mode,
- * or all multicast addresses (we don't have that!)
- * or too many multicast addresses for the hardware filter? */
- if((dev->flags & IFF_PROMISC) ||
- (dev->flags & IFF_ALLMULTI) ||
- (dev->mc_count > I82586_MAX_MULTICAST_ADDRESSES))
- {
- /*
- * Enable promiscuous mode: receive all packets.
- */
- if(!lp->promiscuous)
- {
- lp->promiscuous = 1;
- lp->mc_count = 0;
-
- wv_82586_reconfig(dev);
-
- /* Tell the kernel that we are doing a really bad job. */
- dev->flags |= IFF_PROMISC;
- }
- }
- else
- /* Are there multicast addresses to send? */
- if(dev->mc_list != (struct dev_mc_list *) NULL)
- {
- /*
- * Disable promiscuous mode, but receive all packets
- * in multicast list
- */
+ /* Are we asking for promiscuous mode,
+ * or all multicast addresses (we don't have that!)
+ * or too many multicast addresses for the hardware filter? */
+ if ((dev->flags & IFF_PROMISC) ||
+ (dev->flags & IFF_ALLMULTI) ||
+ (dev->mc_count > I82586_MAX_MULTICAST_ADDRESSES)) {
+ /*
+ * Enable promiscuous mode: receive all packets.
+ */
+ if (!lp->promiscuous) {
+ lp->promiscuous = 1;
+ lp->mc_count = 0;
+
+ wv_82586_reconfig(dev);
+
+ /* Tell the kernel that we are doing a really bad job. */
+ dev->flags |= IFF_PROMISC;
+ }
+ } else
+ /* Are there multicast addresses to send? */
+ if (dev->mc_list != (struct dev_mc_list *) NULL) {
+ /*
+ * Disable promiscuous mode, but receive all packets
+ * in multicast list
+ */
#ifdef MULTICAST_AVOID
- if(lp->promiscuous ||
- (dev->mc_count != lp->mc_count))
+ if (lp->promiscuous || (dev->mc_count != lp->mc_count))
#endif
- {
- lp->promiscuous = 0;
- lp->mc_count = dev->mc_count;
-
- wv_82586_reconfig(dev);
- }
- }
- else
- {
- /*
- * Switch to normal mode: disable promiscuous mode and
- * clear the multicast list.
- */
- if(lp->promiscuous || lp->mc_count == 0)
- {
- lp->promiscuous = 0;
- lp->mc_count = 0;
-
- wv_82586_reconfig(dev);
- }
- }
+ {
+ lp->promiscuous = 0;
+ lp->mc_count = dev->mc_count;
+
+ wv_82586_reconfig(dev);
+ }
+ } else {
+ /*
+ * Switch to normal mode: disable promiscuous mode and
+ * clear the multicast list.
+ */
+ if (lp->promiscuous || lp->mc_count == 0) {
+ lp->promiscuous = 0;
+ lp->mc_count = 0;
+
+ wv_82586_reconfig(dev);
+ }
+ }
#ifdef DEBUG_IOCTL_TRACE
- printk(KERN_DEBUG "%s: <-wavelan_set_multicast_list()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wavelan_set_multicast_list()\n",
+ dev->name);
#endif
}
@@ -1565,23 +1498,21 @@ wavelan_set_multicast_list(device * dev)
* (Note : it was a nice way to test the reconfigure stuff...)
*/
#ifdef SET_MAC_ADDRESS
-static int
-wavelan_set_mac_address(device * dev,
- void * addr)
+static int wavelan_set_mac_address(device * dev, void *addr)
{
- struct sockaddr * mac = addr;
+ struct sockaddr *mac = addr;
- /* Copy the address. */
- memcpy(dev->dev_addr, mac->sa_data, WAVELAN_ADDR_SIZE);
+ /* Copy the address. */
+ memcpy(dev->dev_addr, mac->sa_data, WAVELAN_ADDR_SIZE);
- /* Reconfigure the beast. */
- wv_82586_reconfig(dev);
+ /* Reconfigure the beast. */
+ wv_82586_reconfig(dev);
- return 0;
+ return 0;
}
-#endif /* SET_MAC_ADDRESS */
+#endif /* SET_MAC_ADDRESS */
-#ifdef WIRELESS_EXT /* if wireless extensions exist in the kernel */
+#ifdef WIRELESS_EXT /* if wireless extensions exist in the kernel */
/*------------------------------------------------------------------*/
/*
@@ -1589,232 +1520,215 @@ wavelan_set_mac_address(device * dev,
* It's a bit complicated and you don't really want to look into it.
* (called in wavelan_ioctl)
*/
-static inline int
-wv_set_frequency(u_long ioaddr, /* I/O port of the card */
- iw_freq * frequency)
+static inline int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card */
+ iw_freq * frequency)
{
- const int BAND_NUM = 10; /* Number of bands */
- long freq = 0L; /* offset to 2.4 GHz in .5 MHz */
+ const int BAND_NUM = 10; /* Number of bands */
+ long freq = 0L; /* offset to 2.4 GHz in .5 MHz */
#ifdef DEBUG_IOCTL_INFO
- int i;
+ int i;
#endif
- /* Setting by frequency */
- /* Theoretically, you may set any frequency between
- * the two limits with a 0.5 MHz precision. In practice,
- * I don't want you to have trouble with local regulations.
- */
- if((frequency->e == 1) &&
- (frequency->m >= (int) 2.412e8) && (frequency->m <= (int) 2.487e8))
- {
- freq = ((frequency->m / 10000) - 24000L) / 5;
- }
-
- /* Setting by channel (same as wfreqsel) */
- /* Warning: each channel is 22 MHz wide, so some of the channels
- * will interfere. */
- if((frequency->e == 0) &&
- (frequency->m >= 0) && (frequency->m < BAND_NUM))
- {
- /* Get frequency offset. */
- freq = channel_bands[frequency->m] >> 1;
- }
-
- /* Verify that the frequency is allowed. */
- if(freq != 0L)
- {
- u_short table[10]; /* Authorized frequency table */
-
- /* Read the frequency table. */
- fee_read(ioaddr, 0x71, table, 10);
+ /* Setting by frequency */
+ /* Theoretically, you may set any frequency between
+ * the two limits with a 0.5 MHz precision. In practice,
+ * I don't want you to have trouble with local regulations.
+ */
+ if ((frequency->e == 1) &&
+ (frequency->m >= (int) 2.412e8)
+ && (frequency->m <= (int) 2.487e8)) {
+ freq = ((frequency->m / 10000) - 24000L) / 5;
+ }
-#ifdef DEBUG_IOCTL_INFO
- printk(KERN_DEBUG "Frequency table: ");
- for(i = 0; i < 10; i++)
- {
- printk(" %04X",
- table[i]);
+ /* Setting by channel (same as wfreqsel) */
+ /* Warning: each channel is 22 MHz wide, so some of the channels
+ * will interfere. */
+ if ((frequency->e == 0) &&
+ (frequency->m >= 0) && (frequency->m < BAND_NUM)) {
+ /* Get frequency offset. */
+ freq = channel_bands[frequency->m] >> 1;
}
- printk("\n");
-#endif
- /* Look in the table to see whether the frequency is allowed. */
- if(!(table[9 - ((freq - 24) / 16)] &
- (1 << ((freq - 24) % 16))))
- return -EINVAL; /* not allowed */
- }
- else
- return -EINVAL;
-
- /* if we get a usable frequency */
- if(freq != 0L)
- {
- unsigned short area[16];
- unsigned short dac[2];
- unsigned short area_verify[16];
- unsigned short dac_verify[2];
- /* Corresponding gain (in the power adjust value table)
- * See AT&T WaveLAN Data Manual, REF 407-024689/E, page 3-8
- * and WCIN062D.DOC, page 6.2.9. */
- unsigned short power_limit[] = { 40, 80, 120, 160, 0 };
- int power_band = 0; /* Selected band */
- unsigned short power_adjust; /* Correct value */
-
- /* Search for the gain. */
- power_band = 0;
- while((freq > power_limit[power_band]) &&
- (power_limit[++power_band] != 0))
- ;
-
- /* Read the first area. */
- fee_read(ioaddr, 0x00, area, 16);
-
- /* Read the DAC. */
- fee_read(ioaddr, 0x60, dac, 2);
-
- /* Read the new power adjust value. */
- fee_read(ioaddr, 0x6B - (power_band >> 1), &power_adjust, 1);
- if(power_band & 0x1)
- power_adjust >>= 8;
- else
- power_adjust &= 0xFF;
+ /* Verify that the frequency is allowed. */
+ if (freq != 0L) {
+ u16 table[10]; /* Authorized frequency table */
+
+ /* Read the frequency table. */
+ fee_read(ioaddr, 0x71, table, 10);
#ifdef DEBUG_IOCTL_INFO
- printk(KERN_DEBUG "WaveLAN EEPROM Area 1: ");
- for(i = 0; i < 16; i++)
- {
- printk(" %04X",
- area[i]);
- }
- printk("\n");
+ printk(KERN_DEBUG "Frequency table: ");
+ for (i = 0; i < 10; i++) {
+ printk(" %04X", table[i]);
+ }
+ printk("\n");
+#endif
- printk(KERN_DEBUG "WaveLAN EEPROM DAC: %04X %04X\n",
- dac[0], dac[1]);
+ /* Look in the table to see whether the frequency is allowed. */
+ if (!(table[9 - ((freq - 24) / 16)] &
+ (1 << ((freq - 24) % 16)))) return -EINVAL; /* not allowed */
+ } else
+ return -EINVAL;
+
+ /* if we get a usable frequency */
+ if (freq != 0L) {
+ unsigned short area[16];
+ unsigned short dac[2];
+ unsigned short area_verify[16];
+ unsigned short dac_verify[2];
+ /* Corresponding gain (in the power adjust value table)
+ * See AT&T WaveLAN Data Manual, REF 407-024689/E, page 3-8
+ * and WCIN062D.DOC, page 6.2.9. */
+ unsigned short power_limit[] = { 40, 80, 120, 160, 0 };
+ int power_band = 0; /* Selected band */
+ unsigned short power_adjust; /* Correct value */
+
+ /* Search for the gain. */
+ power_band = 0;
+ while ((freq > power_limit[power_band]) &&
+ (power_limit[++power_band] != 0));
+
+ /* Read the first area. */
+ fee_read(ioaddr, 0x00, area, 16);
+
+ /* Read the DAC. */
+ fee_read(ioaddr, 0x60, dac, 2);
+
+ /* Read the new power adjust value. */
+ fee_read(ioaddr, 0x6B - (power_band >> 1), &power_adjust,
+ 1);
+ if (power_band & 0x1)
+ power_adjust >>= 8;
+ else
+ power_adjust &= 0xFF;
+
+#ifdef DEBUG_IOCTL_INFO
+ printk(KERN_DEBUG "WaveLAN EEPROM Area 1: ");
+ for (i = 0; i < 16; i++) {
+ printk(" %04X", area[i]);
+ }
+ printk("\n");
+
+ printk(KERN_DEBUG "WaveLAN EEPROM DAC: %04X %04X\n",
+ dac[0], dac[1]);
#endif
- /* Frequency offset (for info only) */
- area[0] = ((freq << 5) & 0xFFE0) | (area[0] & 0x1F);
+ /* Frequency offset (for info only) */
+ area[0] = ((freq << 5) & 0xFFE0) | (area[0] & 0x1F);
- /* Receiver Principle main divider coefficient */
- area[3] = (freq >> 1) + 2400L - 352L;
- area[2] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF);
+ /* Receiver Principle main divider coefficient */
+ area[3] = (freq >> 1) + 2400L - 352L;
+ area[2] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF);
- /* Transmitter Main divider coefficient */
- area[13] = (freq >> 1) + 2400L;
- area[12] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF);
+ /* Transmitter Main divider coefficient */
+ area[13] = (freq >> 1) + 2400L;
+ area[12] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF);
- /* Other parts of the area are flags, bit streams or unused. */
+ /* Other parts of the area are flags, bit streams or unused. */
- /* Set the value in the DAC. */
- dac[1] = ((power_adjust >> 1) & 0x7F) | (dac[1] & 0xFF80);
- dac[0] = ((power_adjust & 0x1) << 4) | (dac[0] & 0xFFEF);
+ /* Set the value in the DAC. */
+ dac[1] = ((power_adjust >> 1) & 0x7F) | (dac[1] & 0xFF80);
+ dac[0] = ((power_adjust & 0x1) << 4) | (dac[0] & 0xFFEF);
- /* Write the first area. */
- fee_write(ioaddr, 0x00,
- area, 16);
+ /* Write the first area. */
+ fee_write(ioaddr, 0x00, area, 16);
- /* Write the DAC. */
- fee_write(ioaddr, 0x60,
- dac, 2);
+ /* Write the DAC. */
+ fee_write(ioaddr, 0x60, dac, 2);
- /* We now should verify here that the writing of the EEPROM went OK. */
+ /* We now should verify here that the writing of the EEPROM went OK. */
- /* Reread the first area. */
- fee_read(ioaddr, 0x00, area_verify, 16);
+ /* Reread the first area. */
+ fee_read(ioaddr, 0x00, area_verify, 16);
- /* Reread the DAC. */
- fee_read(ioaddr, 0x60, dac_verify, 2);
+ /* Reread the DAC. */
+ fee_read(ioaddr, 0x60, dac_verify, 2);
- /* Compare. */
- if(memcmp(area, area_verify, 16 * 2) ||
- memcmp(dac, dac_verify, 2 * 2))
- {
+ /* Compare. */
+ if (memcmp(area, area_verify, 16 * 2) ||
+ memcmp(dac, dac_verify, 2 * 2)) {
#ifdef DEBUG_IOCTL_ERROR
- printk(KERN_INFO "WaveLAN: wv_set_frequency: unable to write new frequency to EEPROM(?).\n");
+ printk(KERN_INFO
+ "WaveLAN: wv_set_frequency: unable to write new frequency to EEPROM(?).\n");
#endif
- return -EOPNOTSUPP;
- }
+ return -EOPNOTSUPP;
+ }
- /* We must download the frequency parameters to the
- * synthesizers (from the EEPROM - area 1)
- * Note: as the EEPROM is automatically decremented, we set the end
- * if the area... */
- mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x0F);
- mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl),
- MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD);
+ /* We must download the frequency parameters to the
+ * synthesizers (from the EEPROM - area 1)
+ * Note: as the EEPROM is automatically decremented, we set the end
+ * if the area... */
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x0F);
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl),
+ MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD);
- /* Wait until the download is finished. */
- fee_wait(ioaddr, 100, 100);
+ /* Wait until the download is finished. */
+ fee_wait(ioaddr, 100, 100);
- /* We must now download the power adjust value (gain) to
- * the synthesizers (from the EEPROM - area 7 - DAC). */
- mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x61);
- mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl),
- MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD);
+ /* We must now download the power adjust value (gain) to
+ * the synthesizers (from the EEPROM - area 7 - DAC). */
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x61);
+ mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl),
+ MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD);
- /* Wait for the download to finish. */
- fee_wait(ioaddr, 100, 100);
+ /* Wait for the download to finish. */
+ fee_wait(ioaddr, 100, 100);
#ifdef DEBUG_IOCTL_INFO
- /* Verification of what we have done */
+ /* Verification of what we have done */
- printk(KERN_DEBUG "WaveLAN EEPROM Area 1: ");
- for(i = 0; i < 16; i++)
- {
- printk(" %04X",
- area_verify[i]);
- }
- printk("\n");
+ printk(KERN_DEBUG "WaveLAN EEPROM Area 1: ");
+ for (i = 0; i < 16; i++) {
+ printk(" %04X", area_verify[i]);
+ }
+ printk("\n");
- printk(KERN_DEBUG "WaveLAN EEPROM DAC: %04X %04X\n",
- dac_verify[0], dac_verify[1]);
+ printk(KERN_DEBUG "WaveLAN EEPROM DAC: %04X %04X\n",
+ dac_verify[0], dac_verify[1]);
#endif
- return 0;
- }
- else
- return -EINVAL; /* Bah, never get there... */
+ return 0;
+ } else
+ return -EINVAL; /* Bah, never get there... */
}
/*------------------------------------------------------------------*/
/*
* Give the list of available frequencies.
*/
-static inline int
-wv_frequency_list(u_long ioaddr, /* I/O port of the card */
- iw_freq * list, /* List of frequencies to fill */
- int max) /* Maximum number of frequencies */
-{
- u_short table[10]; /* Authorized frequency table */
- long freq = 0L; /* offset to 2.4 GHz in .5 MHz + 12 MHz */
- int i; /* index in the table */
- int c = 0; /* Channel number */
-
- /* Read the frequency table. */
- fee_read(ioaddr, 0x71 /* frequency table */, table, 10);
-
- /* Check all frequencies. */
- i = 0;
- for(freq = 0; freq < 150; freq++)
- /* Look in the table if the frequency is allowed */
- if(table[9 - (freq / 16)] & (1 << (freq % 16)))
- {
- /* Compute approximate channel number */
- while((((channel_bands[c] >> 1) - 24) < freq) &&
- (c < NELS(channel_bands)))
- c++;
- list[i].i = c; /* Set the list index */
-
- /* put in the list */
- list[i].m = (((freq + 24) * 5) + 24000L) * 10000;
- list[i++].e = 1;
-
- /* Check number. */
- if(i >= max)
- return(i);
- }
-
- return(i);
+static inline int wv_frequency_list(unsigned long ioaddr, /* I/O port of the card */
+ iw_freq * list, /* List of frequencies to fill */
+ int max)
+{ /* Maximum number of frequencies */
+ u16 table[10]; /* Authorized frequency table */
+ long freq = 0L; /* offset to 2.4 GHz in .5 MHz + 12 MHz */
+ int i; /* index in the table */
+ int c = 0; /* Channel number */
+
+ /* Read the frequency table. */
+ fee_read(ioaddr, 0x71 /* frequency table */ , table, 10);
+
+ /* Check all frequencies. */
+ i = 0;
+ for (freq = 0; freq < 150; freq++)
+ /* Look in the table if the frequency is allowed */
+ if (table[9 - (freq / 16)] & (1 << (freq % 16))) {
+ /* Compute approximate channel number */
+ while ((((channel_bands[c] >> 1) - 24) < freq) &&
+ (c < NELS(channel_bands)))
+ c++;
+ list[i].i = c; /* Set the list index */
+
+ /* put in the list */
+ list[i].m = (((freq + 24) * 5) + 24000L) * 10000;
+ list[i++].e = 1;
+
+ /* Check number. */
+ if (i >= max)
+ return (i);
+ }
+
+ return (i);
}
#ifdef WIRELESS_SPY
@@ -1824,27 +1738,24 @@ wv_frequency_list(u_long ioaddr, /* I/O port of the card */
* address with our list, and if they match, get the statistics.
* Sorry, but this function really needs the wireless extensions.
*/
-static inline void
-wl_spy_gather(device * dev,
- u_char * mac, /* MAC address */
- u_char * stats) /* Statistics to gather */
-{
- net_local * lp = (net_local *) dev->priv;
- int i;
-
- /* Check all addresses. */
- for(i = 0; i < lp->spy_number; i++)
- /* If match */
- if(!memcmp(mac, lp->spy_address[i], WAVELAN_ADDR_SIZE))
- {
- /* Update statistics */
- lp->spy_stat[i].qual = stats[2] & MMR_SGNL_QUAL;
- lp->spy_stat[i].level = stats[0] & MMR_SIGNAL_LVL;
- lp->spy_stat[i].noise = stats[1] & MMR_SILENCE_LVL;
- lp->spy_stat[i].updated = 0x7;
- }
+static inline void wl_spy_gather(device * dev, u8 * mac, /* MAC address */
+ u8 * stats)
+{ /* Statistics to gather */
+ net_local *lp = (net_local *) dev->priv;
+ int i;
+
+ /* Check all addresses. */
+ for (i = 0; i < lp->spy_number; i++)
+ /* If match */
+ if (!memcmp(mac, lp->spy_address[i], WAVELAN_ADDR_SIZE)) {
+ /* Update statistics */
+ lp->spy_stat[i].qual = stats[2] & MMR_SGNL_QUAL;
+ lp->spy_stat[i].level = stats[0] & MMR_SIGNAL_LVL;
+ lp->spy_stat[i].noise = stats[1] & MMR_SILENCE_LVL;
+ lp->spy_stat[i].updated = 0x7;
+ }
}
-#endif /* WIRELESS_SPY */
+#endif /* WIRELESS_SPY */
#ifdef HISTOGRAM
/*------------------------------------------------------------------*/
@@ -1856,494 +1767,516 @@ wl_spy_gather(device * dev,
* With this histogram you may detect if one WaveLAN is really weak,
* or you may also calculate the mean and standard deviation of the level.
*/
-static inline void
-wl_his_gather(device * dev,
- u_char * stats) /* Statistics to gather */
-{
- net_local * lp = (net_local *) dev->priv;
- u_char level = stats[0] & MMR_SIGNAL_LVL;
- int i;
-
- /* Find the correct interval. */
- i = 0;
- while((i < (lp->his_number - 1)) && (level >= lp->his_range[i++]))
- ;
-
- /* Increment interval counter. */
- (lp->his_sum[i])++;
+static inline void wl_his_gather(device * dev, u8 * stats)
+{ /* Statistics to gather */
+ net_local *lp = (net_local *) dev->priv;
+ u8 level = stats[0] & MMR_SIGNAL_LVL;
+ int i;
+
+ /* Find the correct interval. */
+ i = 0;
+ while ((i < (lp->his_number - 1))
+ && (level >= lp->his_range[i++]));
+
+ /* Increment interval counter. */
+ (lp->his_sum[i])++;
}
-#endif /* HISTOGRAM */
+#endif /* HISTOGRAM */
/*------------------------------------------------------------------*/
/*
* Perform ioctl for configuration and information.
* It is here that the wireless extensions are treated (iwconfig).
*/
-static int
-wavelan_ioctl(struct net_device * dev, /* device on which the ioctl is applied */
- struct ifreq * rq, /* data passed */
- int cmd) /* ioctl number */
-{
- u_long ioaddr = dev->base_addr;
- net_local * lp = (net_local *)dev->priv; /* lp is not unused */
- struct iwreq * wrq = (struct iwreq *) rq;
- psa_t psa;
- mm_t m;
- unsigned long x;
- int ret = 0;
+static int wavelan_ioctl(struct net_device *dev, /* device on which the ioctl is applied */
+ struct ifreq *rq, /* data passed */
+ int cmd)
+{ /* ioctl number */
+ unsigned long ioaddr = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ struct iwreq *wrq = (struct iwreq *) rq;
+ psa_t psa;
+ mm_t m;
+ unsigned long flags;
+ int ret = 0;
#ifdef DEBUG_IOCTL_TRACE
- printk(KERN_DEBUG "%s: ->wavelan_ioctl(cmd=0x%X)\n", dev->name, cmd);
+ printk(KERN_DEBUG "%s: ->wavelan_ioctl(cmd=0x%X)\n", dev->name,
+ cmd);
#endif
- /* Disable interrupts and save flags. */
- x = wv_splhi();
-
- /* Look what is the request */
- switch(cmd)
- {
- /* --------------- WIRELESS EXTENSIONS --------------- */
-
- case SIOCGIWNAME:
- strcpy(wrq->u.name, "WaveLAN");
- break;
-
- case SIOCSIWNWID:
- /* Set NWID in WaveLAN. */
- if(!wrq->u.nwid.disabled)
- {
- /* Set NWID in psa */
- psa.psa_nwid[0] = (wrq->u.nwid.value & 0xFF00) >> 8;
- psa.psa_nwid[1] = wrq->u.nwid.value & 0xFF;
- psa.psa_nwid_select = 0x01;
- psa_write(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa,
- (unsigned char *)psa.psa_nwid, 3);
-
- /* Set NWID in mmc. */
- m.w.mmw_netw_id_l = psa.psa_nwid[1];
- m.w.mmw_netw_id_h = psa.psa_nwid[0];
- mmc_write(ioaddr, (char *)&m.w.mmw_netw_id_l - (char *)&m,
- (unsigned char *)&m.w.mmw_netw_id_l, 2);
- mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), 0x00);
- }
- else
- {
- /* Disable NWID in the psa. */
- psa.psa_nwid_select = 0x00;
- psa_write(ioaddr, lp->hacr,
- (char *)&psa.psa_nwid_select - (char *)&psa,
- (unsigned char *)&psa.psa_nwid_select, 1);
-
- /* Disable NWID in the mmc (no filtering). */
- mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), MMW_LOOPT_SEL_DIS_NWID);
- }
- /* update the Wavelan checksum */
- update_psa_checksum(dev, ioaddr, lp->hacr);
- break;
-
- case SIOCGIWNWID:
- /* Read the NWID. */
- psa_read(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa,
- (unsigned char *)psa.psa_nwid, 3);
- wrq->u.nwid.value = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
- wrq->u.nwid.disabled = !(psa.psa_nwid_select);
- wrq->u.nwid.fixed = 1; /* Superfluous */
- break;
-
- case SIOCSIWFREQ:
- /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
- if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
- (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
- ret = wv_set_frequency(ioaddr, &(wrq->u.freq));
- else
- ret = -EOPNOTSUPP;
- break;
-
- case SIOCGIWFREQ:
- /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable).
- * Does it work for everybody, especially old cards? */
- if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
- (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
- {
- unsigned short freq;
-
- /* Ask the EEPROM to read the frequency from the first area. */
- fee_read(ioaddr, 0x00, &freq, 1);
- wrq->u.freq.m = ((freq >> 5) * 5 + 24000L) * 10000;
- wrq->u.freq.e = 1;
- }
- else
- {
- psa_read(ioaddr, lp->hacr, (char *)&psa.psa_subband - (char *)&psa,
- (unsigned char *)&psa.psa_subband, 1);
-
- if(psa.psa_subband <= 4)
- {
- wrq->u.freq.m = fixed_bands[psa.psa_subband];
- wrq->u.freq.e = (psa.psa_subband != 0);
- }
- else
- ret = -EOPNOTSUPP;
- }
- break;
-
- case SIOCSIWSENS:
- /* Set the level threshold. */
- /* We should complain loudly if wrq->u.sens.fixed = 0, because we
- * can't set auto mode... */
- psa.psa_thr_pre_set = wrq->u.sens.value & 0x3F;
- psa_write(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa,
- (unsigned char *) &psa.psa_thr_pre_set, 1);
- /* update the Wavelan checksum */
- update_psa_checksum(dev, ioaddr, lp->hacr);
- mmc_out(ioaddr, mmwoff(0, mmw_thr_pre_set), psa.psa_thr_pre_set);
- break;
-
- case SIOCGIWSENS:
- /* Read the level threshold. */
- psa_read(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa,
- (unsigned char *) &psa.psa_thr_pre_set, 1);
- wrq->u.sens.value = psa.psa_thr_pre_set & 0x3F;
- wrq->u.sens.fixed = 1;
- break;
-
- case SIOCSIWENCODE:
- /* Set encryption key */
- if(!mmc_encr(ioaddr))
- {
- ret = -EOPNOTSUPP;
- break;
- }
-
- /* Basic checking... */
- if(wrq->u.encoding.pointer != (caddr_t) 0)
- {
- /* Check the size of the key */
- if(wrq->u.encoding.length != 8)
- {
- ret = -EINVAL;
- break;
- }
-
- /* Copy the key in the driver */
- if(copy_from_user(psa.psa_encryption_key, wrq->u.encoding.pointer,
- wrq->u.encoding.length))
- {
- ret = -EFAULT;
- break;
- }
-
- psa.psa_encryption_select = 1;
- psa_write(ioaddr, lp->hacr,
- (char *) &psa.psa_encryption_select - (char *) &psa,
- (unsigned char *) &psa.psa_encryption_select, 8+1);
-
- mmc_out(ioaddr, mmwoff(0, mmw_encr_enable),
- MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE);
- mmc_write(ioaddr, mmwoff(0, mmw_encr_key),
- (unsigned char *) &psa.psa_encryption_key, 8);
- }
-
- if(wrq->u.encoding.flags & IW_ENCODE_DISABLED)
- { /* disable encryption */
- psa.psa_encryption_select = 0;
- psa_write(ioaddr, lp->hacr,
- (char *) &psa.psa_encryption_select - (char *) &psa,
- (unsigned char *) &psa.psa_encryption_select, 1);
-
- mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), 0);
- }
- /* update the Wavelan checksum */
- update_psa_checksum(dev, ioaddr, lp->hacr);
- break;
-
- case SIOCGIWENCODE:
- /* Read the encryption key */
- if(!mmc_encr(ioaddr))
- {
- ret = -EOPNOTSUPP;
- break;
- }
-
- /* only super-user can see encryption key */
- if(!suser())
- {
- ret = -EPERM;
- break;
- }
-
- /* Basic checking... */
- if(wrq->u.encoding.pointer != (caddr_t) 0)
- {
- /* Verify the user buffer */
- ret = verify_area(VERIFY_WRITE, wrq->u.encoding.pointer, 8);
- if(ret)
- break;
-
- psa_read(ioaddr, lp->hacr,
- (char *) &psa.psa_encryption_select - (char *) &psa,
- (unsigned char *) &psa.psa_encryption_select, 1+8);
-
- /* encryption is enabled ? */
- if(psa.psa_encryption_select)
- wrq->u.encoding.flags = IW_ENCODE_ENABLED;
- else
- wrq->u.encoding.flags = IW_ENCODE_DISABLED;
- wrq->u.encoding.flags |= mmc_encr(ioaddr);
-
- /* Copy the key to the user buffer */
- wrq->u.encoding.length = 8;
- if(copy_to_user(wrq->u.encoding.pointer, psa.psa_encryption_key, 8))
- ret = -EFAULT;
- }
- break;
-
- case SIOCGIWRANGE:
- /* basic checking */
- if(wrq->u.data.pointer != (caddr_t) 0)
- {
- struct iw_range range;
-
- /* Set the length (useless: it's constant). */
- wrq->u.data.length = sizeof(struct iw_range);
-
- /* Set information in the range struct. */
- range.throughput = 1.6 * 1000 * 1000; /* don't argue on this ! */
- range.min_nwid = 0x0000;
- range.max_nwid = 0xFFFF;
-
- /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
- if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
- (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
- {
- range.num_channels = 10;
- range.num_frequency = wv_frequency_list(ioaddr, range.freq,
+ /* Disable interrupts and save flags. */
+ save_flags(flags);
+ cli();
+ /* FIXME: can't copy*user when cli this is broken! */
+
+ /* Look what is the request */
+ switch (cmd) {
+ /* --------------- WIRELESS EXTENSIONS --------------- */
+
+ case SIOCGIWNAME:
+ strcpy(wrq->u.name, "WaveLAN");
+ break;
+
+ case SIOCSIWNWID:
+ /* Set NWID in WaveLAN. */
+ if (!wrq->u.nwid.disabled) {
+ /* Set NWID in psa */
+ psa.psa_nwid[0] =
+ (wrq->u.nwid.value & 0xFF00) >> 8;
+ psa.psa_nwid[1] = wrq->u.nwid.value & 0xFF;
+ psa.psa_nwid_select = 0x01;
+ psa_write(ioaddr, lp->hacr,
+ (char *) psa.psa_nwid - (char *) &psa,
+ (unsigned char *) psa.psa_nwid, 3);
+
+ /* Set NWID in mmc. */
+ m.w.mmw_netw_id_l = psa.psa_nwid[1];
+ m.w.mmw_netw_id_h = psa.psa_nwid[0];
+ mmc_write(ioaddr,
+ (char *) &m.w.mmw_netw_id_l -
+ (char *) &m,
+ (unsigned char *) &m.w.mmw_netw_id_l, 2);
+ mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), 0x00);
+ } else {
+ /* Disable NWID in the psa. */
+ psa.psa_nwid_select = 0x00;
+ psa_write(ioaddr, lp->hacr,
+ (char *) &psa.psa_nwid_select -
+ (char *) &psa,
+ (unsigned char *) &psa.psa_nwid_select,
+ 1);
+
+ /* Disable NWID in the mmc (no filtering). */
+ mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel),
+ MMW_LOOPT_SEL_DIS_NWID);
+ }
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev, ioaddr, lp->hacr);
+ break;
+
+ case SIOCGIWNWID:
+ /* Read the NWID. */
+ psa_read(ioaddr, lp->hacr,
+ (char *) psa.psa_nwid - (char *) &psa,
+ (unsigned char *) psa.psa_nwid, 3);
+ wrq->u.nwid.value =
+ (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
+ wrq->u.nwid.disabled = !(psa.psa_nwid_select);
+ wrq->u.nwid.fixed = 1; /* Superfluous */
+ break;
+
+ case SIOCSIWFREQ:
+ /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
+ if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
+ (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
+ ret = wv_set_frequency(ioaddr, &(wrq->u.freq));
+ else
+ ret = -EOPNOTSUPP;
+ break;
+
+ case SIOCGIWFREQ:
+ /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable).
+ * Does it work for everybody, especially old cards? */
+ if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
+ (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
+ unsigned short freq;
+
+ /* Ask the EEPROM to read the frequency from the first area. */
+ fee_read(ioaddr, 0x00, &freq, 1);
+ wrq->u.freq.m = ((freq >> 5) * 5 + 24000L) * 10000;
+ wrq->u.freq.e = 1;
+ } else {
+ psa_read(ioaddr, lp->hacr,
+ (char *) &psa.psa_subband - (char *) &psa,
+ (unsigned char *) &psa.psa_subband, 1);
+
+ if (psa.psa_subband <= 4) {
+ wrq->u.freq.m =
+ fixed_bands[psa.psa_subband];
+ wrq->u.freq.e = (psa.psa_subband != 0);
+ } else
+ ret = -EOPNOTSUPP;
+ }
+ break;
+
+ case SIOCSIWSENS:
+ /* Set the level threshold. */
+ /* We should complain loudly if wrq->u.sens.fixed = 0, because we
+ * can't set auto mode... */
+ psa.psa_thr_pre_set = wrq->u.sens.value & 0x3F;
+ psa_write(ioaddr, lp->hacr,
+ (char *) &psa.psa_thr_pre_set - (char *) &psa,
+ (unsigned char *) &psa.psa_thr_pre_set, 1);
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev, ioaddr, lp->hacr);
+ mmc_out(ioaddr, mmwoff(0, mmw_thr_pre_set),
+ psa.psa_thr_pre_set);
+ break;
+
+ case SIOCGIWSENS:
+ /* Read the level threshold. */
+ psa_read(ioaddr, lp->hacr,
+ (char *) &psa.psa_thr_pre_set - (char *) &psa,
+ (unsigned char *) &psa.psa_thr_pre_set, 1);
+ wrq->u.sens.value = psa.psa_thr_pre_set & 0x3F;
+ wrq->u.sens.fixed = 1;
+ break;
+
+ case SIOCSIWENCODE:
+ /* Set encryption key */
+ if (!mmc_encr(ioaddr)) {
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ /* Basic checking... */
+ if (wrq->u.encoding.pointer != (caddr_t) 0) {
+ /* Check the size of the key */
+ if (wrq->u.encoding.length != 8) {
+ ret = -EINVAL;
+ break;
+ }
+
+ /* Copy the key in the driver */
+ if (copy_from_user
+ (psa.psa_encryption_key,
+ wrq->u.encoding.pointer,
+ wrq->u.encoding.length)) {
+ ret = -EFAULT;
+ break;
+ }
+
+ psa.psa_encryption_select = 1;
+ psa_write(ioaddr, lp->hacr,
+ (char *) &psa.psa_encryption_select -
+ (char *) &psa,
+ (unsigned char *) &psa.
+ psa_encryption_select, 8 + 1);
+
+ mmc_out(ioaddr, mmwoff(0, mmw_encr_enable),
+ MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE);
+ mmc_write(ioaddr, mmwoff(0, mmw_encr_key),
+ (unsigned char *) &psa.
+ psa_encryption_key, 8);
+ }
+
+ if (wrq->u.encoding.flags & IW_ENCODE_DISABLED) { /* disable encryption */
+ psa.psa_encryption_select = 0;
+ psa_write(ioaddr, lp->hacr,
+ (char *) &psa.psa_encryption_select -
+ (char *) &psa,
+ (unsigned char *) &psa.
+ psa_encryption_select, 1);
+
+ mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), 0);
+ }
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev, ioaddr, lp->hacr);
+ break;
+
+ case SIOCGIWENCODE:
+ /* Read the encryption key */
+ if (!mmc_encr(ioaddr)) {
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ /* only super-user can see encryption key */
+ if (!suser()) {
+ ret = -EPERM;
+ break;
+ }
+
+ /* Basic checking... */
+ if (wrq->u.encoding.pointer != (caddr_t) 0) {
+ /* Verify the user buffer */
+ ret =
+ verify_area(VERIFY_WRITE,
+ wrq->u.encoding.pointer, 8);
+ if (ret)
+ break;
+
+ psa_read(ioaddr, lp->hacr,
+ (char *) &psa.psa_encryption_select -
+ (char *) &psa,
+ (unsigned char *) &psa.
+ psa_encryption_select, 1 + 8);
+
+ /* encryption is enabled ? */
+ if (psa.psa_encryption_select)
+ wrq->u.encoding.flags = IW_ENCODE_ENABLED;
+ else
+ wrq->u.encoding.flags = IW_ENCODE_DISABLED;
+ wrq->u.encoding.flags |= mmc_encr(ioaddr);
+
+ /* Copy the key to the user buffer */
+ wrq->u.encoding.length = 8;
+ if (copy_to_user
+ (wrq->u.encoding.pointer,
+ psa.psa_encryption_key, 8)) ret = -EFAULT;
+ }
+ break;
+
+ case SIOCGIWRANGE:
+ /* basic checking */
+ if (wrq->u.data.pointer != (caddr_t) 0) {
+ struct iw_range range;
+
+ /* Set the length (useless: it's constant). */
+ wrq->u.data.length = sizeof(struct iw_range);
+
+ /* Set information in the range struct. */
+ range.throughput = 1.6 * 1000 * 1000; /* don't argue on this ! */
+ range.min_nwid = 0x0000;
+ range.max_nwid = 0xFFFF;
+
+ /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
+ if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
+ (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
+ range.num_channels = 10;
+ range.num_frequency =
+ wv_frequency_list(ioaddr, range.freq,
IW_MAX_FREQUENCIES);
- }
- else
- range.num_channels = range.num_frequency = 0;
-
- range.sensitivity = 0x3F;
- range.max_qual.qual = MMR_SGNL_QUAL;
- range.max_qual.level = MMR_SIGNAL_LVL;
- range.max_qual.noise = MMR_SILENCE_LVL;
-
- range.num_bitrates = 1;
- range.bitrate[0] = 2000000; /* 2 Mb/s */
-
- /* Encryption supported ? */
- if(mmc_encr(ioaddr))
- {
- range.encoding_size[0] = 8; /* DES = 64 bits key */
- range.num_encoding_sizes = 1;
- range.max_encoding_tokens = 1; /* Only one key possible */
- }
- else
- {
- range.num_encoding_sizes = 0;
- range.max_encoding_tokens = 0;
- }
-
- /* Copy structure to the user buffer. */
- if (copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range)))
- ret = -EFAULT;
- }
- break;
-
- case SIOCGIWPRIV:
- /* Basic checking */
- if(wrq->u.data.pointer != (caddr_t) 0)
- {
- struct iw_priv_args priv[] =
- { /* cmd, set_args, get_args, name */
- { SIOCSIPQTHR, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "setqualthr" },
- { SIOCGIPQTHR, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getqualthr" },
-
- { SIOCSIPHISTO, IW_PRIV_TYPE_BYTE | 16, 0, "sethisto" },
- { SIOCGIPHISTO, 0, IW_PRIV_TYPE_INT | 16, "gethisto" },
- };
-
- /* Set the number of available ioctls. */
- wrq->u.data.length = 4;
-
- /* Copy structure to the user buffer. */
- if (copy_to_user(wrq->u.data.pointer, (u_char *) priv, sizeof(priv)))
- ret = -EFAULT;
- }
- break;
+ } else
+ range.num_channels = range.num_frequency =
+ 0;
+
+ range.sensitivity = 0x3F;
+ range.max_qual.qual = MMR_SGNL_QUAL;
+ range.max_qual.level = MMR_SIGNAL_LVL;
+ range.max_qual.noise = MMR_SILENCE_LVL;
+
+ range.num_bitrates = 1;
+ range.bitrate[0] = 2000000; /* 2 Mb/s */
+
+ /* Encryption supported ? */
+ if (mmc_encr(ioaddr)) {
+ range.encoding_size[0] = 8; /* DES = 64 bits key */
+ range.num_encoding_sizes = 1;
+ range.max_encoding_tokens = 1; /* Only one key possible */
+ } else {
+ range.num_encoding_sizes = 0;
+ range.max_encoding_tokens = 0;
+ }
+
+ /* Copy structure to the user buffer. */
+ if (copy_to_user
+ (wrq->u.data.pointer, &range,
+ sizeof(struct iw_range))) ret = -EFAULT;
+ }
+ break;
+
+ case SIOCGIWPRIV:
+ /* Basic checking */
+ if (wrq->u.data.pointer != (caddr_t) 0) {
+ struct iw_priv_args priv[] = { /* cmd, set_args, get_args, name */
+
+ {SIOCSIPQTHR,
+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED |
+ 1, 0, "setqualthr"},
+ {SIOCGIPQTHR, 0,
+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED |
+ 1, "getqualthr"},
+
+
+ {SIOCSIPHISTO, IW_PRIV_TYPE_BYTE | 16,
+ 0, "sethisto"},
+ {SIOCGIPHISTO, 0, IW_PRIV_TYPE_INT | 16,
+ "gethisto"},
+ };
+
+ /* Set the number of available ioctls. */
+ wrq->u.data.length = 4;
+
+ /* Copy structure to the user buffer. */
+ if (copy_to_user
+ (wrq->u.data.pointer, (u8 *) priv,
+ sizeof(priv))) ret = -EFAULT;
+ }
+ break;
#ifdef WIRELESS_SPY
- case SIOCSIWSPY:
- /* Set the spy list */
-
- /* Check the number of addresses. */
- if(wrq->u.data.length > IW_MAX_SPY)
- {
- ret = -E2BIG;
- break;
- }
- lp->spy_number = wrq->u.data.length;
-
- /* Are there are addresses to copy? */
- if(lp->spy_number > 0)
- {
- struct sockaddr address[IW_MAX_SPY];
- int i;
-
- /* Copy addresses to the driver. */
- if (copy_from_user(address, wrq->u.data.pointer, sizeof(struct sockaddr) * lp->spy_number)) {
- ret = -EFAULT;
- break;
- }
-
- /* Copy addresses to the lp structure. */
- for(i = 0; i < lp->spy_number; i++)
- {
- memcpy(lp->spy_address[i], address[i].sa_data,
- WAVELAN_ADDR_SIZE);
- }
-
- /* Reset structure. */
- memset(lp->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY);
+ case SIOCSIWSPY:
+ /* Set the spy list */
+
+ /* Check the number of addresses. */
+ if (wrq->u.data.length > IW_MAX_SPY) {
+ ret = -E2BIG;
+ break;
+ }
+ lp->spy_number = wrq->u.data.length;
+
+ /* Are there are addresses to copy? */
+ if (lp->spy_number > 0) {
+ struct sockaddr address[IW_MAX_SPY];
+ int i;
+
+ /* Copy addresses to the driver. */
+ if (copy_from_user
+ (address, wrq->u.data.pointer,
+ sizeof(struct sockaddr) * lp->spy_number)) {
+ ret = -EFAULT;
+ break;
+ }
+
+ /* Copy addresses to the lp structure. */
+ for (i = 0; i < lp->spy_number; i++) {
+ memcpy(lp->spy_address[i],
+ address[i].sa_data,
+ WAVELAN_ADDR_SIZE);
+ }
+
+ /* Reset structure. */
+ memset(lp->spy_stat, 0x00,
+ sizeof(iw_qual) * IW_MAX_SPY);
#ifdef DEBUG_IOCTL_INFO
- printk(KERN_DEBUG "SetSpy: set of new addresses is: \n");
- for(i = 0; i < wrq->u.data.length; i++)
- printk(KERN_DEBUG "%02X:%02X:%02X:%02X:%02X:%02X \n",
- lp->spy_address[i][0],
- lp->spy_address[i][1],
- lp->spy_address[i][2],
- lp->spy_address[i][3],
- lp->spy_address[i][4],
- lp->spy_address[i][5]);
-#endif /* DEBUG_IOCTL_INFO */
- }
-
- break;
-
- case SIOCGIWSPY:
- /* Get the spy list and spy stats. */
-
- /* Set the number of addresses */
- wrq->u.data.length = lp->spy_number;
-
- /* Does the user want to have the addresses back? */
- if((lp->spy_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))
- {
- struct sockaddr address[IW_MAX_SPY];
- int i;
-
- /* Copy addresses from the lp structure. */
- for(i = 0; i < lp->spy_number; i++)
- {
- memcpy(address[i].sa_data, lp->spy_address[i],
- WAVELAN_ADDR_SIZE);
- address[i].sa_family = AF_UNIX;
- }
-
- /* Copy addresses to the user buffer. */
- if (copy_to_user(wrq->u.data.pointer, address, sizeof(struct sockaddr) * lp->spy_number)) {
- ret = -EFAULT;
- break;
- }
-
- /* Copy stats to the user buffer (just after). */
- if (copy_to_user(wrq->u.data.pointer +
- (sizeof(struct sockaddr) * lp->spy_number),
- lp->spy_stat, sizeof(iw_qual) * lp->spy_number)) {
- ret = -EFAULT;
- break;
- }
-
- /* Reset updated flags. */
- for(i = 0; i < lp->spy_number; i++)
- lp->spy_stat[i].updated = 0x0;
- } /* if(pointer != NULL) */
-
- break;
-#endif /* WIRELESS_SPY */
-
- /* ------------------ PRIVATE IOCTL ------------------ */
-
- case SIOCSIPQTHR:
- if(!suser())
- {
- ret = -EPERM;
- break;
- }
- psa.psa_quality_thr = *(wrq->u.name) & 0x0F;
- psa_write(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa,
- (unsigned char *)&psa.psa_quality_thr, 1);
- /* update the Wavelan checksum */
- update_psa_checksum(dev, ioaddr, lp->hacr);
- mmc_out(ioaddr, mmwoff(0, mmw_quality_thr), psa.psa_quality_thr);
- break;
-
- case SIOCGIPQTHR:
- psa_read(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa,
- (unsigned char *)&psa.psa_quality_thr, 1);
- *(wrq->u.name) = psa.psa_quality_thr & 0x0F;
- break;
+ printk(KERN_DEBUG
+ "SetSpy: set of new addresses is: \n");
+ for (i = 0; i < wrq->u.data.length; i++)
+ printk(KERN_DEBUG
+ "%02X:%02X:%02X:%02X:%02X:%02X \n",
+ lp->spy_address[i][0],
+ lp->spy_address[i][1],
+ lp->spy_address[i][2],
+ lp->spy_address[i][3],
+ lp->spy_address[i][4],
+ lp->spy_address[i][5]);
+#endif /* DEBUG_IOCTL_INFO */
+ }
+
+ break;
+
+ case SIOCGIWSPY:
+ /* Get the spy list and spy stats. */
+
+ /* Set the number of addresses */
+ wrq->u.data.length = lp->spy_number;
+
+ /* Does the user want to have the addresses back? */
+ if ((lp->spy_number > 0)
+ && (wrq->u.data.pointer != (caddr_t) 0)) {
+ struct sockaddr address[IW_MAX_SPY];
+ int i;
+
+ /* Copy addresses from the lp structure. */
+ for (i = 0; i < lp->spy_number; i++) {
+ memcpy(address[i].sa_data,
+ lp->spy_address[i],
+ WAVELAN_ADDR_SIZE);
+ address[i].sa_family = AF_UNIX;
+ }
+
+ /* Copy addresses to the user buffer. */
+ if (copy_to_user
+ (wrq->u.data.pointer, address,
+ sizeof(struct sockaddr) * lp->spy_number)) {
+ ret = -EFAULT;
+ break;
+ }
+
+ /* Copy stats to the user buffer (just after). */
+ if (copy_to_user(wrq->u.data.pointer +
+ (sizeof(struct sockaddr) *
+ lp->spy_number), lp->spy_stat,
+ sizeof(iw_qual) * lp->spy_number)) {
+ ret = -EFAULT;
+ break;
+ }
+
+ /* Reset updated flags. */
+ for (i = 0; i < lp->spy_number; i++)
+ lp->spy_stat[i].updated = 0x0;
+ }
+ /* if(pointer != NULL) */
+ break;
+#endif /* WIRELESS_SPY */
+
+ /* ------------------ PRIVATE IOCTL ------------------ */
+
+ case SIOCSIPQTHR:
+ if (!suser()) {
+ ret = -EPERM;
+ break;
+ }
+ psa.psa_quality_thr = *(wrq->u.name) & 0x0F;
+ psa_write(ioaddr, lp->hacr,
+ (char *) &psa.psa_quality_thr - (char *) &psa,
+ (unsigned char *) &psa.psa_quality_thr, 1);
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev, ioaddr, lp->hacr);
+ mmc_out(ioaddr, mmwoff(0, mmw_quality_thr),
+ psa.psa_quality_thr);
+ break;
+
+ case SIOCGIPQTHR:
+ psa_read(ioaddr, lp->hacr,
+ (char *) &psa.psa_quality_thr - (char *) &psa,
+ (unsigned char *) &psa.psa_quality_thr, 1);
+ *(wrq->u.name) = psa.psa_quality_thr & 0x0F;
+ break;
#ifdef HISTOGRAM
- case SIOCSIPHISTO:
- /* Verify that the user is root. */
- if(!suser())
- {
- ret = -EPERM;
- break;
- }
-
- /* Check the number of intervals. */
- if(wrq->u.data.length > 16)
- {
- ret = -E2BIG;
- break;
- }
- lp->his_number = wrq->u.data.length;
+ case SIOCSIPHISTO:
+ /* Verify that the user is root. */
+ if (!suser()) {
+ ret = -EPERM;
+ break;
+ }
+
+ /* Check the number of intervals. */
+ if (wrq->u.data.length > 16) {
+ ret = -E2BIG;
+ break;
+ }
+ lp->his_number = wrq->u.data.length;
+
+ /* Are there addresses to copy? */
+ if (lp->his_number > 0) {
+ /* Copy interval ranges to the driver */
+ if (copy_from_user
+ (lp->his_range, wrq->u.data.pointer,
+ sizeof(char) * lp->his_number)) {
+ ret = -EFAULT;
+ break;
+ }
+
+ /* Reset structure. */
+ memset(lp->his_sum, 0x00, sizeof(long) * 16);
+ }
+ break;
+
+ case SIOCGIPHISTO:
+ /* Set the number of intervals. */
+ wrq->u.data.length = lp->his_number;
+
+ /* Give back the distribution statistics */
+ if ((lp->his_number > 0)
+ && (wrq->u.data.pointer != (caddr_t) 0)) {
+ /* Copy data to the user buffer. */
+ if (copy_to_user
+ (wrq->u.data.pointer, lp->his_sum,
+ sizeof(long) * lp->his_number))
+ ret = -EFAULT;
+
+ } /* if(pointer != NULL) */
+ break;
+#endif /* HISTOGRAM */
+
+ /* ------------------- OTHER IOCTL ------------------- */
- /* Are there addresses to copy? */
- if(lp->his_number > 0)
- {
- /* Copy interval ranges to the driver */
- if (copy_from_user(lp->his_range, wrq->u.data.pointer, sizeof(char) * lp->his_number)) {
- ret = -EFAULT;
- break;
- }
-
- /* Reset structure. */
- memset(lp->his_sum, 0x00, sizeof(long) * 16);
+ default:
+ ret = -EOPNOTSUPP;
}
- break;
-
- case SIOCGIPHISTO:
- /* Set the number of intervals. */
- wrq->u.data.length = lp->his_number;
-
- /* Give back the distribution statistics */
- if((lp->his_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))
- {
- /* Copy data to the user buffer. */
- if (copy_to_user(wrq->u.data.pointer, lp->his_sum, sizeof(long) * lp->his_number))
- ret = -EFAULT;
-
- } /* if(pointer != NULL) */
- break;
-#endif /* HISTOGRAM */
- /* ------------------- OTHER IOCTL ------------------- */
-
- default:
- ret = -EOPNOTSUPP;
- }
-
- /* Enable interrupts and restore flags. */
- wv_splx(x);
+ /* Enable interrupts and restore flags. */
+ restore_flags(flags);
#ifdef DEBUG_IOCTL_TRACE
- printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name);
#endif
- return ret;
+ return ret;
}
/*------------------------------------------------------------------*/
@@ -2351,56 +2284,64 @@ wavelan_ioctl(struct net_device * dev, /* device on which the ioctl is applied *
* Get wireless statistics.
* Called by /proc/net/wireless
*/
-static iw_stats *
-wavelan_get_wireless_stats(device * dev)
+static iw_stats *wavelan_get_wireless_stats(device * dev)
{
- u_long ioaddr = dev->base_addr;
- net_local * lp = (net_local *) dev->priv;
- mmr_t m;
- iw_stats * wstats;
- unsigned long x;
+ unsigned long ioaddr = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv;
+ mmr_t m;
+ iw_stats *wstats;
+ unsigned long flags;
#ifdef DEBUG_IOCTL_TRACE
- printk(KERN_DEBUG "%s: ->wavelan_get_wireless_stats()\n", dev->name);
+ printk(KERN_DEBUG "%s: ->wavelan_get_wireless_stats()\n",
+ dev->name);
#endif
- /* Disable interrupts and save flags. */
- x = wv_splhi();
-
- if(lp == (net_local *) NULL)
- return (iw_stats *) NULL;
- wstats = &lp->wstats;
-
- /* Get data from the mmc. */
- mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1);
-
- mmc_read(ioaddr, mmroff(0, mmr_dce_status), &m.mmr_dce_status, 1);
- mmc_read(ioaddr, mmroff(0, mmr_wrong_nwid_l), &m.mmr_wrong_nwid_l, 2);
- mmc_read(ioaddr, mmroff(0, mmr_thr_pre_set), &m.mmr_thr_pre_set, 4);
-
- mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
-
- /* Copy data to wireless stuff. */
- wstats->status = m.mmr_dce_status & MMR_DCE_STATUS;
- wstats->qual.qual = m.mmr_sgnl_qual & MMR_SGNL_QUAL;
- wstats->qual.level = m.mmr_signal_lvl & MMR_SIGNAL_LVL;
- wstats->qual.noise = m.mmr_silence_lvl & MMR_SILENCE_LVL;
- wstats->qual.updated = (((m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 7) |
- ((m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 6) |
- ((m.mmr_silence_lvl & MMR_SILENCE_LVL_VALID) >> 5));
- wstats->discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
- wstats->discard.code = 0L;
- wstats->discard.misc = 0L;
-
- /* Enable interrupts and restore flags. */
- wv_splx(x);
+ /* Disable interrupts and save flags. */
+ save_flags(flags);
+ cli();
+
+ if (lp == (net_local *) NULL)
+ {
+ restore_flags(flags);
+ return (iw_stats *) NULL;
+ }
+
+ wstats = &lp->wstats;
+
+ /* Get data from the mmc. */
+ mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1);
+
+ mmc_read(ioaddr, mmroff(0, mmr_dce_status), &m.mmr_dce_status, 1);
+ mmc_read(ioaddr, mmroff(0, mmr_wrong_nwid_l), &m.mmr_wrong_nwid_l,
+ 2);
+ mmc_read(ioaddr, mmroff(0, mmr_thr_pre_set), &m.mmr_thr_pre_set,
+ 4);
+
+ mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
+
+ /* Copy data to wireless stuff. */
+ wstats->status = m.mmr_dce_status & MMR_DCE_STATUS;
+ wstats->qual.qual = m.mmr_sgnl_qual & MMR_SGNL_QUAL;
+ wstats->qual.level = m.mmr_signal_lvl & MMR_SIGNAL_LVL;
+ wstats->qual.noise = m.mmr_silence_lvl & MMR_SILENCE_LVL;
+ wstats->qual.updated = (((m. mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 7)
+ | ((m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 6)
+ | ((m.mmr_silence_lvl & MMR_SILENCE_LVL_VALID) >> 5));
+ wstats->discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l;
+ wstats->discard.code = 0L;
+ wstats->discard.misc = 0L;
+
+ /* Enable interrupts and restore flags. */
+ restore_flags(flags);
#ifdef DEBUG_IOCTL_TRACE
- printk(KERN_DEBUG "%s: <-wavelan_get_wireless_stats()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wavelan_get_wireless_stats()\n",
+ dev->name);
#endif
- return &lp->wstats;
+ return &lp->wstats;
}
-#endif /* WIRELESS_EXT */
+#endif /* WIRELESS_EXT */
/************************* PACKET RECEPTION *************************/
/*
@@ -2423,90 +2364,90 @@ wavelan_get_wireless_stats(device * dev)
* (called by wv_packet_rcv())
*/
static inline void
-wv_packet_read(device * dev,
- u_short buf_off,
- int sksize)
+wv_packet_read(device * dev, u16 buf_off, int sksize)
{
- net_local * lp = (net_local *) dev->priv;
- u_long ioaddr = dev->base_addr;
- struct sk_buff * skb;
+ net_local *lp = (net_local *) dev->priv;
+ unsigned long ioaddr = dev->base_addr;
+ struct sk_buff *skb;
#ifdef DEBUG_RX_TRACE
- printk(KERN_DEBUG "%s: ->wv_packet_read(0x%X, %d)\n",
- dev->name, buf_off, sksize);
+ printk(KERN_DEBUG "%s: ->wv_packet_read(0x%X, %d)\n",
+ dev->name, buf_off, sksize);
#endif
- /* Allocate buffer for the data */
- if((skb = dev_alloc_skb(sksize)) == (struct sk_buff *) NULL)
- {
+ /* Allocate buffer for the data */
+ if ((skb = dev_alloc_skb(sksize)) == (struct sk_buff *) NULL) {
#ifdef DEBUG_RX_ERROR
- printk(KERN_INFO "%s: wv_packet_read(): could not alloc_skb(%d, GFP_ATOMIC).\n",
- dev->name, sksize);
+ printk(KERN_INFO
+ "%s: wv_packet_read(): could not alloc_skb(%d, GFP_ATOMIC).\n",
+ dev->name, sksize);
#endif
- lp->stats.rx_dropped++;
- return;
- }
+ lp->stats.rx_dropped++;
+ return;
+ }
- skb->dev = dev;
+ skb->dev = dev;
- /* Copy the packet to the buffer. */
- obram_read(ioaddr, buf_off, skb_put(skb, sksize), sksize);
- skb->protocol=eth_type_trans(skb, dev);
+ /* Copy the packet to the buffer. */
+ obram_read(ioaddr, buf_off, skb_put(skb, sksize), sksize);
+ skb->protocol = eth_type_trans(skb, dev);
#ifdef DEBUG_RX_INFO
- wv_packet_info(skb->mac.raw, sksize, dev->name, "wv_packet_read");
-#endif /* DEBUG_RX_INFO */
+ wv_packet_info(skb->mac.raw, sksize, dev->name, "wv_packet_read");
+#endif /* DEBUG_RX_INFO */
- /* Statistics-gathering and associated stuff.
- * It seem a bit messy with all the define, but it's really simple... */
+ /* Statistics-gathering and associated stuff.
+ * It seem a bit messy with all the define, but it's really simple... */
#if defined(WIRELESS_SPY) || defined(HISTOGRAM)
- if(
+ if (
#ifdef WIRELESS_SPY
- (lp->spy_number > 0) ||
-#endif /* WIRELESS_SPY */
+ (lp->spy_number > 0) ||
+#endif /* WIRELESS_SPY */
#ifdef HISTOGRAM
- (lp->his_number > 0) ||
-#endif /* HISTOGRAM */
- 0)
- {
- u_char stats[3]; /* signal level, noise level, signal quality */
-
- /* Read signal level, silence level and signal quality bytes. */
- /* Note: in the PCMCIA hardware, these are part of the frame. It seems
- * that for the ISA hardware, it's nowhere to be found in the frame,
- * so I'm obliged to do this (it has a side effect on /proc/net/wireless).
- * Any ideas?
- */
- mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1);
- mmc_read(ioaddr, mmroff(0, mmr_signal_lvl), stats, 3);
- mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
+ (lp->his_number > 0) ||
+#endif /* HISTOGRAM */
+ 0) {
+ u8 stats[3]; /* signal level, noise level, signal quality */
+
+ /* Read signal level, silence level and signal quality bytes. */
+ /* Note: in the PCMCIA hardware, these are part of the frame. It seems
+ * that for the ISA hardware, it's nowhere to be found in the frame,
+ * so I'm obliged to do this (it has a side effect on /proc/net/wireless).
+ * Any ideas?
+ */
+ mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1);
+ mmc_read(ioaddr, mmroff(0, mmr_signal_lvl), stats, 3);
+ mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0);
#ifdef DEBUG_RX_INFO
- printk(KERN_DEBUG "%s: wv_packet_read(): Signal level %d/63, Silence level %d/63, signal quality %d/16\n",
- dev->name, stats[0] & 0x3F, stats[1] & 0x3F, stats[2] & 0x0F);
+ printk(KERN_DEBUG
+ "%s: wv_packet_read(): Signal level %d/63, Silence level %d/63, signal quality %d/16\n",
+ dev->name, stats[0] & 0x3F, stats[1] & 0x3F,
+ stats[2] & 0x0F);
#endif
- /* Spying stuff */
+ /* Spying stuff */
#ifdef WIRELESS_SPY
- wl_spy_gather(dev, skb->mac.raw + WAVELAN_ADDR_SIZE, stats);
-#endif /* WIRELESS_SPY */
+ wl_spy_gather(dev, skb->mac.raw + WAVELAN_ADDR_SIZE,
+ stats);
+#endif /* WIRELESS_SPY */
#ifdef HISTOGRAM
- wl_his_gather(dev, stats);
-#endif /* HISTOGRAM */
- }
-#endif /* defined(WIRELESS_SPY) || defined(HISTOGRAM) */
+ wl_his_gather(dev, stats);
+#endif /* HISTOGRAM */
+ }
+#endif /* defined(WIRELESS_SPY) || defined(HISTOGRAM) */
- /*
- * Hand the packet to the network module.
- */
- netif_rx(skb);
+ /*
+ * Hand the packet to the network module.
+ */
+ netif_rx(skb);
- /* Keep statistics up to date */
- lp->stats.rx_packets++;
- lp->stats.rx_bytes += skb->len;
+ /* Keep statistics up to date */
+ lp->stats.rx_packets++;
+ lp->stats.rx_bytes += skb->len;
#ifdef DEBUG_RX_TRACE
- printk(KERN_DEBUG "%s: <-wv_packet_read()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wv_packet_read()\n", dev->name);
#endif
}
@@ -2516,150 +2457,160 @@ wv_packet_read(device * dev,
* from the device RAM.
* Called by the interrupt handler.
*/
-static inline void
-wv_receive(device * dev)
+static inline void wv_receive(device * dev)
{
- u_long ioaddr = dev->base_addr;
- net_local * lp = (net_local *)dev->priv;
- fd_t fd;
- rbd_t rbd;
- int nreaped = 0;
+ unsigned long ioaddr = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv;
+ fd_t fd;
+ rbd_t rbd;
+ int nreaped = 0;
#ifdef DEBUG_RX_TRACE
- printk(KERN_DEBUG "%s: ->wv_receive()\n", dev->name);
+ printk(KERN_DEBUG "%s: ->wv_receive()\n", dev->name);
#endif
- /* Loop on each received packet. */
- for(;;)
- {
- obram_read(ioaddr, lp->rx_head, (unsigned char *) &fd, sizeof(fd));
-
- /* Note about the status :
- * It start up to be 0 (the value we set). Then, when the RU
- * grab the buffer to prepare for reception, it sets the
- * FD_STATUS_B flag. When the RU has finished receiving the
- * frame, it clears FD_STATUS_B, set FD_STATUS_C to indicate
- * completion and set the other flags to indicate the eventual
- * errors. FD_STATUS_OK indicates that the reception was OK.
- */
-
- /* If the current frame is not complete, we have reached the end. */
- if((fd.fd_status & FD_STATUS_C) != FD_STATUS_C)
- break; /* This is how we exit the loop. */
-
- nreaped++;
-
- /* Check whether frame was correctly received. */
- if((fd.fd_status & FD_STATUS_OK) == FD_STATUS_OK)
- {
- /* Does the frame contain a pointer to the data? Let's check. */
- if(fd.fd_rbd_offset != I82586NULL)
- {
- /* Read the receive buffer descriptor */
- obram_read(ioaddr, fd.fd_rbd_offset,
- (unsigned char *) &rbd, sizeof(rbd));
+ /* Loop on each received packet. */
+ for (;;) {
+ obram_read(ioaddr, lp->rx_head, (unsigned char *) &fd,
+ sizeof(fd));
+
+ /* Note about the status :
+ * It start up to be 0 (the value we set). Then, when the RU
+ * grab the buffer to prepare for reception, it sets the
+ * FD_STATUS_B flag. When the RU has finished receiving the
+ * frame, it clears FD_STATUS_B, set FD_STATUS_C to indicate
+ * completion and set the other flags to indicate the eventual
+ * errors. FD_STATUS_OK indicates that the reception was OK.
+ */
+
+ /* If the current frame is not complete, we have reached the end. */
+ if ((fd.fd_status & FD_STATUS_C) != FD_STATUS_C)
+ break; /* This is how we exit the loop. */
+
+ nreaped++;
+
+ /* Check whether frame was correctly received. */
+ if ((fd.fd_status & FD_STATUS_OK) == FD_STATUS_OK) {
+ /* Does the frame contain a pointer to the data? Let's check. */
+ if (fd.fd_rbd_offset != I82586NULL) {
+ /* Read the receive buffer descriptor */
+ obram_read(ioaddr, fd.fd_rbd_offset,
+ (unsigned char *) &rbd,
+ sizeof(rbd));
#ifdef DEBUG_RX_ERROR
- if((rbd.rbd_status & RBD_STATUS_EOF) != RBD_STATUS_EOF)
- printk(KERN_INFO "%s: wv_receive(): missing EOF flag.\n",
- dev->name);
-
- if((rbd.rbd_status & RBD_STATUS_F) != RBD_STATUS_F)
- printk(KERN_INFO "%s: wv_receive(): missing F flag.\n",
- dev->name);
-#endif /* DEBUG_RX_ERROR */
-
- /* Read the packet and transmit to Linux */
- wv_packet_read(dev, rbd.rbd_bufl,
- rbd.rbd_status & RBD_STATUS_ACNT);
- }
+ if ((rbd.rbd_status & RBD_STATUS_EOF) !=
+ RBD_STATUS_EOF) printk(KERN_INFO
+ "%s: wv_receive(): missing EOF flag.\n",
+ dev->name);
+
+ if ((rbd.rbd_status & RBD_STATUS_F) !=
+ RBD_STATUS_F) printk(KERN_INFO
+ "%s: wv_receive(): missing F flag.\n",
+ dev->name);
+#endif /* DEBUG_RX_ERROR */
+
+ /* Read the packet and transmit to Linux */
+ wv_packet_read(dev, rbd.rbd_bufl,
+ rbd.
+ rbd_status &
+ RBD_STATUS_ACNT);
+ }
#ifdef DEBUG_RX_ERROR
- else /* if frame has no data */
- printk(KERN_INFO "%s: wv_receive(): frame has no data.\n",
- dev->name);
+ else /* if frame has no data */
+ printk(KERN_INFO
+ "%s: wv_receive(): frame has no data.\n",
+ dev->name);
#endif
- }
- else /* If reception was no successful */
- {
- lp->stats.rx_errors++;
+ } else { /* If reception was no successful */
+
+ lp->stats.rx_errors++;
#ifdef DEBUG_RX_INFO
- printk(KERN_DEBUG "%s: wv_receive(): frame not received successfully (%X).\n",
- dev->name, fd.fd_status);
+ printk(KERN_DEBUG
+ "%s: wv_receive(): frame not received successfully (%X).\n",
+ dev->name, fd.fd_status);
#endif
#ifdef DEBUG_RX_ERROR
- if((fd.fd_status & FD_STATUS_S6) != 0)
- printk(KERN_INFO "%s: wv_receive(): no EOF flag.\n", dev->name);
+ if ((fd.fd_status & FD_STATUS_S6) != 0)
+ printk(KERN_INFO
+ "%s: wv_receive(): no EOF flag.\n",
+ dev->name);
#endif
- if((fd.fd_status & FD_STATUS_S7) != 0)
- {
- lp->stats.rx_length_errors++;
+ if ((fd.fd_status & FD_STATUS_S7) != 0) {
+ lp->stats.rx_length_errors++;
#ifdef DEBUG_RX_FAIL
- printk(KERN_DEBUG "%s: wv_receive(): frame too short.\n",
- dev->name);
+ printk(KERN_DEBUG
+ "%s: wv_receive(): frame too short.\n",
+ dev->name);
#endif
- }
+ }
- if((fd.fd_status & FD_STATUS_S8) != 0)
- {
- lp->stats.rx_over_errors++;
+ if ((fd.fd_status & FD_STATUS_S8) != 0) {
+ lp->stats.rx_over_errors++;
#ifdef DEBUG_RX_FAIL
- printk(KERN_DEBUG "%s: wv_receive(): rx DMA overrun.\n",
- dev->name);
+ printk(KERN_DEBUG
+ "%s: wv_receive(): rx DMA overrun.\n",
+ dev->name);
#endif
- }
+ }
- if((fd.fd_status & FD_STATUS_S9) != 0)
- {
- lp->stats.rx_fifo_errors++;
+ if ((fd.fd_status & FD_STATUS_S9) != 0) {
+ lp->stats.rx_fifo_errors++;
#ifdef DEBUG_RX_FAIL
- printk(KERN_DEBUG "%s: wv_receive(): ran out of resources.\n",
- dev->name);
+ printk(KERN_DEBUG
+ "%s: wv_receive(): ran out of resources.\n",
+ dev->name);
#endif
- }
+ }
- if((fd.fd_status & FD_STATUS_S10) != 0)
- {
- lp->stats.rx_frame_errors++;
+ if ((fd.fd_status & FD_STATUS_S10) != 0) {
+ lp->stats.rx_frame_errors++;
#ifdef DEBUG_RX_FAIL
- printk(KERN_DEBUG "%s: wv_receive(): alignment error.\n",
- dev->name);
+ printk(KERN_DEBUG
+ "%s: wv_receive(): alignment error.\n",
+ dev->name);
#endif
- }
+ }
- if((fd.fd_status & FD_STATUS_S11) != 0)
- {
- lp->stats.rx_crc_errors++;
+ if ((fd.fd_status & FD_STATUS_S11) != 0) {
+ lp->stats.rx_crc_errors++;
#ifdef DEBUG_RX_FAIL
- printk(KERN_DEBUG "%s: wv_receive(): CRC error.\n", dev->name);
+ printk(KERN_DEBUG
+ "%s: wv_receive(): CRC error.\n",
+ dev->name);
#endif
- }
- }
+ }
+ }
- fd.fd_status = 0;
- obram_write(ioaddr, fdoff(lp->rx_head, fd_status),
- (unsigned char *) &fd.fd_status, sizeof(fd.fd_status));
+ fd.fd_status = 0;
+ obram_write(ioaddr, fdoff(lp->rx_head, fd_status),
+ (unsigned char *) &fd.fd_status,
+ sizeof(fd.fd_status));
- fd.fd_command = FD_COMMAND_EL;
- obram_write(ioaddr, fdoff(lp->rx_head, fd_command),
- (unsigned char *) &fd.fd_command, sizeof(fd.fd_command));
+ fd.fd_command = FD_COMMAND_EL;
+ obram_write(ioaddr, fdoff(lp->rx_head, fd_command),
+ (unsigned char *) &fd.fd_command,
+ sizeof(fd.fd_command));
- fd.fd_command = 0;
- obram_write(ioaddr, fdoff(lp->rx_last, fd_command),
- (unsigned char *) &fd.fd_command, sizeof(fd.fd_command));
+ fd.fd_command = 0;
+ obram_write(ioaddr, fdoff(lp->rx_last, fd_command),
+ (unsigned char *) &fd.fd_command,
+ sizeof(fd.fd_command));
- lp->rx_last = lp->rx_head;
- lp->rx_head = fd.fd_link_offset;
- } /* for(;;) -> loop on all frames */
+ lp->rx_last = lp->rx_head;
+ lp->rx_head = fd.fd_link_offset;
+ } /* for(;;) -> loop on all frames */
#ifdef DEBUG_RX_INFO
- if(nreaped > 1)
- printk(KERN_DEBUG "%s: wv_receive(): reaped %d\n", dev->name, nreaped);
+ if (nreaped > 1)
+ printk(KERN_DEBUG "%s: wv_receive(): reaped %d\n",
+ dev->name, nreaped);
#endif
#ifdef DEBUG_RX_TRACE
- printk(KERN_DEBUG "%s: <-wv_receive()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wv_receive()\n", dev->name);
#endif
}
@@ -2689,130 +2640,124 @@ wv_receive(device * dev)
*
* (called in wavelan_packet_xmit())
*/
-static inline void
-wv_packet_write(device * dev,
- void * buf,
- short length)
+static inline void wv_packet_write(device * dev, void *buf, short length)
{
- net_local * lp = (net_local *) dev->priv;
- u_long ioaddr = dev->base_addr;
- unsigned short txblock;
- unsigned short txpred;
- unsigned short tx_addr;
- unsigned short nop_addr;
- unsigned short tbd_addr;
- unsigned short buf_addr;
- ac_tx_t tx;
- ac_nop_t nop;
- tbd_t tbd;
- int clen = length;
- unsigned long x;
+ net_local *lp = (net_local *) dev->priv;
+ unsigned long ioaddr = dev->base_addr;
+ unsigned short txblock;
+ unsigned short txpred;
+ unsigned short tx_addr;
+ unsigned short nop_addr;
+ unsigned short tbd_addr;
+ unsigned short buf_addr;
+ ac_tx_t tx;
+ ac_nop_t nop;
+ tbd_t tbd;
+ int clen = length;
+ unsigned long flags;
#ifdef DEBUG_TX_TRACE
- printk(KERN_DEBUG "%s: ->wv_packet_write(%d)\n", dev->name, length);
+ printk(KERN_DEBUG "%s: ->wv_packet_write(%d)\n", dev->name,
+ length);
#endif
- /* Do we need some padding? */
- if(clen < ETH_ZLEN)
- clen = ETH_ZLEN;
+ /* Do we need some padding? */
+ if (clen < ETH_ZLEN)
+ clen = ETH_ZLEN;
+
+ save_flags(flags);
+ cli();
+
+ /* Calculate addresses of next block and previous block. */
+ txblock = lp->tx_first_free;
+ txpred = txblock - TXBLOCKZ;
+ if (txpred < OFFSET_CU)
+ txpred += NTXBLOCKS * TXBLOCKZ;
+ lp->tx_first_free += TXBLOCKZ;
+ if (lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)
+ lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ;
+
+ lp->tx_n_in_use++;
+
+ /* Calculate addresses of the different parts of the block. */
+ tx_addr = txblock;
+ nop_addr = tx_addr + sizeof(tx);
+ tbd_addr = nop_addr + sizeof(nop);
+ buf_addr = tbd_addr + sizeof(tbd);
- x = wv_splhi();
+ /*
+ * Transmit command
+ */
+ tx.tx_h.ac_status = 0;
+ obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status),
+ (unsigned char *) &tx.tx_h.ac_status,
+ sizeof(tx.tx_h.ac_status));
- /* Calculate addresses of next block and previous block. */
- txblock = lp->tx_first_free;
- txpred = txblock - TXBLOCKZ;
- if(txpred < OFFSET_CU)
- txpred += NTXBLOCKS * TXBLOCKZ;
- lp->tx_first_free += TXBLOCKZ;
- if(lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)
- lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ;
+ /*
+ * NOP command
+ */
+ nop.nop_h.ac_status = 0;
+ obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
+ (unsigned char *) &nop.nop_h.ac_status,
+ sizeof(nop.nop_h.ac_status));
+ nop.nop_h.ac_link = nop_addr;
+ obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
+ (unsigned char *) &nop.nop_h.ac_link,
+ sizeof(nop.nop_h.ac_link));
-/*
-if (lp->tx_n_in_use > 0)
- printk("%c", "0123456789abcdefghijk"[lp->tx_n_in_use]);
-*/
+ /*
+ * Transmit buffer descriptor
+ */
+ tbd.tbd_status = TBD_STATUS_EOF | (TBD_STATUS_ACNT & clen);
+ tbd.tbd_next_bd_offset = I82586NULL;
+ tbd.tbd_bufl = buf_addr;
+ tbd.tbd_bufh = 0;
+ obram_write(ioaddr, tbd_addr, (unsigned char *) &tbd, sizeof(tbd));
+
+ /*
+ * Data
+ */
+ obram_write(ioaddr, buf_addr, buf, length);
+
+ /*
+ * Overwrite the predecessor NOP link
+ * so that it points to this txblock.
+ */
+ nop_addr = txpred + sizeof(tx);
+ nop.nop_h.ac_status = 0;
+ obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
+ (unsigned char *) &nop.nop_h.ac_status,
+ sizeof(nop.nop_h.ac_status));
+ nop.nop_h.ac_link = txblock;
+ obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
+ (unsigned char *) &nop.nop_h.ac_link,
+ sizeof(nop.nop_h.ac_link));
+
+ /* Keep stats up to date. */
+ lp->stats.tx_bytes += length;
+
+ /* If watchdog not already active, activate it... */
+ if (lp->watchdog.prev == (timer_list *) NULL) {
+ /* Set timer to expire in WATCHDOG_JIFFIES. */
+ lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
+ add_timer(&lp->watchdog);
+ }
- lp->tx_n_in_use++;
-
- /* Calculate addresses of the different parts of the block. */
- tx_addr = txblock;
- nop_addr = tx_addr + sizeof(tx);
- tbd_addr = nop_addr + sizeof(nop);
- buf_addr = tbd_addr + sizeof(tbd);
-
- /*
- * Transmit command
- */
- tx.tx_h.ac_status = 0;
- obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status),
- (unsigned char *) &tx.tx_h.ac_status,
- sizeof(tx.tx_h.ac_status));
-
- /*
- * NOP command
- */
- nop.nop_h.ac_status = 0;
- obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
- (unsigned char *) &nop.nop_h.ac_status,
- sizeof(nop.nop_h.ac_status));
- nop.nop_h.ac_link = nop_addr;
- obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
- (unsigned char *) &nop.nop_h.ac_link,
- sizeof(nop.nop_h.ac_link));
-
- /*
- * Transmit buffer descriptor
- */
- tbd.tbd_status = TBD_STATUS_EOF | (TBD_STATUS_ACNT & clen);
- tbd.tbd_next_bd_offset = I82586NULL;
- tbd.tbd_bufl = buf_addr;
- tbd.tbd_bufh = 0;
- obram_write(ioaddr, tbd_addr, (unsigned char *)&tbd, sizeof(tbd));
-
- /*
- * Data
- */
- obram_write(ioaddr, buf_addr, buf, length);
-
- /*
- * Overwrite the predecessor NOP link
- * so that it points to this txblock.
- */
- nop_addr = txpred + sizeof(tx);
- nop.nop_h.ac_status = 0;
- obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
- (unsigned char *)&nop.nop_h.ac_status,
- sizeof(nop.nop_h.ac_status));
- nop.nop_h.ac_link = txblock;
- obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
- (unsigned char *) &nop.nop_h.ac_link,
- sizeof(nop.nop_h.ac_link));
-
- /* Keep stats up to date. */
- lp->stats.tx_bytes += length;
-
- /* If watchdog not already active, activate it... */
- if(lp->watchdog.prev == (timer_list *) NULL)
- {
- /* Set timer to expire in WATCHDOG_JIFFIES. */
- lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
- add_timer(&lp->watchdog);
- }
-
- if(lp->tx_first_in_use == I82586NULL)
- lp->tx_first_in_use = txblock;
-
- if(lp->tx_n_in_use < NTXBLOCKS - 1)
- dev->tbusy = 0;
-
- wv_splx(x);
+ if (lp->tx_first_in_use == I82586NULL)
+ lp->tx_first_in_use = txblock;
+ if (lp->tx_n_in_use < NTXBLOCKS - 1)
+ netif_wake_queue(dev);
+
+ restore_flags(flags);
+
#ifdef DEBUG_TX_INFO
- wv_packet_info((u_char *) buf, length, dev->name, "wv_packet_write");
-#endif /* DEBUG_TX_INFO */
+ wv_packet_info((u8 *) buf, length, dev->name,
+ "wv_packet_write");
+#endif /* DEBUG_TX_INFO */
#ifdef DEBUG_TX_TRACE
- printk(KERN_DEBUG "%s: <-wv_packet_write()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wv_packet_write()\n", dev->name);
#endif
}
@@ -2823,59 +2768,41 @@ if (lp->tx_n_in_use > 0)
* the packet. We also prevent reentrance. Then we call the function
* to send the packet.
*/
-static int
-wavelan_packet_xmit(struct sk_buff * skb,
- device * dev)
+static int wavelan_packet_xmit(struct sk_buff *skb, device * dev)
{
- net_local * lp = (net_local *)dev->priv;
+ net_local *lp = (net_local *) dev->priv;
#ifdef DEBUG_TX_TRACE
- printk(KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name,
- (unsigned) skb);
+ printk(KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name,
+ (unsigned) skb);
#endif
- /* This flag indicate that the hardware can't perform a transmission.
- * Theoretically, NET3 checks it before sending a packet to the driver,
- * but in fact it never does that and pools continuously.
- * As the watchdog will abort overly long transmissions, we are quite safe.
- */
- if(dev->tbusy)
- return 1;
-
- /*
- * Block a timer-based transmit from overlapping.
- * In other words, prevent reentering this routine.
- */
- if(test_and_set_bit(0, (void *)&dev->tbusy) != 0)
-#ifdef DEBUG_TX_ERROR
- printk(KERN_INFO "%s: Transmitter access conflict.\n", dev->name);
-#endif
- else
- {
- /* If somebody has asked to reconfigure the controller,
- * we can do it now.
- */
- if(lp->reconfig_82586)
- {
- wv_82586_config(dev);
- if(dev->tbusy)
- return 1;
- }
+ /*
+ * Block a timer-based transmit from overlapping.
+ * In other words, prevent reentering this routine.
+ */
+ netif_stop_queue(dev);
+
+ /* If somebody has asked to reconfigure the controller,
+ * we can do it now.
+ */
+ if (lp->reconfig_82586) {
+ wv_82586_config(dev);
+ }
#ifdef DEBUG_TX_ERROR
- if(skb->next)
- printk(KERN_INFO "skb has next\n");
+ if (skb->next)
+ printk(KERN_INFO "skb has next\n");
#endif
- wv_packet_write(dev, skb->data, skb->len);
- }
+ wv_packet_write(dev, skb->data, skb->len);
- dev_kfree_skb(skb);
+ dev_kfree_skb(skb);
#ifdef DEBUG_TX_TRACE
- printk(KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name);
#endif
- return 0;
+ return 0;
}
/*********************** HARDWARE CONFIGURATION ***********************/
@@ -2888,166 +2815,170 @@ wavelan_packet_xmit(struct sk_buff * skb,
* Routine to initialize the Modem Management Controller.
* (called by wv_hw_reset())
*/
-static inline int
-wv_mmc_init(device * dev)
+static inline int wv_mmc_init(device * dev)
{
- u_long ioaddr = dev->base_addr;
- net_local * lp = (net_local *)dev->priv;
- psa_t psa;
- mmw_t m;
- int configured;
+ unsigned long ioaddr = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv;
+ psa_t psa;
+ mmw_t m;
+ int configured;
#ifdef DEBUG_CONFIG_TRACE
- printk(KERN_DEBUG "%s: ->wv_mmc_init()\n", dev->name);
+ printk(KERN_DEBUG "%s: ->wv_mmc_init()\n", dev->name);
#endif
- /* Read the parameter storage area. */
- psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa));
+ /* Read the parameter storage area. */
+ psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa));
#ifdef USE_PSA_CONFIG
- configured = psa.psa_conf_status & 1;
+ configured = psa.psa_conf_status & 1;
#else
- configured = 0;
+ configured = 0;
#endif
- /* Is the PSA is not configured */
- if(!configured)
- {
- /* User will be able to configure NWID later (with iwconfig). */
- psa.psa_nwid[0] = 0;
- psa.psa_nwid[1] = 0;
-
- /* no NWID checking since NWID is not set */
- psa.psa_nwid_select = 0;
-
- /* Disable encryption */
- psa.psa_encryption_select = 0;
-
- /* Set to standard values:
- * 0x04 for AT,
- * 0x01 for MCA,
- * 0x04 for PCMCIA and 2.00 card (AT&T 407-024689/E document)
- */
- if (psa.psa_comp_number & 1)
- psa.psa_thr_pre_set = 0x01;
- else
- psa.psa_thr_pre_set = 0x04;
- psa.psa_quality_thr = 0x03;
-
- /* It is configured */
- psa.psa_conf_status |= 1;
+ /* Is the PSA is not configured */
+ if (!configured) {
+ /* User will be able to configure NWID later (with iwconfig). */
+ psa.psa_nwid[0] = 0;
+ psa.psa_nwid[1] = 0;
+
+ /* no NWID checking since NWID is not set */
+ psa.psa_nwid_select = 0;
+
+ /* Disable encryption */
+ psa.psa_encryption_select = 0;
+
+ /* Set to standard values:
+ * 0x04 for AT,
+ * 0x01 for MCA,
+ * 0x04 for PCMCIA and 2.00 card (AT&T 407-024689/E document)
+ */
+ if (psa.psa_comp_number & 1)
+ psa.psa_thr_pre_set = 0x01;
+ else
+ psa.psa_thr_pre_set = 0x04;
+ psa.psa_quality_thr = 0x03;
+
+ /* It is configured */
+ psa.psa_conf_status |= 1;
#ifdef USE_PSA_CONFIG
- /* Write the psa. */
- psa_write(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa,
- (unsigned char *)psa.psa_nwid, 4);
- psa_write(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa,
- (unsigned char *)&psa.psa_thr_pre_set, 1);
- psa_write(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa,
- (unsigned char *)&psa.psa_quality_thr, 1);
- psa_write(ioaddr, lp->hacr, (char *)&psa.psa_conf_status - (char *)&psa,
- (unsigned char *)&psa.psa_conf_status, 1);
- /* update the Wavelan checksum */
- update_psa_checksum(dev, ioaddr, lp->hacr);
+ /* Write the psa. */
+ psa_write(ioaddr, lp->hacr,
+ (char *) psa.psa_nwid - (char *) &psa,
+ (unsigned char *) psa.psa_nwid, 4);
+ psa_write(ioaddr, lp->hacr,
+ (char *) &psa.psa_thr_pre_set - (char *) &psa,
+ (unsigned char *) &psa.psa_thr_pre_set, 1);
+ psa_write(ioaddr, lp->hacr,
+ (char *) &psa.psa_quality_thr - (char *) &psa,
+ (unsigned char *) &psa.psa_quality_thr, 1);
+ psa_write(ioaddr, lp->hacr,
+ (char *) &psa.psa_conf_status - (char *) &psa,
+ (unsigned char *) &psa.psa_conf_status, 1);
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev, ioaddr, lp->hacr);
#endif
- }
-
- /* Zero the mmc structure. */
- memset(&m, 0x00, sizeof(m));
-
- /* Copy PSA info to the mmc. */
- m.mmw_netw_id_l = psa.psa_nwid[1];
- m.mmw_netw_id_h = psa.psa_nwid[0];
-
- if(psa.psa_nwid_select & 1)
- m.mmw_loopt_sel = 0x00;
- else
- m.mmw_loopt_sel = MMW_LOOPT_SEL_DIS_NWID;
-
- memcpy(&m.mmw_encr_key, &psa.psa_encryption_key,
- sizeof(m.mmw_encr_key));
-
- if(psa.psa_encryption_select)
- m.mmw_encr_enable = MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE;
- else
- m.mmw_encr_enable = 0;
-
- m.mmw_thr_pre_set = psa.psa_thr_pre_set & 0x3F;
- m.mmw_quality_thr = psa.psa_quality_thr & 0x0F;
-
- /*
- * Set default modem control parameters.
- * See NCR document 407-0024326 Rev. A.
- */
- m.mmw_jabber_enable = 0x01;
- m.mmw_freeze = 0;
- m.mmw_anten_sel = MMW_ANTEN_SEL_ALG_EN;
- m.mmw_ifs = 0x20;
- m.mmw_mod_delay = 0x04;
- m.mmw_jam_time = 0x38;
-
- m.mmw_des_io_invert = 0;
- m.mmw_decay_prm = 0;
- m.mmw_decay_updat_prm = 0;
-
- /* Write all info to MMC. */
- mmc_write(ioaddr, 0, (u_char *)&m, sizeof(m));
-
- /* The following code starts the modem of the 2.00 frequency
- * selectable cards at power on. It's not strictly needed for the
- * following boots.
- * The original patch was by Joe Finney for the PCMCIA driver, but
- * I've cleaned it up a bit and added documentation.
- * Thanks to Loeke Brederveld from Lucent for the info.
- */
-
- /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable)
- * Does it work for everybody, especially old cards? */
- /* Note: WFREQSEL verifies that it is able to read a sensible
- * frequency from EEPROM (address 0x00) and that MMR_FEE_STATUS_ID
- * is 0xA (Xilinx version) or 0xB (Ariadne version).
- * My test is more crude but does work. */
- if(!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
- (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
- {
- /* We must download the frequency parameters to the
- * synthesizers (from the EEPROM - area 1)
- * Note: as the EEPROM is automatically decremented, we set the end
- * if the area... */
- m.mmw_fee_addr = 0x0F;
- m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD;
- mmc_write(ioaddr, (char *)&m.mmw_fee_ctrl - (char *)&m,
- (unsigned char *)&m.mmw_fee_ctrl, 2);
-
- /* Wait until the download is finished. */
- fee_wait(ioaddr, 100, 100);
+ }
+
+ /* Zero the mmc structure. */
+ memset(&m, 0x00, sizeof(m));
+
+ /* Copy PSA info to the mmc. */
+ m.mmw_netw_id_l = psa.psa_nwid[1];
+ m.mmw_netw_id_h = psa.psa_nwid[0];
+
+ if (psa.psa_nwid_select & 1)
+ m.mmw_loopt_sel = 0x00;
+ else
+ m.mmw_loopt_sel = MMW_LOOPT_SEL_DIS_NWID;
+
+ memcpy(&m.mmw_encr_key, &psa.psa_encryption_key,
+ sizeof(m.mmw_encr_key));
+
+ if (psa.psa_encryption_select)
+ m.mmw_encr_enable =
+ MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE;
+ else
+ m.mmw_encr_enable = 0;
+
+ m.mmw_thr_pre_set = psa.psa_thr_pre_set & 0x3F;
+ m.mmw_quality_thr = psa.psa_quality_thr & 0x0F;
+
+ /*
+ * Set default modem control parameters.
+ * See NCR document 407-0024326 Rev. A.
+ */
+ m.mmw_jabber_enable = 0x01;
+ m.mmw_freeze = 0;
+ m.mmw_anten_sel = MMW_ANTEN_SEL_ALG_EN;
+ m.mmw_ifs = 0x20;
+ m.mmw_mod_delay = 0x04;
+ m.mmw_jam_time = 0x38;
+
+ m.mmw_des_io_invert = 0;
+ m.mmw_decay_prm = 0;
+ m.mmw_decay_updat_prm = 0;
+
+ /* Write all info to MMC. */
+ mmc_write(ioaddr, 0, (u8 *) & m, sizeof(m));
+
+ /* The following code starts the modem of the 2.00 frequency
+ * selectable cards at power on. It's not strictly needed for the
+ * following boots.
+ * The original patch was by Joe Finney for the PCMCIA driver, but
+ * I've cleaned it up a bit and added documentation.
+ * Thanks to Loeke Brederveld from Lucent for the info.
+ */
+
+ /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable)
+ * Does it work for everybody, especially old cards? */
+ /* Note: WFREQSEL verifies that it is able to read a sensible
+ * frequency from EEPROM (address 0x00) and that MMR_FEE_STATUS_ID
+ * is 0xA (Xilinx version) or 0xB (Ariadne version).
+ * My test is more crude but does work. */
+ if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
+ (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
+ /* We must download the frequency parameters to the
+ * synthesizers (from the EEPROM - area 1)
+ * Note: as the EEPROM is automatically decremented, we set the end
+ * if the area... */
+ m.mmw_fee_addr = 0x0F;
+ m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD;
+ mmc_write(ioaddr, (char *) &m.mmw_fee_ctrl - (char *) &m,
+ (unsigned char *) &m.mmw_fee_ctrl, 2);
+
+ /* Wait until the download is finished. */
+ fee_wait(ioaddr, 100, 100);
#ifdef DEBUG_CONFIG_INFO
- /* The frequency was in the last word downloaded. */
- mmc_read(ioaddr, (char *)&m.mmw_fee_data_l - (char *)&m,
- (unsigned char *)&m.mmw_fee_data_l, 2);
-
- /* Print some info for the user. */
- printk(KERN_DEBUG "%s: WaveLAN 2.00 recognised (frequency select). Current frequency = %ld\n",
- dev->name,
- ((m.mmw_fee_data_h << 4) |
- (m.mmw_fee_data_l >> 4)) * 5 / 2 + 24000L);
+ /* The frequency was in the last word downloaded. */
+ mmc_read(ioaddr, (char *) &m.mmw_fee_data_l - (char *) &m,
+ (unsigned char *) &m.mmw_fee_data_l, 2);
+
+ /* Print some info for the user. */
+ printk(KERN_DEBUG
+ "%s: WaveLAN 2.00 recognised (frequency select). Current frequency = %ld\n",
+ dev->name,
+ ((m.
+ mmw_fee_data_h << 4) | (m.mmw_fee_data_l >> 4)) *
+ 5 / 2 + 24000L);
#endif
- /* We must now download the power adjust value (gain) to
- * the synthesizers (from the EEPROM - area 7 - DAC). */
- m.mmw_fee_addr = 0x61;
- m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD;
- mmc_write(ioaddr, (char *)&m.mmw_fee_ctrl - (char *)&m,
- (unsigned char *)&m.mmw_fee_ctrl, 2);
-
- /* Wait until the download is finished. */
- } /* if 2.00 card */
+ /* We must now download the power adjust value (gain) to
+ * the synthesizers (from the EEPROM - area 7 - DAC). */
+ m.mmw_fee_addr = 0x61;
+ m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD;
+ mmc_write(ioaddr, (char *) &m.mmw_fee_ctrl - (char *) &m,
+ (unsigned char *) &m.mmw_fee_ctrl, 2);
+ /* Wait until the download is finished. */
+ }
+ /* if 2.00 card */
#ifdef DEBUG_CONFIG_TRACE
- printk(KERN_DEBUG "%s: <-wv_mmc_init()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wv_mmc_init()\n", dev->name);
#endif
- return 0;
+ return 0;
}
/*------------------------------------------------------------------*/
@@ -3056,81 +2987,79 @@ wv_mmc_init(device * dev)
* Start the receive unit.
* (called by wv_hw_reset())
*/
-static inline int
-wv_ru_start(device * dev)
+static inline int wv_ru_start(device * dev)
{
- net_local * lp = (net_local *) dev->priv;
- u_long ioaddr = dev->base_addr;
- u_short scb_cs;
- fd_t fd;
- rbd_t rbd;
- u_short rx;
- u_short rx_next;
- int i;
+ net_local *lp = (net_local *) dev->priv;
+ unsigned long ioaddr = dev->base_addr;
+ u16 scb_cs;
+ fd_t fd;
+ rbd_t rbd;
+ u16 rx;
+ u16 rx_next;
+ int i;
#ifdef DEBUG_CONFIG_TRACE
- printk(KERN_DEBUG "%s: ->wv_ru_start()\n", dev->name);
+ printk(KERN_DEBUG "%s: ->wv_ru_start()\n", dev->name);
#endif
- obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), (unsigned char *)&scb_cs, sizeof(scb_cs));
- if((scb_cs & SCB_ST_RUS) == SCB_ST_RUS_RDY)
- return 0;
+ obram_read(ioaddr, scboff(OFFSET_SCB, scb_status),
+ (unsigned char *) &scb_cs, sizeof(scb_cs));
+ if ((scb_cs & SCB_ST_RUS) == SCB_ST_RUS_RDY)
+ return 0;
- lp->rx_head = OFFSET_RU;
+ lp->rx_head = OFFSET_RU;
- for(i = 0, rx = lp->rx_head; i < NRXBLOCKS; i++, rx = rx_next)
- {
- rx_next = (i == NRXBLOCKS - 1) ? lp->rx_head : rx + RXBLOCKZ;
+ for (i = 0, rx = lp->rx_head; i < NRXBLOCKS; i++, rx = rx_next) {
+ rx_next =
+ (i == NRXBLOCKS - 1) ? lp->rx_head : rx + RXBLOCKZ;
- fd.fd_status = 0;
- fd.fd_command = (i == NRXBLOCKS - 1) ? FD_COMMAND_EL : 0;
- fd.fd_link_offset = rx_next;
- fd.fd_rbd_offset = rx + sizeof(fd);
- obram_write(ioaddr, rx, (unsigned char *)&fd, sizeof(fd));
+ fd.fd_status = 0;
+ fd.fd_command = (i == NRXBLOCKS - 1) ? FD_COMMAND_EL : 0;
+ fd.fd_link_offset = rx_next;
+ fd.fd_rbd_offset = rx + sizeof(fd);
+ obram_write(ioaddr, rx, (unsigned char *) &fd, sizeof(fd));
- rbd.rbd_status = 0;
- rbd.rbd_next_rbd_offset = I82586NULL;
- rbd.rbd_bufl = rx + sizeof(fd) + sizeof(rbd);
- rbd.rbd_bufh = 0;
- rbd.rbd_el_size = RBD_EL | (RBD_SIZE & MAXDATAZ);
- obram_write(ioaddr, rx + sizeof(fd),
- (unsigned char *) &rbd, sizeof(rbd));
+ rbd.rbd_status = 0;
+ rbd.rbd_next_rbd_offset = I82586NULL;
+ rbd.rbd_bufl = rx + sizeof(fd) + sizeof(rbd);
+ rbd.rbd_bufh = 0;
+ rbd.rbd_el_size = RBD_EL | (RBD_SIZE & MAXDATAZ);
+ obram_write(ioaddr, rx + sizeof(fd),
+ (unsigned char *) &rbd, sizeof(rbd));
- lp->rx_last = rx;
- }
+ lp->rx_last = rx;
+ }
- obram_write(ioaddr, scboff(OFFSET_SCB, scb_rfa_offset),
- (unsigned char *) &lp->rx_head, sizeof(lp->rx_head));
+ obram_write(ioaddr, scboff(OFFSET_SCB, scb_rfa_offset),
+ (unsigned char *) &lp->rx_head, sizeof(lp->rx_head));
- scb_cs = SCB_CMD_RUC_GO;
- obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
- (unsigned char *) &scb_cs, sizeof(scb_cs));
+ scb_cs = SCB_CMD_RUC_GO;
+ obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
+ (unsigned char *) &scb_cs, sizeof(scb_cs));
- set_chan_attn(ioaddr, lp->hacr);
+ set_chan_attn(ioaddr, lp->hacr);
- for(i = 1000; i > 0; i--)
- {
- obram_read(ioaddr, scboff(OFFSET_SCB, scb_command),
- (unsigned char *) &scb_cs, sizeof(scb_cs));
- if (scb_cs == 0)
- break;
+ for (i = 1000; i > 0; i--) {
+ obram_read(ioaddr, scboff(OFFSET_SCB, scb_command),
+ (unsigned char *) &scb_cs, sizeof(scb_cs));
+ if (scb_cs == 0)
+ break;
- udelay(10);
- }
+ udelay(10);
+ }
- if(i <= 0)
- {
+ if (i <= 0) {
#ifdef DEBUG_CONFIG_ERROR
- printk(KERN_INFO "%s: wavelan_ru_start(): board not accepting command.\n",
- dev->name);
+ printk(KERN_INFO
+ "%s: wavelan_ru_start(): board not accepting command.\n",
+ dev->name);
#endif
- return -1;
- }
-
+ return -1;
+ }
#ifdef DEBUG_CONFIG_TRACE
- printk(KERN_DEBUG "%s: <-wv_ru_start()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wv_ru_start()\n", dev->name);
#endif
- return 0;
+ return 0;
}
/*------------------------------------------------------------------*/
@@ -3150,94 +3079,93 @@ wv_ru_start(device * dev)
*
* (called by wv_hw_reset())
*/
-static inline int
-wv_cu_start(device * dev)
+static inline int wv_cu_start(device * dev)
{
- net_local * lp = (net_local *) dev->priv;
- u_long ioaddr = dev->base_addr;
- int i;
- u_short txblock;
- u_short first_nop;
- u_short scb_cs;
+ net_local *lp = (net_local *) dev->priv;
+ unsigned long ioaddr = dev->base_addr;
+ int i;
+ u16 txblock;
+ u16 first_nop;
+ u16 scb_cs;
#ifdef DEBUG_CONFIG_TRACE
- printk(KERN_DEBUG "%s: ->wv_cu_start()\n", dev->name);
+ printk(KERN_DEBUG "%s: ->wv_cu_start()\n", dev->name);
#endif
- lp->tx_first_free = OFFSET_CU;
- lp->tx_first_in_use = I82586NULL;
-
- for(i = 0, txblock = OFFSET_CU;
- i < NTXBLOCKS;
- i++, txblock += TXBLOCKZ)
- {
- ac_tx_t tx;
- ac_nop_t nop;
- tbd_t tbd;
- unsigned short tx_addr;
- unsigned short nop_addr;
- unsigned short tbd_addr;
- unsigned short buf_addr;
-
- tx_addr = txblock;
- nop_addr = tx_addr + sizeof(tx);
- tbd_addr = nop_addr + sizeof(nop);
- buf_addr = tbd_addr + sizeof(tbd);
-
- tx.tx_h.ac_status = 0;
- tx.tx_h.ac_command = acmd_transmit | AC_CFLD_I;
- tx.tx_h.ac_link = nop_addr;
- tx.tx_tbd_offset = tbd_addr;
- obram_write(ioaddr, tx_addr, (unsigned char *) &tx, sizeof(tx));
-
- nop.nop_h.ac_status = 0;
- nop.nop_h.ac_command = acmd_nop;
- nop.nop_h.ac_link = nop_addr;
- obram_write(ioaddr, nop_addr, (unsigned char *) &nop, sizeof(nop));
-
- tbd.tbd_status = TBD_STATUS_EOF;
- tbd.tbd_next_bd_offset = I82586NULL;
- tbd.tbd_bufl = buf_addr;
- tbd.tbd_bufh = 0;
- obram_write(ioaddr, tbd_addr, (unsigned char *) &tbd, sizeof(tbd));
- }
-
- first_nop = OFFSET_CU + (NTXBLOCKS - 1) * TXBLOCKZ + sizeof(ac_tx_t);
- obram_write(ioaddr, scboff(OFFSET_SCB, scb_cbl_offset),
- (unsigned char *) &first_nop, sizeof(first_nop));
-
- scb_cs = SCB_CMD_CUC_GO;
- obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
- (unsigned char *) &scb_cs, sizeof(scb_cs));
-
- set_chan_attn(ioaddr, lp->hacr);
-
- for(i = 1000; i > 0; i--)
- {
- obram_read(ioaddr, scboff(OFFSET_SCB, scb_command),
- (unsigned char *) &scb_cs, sizeof(scb_cs));
- if (scb_cs == 0)
- break;
-
- udelay(10);
- }
-
- if(i <= 0)
- {
+ lp->tx_first_free = OFFSET_CU;
+ lp->tx_first_in_use = I82586NULL;
+
+ for (i = 0, txblock = OFFSET_CU;
+ i < NTXBLOCKS; i++, txblock += TXBLOCKZ) {
+ ac_tx_t tx;
+ ac_nop_t nop;
+ tbd_t tbd;
+ unsigned short tx_addr;
+ unsigned short nop_addr;
+ unsigned short tbd_addr;
+ unsigned short buf_addr;
+
+ tx_addr = txblock;
+ nop_addr = tx_addr + sizeof(tx);
+ tbd_addr = nop_addr + sizeof(nop);
+ buf_addr = tbd_addr + sizeof(tbd);
+
+ tx.tx_h.ac_status = 0;
+ tx.tx_h.ac_command = acmd_transmit | AC_CFLD_I;
+ tx.tx_h.ac_link = nop_addr;
+ tx.tx_tbd_offset = tbd_addr;
+ obram_write(ioaddr, tx_addr, (unsigned char *) &tx,
+ sizeof(tx));
+
+ nop.nop_h.ac_status = 0;
+ nop.nop_h.ac_command = acmd_nop;
+ nop.nop_h.ac_link = nop_addr;
+ obram_write(ioaddr, nop_addr, (unsigned char *) &nop,
+ sizeof(nop));
+
+ tbd.tbd_status = TBD_STATUS_EOF;
+ tbd.tbd_next_bd_offset = I82586NULL;
+ tbd.tbd_bufl = buf_addr;
+ tbd.tbd_bufh = 0;
+ obram_write(ioaddr, tbd_addr, (unsigned char *) &tbd,
+ sizeof(tbd));
+ }
+
+ first_nop =
+ OFFSET_CU + (NTXBLOCKS - 1) * TXBLOCKZ + sizeof(ac_tx_t);
+ obram_write(ioaddr, scboff(OFFSET_SCB, scb_cbl_offset),
+ (unsigned char *) &first_nop, sizeof(first_nop));
+
+ scb_cs = SCB_CMD_CUC_GO;
+ obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
+ (unsigned char *) &scb_cs, sizeof(scb_cs));
+
+ set_chan_attn(ioaddr, lp->hacr);
+
+ for (i = 1000; i > 0; i--) {
+ obram_read(ioaddr, scboff(OFFSET_SCB, scb_command),
+ (unsigned char *) &scb_cs, sizeof(scb_cs));
+ if (scb_cs == 0)
+ break;
+
+ udelay(10);
+ }
+
+ if (i <= 0) {
#ifdef DEBUG_CONFIG_ERROR
- printk(KERN_INFO "%s: wavelan_cu_start(): board not accepting command.\n",
- dev->name);
+ printk(KERN_INFO
+ "%s: wavelan_cu_start(): board not accepting command.\n",
+ dev->name);
#endif
- return -1;
- }
-
- lp->tx_n_in_use = 0;
- dev->tbusy = 0;
+ return -1;
+ }
+ lp->tx_n_in_use = 0;
+ netif_wake_queue(dev);
#ifdef DEBUG_CONFIG_TRACE
- printk(KERN_DEBUG "%s: <-wv_cu_start()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wv_cu_start()\n", dev->name);
#endif
- return 0;
+ return 0;
}
/*------------------------------------------------------------------*/
@@ -3252,121 +3180,122 @@ wv_cu_start(device * dev)
*
* (called by wv_hw_reset())
*/
-static inline int
-wv_82586_start(device * dev)
+static inline int wv_82586_start(device * dev)
{
- net_local * lp = (net_local *) dev->priv;
- u_long ioaddr = dev->base_addr;
- scp_t scp; /* system configuration pointer */
- iscp_t iscp; /* intermediate scp */
- scb_t scb; /* system control block */
- ach_t cb; /* Action command header */
- u_char zeroes[512];
- int i;
+ net_local *lp = (net_local *) dev->priv;
+ unsigned long ioaddr = dev->base_addr;
+ scp_t scp; /* system configuration pointer */
+ iscp_t iscp; /* intermediate scp */
+ scb_t scb; /* system control block */
+ ach_t cb; /* Action command header */
+ u8 zeroes[512];
+ int i;
#ifdef DEBUG_CONFIG_TRACE
- printk(KERN_DEBUG "%s: ->wv_82586_start()\n", dev->name);
+ printk(KERN_DEBUG "%s: ->wv_82586_start()\n", dev->name);
#endif
- /*
- * Clear the onboard RAM.
- */
- memset(&zeroes[0], 0x00, sizeof(zeroes));
- for(i = 0; i < I82586_MEMZ; i += sizeof(zeroes))
- obram_write(ioaddr, i, &zeroes[0], sizeof(zeroes));
-
- /*
- * Construct the command unit structures:
- * scp, iscp, scb, cb.
- */
- memset(&scp, 0x00, sizeof(scp));
- scp.scp_sysbus = SCP_SY_16BBUS;
- scp.scp_iscpl = OFFSET_ISCP;
- obram_write(ioaddr, OFFSET_SCP, (unsigned char *)&scp, sizeof(scp));
-
- memset(&iscp, 0x00, sizeof(iscp));
- iscp.iscp_busy = 1;
- iscp.iscp_offset = OFFSET_SCB;
- obram_write(ioaddr, OFFSET_ISCP, (unsigned char *)&iscp, sizeof(iscp));
-
- /* Our first command is to reset the i82586. */
- memset(&scb, 0x00, sizeof(scb));
- scb.scb_command = SCB_CMD_RESET;
- scb.scb_cbl_offset = OFFSET_CU;
- scb.scb_rfa_offset = OFFSET_RU;
- obram_write(ioaddr, OFFSET_SCB, (unsigned char *)&scb, sizeof(scb));
-
- set_chan_attn(ioaddr, lp->hacr);
-
- /* Wait for command to finish. */
- for(i = 1000; i > 0; i--)
- {
- obram_read(ioaddr, OFFSET_ISCP, (unsigned char *) &iscp, sizeof(iscp));
-
- if(iscp.iscp_busy == (unsigned short) 0)
- break;
-
- udelay(10);
- }
-
- if(i <= 0)
- {
+ /*
+ * Clear the onboard RAM.
+ */
+ memset(&zeroes[0], 0x00, sizeof(zeroes));
+ for (i = 0; i < I82586_MEMZ; i += sizeof(zeroes))
+ obram_write(ioaddr, i, &zeroes[0], sizeof(zeroes));
+
+ /*
+ * Construct the command unit structures:
+ * scp, iscp, scb, cb.
+ */
+ memset(&scp, 0x00, sizeof(scp));
+ scp.scp_sysbus = SCP_SY_16BBUS;
+ scp.scp_iscpl = OFFSET_ISCP;
+ obram_write(ioaddr, OFFSET_SCP, (unsigned char *) &scp,
+ sizeof(scp));
+
+ memset(&iscp, 0x00, sizeof(iscp));
+ iscp.iscp_busy = 1;
+ iscp.iscp_offset = OFFSET_SCB;
+ obram_write(ioaddr, OFFSET_ISCP, (unsigned char *) &iscp,
+ sizeof(iscp));
+
+ /* Our first command is to reset the i82586. */
+ memset(&scb, 0x00, sizeof(scb));
+ scb.scb_command = SCB_CMD_RESET;
+ scb.scb_cbl_offset = OFFSET_CU;
+ scb.scb_rfa_offset = OFFSET_RU;
+ obram_write(ioaddr, OFFSET_SCB, (unsigned char *) &scb,
+ sizeof(scb));
+
+ set_chan_attn(ioaddr, lp->hacr);
+
+ /* Wait for command to finish. */
+ for (i = 1000; i > 0; i--) {
+ obram_read(ioaddr, OFFSET_ISCP, (unsigned char *) &iscp,
+ sizeof(iscp));
+
+ if (iscp.iscp_busy == (unsigned short) 0)
+ break;
+
+ udelay(10);
+ }
+
+ if (i <= 0) {
#ifdef DEBUG_CONFIG_ERROR
- printk(KERN_INFO "%s: wv_82586_start(): iscp_busy timeout.\n",
- dev->name);
+ printk(KERN_INFO
+ "%s: wv_82586_start(): iscp_busy timeout.\n",
+ dev->name);
#endif
- return -1;
- }
+ return -1;
+ }
- /* Check command completion. */
- for(i = 15; i > 0; i--)
- {
- obram_read(ioaddr, OFFSET_SCB, (unsigned char *) &scb, sizeof(scb));
+ /* Check command completion. */
+ for (i = 15; i > 0; i--) {
+ obram_read(ioaddr, OFFSET_SCB, (unsigned char *) &scb,
+ sizeof(scb));
- if (scb.scb_status == (SCB_ST_CX | SCB_ST_CNA))
- break;
+ if (scb.scb_status == (SCB_ST_CX | SCB_ST_CNA))
+ break;
- udelay(10);
- }
+ udelay(10);
+ }
- if (i <= 0)
- {
+ if (i <= 0) {
#ifdef DEBUG_CONFIG_ERROR
- printk(KERN_INFO "%s: wv_82586_start(): status: expected 0x%02x, got 0x%02x.\n",
- dev->name, SCB_ST_CX | SCB_ST_CNA, scb.scb_status);
+ printk(KERN_INFO
+ "%s: wv_82586_start(): status: expected 0x%02x, got 0x%02x.\n",
+ dev->name, SCB_ST_CX | SCB_ST_CNA, scb.scb_status);
#endif
- return -1;
- }
+ return -1;
+ }
- wv_ack(dev);
+ wv_ack(dev);
- /* Set the action command header. */
- memset(&cb, 0x00, sizeof(cb));
- cb.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_diagnose);
- cb.ac_link = OFFSET_CU;
- obram_write(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb));
+ /* Set the action command header. */
+ memset(&cb, 0x00, sizeof(cb));
+ cb.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_diagnose);
+ cb.ac_link = OFFSET_CU;
+ obram_write(ioaddr, OFFSET_CU, (unsigned char *) &cb, sizeof(cb));
- if(wv_synchronous_cmd(dev, "diag()") == -1)
- return -1;
+ if (wv_synchronous_cmd(dev, "diag()") == -1)
+ return -1;
- obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb));
- if(cb.ac_status & AC_SFLD_FAIL)
- {
+ obram_read(ioaddr, OFFSET_CU, (unsigned char *) &cb, sizeof(cb));
+ if (cb.ac_status & AC_SFLD_FAIL) {
#ifdef DEBUG_CONFIG_ERROR
- printk(KERN_INFO "%s: wv_82586_start(): i82586 Self Test failed.\n",
- dev->name);
+ printk(KERN_INFO
+ "%s: wv_82586_start(): i82586 Self Test failed.\n",
+ dev->name);
#endif
- return -1;
- }
-
+ return -1;
+ }
#ifdef DEBUG_I82586_SHOW
- wv_scb_show(ioaddr);
+ wv_scb_show(ioaddr);
#endif
#ifdef DEBUG_CONFIG_TRACE
- printk(KERN_DEBUG "%s: <-wv_82586_start()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wv_82586_start()\n", dev->name);
#endif
- return 0;
+ return 0;
}
/*------------------------------------------------------------------*/
@@ -3383,184 +3312,179 @@ wv_82586_start(device * dev)
*
* (called by wv_hw_reset(), wv_82586_reconfig())
*/
-static void
-wv_82586_config(device * dev)
+static void wv_82586_config(device * dev)
{
- net_local * lp = (net_local *) dev->priv;
- u_long ioaddr = dev->base_addr;
- unsigned short txblock;
- unsigned short txpred;
- unsigned short tx_addr;
- unsigned short nop_addr;
- unsigned short tbd_addr;
- unsigned short cfg_addr;
- unsigned short ias_addr;
- unsigned short mcs_addr;
- ac_tx_t tx;
- ac_nop_t nop;
- ac_cfg_t cfg; /* Configure action */
- ac_ias_t ias; /* IA-setup action */
- ac_mcs_t mcs; /* Multicast setup */
- struct dev_mc_list * dmi;
- unsigned long x;
+ net_local *lp = (net_local *) dev->priv;
+ unsigned long ioaddr = dev->base_addr;
+ unsigned short txblock;
+ unsigned short txpred;
+ unsigned short tx_addr;
+ unsigned short nop_addr;
+ unsigned short tbd_addr;
+ unsigned short cfg_addr;
+ unsigned short ias_addr;
+ unsigned short mcs_addr;
+ ac_tx_t tx;
+ ac_nop_t nop;
+ ac_cfg_t cfg; /* Configure action */
+ ac_ias_t ias; /* IA-setup action */
+ ac_mcs_t mcs; /* Multicast setup */
+ struct dev_mc_list *dmi;
+ unsigned long flags;
#ifdef DEBUG_CONFIG_TRACE
- printk(KERN_DEBUG "%s: ->wv_82586_config()\n", dev->name);
+ printk(KERN_DEBUG "%s: ->wv_82586_config()\n", dev->name);
#endif
- x = wv_splhi();
-
- /* Calculate addresses of next block and previous block. */
- txblock = lp->tx_first_free;
- txpred = txblock - TXBLOCKZ;
- if(txpred < OFFSET_CU)
- txpred += NTXBLOCKS * TXBLOCKZ;
- lp->tx_first_free += TXBLOCKZ;
- if(lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)
- lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ;
-
- lp->tx_n_in_use++;
-
- /* Calculate addresses of the different parts of the block. */
- tx_addr = txblock;
- nop_addr = tx_addr + sizeof(tx);
- tbd_addr = nop_addr + sizeof(nop);
- cfg_addr = tbd_addr + sizeof(tbd_t); /* beginning of the buffer */
- ias_addr = cfg_addr + sizeof(cfg);
- mcs_addr = ias_addr + sizeof(ias);
-
- /*
- * Transmit command
- */
- tx.tx_h.ac_status = 0xFFFF; /* Fake completion value */
- obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status),
- (unsigned char *) &tx.tx_h.ac_status,
- sizeof(tx.tx_h.ac_status));
-
- /*
- * NOP command
- */
- nop.nop_h.ac_status = 0;
- obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
- (unsigned char *) &nop.nop_h.ac_status,
- sizeof(nop.nop_h.ac_status));
- nop.nop_h.ac_link = nop_addr;
- obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
- (unsigned char *) &nop.nop_h.ac_link,
- sizeof(nop.nop_h.ac_link));
-
- /* Create a configure action. */
- memset(&cfg, 0x00, sizeof(cfg));
-
- /*
- * For Linux we invert AC_CFG_ALOC() so as to conform
- * to the way that net packets reach us from above.
- * (See also ac_tx_t.)
- *
- * Updated from Wavelan Manual WCIN085B
- */
- cfg.cfg_byte_cnt = AC_CFG_BYTE_CNT(sizeof(ac_cfg_t) - sizeof(ach_t));
- cfg.cfg_fifolim = AC_CFG_FIFOLIM(4);
- cfg.cfg_byte8 = AC_CFG_SAV_BF(1) |
- AC_CFG_SRDY(0);
- cfg.cfg_byte9 = AC_CFG_ELPBCK(0) |
- AC_CFG_ILPBCK(0) |
- AC_CFG_PRELEN(AC_CFG_PLEN_2) |
- AC_CFG_ALOC(1) |
- AC_CFG_ADDRLEN(WAVELAN_ADDR_SIZE);
- cfg.cfg_byte10 = AC_CFG_BOFMET(1) |
- AC_CFG_ACR(6) |
- AC_CFG_LINPRIO(0);
- cfg.cfg_ifs = 0x20;
- cfg.cfg_slotl = 0x0C;
- cfg.cfg_byte13 = AC_CFG_RETRYNUM(15) |
- AC_CFG_SLTTMHI(0);
- cfg.cfg_byte14 = AC_CFG_FLGPAD(0) |
- AC_CFG_BTSTF(0) |
- AC_CFG_CRC16(0) |
- AC_CFG_NCRC(0) |
- AC_CFG_TNCRS(1) |
- AC_CFG_MANCH(0) |
- AC_CFG_BCDIS(0) |
- AC_CFG_PRM(lp->promiscuous);
- cfg.cfg_byte15 = AC_CFG_ICDS(0) |
- AC_CFG_CDTF(0) |
- AC_CFG_ICSS(0) |
- AC_CFG_CSTF(0);
+ save_flags(flags);
+ cli();
+
+ /* Calculate addresses of next block and previous block. */
+ txblock = lp->tx_first_free;
+ txpred = txblock - TXBLOCKZ;
+ if (txpred < OFFSET_CU)
+ txpred += NTXBLOCKS * TXBLOCKZ;
+ lp->tx_first_free += TXBLOCKZ;
+ if (lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)
+ lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ;
+
+ lp->tx_n_in_use++;
+
+ /* Calculate addresses of the different parts of the block. */
+ tx_addr = txblock;
+ nop_addr = tx_addr + sizeof(tx);
+ tbd_addr = nop_addr + sizeof(nop);
+ cfg_addr = tbd_addr + sizeof(tbd_t); /* beginning of the buffer */
+ ias_addr = cfg_addr + sizeof(cfg);
+ mcs_addr = ias_addr + sizeof(ias);
+
+ /*
+ * Transmit command
+ */
+ tx.tx_h.ac_status = 0xFFFF; /* Fake completion value */
+ obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status),
+ (unsigned char *) &tx.tx_h.ac_status,
+ sizeof(tx.tx_h.ac_status));
+
+ /*
+ * NOP command
+ */
+ nop.nop_h.ac_status = 0;
+ obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
+ (unsigned char *) &nop.nop_h.ac_status,
+ sizeof(nop.nop_h.ac_status));
+ nop.nop_h.ac_link = nop_addr;
+ obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
+ (unsigned char *) &nop.nop_h.ac_link,
+ sizeof(nop.nop_h.ac_link));
+
+ /* Create a configure action. */
+ memset(&cfg, 0x00, sizeof(cfg));
+
+ /*
+ * For Linux we invert AC_CFG_ALOC() so as to conform
+ * to the way that net packets reach us from above.
+ * (See also ac_tx_t.)
+ *
+ * Updated from Wavelan Manual WCIN085B
+ */
+ cfg.cfg_byte_cnt =
+ AC_CFG_BYTE_CNT(sizeof(ac_cfg_t) - sizeof(ach_t));
+ cfg.cfg_fifolim = AC_CFG_FIFOLIM(4);
+ cfg.cfg_byte8 = AC_CFG_SAV_BF(1) | AC_CFG_SRDY(0);
+ cfg.cfg_byte9 = AC_CFG_ELPBCK(0) |
+ AC_CFG_ILPBCK(0) |
+ AC_CFG_PRELEN(AC_CFG_PLEN_2) |
+ AC_CFG_ALOC(1) | AC_CFG_ADDRLEN(WAVELAN_ADDR_SIZE);
+ cfg.cfg_byte10 = AC_CFG_BOFMET(1) |
+ AC_CFG_ACR(6) | AC_CFG_LINPRIO(0);
+ cfg.cfg_ifs = 0x20;
+ cfg.cfg_slotl = 0x0C;
+ cfg.cfg_byte13 = AC_CFG_RETRYNUM(15) | AC_CFG_SLTTMHI(0);
+ cfg.cfg_byte14 = AC_CFG_FLGPAD(0) |
+ AC_CFG_BTSTF(0) |
+ AC_CFG_CRC16(0) |
+ AC_CFG_NCRC(0) |
+ AC_CFG_TNCRS(1) |
+ AC_CFG_MANCH(0) |
+ AC_CFG_BCDIS(0) | AC_CFG_PRM(lp->promiscuous);
+ cfg.cfg_byte15 = AC_CFG_ICDS(0) |
+ AC_CFG_CDTF(0) | AC_CFG_ICSS(0) | AC_CFG_CSTF(0);
/*
cfg.cfg_min_frm_len = AC_CFG_MNFRM(64);
*/
- cfg.cfg_min_frm_len = AC_CFG_MNFRM(8);
-
- cfg.cfg_h.ac_command = (AC_CFLD_CMD & acmd_configure);
- cfg.cfg_h.ac_link = ias_addr;
- obram_write(ioaddr, cfg_addr, (unsigned char *)&cfg, sizeof(cfg));
-
- /* Set up the MAC address */
- memset(&ias, 0x00, sizeof(ias));
- ias.ias_h.ac_command = (AC_CFLD_CMD & acmd_ia_setup);
- ias.ias_h.ac_link = mcs_addr;
- memcpy(&ias.ias_addr[0], (unsigned char *)&dev->dev_addr[0], sizeof(ias.ias_addr));
- obram_write(ioaddr, ias_addr, (unsigned char *)&ias, sizeof(ias));
-
- /* Initialize adapter's Ethernet multicast addresses */
- memset(&mcs, 0x00, sizeof(mcs));
- mcs.mcs_h.ac_command = AC_CFLD_I | (AC_CFLD_CMD & acmd_mc_setup);
- mcs.mcs_h.ac_link = nop_addr;
- mcs.mcs_cnt = WAVELAN_ADDR_SIZE * lp->mc_count;
- obram_write(ioaddr, mcs_addr, (unsigned char *)&mcs, sizeof(mcs));
-
- /* Any address to set? */
- if(lp->mc_count)
- {
- for(dmi=dev->mc_list; dmi; dmi=dmi->next)
- outsw(PIOP1(ioaddr), (u_short *) dmi->dmi_addr,
- WAVELAN_ADDR_SIZE >> 1);
+ cfg.cfg_min_frm_len = AC_CFG_MNFRM(8);
+
+ cfg.cfg_h.ac_command = (AC_CFLD_CMD & acmd_configure);
+ cfg.cfg_h.ac_link = ias_addr;
+ obram_write(ioaddr, cfg_addr, (unsigned char *) &cfg, sizeof(cfg));
+
+ /* Set up the MAC address */
+ memset(&ias, 0x00, sizeof(ias));
+ ias.ias_h.ac_command = (AC_CFLD_CMD & acmd_ia_setup);
+ ias.ias_h.ac_link = mcs_addr;
+ memcpy(&ias.ias_addr[0], (unsigned char *) &dev->dev_addr[0],
+ sizeof(ias.ias_addr));
+ obram_write(ioaddr, ias_addr, (unsigned char *) &ias, sizeof(ias));
+
+ /* Initialize adapter's Ethernet multicast addresses */
+ memset(&mcs, 0x00, sizeof(mcs));
+ mcs.mcs_h.ac_command = AC_CFLD_I | (AC_CFLD_CMD & acmd_mc_setup);
+ mcs.mcs_h.ac_link = nop_addr;
+ mcs.mcs_cnt = WAVELAN_ADDR_SIZE * lp->mc_count;
+ obram_write(ioaddr, mcs_addr, (unsigned char *) &mcs, sizeof(mcs));
+
+ /* Any address to set? */
+ if (lp->mc_count) {
+ for (dmi = dev->mc_list; dmi; dmi = dmi->next)
+ outsw(PIOP1(ioaddr), (u16 *) dmi->dmi_addr,
+ WAVELAN_ADDR_SIZE >> 1);
#ifdef DEBUG_CONFIG_INFO
- printk(KERN_DEBUG "%s: wv_82586_config(): set %d multicast addresses:\n",
- dev->name, lp->mc_count);
- for(dmi=dev->mc_list; dmi; dmi=dmi->next)
- printk(KERN_DEBUG " %02x:%02x:%02x:%02x:%02x:%02x\n",
- dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2],
- dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5] );
+ printk(KERN_DEBUG
+ "%s: wv_82586_config(): set %d multicast addresses:\n",
+ dev->name, lp->mc_count);
+ for (dmi = dev->mc_list; dmi; dmi = dmi->next)
+ printk(KERN_DEBUG
+ " %02x:%02x:%02x:%02x:%02x:%02x\n",
+ dmi->dmi_addr[0], dmi->dmi_addr[1],
+ dmi->dmi_addr[2], dmi->dmi_addr[3],
+ dmi->dmi_addr[4], dmi->dmi_addr[5]);
#endif
- }
-
- /*
- * Overwrite the predecessor NOP link
- * so that it points to the configure action.
- */
- nop_addr = txpred + sizeof(tx);
- nop.nop_h.ac_status = 0;
- obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
- (unsigned char *)&nop.nop_h.ac_status,
- sizeof(nop.nop_h.ac_status));
- nop.nop_h.ac_link = cfg_addr;
- obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
- (unsigned char *) &nop.nop_h.ac_link,
- sizeof(nop.nop_h.ac_link));
-
- /* If watchdog not already active, activate it... */
- if(lp->watchdog.prev == (timer_list *) NULL)
- {
- /* set timer to expire in WATCHDOG_JIFFIES */
- lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
- add_timer(&lp->watchdog);
- }
-
- lp->reconfig_82586 = 0;
-
- if(lp->tx_first_in_use == I82586NULL)
- lp->tx_first_in_use = txblock;
-
- if(lp->tx_n_in_use < NTXBLOCKS - 1)
- dev->tbusy = 0;
-
- wv_splx(x);
+ }
+
+ /*
+ * Overwrite the predecessor NOP link
+ * so that it points to the configure action.
+ */
+ nop_addr = txpred + sizeof(tx);
+ nop.nop_h.ac_status = 0;
+ obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status),
+ (unsigned char *) &nop.nop_h.ac_status,
+ sizeof(nop.nop_h.ac_status));
+ nop.nop_h.ac_link = cfg_addr;
+ obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link),
+ (unsigned char *) &nop.nop_h.ac_link,
+ sizeof(nop.nop_h.ac_link));
+
+ /* If watchdog not already active, activate it... */
+ if (lp->watchdog.prev == (timer_list *) NULL) {
+ /* set timer to expire in WATCHDOG_JIFFIES */
+ lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
+ add_timer(&lp->watchdog);
+ }
+
+ lp->reconfig_82586 = 0;
+ if (lp->tx_first_in_use == I82586NULL)
+ lp->tx_first_in_use = txblock;
+
+ if (lp->tx_n_in_use < NTXBLOCKS - 1)
+ netif_wake_queue(dev);
+
+ restore_flags(flags);
#ifdef DEBUG_CONFIG_TRACE
- printk(KERN_DEBUG "%s: <-wv_82586_config()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wv_82586_config()\n", dev->name);
#endif
}
@@ -3569,28 +3493,29 @@ wv_82586_config(device * dev)
* This routine, called by wavelan_close(), gracefully stops the
* WaveLAN controller (i82586).
*/
-static inline void
-wv_82586_stop(device * dev)
+static inline void wv_82586_stop(device * dev)
{
- net_local * lp = (net_local *) dev->priv;
- u_long ioaddr = dev->base_addr;
- u_short scb_cmd;
+ net_local *lp = (net_local *) dev->priv;
+ unsigned long ioaddr = dev->base_addr;
+ u16 scb_cmd;
#ifdef DEBUG_CONFIG_TRACE
- printk(KERN_DEBUG "%s: ->wv_82586_stop()\n", dev->name);
+ printk(KERN_DEBUG "%s: ->wv_82586_stop()\n", dev->name);
#endif
- /* Suspend both command unit and receive unit. */
- scb_cmd = (SCB_CMD_CUC & SCB_CMD_CUC_SUS) | (SCB_CMD_RUC & SCB_CMD_RUC_SUS);
- obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
- (unsigned char *)&scb_cmd, sizeof(scb_cmd));
- set_chan_attn(ioaddr, lp->hacr);
+ /* Suspend both command unit and receive unit. */
+ scb_cmd =
+ (SCB_CMD_CUC & SCB_CMD_CUC_SUS) | (SCB_CMD_RUC &
+ SCB_CMD_RUC_SUS);
+ obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
+ (unsigned char *) &scb_cmd, sizeof(scb_cmd));
+ set_chan_attn(ioaddr, lp->hacr);
- /* No more interrupts */
- wv_ints_off(dev);
+ /* No more interrupts */
+ wv_ints_off(dev);
#ifdef DEBUG_CONFIG_TRACE
- printk(KERN_DEBUG "%s: <-wv_82586_stop()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wv_82586_stop()\n", dev->name);
#endif
}
@@ -3604,49 +3529,47 @@ wv_82586_stop(device * dev)
* 4. Start the LAN controller's command unit
* 5. Start the LAN controller's receive unit
*/
-static int
-wv_hw_reset(device * dev)
+static int wv_hw_reset(device * dev)
{
- net_local * lp = (net_local *)dev->priv;
- u_long ioaddr = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv;
+ unsigned long ioaddr = dev->base_addr;
#ifdef DEBUG_CONFIG_TRACE
- printk(KERN_DEBUG "%s: ->wv_hw_reset(dev=0x%x)\n", dev->name,
- (unsigned int)dev);
+ printk(KERN_DEBUG "%s: ->wv_hw_reset(dev=0x%x)\n", dev->name,
+ (unsigned int) dev);
#endif
- /* If watchdog was activated, kill it! */
- if(lp->watchdog.prev != (timer_list *) NULL)
- del_timer(&lp->watchdog);
+ /* If watchdog was activated, kill it! */
+ if (lp->watchdog.prev != (timer_list *) NULL)
+ del_timer(&lp->watchdog);
- /* Increase the number of resets done. */
- lp->nresets++;
+ /* Increase the number of resets done. */
+ lp->nresets++;
- wv_hacr_reset(ioaddr);
- lp->hacr = HACR_DEFAULT;
+ wv_hacr_reset(ioaddr);
+ lp->hacr = HACR_DEFAULT;
- if((wv_mmc_init(dev) < 0) ||
- (wv_82586_start(dev) < 0))
- return -1;
+ if ((wv_mmc_init(dev) < 0) || (wv_82586_start(dev) < 0))
+ return -1;
- /* Enable the card to send interrupts. */
- wv_ints_on(dev);
+ /* Enable the card to send interrupts. */
+ wv_ints_on(dev);
- /* Start card functions */
- if(wv_cu_start(dev) < 0)
- return -1;
+ /* Start card functions */
+ if (wv_cu_start(dev) < 0)
+ return -1;
- /* Setup the controller and parameters */
- wv_82586_config(dev);
+ /* Setup the controller and parameters */
+ wv_82586_config(dev);
- /* Finish configuration with the receive unit */
- if(wv_ru_start(dev) < 0)
- return -1;
+ /* Finish configuration with the receive unit */
+ if (wv_ru_start(dev) < 0)
+ return -1;
#ifdef DEBUG_CONFIG_TRACE
- printk(KERN_DEBUG "%s: <-wv_hw_reset()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wv_hw_reset()\n", dev->name);
#endif
- return 0;
+ return 0;
}
/*------------------------------------------------------------------*/
@@ -3655,40 +3578,39 @@ wv_hw_reset(device * dev)
* As a side effect, this reads the MAC address.
* (called in wavelan_probe() and init_module())
*/
-static int
-wv_check_ioaddr(u_long ioaddr,
- u_char * mac)
+static int wv_check_ioaddr(unsigned long ioaddr, u8 * mac)
{
- int i; /* Loop counter */
-
- /* Check if the base address if available. */
- if(check_region(ioaddr, sizeof(ha_t)))
- return EADDRINUSE; /* ioaddr already used */
-
- /* Reset host interface */
- wv_hacr_reset(ioaddr);
-
- /* Read the MAC address from the parameter storage area. */
- psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_univ_mac_addr),
- mac, 6);
-
- /*
- * Check the first three octets of the address for the manufacturer's code.
- * Note: if this can't find your WaveLAN card, you've got a
- * non-NCR/AT&T/Lucent ISA card. See wavelan.p.h for detail on
- * how to configure your card.
- */
- for(i = 0; i < (sizeof(MAC_ADDRESSES) / sizeof(char) / 3); i++)
- if((mac[0] == MAC_ADDRESSES[i][0]) &&
- (mac[1] == MAC_ADDRESSES[i][1]) &&
- (mac[2] == MAC_ADDRESSES[i][2]))
- return 0;
+ int i; /* Loop counter */
+
+ /* Check if the base address if available. */
+ if (check_region(ioaddr, sizeof(ha_t)))
+ return EADDRINUSE; /* ioaddr already used */
+
+ /* Reset host interface */
+ wv_hacr_reset(ioaddr);
+
+ /* Read the MAC address from the parameter storage area. */
+ psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_univ_mac_addr),
+ mac, 6);
+
+ /*
+ * Check the first three octets of the address for the manufacturer's code.
+ * Note: if this can't find your WaveLAN card, you've got a
+ * non-NCR/AT&T/Lucent ISA card. See wavelan.p.h for detail on
+ * how to configure your card.
+ */
+ for (i = 0; i < (sizeof(MAC_ADDRESSES) / sizeof(char) / 3); i++)
+ if ((mac[0] == MAC_ADDRESSES[i][0]) &&
+ (mac[1] == MAC_ADDRESSES[i][1]) &&
+ (mac[2] == MAC_ADDRESSES[i][2]))
+ return 0;
#ifdef DEBUG_CONFIG_INFO
- printk(KERN_WARNING "WaveLAN (0x%3X): your MAC address might be %02X:%02X:%02X.\n",
- ioaddr, mac[0], mac[1], mac[2]);
+ printk(KERN_WARNING
+ "WaveLAN (0x%3X): your MAC address might be %02X:%02X:%02X.\n",
+ ioaddr, mac[0], mac[1], mac[2]);
#endif
- return ENODEV;
+ return ENODEV;
}
/************************ INTERRUPT HANDLING ************************/
@@ -3697,133 +3619,121 @@ wv_check_ioaddr(u_long ioaddr,
* This function is the interrupt handler for the WaveLAN card. This
* routine will be called whenever:
*/
-static void
-wavelan_interrupt(int irq,
- void * dev_id,
- struct pt_regs * regs)
+static void wavelan_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- device * dev;
- u_long ioaddr;
- net_local * lp;
- u_short hasr;
- u_short status;
- u_short ack_cmd;
+ device *dev;
+ unsigned long ioaddr;
+ net_local *lp;
+ u16 hasr;
+ u16 status;
+ u16 ack_cmd;
- dev = dev_id;
+ dev = dev_id;
#ifdef DEBUG_INTERRUPT_TRACE
- printk(KERN_DEBUG "%s: ->wavelan_interrupt()\n", dev->name);
+ printk(KERN_DEBUG "%s: ->wavelan_interrupt()\n", dev->name);
#endif
- lp = (net_local *) dev->priv;
- ioaddr = dev->base_addr;
+ lp = (net_local *) dev->priv;
+ ioaddr = dev->base_addr;
- /* Prevent reentrance. What should we do here? */
-#ifdef DEBUG_INTERRUPT_ERROR
- if(dev->interrupt)
- printk(KERN_INFO "%s: wavelan_interrupt(): Re-entering the interrupt handler.\n",
- dev->name);
-#endif
- dev->interrupt = 1;
+ /* Prevent reentrance. What should we do here? */
- if((hasr = hasr_read(ioaddr)) & HASR_MMC_INTR)
- {
- u_char dce_status;
+ if ((hasr = hasr_read(ioaddr)) & HASR_MMC_INTR) {
+ u8 dce_status;
- /*
- * Interrupt from the modem management controller.
- * This will clear it -- ignored for now.
- */
- mmc_read(ioaddr, mmroff(0, mmr_dce_status), &dce_status, sizeof(dce_status));
+ /*
+ * Interrupt from the modem management controller.
+ * This will clear it -- ignored for now.
+ */
+ mmc_read(ioaddr, mmroff(0, mmr_dce_status), &dce_status,
+ sizeof(dce_status));
#ifdef DEBUG_INTERRUPT_ERROR
- printk(KERN_INFO "%s: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n",
- dev->name, dce_status);
+ printk(KERN_INFO
+ "%s: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n",
+ dev->name, dce_status);
#endif
- }
+ }
- if((hasr & HASR_82586_INTR) == 0)
- {
- dev->interrupt = 0;
+ if ((hasr & HASR_82586_INTR) == 0) {
#ifdef DEBUG_INTERRUPT_ERROR
- printk(KERN_INFO "%s: wavelan_interrupt(): interrupt not coming from i82586\n",
- dev->name);
+ printk(KERN_INFO
+ "%s: wavelan_interrupt(): interrupt not coming from i82586\n",
+ dev->name);
#endif
- return;
- }
+ return;
+ }
- /* Read interrupt data. */
- obram_read(ioaddr, scboff(OFFSET_SCB, scb_status),
- (unsigned char *) &status, sizeof(status));
+ /* Read interrupt data. */
+ obram_read(ioaddr, scboff(OFFSET_SCB, scb_status),
+ (unsigned char *) &status, sizeof(status));
- /*
- * Acknowledge the interrupt(s).
- */
- ack_cmd = status & SCB_ST_INT;
- obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
- (unsigned char *) &ack_cmd, sizeof(ack_cmd));
- set_chan_attn(ioaddr, lp->hacr);
+ /*
+ * Acknowledge the interrupt(s).
+ */
+ ack_cmd = status & SCB_ST_INT;
+ obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),
+ (unsigned char *) &ack_cmd, sizeof(ack_cmd));
+ set_chan_attn(ioaddr, lp->hacr);
#ifdef DEBUG_INTERRUPT_INFO
- printk(KERN_DEBUG "%s: wavelan_interrupt(): status 0x%04x.\n",
- dev->name, status);
+ printk(KERN_DEBUG "%s: wavelan_interrupt(): status 0x%04x.\n",
+ dev->name, status);
#endif
- /* Command completed. */
- if((status & SCB_ST_CX) == SCB_ST_CX)
- {
+ /* Command completed. */
+ if ((status & SCB_ST_CX) == SCB_ST_CX) {
#ifdef DEBUG_INTERRUPT_INFO
- printk(KERN_DEBUG "%s: wavelan_interrupt(): command completed.\n",
- dev->name);
+ printk(KERN_DEBUG
+ "%s: wavelan_interrupt(): command completed.\n",
+ dev->name);
#endif
- wv_complete(dev, ioaddr, lp);
-
- /* If watchdog was activated, kill it ! */
- if(lp->watchdog.prev != (timer_list *) NULL)
- del_timer(&lp->watchdog);
- if(lp->tx_n_in_use > 0)
- {
- /* set timer to expire in WATCHDOG_JIFFIES */
- lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
- add_timer(&lp->watchdog);
+ wv_complete(dev, ioaddr, lp);
+
+ /* If watchdog was activated, kill it ! */
+ if (lp->watchdog.prev != (timer_list *) NULL)
+ del_timer(&lp->watchdog);
+ if (lp->tx_n_in_use > 0) {
+ /* set timer to expire in WATCHDOG_JIFFIES */
+ lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
+ add_timer(&lp->watchdog);
+ }
}
- }
- /* Frame received. */
- if((status & SCB_ST_FR) == SCB_ST_FR)
- {
+ /* Frame received. */
+ if ((status & SCB_ST_FR) == SCB_ST_FR) {
#ifdef DEBUG_INTERRUPT_INFO
- printk(KERN_DEBUG "%s: wavelan_interrupt(): received packet.\n",
- dev->name);
+ printk(KERN_DEBUG
+ "%s: wavelan_interrupt(): received packet.\n",
+ dev->name);
#endif
- wv_receive(dev);
- }
+ wv_receive(dev);
+ }
- /* Check the state of the command unit. */
- if(((status & SCB_ST_CNA) == SCB_ST_CNA) ||
- (((status & SCB_ST_CUS) != SCB_ST_CUS_ACTV) && dev->start))
- {
+ /* Check the state of the command unit. */
+ if (((status & SCB_ST_CNA) == SCB_ST_CNA) ||
+ (((status & SCB_ST_CUS) != SCB_ST_CUS_ACTV) && netif_running(dev))) {
#ifdef DEBUG_INTERRUPT_ERROR
- printk(KERN_INFO "%s: wavelan_interrupt(): CU inactive -- restarting\n",
- dev->name);
+ printk(KERN_INFO
+ "%s: wavelan_interrupt(): CU inactive -- restarting\n",
+ dev->name);
#endif
- wv_hw_reset(dev);
- }
+ wv_hw_reset(dev);
+ }
- /* Check the state of the command unit. */
- if(((status & SCB_ST_RNR) == SCB_ST_RNR) ||
- (((status & SCB_ST_RUS) != SCB_ST_RUS_RDY) && dev->start))
- {
+ /* Check the state of the command unit. */
+ if (((status & SCB_ST_RNR) == SCB_ST_RNR) ||
+ (((status & SCB_ST_RUS) != SCB_ST_RUS_RDY) && netif_running(dev))) {
#ifdef DEBUG_INTERRUPT_ERROR
- printk(KERN_INFO "%s: wavelan_interrupt(): RU not ready -- restarting\n",
- dev->name);
+ printk(KERN_INFO
+ "%s: wavelan_interrupt(): RU not ready -- restarting\n",
+ dev->name);
#endif
- wv_hw_reset(dev);
- }
-
- dev->interrupt = 0;
+ wv_hw_reset(dev);
+ }
#ifdef DEBUG_INTERRUPT_TRACE
- printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name);
#endif
}
@@ -3838,83 +3748,81 @@ wavelan_interrupt(int irq,
* way because the overhead of add_timer() and del_timer() is nothing
* and because it avoids calling the watchdog, saving some CPU.
*/
-static void
-wavelan_watchdog(u_long a)
+static void wavelan_watchdog(unsigned long a)
{
- device * dev;
- net_local * lp;
- u_long ioaddr;
- unsigned long x;
- unsigned int nreaped;
+ device *dev;
+ net_local *lp;
+ unsigned long ioaddr;
+ unsigned long flags;
+ unsigned int nreaped;
- dev = (device *) a;
- ioaddr = dev->base_addr;
- lp = (net_local *) dev->priv;
+ dev = (device *) a;
+ ioaddr = dev->base_addr;
+ lp = (net_local *) dev->priv;
#ifdef DEBUG_INTERRUPT_TRACE
- printk(KERN_DEBUG "%s: ->wavelan_watchdog()\n", dev->name);
+ printk(KERN_DEBUG "%s: ->wavelan_watchdog()\n", dev->name);
#endif
#ifdef DEBUG_INTERRUPT_ERROR
- printk(KERN_INFO "%s: wavelan_watchdog: watchdog timer expired\n",
- dev->name);
+ printk(KERN_INFO "%s: wavelan_watchdog: watchdog timer expired\n",
+ dev->name);
#endif
- x = wv_splhi();
-
- dev = (device *) a;
- ioaddr = dev->base_addr;
- lp = (net_local *) dev->priv;
+ save_flags(flags);
+ cli();
+
+ dev = (device *) a;
+ ioaddr = dev->base_addr;
+ lp = (net_local *) dev->priv;
- if(lp->tx_n_in_use <= 0)
- {
- wv_splx(x);
- return;
- }
+ if (lp->tx_n_in_use <= 0) {
+ restore_flags(flags);
+ return;
+ }
- nreaped = wv_complete(dev, ioaddr, lp);
+ nreaped = wv_complete(dev, ioaddr, lp);
#ifdef DEBUG_INTERRUPT_INFO
- printk(KERN_DEBUG "%s: wavelan_watchdog(): %d reaped, %d remain.\n",
- dev->name, nreaped, lp->tx_n_in_use);
+ printk(KERN_DEBUG
+ "%s: wavelan_watchdog(): %d reaped, %d remain.\n",
+ dev->name, nreaped, lp->tx_n_in_use);
#endif
#ifdef DEBUG_PSA_SHOW
- {
- psa_t psa;
- psa_read(dev, 0, (unsigned char *) &psa, sizeof(psa));
- wv_psa_show(&psa);
- }
+ {
+ psa_t psa;
+ psa_read(dev, 0, (unsigned char *) &psa, sizeof(psa));
+ wv_psa_show(&psa);
+ }
#endif
#ifdef DEBUG_MMC_SHOW
- wv_mmc_show(dev);
+ wv_mmc_show(dev);
#endif
#ifdef DEBUG_I82586_SHOW
- wv_cu_show(dev);
+ wv_cu_show(dev);
#endif
- /* If no buffer has been freed */
- if(nreaped == 0)
- {
+ /* If no buffer has been freed */
+ if (nreaped == 0) {
#ifdef DEBUG_INTERRUPT_ERROR
- printk(KERN_INFO "%s: wavelan_watchdog(): cleanup failed, trying reset\n",
- dev->name);
+ printk(KERN_INFO
+ "%s: wavelan_watchdog(): cleanup failed, trying reset\n",
+ dev->name);
#endif
- wv_hw_reset(dev);
- }
- else
- /* Reset watchdog for next transmission. */
- if(lp->tx_n_in_use > 0)
- {
- /* set timer to expire in WATCHDOG_JIFFIES */
- lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
- add_timer(&lp->watchdog);
- }
-
- wv_splx(x);
+ wv_hw_reset(dev);
+ } else
+ /* Reset watchdog for next transmission. */
+ if (lp->tx_n_in_use > 0) {
+ /* set timer to expire in WATCHDOG_JIFFIES */
+ lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
+ add_timer(&lp->watchdog);
+ }
+ restore_flags(flags);
+
#ifdef DEBUG_INTERRUPT_TRACE
- printk(KERN_DEBUG "%s: <-wavelan_watchdog()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wavelan_watchdog()\n", dev->name);
#endif
}
@@ -3930,56 +3838,55 @@ wavelan_watchdog(u_long a)
* Configure and start up the WaveLAN PCMCIA adaptor.
* Called by NET3 when it "opens" the device.
*/
-static int
-wavelan_open(device * dev)
+static int wavelan_open(device * dev)
{
- u_long x;
+ unsigned long flags;
#ifdef DEBUG_CALLBACK_TRACE
- printk(KERN_DEBUG "%s: ->wavelan_open(dev=0x%x)\n", dev->name,
- (unsigned int) dev);
+ printk(KERN_DEBUG "%s: ->wavelan_open(dev=0x%x)\n", dev->name,
+ (unsigned int) dev);
#endif
- /* Check irq */
- if(dev->irq == 0)
- {
+ /* Check irq */
+ if (dev->irq == 0) {
#ifdef DEBUG_CONFIG_ERROR
- printk(KERN_WARNING "%s: wavelan_open(): no IRQ\n", dev->name);
+ printk(KERN_WARNING "%s: wavelan_open(): no IRQ\n",
+ dev->name);
#endif
- return -ENXIO;
- }
+ return -ENXIO;
+ }
- if(request_irq(dev->irq, &wavelan_interrupt, 0, "WaveLAN", dev) != 0)
- {
+ if (request_irq(dev->irq, &wavelan_interrupt, 0, "WaveLAN", dev) != 0)
+ {
#ifdef DEBUG_CONFIG_ERROR
- printk(KERN_WARNING "%s: wavelan_open(): invalid IRQ\n", dev->name);
+ printk(KERN_WARNING "%s: wavelan_open(): invalid IRQ\n",
+ dev->name);
#endif
- return -EAGAIN;
- }
-
- x = wv_splhi();
- if(wv_hw_reset(dev) != -1)
- {
- dev->interrupt = 0;
- dev->start = 1;
- }
- else
- {
- free_irq(dev->irq, dev);
+ return -EAGAIN;
+ }
+
+ save_flags(flags);
+ cli();
+
+ if (wv_hw_reset(dev) != -1) {
+ netif_start_queue(dev);
+ } else {
+ free_irq(dev->irq, dev);
#ifdef DEBUG_CONFIG_ERROR
- printk(KERN_INFO "%s: wavelan_open(): impossible to start the card\n",
- dev->name);
+ printk(KERN_INFO
+ "%s: wavelan_open(): impossible to start the card\n",
+ dev->name);
#endif
- return -EAGAIN;
- }
- wv_splx(x);
-
- MOD_INC_USE_COUNT;
+ return -EAGAIN;
+ }
+ restore_flags(flags);
+
+ MOD_INC_USE_COUNT;
#ifdef DEBUG_CALLBACK_TRACE
- printk(KERN_DEBUG "%s: <-wavelan_open()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wavelan_open()\n", dev->name);
#endif
- return 0;
+ return 0;
}
/*------------------------------------------------------------------*/
@@ -3987,40 +3894,34 @@ wavelan_open(device * dev)
* Shut down the WaveLAN ISA card.
* Called by NET3 when it "closes" the device.
*/
-static int
-wavelan_close(device * dev)
+static int wavelan_close(device * dev)
{
- net_local * lp = (net_local *)dev->priv;
+ net_local *lp = (net_local *) dev->priv;
#ifdef DEBUG_CALLBACK_TRACE
- printk(KERN_DEBUG "%s: ->wavelan_close(dev=0x%x)\n", dev->name,
- (unsigned int) dev);
+ printk(KERN_DEBUG "%s: ->wavelan_close(dev=0x%x)\n", dev->name,
+ (unsigned int) dev);
#endif
- /* Don't do the job twice. */
- if(dev->start == 0)
- return 0;
-
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue(dev);
- /* If watchdog was activated, kill it! */
- if(lp->watchdog.prev != (timer_list *) NULL)
- del_timer(&lp->watchdog);
+ /* If watchdog was activated, kill it! */
+ if (lp->watchdog.prev != (timer_list *) NULL)
+ del_timer(&lp->watchdog);
- /*
- * Flush the Tx and disable Rx.
- */
- wv_82586_stop(dev);
+ /*
+ * Flush the Tx and disable Rx.
+ */
+ wv_82586_stop(dev);
- free_irq(dev->irq, dev);
+ free_irq(dev->irq, dev);
- MOD_DEC_USE_COUNT;
+ MOD_DEC_USE_COUNT;
#ifdef DEBUG_CALLBACK_TRACE
- printk(KERN_DEBUG "%s: <-wavelan_close()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wavelan_close()\n", dev->name);
#endif
- return 0;
+ return 0;
}
/*------------------------------------------------------------------*/
@@ -4029,113 +3930,111 @@ wavelan_close(device * dev)
* device structure
* (called by wavelan_probe() and via init_module()).
*/
-static int __init
-wavelan_config(device * dev)
+static int __init wavelan_config(device * dev)
{
- u_long ioaddr = dev->base_addr;
- u_char irq_mask;
- int irq;
- net_local * lp;
+ unsigned long ioaddr = dev->base_addr;
+ u8 irq_mask;
+ int irq;
+ net_local *lp;
#ifdef DEBUG_CALLBACK_TRACE
- printk(KERN_DEBUG "%s: ->wavelan_config(dev=0x%x, ioaddr=0x%x)\n", dev->name,
- (unsigned int)dev, ioaddr);
+ printk(KERN_DEBUG "%s: ->wavelan_config(dev=0x%x, ioaddr=0x%x)\n",
+ dev->name, (unsigned int) dev, ioaddr);
#endif
- /* Check IRQ argument on command line. */
- if(dev->irq != 0)
- {
- irq_mask = wv_irq_to_psa(dev->irq);
+ /* Check IRQ argument on command line. */
+ if (dev->irq != 0) {
+ irq_mask = wv_irq_to_psa(dev->irq);
- if(irq_mask == 0)
- {
+ if (irq_mask == 0) {
#ifdef DEBUG_CONFIG_ERROR
- printk(KERN_WARNING "%s: wavelan_config(): invalid IRQ %d ignored.\n",
- dev->name, dev->irq);
+ printk(KERN_WARNING
+ "%s: wavelan_config(): invalid IRQ %d ignored.\n",
+ dev->name, dev->irq);
#endif
- dev->irq = 0;
- }
- else
- {
+ dev->irq = 0;
+ } else {
#ifdef DEBUG_CONFIG_INFO
- printk(KERN_DEBUG "%s: wavelan_config(): changing IRQ to %d\n",
- dev->name, dev->irq);
+ printk(KERN_DEBUG
+ "%s: wavelan_config(): changing IRQ to %d\n",
+ dev->name, dev->irq);
#endif
- psa_write(ioaddr, HACR_DEFAULT,
- psaoff(0, psa_int_req_no), &irq_mask, 1);
- /* update the Wavelan checksum */
- update_psa_checksum(dev, ioaddr, HACR_DEFAULT);
- wv_hacr_reset(ioaddr);
+ psa_write(ioaddr, HACR_DEFAULT,
+ psaoff(0, psa_int_req_no), &irq_mask, 1);
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev, ioaddr, HACR_DEFAULT);
+ wv_hacr_reset(ioaddr);
+ }
}
- }
- psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_int_req_no), &irq_mask, 1);
- if((irq = wv_psa_to_irq(irq_mask)) == -1)
- {
+ psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_int_req_no),
+ &irq_mask, 1);
+ if ((irq = wv_psa_to_irq(irq_mask)) == -1) {
#ifdef DEBUG_CONFIG_ERROR
- printk(KERN_INFO "%s: wavelan_config(): could not wavelan_map_irq(%d).\n",
- dev->name, irq_mask);
+ printk(KERN_INFO
+ "%s: wavelan_config(): could not wavelan_map_irq(%d).\n",
+ dev->name, irq_mask);
#endif
- return EAGAIN;
- }
-
- dev->irq = irq;
-
- request_region(ioaddr, sizeof(ha_t), "wavelan");
-
- dev->mem_start = 0x0000;
- dev->mem_end = 0x0000;
- dev->if_port = 0;
-
- /* Initialize device structures */
- dev->priv = kmalloc(sizeof(net_local), GFP_KERNEL);
- if(dev->priv == NULL)
- return -ENOMEM;
- memset(dev->priv, 0x00, sizeof(net_local));
- lp = (net_local *)dev->priv;
-
- /* Back link to the device structure. */
- lp->dev = dev;
- /* Add the device at the beginning of the linked list. */
- lp->next = wavelan_list;
- wavelan_list = lp;
-
- lp->hacr = HACR_DEFAULT;
-
- lp->watchdog.function = wavelan_watchdog;
- lp->watchdog.data = (unsigned long) dev;
- lp->promiscuous = 0;
- lp->mc_count = 0;
-
- /*
- * Fill in the fields of the device structure
- * with generic Ethernet values.
- */
- ether_setup(dev);
-
- dev->open = wavelan_open;
- dev->stop = wavelan_close;
- dev->hard_start_xmit = wavelan_packet_xmit;
- dev->get_stats = wavelan_get_stats;
- dev->set_multicast_list = &wavelan_set_multicast_list;
+ return EAGAIN;
+ }
+
+ dev->irq = irq;
+
+ request_region(ioaddr, sizeof(ha_t), "wavelan");
+
+ dev->mem_start = 0x0000;
+ dev->mem_end = 0x0000;
+ dev->if_port = 0;
+
+ /* Initialize device structures */
+ dev->priv = kmalloc(sizeof(net_local), GFP_KERNEL);
+ if (dev->priv == NULL)
+ return -ENOMEM;
+ memset(dev->priv, 0x00, sizeof(net_local));
+ lp = (net_local *) dev->priv;
+
+ /* Back link to the device structure. */
+ lp->dev = dev;
+ /* Add the device at the beginning of the linked list. */
+ lp->next = wavelan_list;
+ wavelan_list = lp;
+
+ lp->hacr = HACR_DEFAULT;
+
+ lp->watchdog.function = wavelan_watchdog;
+ lp->watchdog.data = (unsigned long) dev;
+ lp->promiscuous = 0;
+ lp->mc_count = 0;
+
+ /*
+ * Fill in the fields of the device structure
+ * with generic Ethernet values.
+ */
+ ether_setup(dev);
+
+ dev->open = wavelan_open;
+ dev->stop = wavelan_close;
+ dev->hard_start_xmit = wavelan_packet_xmit;
+ dev->get_stats = wavelan_get_stats;
+ dev->set_multicast_list = &wavelan_set_multicast_list;
#ifdef SET_MAC_ADDRESS
- dev->set_mac_address = &wavelan_set_mac_address;
-#endif /* SET_MAC_ADDRESS */
+ dev->set_mac_address = &wavelan_set_mac_address;
+#endif /* SET_MAC_ADDRESS */
-#ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */
- dev->do_ioctl = wavelan_ioctl;
- dev->get_wireless_stats = wavelan_get_wireless_stats;
+#ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */
+ dev->do_ioctl = wavelan_ioctl;
+ dev->get_wireless_stats = wavelan_get_wireless_stats;
#endif
- dev->mtu = WAVELAN_MTU;
+ dev->mtu = WAVELAN_MTU;
- /* Display nice information. */
- wv_init_info(dev);
+ /* Display nice information. */
+ wv_init_info(dev);
#ifdef DEBUG_CALLBACK_TRACE
- printk(KERN_DEBUG "%s: <-wavelan_config()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wavelan_config()\n", dev->name);
#endif
- return 0;
+ return 0;
}
/*------------------------------------------------------------------*/
@@ -4146,90 +4045,88 @@ wavelan_config(device * dev)
* We follow the example in drivers/net/ne.c.
* (called in "Space.c")
*/
-int __init
-wavelan_probe(device * dev)
+int __init wavelan_probe(device * dev)
{
- short base_addr;
- mac_addr mac; /* MAC address (check existence of WaveLAN) */
- int i;
- int r;
+ short base_addr;
+ mac_addr mac; /* MAC address (check existence of WaveLAN) */
+ int i;
+ int r;
#ifdef DEBUG_CALLBACK_TRACE
- printk(KERN_DEBUG "%s: ->wavelan_probe(dev=0x%x (base_addr=0x%x))\n",
- dev->name, (unsigned int)dev, (unsigned int)dev->base_addr);
+ printk(KERN_DEBUG
+ "%s: ->wavelan_probe(dev=0x%x (base_addr=0x%x))\n",
+ dev->name, (unsigned int) dev,
+ (unsigned int) dev->base_addr);
#endif
#ifdef STRUCT_CHECK
- if (wv_struct_check() != (char *) NULL)
- {
- printk(KERN_WARNING "%s: wavelan_probe(): structure/compiler botch: \"%s\"\n",
- dev->name, wv_struct_check());
- return ENODEV;
- }
-#endif /* STRUCT_CHECK */
-
- /* Check the value of the command line parameter for base address. */
- base_addr = dev->base_addr;
-
- /* Don't probe at all. */
- if(base_addr < 0)
- {
+ if (wv_struct_check() != (char *) NULL) {
+ printk(KERN_WARNING
+ "%s: wavelan_probe(): structure/compiler botch: \"%s\"\n",
+ dev->name, wv_struct_check());
+ return ENODEV;
+ }
+#endif /* STRUCT_CHECK */
+
+ /* Check the value of the command line parameter for base address. */
+ base_addr = dev->base_addr;
+
+ /* Don't probe at all. */
+ if (base_addr < 0) {
#ifdef DEBUG_CONFIG_ERROR
- printk(KERN_WARNING "%s: wavelan_probe(): invalid base address\n",
- dev->name);
+ printk(KERN_WARNING
+ "%s: wavelan_probe(): invalid base address\n",
+ dev->name);
#endif
- return ENXIO;
- }
-
- /* Check a single specified location. */
- if(base_addr > 0x100)
- {
- /* Check if there is something at this base address */
- if((r = wv_check_ioaddr(base_addr, mac)) == 0)
- {
- memcpy(dev->dev_addr, mac, 6); /* Copy MAC address. */
- r = wavelan_config(dev);
+ return ENXIO;
}
+ /* Check a single specified location. */
+ if (base_addr > 0x100) {
+ /* Check if there is something at this base address */
+ if ((r = wv_check_ioaddr(base_addr, mac)) == 0) {
+ memcpy(dev->dev_addr, mac, 6); /* Copy MAC address. */
+ r = wavelan_config(dev);
+ }
#ifdef DEBUG_CONFIG_INFO
- if(r != 0)
- printk(KERN_DEBUG "%s: wavelan_probe(): no device at specified base address (0x%X) or address already in use\n",
- dev->name, base_addr);
+ if (r != 0)
+ printk(KERN_DEBUG
+ "%s: wavelan_probe(): no device at specified base address (0x%X) or address already in use\n",
+ dev->name, base_addr);
#endif
#ifdef DEBUG_CALLBACK_TRACE
- printk(KERN_DEBUG "%s: <-wavelan_probe()\n", dev->name);
+ printk(KERN_DEBUG "%s: <-wavelan_probe()\n", dev->name);
#endif
- return r;
- }
-
- /* Scan all possible addresses of the WaveLAN hardware. */
- for(i = 0; i < NELS(iobase); i++)
- {
- /* Check whether there is something at this base address. */
- if(wv_check_ioaddr(iobase[i], mac) == 0)
- {
- dev->base_addr = iobase[i]; /* Copy base address. */
- memcpy(dev->dev_addr, mac, 6); /* Copy MAC address. */
- if(wavelan_config(dev) == 0)
- {
+ return r;
+ }
+
+ /* Scan all possible addresses of the WaveLAN hardware. */
+ for (i = 0; i < NELS(iobase); i++) {
+ /* Check whether there is something at this base address. */
+ if (wv_check_ioaddr(iobase[i], mac) == 0) {
+ dev->base_addr = iobase[i]; /* Copy base address. */
+ memcpy(dev->dev_addr, mac, 6); /* Copy MAC address. */
+ if (wavelan_config(dev) == 0) {
#ifdef DEBUG_CALLBACK_TRACE
- printk(KERN_DEBUG "%s: <-wavelan_probe()\n", dev->name);
+ printk(KERN_DEBUG
+ "%s: <-wavelan_probe()\n",
+ dev->name);
#endif
- return 0;
- }
+ return 0;
+ }
+ }
}
- }
- /* We may have touched base_addr. Another driver may not like it. */
- dev->base_addr = base_addr;
+ /* We may have touched base_addr. Another driver may not like it. */
+ dev->base_addr = base_addr;
#ifdef DEBUG_CONFIG_INFO
- printk(KERN_DEBUG "%s: wavelan_probe(): no device found\n",
- dev->name);
+ printk(KERN_DEBUG "%s: wavelan_probe(): no device found\n",
+ dev->name);
#endif
- return ENODEV;
+ return ENODEV;
}
/****************************** MODULE ******************************/
@@ -4243,120 +4140,115 @@ wavelan_probe(device * dev)
* Insertion of the module
* I'm now quite proud of the multi-device support.
*/
-int
-init_module(void)
+int init_module(void)
{
- mac_addr mac; /* MAC address (check WaveLAN existence) */
- int ret = -EIO; /* Return error if no cards found */
- int i;
+ mac_addr mac; /* MAC address (check WaveLAN existence) */
+ int ret = -EIO; /* Return error if no cards found */
+ int i;
#ifdef DEBUG_MODULE_TRACE
- printk(KERN_DEBUG "-> init_module()\n");
+ printk(KERN_DEBUG "-> init_module()\n");
#endif
- /* If probing is asked */
- if(io[0] == 0)
- {
+ /* If probing is asked */
+ if (io[0] == 0) {
#ifdef DEBUG_CONFIG_ERROR
- printk(KERN_WARNING "WaveLAN init_module(): doing device probing (bad !)\n");
- printk(KERN_WARNING "Specify base addresses while loading module to correct the problem\n");
+ printk(KERN_WARNING
+ "WaveLAN init_module(): doing device probing (bad !)\n");
+ printk(KERN_WARNING
+ "Specify base addresses while loading module to correct the problem\n");
#endif
- /* Copy the basic set of address to be probed. */
- for(i = 0; i < NELS(iobase); i++)
- io[i] = iobase[i];
- }
+ /* Copy the basic set of address to be probed. */
+ for (i = 0; i < NELS(iobase); i++)
+ io[i] = iobase[i];
+ }
- /* Loop on all possible base addresses. */
- i = -1;
- while((io[++i] != 0) && (i < NELS(io)))
- {
- /* Check if there is something at this base address. */
- if(wv_check_ioaddr(io[i], mac) == 0)
- {
- device * dev;
-
- /* Create device and set basic arguments. */
- dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
- if(dev==NULL)
- {
- ret = -ENOMEM;
- break;
- }
- memset(dev, 0x00, sizeof(struct net_device));
- dev->name = name[i];
- dev->base_addr = io[i];
- dev->irq = irq[i];
- dev->init = &wavelan_config;
- memcpy(dev->dev_addr, mac, 6); /* Copy MAC address. */
-
- /* Try to create the device. */
- if(register_netdev(dev) != 0)
- {
- /* Deallocate everything. */
- /* Note: if dev->priv is mallocated, there is no way to fail. */
- kfree_s(dev, sizeof(struct net_device));
- }
- else
- {
- /* If at least one device OK, we do not fail */
- ret = 0;
- }
- } /* if there is something at the address */
- } /* Loop on all addresses. */
+ /* Loop on all possible base addresses. */
+ i = -1;
+ while ((io[++i] != 0) && (i < NELS(io))) {
+ /* Check if there is something at this base address. */
+ if (wv_check_ioaddr(io[i], mac) == 0) {
+ device *dev;
+
+ /* Create device and set basic arguments. */
+ dev =
+ kmalloc(sizeof(struct net_device), GFP_KERNEL);
+ if (dev == NULL) {
+ ret = -ENOMEM;
+ break;
+ }
+ memset(dev, 0x00, sizeof(struct net_device));
+ dev->name = name[i];
+ dev->base_addr = io[i];
+ dev->irq = irq[i];
+ dev->init = &wavelan_config;
+ memcpy(dev->dev_addr, mac, 6); /* Copy MAC address. */
+
+ /* Try to create the device. */
+ if (register_netdev(dev) != 0) {
+ /* Deallocate everything. */
+ /* Note: if dev->priv is mallocated, there is no way to fail. */
+ kfree_s(dev, sizeof(struct net_device));
+ } else {
+ /* If at least one device OK, we do not fail */
+ ret = 0;
+ }
+ } /* if there is something at the address */
+ } /* Loop on all addresses. */
#ifdef DEBUG_CONFIG_ERROR
- if(wavelan_list == (net_local *) NULL)
- printk(KERN_WARNING "WaveLAN init_module(): no device found\n");
+ if (wavelan_list == (net_local *) NULL)
+ printk(KERN_WARNING
+ "WaveLAN init_module(): no device found\n");
#endif
#ifdef DEBUG_MODULE_TRACE
- printk(KERN_DEBUG "<- init_module()\n");
+ printk(KERN_DEBUG "<- init_module()\n");
#endif
- return ret;
+ return ret;
}
/*------------------------------------------------------------------*/
/*
* Removal of the module
*/
-void
-cleanup_module(void)
+void cleanup_module(void)
{
#ifdef DEBUG_MODULE_TRACE
- printk(KERN_DEBUG "-> cleanup_module()\n");
+ printk(KERN_DEBUG "-> cleanup_module()\n");
#endif
- /* Loop on all devices and release them. */
- while(wavelan_list != (net_local *) NULL)
- {
- device * dev = wavelan_list->dev;
+ /* Loop on all devices and release them. */
+ while (wavelan_list != (net_local *) NULL) {
+ device *dev = wavelan_list->dev;
#ifdef DEBUG_CONFIG_INFO
- printk(KERN_DEBUG "%s: cleanup_module(): removing device at 0x%x\n",
- dev->name, (unsigned int) dev);
+ printk(KERN_DEBUG
+ "%s: cleanup_module(): removing device at 0x%x\n",
+ dev->name, (unsigned int) dev);
#endif
- /* Release the ioport region. */
- release_region(dev->base_addr, sizeof(ha_t));
+ /* Release the ioport region. */
+ release_region(dev->base_addr, sizeof(ha_t));
- /* Definitely remove the device. */
- unregister_netdev(dev);
+ /* Definitely remove the device. */
+ unregister_netdev(dev);
- /* Unlink the device. */
- wavelan_list = wavelan_list->next;
+ /* Unlink the device. */
+ wavelan_list = wavelan_list->next;
- /* Free pieces. */
- kfree_s(dev->priv, sizeof(struct net_local));
- kfree_s(dev, sizeof(struct net_device));
- }
+ /* Free pieces. */
+ kfree_s(dev->priv, sizeof(struct net_local));
+ kfree_s(dev, sizeof(struct net_device));
+ }
#ifdef DEBUG_MODULE_TRACE
- printk(KERN_DEBUG "<- cleanup_module()\n");
+ printk(KERN_DEBUG "<- cleanup_module()\n");
#endif
}
-#endif /* MODULE */
+#endif /* MODULE */
/*
* This software may only be used and distributed
@@ -4379,7 +4271,7 @@ cleanup_module(void)
*
* Thanks go also to:
* James Ashton (jaa101@syseng.anu.edu.au),
- * Alan Cox (iialan@iiit.swan.ac.uk),
+ * Alan Cox (alan@redhat.com),
* Allan Creighton (allanc@cs.usyd.edu.au),
* Matthew Geier (matthew@cs.usyd.edu.au),
* Remo di Giovanni (remo@cs.usyd.edu.au),
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index 37cf755ed..a907847c0 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -1,6 +1,6 @@
/* yellowfin.c: A Packet Engines G-NIC ethernet driver for linux. */
/*
- Written 1997-1998 by Donald Becker.
+ Written 1997-1999 by Donald Becker.
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
@@ -17,13 +17,13 @@
*/
static const char *version =
-"yellowfin.c:v1.02 7/26/98 Written by Donald Becker, becker@cesdis.edu\n"
+"yellowfin.c:v1.03a 7/30/99 Written by Donald Becker, becker@cesdis.edu\n"
" http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html\n";
/* A few user-configurable values. */
+static int debug = 1;
static int max_interrupt_work = 20;
-static int min_pci_latency = 64;
static int mtu = 0;
#ifdef YF_PROTOTYPE /* Support for prototype hardware errata. */
/* System-wide count of bogus-rx frames. */
@@ -50,25 +50,37 @@ static int rx_copybreak = 0;
static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+/* Do ugly workaround for GX server chipset errata. */
+static int gx_fix = 0;
+
/* Operational parameters that are set at compile time. */
/* Keep the ring sizes a power of two for efficiency.
- Making the Tx ring too large decreases the effectiveness of channel
+ Making the Tx queue too long decreases the effectiveness of channel
bonding and packet priority.
There are no ill effects from too-large receive rings. */
#define TX_RING_SIZE 16
-#define RX_RING_SIZE 32
+#define TX_QUEUE_SIZE 12 /* Must be > 4 && <= TX_RING_SIZE */
+#define RX_RING_SIZE 64
/* Operational parameters that usually are not changed. */
/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT ((2000*HZ)/1000)
+#define TX_TIMEOUT (2*HZ)
+
+#define yellowfin_debug debug
+#if !defined(__OPTIMIZE__) || !defined(__KERNEL__)
+#warning You must compile this file with the correct options!
+#warning See the last lines of the source file.
+#error You must compile this driver with "-O".
+#endif
+
+#include <linux/version.h>
#include <linux/module.h>
+#include <linux/modversions.h>
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/string.h>
#include <linux/timer.h>
-#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/malloc.h>
@@ -76,22 +88,20 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
#include <linux/pci.h>
#include <linux/init.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
-#include <asm/bitops.h>
#include <asm/unaligned.h>
+#include <asm/bitops.h>
#include <asm/io.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-#define RUN_AT(x) (jiffies + (x))
-
-#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
+/* Condensed operations for readability.
+ Compatibility defines are now in drv_compat.h */
-/* The PCI I/O space extent. */
-#define YELLOWFIN_TOTAL_SIZE 0x100
+#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
+#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
-int yellowfin_debug = 1;
/*
Theory of Operation
@@ -174,31 +184,49 @@ See Packet Engines confidential appendix (prototype chips only).
/* A few values that may be tweaked. */
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
-#ifndef PCI_VENDOR_ID_PKT_ENG /* To be defined in linux/pci.h */
-#define PCI_VENDOR_ID_PKT_ENG 0x1000 /* Hmm, likely number.. */
-#define PCI_DEVICE_ID_SYM58C885 0x0701
-#define PCI_DEVICE_ID_YELLOWFIN 0x0702
-#endif
-
/* The rest of these values should never change. */
-static void yellowfin_timer(unsigned long data);
+enum capability_flags {
+ HasMII=1, FullTxStatus=2, IsGigabit=4, HasMulticastBug=8, FullRxStatus=16,
+ HasMACAddrBug=32, /* Really only on early revs. */
+};
+
+
+/* The PCI I/O space extent. */
+#define YELLOWFIN_SIZE 0x100
+
+#define YELLOWFIN_MODULE_NAME "yellowfin"
+#define PFX YELLOWFIN_MODULE_NAME ": "
+
+
+typedef enum {
+ YELLOWFIN_GNIC,
+ SYM83C885,
+} chip_t;
-enum capability_flags {HasMII=1, FullTxStatus=2};
-static struct chip_info {
- u16 vendor_id, device_id, device_id_mask, pci_flags;
+
+struct chip_info {
const char *name;
- void (*media_timer)(unsigned long data);
- u32 chip_rev; /* As read from ChipRev, not PCI dev ID. */
int flags;
-} chip_tbl[] = {
- {0x1000, 0x0702, 0xffff, 0, "Yellowfin G-NIC Gbit Ethernet",
- yellowfin_timer, 0x0702, FullTxStatus},
- {0x1000, 0x0701, 0xffff, 0, "Symbios SYM83C885",
- yellowfin_timer, 0x0701, HasMII},
- {0,},
};
+
+/* index by chip_t */
+static struct chip_info chip_info[] = {
+ {"Yellowfin G-NIC Gigabit Ethernet",
+ FullTxStatus | IsGigabit | HasMulticastBug | HasMACAddrBug},
+ {"Symbios SYM83C885", HasMII },
+};
+
+
+static struct pci_device_id yellowfin_pci_tbl[] __devinitdata = {
+ { 0x1000, 0x0702, PCI_ANY_ID, PCI_ANY_ID, 0, 0, YELLOWFIN_GNIC },
+ { 0x1000, 0x0701, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SYM83C885 },
+ { 0, },
+};
+MODULE_DEVICE_TABLE (pci, yellowfin_pci_tbl);
+
+
/* Offsets to the Yellowfin registers. Various sizes and alignments. */
enum yellowfin_offsets {
TxCtrl=0x00, TxStatus=0x04, TxPtr=0x0C,
@@ -206,7 +234,8 @@ enum yellowfin_offsets {
RxCtrl=0x40, RxStatus=0x44, RxPtr=0x4C,
RxIntrSel=0x50, RxBranchSel=0x54, RxWaitSel=0x58,
EventStatus=0x80, IntrEnb=0x82, IntrClear=0x84, IntrStatus=0x86,
- ChipRev=0x8C, DMACtrl=0x90, Cnfg=0xA0, FrameGap0=0xA2, FrameGap1=0xA4,
+ ChipRev=0x8C, DMACtrl=0x90, TxThreshold=0x94,
+ Cnfg=0xA0, FrameGap0=0xA2, FrameGap1=0xA4,
MII_Cmd=0xA6, MII_Addr=0xA8, MII_Wr_Data=0xAA, MII_Rd_Data=0xAC,
MII_Status=0xAE,
RxDepth=0xB8, FlowCtrl=0xBC,
@@ -215,29 +244,35 @@ enum yellowfin_offsets {
EEFeature=0xF5,
};
-/* The Yellowfin Rx and Tx buffer descriptors. */
+/* The Yellowfin Rx and Tx buffer descriptors.
+ Elements are written as 32 bit for endian portability. */
struct yellowfin_desc {
- u16 request_cnt;
- u16 cmd;
+ u32 dbdma_cmd;
u32 addr;
u32 branch_addr;
- u16 result_cnt;
- u16 status;
+ u32 result_status;
};
struct tx_status_words {
+#if defined(__powerpc__)
+ u16 tx_errs;
+ u16 tx_cnt;
+ u16 paused;
+ u16 total_tx_cnt;
+#else /* Little endian chips. */
u16 tx_cnt;
u16 tx_errs;
u16 total_tx_cnt;
u16 paused;
+#endif
};
/* Bits in yellowfin_desc.cmd */
enum desc_cmd_bits {
- CMD_TX_PKT=0x1000, CMD_RX_BUF=0x2000, CMD_TXSTATUS=0x3000,
- CMD_NOP=0x6000, CMD_STOP=0x7000,
- BRANCH_ALWAYS=0x0C, INTR_ALWAYS=0x30, WAIT_ALWAYS=0x03,
- BRANCH_IFTRUE=0x04,
+ CMD_TX_PKT=0x10000000, CMD_RX_BUF=0x20000000, CMD_TXSTATUS=0x30000000,
+ CMD_NOP=0x60000000, CMD_STOP=0x70000000,
+ BRANCH_ALWAYS=0x0C0000, INTR_ALWAYS=0x300000, WAIT_ALWAYS=0x030000,
+ BRANCH_IFTRUE=0x040000,
};
/* Bits in yellowfin_desc.status */
@@ -249,6 +284,7 @@ enum intr_status_bits {
IntrTxDone=0x10, IntrTxInvalid=0x20, IntrTxPCIFault=0x40,IntrTxPCIErr=0x80,
IntrEarlyRx=0x100, IntrWakeup=0x200, };
+#define PRIV_ALIGN 31 /* Required alignment mask */
struct yellowfin_private {
/* Descriptor rings first for alignment. Tx requires a second descriptor
for status. */
@@ -256,21 +292,23 @@ struct yellowfin_private {
struct yellowfin_desc tx_ring[TX_RING_SIZE*2];
const char *product_name;
struct net_device *next_module;
+ void *priv_addr; /* Unaligned address for kfree */
/* The addresses of receive-in-place skbuffs. */
struct sk_buff* rx_skbuff[RX_RING_SIZE];
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
struct sk_buff* tx_skbuff[TX_RING_SIZE];
struct tx_status_words tx_status[TX_RING_SIZE];
struct timer_list timer; /* Media selection timer. */
- struct enet_statistics stats;
- spinlock_t lock;
+ struct net_device_stats stats;
/* Frequently used and paired value: keep adjacent for cache effect. */
- int chip_id;
+ struct pci_dev *pci_dev;
+ int chip_id, flags;
struct yellowfin_desc *rx_head_desc;
- struct tx_status_words *tx_tail_desc;
unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */
- unsigned int cur_tx, dirty_tx;
unsigned int rx_buf_sz; /* Based on MTU+slack. */
+ struct tx_status_words *tx_tail_desc;
+ unsigned int cur_tx, dirty_tx;
+ int tx_threshold;
unsigned int tx_full:1; /* The Tx queue is full. */
unsigned int full_duplex:1; /* Full-duplex operation requested. */
unsigned int duplex_lock:1;
@@ -281,19 +319,21 @@ struct yellowfin_private {
u16 advertising; /* NWay media advertisement */
unsigned char phys[2]; /* MII device addresses. */
u32 pad[4]; /* Used for 32-byte alignment */
+ spinlock_t lock;
};
+
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_DESCRIPTION("Packet Engines Yellowfin G-NIC Gigabit Ethernet driver");
MODULE_PARM(max_interrupt_work, "i");
-MODULE_PARM(min_pci_latency, "i");
MODULE_PARM(mtu, "i");
MODULE_PARM(debug, "i");
MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(gx_fix, "i");
MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-static struct net_device *yellowfin_probe1(long ioaddr, int irq, int chip_id, int options);
+
static int read_eeprom(long ioaddr, int location);
static int mdio_read(long ioaddr, int phy_id, int location);
static void mdio_write(long ioaddr, int phy_id, int location, int value);
@@ -309,197 +349,17 @@ static void yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *reg
static int yellowfin_rx(struct net_device *dev);
static void yellowfin_error(struct net_device *dev, int intr_status);
static int yellowfin_close(struct net_device *dev);
-static struct enet_statistics *yellowfin_get_stats(struct net_device *dev);
+static struct net_device_stats *yellowfin_get_stats(struct net_device *dev);
static void set_rx_mode(struct net_device *dev);
-
-
-/* A list of all installed Yellowfin devices, for removing the driver module. */
-static struct net_device *root_yellowfin_dev = NULL;
-
-static int __init yellowfin_probe(void)
-{
- int cards_found = 0;
- int pci_index = 0;
- unsigned char pci_bus, pci_device_fn;
-
- if ( ! pci_present())
- return -ENODEV;
-
- for (;pci_index < 0xff; pci_index++) {
- u8 pci_latency;
- u16 pci_command, new_command, vendor, device;
- int chip_idx;
- int irq;
- long ioaddr;
- struct pci_dev *pdev;
-
- if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
- pci_index,
- &pci_bus, &pci_device_fn)
- != PCIBIOS_SUCCESSFUL)
- break;
-
- pdev = pci_find_slot (pci_bus, pci_device_fn);
- if (!pdev) break;
- vendor = pdev->vendor;
- device = pdev->device;
-
- for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++)
- if (vendor == chip_tbl[chip_idx].vendor_id
- && (device & chip_tbl[chip_idx].device_id_mask) ==
- chip_tbl[chip_idx].device_id)
- break;
- if (chip_tbl[chip_idx].vendor_id == 0) /* Compiled out! */
- continue;
-
- {
- struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
- ioaddr = pdev->resource[0].start;
- irq = pdev->irq;
- }
-
- if (yellowfin_debug > 2)
- printk(KERN_INFO "Found %s at I/O %#lx, IRQ %d.\n",
- chip_tbl[chip_idx].name, ioaddr, irq);
-
- if (check_region(ioaddr, YELLOWFIN_TOTAL_SIZE))
- continue;
-
- pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
- new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
- if (pci_command != new_command) {
- printk(KERN_INFO " The PCI BIOS has not enabled the"
- " device at %d/%d! Updating PCI command %4.4x->%4.4x.\n",
- pci_bus, pci_device_fn, pci_command, new_command);
- pci_write_config_word(pdev, PCI_COMMAND, new_command);
- }
-
- if(yellowfin_probe1(ioaddr, irq, chip_idx, cards_found))
- {
- /* Get and check the bus-master and latency values. */
- pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
- if (pci_latency < min_pci_latency) {
- printk(KERN_INFO " PCI latency timer (CFLT) is "
- "unreasonably low at %d. Setting to %d clocks.\n",
- pci_latency, min_pci_latency);
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, min_pci_latency);
- } else if (yellowfin_debug > 1)
- printk(KERN_INFO " PCI latency timer (CFLT) is %#x.\n",
- pci_latency);
- cards_found++;
- }
- }
-
- return cards_found ? 0 : -ENODEV;
-}
-
-static struct net_device *yellowfin_probe1(long ioaddr, int irq, int chip_id, int card_idx)
-{
- static int did_version = 0; /* Already printed version info. */
- struct yellowfin_private *yp;
- int option, i;
- struct net_device *dev;
-
- if (yellowfin_debug > 0 && did_version++ == 0)
- printk(version);
-
- dev = init_etherdev(NULL, sizeof(struct yellowfin_private));
-
- printk(KERN_INFO "%s: %s type %8x at 0x%lx, ",
- dev->name, chip_tbl[chip_id].name, inl(ioaddr + ChipRev), ioaddr);
-
- if (inw(ioaddr + ChipRev) == 0x0702)
- for (i = 0; i < 6; i++)
- dev->dev_addr[i] = inb(ioaddr + StnAddr + i);
- else {
- int ee_offset = (read_eeprom(ioaddr, 6) == 0xff ? 0x100 : 0);
- for (i = 0; i < 6; i++)
- dev->dev_addr[i] = read_eeprom(ioaddr, ee_offset + i);
- }
- for (i = 0; i < 5; i++)
- printk("%2.2x:", dev->dev_addr[i]);
- printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
-
- /* Reset the chip. */
- outl(0x80000000, ioaddr + DMACtrl);
-
- /* We do a request_region() only to register /proc/ioports info. */
- request_region(ioaddr, YELLOWFIN_TOTAL_SIZE, dev->name);
-
- dev->base_addr = ioaddr;
- dev->irq = irq;
-
- /* Make certain the descriptor lists are aligned. */
- yp = (void *)(((long)kmalloc(sizeof(*yp), GFP_KERNEL) + 31) & ~31);
- memset(yp, 0, sizeof(*yp));
- dev->priv = yp;
-
- yp->next_module = root_yellowfin_dev;
- root_yellowfin_dev = dev;
-
- yp->chip_id = chip_id;
- yp->lock = SPIN_LOCK_UNLOCKED;
-
- option = card_idx < MAX_UNITS ? options[card_idx] : 0;
- if (dev->mem_start)
- option = dev->mem_start;
-
- /* The lower four bits are the media type. */
- if (option > 0) {
- if (option & 0x200)
- yp->full_duplex = 1;
- yp->default_port = option & 15;
- if (yp->default_port)
- yp->medialock = 1;
- }
- if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
- yp->full_duplex = 1;
-
- if (yp->full_duplex)
- yp->duplex_lock = 1;
-
- /* The Yellowfin-specific entries in the device structure. */
- dev->open = &yellowfin_open;
- dev->hard_start_xmit = &yellowfin_start_xmit;
- dev->stop = &yellowfin_close;
- dev->get_stats = &yellowfin_get_stats;
- dev->set_multicast_list = &set_rx_mode;
-#ifdef HAVE_PRIVATE_IOCTL
- dev->do_ioctl = &mii_ioctl;
-#endif
- dev->tx_timeout = yellowfin_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
-
- if (mtu)
- dev->mtu = mtu;
-
- if (chip_tbl[yp->chip_id].flags & HasMII) {
- int phy, phy_idx = 0;
- for (phy = 0; phy < 32 && phy_idx < 4; phy++) {
- int mii_status = mdio_read(ioaddr, phy, 1);
- if (mii_status != 0xffff &&
- mii_status != 0x0000) {
- yp->phys[phy_idx++] = phy;
- yp->advertising = mdio_read(ioaddr, phy, 4);
- printk(KERN_INFO "%s: MII PHY found at address %d, status "
- "0x%4.4x advertising %4.4x.\n",
- dev->name, phy, mii_status, yp->advertising);
- }
- }
- yp->mii_cnt = phy_idx;
- }
-
- return dev;
-}
-static int read_eeprom(long ioaddr, int location)
+static int __devinit read_eeprom(long ioaddr, int location)
{
- int bogus_cnt = 1000;
+ int bogus_cnt = 10000; /* Typical 33Mhz: 1050 ticks */
outb(location, ioaddr + EEAddr);
outb(0x30 | ((location >> 8) & 7), ioaddr + EECtrl);
- while ((inb(ioaddr + EEStatus) & 0x80) && --bogus_cnt > 0)
+ while ((inb(ioaddr + EEStatus) & 0x80) && --bogus_cnt > 0)
;
return inb(ioaddr + EERead);
}
@@ -577,13 +437,16 @@ static int yellowfin_open(struct net_device *dev)
/* Enable automatic generation of flow control frames, period 0xffff. */
outl(0x0030FFFF, ioaddr + FlowCtrl);
+ yp->tx_threshold = 32;
+ outl(yp->tx_threshold, ioaddr + TxThreshold);
+
if (dev->if_port == 0)
dev->if_port = yp->default_port;
- netif_start_queue(dev);
+ netif_start_queue (dev);
/* Setting the Rx mode will start the Rx process. */
- if (yp->chip_id == 0) {
+ if (yp->flags & IsGigabit) {
/* We are always in full-duplex mode with gigabit! */
yp->full_duplex = 1;
outw(0x01CF, ioaddr + Cnfg);
@@ -606,7 +469,7 @@ static int yellowfin_open(struct net_device *dev)
}
/* Set the timer to check for link beat. */
init_timer(&yp->timer);
- yp->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */
+ yp->timer.expires = jiffies + 3*HZ;
yp->timer.data = (unsigned long)dev;
yp->timer.function = &yellowfin_timer; /* timer handler */
add_timer(&yp->timer);
@@ -619,7 +482,7 @@ static void yellowfin_timer(unsigned long data)
struct net_device *dev = (struct net_device *)data;
struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
long ioaddr = dev->base_addr;
- int next_tick = 0;
+ int next_tick = 60*HZ;
if (yellowfin_debug > 3) {
printk(KERN_DEBUG "%s: Yellowfin timer tick, status %8.8x.\n",
@@ -648,10 +511,8 @@ static void yellowfin_timer(unsigned long data)
next_tick = 3*HZ;
}
- if (next_tick) {
- yp->timer.expires = RUN_AT(next_tick);
- add_timer(&yp->timer);
- }
+ yp->timer.expires = jiffies + next_tick;
+ add_timer(&yp->timer);
}
static void yellowfin_tx_timeout(struct net_device *dev)
@@ -659,34 +520,38 @@ static void yellowfin_tx_timeout(struct net_device *dev)
struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
long ioaddr = dev->base_addr;
- printk(KERN_WARNING "%s: Yellowfin transmit timed out, status %8.8x, resetting...\n",
- dev->name, inl(ioaddr));
+ printk(KERN_WARNING "%s: Yellowfin transmit timed out at %d/%d Tx "
+ "status %4.4x, Rx status %4.4x, resetting...\n",
+ dev->name, yp->cur_tx, yp->dirty_tx,
+ inl(ioaddr + TxStatus), inl(ioaddr + RxStatus));
-#ifndef __alpha__
- {
+ /* Note: these should be KERN_DEBUG. */
+ if (yellowfin_debug) {
int i;
- printk(KERN_DEBUG " Rx ring %8.8x: ", (int)yp->rx_ring);
+ printk(KERN_WARNING " Rx ring %p: ", yp->rx_ring);
for (i = 0; i < RX_RING_SIZE; i++)
- printk(" %8.8x", (unsigned int)yp->rx_ring[i].status);
- printk("\n"KERN_DEBUG" Tx ring %8.8x: ", (int)yp->tx_ring);
+ printk(" %8.8x", yp->rx_ring[i].result_status);
+ printk("\n"KERN_WARNING" Tx ring %p: ", yp->tx_ring);
for (i = 0; i < TX_RING_SIZE; i++)
- printk(" %4.4x /%4.4x", yp->tx_status[i].tx_errs, yp->tx_ring[i].status);
+ printk(" %4.4x /%8.8x", yp->tx_status[i].tx_errs,
+ yp->tx_ring[i].result_status);
printk("\n");
}
-#endif
- /* Perhaps we should reinitialize the hardware here. */
- dev->if_port = 0;
- /* Stop and restart the chip's Tx processes . */
+ /* If the hardware is found to hang regularly, we will update the code
+ to reinitialize the chip here. */
+ dev->if_port = 0;
- /* Trigger an immediate transmit demand. */
+ /* Wake the potentially-idle transmit channel. */
+ outl(0x10001000, dev->base_addr + TxCtrl);
+ if (yp->cur_tx - yp->dirty_tx < TX_QUEUE_SIZE)
+ netif_wake_queue (dev); /* Typical path */
- dev->trans_start = jiffies;
- yp->stats.tx_errors++;
- return;
+ dev->trans_start = jiffies;
+ yp->stats.tx_errors++;
+ return;
}
-
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
static void yellowfin_init_ring(struct net_device *dev)
{
@@ -695,62 +560,66 @@ static void yellowfin_init_ring(struct net_device *dev)
yp->tx_full = 0;
yp->cur_rx = yp->cur_tx = 0;
- yp->dirty_rx = yp->dirty_tx = 0;
+ yp->dirty_tx = 0;
yp->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
yp->rx_head_desc = &yp->rx_ring[0];
for (i = 0; i < RX_RING_SIZE; i++) {
- struct sk_buff *skb;
-
- yp->rx_ring[i].request_cnt = yp->rx_buf_sz;
- yp->rx_ring[i].cmd = CMD_RX_BUF | INTR_ALWAYS;
+ yp->rx_ring[i].dbdma_cmd =
+ cpu_to_le32(CMD_RX_BUF | INTR_ALWAYS | yp->rx_buf_sz);
+ yp->rx_ring[i].branch_addr = virt_to_le32desc(&yp->rx_ring[i+1]);
+ }
+ /* Mark the last entry as wrapping the ring. */
+ yp->rx_ring[i-1].branch_addr = virt_to_le32desc(&yp->rx_ring[0]);
- skb = dev_alloc_skb(yp->rx_buf_sz);
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ struct sk_buff *skb = dev_alloc_skb(yp->rx_buf_sz);
yp->rx_skbuff[i] = skb;
- if (skb) {
- skb->dev = dev; /* Mark as being used by this device. */
- skb_reserve(skb, 2); /* 16 byte align the IP header. */
- yp->rx_ring[i].addr = virt_to_bus(skb->tail);
- } else if (yp->dirty_rx == 0)
- yp->dirty_rx = (unsigned int)(0 - RX_RING_SIZE);
- yp->rx_ring[i].branch_addr = virt_to_bus(&yp->rx_ring[i+1]);
+ if (skb == NULL)
+ break;
+ skb->dev = dev; /* Mark as being used by this device. */
+ skb_reserve(skb, 2); /* 16 byte align the IP header. */
+ yp->rx_ring[i].addr = virt_to_le32desc(skb->tail);
}
- /* Mark the last entry as wrapping the ring. */
- yp->rx_ring[i-1].cmd = CMD_RX_BUF | INTR_ALWAYS | BRANCH_ALWAYS;
- yp->rx_ring[i-1].branch_addr = virt_to_bus(&yp->rx_ring[0]);
+ yp->rx_ring[i-1].dbdma_cmd = cpu_to_le32(CMD_STOP);
+ yp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
-/*#define NO_TXSTATS*/
+#define NO_TXSTATS
#ifdef NO_TXSTATS
/* In this mode the Tx ring needs only a single descriptor. */
for (i = 0; i < TX_RING_SIZE; i++) {
yp->tx_skbuff[i] = 0;
- yp->tx_ring[i].cmd = CMD_STOP;
- yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[i+1]);
+ yp->tx_ring[i].dbdma_cmd = cpu_to_le32(CMD_STOP);
+ yp->tx_ring[i].branch_addr = virt_to_le32desc(&yp->tx_ring[i+1]);
}
- yp->tx_ring[--i].cmd = CMD_STOP | BRANCH_ALWAYS; /* Wrap ring */
- yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[0]);
+ /* Wrap ring */
+ yp->tx_ring[--i].dbdma_cmd = cpu_to_le32(CMD_STOP | BRANCH_ALWAYS);
+ yp->tx_ring[i].branch_addr = virt_to_le32desc(&yp->tx_ring[0]);
#else
/* Tx ring needs a pair of descriptors, the second for the status. */
for (i = 0; i < TX_RING_SIZE*2; i++) {
yp->tx_skbuff[i/2] = 0;
- yp->tx_ring[i].cmd = CMD_STOP; /* Branch on Tx error. */
- yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[i+1]);
+ /* Branch on Tx error. */
+ yp->tx_ring[i].dbdma_cmd = cpu_to_le32(CMD_STOP);
+ yp->tx_ring[i].branch_addr = virt_to_le32desc(&yp->tx_ring[i+1]);
i++;
- if (chip_tbl[yp->chip_id].flags & FullTxStatus) {
- yp->tx_ring[i].cmd = CMD_TXSTATUS;
+ if (yp->flags & FullTxStatus) {
+ yp->tx_ring[i].dbdma_cmd =
+ cpu_to_le32(CMD_TXSTATUS | sizeof(yp->tx_status[i]));
yp->tx_ring[i].request_cnt = sizeof(yp->tx_status[i]);
- yp->tx_ring[i].addr = virt_to_bus(&yp->tx_status[i/2]);
+ yp->tx_ring[i].addr = virt_to_le32desc(&yp->tx_status[i/2]);
} else { /* Symbios chips write only tx_errs word. */
- yp->tx_ring[i].cmd = CMD_TXSTATUS | INTR_ALWAYS;
+ yp->tx_ring[i].dbdma_cmd =
+ cpu_to_le32(CMD_TXSTATUS | INTR_ALWAYS | 2);
yp->tx_ring[i].request_cnt = 2;
- yp->tx_ring[i].addr = virt_to_bus(&yp->tx_status[i/2].tx_errs);
+ yp->tx_ring[i].addr = virt_to_le32desc(&yp->tx_status[i/2].tx_errs);
}
- yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[i+1]);
+ yp->tx_ring[i].branch_addr = virt_to_le32desc(&yp->tx_ring[i+1]);
}
/* Wrap ring */
- yp->tx_ring[--i].cmd = CMD_TXSTATUS | BRANCH_ALWAYS | INTR_ALWAYS;
- yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[0]);
+ yp->tx_ring[--i].dbdma_cmd |= cpu_to_le32(BRANCH_ALWAYS | INTR_ALWAYS);
+ yp->tx_ring[i].branch_addr = virt_to_le32desc(&yp->tx_ring[0]);
#endif
yp->tx_tail_desc = &yp->tx_status[0];
return;
@@ -761,6 +630,8 @@ static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
unsigned entry;
+ netif_stop_queue (dev);
+
/* Caution: the write order is important here, set the base address
with the "ownership" bits last. */
@@ -769,34 +640,42 @@ static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev)
yp->tx_skbuff[entry] = skb;
+ if (gx_fix) { /* Note: only works for paddable protocols e.g. IP. */
+ int cacheline_end = (virt_to_bus(skb->data) + skb->len) % 32;
+ /* Fix GX chipset errata. */
+ if (cacheline_end > 24 || cacheline_end == 0)
+ skb->len += 32 - cacheline_end + 1;
+ }
#ifdef NO_TXSTATS
- yp->tx_ring[entry].request_cnt = skb->len;
- yp->tx_ring[entry].addr = virt_to_bus(skb->data);
- yp->tx_ring[entry].status = 0;
+ yp->tx_ring[entry].addr = virt_to_le32desc(skb->data);
+ yp->tx_ring[entry].result_status = 0;
if (entry >= TX_RING_SIZE-1) {
- yp->tx_ring[0].cmd = CMD_STOP; /* New stop command. */
- yp->tx_ring[TX_RING_SIZE-1].cmd = CMD_TX_PKT | BRANCH_ALWAYS;
+ /* New stop command. */
+ yp->tx_ring[0].dbdma_cmd = cpu_to_le32(CMD_STOP);
+ yp->tx_ring[TX_RING_SIZE-1].dbdma_cmd =
+ cpu_to_le32(CMD_TX_PKT|BRANCH_ALWAYS | skb->len);
} else {
- yp->tx_ring[entry+1].cmd = CMD_STOP; /* New stop command. */
- yp->tx_ring[entry].cmd = CMD_TX_PKT | BRANCH_IFTRUE;
+ yp->tx_ring[entry+1].dbdma_cmd = cpu_to_le32(CMD_STOP);
+ yp->tx_ring[entry].dbdma_cmd =
+ cpu_to_le32(CMD_TX_PKT | BRANCH_IFTRUE | skb->len);
}
yp->cur_tx++;
#else
yp->tx_ring[entry<<1].request_cnt = skb->len;
- yp->tx_ring[entry<<1].addr = virt_to_bus(skb->data);
+ yp->tx_ring[entry<<1].addr = virt_to_le32desc(skb->data);
/* The input_last (status-write) command is constant, but we must rewrite
the subsequent 'stop' command. */
yp->cur_tx++;
{
unsigned next_entry = yp->cur_tx % TX_RING_SIZE;
- yp->tx_ring[next_entry<<1].cmd = CMD_STOP;
+ yp->tx_ring[next_entry<<1].dbdma_cmd = cpu_to_le32(CMD_STOP);
}
/* Final step -- overwrite the old 'stop' command. */
- yp->tx_ring[entry<<1].cmd =
- (entry % 6) == 0 ? CMD_TX_PKT | INTR_ALWAYS | BRANCH_IFTRUE :
- CMD_TX_PKT | BRANCH_IFTRUE;
+ yp->tx_ring[entry<<1].dbdma_cmd =
+ cpu_to_le32( ((entry % 6) == 0 ? CMD_TX_PKT|INTR_ALWAYS|BRANCH_IFTRUE :
+ CMD_TX_PKT | BRANCH_IFTRUE) | skb->len);
#endif
/* Non-x86 Todo: explicitly flush cache lines here. */
@@ -804,8 +683,8 @@ static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Wake the potentially-idle transmit channel. */
outl(0x10001000, dev->base_addr + TxCtrl);
- if (yp->cur_tx - yp->dirty_tx < TX_RING_SIZE - 1)
- netif_start_queue(dev); /* Typical path */
+ if (yp->cur_tx - yp->dirty_tx < TX_QUEUE_SIZE)
+ netif_start_queue (dev); /* Typical path */
else
yp->tx_full = 1;
dev->trans_start = jiffies;
@@ -855,20 +734,23 @@ static void yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *reg
#ifdef NO_TXSTATS
for (; yp->cur_tx - yp->dirty_tx > 0; yp->dirty_tx++) {
int entry = yp->dirty_tx % TX_RING_SIZE;
- if (yp->tx_ring[entry].status == 0)
+ if (yp->tx_ring[entry].result_status == 0)
break;
+ yp->stats.tx_bytes += yp->tx_skbuff[entry]->len;
+ yp->stats.tx_packets++;
/* Free the original skb. */
- DEV_FREE_SKB(yp->tx_skbuff[entry]);
+ dev_kfree_skb_irq(yp->tx_skbuff[entry]);
yp->tx_skbuff[entry] = 0;
- yp->stats.tx_packets++;
}
- if (yp->tx_full &&
- test_bit(LINK_STATE_XOFF, &dev->flags) &&
- yp->cur_tx - yp->dirty_tx < TX_RING_SIZE - 4) {
+ if (yp->tx_full
+ && yp->cur_tx - yp->dirty_tx < TX_QUEUE_SIZE - 4) {
/* The ring is no longer full, clear tbusy. */
yp->tx_full = 0;
- netif_wake_queue (dev);
}
+ if (yp->tx_full)
+ netif_stop_queue(dev);
+ else
+ netif_wake_queue(dev);
#else
if (intr_status & IntrTxDone
|| yp->tx_tail_desc->tx_errs) {
@@ -892,7 +774,7 @@ static void yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *reg
#endif
if (tx_errs == 0)
break; /* It still hasn't been Txed */
- if (tx_errs & 0xF8100000) {
+ if (tx_errs & 0xF810) {
/* There was an major error, log it. */
#ifndef final_version
if (yellowfin_debug > 1)
@@ -916,12 +798,12 @@ static void yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *reg
#ifdef ETHER_STATS
if (tx_errs & 0x0400) yp->stats.tx_deferred++;
#endif
+ yp->stats.tx_bytes += yp->tx_skbuff[entry]->len;
yp->stats.collisions += tx_errs & 15;
yp->stats.tx_packets++;
}
-
/* Free the original skb. */
- DEV_FREE_SKB(yp->tx_skbuff[entry]);
+ dev_kfree_skb_irq(yp->tx_skbuff[entry]);
yp->tx_skbuff[entry] = 0;
/* Mark status as empty. */
yp->tx_status[entry].tx_errs = 0;
@@ -935,13 +817,15 @@ static void yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *reg
}
#endif
- if (yp->tx_full &&
- test_bit(LINK_STATE_XOFF, &dev->flags) &&
- yp->cur_tx - dirty_tx < TX_RING_SIZE - 2) {
+ if (yp->tx_full
+ && yp->cur_tx - dirty_tx < TX_QUEUE_SIZE - 2) {
/* The ring is no longer full, clear tbusy. */
yp->tx_full = 0;
- netif_wake_queue (dev);
}
+ if (yp->tx_full)
+ netif_stop_queue(dev);
+ else
+ netif_wake_queue(dev);
yp->dirty_tx = dirty_tx;
yp->tx_tail_desc = &yp->tx_status[dirty_tx % TX_RING_SIZE];
@@ -966,15 +850,14 @@ static void yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *reg
/* Code that should never be run! Perhaps remove after testing.. */
{
static int stopit = 10;
- if ((!test_bit(LINK_STATE_START, &dev->state)) && --stopit < 0) {
+ if ((!(netif_running(dev))) && --stopit < 0) {
printk(KERN_ERR "%s: Emergency stop, looping startup interrupt.\n",
dev->name);
free_irq(irq, dev);
}
}
- spin_lock (&yp->lock);
- return;
+ spin_unlock (&yp->lock);
}
/* This routine is logically part of the interrupt handler, but separated
@@ -986,21 +869,22 @@ static int yellowfin_rx(struct net_device *dev)
int boguscnt = 20;
if (yellowfin_debug > 4) {
- printk(KERN_DEBUG " In yellowfin_rx(), entry %d status %4.4x.\n",
- entry, yp->rx_ring[entry].status);
- printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x %4.4x %4.4x.\n",
- entry, yp->rx_ring[entry].cmd,
- yp->rx_ring[entry].request_cnt, yp->rx_ring[entry].addr,
- yp->rx_ring[entry].result_cnt, yp->rx_ring[entry].status);
+ printk(KERN_DEBUG " In yellowfin_rx(), entry %d status %8.8x.\n",
+ entry, yp->rx_ring[entry].result_status);
+ printk(KERN_DEBUG " #%d desc. %8.8x %8.8x %8.8x.\n",
+ entry, yp->rx_ring[entry].dbdma_cmd, yp->rx_ring[entry].addr,
+ yp->rx_ring[entry].result_status);
}
/* If EOP is set on the next entry, it's a new packet. Send it up. */
- while (yp->rx_head_desc->status) {
+ while (yp->rx_head_desc->result_status) {
struct yellowfin_desc *desc = yp->rx_head_desc;
- u16 desc_status = desc->status;
- int data_size = desc->request_cnt - desc->result_cnt;
- u8 *buf_addr = bus_to_virt(desc->addr);
- s16 frame_status = get_unaligned((s16*)(buf_addr+data_size-2));
+ u16 desc_status = le32_to_cpu(desc->result_status) >> 16;
+ int data_size =
+ (le32_to_cpu(desc->dbdma_cmd) - le32_to_cpu(desc->result_status))
+ & 0xffff;
+ u8 *buf_addr = le32desc_to_virt(desc->addr);
+ s16 frame_status = get_unaligned((s16*)&(buf_addr[data_size - 2]));
if (yellowfin_debug > 4)
printk(KERN_DEBUG " yellowfin_rx() status was %4.4x.\n",
@@ -1011,7 +895,7 @@ static int yellowfin_rx(struct net_device *dev)
printk(KERN_WARNING "%s: Oversized Ethernet frame spanned multiple buffers,"
" status %4.4x!\n", dev->name, desc_status);
yp->stats.rx_length_errors++;
- } else if (yp->chip_id == 0 && (frame_status & 0x0038)) {
+ } else if ((yp->flags & IsGigabit) && (frame_status & 0x0038)) {
/* There was a error. */
if (yellowfin_debug > 3)
printk(KERN_DEBUG " yellowfin_rx() Rx error was %4.4x.\n",
@@ -1021,7 +905,7 @@ static int yellowfin_rx(struct net_device *dev)
if (frame_status & 0x0008) yp->stats.rx_frame_errors++;
if (frame_status & 0x0010) yp->stats.rx_crc_errors++;
if (frame_status < 0) yp->stats.rx_dropped++;
- } else if (yp->chip_id != 0 &&
+ } else if ( !(yp->flags & IsGigabit) &&
((buf_addr[data_size-1] & 0x85) || buf_addr[data_size-2] & 0xC0)) {
u8 status1 = buf_addr[data_size-2];
u8 status2 = buf_addr[data_size-1];
@@ -1031,14 +915,16 @@ static int yellowfin_rx(struct net_device *dev)
if (status2 & 0x04) yp->stats.rx_crc_errors++;
if (status2 & 0x80) yp->stats.rx_dropped++;
#ifdef YF_PROTOTYPE /* Support for prototype hardware errata. */
- } else if (memcmp(bus_to_virt(yp->rx_ring[entry].addr),
+ } else if ((yp->flags & HasMACAddrBug) &&
+ memcmp(le32desc_to_virt(yp->rx_ring[entry].addr),
dev->dev_addr, 6) != 0
- && memcmp(bus_to_virt(yp->rx_ring[entry].addr),
+ && memcmp(le32desc_to_virt(yp->rx_ring[entry].addr),
"\377\377\377\377\377\377", 6) != 0) {
- printk(KERN_WARNING "%s: Bad frame to %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
- dev->name, buf_addr[0], buf_addr[1], buf_addr[2],
- buf_addr[3], buf_addr[4], buf_addr[5]);
- bogus_rx++;
+ if (bogus_rx++ == 0)
+ printk(KERN_WARNING "%s: Bad frame to %2.2x:%2.2x:%2.2x:%2.2x:"
+ "%2.2x:%2.2x.\n",
+ dev->name, buf_addr[0], buf_addr[1], buf_addr[2],
+ buf_addr[3], buf_addr[4], buf_addr[5]);
#endif
} else {
struct sk_buff *skb;
@@ -1057,10 +943,10 @@ static int yellowfin_rx(struct net_device *dev)
if (pkt_len > rx_copybreak) {
char *temp = skb_put(skb = yp->rx_skbuff[entry], pkt_len);
#ifndef final_verison /* Remove after testing. */
- if (bus_to_virt(yp->rx_ring[entry].addr) != temp)
+ if (le32desc_to_virt(yp->rx_ring[entry].addr) != temp)
printk(KERN_WARNING "%s: Warning -- the skbuff addresses "
"do not match in yellowfin_rx: %p vs. %p / %p.\n",
- dev->name, bus_to_virt(yp->rx_ring[entry].addr),
+ dev->name, le32desc_to_virt(yp->rx_ring[entry].addr),
skb->head, temp);
#endif
yp->rx_skbuff[entry] = NULL;
@@ -1070,19 +956,19 @@ static int yellowfin_rx(struct net_device *dev)
break;
skb->dev = dev;
skb_reserve(skb, 2); /* 16 byte align the data fields */
-#if 1
- eth_copy_and_sum(skb, bus_to_virt(yp->rx_ring[entry].addr),
- pkt_len, 0);
+#if 1 || USE_IP_CSUM
+ eth_copy_and_sum(skb, yp->rx_skbuff[entry]->tail, pkt_len, 0);
skb_put(skb, pkt_len);
#else
- memcpy(skb_put(skb, pkt_len),
- bus_to_virt(yp->rx_ring[entry].addr), pkt_len);
+ memcpy(skb_put(skb, pkt_len), yp->rx_skbuff[entry]->tail,
+ pkt_len);
#endif
}
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
dev->last_rx = jiffies;
yp->stats.rx_packets++;
+ yp->stats.rx_bytes += pkt_len;
}
entry = (++yp->cur_rx) % RX_RING_SIZE;
yp->rx_head_desc = &yp->rx_ring[entry];
@@ -1090,24 +976,25 @@ static int yellowfin_rx(struct net_device *dev)
/* Refill the Rx ring buffers. */
for (; yp->cur_rx - yp->dirty_rx > 0; yp->dirty_rx++) {
- struct sk_buff *skb;
entry = yp->dirty_rx % RX_RING_SIZE;
if (yp->rx_skbuff[entry] == NULL) {
- skb = dev_alloc_skb(yp->rx_buf_sz);
+ struct sk_buff *skb = dev_alloc_skb(yp->rx_buf_sz);
if (skb == NULL)
break; /* Better luck next round. */
+ yp->rx_skbuff[entry] = skb;
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- yp->rx_ring[entry].addr = virt_to_bus(skb->tail);
- yp->rx_skbuff[entry] = skb;
+ yp->rx_ring[entry].addr = virt_to_le32desc(skb->tail);
}
- yp->rx_ring[entry].cmd = CMD_STOP;
- yp->rx_ring[entry].status = 0; /* Clear complete bit. */
+ yp->rx_ring[entry].dbdma_cmd = cpu_to_le32(CMD_STOP);
+ yp->rx_ring[entry].result_status = 0; /* Clear complete bit. */
if (entry != 0)
- yp->rx_ring[entry - 1].cmd = CMD_RX_BUF | INTR_ALWAYS;
+ yp->rx_ring[entry - 1].dbdma_cmd =
+ cpu_to_le32(CMD_RX_BUF | INTR_ALWAYS | yp->rx_buf_sz);
else
- yp->rx_ring[RX_RING_SIZE - 1].cmd =
- CMD_RX_BUF | INTR_ALWAYS | BRANCH_ALWAYS;
+ yp->rx_ring[RX_RING_SIZE - 1].dbdma_cmd =
+ cpu_to_le32(CMD_RX_BUF | INTR_ALWAYS | BRANCH_ALWAYS
+ | yp->rx_buf_sz);
}
return 0;
@@ -1132,7 +1019,7 @@ static int yellowfin_close(struct net_device *dev)
struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
int i;
- netif_stop_queue(dev);
+ netif_stop_queue (dev);
if (yellowfin_debug > 1) {
printk(KERN_DEBUG "%s: Shutting down ethercard, status was Tx %4.4x Rx %4.4x Int %2.2x.\n",
@@ -1151,16 +1038,14 @@ static int yellowfin_close(struct net_device *dev)
del_timer(&yp->timer);
-#ifdef __i386__
+#if !defined(final_version) && defined(__i386__)
if (yellowfin_debug > 2) {
printk("\n"KERN_DEBUG" Tx ring at %8.8x:\n", (int)virt_to_bus(yp->tx_ring));
for (i = 0; i < TX_RING_SIZE*2; i++)
- printk(" %c #%d desc. %4.4x %4.4x %8.8x %8.8x %4.4x %4.4x.\n",
+ printk(" %c #%d desc. %8.8x %8.8x %8.8x %8.8x.\n",
inl(ioaddr + TxPtr) == (long)&yp->tx_ring[i] ? '>' : ' ',
- i, yp->tx_ring[i].cmd,
- yp->tx_ring[i].request_cnt, yp->tx_ring[i].addr,
- yp->tx_ring[i].branch_addr,
- yp->tx_ring[i].result_cnt, yp->tx_ring[i].status);
+ i, yp->tx_ring[i].dbdma_cmd, yp->tx_ring[i].addr,
+ yp->tx_ring[i].branch_addr, yp->tx_ring[i].result_status);
printk(KERN_DEBUG " Tx status %p:\n", yp->tx_status);
for (i = 0; i < TX_RING_SIZE; i++)
printk(" #%d status %4.4x %4.4x %4.4x %4.4x.\n",
@@ -1169,16 +1054,16 @@ static int yellowfin_close(struct net_device *dev)
printk("\n"KERN_DEBUG " Rx ring %8.8x:\n", (int)virt_to_bus(yp->rx_ring));
for (i = 0; i < RX_RING_SIZE; i++) {
- printk(KERN_DEBUG " %c #%d desc. %4.4x %4.4x %8.8x %4.4x %4.4x\n",
+ printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x %8.8x\n",
inl(ioaddr + RxPtr) == (long)&yp->rx_ring[i] ? '>' : ' ',
- i, yp->rx_ring[i].cmd,
- yp->rx_ring[i].request_cnt, yp->rx_ring[i].addr,
- yp->rx_ring[i].result_cnt, yp->rx_ring[i].status);
+ i, yp->rx_ring[i].dbdma_cmd, yp->rx_ring[i].addr,
+ yp->rx_ring[i].result_status);
if (yellowfin_debug > 6) {
- if (*(u8*)yp->rx_ring[i].addr != 0x69) {
+ if (get_unaligned((u8*)yp->rx_ring[i].addr) != 0x69) {
int j;
for (j = 0; j < 0x50; j++)
- printk(" %4.4x", ((u16*)yp->rx_ring[i].addr)[j]);
+ printk(" %4.4x",
+ get_unaligned(((u16*)yp->rx_ring[i].addr) + j));
printk("\n");
}
}
@@ -1190,16 +1075,16 @@ static int yellowfin_close(struct net_device *dev)
/* Free all the skbuffs in the Rx queue. */
for (i = 0; i < RX_RING_SIZE; i++) {
- yp->rx_ring[i].cmd = CMD_STOP;
+ yp->rx_ring[i].dbdma_cmd = cpu_to_le32(CMD_STOP);
yp->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */
if (yp->rx_skbuff[i]) {
- DEV_FREE_SKB(yp->rx_skbuff[i]);
+ dev_kfree_skb(yp->rx_skbuff[i]);
}
yp->rx_skbuff[i] = 0;
}
for (i = 0; i < TX_RING_SIZE; i++) {
if (yp->tx_skbuff[i])
- DEV_FREE_SKB(yp->tx_skbuff[i]);
+ dev_kfree_skb(yp->tx_skbuff[i]);
yp->tx_skbuff[i] = 0;
}
@@ -1214,7 +1099,7 @@ static int yellowfin_close(struct net_device *dev)
return 0;
}
-static struct enet_statistics *yellowfin_get_stats(struct net_device *dev)
+static struct net_device_stats *yellowfin_get_stats(struct net_device *dev)
{
struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
return &yp->stats;
@@ -1269,7 +1154,7 @@ static void set_rx_mode(struct net_device *dev)
i++, mclist = mclist->next) {
/* Due to a bug in the early chip versions, multiple filter
slots must be set for each address. */
- if (yp->chip_id == 0) {
+ if (yp->flags & HasMulticastBug) {
set_bit((ether_crc_le(3, mclist->dmi_addr) >> 3) & 0x3f,
hash_table);
set_bit((ether_crc_le(4, mclist->dmi_addr) >> 3) & 0x3f,
@@ -1305,7 +1190,7 @@ static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
return 0;
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
- if (!suser())
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
return 0;
@@ -1316,40 +1201,206 @@ static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
#endif /* HAVE_PRIVATE_IOCTL */
-/* An additional parameter that may be passed in... */
-static int debug = -1;
-
-static int __init yellowfin_init_module(void)
+static int __devinit yellowfin_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
- if (debug >= 0)
- yellowfin_debug = debug;
+ struct net_device *dev;
+ struct yellowfin_private *yp;
+ int option, i, irq;
+ int flags, chip_idx;
+ static int find_cnt = 0;
+ long ioaddr;
+
+ chip_idx = ent->driver_data;
+ flags = chip_info[chip_idx].flags;
+
+ dev = init_etherdev(NULL, 0);
+ if (!dev) {
+ printk (KERN_ERR PFX "cannot allocate ethernet device\n");
+ return -ENOMEM;
+ }
+
+ dev->priv = kmalloc(sizeof(*yp) + PRIV_ALIGN, GFP_KERNEL);
+ if (!dev->priv)
+ goto err_out_free_netdev;
+ yp = (void *)(((long)dev->priv + PRIV_ALIGN) & ~PRIV_ALIGN);
+ memset(yp, 0, sizeof(*yp));
+ yp->priv_addr = dev->priv; /* store real addr for kfree */
+ dev->priv = yp; /* use aligned addr */
+
+ if (!request_region (pci_resource_start (pdev, 0),
+ YELLOWFIN_SIZE, YELLOWFIN_MODULE_NAME)) {
+ printk (KERN_ERR PFX "cannot obtain I/O port region\n");
+ goto err_out_free_priv;
+ }
+ if (!request_mem_region (pci_resource_start (pdev, 1),
+ YELLOWFIN_SIZE, YELLOWFIN_MODULE_NAME)) {
+ printk (KERN_ERR PFX "cannot obtain MMIO region\n");
+ goto err_out_free_pio_region;
+ }
+
+ pci_enable_device (pdev);
+ pci_set_master (pdev);
+
+#ifdef USE_IO_OPS
+ ioaddr = pci_resource_start (pdev, 0);
+#else
+ ioaddr = pci_resource_start (pdev, 1);
+#endif
+ irq = pdev->irq;
+
+ printk(KERN_INFO "%s: %s type %8x at 0x%lx, ",
+ dev->name, chip_info[chip_idx].name, inl(ioaddr + ChipRev), ioaddr);
+
+ if (flags & IsGigabit)
+ for (i = 0; i < 6; i++)
+ dev->dev_addr[i] = inb(ioaddr + StnAddr + i);
+ else {
+ int ee_offset = (read_eeprom(ioaddr, 6) == 0xff ? 0x100 : 0);
+ for (i = 0; i < 6; i++)
+ dev->dev_addr[i] = read_eeprom(ioaddr, ee_offset + i);
+ }
+ for (i = 0; i < 5; i++)
+ printk("%2.2x:", dev->dev_addr[i]);
+ printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
+
+ /* Reset the chip. */
+ outl(0x80000000, ioaddr + DMACtrl);
+
+ dev->base_addr = ioaddr;
+ dev->irq = irq;
+
+ pdev->driver_data = dev;
+ yp->chip_id = chip_idx;
+ yp->flags = flags;
+ yp->lock = SPIN_LOCK_UNLOCKED;
+
+ option = find_cnt < MAX_UNITS ? options[find_cnt] : 0;
+ if (dev->mem_start)
+ option = dev->mem_start;
+
+ /* The lower four bits are the media type. */
+ if (option > 0) {
+ if (option & 0x200)
+ yp->full_duplex = 1;
+ yp->default_port = option & 15;
+ if (yp->default_port)
+ yp->medialock = 1;
+ }
+ if (find_cnt < MAX_UNITS && full_duplex[find_cnt] > 0)
+ yp->full_duplex = 1;
+
+ if (yp->full_duplex)
+ yp->duplex_lock = 1;
+
+ /* The Yellowfin-specific entries in the device structure. */
+ dev->open = &yellowfin_open;
+ dev->hard_start_xmit = &yellowfin_start_xmit;
+ dev->stop = &yellowfin_close;
+ dev->get_stats = &yellowfin_get_stats;
+ dev->set_multicast_list = &set_rx_mode;
+#ifdef HAVE_PRIVATE_IOCTL
+ dev->do_ioctl = &mii_ioctl;
+#endif
+ dev->tx_timeout = yellowfin_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
+ if (mtu)
+ dev->mtu = mtu;
+
+ if (yp->flags & HasMII) {
+ int phy, phy_idx = 0;
+ for (phy = 0; phy < 32 && phy_idx < 4; phy++) {
+ int mii_status = mdio_read(ioaddr, phy, 1);
+ if (mii_status != 0xffff &&
+ mii_status != 0x0000) {
+ yp->phys[phy_idx++] = phy;
+ yp->advertising = mdio_read(ioaddr, phy, 4);
+ printk(KERN_INFO "%s: MII PHY found at address %d, status "
+ "0x%4.4x advertising %4.4x.\n",
+ dev->name, phy, mii_status, yp->advertising);
+ }
+ }
+ yp->mii_cnt = phy_idx;
+ }
- return yellowfin_probe();
+ find_cnt++;
+
+ return 0;
+
+err_out_free_pio_region:
+ release_region (pci_resource_start (pdev, 0), YELLOWFIN_SIZE);
+err_out_free_priv:
+ kfree (dev->priv);
+err_out_free_netdev:
+ unregister_netdev (dev);
+ kfree (dev);
+ return -ENODEV;
}
-static void __exit yellowfin_cleanup_module (void)
+static void __devexit yellowfin_remove_one (struct pci_dev *pdev)
{
- struct net_device *next_dev;
-
- /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
- while (root_yellowfin_dev) {
- next_dev = ((struct yellowfin_private *)root_yellowfin_dev->priv)->next_module;
- unregister_netdev(root_yellowfin_dev);
- release_region(root_yellowfin_dev->base_addr, YELLOWFIN_TOTAL_SIZE);
- kfree(root_yellowfin_dev);
- root_yellowfin_dev = next_dev;
+ struct net_device *dev = pdev->driver_data;
+ struct yellowfin_private *np;
+
+ if (!dev) {
+ printk (KERN_ERR "remove non-existent device\n");
+ return;
}
+ np = (struct yellowfin_private *) dev->priv;
+
+ unregister_netdev (dev);
+
+#ifdef USE_IO_OPS
+ release_region (dev->base_addr, YELLOWFIN_SIZE);
+#else
+ iounmap ((void *) dev->base_addr);
+ release_mem_region (dev->base_addr, YELLOWFIN_SIZE);
+#endif
+
+ if (np->priv_addr)
+ kfree (np->priv_addr);
+
+ kfree (dev);
}
-module_init(yellowfin_init_module);
-module_exit(yellowfin_cleanup_module);
+
+static struct pci_driver yellowfin_driver = {
+ name: YELLOWFIN_MODULE_NAME,
+ id_table: yellowfin_pci_tbl,
+ probe: yellowfin_init_one,
+ remove: yellowfin_remove_one,
+};
+
+
+static int __init yellowfin_init (void)
+{
+ if (debug) /* Emit version even if no cards detected. */
+ printk(KERN_INFO "%s", version);
+
+ if (pci_register_driver (&yellowfin_driver) > 0)
+ return 0;
+
+ pci_unregister_driver (&yellowfin_driver);
+ return -ENODEV;
+}
+
+
+static void __exit yellowfin_cleanup (void)
+{
+ pci_unregister_driver (&yellowfin_driver);
+}
+
+
+module_init(yellowfin_init);
+module_exit(yellowfin_exit);
/*
* Local variables:
- * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c yellowfin.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
- * compile-command-alphaLX: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -c yellowfin.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS` -fomit-frame-pointer -fno-strength-reduce -mno-fp-regs -Wa,-m21164a -DBWX_USABLE -DBWIO_ENABLED"
- * SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c yellowfin.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c yellowfin.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ * compile-command-alphaLX: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O2 -c yellowfin.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS` -fomit-frame-pointer -fno-strength-reduce -mno-fp-regs -Wa,-m21164a -DBWX_USABLE -DBWIO_ENABLED"
+ * SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c yellowfin.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
* c-indent-level: 4
* c-basic-offset: 4
* tab-width: 4
diff --git a/drivers/net/znet.c b/drivers/net/znet.c
index f48e41e7e..7ca88c26a 100644
--- a/drivers/net/znet.c
+++ b/drivers/net/znet.c
@@ -119,10 +119,13 @@ static unsigned int znet_debug = ZNET_DEBUG;
#define CMD0_STAT2 (2 << 5)
#define CMD0_STAT3 (3 << 5)
+#define TX_TIMEOUT 10
+
#define net_local znet_private
struct znet_private {
int rx_dma, tx_dma;
struct net_device_stats stats;
+ spinlock_t lock;
/* The starting, current, and end pointers for the packet buffers. */
ushort *rx_start, *rx_cur, *rx_end;
ushort *tx_start, *tx_cur, *tx_end;
@@ -190,6 +193,7 @@ static struct net_device_stats *net_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
static void hardware_init(struct net_device *dev);
static void update_stop_hit(short ioaddr, unsigned short rx_stop_offset);
+static void znet_tx_timeout (struct net_device *dev);
#ifdef notdef
static struct sigaction znet_sigaction = { &znet_interrupt, 0, 0, NULL, };
@@ -245,6 +249,7 @@ int __init znet_probe(struct net_device *dev)
dev->priv = (void *) &zn;
zn.rx_dma = netinfo->dma1;
zn.tx_dma = netinfo->dma2;
+ zn.lock = SPIN_LOCK_UNLOCKED;
/* These should never fail. You can't add devices to a sealed box! */
if (request_irq(dev->irq, &znet_interrupt, 0, "ZNet", dev)
@@ -275,6 +280,8 @@ int __init znet_probe(struct net_device *dev)
dev->stop = &znet_close;
dev->get_stats = net_get_stats;
dev->set_multicast_list = &set_multicast_list;
+ dev->tx_timeout = znet_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
/* Fill in the 'dev' with ethernet-generic values. */
ether_setup(dev);
@@ -306,41 +313,47 @@ static int znet_open(struct net_device *dev)
printk(KERN_WARNING "%s: Problem turning on the transceiver power.\n",
dev->name);
- dev->tbusy = 0;
- dev->interrupt = 0;
hardware_init(dev);
- dev->start = 1;
+ netif_start_queue (dev);
return 0;
}
+
+static void znet_tx_timeout (struct net_device *dev)
+{
+ int ioaddr = dev->base_addr;
+ ushort event, tx_status, rx_offset, state;
+
+ outb (CMD0_STAT0, ioaddr);
+ event = inb (ioaddr);
+ outb (CMD0_STAT1, ioaddr);
+ tx_status = inw (ioaddr);
+ outb (CMD0_STAT2, ioaddr);
+ rx_offset = inw (ioaddr);
+ outb (CMD0_STAT3, ioaddr);
+ state = inb (ioaddr);
+ printk (KERN_WARNING "%s: transmit timed out, status %02x %04x %04x %02x,"
+ " resetting.\n", dev->name, event, tx_status, rx_offset, state);
+ if (tx_status == 0x0400)
+ printk (KERN_WARNING "%s: Tx carrier error, check transceiver cable.\n",
+ dev->name);
+ outb (CMD0_RESET, ioaddr);
+ hardware_init (dev);
+ netif_start_queue (dev);
+}
+
static int znet_send_packet(struct sk_buff *skb, struct net_device *dev)
{
int ioaddr = dev->base_addr;
struct net_local *lp = (struct net_local *)dev->priv;
+ unsigned long flags;
if (znet_debug > 4)
- printk(KERN_DEBUG "%s: ZNet_send_packet(%ld).\n", dev->name, dev->tbusy);
-
- /* Transmitter timeout, likely just recovery after suspending the machine. */
- if (dev->tbusy) {
- ushort event, tx_status, rx_offset, state;
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 10)
- return 1;
- outb(CMD0_STAT0, ioaddr); event = inb(ioaddr);
- outb(CMD0_STAT1, ioaddr); tx_status = inw(ioaddr);
- outb(CMD0_STAT2, ioaddr); rx_offset = inw(ioaddr);
- outb(CMD0_STAT3, ioaddr); state = inb(ioaddr);
- printk(KERN_WARNING "%s: transmit timed out, status %02x %04x %04x %02x,"
- " resetting.\n", dev->name, event, tx_status, rx_offset, state);
- if (tx_status == 0x0400)
- printk(KERN_WARNING "%s: Tx carrier error, check transceiver cable.\n",
- dev->name);
- outb(CMD0_RESET, ioaddr);
- hardware_init(dev);
- }
+ printk(KERN_DEBUG "%s: ZNet_send_packet.\n", dev->name);
+ netif_stop_queue (dev);
+
/* Check that the part hasn't reset itself, probably from suspend. */
outb(CMD0_STAT0, ioaddr);
if (inw(ioaddr) == 0x0010
@@ -348,11 +361,7 @@ static int znet_send_packet(struct sk_buff *skb, struct net_device *dev)
&& inw(ioaddr) == 0x0010)
hardware_init(dev);
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
- else {
+ if (1) {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
unsigned char *buf = (void *)skb->data;
ushort *tx_link = zn.tx_cur - 1;
@@ -385,13 +394,18 @@ static int znet_send_packet(struct sk_buff *skb, struct net_device *dev)
zn.tx_cur += rnd_len;
}
*zn.tx_cur++ = 0;
- cli(); {
+
+ spin_lock_irqsave(&lp->lock, flags);
+ {
*tx_link = CMD0_TRANSMIT + CMD0_CHNL_1;
/* Is this always safe to do? */
outb(CMD0_TRANSMIT + CMD0_CHNL_1,ioaddr);
- } sti();
+ }
+ spin_unlock_irqrestore (&lp->lock, flags);
dev->trans_start = jiffies;
+ netif_start_queue (dev);
+
if (znet_debug > 4)
printk(KERN_DEBUG "%s: Transmitter queued, length %d.\n", dev->name, length);
}
@@ -403,6 +417,7 @@ static int znet_send_packet(struct sk_buff *skb, struct net_device *dev)
static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct net_device *dev = dev_id;
+ struct net_local *lp = (struct net_local *)dev->priv;
int ioaddr;
int boguscnt = 20;
@@ -411,7 +426,8 @@ static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs)
return;
}
- dev->interrupt = 1;
+ spin_lock (&lp->lock);
+
ioaddr = dev->base_addr;
outb(CMD0_STAT0, ioaddr);
@@ -432,7 +448,6 @@ static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs)
break;
if ((status & 0x0F) == 4) { /* Transmit done. */
- struct net_local *lp = (struct net_local *)dev->priv;
int tx_status;
outb(CMD0_STAT1, ioaddr);
tx_status = inw(ioaddr);
@@ -449,8 +464,7 @@ static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs)
if ((tx_status | 0x0760) != 0x0760)
lp->stats.tx_errors++;
}
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_wake_queue (dev);
}
if ((status & 0x40)
@@ -461,7 +475,8 @@ static void znet_interrupt(int irq, void *dev_id, struct pt_regs * regs)
outb(CMD0_ACK,ioaddr);
} while (boguscnt--);
- dev->interrupt = 0;
+ spin_unlock (&lp->lock);
+
return;
}
@@ -594,8 +609,7 @@ static int znet_close(struct net_device *dev)
unsigned long flags;
int ioaddr = dev->base_addr;
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue (dev);
outb(CMD0_RESET, ioaddr); /* CMD0_RESET */
@@ -728,7 +742,7 @@ static void hardware_init(struct net_device *dev)
update_stop_hit(ioaddr, 8192);
if (znet_debug > 1) printk("enabling Rx.\n");
outb(CMD0_Rx_ENABLE+CMD0_CHNL_0, ioaddr);
- dev->tbusy = 0;
+ netif_start_queue (dev);
}
static void update_stop_hit(short ioaddr, unsigned short rx_stop_offset)