aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/tokenring
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/net/tokenring
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/net/tokenring')
-rw-r--r--drivers/net/tokenring/3c359.c1830
-rw-r--r--drivers/net/tokenring/3c359.h290
-rw-r--r--drivers/net/tokenring/3c359_microcode.h1581
-rw-r--r--drivers/net/tokenring/Kconfig186
-rw-r--r--drivers/net/tokenring/Makefile15
-rw-r--r--drivers/net/tokenring/abyss.c481
-rw-r--r--drivers/net/tokenring/abyss.h58
-rw-r--r--drivers/net/tokenring/ibmtr.c1987
-rw-r--r--drivers/net/tokenring/lanstreamer.c2011
-rw-r--r--drivers/net/tokenring/lanstreamer.h358
-rw-r--r--drivers/net/tokenring/madgemc.c800
-rw-r--r--drivers/net/tokenring/madgemc.h70
-rw-r--r--drivers/net/tokenring/olympic.c1786
-rw-r--r--drivers/net/tokenring/olympic.h322
-rw-r--r--drivers/net/tokenring/proteon.c432
-rw-r--r--drivers/net/tokenring/skisa.c442
-rw-r--r--drivers/net/tokenring/smctr.c5742
-rw-r--r--drivers/net/tokenring/smctr.h1588
-rw-r--r--drivers/net/tokenring/smctr_firmware.h979
-rw-r--r--drivers/net/tokenring/tms380tr.c2410
-rw-r--r--drivers/net/tokenring/tms380tr.h1141
-rw-r--r--drivers/net/tokenring/tmspci.c267
22 files changed, 24776 insertions, 0 deletions
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
new file mode 100644
index 00000000000..0d1dcf42177
--- /dev/null
+++ b/drivers/net/tokenring/3c359.c
@@ -0,0 +1,1830 @@
+/*
+ * 3c359.c (c) 2000 Mike Phillips (mikep@linuxtr.net) All Rights Reserved
+ *
+ * Linux driver for 3Com 3c359 Tokenlink Velocity XL PCI NIC
+ *
+ * Base Driver Olympic:
+ * Written 1999 Peter De Schrijver & Mike Phillips
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * 7/17/00 - Clean up, version number 0.9.0. Ready to release to the world.
+ *
+ * 2/16/01 - Port up to kernel 2.4.2 ready for submission into the kernel.
+ * 3/05/01 - Last clean up stuff before submission.
+ * 2/15/01 - Finally, update to new pci api.
+ *
+ * To Do:
+ */
+
+/*
+ * Technical Card Details
+ *
+ * All access to data is done with 16/8 bit transfers. The transfer
+ * method really sucks. You can only read or write one location at a time.
+ *
+ * Also, the microcode for the card must be uploaded if the card does not have
+ * the flashrom on board. This is a 28K bloat in the driver when compiled
+ * as a module.
+ *
+ * Rx is very simple, status into a ring of descriptors, dma data transfer,
+ * interrupts to tell us when a packet is received.
+ *
+ * Tx is a little more interesting. Similar scenario, descriptor and dma data
+ * transfers, but we don't have to interrupt the card to tell it another packet
+ * is ready for transmission, we are just doing simple memory writes, not io or mmio
+ * writes. The card can be set up to simply poll on the next
+ * descriptor pointer and when this value is non-zero will automatically download
+ * the next packet. The card then interrupts us when the packet is done.
+ *
+ */
+
+#define XL_DEBUG 0
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/string.h>
+#include <linux/proc_fs.h>
+#include <linux/ptrace.h>
+#include <linux/skbuff.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/trdevice.h>
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+
+#include <net/checksum.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "3c359.h"
+
+static char version[] __devinitdata =
+"3c359.c v1.2.0 2/17/01 - Mike Phillips (mikep@linuxtr.net)" ;
+
+MODULE_AUTHOR("Mike Phillips <mikep@linuxtr.net>") ;
+MODULE_DESCRIPTION("3Com 3C359 Velocity XL Token Ring Adapter Driver \n") ;
+
+/* Module paramters */
+
+/* Ring Speed 0,4,16
+ * 0 = Autosense
+ * 4,16 = Selected speed only, no autosense
+ * This allows the card to be the first on the ring
+ * and become the active monitor.
+ *
+ * WARNING: Some hubs will allow you to insert
+ * at the wrong speed.
+ *
+ * The adapter will _not_ fail to open if there are no
+ * active monitors on the ring, it will simply open up in
+ * its last known ringspeed if no ringspeed is specified.
+ */
+
+static int ringspeed[XL_MAX_ADAPTERS] = {0,} ;
+
+module_param_array(ringspeed, int, NULL, 0);
+MODULE_PARM_DESC(ringspeed,"3c359: Ringspeed selection - 4,16 or 0") ;
+
+/* Packet buffer size */
+
+static int pkt_buf_sz[XL_MAX_ADAPTERS] = {0,} ;
+
+module_param_array(pkt_buf_sz, int, NULL, 0) ;
+MODULE_PARM_DESC(pkt_buf_sz,"3c359: Initial buffer size") ;
+/* Message Level */
+
+static int message_level[XL_MAX_ADAPTERS] = {0,} ;
+
+module_param_array(message_level, int, NULL, 0) ;
+MODULE_PARM_DESC(message_level, "3c359: Level of reported messages \n") ;
+/*
+ * This is a real nasty way of doing this, but otherwise you
+ * will be stuck with 1555 lines of hex #'s in the code.
+ */
+
+#include "3c359_microcode.h"
+
+static struct pci_device_id xl_pci_tbl[] =
+{
+ {PCI_VENDOR_ID_3COM,PCI_DEVICE_ID_3COM_3C359, PCI_ANY_ID, PCI_ANY_ID, },
+ { } /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci,xl_pci_tbl) ;
+
+static int xl_init(struct net_device *dev);
+static int xl_open(struct net_device *dev);
+static int xl_open_hw(struct net_device *dev) ;
+static int xl_hw_reset(struct net_device *dev);
+static int xl_xmit(struct sk_buff *skb, struct net_device *dev);
+static void xl_dn_comp(struct net_device *dev);
+static int xl_close(struct net_device *dev);
+static void xl_set_rx_mode(struct net_device *dev);
+static irqreturn_t xl_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static struct net_device_stats * xl_get_stats(struct net_device *dev);
+static int xl_set_mac_address(struct net_device *dev, void *addr) ;
+static void xl_arb_cmd(struct net_device *dev);
+static void xl_asb_cmd(struct net_device *dev) ;
+static void xl_srb_cmd(struct net_device *dev, int srb_cmd) ;
+static void xl_wait_misr_flags(struct net_device *dev) ;
+static int xl_change_mtu(struct net_device *dev, int mtu);
+static void xl_srb_bh(struct net_device *dev) ;
+static void xl_asb_bh(struct net_device *dev) ;
+static void xl_reset(struct net_device *dev) ;
+static void xl_freemem(struct net_device *dev) ;
+
+
+/* EEProm Access Functions */
+static u16 xl_ee_read(struct net_device *dev, int ee_addr) ;
+static void xl_ee_write(struct net_device *dev, int ee_addr, u16 ee_value) ;
+
+/* Debugging functions */
+#if XL_DEBUG
+static void print_tx_state(struct net_device *dev) ;
+static void print_rx_state(struct net_device *dev) ;
+
+static void print_tx_state(struct net_device *dev)
+{
+
+ struct xl_private *xl_priv = (struct xl_private *)dev->priv ;
+ struct xl_tx_desc *txd ;
+ u8 __iomem *xl_mmio = xl_priv->xl_mmio ;
+ int i ;
+
+ printk("tx_ring_head: %d, tx_ring_tail: %d, free_ent: %d \n",xl_priv->tx_ring_head,
+ xl_priv->tx_ring_tail, xl_priv->free_ring_entries) ;
+ printk("Ring , Address , FSH , DnNextPtr, Buffer, Buffer_Len \n");
+ for (i = 0; i < 16; i++) {
+ txd = &(xl_priv->xl_tx_ring[i]) ;
+ printk("%d, %08lx, %08x, %08x, %08x, %08x \n", i, virt_to_bus(txd),
+ txd->framestartheader, txd->dnnextptr, txd->buffer, txd->buffer_length ) ;
+ }
+
+ printk("DNLISTPTR = %04x \n", readl(xl_mmio + MMIO_DNLISTPTR) );
+
+ printk("DmaCtl = %04x \n", readl(xl_mmio + MMIO_DMA_CTRL) );
+ printk("Queue status = %0x \n",netif_running(dev) ) ;
+}
+
+static void print_rx_state(struct net_device *dev)
+{
+
+ struct xl_private *xl_priv = (struct xl_private *)dev->priv ;
+ struct xl_rx_desc *rxd ;
+ u8 __iomem *xl_mmio = xl_priv->xl_mmio ;
+ int i ;
+
+ printk("rx_ring_tail: %d \n", xl_priv->rx_ring_tail) ;
+ printk("Ring , Address , FrameState , UPNextPtr, FragAddr, Frag_Len \n");
+ for (i = 0; i < 16; i++) {
+ /* rxd = (struct xl_rx_desc *)xl_priv->rx_ring_dma_addr + (i * sizeof(struct xl_rx_desc)) ; */
+ rxd = &(xl_priv->xl_rx_ring[i]) ;
+ printk("%d, %08lx, %08x, %08x, %08x, %08x \n", i, virt_to_bus(rxd),
+ rxd->framestatus, rxd->upnextptr, rxd->upfragaddr, rxd->upfraglen ) ;
+ }
+
+ printk("UPLISTPTR = %04x \n", readl(xl_mmio + MMIO_UPLISTPTR) );
+
+ printk("DmaCtl = %04x \n", readl(xl_mmio + MMIO_DMA_CTRL) );
+ printk("Queue status = %0x \n",netif_running(dev) ) ;
+}
+#endif
+
+/*
+ * Read values from the on-board EEProm. This looks very strange
+ * but you have to wait for the EEProm to get/set the value before
+ * passing/getting the next value from the nic. As with all requests
+ * on this nic it has to be done in two stages, a) tell the nic which
+ * memory address you want to access and b) pass/get the value from the nic.
+ * With the EEProm, you have to wait before and inbetween access a) and b).
+ * As this is only read at initialization time and the wait period is very
+ * small we shouldn't have to worry about scheduling issues.
+ */
+
+static u16 xl_ee_read(struct net_device *dev, int ee_addr)
+{
+ struct xl_private *xl_priv = (struct xl_private *)dev->priv ;
+ u8 __iomem *xl_mmio = xl_priv->xl_mmio ;
+
+ /* Wait for EEProm to not be busy */
+ writel(IO_WORD_READ | EECONTROL, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ while ( readw(xl_mmio + MMIO_MACDATA) & EEBUSY ) ;
+
+ /* Tell EEProm what we want to do and where */
+ writel(IO_WORD_WRITE | EECONTROL, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writew(EEREAD + ee_addr, xl_mmio + MMIO_MACDATA) ;
+
+ /* Wait for EEProm to not be busy */
+ writel(IO_WORD_READ | EECONTROL, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ while ( readw(xl_mmio + MMIO_MACDATA) & EEBUSY ) ;
+
+ /* Tell EEProm what we want to do and where */
+ writel(IO_WORD_WRITE | EECONTROL , xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writew(EEREAD + ee_addr, xl_mmio + MMIO_MACDATA) ;
+
+ /* Finally read the value from the EEProm */
+ writel(IO_WORD_READ | EEDATA , xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ return readw(xl_mmio + MMIO_MACDATA) ;
+}
+
+/*
+ * Write values to the onboard eeprom. As with eeprom read you need to
+ * set which location to write, wait, value to write, wait, with the
+ * added twist of having to enable eeprom writes as well.
+ */
+
+static void xl_ee_write(struct net_device *dev, int ee_addr, u16 ee_value)
+{
+ struct xl_private *xl_priv = (struct xl_private *)dev->priv ;
+ u8 __iomem *xl_mmio = xl_priv->xl_mmio ;
+
+ /* Wait for EEProm to not be busy */
+ writel(IO_WORD_READ | EECONTROL, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ while ( readw(xl_mmio + MMIO_MACDATA) & EEBUSY ) ;
+
+ /* Enable write/erase */
+ writel(IO_WORD_WRITE | EECONTROL, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writew(EE_ENABLE_WRITE, xl_mmio + MMIO_MACDATA) ;
+
+ /* Wait for EEProm to not be busy */
+ writel(IO_WORD_READ | EECONTROL, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ while ( readw(xl_mmio + MMIO_MACDATA) & EEBUSY ) ;
+
+ /* Put the value we want to write into EEDATA */
+ writel(IO_WORD_WRITE | EEDATA, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writew(ee_value, xl_mmio + MMIO_MACDATA) ;
+
+ /* Tell EEProm to write eevalue into ee_addr */
+ writel(IO_WORD_WRITE | EECONTROL, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writew(EEWRITE + ee_addr, xl_mmio + MMIO_MACDATA) ;
+
+ /* Wait for EEProm to not be busy, to ensure write gets done */
+ writel(IO_WORD_READ | EECONTROL, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ while ( readw(xl_mmio + MMIO_MACDATA) & EEBUSY ) ;
+
+ return ;
+}
+
+int __devinit xl_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct net_device *dev ;
+ struct xl_private *xl_priv ;
+ static int card_no = -1 ;
+ int i ;
+
+ card_no++ ;
+
+ if (pci_enable_device(pdev)) {
+ return -ENODEV ;
+ }
+
+ pci_set_master(pdev);
+
+ if ((i = pci_request_regions(pdev,"3c359"))) {
+ return i ;
+ } ;
+
+ /*
+ * Allowing init_trdev to allocate the dev->priv structure will align xl_private
+ * on a 32 bytes boundary which we need for the rx/tx descriptors
+ */
+
+ dev = alloc_trdev(sizeof(struct xl_private)) ;
+ if (!dev) {
+ pci_release_regions(pdev) ;
+ return -ENOMEM ;
+ }
+ xl_priv = dev->priv ;
+
+#if XL_DEBUG
+ printk("pci_device: %p, dev:%p, dev->priv: %p, ba[0]: %10x, ba[1]:%10x\n",
+ pdev, dev, dev->priv, (unsigned int)pdev->resource[0].start, (unsigned int)pdev->resource[1].start) ;
+#endif
+
+ dev->irq=pdev->irq;
+ dev->base_addr=pci_resource_start(pdev,0) ;
+ xl_priv->xl_card_name = pci_name(pdev);
+ xl_priv->xl_mmio=ioremap(pci_resource_start(pdev,1), XL_IO_SPACE);
+ xl_priv->pdev = pdev ;
+
+ if ((pkt_buf_sz[card_no] < 100) || (pkt_buf_sz[card_no] > 18000) )
+ xl_priv->pkt_buf_sz = PKT_BUF_SZ ;
+ else
+ xl_priv->pkt_buf_sz = pkt_buf_sz[card_no] ;
+
+ dev->mtu = xl_priv->pkt_buf_sz - TR_HLEN ;
+ xl_priv->xl_ring_speed = ringspeed[card_no] ;
+ xl_priv->xl_message_level = message_level[card_no] ;
+ xl_priv->xl_functional_addr[0] = xl_priv->xl_functional_addr[1] = xl_priv->xl_functional_addr[2] = xl_priv->xl_functional_addr[3] = 0 ;
+ xl_priv->xl_copy_all_options = 0 ;
+
+ if((i = xl_init(dev))) {
+ iounmap(xl_priv->xl_mmio) ;
+ free_netdev(dev) ;
+ pci_release_regions(pdev) ;
+ return i ;
+ }
+
+ dev->open=&xl_open;
+ dev->hard_start_xmit=&xl_xmit;
+ dev->change_mtu=&xl_change_mtu;
+ dev->stop=&xl_close;
+ dev->do_ioctl=NULL;
+ dev->set_multicast_list=&xl_set_rx_mode;
+ dev->get_stats=&xl_get_stats ;
+ dev->set_mac_address=&xl_set_mac_address ;
+ SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ pci_set_drvdata(pdev,dev) ;
+ if ((i = register_netdev(dev))) {
+ printk(KERN_ERR "3C359, register netdev failed\n") ;
+ pci_set_drvdata(pdev,NULL) ;
+ iounmap(xl_priv->xl_mmio) ;
+ free_netdev(dev) ;
+ pci_release_regions(pdev) ;
+ return i ;
+ }
+
+ printk(KERN_INFO "3C359: %s registered as: %s\n",xl_priv->xl_card_name,dev->name) ;
+
+ return 0;
+}
+
+
+static int __init xl_init(struct net_device *dev)
+{
+ struct xl_private *xl_priv = (struct xl_private *)dev->priv ;
+
+ printk(KERN_INFO "%s \n", version);
+ printk(KERN_INFO "%s: I/O at %hx, MMIO at %p, using irq %d\n",
+ xl_priv->xl_card_name, (unsigned int)dev->base_addr ,xl_priv->xl_mmio, dev->irq);
+
+ spin_lock_init(&xl_priv->xl_lock) ;
+
+ return xl_hw_reset(dev) ;
+
+}
+
+
+/*
+ * Hardware reset. This needs to be a separate entity as we need to reset the card
+ * when we change the EEProm settings.
+ */
+
+static int xl_hw_reset(struct net_device *dev)
+{
+ struct xl_private *xl_priv = (struct xl_private *)dev->priv ;
+ u8 __iomem *xl_mmio = xl_priv->xl_mmio ;
+ unsigned long t ;
+ u16 i ;
+ u16 result_16 ;
+ u8 result_8 ;
+ u16 start ;
+ int j ;
+
+ /*
+ * Reset the card. If the card has got the microcode on board, we have
+ * missed the initialization interrupt, so we must always do this.
+ */
+
+ writew( GLOBAL_RESET, xl_mmio + MMIO_COMMAND ) ;
+
+ /*
+ * Must wait for cmdInProgress bit (12) to clear before continuing with
+ * card configuration.
+ */
+
+ t=jiffies;
+ while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) {
+ schedule();
+ if(jiffies-t > 40*HZ) {
+ printk(KERN_ERR "%s: 3COM 3C359 Velocity XL card not responding to global reset.\n", dev->name);
+ return -ENODEV;
+ }
+ }
+
+ /*
+ * Enable pmbar by setting bit in CPAttention
+ */
+
+ writel( (IO_BYTE_READ | CPATTENTION), xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ result_8 = readb(xl_mmio + MMIO_MACDATA) ;
+ result_8 = result_8 | CPA_PMBARVIS ;
+ writel( (IO_BYTE_WRITE | CPATTENTION), xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(result_8, xl_mmio + MMIO_MACDATA) ;
+
+ /*
+ * Read cpHold bit in pmbar, if cleared we have got Flashrom on board.
+ * If not, we need to upload the microcode to the card
+ */
+
+ writel( (IO_WORD_READ | PMBAR),xl_mmio + MMIO_MAC_ACCESS_CMD);
+
+#if XL_DEBUG
+ printk(KERN_INFO "Read from PMBAR = %04x \n", readw(xl_mmio + MMIO_MACDATA)) ;
+#endif
+
+ if ( readw( (xl_mmio + MMIO_MACDATA)) & PMB_CPHOLD ) {
+
+ /* Set PmBar, privateMemoryBase bits (8:2) to 0 */
+
+ writel( (IO_WORD_READ | PMBAR),xl_mmio + MMIO_MAC_ACCESS_CMD);
+ result_16 = readw(xl_mmio + MMIO_MACDATA) ;
+ result_16 = result_16 & ~((0x7F) << 2) ;
+ writel( (IO_WORD_WRITE | PMBAR), xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writew(result_16,xl_mmio + MMIO_MACDATA) ;
+
+ /* Set CPAttention, memWrEn bit */
+
+ writel( (IO_BYTE_READ | CPATTENTION), xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ result_8 = readb(xl_mmio + MMIO_MACDATA) ;
+ result_8 = result_8 | CPA_MEMWREN ;
+ writel( (IO_BYTE_WRITE | CPATTENTION), xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(result_8, xl_mmio + MMIO_MACDATA) ;
+
+ /*
+ * Now to write the microcode into the shared ram
+ * The microcode must finish at position 0xFFFF, so we must subtract
+ * to get the start position for the code
+ */
+
+ start = (0xFFFF - (mc_size) + 1 ) ; /* Looks strange but ensures compiler only uses 16 bit unsigned int for this */
+
+ printk(KERN_INFO "3C359: Uploading Microcode: ");
+
+ for (i = start, j = 0; j < mc_size; i++, j++) {
+ writel(MEM_BYTE_WRITE | 0XD0000 | i, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(microcode[j],xl_mmio + MMIO_MACDATA) ;
+ if (j % 1024 == 0)
+ printk(".");
+ }
+ printk("\n") ;
+
+ for (i=0;i < 16; i++) {
+ writel( (MEM_BYTE_WRITE | 0xDFFF0) + i, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(microcode[mc_size - 16 + i], xl_mmio + MMIO_MACDATA) ;
+ }
+
+ /*
+ * Have to write the start address of the upload to FFF4, but
+ * the address must be >> 4. You do not want to know how long
+ * it took me to discover this.
+ */
+
+ writel(MEM_WORD_WRITE | 0xDFFF4, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writew(start >> 4, xl_mmio + MMIO_MACDATA);
+
+ /* Clear the CPAttention, memWrEn Bit */
+
+ writel( (IO_BYTE_READ | CPATTENTION), xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ result_8 = readb(xl_mmio + MMIO_MACDATA) ;
+ result_8 = result_8 & ~CPA_MEMWREN ;
+ writel( (IO_BYTE_WRITE | CPATTENTION), xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(result_8, xl_mmio + MMIO_MACDATA) ;
+
+ /* Clear the cpHold bit in pmbar */
+
+ writel( (IO_WORD_READ | PMBAR),xl_mmio + MMIO_MAC_ACCESS_CMD);
+ result_16 = readw(xl_mmio + MMIO_MACDATA) ;
+ result_16 = result_16 & ~PMB_CPHOLD ;
+ writel( (IO_WORD_WRITE | PMBAR), xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writew(result_16,xl_mmio + MMIO_MACDATA) ;
+
+
+ } /* If microcode upload required */
+
+ /*
+ * The card should now go though a self test procedure and get itself ready
+ * to be opened, we must wait for an srb response with the initialization
+ * information.
+ */
+
+#if XL_DEBUG
+ printk(KERN_INFO "%s: Microcode uploaded, must wait for the self test to complete\n", dev->name);
+#endif
+
+ writew(SETINDENABLE | 0xFFF, xl_mmio + MMIO_COMMAND) ;
+
+ t=jiffies;
+ while ( !(readw(xl_mmio + MMIO_INTSTATUS_AUTO) & INTSTAT_SRB) ) {
+ schedule();
+ if(jiffies-t > 15*HZ) {
+ printk(KERN_ERR "3COM 3C359 Velocity XL card not responding.\n");
+ return -ENODEV;
+ }
+ }
+
+ /*
+ * Write the RxBufArea with D000, RxEarlyThresh, TxStartThresh,
+ * DnPriReqThresh, read the tech docs if you want to know what
+ * values they need to be.
+ */
+
+ writel(MMIO_WORD_WRITE | RXBUFAREA, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writew(0xD000, xl_mmio + MMIO_MACDATA) ;
+
+ writel(MMIO_WORD_WRITE | RXEARLYTHRESH, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writew(0X0020, xl_mmio + MMIO_MACDATA) ;
+
+ writew( SETTXSTARTTHRESH | 0x40 , xl_mmio + MMIO_COMMAND) ;
+
+ writeb(0x04, xl_mmio + MMIO_DNBURSTTHRESH) ;
+ writeb(0x04, xl_mmio + DNPRIREQTHRESH) ;
+
+ /*
+ * Read WRBR to provide the location of the srb block, have to use byte reads not word reads.
+ * Tech docs have this wrong !!!!
+ */
+
+ writel(MMIO_BYTE_READ | WRBR, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ xl_priv->srb = readb(xl_mmio + MMIO_MACDATA) << 8 ;
+ writel( (MMIO_BYTE_READ | WRBR) + 1, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ xl_priv->srb = xl_priv->srb | readb(xl_mmio + MMIO_MACDATA) ;
+
+#if XL_DEBUG
+ writel(IO_WORD_READ | SWITCHSETTINGS, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ if ( readw(xl_mmio + MMIO_MACDATA) & 2) {
+ printk(KERN_INFO "Default ring speed 4 mbps \n") ;
+ } else {
+ printk(KERN_INFO "Default ring speed 16 mbps \n") ;
+ }
+ printk(KERN_INFO "%s: xl_priv->srb = %04x\n",xl_priv->xl_card_name, xl_priv->srb);
+#endif
+
+ return 0;
+}
+
+static int xl_open(struct net_device *dev)
+{
+ struct xl_private *xl_priv=(struct xl_private *)dev->priv;
+ u8 __iomem *xl_mmio = xl_priv->xl_mmio ;
+ u8 i ;
+ u16 hwaddr[3] ; /* Should be u8[6] but we get word return values */
+ int open_err ;
+
+ u16 switchsettings, switchsettings_eeprom ;
+
+ if(request_irq(dev->irq, &xl_interrupt, SA_SHIRQ , "3c359", dev)) {
+ return -EAGAIN;
+ }
+
+ /*
+ * Read the information from the EEPROM that we need. I know we
+ * should use ntohs, but the word gets stored reversed in the 16
+ * bit field anyway and it all works its self out when we memcpy
+ * it into dev->dev_addr.
+ */
+
+ hwaddr[0] = xl_ee_read(dev,0x10) ;
+ hwaddr[1] = xl_ee_read(dev,0x11) ;
+ hwaddr[2] = xl_ee_read(dev,0x12) ;
+
+ /* Ring speed */
+
+ switchsettings_eeprom = xl_ee_read(dev,0x08) ;
+ switchsettings = switchsettings_eeprom ;
+
+ if (xl_priv->xl_ring_speed != 0) {
+ if (xl_priv->xl_ring_speed == 4)
+ switchsettings = switchsettings | 0x02 ;
+ else
+ switchsettings = switchsettings & ~0x02 ;
+ }
+
+ /* Only write EEProm if there has been a change */
+ if (switchsettings != switchsettings_eeprom) {
+ xl_ee_write(dev,0x08,switchsettings) ;
+ /* Hardware reset after changing EEProm */
+ xl_hw_reset(dev) ;
+ }
+
+ memcpy(dev->dev_addr,hwaddr,dev->addr_len) ;
+
+ open_err = xl_open_hw(dev) ;
+
+ /*
+ * This really needs to be cleaned up with better error reporting.
+ */
+
+ if (open_err != 0) { /* Something went wrong with the open command */
+ if (open_err & 0x07) { /* Wrong speed, retry at different speed */
+ printk(KERN_WARNING "%s: Open Error, retrying at different ringspeed \n", dev->name) ;
+ switchsettings = switchsettings ^ 2 ;
+ xl_ee_write(dev,0x08,switchsettings) ;
+ xl_hw_reset(dev) ;
+ open_err = xl_open_hw(dev) ;
+ if (open_err != 0) {
+ printk(KERN_WARNING "%s: Open error returned a second time, we're bombing out now\n", dev->name);
+ free_irq(dev->irq,dev) ;
+ return -ENODEV ;
+ }
+ } else {
+ printk(KERN_WARNING "%s: Open Error = %04x\n", dev->name, open_err) ;
+ free_irq(dev->irq,dev) ;
+ return -ENODEV ;
+ }
+ }
+
+ /*
+ * Now to set up the Rx and Tx buffer structures
+ */
+ /* These MUST be on 8 byte boundaries */
+ xl_priv->xl_tx_ring = kmalloc((sizeof(struct xl_tx_desc) * XL_TX_RING_SIZE) + 7, GFP_DMA | GFP_KERNEL) ;
+ if (xl_priv->xl_tx_ring == NULL) {
+ printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers.\n",
+ dev->name);
+ free_irq(dev->irq,dev);
+ return -ENOMEM;
+ }
+ xl_priv->xl_rx_ring = kmalloc((sizeof(struct xl_rx_desc) * XL_RX_RING_SIZE) +7, GFP_DMA | GFP_KERNEL) ;
+ if (xl_priv->xl_tx_ring == NULL) {
+ printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers.\n",
+ dev->name);
+ free_irq(dev->irq,dev);
+ kfree(xl_priv->xl_tx_ring);
+ return -ENOMEM;
+ }
+ memset(xl_priv->xl_tx_ring,0,sizeof(struct xl_tx_desc) * XL_TX_RING_SIZE) ;
+ memset(xl_priv->xl_rx_ring,0,sizeof(struct xl_rx_desc) * XL_RX_RING_SIZE) ;
+
+ /* Setup Rx Ring */
+ for (i=0 ; i < XL_RX_RING_SIZE ; i++) {
+ struct sk_buff *skb ;
+
+ skb = dev_alloc_skb(xl_priv->pkt_buf_sz) ;
+ if (skb==NULL)
+ break ;
+
+ skb->dev = dev ;
+ xl_priv->xl_rx_ring[i].upfragaddr = pci_map_single(xl_priv->pdev, skb->data,xl_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE) ;
+ xl_priv->xl_rx_ring[i].upfraglen = xl_priv->pkt_buf_sz | RXUPLASTFRAG;
+ xl_priv->rx_ring_skb[i] = skb ;
+ }
+
+ if (i==0) {
+ printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers. Adapter disabled \n",dev->name) ;
+ free_irq(dev->irq,dev) ;
+ return -EIO ;
+ }
+
+ xl_priv->rx_ring_no = i ;
+ xl_priv->rx_ring_tail = 0 ;
+ xl_priv->rx_ring_dma_addr = pci_map_single(xl_priv->pdev,xl_priv->xl_rx_ring, sizeof(struct xl_rx_desc) * XL_RX_RING_SIZE, PCI_DMA_TODEVICE) ;
+ for (i=0;i<(xl_priv->rx_ring_no-1);i++) {
+ xl_priv->xl_rx_ring[i].upnextptr = xl_priv->rx_ring_dma_addr + (sizeof (struct xl_rx_desc) * (i+1)) ;
+ }
+ xl_priv->xl_rx_ring[i].upnextptr = 0 ;
+
+ writel(xl_priv->rx_ring_dma_addr, xl_mmio + MMIO_UPLISTPTR) ;
+
+ /* Setup Tx Ring */
+
+ xl_priv->tx_ring_dma_addr = pci_map_single(xl_priv->pdev,xl_priv->xl_tx_ring, sizeof(struct xl_tx_desc) * XL_TX_RING_SIZE,PCI_DMA_TODEVICE) ;
+
+ xl_priv->tx_ring_head = 1 ;
+ xl_priv->tx_ring_tail = 255 ; /* Special marker for first packet */
+ xl_priv->free_ring_entries = XL_TX_RING_SIZE ;
+
+ /*
+ * Setup the first dummy DPD entry for polling to start working.
+ */
+
+ xl_priv->xl_tx_ring[0].framestartheader = TXDPDEMPTY ;
+ xl_priv->xl_tx_ring[0].buffer = 0 ;
+ xl_priv->xl_tx_ring[0].buffer_length = 0 ;
+ xl_priv->xl_tx_ring[0].dnnextptr = 0 ;
+
+ writel(xl_priv->tx_ring_dma_addr, xl_mmio + MMIO_DNLISTPTR) ;
+ writel(DNUNSTALL, xl_mmio + MMIO_COMMAND) ;
+ writel(UPUNSTALL, xl_mmio + MMIO_COMMAND) ;
+ writel(DNENABLE, xl_mmio + MMIO_COMMAND) ;
+ writeb(0x40, xl_mmio + MMIO_DNPOLL) ;
+
+ /*
+ * Enable interrupts on the card
+ */
+
+ writel(SETINTENABLE | INT_MASK, xl_mmio + MMIO_COMMAND) ;
+ writel(SETINDENABLE | INT_MASK, xl_mmio + MMIO_COMMAND) ;
+
+ netif_start_queue(dev) ;
+ return 0;
+
+}
+
+static int xl_open_hw(struct net_device *dev)
+{
+ struct xl_private *xl_priv=(struct xl_private *)dev->priv;
+ u8 __iomem *xl_mmio = xl_priv->xl_mmio ;
+ u16 vsoff ;
+ char ver_str[33];
+ int open_err ;
+ int i ;
+ unsigned long t ;
+
+ /*
+ * Okay, let's build up the Open.NIC srb command
+ *
+ */
+
+ writel( (MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb), xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(OPEN_NIC, xl_mmio + MMIO_MACDATA) ;
+
+ /*
+ * Use this as a test byte, if it comes back with the same value, the command didn't work
+ */
+
+ writel( (MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb)+ 2, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(0xff,xl_mmio + MMIO_MACDATA) ;
+
+ /* Open options */
+ writel( (MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb) + 8, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(0x00, xl_mmio + MMIO_MACDATA) ;
+ writel( (MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb) + 9, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(0x00, xl_mmio + MMIO_MACDATA) ;
+
+ /*
+ * Node address, be careful here, the docs say you can just put zeros here and it will use
+ * the hardware address, it doesn't, you must include the node address in the open command.
+ */
+
+ if (xl_priv->xl_laa[0]) { /* If using a LAA address */
+ for (i=10;i<16;i++) {
+ writel( (MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb) + i, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(xl_priv->xl_laa[i],xl_mmio + MMIO_MACDATA) ;
+ }
+ memcpy(dev->dev_addr,xl_priv->xl_laa,dev->addr_len) ;
+ } else { /* Regular hardware address */
+ for (i=10;i<16;i++) {
+ writel( (MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb) + i, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(dev->dev_addr[i-10], xl_mmio + MMIO_MACDATA) ;
+ }
+ }
+
+ /* Default everything else to 0 */
+ for (i = 16; i < 34; i++) {
+ writel( (MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb) + i, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(0x00,xl_mmio + MMIO_MACDATA) ;
+ }
+
+ /*
+ * Set the csrb bit in the MISR register
+ */
+
+ xl_wait_misr_flags(dev) ;
+ writel(MEM_BYTE_WRITE | MF_CSRB, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(0xFF, xl_mmio + MMIO_MACDATA) ;
+ writel(MMIO_BYTE_WRITE | MISR_SET, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(MISR_CSRB , xl_mmio + MMIO_MACDATA) ;
+
+ /*
+ * Now wait for the command to run
+ */
+
+ t=jiffies;
+ while (! (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_SRB)) {
+ schedule();
+ if(jiffies-t > 40*HZ) {
+ printk(KERN_ERR "3COM 3C359 Velocity XL card not responding.\n");
+ break ;
+ }
+ }
+
+ /*
+ * Let's interpret the open response
+ */
+
+ writel( (MEM_BYTE_READ | 0xD0000 | xl_priv->srb)+2, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ if (readb(xl_mmio + MMIO_MACDATA)!=0) {
+ open_err = readb(xl_mmio + MMIO_MACDATA) << 8 ;
+ writel( (MEM_BYTE_READ | 0xD0000 | xl_priv->srb) + 7, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ open_err |= readb(xl_mmio + MMIO_MACDATA) ;
+ return open_err ;
+ } else {
+ writel( (MEM_WORD_READ | 0xD0000 | xl_priv->srb) + 8, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ xl_priv->asb = ntohs(readw(xl_mmio + MMIO_MACDATA)) ;
+ printk(KERN_INFO "%s: Adapter Opened Details: ",dev->name) ;
+ printk("ASB: %04x",xl_priv->asb ) ;
+ writel( (MEM_WORD_READ | 0xD0000 | xl_priv->srb) + 10, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ printk(", SRB: %04x",ntohs(readw(xl_mmio + MMIO_MACDATA)) ) ;
+
+ writel( (MEM_WORD_READ | 0xD0000 | xl_priv->srb) + 12, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ xl_priv->arb = ntohs(readw(xl_mmio + MMIO_MACDATA)) ;
+ printk(", ARB: %04x \n",xl_priv->arb ) ;
+ writel( (MEM_WORD_READ | 0xD0000 | xl_priv->srb) + 14, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ vsoff = ntohs(readw(xl_mmio + MMIO_MACDATA)) ;
+
+ /*
+ * Interesting, sending the individual characters directly to printk was causing klogd to use
+ * use 100% of processor time, so we build up the string and print that instead.
+ */
+
+ for (i=0;i<0x20;i++) {
+ writel( (MEM_BYTE_READ | 0xD0000 | vsoff) + i, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ ver_str[i] = readb(xl_mmio + MMIO_MACDATA) ;
+ }
+ ver_str[i] = '\0' ;
+ printk(KERN_INFO "%s: Microcode version String: %s \n",dev->name,ver_str);
+ }
+
+ /*
+ * Issue the AckInterrupt
+ */
+ writew(ACK_INTERRUPT | SRBRACK | LATCH_ACK, xl_mmio + MMIO_COMMAND) ;
+
+ return 0 ;
+}
+
+/*
+ * There are two ways of implementing rx on the 359 NIC, either
+ * interrupt driven or polling. We are going to uses interrupts,
+ * it is the easier way of doing things.
+ *
+ * The Rx works with a ring of Rx descriptors. At initialise time the ring
+ * entries point to the next entry except for the last entry in the ring
+ * which points to 0. The card is programmed with the location of the first
+ * available descriptor and keeps reading the next_ptr until next_ptr is set
+ * to 0. Hopefully with a ring size of 16 the card will never get to read a next_ptr
+ * of 0. As the Rx interrupt is received we copy the frame up to the protocol layers
+ * and then point the end of the ring to our current position and point our current
+ * position to 0, therefore making the current position the last position on the ring.
+ * The last position on the ring therefore loops continually loops around the rx ring.
+ *
+ * rx_ring_tail is the position on the ring to process next. (Think of a snake, the head
+ * expands as the card adds new packets and we go around eating the tail processing the
+ * packets.)
+ *
+ * Undoubtably it could be streamlined and improved upon, but at the moment it works
+ * and the fast path through the routine is fine.
+ *
+ * adv_rx_ring could be inlined to increase performance, but its called a *lot* of times
+ * in xl_rx so would increase the size of the function significantly.
+ */
+
+static void adv_rx_ring(struct net_device *dev) /* Advance rx_ring, cut down on bloat in xl_rx */
+{
+ struct xl_private *xl_priv=(struct xl_private *)dev->priv;
+ int prev_ring_loc ;
+
+ prev_ring_loc = (xl_priv->rx_ring_tail + XL_RX_RING_SIZE - 1) & (XL_RX_RING_SIZE - 1);
+ xl_priv->xl_rx_ring[prev_ring_loc].upnextptr = xl_priv->rx_ring_dma_addr + (sizeof (struct xl_rx_desc) * xl_priv->rx_ring_tail) ;
+ xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].framestatus = 0 ;
+ xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upnextptr = 0 ;
+ xl_priv->rx_ring_tail++ ;
+ xl_priv->rx_ring_tail &= (XL_RX_RING_SIZE-1) ;
+
+ return ;
+}
+
+static void xl_rx(struct net_device *dev)
+{
+ struct xl_private *xl_priv=(struct xl_private *)dev->priv;
+ u8 __iomem * xl_mmio = xl_priv->xl_mmio ;
+ struct sk_buff *skb, *skb2 ;
+ int frame_length = 0, copy_len = 0 ;
+ int temp_ring_loc ;
+
+ /*
+ * Receive the next frame, loop around the ring until all frames
+ * have been received.
+ */
+
+ while (xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].framestatus & (RXUPDCOMPLETE | RXUPDFULL) ) { /* Descriptor to process */
+
+ if (xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].framestatus & RXUPDFULL ) { /* UpdFull, Multiple Descriptors used for the frame */
+
+ /*
+ * This is a pain, you need to go through all the descriptors until the last one
+ * for this frame to find the framelength
+ */
+
+ temp_ring_loc = xl_priv->rx_ring_tail ;
+
+ while (xl_priv->xl_rx_ring[temp_ring_loc].framestatus & RXUPDFULL ) {
+ temp_ring_loc++ ;
+ temp_ring_loc &= (XL_RX_RING_SIZE-1) ;
+ }
+
+ frame_length = xl_priv->xl_rx_ring[temp_ring_loc].framestatus & 0x7FFF ;
+
+ skb = dev_alloc_skb(frame_length) ;
+
+ if (skb==NULL) { /* No memory for frame, still need to roll forward the rx ring */
+ printk(KERN_WARNING "%s: dev_alloc_skb failed - multi buffer !\n", dev->name) ;
+ while (xl_priv->rx_ring_tail != temp_ring_loc)
+ adv_rx_ring(dev) ;
+
+ adv_rx_ring(dev) ; /* One more time just for luck :) */
+ xl_priv->xl_stats.rx_dropped++ ;
+
+ writel(ACK_INTERRUPT | UPCOMPACK | LATCH_ACK , xl_mmio + MMIO_COMMAND) ;
+ return ;
+ }
+
+ skb->dev = dev ;
+
+ while (xl_priv->rx_ring_tail != temp_ring_loc) {
+ copy_len = xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfraglen & 0x7FFF ;
+ frame_length -= copy_len ;
+ pci_dma_sync_single_for_cpu(xl_priv->pdev,xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr,xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ;
+ memcpy(skb_put(skb,copy_len), xl_priv->rx_ring_skb[xl_priv->rx_ring_tail]->data, copy_len) ;
+ pci_dma_sync_single_for_device(xl_priv->pdev,xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr,xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ;
+ adv_rx_ring(dev) ;
+ }
+
+ /* Now we have found the last fragment */
+ pci_dma_sync_single_for_cpu(xl_priv->pdev,xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr,xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ;
+ memcpy(skb_put(skb,copy_len), xl_priv->rx_ring_skb[xl_priv->rx_ring_tail]->data, frame_length) ;
+/* memcpy(skb_put(skb,frame_length), bus_to_virt(xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr), frame_length) ; */
+ pci_dma_sync_single_for_device(xl_priv->pdev,xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr,xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ;
+ adv_rx_ring(dev) ;
+ skb->protocol = tr_type_trans(skb,dev) ;
+ netif_rx(skb) ;
+
+ } else { /* Single Descriptor Used, simply swap buffers over, fast path */
+
+ frame_length = xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].framestatus & 0x7FFF ;
+
+ skb = dev_alloc_skb(xl_priv->pkt_buf_sz) ;
+
+ if (skb==NULL) { /* Still need to fix the rx ring */
+ printk(KERN_WARNING "%s: dev_alloc_skb failed in rx, single buffer \n",dev->name) ;
+ adv_rx_ring(dev) ;
+ xl_priv->xl_stats.rx_dropped++ ;
+ writel(ACK_INTERRUPT | UPCOMPACK | LATCH_ACK , xl_mmio + MMIO_COMMAND) ;
+ return ;
+ }
+
+ skb->dev = dev ;
+
+ skb2 = xl_priv->rx_ring_skb[xl_priv->rx_ring_tail] ;
+ pci_unmap_single(xl_priv->pdev, xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr, xl_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ;
+ skb_put(skb2, frame_length) ;
+ skb2->protocol = tr_type_trans(skb2,dev) ;
+
+ xl_priv->rx_ring_skb[xl_priv->rx_ring_tail] = skb ;
+ xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr = pci_map_single(xl_priv->pdev,skb->data,xl_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE) ;
+ xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfraglen = xl_priv->pkt_buf_sz | RXUPLASTFRAG ;
+ adv_rx_ring(dev) ;
+ xl_priv->xl_stats.rx_packets++ ;
+ xl_priv->xl_stats.rx_bytes += frame_length ;
+
+ netif_rx(skb2) ;
+ } /* if multiple buffers */
+ dev->last_rx = jiffies ;
+ } /* while packet to do */
+
+ /* Clear the updComplete interrupt */
+ writel(ACK_INTERRUPT | UPCOMPACK | LATCH_ACK , xl_mmio + MMIO_COMMAND) ;
+ return ;
+}
+
+/*
+ * This is ruthless, it doesn't care what state the card is in it will
+ * completely reset the adapter.
+ */
+
+static void xl_reset(struct net_device *dev)
+{
+ struct xl_private *xl_priv=(struct xl_private *)dev->priv;
+ u8 __iomem * xl_mmio = xl_priv->xl_mmio ;
+ unsigned long t;
+
+ writew( GLOBAL_RESET, xl_mmio + MMIO_COMMAND ) ;
+
+ /*
+ * Must wait for cmdInProgress bit (12) to clear before continuing with
+ * card configuration.
+ */
+
+ t=jiffies;
+ while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) {
+ if(jiffies-t > 40*HZ) {
+ printk(KERN_ERR "3COM 3C359 Velocity XL card not responding.\n");
+ break ;
+ }
+ }
+
+}
+
+static void xl_freemem(struct net_device *dev)
+{
+ struct xl_private *xl_priv=(struct xl_private *)dev->priv ;
+ int i ;
+
+ for (i=0;i<XL_RX_RING_SIZE;i++) {
+ dev_kfree_skb_irq(xl_priv->rx_ring_skb[xl_priv->rx_ring_tail]) ;
+ pci_unmap_single(xl_priv->pdev,xl_priv->xl_rx_ring[xl_priv->rx_ring_tail].upfragaddr,xl_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE) ;
+ xl_priv->rx_ring_tail++ ;
+ xl_priv->rx_ring_tail &= XL_RX_RING_SIZE-1;
+ }
+
+ /* unmap ring */
+ pci_unmap_single(xl_priv->pdev,xl_priv->rx_ring_dma_addr, sizeof(struct xl_rx_desc) * XL_RX_RING_SIZE, PCI_DMA_FROMDEVICE) ;
+
+ pci_unmap_single(xl_priv->pdev,xl_priv->tx_ring_dma_addr, sizeof(struct xl_tx_desc) * XL_TX_RING_SIZE, PCI_DMA_TODEVICE) ;
+
+ kfree(xl_priv->xl_rx_ring) ;
+ kfree(xl_priv->xl_tx_ring) ;
+
+ return ;
+}
+
+static irqreturn_t xl_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *)dev_id;
+ struct xl_private *xl_priv =(struct xl_private *)dev->priv;
+ u8 __iomem * xl_mmio = xl_priv->xl_mmio ;
+ u16 intstatus, macstatus ;
+
+ if (!dev) {
+ printk(KERN_WARNING "Device structure dead, aaahhhh !\n") ;
+ return IRQ_NONE;
+ }
+
+ intstatus = readw(xl_mmio + MMIO_INTSTATUS) ;
+
+ if (!(intstatus & 1)) /* We didn't generate the interrupt */
+ return IRQ_NONE;
+
+ spin_lock(&xl_priv->xl_lock) ;
+
+ /*
+ * Process the interrupt
+ */
+ /*
+ * Something fishy going on here, we shouldn't get 0001 ints, not fatal though.
+ */
+ if (intstatus == 0x0001) {
+ writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ;
+ printk(KERN_INFO "%s: 00001 int received \n",dev->name) ;
+ } else {
+ if (intstatus & (HOSTERRINT | SRBRINT | ARBCINT | UPCOMPINT | DNCOMPINT | HARDERRINT | (1<<8) | TXUNDERRUN | ASBFINT)) {
+
+ /*
+ * Host Error.
+ * It may be possible to recover from this, but usually it means something
+ * is seriously fubar, so we just close the adapter.
+ */
+
+ if (intstatus & HOSTERRINT) {
+ printk(KERN_WARNING "%s: Host Error, performing global reset, intstatus = %04x \n",dev->name,intstatus) ;
+ writew( GLOBAL_RESET, xl_mmio + MMIO_COMMAND ) ;
+ printk(KERN_WARNING "%s: Resetting hardware: \n", dev->name);
+ netif_stop_queue(dev) ;
+ xl_freemem(dev) ;
+ free_irq(dev->irq,dev);
+ xl_reset(dev) ;
+ writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ;
+ spin_unlock(&xl_priv->xl_lock) ;
+ return IRQ_HANDLED;
+ } /* Host Error */
+
+ if (intstatus & SRBRINT ) { /* Srbc interrupt */
+ writel(ACK_INTERRUPT | SRBRACK | LATCH_ACK, xl_mmio + MMIO_COMMAND) ;
+ if (xl_priv->srb_queued)
+ xl_srb_bh(dev) ;
+ } /* SRBR Interrupt */
+
+ if (intstatus & TXUNDERRUN) { /* Issue DnReset command */
+ writel(DNRESET, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) { /* Wait for command to run */
+ /* !!! FIX-ME !!!!
+ Must put a timeout check here ! */
+ /* Empty Loop */
+ }
+ printk(KERN_WARNING "%s: TX Underrun received \n",dev->name) ;
+ writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ;
+ } /* TxUnderRun */
+
+ if (intstatus & ARBCINT ) { /* Arbc interrupt */
+ xl_arb_cmd(dev) ;
+ } /* Arbc */
+
+ if (intstatus & ASBFINT) {
+ if (xl_priv->asb_queued == 1) {
+ xl_asb_cmd(dev) ;
+ } else if (xl_priv->asb_queued == 2) {
+ xl_asb_bh(dev) ;
+ } else {
+ writel(ACK_INTERRUPT | LATCH_ACK | ASBFACK, xl_mmio + MMIO_COMMAND) ;
+ }
+ } /* Asbf */
+
+ if (intstatus & UPCOMPINT ) /* UpComplete */
+ xl_rx(dev) ;
+
+ if (intstatus & DNCOMPINT ) /* DnComplete */
+ xl_dn_comp(dev) ;
+
+ if (intstatus & HARDERRINT ) { /* Hardware error */
+ writel(MMIO_WORD_READ | MACSTATUS, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ macstatus = readw(xl_mmio + MMIO_MACDATA) ;
+ printk(KERN_WARNING "%s: MacStatusError, details: ", dev->name);
+ if (macstatus & (1<<14))
+ printk(KERN_WARNING "tchk error: Unrecoverable error \n") ;
+ if (macstatus & (1<<3))
+ printk(KERN_WARNING "eint error: Internal watchdog timer expired \n") ;
+ if (macstatus & (1<<2))
+ printk(KERN_WARNING "aint error: Host tried to perform invalid operation \n") ;
+ printk(KERN_WARNING "Instatus = %02x, macstatus = %02x\n",intstatus,macstatus) ;
+ printk(KERN_WARNING "%s: Resetting hardware: \n", dev->name);
+ netif_stop_queue(dev) ;
+ xl_freemem(dev) ;
+ free_irq(dev->irq,dev);
+ unregister_netdev(dev) ;
+ free_netdev(dev) ;
+ xl_reset(dev) ;
+ writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ;
+ spin_unlock(&xl_priv->xl_lock) ;
+ return IRQ_HANDLED;
+ }
+ } else {
+ printk(KERN_WARNING "%s: Received Unknown interrupt : %04x \n", dev->name, intstatus) ;
+ writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ;
+ }
+ }
+
+ /* Turn interrupts back on */
+
+ writel( SETINDENABLE | INT_MASK, xl_mmio + MMIO_COMMAND) ;
+ writel( SETINTENABLE | INT_MASK, xl_mmio + MMIO_COMMAND) ;
+
+ spin_unlock(&xl_priv->xl_lock) ;
+ return IRQ_HANDLED;
+}
+
+/*
+ * Tx - Polling configuration
+ */
+
+static int xl_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct xl_private *xl_priv=(struct xl_private *)dev->priv;
+ struct xl_tx_desc *txd ;
+ int tx_head, tx_tail, tx_prev ;
+ unsigned long flags ;
+
+ spin_lock_irqsave(&xl_priv->xl_lock,flags) ;
+
+ netif_stop_queue(dev) ;
+
+ if (xl_priv->free_ring_entries > 1 ) {
+ /*
+ * Set up the descriptor for the packet
+ */
+ tx_head = xl_priv->tx_ring_head ;
+ tx_tail = xl_priv->tx_ring_tail ;
+
+ txd = &(xl_priv->xl_tx_ring[tx_head]) ;
+ txd->dnnextptr = 0 ;
+ txd->framestartheader = skb->len | TXDNINDICATE ;
+ txd->buffer = pci_map_single(xl_priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE) ;
+ txd->buffer_length = skb->len | TXDNFRAGLAST ;
+ xl_priv->tx_ring_skb[tx_head] = skb ;
+ xl_priv->xl_stats.tx_packets++ ;
+ xl_priv->xl_stats.tx_bytes += skb->len ;
+
+ /*
+ * Set the nextptr of the previous descriptor equal to this descriptor, add XL_TX_RING_SIZE -1
+ * to ensure no negative numbers in unsigned locations.
+ */
+
+ tx_prev = (xl_priv->tx_ring_head + XL_TX_RING_SIZE - 1) & (XL_TX_RING_SIZE - 1) ;
+
+ xl_priv->tx_ring_head++ ;
+ xl_priv->tx_ring_head &= (XL_TX_RING_SIZE - 1) ;
+ xl_priv->free_ring_entries-- ;
+
+ xl_priv->xl_tx_ring[tx_prev].dnnextptr = xl_priv->tx_ring_dma_addr + (sizeof (struct xl_tx_desc) * tx_head) ;
+
+ /* Sneaky, by doing a read on DnListPtr we can force the card to poll on the DnNextPtr */
+ /* readl(xl_mmio + MMIO_DNLISTPTR) ; */
+
+ netif_wake_queue(dev) ;
+
+ spin_unlock_irqrestore(&xl_priv->xl_lock,flags) ;
+
+ return 0;
+ } else {
+ spin_unlock_irqrestore(&xl_priv->xl_lock,flags) ;
+ return 1;
+ }
+
+}
+
+/*
+ * The NIC has told us that a packet has been downloaded onto the card, we must
+ * find out which packet it has done, clear the skb and information for the packet
+ * then advance around the ring for all tranmitted packets
+ */
+
+static void xl_dn_comp(struct net_device *dev)
+{
+ struct xl_private *xl_priv=(struct xl_private *)dev->priv;
+ u8 __iomem * xl_mmio = xl_priv->xl_mmio ;
+ struct xl_tx_desc *txd ;
+
+
+ if (xl_priv->tx_ring_tail == 255) {/* First time */
+ xl_priv->xl_tx_ring[0].framestartheader = 0 ;
+ xl_priv->xl_tx_ring[0].dnnextptr = 0 ;
+ xl_priv->tx_ring_tail = 1 ;
+ }
+
+ while (xl_priv->xl_tx_ring[xl_priv->tx_ring_tail].framestartheader & TXDNCOMPLETE ) {
+ txd = &(xl_priv->xl_tx_ring[xl_priv->tx_ring_tail]) ;
+ pci_unmap_single(xl_priv->pdev,txd->buffer, xl_priv->tx_ring_skb[xl_priv->tx_ring_tail]->len, PCI_DMA_TODEVICE) ;
+ txd->framestartheader = 0 ;
+ txd->buffer = 0xdeadbeef ;
+ txd->buffer_length = 0 ;
+ dev_kfree_skb_irq(xl_priv->tx_ring_skb[xl_priv->tx_ring_tail]) ;
+ xl_priv->tx_ring_tail++ ;
+ xl_priv->tx_ring_tail &= (XL_TX_RING_SIZE - 1) ;
+ xl_priv->free_ring_entries++ ;
+ }
+
+ netif_wake_queue(dev) ;
+
+ writel(ACK_INTERRUPT | DNCOMPACK | LATCH_ACK , xl_mmio + MMIO_COMMAND) ;
+}
+
+/*
+ * Close the adapter properly.
+ * This srb reply cannot be handled from interrupt context as we have
+ * to free the interrupt from the driver.
+ */
+
+static int xl_close(struct net_device *dev)
+{
+ struct xl_private *xl_priv = (struct xl_private *) dev->priv ;
+ u8 __iomem * xl_mmio = xl_priv->xl_mmio ;
+ unsigned long t ;
+
+ netif_stop_queue(dev) ;
+
+ /*
+ * Close the adapter, need to stall the rx and tx queues.
+ */
+
+ writew(DNSTALL, xl_mmio + MMIO_COMMAND) ;
+ t=jiffies;
+ while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) {
+ schedule();
+ if(jiffies-t > 10*HZ) {
+ printk(KERN_ERR "%s: 3COM 3C359 Velocity XL-DNSTALL not responding.\n", dev->name);
+ break ;
+ }
+ }
+ writew(DNDISABLE, xl_mmio + MMIO_COMMAND) ;
+ t=jiffies;
+ while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) {
+ schedule();
+ if(jiffies-t > 10*HZ) {
+ printk(KERN_ERR "%s: 3COM 3C359 Velocity XL-DNDISABLE not responding.\n", dev->name);
+ break ;
+ }
+ }
+ writew(UPSTALL, xl_mmio + MMIO_COMMAND) ;
+ t=jiffies;
+ while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) {
+ schedule();
+ if(jiffies-t > 10*HZ) {
+ printk(KERN_ERR "%s: 3COM 3C359 Velocity XL-UPSTALL not responding.\n", dev->name);
+ break ;
+ }
+ }
+
+ /* Turn off interrupts, we will still get the indication though
+ * so we can trap it
+ */
+
+ writel(SETINTENABLE, xl_mmio + MMIO_COMMAND) ;
+
+ xl_srb_cmd(dev,CLOSE_NIC) ;
+
+ t=jiffies;
+ while (!(readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_SRB)) {
+ schedule();
+ if(jiffies-t > 10*HZ) {
+ printk(KERN_ERR "%s: 3COM 3C359 Velocity XL-CLOSENIC not responding.\n", dev->name);
+ break ;
+ }
+ }
+ /* Read the srb response from the adapter */
+
+ writel(MEM_BYTE_READ | 0xd0000 | xl_priv->srb, xl_mmio + MMIO_MAC_ACCESS_CMD);
+ if (readb(xl_mmio + MMIO_MACDATA) != CLOSE_NIC) {
+ printk(KERN_INFO "%s: CLOSE_NIC did not get a CLOSE_NIC response \n",dev->name) ;
+ } else {
+ writel((MEM_BYTE_READ | 0xd0000 | xl_priv->srb) +2, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ if (readb(xl_mmio + MMIO_MACDATA)==0) {
+ printk(KERN_INFO "%s: Adapter has been closed \n",dev->name) ;
+ writew(ACK_INTERRUPT | SRBRACK | LATCH_ACK, xl_mmio + MMIO_COMMAND) ;
+
+ xl_freemem(dev) ;
+ free_irq(dev->irq,dev) ;
+ } else {
+ printk(KERN_INFO "%s: Close nic command returned error code %02x\n",dev->name, readb(xl_mmio + MMIO_MACDATA)) ;
+ }
+ }
+
+ /* Reset the upload and download logic */
+
+ writew(UPRESET, xl_mmio + MMIO_COMMAND) ;
+ t=jiffies;
+ while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) {
+ schedule();
+ if(jiffies-t > 10*HZ) {
+ printk(KERN_ERR "%s: 3COM 3C359 Velocity XL-UPRESET not responding.\n", dev->name);
+ break ;
+ }
+ }
+ writew(DNRESET, xl_mmio + MMIO_COMMAND) ;
+ t=jiffies;
+ while (readw(xl_mmio + MMIO_INTSTATUS) & INTSTAT_CMD_IN_PROGRESS) {
+ schedule();
+ if(jiffies-t > 10*HZ) {
+ printk(KERN_ERR "%s: 3COM 3C359 Velocity XL-DNRESET not responding.\n", dev->name);
+ break ;
+ }
+ }
+ xl_hw_reset(dev) ;
+ return 0 ;
+}
+
+static void xl_set_rx_mode(struct net_device *dev)
+{
+ struct xl_private *xl_priv = (struct xl_private *) dev->priv ;
+ struct dev_mc_list *dmi ;
+ unsigned char dev_mc_address[4] ;
+ u16 options ;
+ int i ;
+
+ if (dev->flags & IFF_PROMISC)
+ options = 0x0004 ;
+ else
+ options = 0x0000 ;
+
+ if (options ^ xl_priv->xl_copy_all_options) { /* Changed, must send command */
+ xl_priv->xl_copy_all_options = options ;
+ xl_srb_cmd(dev, SET_RECEIVE_MODE) ;
+ return ;
+ }
+
+ dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ;
+
+ for (i=0,dmi=dev->mc_list;i < dev->mc_count; i++,dmi = dmi->next) {
+ dev_mc_address[0] |= dmi->dmi_addr[2] ;
+ dev_mc_address[1] |= dmi->dmi_addr[3] ;
+ dev_mc_address[2] |= dmi->dmi_addr[4] ;
+ dev_mc_address[3] |= dmi->dmi_addr[5] ;
+ }
+
+ if (memcmp(xl_priv->xl_functional_addr,dev_mc_address,4) != 0) { /* Options have changed, run the command */
+ memcpy(xl_priv->xl_functional_addr, dev_mc_address,4) ;
+ xl_srb_cmd(dev, SET_FUNC_ADDRESS) ;
+ }
+ return ;
+}
+
+
+/*
+ * We issued an srb command and now we must read
+ * the response from the completed command.
+ */
+
+static void xl_srb_bh(struct net_device *dev)
+{
+ struct xl_private *xl_priv = (struct xl_private *) dev->priv ;
+ u8 __iomem * xl_mmio = xl_priv->xl_mmio ;
+ u8 srb_cmd, ret_code ;
+ int i ;
+
+ writel(MEM_BYTE_READ | 0xd0000 | xl_priv->srb, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ srb_cmd = readb(xl_mmio + MMIO_MACDATA) ;
+ writel((MEM_BYTE_READ | 0xd0000 | xl_priv->srb) +2, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ ret_code = readb(xl_mmio + MMIO_MACDATA) ;
+
+ /* Ret_code is standard across all commands */
+
+ switch (ret_code) {
+ case 1:
+ printk(KERN_INFO "%s: Command: %d - Invalid Command code\n",dev->name,srb_cmd) ;
+ break ;
+ case 4:
+ printk(KERN_INFO "%s: Command: %d - Adapter is closed, must be open for this command \n",dev->name,srb_cmd) ;
+ break ;
+
+ case 6:
+ printk(KERN_INFO "%s: Command: %d - Options Invalid for command \n",dev->name,srb_cmd) ;
+ break ;
+
+ case 0: /* Successful command execution */
+ switch (srb_cmd) {
+ case READ_LOG: /* Returns 14 bytes of data from the NIC */
+ if(xl_priv->xl_message_level)
+ printk(KERN_INFO "%s: READ.LOG 14 bytes of data ",dev->name) ;
+ /*
+ * We still have to read the log even if message_level = 0 and we don't want
+ * to see it
+ */
+ for (i=0;i<14;i++) {
+ writel(MEM_BYTE_READ | 0xd0000 | xl_priv->srb | i, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ if(xl_priv->xl_message_level)
+ printk("%02x:",readb(xl_mmio + MMIO_MACDATA)) ;
+ }
+ printk("\n") ;
+ break ;
+ case SET_FUNC_ADDRESS:
+ if(xl_priv->xl_message_level)
+ printk(KERN_INFO "%s: Functional Address Set \n",dev->name) ;
+ break ;
+ case CLOSE_NIC:
+ if(xl_priv->xl_message_level)
+ printk(KERN_INFO "%s: Received CLOSE_NIC interrupt in interrupt handler \n",dev->name) ;
+ break ;
+ case SET_MULTICAST_MODE:
+ if(xl_priv->xl_message_level)
+ printk(KERN_INFO "%s: Multicast options successfully changed\n",dev->name) ;
+ break ;
+ case SET_RECEIVE_MODE:
+ if(xl_priv->xl_message_level) {
+ if (xl_priv->xl_copy_all_options == 0x0004)
+ printk(KERN_INFO "%s: Entering promiscuous mode \n", dev->name) ;
+ else
+ printk(KERN_INFO "%s: Entering normal receive mode \n",dev->name) ;
+ }
+ break ;
+
+ } /* switch */
+ break ;
+ } /* switch */
+ return ;
+}
+
+static struct net_device_stats * xl_get_stats(struct net_device *dev)
+{
+ struct xl_private *xl_priv = (struct xl_private *) dev->priv ;
+ return (struct net_device_stats *) &xl_priv->xl_stats;
+}
+
+static int xl_set_mac_address (struct net_device *dev, void *addr)
+{
+ struct sockaddr *saddr = addr ;
+ struct xl_private *xl_priv = (struct xl_private *)dev->priv ;
+
+ if (netif_running(dev)) {
+ printk(KERN_WARNING "%s: Cannot set mac/laa address while card is open\n", dev->name) ;
+ return -EIO ;
+ }
+
+ memcpy(xl_priv->xl_laa, saddr->sa_data,dev->addr_len) ;
+
+ if (xl_priv->xl_message_level) {
+ printk(KERN_INFO "%s: MAC/LAA Set to = %x.%x.%x.%x.%x.%x\n",dev->name, xl_priv->xl_laa[0],
+ xl_priv->xl_laa[1], xl_priv->xl_laa[2],
+ xl_priv->xl_laa[3], xl_priv->xl_laa[4],
+ xl_priv->xl_laa[5]);
+ }
+
+ return 0 ;
+}
+
+static void xl_arb_cmd(struct net_device *dev)
+{
+ struct xl_private *xl_priv = (struct xl_private *) dev->priv;
+ u8 __iomem * xl_mmio = xl_priv->xl_mmio ;
+ u8 arb_cmd ;
+ u16 lan_status, lan_status_diff ;
+
+ writel( ( MEM_BYTE_READ | 0xD0000 | xl_priv->arb), xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ arb_cmd = readb(xl_mmio + MMIO_MACDATA) ;
+
+ if (arb_cmd == RING_STATUS_CHANGE) { /* Ring.Status.Change */
+ writel( ( (MEM_WORD_READ | 0xD0000 | xl_priv->arb) + 6), xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+
+ printk(KERN_INFO "%s: Ring Status Change: New Status = %04x\n", dev->name, ntohs(readw(xl_mmio + MMIO_MACDATA) )) ;
+
+ lan_status = ntohs(readw(xl_mmio + MMIO_MACDATA));
+
+ /* Acknowledge interrupt, this tells nic we are done with the arb */
+ writel(ACK_INTERRUPT | ARBCACK | LATCH_ACK, xl_mmio + MMIO_COMMAND) ;
+
+ lan_status_diff = xl_priv->xl_lan_status ^ lan_status ;
+
+ if (lan_status_diff & (LSC_LWF | LSC_ARW | LSC_FPE | LSC_RR) ) {
+ if (lan_status_diff & LSC_LWF)
+ printk(KERN_WARNING "%s: Short circuit detected on the lobe\n",dev->name);
+ if (lan_status_diff & LSC_ARW)
+ printk(KERN_WARNING "%s: Auto removal error\n",dev->name);
+ if (lan_status_diff & LSC_FPE)
+ printk(KERN_WARNING "%s: FDX Protocol Error\n",dev->name);
+ if (lan_status_diff & LSC_RR)
+ printk(KERN_WARNING "%s: Force remove MAC frame received\n",dev->name);
+
+ /* Adapter has been closed by the hardware */
+
+ netif_stop_queue(dev);
+ xl_freemem(dev) ;
+ free_irq(dev->irq,dev);
+
+ printk(KERN_WARNING "%s: Adapter has been closed \n", dev->name) ;
+ } /* If serious error */
+
+ if (xl_priv->xl_message_level) {
+ if (lan_status_diff & LSC_SIG_LOSS)
+ printk(KERN_WARNING "%s: No receive signal detected \n", dev->name) ;
+ if (lan_status_diff & LSC_HARD_ERR)
+ printk(KERN_INFO "%s: Beaconing \n",dev->name);
+ if (lan_status_diff & LSC_SOFT_ERR)
+ printk(KERN_WARNING "%s: Adapter transmitted Soft Error Report Mac Frame \n",dev->name);
+ if (lan_status_diff & LSC_TRAN_BCN)
+ printk(KERN_INFO "%s: We are tranmitting the beacon, aaah\n",dev->name);
+ if (lan_status_diff & LSC_SS)
+ printk(KERN_INFO "%s: Single Station on the ring \n", dev->name);
+ if (lan_status_diff & LSC_RING_REC)
+ printk(KERN_INFO "%s: Ring recovery ongoing\n",dev->name);
+ if (lan_status_diff & LSC_FDX_MODE)
+ printk(KERN_INFO "%s: Operating in FDX mode\n",dev->name);
+ }
+
+ if (lan_status_diff & LSC_CO) {
+ if (xl_priv->xl_message_level)
+ printk(KERN_INFO "%s: Counter Overflow \n", dev->name);
+ /* Issue READ.LOG command */
+ xl_srb_cmd(dev, READ_LOG) ;
+ }
+
+ /* There is no command in the tech docs to issue the read_sr_counters */
+ if (lan_status_diff & LSC_SR_CO) {
+ if (xl_priv->xl_message_level)
+ printk(KERN_INFO "%s: Source routing counters overflow\n", dev->name);
+ }
+
+ xl_priv->xl_lan_status = lan_status ;
+
+ } /* Lan.change.status */
+ else if ( arb_cmd == RECEIVE_DATA) { /* Received.Data */
+#if XL_DEBUG
+ printk(KERN_INFO "Received.Data \n") ;
+#endif
+ writel( ((MEM_WORD_READ | 0xD0000 | xl_priv->arb) + 6), xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ xl_priv->mac_buffer = ntohs(readw(xl_mmio + MMIO_MACDATA)) ;
+
+ /* Now we are going to be really basic here and not do anything
+ * with the data at all. The tech docs do not give me enough
+ * information to calculate the buffers properly so we're
+ * just going to tell the nic that we've dealt with the frame
+ * anyway.
+ */
+
+ dev->last_rx = jiffies ;
+ /* Acknowledge interrupt, this tells nic we are done with the arb */
+ writel(ACK_INTERRUPT | ARBCACK | LATCH_ACK, xl_mmio + MMIO_COMMAND) ;
+
+ /* Is the ASB free ? */
+
+ xl_priv->asb_queued = 0 ;
+ writel( ((MEM_BYTE_READ | 0xD0000 | xl_priv->asb) + 2), xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ if (readb(xl_mmio + MMIO_MACDATA) != 0xff) {
+ xl_priv->asb_queued = 1 ;
+
+ xl_wait_misr_flags(dev) ;
+
+ writel(MEM_BYTE_WRITE | MF_ASBFR, xl_mmio + MMIO_MAC_ACCESS_CMD);
+ writeb(0xff, xl_mmio + MMIO_MACDATA) ;
+ writel(MMIO_BYTE_WRITE | MISR_SET, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(MISR_ASBFR, xl_mmio + MMIO_MACDATA) ;
+ return ;
+ /* Drop out and wait for the bottom half to be run */
+ }
+
+ xl_asb_cmd(dev) ;
+
+ } else {
+ printk(KERN_WARNING "%s: Received unknown arb (xl_priv) command: %02x \n",dev->name,arb_cmd) ;
+ }
+
+ /* Acknowledge the arb interrupt */
+
+ writel(ACK_INTERRUPT | ARBCACK | LATCH_ACK , xl_mmio + MMIO_COMMAND) ;
+
+ return ;
+}
+
+
+/*
+ * There is only one asb command, but we can get called from different
+ * places.
+ */
+
+static void xl_asb_cmd(struct net_device *dev)
+{
+ struct xl_private *xl_priv = (struct xl_private *) dev->priv ;
+ u8 __iomem * xl_mmio = xl_priv->xl_mmio ;
+
+ if (xl_priv->asb_queued == 1)
+ writel(ACK_INTERRUPT | LATCH_ACK | ASBFACK, xl_mmio + MMIO_COMMAND) ;
+
+ writel(MEM_BYTE_WRITE | 0xd0000 | xl_priv->asb, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(0x81, xl_mmio + MMIO_MACDATA) ;
+
+ writel(MEM_WORD_WRITE | 0xd0000 | xl_priv->asb | 6, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writew(ntohs(xl_priv->mac_buffer), xl_mmio + MMIO_MACDATA) ;
+
+ xl_wait_misr_flags(dev) ;
+
+ writel(MEM_BYTE_WRITE | MF_RASB, xl_mmio + MMIO_MAC_ACCESS_CMD);
+ writeb(0xff, xl_mmio + MMIO_MACDATA) ;
+
+ writel(MMIO_BYTE_WRITE | MISR_SET, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(MISR_RASB, xl_mmio + MMIO_MACDATA) ;
+
+ xl_priv->asb_queued = 2 ;
+
+ return ;
+}
+
+/*
+ * This will only get called if there was an error
+ * from the asb cmd.
+ */
+static void xl_asb_bh(struct net_device *dev)
+{
+ struct xl_private *xl_priv = (struct xl_private *) dev->priv ;
+ u8 __iomem * xl_mmio = xl_priv->xl_mmio ;
+ u8 ret_code ;
+
+ writel(MMIO_BYTE_READ | 0xd0000 | xl_priv->asb | 2, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ ret_code = readb(xl_mmio + MMIO_MACDATA) ;
+ switch (ret_code) {
+ case 0x01:
+ printk(KERN_INFO "%s: ASB Command, unrecognized command code \n",dev->name) ;
+ break ;
+ case 0x26:
+ printk(KERN_INFO "%s: ASB Command, unexpected receive buffer \n", dev->name) ;
+ break ;
+ case 0x40:
+ printk(KERN_INFO "%s: ASB Command, Invalid Station ID \n", dev->name) ;
+ break ;
+ }
+ xl_priv->asb_queued = 0 ;
+ writel(ACK_INTERRUPT | LATCH_ACK | ASBFACK, xl_mmio + MMIO_COMMAND) ;
+ return ;
+}
+
+/*
+ * Issue srb commands to the nic
+ */
+
+static void xl_srb_cmd(struct net_device *dev, int srb_cmd)
+{
+ struct xl_private *xl_priv = (struct xl_private *) dev->priv ;
+ u8 __iomem * xl_mmio = xl_priv->xl_mmio ;
+
+ switch (srb_cmd) {
+ case READ_LOG:
+ writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(READ_LOG, xl_mmio + MMIO_MACDATA) ;
+ break;
+
+ case CLOSE_NIC:
+ writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(CLOSE_NIC, xl_mmio + MMIO_MACDATA) ;
+ break ;
+
+ case SET_RECEIVE_MODE:
+ writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(SET_RECEIVE_MODE, xl_mmio + MMIO_MACDATA) ;
+ writel(MEM_WORD_WRITE | 0xD0000 | xl_priv->srb | 4, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writew(xl_priv->xl_copy_all_options, xl_mmio + MMIO_MACDATA) ;
+ break ;
+
+ case SET_FUNC_ADDRESS:
+ writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(SET_FUNC_ADDRESS, xl_mmio + MMIO_MACDATA) ;
+ writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb | 6 , xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(xl_priv->xl_functional_addr[0], xl_mmio + MMIO_MACDATA) ;
+ writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb | 7 , xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(xl_priv->xl_functional_addr[1], xl_mmio + MMIO_MACDATA) ;
+ writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb | 8 , xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(xl_priv->xl_functional_addr[2], xl_mmio + MMIO_MACDATA) ;
+ writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb | 9 , xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(xl_priv->xl_functional_addr[3], xl_mmio + MMIO_MACDATA) ;
+ break ;
+ } /* switch */
+
+
+ xl_wait_misr_flags(dev) ;
+
+ /* Write 0xff to the CSRB flag */
+ writel(MEM_BYTE_WRITE | MF_CSRB , xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(0xFF, xl_mmio + MMIO_MACDATA) ;
+ /* Set csrb bit in MISR register to process command */
+ writel(MMIO_BYTE_WRITE | MISR_SET, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(MISR_CSRB, xl_mmio + MMIO_MACDATA) ;
+ xl_priv->srb_queued = 1 ;
+
+ return ;
+}
+
+/*
+ * This is nasty, to use the MISR command you have to wait for 6 memory locations
+ * to be zero. This is the way the driver does on other OS'es so we should be ok with
+ * the empty loop.
+ */
+
+static void xl_wait_misr_flags(struct net_device *dev)
+{
+ struct xl_private *xl_priv = (struct xl_private *) dev->priv ;
+ u8 __iomem * xl_mmio = xl_priv->xl_mmio ;
+
+ int i ;
+
+ writel(MMIO_BYTE_READ | MISR_RW, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ if (readb(xl_mmio + MMIO_MACDATA) != 0) { /* Misr not clear */
+ for (i=0; i<6; i++) {
+ writel(MEM_BYTE_READ | 0xDFFE0 | i, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ while (readb(xl_mmio + MMIO_MACDATA) != 0 ) {} ; /* Empty Loop */
+ }
+ }
+
+ writel(MMIO_BYTE_WRITE | MISR_AND, xl_mmio + MMIO_MAC_ACCESS_CMD) ;
+ writeb(0x80, xl_mmio + MMIO_MACDATA) ;
+
+ return ;
+}
+
+/*
+ * Change mtu size, this should work the same as olympic
+ */
+
+static int xl_change_mtu(struct net_device *dev, int mtu)
+{
+ struct xl_private *xl_priv = (struct xl_private *) dev->priv;
+ u16 max_mtu ;
+
+ if (xl_priv->xl_ring_speed == 4)
+ max_mtu = 4500 ;
+ else
+ max_mtu = 18000 ;
+
+ if (mtu > max_mtu)
+ return -EINVAL ;
+ if (mtu < 100)
+ return -EINVAL ;
+
+ dev->mtu = mtu ;
+ xl_priv->pkt_buf_sz = mtu + TR_HLEN ;
+
+ return 0 ;
+}
+
+static void __devexit xl_remove_one (struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct xl_private *xl_priv=(struct xl_private *)dev->priv;
+
+ unregister_netdev(dev);
+ iounmap(xl_priv->xl_mmio) ;
+ pci_release_regions(pdev) ;
+ pci_set_drvdata(pdev,NULL) ;
+ free_netdev(dev);
+ return ;
+}
+
+static struct pci_driver xl_3c359_driver = {
+ .name = "3c359",
+ .id_table = xl_pci_tbl,
+ .probe = xl_probe,
+ .remove = __devexit_p(xl_remove_one),
+};
+
+static int __init xl_pci_init (void)
+{
+ return pci_module_init (&xl_3c359_driver);
+}
+
+
+static void __exit xl_pci_cleanup (void)
+{
+ pci_unregister_driver (&xl_3c359_driver);
+}
+
+module_init(xl_pci_init);
+module_exit(xl_pci_cleanup);
+
+MODULE_LICENSE("GPL") ;
diff --git a/drivers/net/tokenring/3c359.h b/drivers/net/tokenring/3c359.h
new file mode 100644
index 00000000000..05c86036885
--- /dev/null
+++ b/drivers/net/tokenring/3c359.h
@@ -0,0 +1,290 @@
+/*
+ * 3c359.h (c) 2000 Mike Phillips (mikep@linuxtr.net) All Rights Reserved
+ *
+ * Linux driver for 3Com 3C359 Token Link PCI XL cards.
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License Version 2 or (at your option)
+ * any later verion, incorporated herein by reference.
+ */
+
+/* Memory Access Commands */
+#define IO_BYTE_READ 0x28 << 24
+#define IO_BYTE_WRITE 0x18 << 24
+#define IO_WORD_READ 0x20 << 24
+#define IO_WORD_WRITE 0x10 << 24
+#define MMIO_BYTE_READ 0x88 << 24
+#define MMIO_BYTE_WRITE 0x48 << 24
+#define MMIO_WORD_READ 0x80 << 24
+#define MMIO_WORD_WRITE 0x40 << 24
+#define MEM_BYTE_READ 0x8C << 24
+#define MEM_BYTE_WRITE 0x4C << 24
+#define MEM_WORD_READ 0x84 << 24
+#define MEM_WORD_WRITE 0x44 << 24
+
+#define PMBAR 0x1C80
+#define PMB_CPHOLD (1<<10)
+
+#define CPATTENTION 0x180D
+#define CPA_PMBARVIS (1<<7)
+#define CPA_MEMWREN (1<<6)
+
+#define SWITCHSETTINGS 0x1C88
+#define EECONTROL 0x1C8A
+#define EEDATA 0x1C8C
+#define EEREAD 0x0080
+#define EEWRITE 0x0040
+#define EEERASE 0x0060
+#define EE_ENABLE_WRITE 0x0030
+#define EEBUSY (1<<15)
+
+#define WRBR 0xCDE02
+#define WWOR 0xCDE04
+#define WWCR 0xCDE06
+#define MACSTATUS 0xCDE08
+#define MISR_RW 0xCDE0B
+#define MISR_AND 0xCDE2B
+#define MISR_SET 0xCDE4B
+#define RXBUFAREA 0xCDE10
+#define RXEARLYTHRESH 0xCDE12
+#define TXSTARTTHRESH 0x58
+#define DNPRIREQTHRESH 0x2C
+
+#define MISR_CSRB (1<<5)
+#define MISR_RASB (1<<4)
+#define MISR_SRBFR (1<<3)
+#define MISR_ASBFR (1<<2)
+#define MISR_ARBF (1<<1)
+
+/* MISR Flags memory locations */
+#define MF_SSBF 0xDFFE0
+#define MF_ARBF 0xDFFE1
+#define MF_ASBFR 0xDFFE2
+#define MF_SRBFR 0xDFFE3
+#define MF_RASB 0xDFFE4
+#define MF_CSRB 0xDFFE5
+
+#define MMIO_MACDATA 0x10
+#define MMIO_MAC_ACCESS_CMD 0x14
+#define MMIO_TIMER 0x1A
+#define MMIO_DMA_CTRL 0x20
+#define MMIO_DNLISTPTR 0x24
+#define MMIO_HASHFILTER 0x28
+#define MMIO_CONFIG 0x29
+#define MMIO_DNPRIREQTHRESH 0x2C
+#define MMIO_DNPOLL 0x2D
+#define MMIO_UPPKTSTATUS 0x30
+#define MMIO_FREETIMER 0x34
+#define MMIO_COUNTDOWN 0x36
+#define MMIO_UPLISTPTR 0x38
+#define MMIO_UPPOLL 0x3C
+#define MMIO_UPBURSTTHRESH 0x40
+#define MMIO_DNBURSTTHRESH 0x41
+#define MMIO_INTSTATUS_AUTO 0x56
+#define MMIO_TXSTARTTHRESH 0x58
+#define MMIO_INTERRUPTENABLE 0x5A
+#define MMIO_INDICATIONENABLE 0x5C
+#define MMIO_COMMAND 0x5E /* These two are meant to be the same */
+#define MMIO_INTSTATUS 0x5E /* Makes the code more readable this way */
+#define INTSTAT_CMD_IN_PROGRESS (1<<12)
+#define INTSTAT_SRB (1<<14)
+#define INTSTAT_INTLATCH (1<<0)
+
+/* Indication / Interrupt Mask
+ * Annoyingly the bits to be set in the indication and interrupt enable
+ * do not match with the actual bits received in the interrupt, although
+ * they are in the same order.
+ * The mapping for the indication / interrupt are:
+ * Bit Indication / Interrupt
+ * 0 HostError
+ * 1 txcomplete
+ * 2 updneeded
+ * 3 rxcomplete
+ * 4 intrequested
+ * 5 macerror
+ * 6 dncomplete
+ * 7 upcomplete
+ * 8 txunderrun
+ * 9 asbf
+ * 10 srbr
+ * 11 arbc
+ *
+ * The only ones we don't want to receive are txcomplete and rxcomplete
+ * we use dncomplete and upcomplete instead.
+ */
+
+#define INT_MASK 0xFF5
+
+/* Note the subtle difference here, IND and INT */
+
+#define SETINDENABLE (8<<12)
+#define SETINTENABLE (7<<12)
+#define SRBBIT (1<<10)
+#define ASBBIT (1<<9)
+#define ARBBIT (1<<11)
+
+#define SRB 0xDFE90
+#define ASB 0xDFED0
+#define ARB 0xD0000
+#define SCRATCH 0xDFEF0
+
+#define INT_REQUEST 0x6000 /* (6 << 12) */
+#define ACK_INTERRUPT 0x6800 /* (13 <<11) */
+#define GLOBAL_RESET 0x00
+#define DNDISABLE 0x5000
+#define DNENABLE 0x4800
+#define DNSTALL 0x3002
+#define DNRESET 0x5800
+#define DNUNSTALL 0x3003
+#define UPRESET 0x2800
+#define UPSTALL 0x3000
+#define UPUNSTALL 0x3001
+#define SETCONFIG 0x4000
+#define SETTXSTARTTHRESH 0x9800
+
+/* Received Interrupts */
+#define ASBFINT (1<<13)
+#define SRBRINT (1<<14)
+#define ARBCINT (1<<15)
+#define TXUNDERRUN (1<<11)
+
+#define UPCOMPINT (1<<10)
+#define DNCOMPINT (1<<9)
+#define HARDERRINT (1<<7)
+#define RXCOMPLETE (1<<4)
+#define TXCOMPINT (1<<2)
+#define HOSTERRINT (1<<1)
+
+/* Receive descriptor bits */
+#define RXOVERRUN (1<<19)
+#define RXFC (1<<21)
+#define RXAR (1<<22)
+#define RXUPDCOMPLETE (1<<23)
+#define RXUPDFULL (1<<24)
+#define RXUPLASTFRAG (1<<31)
+
+/* Transmit descriptor bits */
+#define TXDNCOMPLETE (1<<16)
+#define TXTXINDICATE (1<<27)
+#define TXDPDEMPTY (1<<29)
+#define TXDNINDICATE (1<<31)
+#define TXDNFRAGLAST (1<<31)
+
+/* Interrupts to Acknowledge */
+#define LATCH_ACK 1
+#define TXCOMPACK (1<<1)
+#define INTREQACK (1<<2)
+#define DNCOMPACK (1<<3)
+#define UPCOMPACK (1<<4)
+#define ASBFACK (1<<5)
+#define SRBRACK (1<<6)
+#define ARBCACK (1<<7)
+
+#define XL_IO_SPACE 128
+#define SRB_COMMAND_SIZE 50
+
+/* Adapter Commands */
+#define REQUEST_INT 0x00
+#define MODIFY_OPEN_PARMS 0x01
+#define RESTORE_OPEN_PARMS 0x02
+#define OPEN_NIC 0x03
+#define CLOSE_NIC 0x04
+#define SET_SLEEP_MODE 0x05
+#define SET_GROUP_ADDRESS 0x06
+#define SET_FUNC_ADDRESS 0x07
+#define READ_LOG 0x08
+#define SET_MULTICAST_MODE 0x0C
+#define CHANGE_WAKEUP_PATTERN 0x0D
+#define GET_STATISTICS 0x13
+#define SET_RECEIVE_MODE 0x1F
+
+/* ARB Commands */
+#define RECEIVE_DATA 0x81
+#define RING_STATUS_CHANGE 0x84
+
+/* ASB Commands */
+#define ASB_RECEIVE_DATE 0x81
+
+/* Defines for LAN STATUS CHANGE reports */
+#define LSC_SIG_LOSS 0x8000
+#define LSC_HARD_ERR 0x4000
+#define LSC_SOFT_ERR 0x2000
+#define LSC_TRAN_BCN 0x1000
+#define LSC_LWF 0x0800
+#define LSC_ARW 0x0400
+#define LSC_FPE 0x0200
+#define LSC_RR 0x0100
+#define LSC_CO 0x0080
+#define LSC_SS 0x0040
+#define LSC_RING_REC 0x0020
+#define LSC_SR_CO 0x0010
+#define LSC_FDX_MODE 0x0004
+
+#define XL_MAX_ADAPTERS 8 /* 0x08 __MODULE_STRING can't hand 0xnn */
+
+/* 3c359 defaults for buffers */
+
+#define XL_RX_RING_SIZE 16 /* must be a power of 2 */
+#define XL_TX_RING_SIZE 16 /* must be a power of 2 */
+
+#define PKT_BUF_SZ 4096 /* Default packet size */
+
+/* 3c359 data structures */
+
+struct xl_tx_desc {
+ u32 dnnextptr ;
+ u32 framestartheader ;
+ u32 buffer ;
+ u32 buffer_length ;
+};
+
+struct xl_rx_desc {
+ u32 upnextptr ;
+ u32 framestatus ;
+ u32 upfragaddr ;
+ u32 upfraglen ;
+};
+
+struct xl_private {
+
+
+ /* These two structures must be aligned on 8 byte boundaries */
+
+ /* struct xl_rx_desc xl_rx_ring[XL_RX_RING_SIZE]; */
+ /* struct xl_tx_desc xl_tx_ring[XL_TX_RING_SIZE]; */
+ struct xl_rx_desc *xl_rx_ring ;
+ struct xl_tx_desc *xl_tx_ring ;
+ struct sk_buff *tx_ring_skb[XL_TX_RING_SIZE], *rx_ring_skb[XL_RX_RING_SIZE];
+ int tx_ring_head, tx_ring_tail ;
+ int rx_ring_tail, rx_ring_no ;
+ int free_ring_entries ;
+
+ u16 srb;
+ u16 arb;
+ u16 asb;
+
+ u8 __iomem *xl_mmio;
+ char *xl_card_name;
+ struct pci_dev *pdev ;
+
+ spinlock_t xl_lock ;
+
+ volatile int srb_queued;
+ struct wait_queue *srb_wait;
+ volatile int asb_queued;
+
+ struct net_device_stats xl_stats ;
+
+ u16 mac_buffer ;
+ u16 xl_lan_status ;
+ u8 xl_ring_speed ;
+ u16 pkt_buf_sz ;
+ u8 xl_message_level;
+ u16 xl_copy_all_options ;
+ unsigned char xl_functional_addr[4] ;
+ u16 xl_addr_table_addr, xl_parms_addr ;
+ u8 xl_laa[6] ;
+ u32 rx_ring_dma_addr ;
+ u32 tx_ring_dma_addr ;
+};
+
diff --git a/drivers/net/tokenring/3c359_microcode.h b/drivers/net/tokenring/3c359_microcode.h
new file mode 100644
index 00000000000..81354afa3d3
--- /dev/null
+++ b/drivers/net/tokenring/3c359_microcode.h
@@ -0,0 +1,1581 @@
+
+/*
+ * The firmware this driver downloads into the tokenring card is a
+ * separate program and is not GPL'd source code, even though the Linux
+ * side driver and the routine that loads this data into the card are.
+ *
+ * This firmware is licensed to you strictly for use in conjunction
+ * with the use of 3Com 3C359 TokenRing adapters. There is no
+ * waranty expressed or implied about its fitness for any purpose.
+ */
+
+/* 3c359_microcode.mac: 3Com 3C359 Tokenring microcode.
+ *
+ * Notes:
+ * - Loaded from xl_init upon adapter initialization.
+ *
+ * Available from 3Com as part of their standard 3C359 driver.
+ *
+ * mc_size *must* must match the microcode being used, each version is a
+ * different length.
+ */
+
+static int mc_size = 24880 ;
+
+u8 microcode[] = {
+ 0xfe,0x3a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x33,0x2f,0x30,0x32,0x2f,0x39,0x39,0x20,0x31
+,0x37,0x3a,0x31,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46
+,0x00,0x00,0x07,0xff,0x02,0x00,0xfe,0x9f,0x06,0x00,0x00,0x7c,0x48,0x00,0x00,0x70
+,0x82,0x00,0xff,0xff,0x86,0x00,0xff,0xff,0x88,0x00,0xff,0xff,0x9a,0x00,0xff,0xff
+,0xff,0xff,0x11,0x00,0xc0,0x00,0xff,0xff,0xff,0xff,0x11,0x22,0x33,0x44,0x55,0x66
+,0x33,0x43,0x4f,0x4d,0x20,0x42,0x41,0x42,0x45,0x11,0x40,0xc0,0x00,0xff,0xff,0xff
+,0xff,0x11,0x22,0x33,0x44,0x55,0x66,0x53,0x74,0x61,0x72,0x74,0x20,0x6f,0x66,0x20
+,0x4c,0x4c,0x43,0x20,0x66,0x72,0x61,0x6d,0x65,0x2e,0x20,0x20,0x54,0x6f,0x74,0x61
+,0x6c,0x20,0x64,0x61,0x74,0x61,0x20,0x73,0x69,0x7a,0x65,0x20,0x69,0x73,0x20,0x78
+,0x78,0x78,0x20,0x20,0x20,0x42,0x41,0x42,0x45,0xe8,0xd2,0x01,0x83,0x3e,0xf7,0x34
+,0x00,0x75,0x21,0xe8,0x41,0x00,0x83,0x3e,0xf7,0x34,0x00,0x75,0x17,0xe8,0x82,0x00
+,0x83,0x3e,0xf7,0x34,0x00,0x75,0x0d,0xe8,0xbf,0x00,0x83,0x3e,0xf7,0x34,0x00,0x75
+,0x03,0xe8,0x41,0x02,0xc3,0x1e,0xb8,0x00,0xf0,0x8e,0xd8,0x33,0xf6,0xb9,0x00,0x80
+,0x33,0xdb,0xad,0x03,0xd8,0xe2,0xfb,0x1f,0xb8,0x00,0x00,0x83,0xfb,0x00,0x74,0x03
+,0xb8,0x22,0x00,0xa3,0xf7,0x34,0xc3,0xfa,0xba,0x56,0x00,0xb0,0xff,0xee,0x33,0xc0
+,0x8e,0xc0,0x33,0xf6,0xb9,0xff,0x7f,0x83,0x3e,0xff,0x34,0x00,0x74,0x08,0x8d,0x3e
+,0x30,0x61,0xd1,0xef,0x2b,0xcf,0x26,0x8b,0x1c,0x26,0xc7,0x04,0xff,0xff,0x26,0x83
+,0x3c,0xff,0x75,0x17,0x26,0xc7,0x04,0x00,0x00,0x26,0x83,0x3c,0x00,0x75,0x0c,0x26
+,0x89,0x1c,0x46,0x46,0xe2,0xe0,0xb8,0x00,0x00,0xeb,0x03,0xb8,0x24,0x00,0xa3,0xf7
+,0x34,0xc3,0xfa,0xb4,0xd7,0x9e,0x73,0x3a,0x75,0x38,0x79,0x36,0x7b,0x34,0x9f,0xb1
+,0x05,0xd2,0xec,0x73,0x2d,0xb0,0x40,0xd0,0xe0,0x71,0x27,0x79,0x25,0xd0,0xe0,0x73
+,0x21,0x7b,0x1f,0x32,0xc0,0x75,0x1b,0x32,0xe4,0x9e,0x72,0x16,0x74,0x14,0x78,0x12
+,0x7a,0x10,0x9f,0xd2,0xec,0x72,0x0b,0xd0,0xe4,0x70,0x07,0x75,0x05,0xb8,0x00,0x00
+,0xeb,0x03,0xb8,0x26,0x00,0xa3,0xf7,0x34,0xc3,0xfa,0xba,0x5a,0x00,0x33,0xc0,0xef
+,0xef,0xef,0xef,0xb0,0x00,0xe6,0x56,0xb0,0x00,0xe6,0x54,0xba,0x52,0x00,0xb8,0x01
+,0x01,0xef,0xe8,0xca,0x00,0x3c,0x01,0x75,0x7f,0xe8,0x83,0x00,0xba,0x52,0x00,0xb8
+,0x02,0x02,0xef,0xe8,0xb9,0x00,0x3c,0x02,0x75,0x6e,0xe8,0x7a,0x00,0xba,0x52,0x00
+,0xb8,0x04,0x04,0xef,0xe8,0xa8,0x00,0x3c,0x04,0x75,0x5d,0xe8,0x71,0x00,0xba,0x52
+,0x00,0xb8,0x08,0x08,0xef,0xe8,0x97,0x00,0x3c,0x08,0x75,0x4c,0xe8,0x68,0x00,0xba
+,0x52,0x00,0xb8,0x10,0x10,0xef,0xe8,0x86,0x00,0x3c,0x10,0x75,0x3b,0xe8,0x5f,0x00
+,0xba,0x52,0x00,0xb8,0x20,0x20,0xef,0xe8,0x75,0x00,0x3c,0x20,0x75,0x2a,0xe8,0x56
+,0x00,0xba,0x52,0x00,0xb8,0x40,0x40,0xef,0xe8,0x64,0x00,0x3c,0x40,0x75,0x19,0xe8
+,0x4d,0x00,0xba,0x52,0x00,0xb8,0x80,0x80,0xef,0xe8,0x53,0x00,0x3c,0x80,0x75,0x08
+,0xe8,0x44,0x00,0xb8,0x00,0x00,0xeb,0x03,0xb8,0x28,0x00,0xa3,0xf7,0x34,0xc3,0xba
+,0x5a,0x00,0xb8,0x00,0x80,0xef,0xc3,0xba,0x5a,0x00,0xb8,0x01,0x80,0xef,0xc3,0xba
+,0x5a,0x00,0xb8,0x02,0x80,0xef,0xc3,0xba,0x5a,0x00,0xb8,0x03,0x80,0xef,0xc3,0xba
+,0x5a,0x00,0xb8,0x04,0x80,0xef,0xc3,0xba,0x5a,0x00,0xb8,0x05,0x80,0xef,0xc3,0xba
+,0x5a,0x00,0xb8,0x06,0x80,0xef,0xc3,0xba,0x5a,0x00,0xb8,0x07,0x80,0xef,0xc3,0xb9
+,0xff,0xff,0xe4,0x58,0xe4,0x54,0x3c,0x00,0x75,0x03,0x49,0x75,0xf7,0xc3,0xfa,0x32
+,0xc0,0xe6,0x56,0xe4,0x56,0x3c,0x00,0x74,0x03,0xe9,0x82,0x00,0xb0,0xff,0xe6,0x56
+,0xe4,0x56,0x3c,0xff,0x75,0x78,0xba,0x52,0x00,0xb8,0xff,0xff,0xef,0xed,0x3c,0xff
+,0x75,0x6c,0xb8,0x00,0xff,0xef,0xed,0x3c,0x00,0x75,0x63,0xb0,0xff,0xe6,0x54,0xe4
+,0x54,0x3c,0xff,0x75,0x59,0x32,0xc0,0xe6,0x54,0xe4,0x54,0x3c,0x00,0x75,0x4f,0xb0
+,0x0f,0xe6,0x50,0xe4,0x50,0x24,0x0f,0x3c,0x0f,0x75,0x43,0xb0,0x00,0xe6,0x50,0xe4
+,0x50,0x24,0x0f,0x3c,0x00,0x75,0x37,0x8c,0xc8,0x8e,0xc0,0xbe,0x70,0x00,0x26,0x8b
+,0x14,0x26,0x8b,0x5c,0x02,0xb8,0x00,0x00,0xef,0xed,0x23,0xc3,0x3d,0x00,0x00,0x75
+,0x1d,0xb8,0xff,0xff,0x23,0xc3,0xef,0x8b,0xc8,0xed,0x23,0xc3,0x3b,0xc1,0x75,0x0e
+,0x83,0xc6,0x04,0x26,0x83,0x3c,0xff,0x75,0xd5,0xb8,0x00,0x00,0xeb,0x03,0xb8,0x2a
+,0x00,0xa3,0xf7,0x34,0xc3,0xfa,0x33,0xc0,0xbf,0x00,0x20,0xb9,0x17,0x00,0xf3,0xab
+,0xbf,0x00,0x30,0xb9,0x17,0x00,0xf3,0xab,0xbf,0x00,0x22,0xb9,0x40,0x00,0xf3,0xab
+,0xbf,0x00,0x32,0xb9,0x40,0x00,0xf3,0xab,0xfc,0x1e,0x8c,0xc8,0x8e,0xd8,0x33,0xc0
+,0x8e,0xc0,0xbe,0x92,0x00,0xbf,0x00,0x20,0xb9,0x17,0x00,0xf3,0xa4,0xbe,0xa9,0x00
+,0xbf,0x00,0x22,0xb9,0x40,0x00,0xf3,0xa4,0x1f,0xc7,0x06,0xfb,0x34,0x64,0x00,0xba
+,0x08,0x00,0xb8,0x0f,0x00,0xef,0xe8,0x82,0x01,0xe8,0x9b,0x01,0x72,0x0d,0xc7,0x06
+,0xf7,0x34,0x2c,0x00,0xc7,0x06,0xf9,0x34,0x04,0x00,0xc3,0xba,0x0a,0x00,0x33,0xc0
+,0xef,0xe8,0x98,0x01,0xe8,0xb5,0x01,0xb8,0x17,0x00,0xba,0x9c,0x00,0xef,0xb8,0x00
+,0x10,0xba,0x9a,0x00,0xef,0xb8,0x17,0x00,0xa9,0x01,0x00,0x74,0x01,0x40,0xba,0x8c
+,0x00,0xef,0xb8,0x00,0x18,0xba,0x86,0x00,0xef,0xb8,0x0c,0x00,0xba,0x82,0x00,0xef
+,0xba,0x02,0x00,0xed,0x25,0xf9,0xff,0x0d,0x02,0x00,0xef,0xba,0x06,0x00,0x33,0xc0
+,0xef,0xba,0x04,0x00,0xb8,0x60,0x00,0xef,0xba,0x00,0x00,0xb8,0x18,0x00,0xef,0xba
+,0x80,0x00,0xb9,0xff,0xff,0xed,0xa9,0x01,0x00,0x75,0x04,0xe2,0xf8,0xeb,0x3e,0xba
+,0x0a,0x00,0xed,0xa9,0x00,0x40,0x74,0x35,0xa9,0x00,0x20,0x74,0x30,0x33,0xc0,0xef
+,0x51,0xb9,0xc8,0x00,0xe2,0xfe,0x59,0x1e,0x06,0x1f,0x26,0x8b,0x0e,0x02,0x30,0x83
+,0xf9,0x17,0x75,0x18,0x49,0x49,0xbe,0x02,0x20,0xbf,0x06,0x30,0xf3,0xa6,0x1f,0x23
+,0xc9,0x75,0x0a,0xff,0x0e,0xfb,0x34,0x74,0x12,0xe9,0x4d,0xff,0x1f,0xb8,0x2c,0x00
+,0xbb,0x00,0x00,0xa3,0xf7,0x34,0x89,0x1e,0xf9,0x34,0xc3,0xc7,0x06,0xfb,0x34,0x64
+,0x00,0xe8,0xd3,0x00,0x72,0x0d,0xc7,0x06,0xf7,0x34,0x2c,0x00,0xc7,0x06,0xf9,0x34
+,0x04,0x00,0xc3,0xe8,0xd6,0x00,0xe8,0xf3,0x00,0xb8,0x03,0x00,0xba,0x82,0x00,0xef
+,0xb8,0x40,0x80,0xba,0x98,0x00,0xef,0xb8,0x00,0x11,0xba,0x96,0x00,0xef,0xb8,0x40
+,0x00,0xa9,0x01,0x00,0x74,0x01,0x40,0xba,0x92,0x00,0xef,0xb8,0x00,0x19,0xba,0x8e
+,0x00,0xef,0xba,0x02,0x00,0xed,0x25,0xf9,0xff,0x0d,0x06,0x00,0xef,0xba,0x06,0x00
+,0x33,0xc0,0xef,0xba,0x00,0x00,0xb8,0x18,0x00,0xef,0xba,0x80,0x00,0xb9,0xff,0xff
+,0xed,0xa9,0x20,0x00,0x75,0x04,0xe2,0xf8,0xeb,0x43,0xba,0x0a,0x00,0xed,0xa9,0x00
+,0x40,0x74,0x3a,0xa9,0x00,0x20,0x74,0x35,0x33,0xc0,0xef,0x51,0xb9,0xc8,0x00,0xe2
+,0xfe,0x59,0x1e,0x06,0x1f,0x26,0x8b,0x0e,0x02,0x32,0x83,0xf9,0x40,0x75,0x1d,0x49
+,0x49,0xbe,0x02,0x22,0xbf,0x06,0x32,0xf3,0xa6,0x1f,0x23,0xc9,0x75,0x0f,0xff,0x0e
+,0xfb,0x34,0x74,0x03,0xe9,0x5a,0xff,0xb8,0x00,0x00,0xeb,0x0b,0x1f,0xb8,0x2c,0x00
+,0xbb,0x02,0x00,0x89,0x1e,0xf9,0x34,0xa3,0xf7,0x34,0xc3,0xba,0x02,0x00,0xb8,0x00
+,0x9c,0xef,0xba,0x00,0x00,0xb8,0x00,0x84,0xef,0x33,0xc0,0xef,0xba,0x0a,0x00,0xef
+,0xba,0x0e,0x00,0x33,0xc0,0xef,0xc3,0xba,0x0a,0x00,0xb9,0xff,0xff,0xed,0x25,0x00
+,0x60,0x3d,0x00,0x60,0x74,0x04,0xe2,0xf5,0xf8,0xc3,0xf9,0xc3,0xb0,0x00,0xe6,0x56
+,0xb8,0x00,0xff,0xba,0x52,0x00,0xef,0xb9,0xff,0xff,0xba,0x58,0x00,0xed,0x25,0xef
+,0x00,0x74,0x08,0xba,0x5a,0x00,0x33,0xc0,0xef,0xe2,0xef,0xc3,0xba,0x80,0x00,0xed
+,0xba,0x84,0x00,0xef,0xba,0x80,0x00,0xed,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0xc6,0x06,0xec,0x34,0x15,0x33,0xc0,0x8e,0xd8,0x8e,0xc0,0x1e,0x8c,0xc8,0xbe,0x40
+,0x54,0xbf,0x60,0xfe,0x8e,0xd8,0xb9,0x10,0x00,0xf3,0xa4,0x1f,0xc7,0x06,0x80,0x36
+,0x10,0x35,0xc7,0x06,0x8c,0x36,0x30,0x35,0x8d,0x06,0x38,0x35,0xa3,0x30,0x35,0xa3
+,0x32,0x35,0x05,0x33,0x01,0xa3,0x34,0x35,0xc7,0x06,0x36,0x35,0x50,0x01,0xc7,0x06
+,0x84,0x36,0x80,0xfe,0xc7,0x06,0x88,0x36,0xc0,0xfe,0xc6,0x06,0xc2,0xfe,0xff,0xc6
+,0x06,0x93,0x36,0x80,0xc6,0x06,0x92,0x36,0x00,0xc6,0x06,0x80,0xfe,0x80,0xc7,0x06
+,0x82,0xfe,0x54,0x50,0xc7,0x06,0x84,0xfe,0x2b,0x4d,0xe5,0xce,0xa9,0x02,0x00,0x75
+,0x08,0xc6,0x06,0x81,0xfe,0x23,0xe9,0x05,0x00,0xc6,0x06,0x81,0xfe,0x22,0xa1,0xf7
+,0x34,0xa3,0x86,0xfe,0xb8,0x48,0x34,0x86,0xe0,0xa3,0x88,0xfe,0x8d,0x06,0x4e,0x34
+,0x86,0xe0,0xa3,0x8a,0xfe,0xb8,0x58,0x34,0x86,0xe0,0xa3,0x8c,0xfe,0xb8,0x9c,0x34
+,0x86,0xe0,0xa3,0x8e,0xfe,0x8d,0x06,0x20,0x03,0x86,0xe0,0xa3,0x90,0xfe,0x33,0xc0
+,0xba,0x72,0x00,0xef,0x33,0xc0,0xba,0x74,0x00,0xef,0xba,0x76,0x00,0xef,0xb8,0x80
+,0xfe,0x86,0xe0,0xba,0x72,0x00,0xef,0xe8,0xbf,0x07,0xba,0x0c,0x01,0xb8,0x40,0x40
+,0xef,0xed,0xba,0x6a,0x00,0xb8,0x03,0x00,0xc1,0xe0,0x08,0x0d,0x03,0x00,0xef,0xb9
+,0x0a,0x00,0xe8,0x94,0x00,0xba,0x6a,0x00,0xb8,0x03,0x00,0xc1,0xe0,0x08,0xef,0xa1
+,0x32,0x34,0xa3,0xa2,0x33,0xc7,0x06,0xa6,0x33,0x04,0x00,0x8d,0x06,0xa0,0x33,0xc1
+,0xe8,0x04,0xcd,0x39,0xc7,0x06,0x90,0x36,0xff,0xff,0xe9,0xe3,0x00,0x63,0x0d,0x66
+,0x0d,0x66,0x0d,0x8a,0x0d,0xe6,0x0e,0x75,0x12,0x2e,0x0f,0x03,0x0f,0x50,0x0f,0x60
+,0x0d,0x60,0x0d,0x60,0x0d,0xed,0x0f,0xe9,0x12,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60
+,0x0d,0x60,0x0d,0x22,0x10,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0xfe,0x10,0x60
+,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0xaf,0x0f,0x32,0x10,0x37
+,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60
+,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60,0x0d,0x60
+,0x0d,0x64,0x0e,0x00,0x0f,0x95,0x09,0x60,0x0a,0x49,0xbb,0xff,0xff,0xba,0x6a,0x00
+,0xed,0xa9,0x00,0x20,0x74,0x38,0x80,0x3e,0x80,0xfe,0x12,0x75,0x31,0xe8,0x4a,0x00
+,0xa1,0x32,0x34,0xa3,0xa2,0x33,0xc7,0x06,0xa6,0x33,0x04,0x00,0x8d,0x06,0xa0,0x33
+,0xc1,0xe8,0x04,0xcd,0x39,0xe8,0x22,0x00,0xc7,0x06,0xf3,0x34,0x46,0x00,0xc7,0x06
+,0xf5,0x34,0xff,0xff,0xc7,0x06,0x90,0x36,0xff,0xff,0x58,0xe9,0x32,0x00,0x4b,0x83
+,0xfb,0x00,0x75,0xb9,0x83,0xf9,0x00,0x75,0xb0,0xc3,0x52,0xba,0x6a,0x00,0xb8,0x03
+,0x00,0xc1,0xe0,0x08,0x0d,0x03,0x00,0xef,0x5a,0xc3,0x52,0xba,0x6a,0x00,0xb8,0x03
+,0x00,0xc1,0xe0,0x08,0xef,0x5a,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x68,0x80,0x07,0xa1,0x90,0x36,0xcd,0x35,0x8b,0x36,0x24,0x02,0x2e,0xff,0xa4,0x35
+,0x0a,0xfa,0x8a,0x26,0x94,0x36,0x88,0x26,0xe8,0x34,0xc6,0x06,0x94,0x36,0x00,0xfb
+,0x22,0xe4,0x75,0x01,0xc3,0xf6,0xc4,0x20,0x74,0x7d,0xf6,0xc4,0x08,0x74,0x05,0x80
+,0x0e,0x92,0x36,0x04,0x80,0x26,0xe8,0x34,0xd7,0xc4,0x1e,0x84,0x36,0x26,0x8b,0x37
+,0x81,0xe6,0xff,0x00,0x83,0xfe,0x20,0x76,0x05,0xb0,0x01,0xe9,0x28,0x00,0x53,0x06
+,0xd1,0xe6,0x2e,0xff,0x94,0x9d,0x06,0x07,0x5b,0x26,0x88,0x47,0x02,0x3c,0xff,0x74
+,0x07,0x3c,0xfe,0x75,0x11,0xe9,0x3b,0x00,0xf6,0x06,0x92,0x36,0x08,0x75,0x34,0xf6
+,0x06,0x92,0x36,0x04,0x74,0x2d,0x80,0x26,0x92,0x36,0xf3,0x80,0x3e,0x95,0x36,0x00
+,0x75,0x21,0x26,0x80,0x3f,0x05,0x75,0x13,0xc6,0x06,0x95,0x36,0x00,0x26,0x80,0x7f
+,0x06,0x00,0x74,0x07,0x26,0x8b,0x47,0x04,0xa2,0x95,0x36,0xba,0x0c,0x01,0xb8,0x40
+,0x40,0xef,0xed,0x8a,0x26,0xe8,0x34,0xf6,0xc4,0x10,0x75,0x03,0xe9,0x5b,0x00,0xf6
+,0xc4,0x04,0x74,0x05,0x80,0x0e,0x92,0x36,0x01,0x80,0x26,0xe8,0x34,0xeb,0xc4,0x3e
+,0x88,0x36,0x26,0x8b,0x35,0x83,0xe6,0x7f,0x83,0xfe,0x12,0x72,0x08,0x26,0xc6,0x45
+,0x02,0x01,0xe9,0x24,0x00,0x83,0xc6,0x20,0xd1,0xe6,0x2e,0xff,0x94,0x9d,0x06,0xc4
+,0x3e,0x88,0x36,0x26,0x88,0x45,0x02,0x3c,0xff,0x75,0x0e,0xf6,0x06,0x92,0x36,0x01
+,0x74,0x14,0xf6,0x06,0x92,0x36,0x02,0x75,0x0d,0x80,0x26,0x92,0x36,0xfc,0xba,0x0c
+,0x01,0xb8,0x20,0x20,0xef,0xed,0x8a,0x26,0xe8,0x34,0xf6,0xc4,0x08,0x74,0x22,0x80
+,0x26,0xe8,0x34,0xf7,0x80,0x0e,0x92,0x36,0x04,0xf6,0x06,0x92,0x36,0x08,0x74,0x11
+,0x80,0x26,0x92,0x36,0xf3,0xba,0x0c,0x01,0xb8,0x40,0x40,0xef,0xed,0x8a,0x26,0xe8
+,0x34,0xf6,0xc4,0x04,0x74,0x22,0x80,0x26,0xe8,0x34,0xfb,0x80,0x0e,0x92,0x36,0x01
+,0xf6,0x06,0x92,0x36,0x02,0x75,0x11,0x80,0x26,0x92,0x36,0xfe,0xba,0x0c,0x01,0xb8
+,0x20,0x20,0xef,0xed,0x8a,0x26,0xe8,0x34,0xf6,0xc4,0x01,0x74,0x67,0x80,0x26,0xe8
+,0x34,0xfe,0x80,0x3e,0xe8,0xff,0x00,0x74,0x39,0x80,0x3e,0xe8,0xff,0x04,0x74,0x32
+,0x80,0x3e,0xe8,0xff,0x01,0x75,0x21,0xe5,0x80,0xa9,0x00,0x07,0x74,0x0a,0xba,0x9e
+,0x00,0xb8,0x00,0x02,0xef,0xe9,0xef,0xff,0xc6,0x06,0xe8,0xff,0x03,0xba,0x0c,0x01
+,0xb8,0x08,0x08,0xef,0xed,0xe9,0x28,0x00,0x80,0x3e,0xe8,0xff,0x03,0x74,0x06,0xe9
+,0x1e,0x00,0xe9,0x00,0x00,0xba,0x10,0x01,0xb8,0x02,0x02,0xef,0xed,0xe5,0x00,0x0d
+,0x18,0x00,0xe7,0x00,0xe5,0x82,0x0d,0x02,0x00,0xe7,0x82,0xc6,0x06,0xe8,0xff,0x04
+,0x8a,0x26,0xe8,0x34,0xf6,0xc4,0x02,0x74,0x0d,0x80,0x26,0xe8,0x34,0xfd,0x80,0x26
+,0x92,0x36,0xbf,0xe8,0x4f,0x0b,0xfa,0xa0,0xe8,0x34,0x08,0x06,0x94,0x36,0xc6,0x06
+,0xe8,0x34,0x00,0xfb,0xc3,0xe8,0xe7,0x0f,0xc4,0x1e,0x84,0x36,0x2e,0xff,0x16,0x01
+,0x07,0x26,0x88,0x47,0x02,0xe9,0x7e,0xfe,0xe8,0x2d,0x10,0xc4,0x1e,0x84,0x36,0x2e
+,0xff,0x16,0x03,0x07,0x26,0x88,0x47,0x02,0xe9,0x6b,0xfe,0x8e,0x06,0x26,0x02,0x2e
+,0xff,0x16,0x07,0x07,0xc3,0xc3,0x83,0x3e,0xf5,0x34,0x00,0x74,0x0f,0xff,0x0e,0xf3
+,0x34,0x75,0x09,0xe8,0xc4,0xfd,0xc7,0x06,0xf5,0x34,0x00,0x00,0xf6,0x06,0x93,0x36
+,0x20,0x74,0x30,0xa1,0xc2,0x34,0x3b,0x06,0xe9,0x34,0xa3,0xe9,0x34,0x74,0x24,0x80
+,0x3e,0x95,0x36,0x00,0x75,0x1d,0xf7,0x06,0xe6,0x34,0x20,0x00,0x74,0x12,0xa9,0x20
+,0x00,0x74,0x0d,0x83,0x26,0xc2,0x34,0xdf,0x83,0x26,0xe9,0x34,0xdf,0xe9,0x03,0x00
+,0xe8,0xdd,0x09,0xba,0x06,0x01,0xed,0x8b,0xd0,0x81,0xe2,0x00,0xc0,0xc1,0xea,0x0e
+,0x03,0x16,0x74,0x34,0xc1,0xe0,0x02,0x11,0x06,0x72,0x34,0x73,0x04,0xff,0x06,0x74
+,0x34,0xba,0x02,0x01,0xed,0x8b,0xd0,0x81,0xe2,0x00,0xc0,0xc1,0xea,0x0e,0x03,0x16
+,0x70,0x34,0xc1,0xe0,0x02,0x11,0x06,0x6e,0x34,0x73,0x04,0xff,0x06,0x70,0x34,0xc7
+,0x06,0xa6,0x33,0x04,0x00,0xc7,0x06,0xaa,0x33,0x00,0x00,0x8d,0x06,0xa0,0x33,0xc1
+,0xe8,0x04,0xcd,0x39,0xc3,0x95,0x09,0x95,0x09,0x65,0x09,0x78,0x09,0x95,0x09,0x95
+,0x09,0x91,0x07,0x95,0x09,0x96,0x09,0x8b,0x09,0x95,0x09,0x95,0x09,0x95,0x09,0x95
+,0x09,0x95,0x09,0x95,0x09,0x8b,0xc0,0x8b,0xc0,0x8b,0xc0,0x8b,0xc0,0x8b,0xc0,0x90
+,0xf6,0x06,0x93,0x36,0x20,0x75,0x03,0xe9,0xcc,0x00,0x8c,0xc0,0x40,0x8e,0xc0,0x26
+,0x8b,0x0e,0x06,0x00,0x86,0xe9,0x26,0x89,0x0e,0x06,0x00,0x8c,0xc2,0xc1,0xe2,0x04
+,0xbe,0x0e,0x00,0x26,0xa1,0x04,0x00,0xd0,0xe0,0x24,0xc0,0x8a,0xe0,0xc0,0xec,0x04
+,0x0a,0xc4,0x26,0xa2,0x05,0x00,0x26,0xa1,0x08,0x00,0xa9,0x00,0xc0,0x74,0x03,0xe9
+,0x9e,0x00,0x26,0xf6,0x06,0x10,0x00,0x80,0x75,0x03,0xe9,0x0a,0x00,0x26,0xa0,0x16
+,0x00,0x24,0x1f,0x32,0xe4,0x03,0xf0,0x80,0x3e,0xec,0x34,0x06,0x72,0x5c,0x80,0x3e
+,0x95,0x36,0x00,0x75,0x66,0x8b,0xfa,0x33,0xdb,0x8e,0xc3,0x26,0x89,0x1d,0x26,0x88
+,0x5d,0x04,0x51,0x50,0xc4,0x1e,0x8c,0x36,0xb9,0x0f,0x00,0x33,0xc0,0xe8,0x21,0x09
+,0x58,0x59,0x0b,0xdb,0x74,0x34,0xfe,0x0e,0xe6,0x3a,0x26,0xc6,0x07,0x81,0x26,0xc6
+,0x47,0x01,0x00,0x26,0xc6,0x47,0x02,0xff,0x26,0xc7,0x47,0x04,0x00,0x00,0x26,0x89
+,0x4f,0x0a,0x86,0xf2,0x26,0x89,0x57,0x06,0x26,0x89,0x77,0x08,0x26,0xc6,0x47,0x09
+,0x00,0x26,0xc6,0x47,0x0c,0x02,0xe8,0x8c,0x09,0xc3,0xff,0x06,0xec,0x33,0x8c,0xc0
+,0x48,0x8e,0xc0,0xfa,0xe8,0x97,0x10,0xfb,0xe9,0xeb,0xff,0x8c,0xc0,0x48,0x8e,0xc0
+,0xfa,0xe8,0x8a,0x10,0xfb,0xc3,0x8c,0xc0,0x8e,0xc0,0xfa,0xe8,0x80,0x10,0xfb,0xc3
+,0x80,0x3e,0x95,0x36,0x00,0x75,0x03,0xe9,0xc2,0x00,0xbf,0x08,0x00,0x26,0xf6,0x06
+,0x10,0x00,0x80,0x75,0x05,0x03,0xfe,0xe9,0x0c,0x00,0x26,0xa0,0x16,0x00,0x24,0x1f
+,0x32,0xe4,0x03,0xf0,0x03,0xfe,0xa0,0x95,0x36,0x3c,0x00,0x75,0x03,0xe9,0x9c,0x00
+,0x3c,0x01,0x74,0x0b,0x3c,0x02,0x74,0x14,0x3c,0x03,0x74,0x1d,0xe9,0x8d,0x00,0xc6
+,0x06,0x96,0x36,0x01,0xe8,0x3c,0x01,0x72,0x27,0xe9,0x80,0x00,0xc6,0x06,0x96,0x36
+,0x02,0xe8,0x83,0x00,0x72,0x1a,0xe9,0x73,0x00,0xc6,0x06,0x96,0x36,0x01,0xe8,0x22
+,0x01,0x72,0x0d,0xc6,0x06,0x96,0x36,0x02,0xe8,0x6c,0x00,0x72,0x03,0xe9,0x5c,0x00
+,0x53,0x06,0x50,0xc4,0x1e,0x8c,0x36,0xb9,0x0b,0x00,0x33,0xc0,0xe8,0x42,0x08,0x58
+,0x26,0xc6,0x07,0x82,0x26,0xc6,0x47,0x02,0xff,0x8d,0x06,0xe0,0xfe,0x86,0xc4,0x26
+,0x89,0x47,0x06,0xa0,0x96,0x36,0x26,0x88,0x47,0x08,0xe8,0xc8,0x08,0x07,0x5b,0x83
+,0x26,0xad,0x36,0xfe,0xa1,0xad,0x36,0xe7,0x04,0xba,0x10,0x01,0xb8,0x80,0x80,0xef
+,0xed,0xba,0x10,0x01,0xb8,0x02,0x02,0xef,0xed,0x52,0xba,0xe0,0x00,0xb8,0x41,0x10
+,0xef,0x5a,0xb8,0x9c,0x03,0xcd,0x39,0xc6,0x06,0x95,0x36,0x00,0x8c,0xc0,0x48,0x8e
+,0xc0,0xfa,0xe8,0xa9,0x0f,0xfb,0xc3,0x1e,0x06,0x1f,0x06,0x33,0xc0,0x8e,0xc0,0x8b
+,0xf0,0x8d,0x3e,0x20,0xf3,0x51,0xb1,0x0a,0x26,0x83,0x7d,0x0c,0x01,0x75,0x2a,0x57
+,0x26,0x83,0x7d,0x0e,0x00,0x74,0x06,0xe8,0x2f,0x00,0xe9,0x03,0x00,0xe8,0x66,0x07
+,0x5f,0x73,0x16,0x33,0xc0,0x8e,0xd8,0x26,0x8b,0x4d,0x12,0x8d,0x75,0x20,0x8d,0x3e
+,0xe0,0xfe,0xf3,0xa4,0x59,0x07,0x1f,0xf9,0xc3,0xfe,0xc9,0x74,0x07,0x81,0xc7,0x20
+,0x01,0xe9,0xc4,0xff,0x59,0x07,0x1f,0xf8,0xc3,0x51,0x50,0x53,0x56,0x52,0x57,0x33
+,0xdb,0x26,0x8a,0x5d,0x0e,0x26,0x8b,0x4d,0x12,0x8d,0x7d,0x20,0x5a,0x87,0xd7,0x26
+,0x8a,0x45,0x14,0x87,0xd7,0x42,0x32,0xff,0x80,0xff,0x08,0x75,0x08,0xfe,0xcb,0x22
+,0xdb,0x75,0xea,0x33,0xdb,0x23,0xdb,0x74,0x06,0xfe,0xc7,0xd0,0xc8,0x73,0x0c,0x50
+,0x26,0x8a,0x05,0x38,0x04,0x58,0x74,0x03,0xe9,0x0a,0x00,0x49,0x46,0x47,0x23,0xc9
+,0x74,0x0a,0xe9,0xd3,0xff,0x5a,0x5e,0x5b,0x58,0x59,0xf8,0xc3,0x5a,0x5e,0x5b,0x58
+,0x59,0xf9,0xc3,0x1e,0x06,0x1f,0x06,0x33,0xc0,0x8e,0xc0,0x86,0xcd,0x2b,0xce,0x8b
+,0xf7,0x8b,0xc1,0x33,0xc9,0x80,0x3c,0xff,0x74,0x16,0x80,0xf9,0x06,0x73,0x09,0x32
+,0xc9,0x46,0x48,0x74,0x2e,0xe9,0xed,0xff,0x3d,0x60,0x00,0x73,0x0c,0xe9,0x23,0x00
+,0xfe,0xc1,0x46,0x48,0x74,0x1d,0xe9,0xdc,0xff,0xb8,0x10,0x00,0x8d,0x3e,0x18,0x34
+,0x32,0xed,0xb1,0x06,0xf3,0xa6,0x74,0x03,0xe9,0x08,0x00,0x48,0x23,0xc0,0x74,0x07
+,0xe9,0xe9,0xff,0x07,0x1f,0xf8,0xc3,0x8d,0x36,0x18,0x34,0x33,0xc0,0x8e,0xd8,0x8d
+,0x3e,0xe0,0xfe,0xb8,0x10,0x00,0xb9,0x06,0x00,0x56,0xf3,0xa4,0x5e,0x48,0x3d,0x00
+,0x00,0x75,0xf3,0x07,0x1f,0xf9,0xc3,0xff,0x06,0xe4,0x33,0xc6,0x06,0xeb,0x34,0x00
+,0x26,0x8b,0x45,0x06,0x86,0xe0,0xc1,0xe8,0x04,0x48,0x06,0x8e,0xc0,0xfe,0x06,0xe6
+,0x3a,0xfa,0xe8,0x69,0x0e,0xfb,0x07,0xb0,0xff,0xc3,0x00,0x00,0x00,0x00,0x00,0x00
+,0xb0,0x01,0xc3,0xb0,0x00,0xc3,0xf6,0x06,0x93,0x36,0x20,0x75,0x03,0xb0,0x04,0xc3
+,0x8b,0x0e,0x97,0x36,0x81,0xe1,0x80,0x30,0x26,0x8b,0x47,0x04,0x25,0x7f,0xcf,0x0b
+,0xc1,0xa3,0x97,0x36,0xa3,0xe6,0x34,0xb0,0x00,0xc3,0xf6,0x06,0x93,0x36,0x20,0x74
+,0x03,0xb0,0x03,0xc3,0x26,0x8b,0x47,0x08,0xa3,0x97,0x36,0xa3,0xe6,0x34,0x26,0x8a
+,0x47,0x20,0xa2,0xfd,0x34,0x3c,0x01,0x75,0x06,0xc7,0x06,0xa1,0x36,0x00,0x00,0x26
+,0x8a,0x47,0x21,0xa2,0xfe,0x34,0x26,0x8b,0x47,0x0a,0xa3,0x18,0x34,0xa3,0x58,0x34
+,0x26,0x8b,0x47,0x0c,0xa3,0x1a,0x34,0xa3,0x5a,0x34,0x26,0x8b,0x47,0x0e,0xa3,0x1c
+,0x34,0xa3,0x5c,0x34,0xc6,0x06,0x2a,0x34,0xc0,0x26,0x8b,0x47,0x14,0x25,0x7f,0xff
+,0x09,0x06,0x2c,0x34,0x26,0x8b,0x47,0x16,0x25,0xff,0xfe,0x25,0xff,0xfc,0x09,0x06
+,0x2e,0x34,0xc6,0x06,0x00,0x34,0xc0,0x26,0x8b,0x47,0x10,0xa3,0x02,0x34,0x26,0x8b
+,0x47,0x12,0xa3,0x04,0x34,0x06,0x53,0xe8,0x84,0x0a,0x5b,0x07,0x3d,0x00,0x00,0x75
+,0x07,0x80,0x0e,0x92,0x36,0x08,0xb0,0xfe,0xc3,0xb9,0x00,0x01,0xa1,0xac,0x33,0x33
+,0xd2,0xf7,0xf9,0xa3,0xae,0x33,0x91,0x49,0x33,0xd2,0xf7,0xe9,0x05,0x00,0x3b,0xa3
+,0x46,0x34,0xbf,0x00,0x3b,0x89,0x3e,0x44,0x34,0xba,0x68,0x00,0xb8,0xe0,0xe0,0xef
+,0xa1,0xae,0x33,0xe7,0x62,0xa1,0xae,0x33,0xba,0x08,0x01,0xef,0xa1,0x44,0x34,0xe7
+,0x64,0xa1,0x44,0x34,0xba,0x0a,0x01,0xef,0xb8,0x00,0x01,0x2d,0x04,0x00,0x0d,0x00
+,0x10,0xe7,0x92,0xc3,0x3d,0x00,0x00,0x74,0x0a,0x26,0x89,0x47,0x07,0xe8,0x83,0x3a
+,0xb0,0x07,0xc3,0xa1,0xae,0x33,0x26,0x89,0x47,0x2b,0xa1,0x44,0x34,0x26,0x89,0x47
+,0x2d,0xa1,0x46,0x34,0x26,0x89,0x47,0x2f,0x80,0x0e,0x93,0x36,0x20,0xa1,0x88,0x36
+,0x86,0xe0,0x26,0x89,0x47,0x08,0xa1,0x84,0x36,0x86,0xe0,0x26,0x89,0x47,0x0a,0xa1
+,0x80,0x36,0x86,0xe0,0x26,0x89,0x47,0x0c,0xb8,0x60,0xfe,0x86,0xe0,0x26,0x89,0x47
+,0x0e,0xa0,0xa1,0x36,0x26,0x88,0x47,0x10,0x8b,0x36,0x88,0x36,0x26,0xc6,0x44,0x02
+,0xff,0xe5,0x9e,0xa9,0x00,0x08,0x74,0x0c,0xba,0x84,0x00,0xed,0x0d,0x08,0x00,0xef
+,0xba,0x8e,0x00,0xef,0xe5,0x02,0x25,0xf9,0xff,0xe7,0x02,0xba,0x10,0x01,0xb8,0x02
+,0x02,0xef,0xed,0xb0,0x00,0xc3,0xf6,0x06,0x93,0x36,0x20,0x75,0x03,0xb0,0x01,0xc3
+,0x80,0x26,0x93,0x36,0x9f,0xe8,0x8d,0x0a,0x80,0x0e,0x92,0x36,0x08,0xb0,0xfe,0xc3
+,0xb0,0x00,0xc3,0xf6,0x06,0x93,0x36,0x20,0x75,0x03,0xb0,0x04,0xc3,0xc6,0x06,0x2a
+,0x34,0xc0,0x26,0x8b,0x47,0x06,0x25,0x7f,0xff,0xa3,0x2c,0x34,0x26,0x8b,0x47,0x08
+,0x25,0xff,0xfe,0x25,0xff,0xfc,0xa3,0x2e,0x34,0xcd,0x52,0xb0,0x00,0xc3,0xf6,0x06
+,0x93,0x36,0x20,0x75,0x03,0xb0,0x04,0xc3,0xc6,0x06,0x00,0x34,0xc0,0x26,0x8b,0x47
+,0x06,0xa3,0x02,0x34,0x26,0x8b,0x47,0x08,0xa3,0x04,0x34,0xcd,0x52,0xb0,0x00,0xc3
+,0xf6,0x06,0x93,0x36,0x20,0x75,0x03,0xb0,0x04,0xc3,0x57,0x8d,0x7f,0x06,0x51,0xb9
+,0x07,0x00,0x33,0xc0,0xf3,0xab,0x59,0x8d,0x7f,0x06,0xa1,0x7a,0x34,0x03,0x06,0x39
+,0x37,0x26,0x88,0x05,0xa1,0x95,0x37,0x26,0x88,0x45,0x02,0xa1,0x80,0x34,0x03,0x06
+,0x76,0x34,0x26,0x88,0x45,0x07,0xa1,0xc6,0x34,0x26,0x88,0x45,0x09,0xa1,0xd8,0x33
+,0x26,0x88,0x45,0x0a,0x33,0xc0,0xa3,0x7a,0x34,0xa3,0x39,0x37,0xa3,0x95,0x37,0xa3
+,0x80,0x34,0xa3,0x76,0x34,0xa3,0xc6,0x34,0xa3,0xd8,0x33,0x5f,0xb0,0x00,0xc3,0xf6
+,0x06,0x93,0x36,0x20,0x75,0x03,0xb0,0x04,0xc3,0x26,0x8b,0x4f,0x04,0x83,0xf9,0x06
+,0x74,0x12,0x83,0xf9,0x04,0x74,0x0d,0x83,0xf9,0x00,0x74,0x08,0x83,0xf9,0x02,0x74
+,0x03,0xb0,0x01,0xc3,0x89,0x0e,0xe8,0x3a,0x83,0x26,0xab,0x36,0xf9,0x09,0x0e,0xab
+,0x36,0xe5,0x02,0x25,0xf9,0xff,0x0b,0xc1,0xe7,0x02,0xb0,0x00,0xc3,0xf6,0x06,0x93
+,0x36,0x20,0x75,0x03,0xb0,0x04,0xc3,0x26,0x8b,0x4f,0x04,0x80,0xf9,0xff,0x74,0x08
+,0x80,0xf9,0x00,0x74,0x10,0xb0,0x01,0xc3,0x83,0x0e,0xad,0x36,0x02,0xa1,0xad,0x36
+,0xe7,0x04,0xe9,0x0a,0x00,0x83,0x26,0xad,0x36,0xfd,0xa1,0xad,0x36,0xe7,0x04,0xb0
+,0x00,0xc3,0xf6,0x06,0x93,0x36,0x20,0x75,0x03,0xb0,0x04,0xc3,0xe8,0xd5,0x04,0xb0
+,0x00,0xc3,0xf6,0x06,0x93,0x36,0x80,0x75,0x03,0xb0,0x01,0xc3,0x26,0x83,0x7f,0x06
+,0x05,0x75,0x03,0xe9,0x9d,0x00,0x26,0x8b,0x57,0x04,0x26,0x8b,0x47,0x08,0x26,0x81
+,0x7f,0x06,0x00,0x80,0x75,0x08,0xed,0x26,0x89,0x47,0x0a,0xe9,0x9d,0x00,0x26,0x83
+,0x7f,0x06,0x01,0x75,0x04,0xef,0xe9,0x92,0x00,0x26,0x81,0x7f,0x06,0x01,0x80,0x75
+,0x09,0xef,0xed,0x26,0x89,0x47,0x0a,0xe9,0x81,0x00,0x26,0x83,0x7f,0x06,0x02,0x75
+,0x07,0x26,0x21,0x47,0x04,0xe9,0x73,0x00,0x26,0x81,0x7f,0x06,0x02,0x80,0x75,0x0c
+,0x26,0x21,0x47,0x04,0xed,0x26,0x89,0x47,0x0a,0xe9,0x5f,0x00,0x26,0x83,0x7f,0x06
+,0x03,0x75,0x07,0x26,0x09,0x47,0x04,0xe9,0x51,0x00,0x26,0x81,0x7f,0x06,0x03,0x80
+,0x75,0x0c,0x26,0x09,0x47,0x04,0xed,0x26,0x89,0x47,0x0a,0xe9,0x3d,0x00,0x26,0x83
+,0x7f,0x06,0x04,0x75,0x07,0x26,0x31,0x47,0x04,0xe9,0x2f,0x00,0x26,0x81,0x7f,0x06
+,0x04,0x80,0x75,0x0c,0x26,0x31,0x47,0x04,0xed,0x26,0x89,0x47,0x0a,0xe9,0x1b,0x00
+,0xb0,0x01,0xc3,0xfa,0x53,0x26,0x8b,0x4f,0x08,0x0b,0xc9,0x74,0x0c,0x8d,0x1e,0xe0
+,0xfe,0xe8,0x52,0xff,0x83,0xc3,0x08,0xe2,0xf8,0x5b,0xfb,0xb0,0x00,0xc3,0xf6,0x06
+,0x93,0x36,0x80,0x75,0x0a,0xf6,0x06,0x93,0x36,0x20,0x75,0x03,0xb0,0x01,0xc3,0x8d
+,0x3e,0xe0,0xfe,0xe5,0x00,0x26,0x89,0x05,0xe5,0x02,0x26,0x89,0x45,0x02,0xa1,0xad
+,0x36,0x26,0x89,0x45,0x04,0xe5,0x06,0x26,0x89,0x45,0x06,0xe5,0x08,0x26,0x89,0x45
+,0x08,0xe5,0x0a,0x26,0x89,0x45,0x0a,0xe5,0x0e,0x26,0x89,0x45,0x0c,0xe5,0x48,0x26
+,0x89,0x45,0x0e,0xe5,0x4a,0x26,0x89,0x45,0x10,0xe5,0x4c,0x26,0x89,0x45,0x12,0xa1
+,0xb7,0x36,0x26,0x89,0x45,0x14,0xe5,0x50,0x26,0x89,0x45,0x16,0xe5,0x52,0x26,0x89
+,0x45,0x18,0xe5,0x54,0x26,0x89,0x45,0x1a,0xe5,0x56,0x26,0x89,0x45,0x1c,0xe5,0x58
+,0x26,0x89,0x45,0x1e,0xe5,0x62,0x26,0x89,0x45,0x20,0xe5,0x64,0x26,0x89,0x45,0x22
+,0xe5,0x66,0x26,0x89,0x45,0x24,0xe5,0x68,0x26,0x89,0x45,0x26,0xe5,0x6a,0x26,0x89
+,0x45,0x28,0xe5,0x6c,0x26,0x89,0x45,0x2a,0xe5,0x70,0x26,0x89,0x45,0x2c,0xe5,0x72
+,0x26,0x89,0x45,0x2e,0xe5,0x74,0x26,0x89,0x45,0x30,0xe5,0x76,0x26,0x89,0x45,0x32
+,0xe5,0x7c,0x26,0x89,0x45,0x34,0xe5,0x7e,0x26,0x89,0x45,0x36,0xe5,0x80,0x26,0x89
+,0x45,0x38,0xe5,0x82,0x26,0x89,0x45,0x3a,0xe5,0x86,0x26,0x89,0x45,0x3c,0xe5,0x88
+,0x26,0x89,0x45,0x3e,0xe5,0x9a,0x26,0x89,0x45,0x40,0xe5,0x9e,0x26,0x89,0x45,0x42
+,0xe5,0xcc,0x26,0x89,0x45,0x44,0xe5,0xce,0x26,0x89,0x45,0x46,0xe5,0xd0,0x26,0x89
+,0x45,0x48,0xe5,0xd2,0x26,0x89,0x45,0x4a,0xba,0x00,0x01,0xed,0x11,0x06,0x66,0x34
+,0x73,0x04,0xff,0x06,0x68,0x34,0x26,0x89,0x45,0x4c,0xba,0x02,0x01,0xed,0xc1,0xe0
+,0x02,0x11,0x06,0x6e,0x34,0x73,0x04,0xff,0x06,0x70,0x34,0x26,0x89,0x45,0x4e,0xba
+,0x04,0x01,0xed,0x11,0x06,0x6a,0x34,0x73,0x04,0xff,0x06,0x6c,0x34,0x26,0x89,0x45
+,0x50,0xba,0x06,0x01,0xed,0xc1,0xe0,0x02,0x11,0x06,0x72,0x34,0x73,0x04,0xff,0x06
+,0x74,0x34,0x26,0x89,0x45,0x52,0xba,0x08,0x01,0xed,0x26,0x89,0x45,0x54,0xba,0x0a
+,0x01,0xed,0x26,0x89,0x45,0x56,0xba,0x0c,0x01,0xed,0x26,0x89,0x45,0x58,0xba,0x0e
+,0x01,0xed,0x01,0x06,0x7a,0x34,0x26,0x89,0x45,0x5e,0xba,0x10,0x01,0xed,0x26,0x89
+,0x45,0x5c,0xb0,0x00,0xc3,0xf6,0x06,0x93,0x36,0x80,0x74,0x07,0xf6,0x06,0x93,0x36
+,0x20,0x75,0x03,0xb0,0x01,0xc3,0x26,0x80,0x7f,0x06,0x00,0x75,0x30,0x80,0x3e,0x95
+,0x36,0x00,0x74,0x52,0xc6,0x06,0x95,0x36,0x00,0x83,0x26,0xad,0x36,0xfe,0xa1,0xad
+,0x36,0xe7,0x04,0xba,0x10,0x01,0xb8,0x80,0x80,0xef,0xed,0xba,0x10,0x01,0xb8,0x02
+,0x02,0xef,0xed,0xba,0xe0,0x00,0xb8,0x00,0x10,0xef,0xb0,0x00,0xc3,0x26,0x8b,0x47
+,0x04,0x3d,0x00,0x00,0x74,0x20,0x3d,0x03,0x00,0x77,0x1b,0xba,0x10,0x01,0xb8,0x02
+,0x00,0xef,0xba,0xe0,0x00,0xb8,0x01,0x10,0xef,0x83,0x0e,0xad,0x36,0x01,0xa1,0xad
+,0x36,0xe7,0x04,0xb0,0x00,0xc3,0xb0,0x06,0xc3,0xf6,0x06,0x93,0x36,0x80,0x75,0x03
+,0xb0,0x01,0xc3,0x26,0x83,0x7f,0x04,0x01,0x74,0x0a,0x26,0x83,0x7f,0x04,0x02,0x74
+,0x19,0xb0,0x06,0xc3,0x26,0x83,0x7f,0x06,0x0c,0x77,0xf6,0x26,0x83,0x7f,0x0a,0x60
+,0x77,0xef,0xe8,0x10,0x00,0x72,0x0b,0xb0,0x46,0xc3,0xe8,0x4e,0x00,0x72,0x03,0xb0
+,0x46,0xc3,0xb0,0x00,0xc3,0x51,0xb1,0x0a,0x8b,0x3e,0x20,0xf3,0x26,0x83,0x7d,0x0c
+,0x02,0x75,0x03,0xe9,0x0e,0x00,0xfe,0xc9,0x74,0x07,0x81,0xc7,0x20,0x01,0xe9,0xeb
+,0xff,0x59,0xf8,0xc3,0x57,0x8d,0x7d,0x0e,0x8d,0x77,0x06,0xb9,0x12,0x00,0xf3,0xa4
+,0x8d,0x7d,0x20,0x8d,0x36,0xe0,0xfe,0x26,0x8b,0x4d,0x12,0xf3,0xa4,0xff,0x06,0x01
+,0x35,0x5f,0x26,0xc7,0x45,0x0c,0x01,0x00,0x59,0xf9,0xc3,0x51,0xb1,0x0a,0x8d,0x3e
+,0x20,0xf3,0x8d,0x36,0xe0,0xfe,0x26,0x83,0x7d,0x0c,0x01,0x75,0x1b,0x57,0xe8,0x25
+,0x00,0x5f,0x73,0x14,0x33,0xc0,0xb9,0x20,0x01,0xf3,0xaa,0x26,0xc7,0x45,0x0c,0x02
+,0x00,0xff,0x0e,0x01,0x35,0x59,0xf9,0xc3,0xfe,0xc9,0x74,0x07,0x81,0xc7,0x20,0x01
+,0xe9,0xd3,0xff,0x59,0xf8,0xc3,0x51,0x26,0x8b,0x4d,0x12,0x8d,0x7d,0x20,0xf3,0xa6
+,0x74,0x03,0x59,0xf8,0xc3,0x59,0xf9,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x80,0x3e,0xec,0x34,0x06,0x72,0x33,0xff,0x06,0xf0,0x33,0x50,0xc4,0x1e,0x8c,0x36
+,0xb9,0x0f,0x00,0x33,0xc0,0xe8,0x29,0x00,0x58,0x81,0x26,0xc2,0x34,0xdf,0x7f,0x81
+,0x26,0xe9,0x34,0xdf,0x7f,0x0b,0xdb,0x74,0x11,0x26,0xc6,0x07,0x84,0x26,0xc6,0x47
+,0x02,0xff,0x26,0x89,0x47,0x06,0xe8,0xac,0x00,0xc3,0xff,0x06,0xea,0x33,0xe9,0xf5
+,0xff,0x57,0x26,0x8b,0x3f,0x03,0xf9,0x26,0x3b,0x7f,0x02,0x74,0x16,0x26,0x3b,0x7f
+,0x04,0x7c,0x2a,0x3d,0x00,0x00,0x75,0x13,0x8d,0x7f,0x08,0x03,0xf9,0x26,0x3b,0x7f
+,0x02,0x7c,0x14,0xff,0x06,0xde,0x33,0x33,0xdb,0x5f,0xc3,0x26,0x8b,0x7f,0x02,0x26
+,0x89,0x3f,0x03,0xf9,0xe9,0x06,0x00,0x26,0x89,0x3f,0x26,0x29,0x0f,0x26,0xc7,0x05
+,0xff,0xff,0x26,0x87,0x3f,0x26,0x89,0x0d,0x8d,0x5d,0x02,0x50,0x8b,0xfb,0x83,0xe9
+,0x02,0x33,0xc0,0xf3,0xaa,0x58,0xfe,0x0e,0xec,0x34,0x5f,0xc3,0x8b,0x7c,0x02,0x3b
+,0x3c,0x74,0x2f,0x83,0x3d,0xff,0x75,0x0b,0x8d,0x7c,0x08,0x89,0x7c,0x02,0x83,0x3d
+,0xff,0x74,0x1e,0x8a,0x45,0x02,0x3c,0x81,0x75,0x0c,0x80,0x3e,0xeb,0x34,0x00,0x74
+,0x05,0x33,0xc0,0xe9,0x0b,0x00,0x8b,0x0d,0x01,0x4c,0x02,0x8d,0x75,0x02,0x83,0xe9
+,0x02,0xc3,0x80,0x3e,0xec,0x34,0x06,0x72,0x05,0x33,0xc0,0xe9,0xf3,0xff,0xff,0x06
+,0xee,0x33,0xe9,0xbe,0xff,0xf6,0x06,0x92,0x36,0x40,0x74,0x01,0xc3,0x57,0x56,0x51
+,0x52,0x8b,0x36,0x8c,0x36,0xe8,0xa4,0xff,0x75,0x03,0xe9,0x1a,0x00,0xe9,0x1c,0x00
+,0xfe,0x06,0xec,0x34,0xc4,0x3e,0x80,0x36,0xf3,0xa4,0x80,0x0e,0x92,0x36,0x40,0xba
+,0x0c,0x01,0xb8,0x80,0x80,0xef,0xed,0x5a,0x59,0x5e,0x5f,0xc3,0xff,0x06,0xe0,0x33
+,0x80,0x3c,0x81,0x75,0x0c,0xff,0x06,0xe2,0x33,0xc6,0x06,0xeb,0x34,0x01,0xe9,0xcf
+,0xff,0x80,0x3c,0x84,0x75,0x07,0xff,0x06,0xe6,0x33,0xe9,0xc3,0xff,0xff,0x06,0xe8
+,0x33,0xe9,0xbc,0xff,0x8d,0x3e,0xe0,0xfe,0xa1,0x72,0x34,0xc7,0x06,0x72,0x34,0x00
+,0x00,0x89,0x05,0xa1,0x74,0x34,0xc7,0x06,0x74,0x34,0x00,0x00,0x89,0x45,0x02,0xba
+,0x04,0x01,0xed,0x89,0x45,0x04,0xc7,0x45,0x06,0x00,0x00,0xa1,0x6e,0x34,0xc7,0x06
+,0x6e,0x34,0x00,0x00,0x89,0x45,0x08,0xa1,0x70,0x34,0xc7,0x06,0x70,0x34,0x00,0x00
+,0x89,0x45,0x0a,0xba,0x00,0x01,0xed,0x89,0x45,0x0c,0xc7,0x45,0x0e,0x00,0x00,0x32
+,0xe4,0xba,0x0e,0x01,0xec,0x89,0x45,0x10,0xa1,0x7e,0x34,0xc7,0x06,0x7e,0x34,0x00
+,0x00,0x89,0x45,0x12,0xa1,0x8c,0x34,0xc7,0x06,0x8c,0x34,0x00,0x00,0x89,0x45,0x14
+,0xa1,0x8a,0x34,0xc7,0x06,0x8a,0x34,0x00,0x00,0x89,0x45,0x16,0xa1,0x7c,0x34,0xc7
+,0x06,0x7c,0x34,0x00,0x00,0x89,0x45,0x18,0xa1,0x88,0x34,0xc7,0x06,0x88,0x34,0x00
+,0x00,0x89,0x45,0x1a,0xa1,0xca,0x33,0xc7,0x06,0xca,0x33,0x00,0x00,0x89,0x45,0x1c
+,0xa1,0x78,0x34,0xc7,0x06,0x78,0x34,0x00,0x00,0x89,0x45,0x1e,0xa1,0xc6,0x34,0xc7
+,0x06,0xc6,0x34,0x00,0x00,0x89,0x45,0x20,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0xfa,0x33,0xc0,0x8e,0xd8,0x8e,0xc0,0xb8,0xa0,0x01,0xc1,0xe8,0x04,0x8e,0xd0,0x8d
+,0x26,0x80,0x00,0xe8,0x00,0x01,0xe8,0x10,0xeb,0x8b,0x1e,0xf7,0x34,0x8b,0x16,0xf9
+,0x34,0x8b,0x36,0xff,0x34,0x33,0xc0,0xb9,0xef,0xff,0x8d,0x3e,0x14,0x00,0x2b,0xcf
+,0x2b,0xce,0xd1,0xe9,0xf3,0xab,0x89,0x1e,0xf7,0x34,0x89,0x16,0xf9,0x34,0x83,0xfe
+,0x00,0x74,0x0c,0xb9,0xef,0xff,0xbf,0x80,0xfe,0x2b,0xcf,0xd1,0xe9,0xf3,0xab,0xb9
+,0xff,0xff,0x81,0xe9,0x00,0x3b,0x83,0xfe,0x00,0x74,0x03,0xe9,0x1b,0x00,0x51,0x1e
+,0xb8,0x00,0xe0,0x8e,0xd8,0x33,0xf6,0x8d,0x3e,0x00,0xd8,0xb9,0x00,0x0c,0xf3,0xa5
+,0x1f,0x59,0xbe,0xff,0xff,0x81,0xee,0x00,0xd8,0x2b,0xce,0x81,0xe1,0x00,0xff,0x89
+,0x0e,0xac,0x33,0x8d,0x06,0x20,0x02,0xc1,0xe8,0x04,0xa3,0x32,0x34,0x8e,0xd0,0x36
+,0xc7,0x06,0x1e,0x00,0x80,0x18,0x36,0xc7,0x06,0x22,0x00,0xff,0x7f,0x36,0xc7,0x06
+,0x0a,0x00,0xff,0xff,0x36,0xc7,0x06,0x1c,0x00,0x80,0x00,0x8d,0x06,0xa0,0x02,0xc1
+,0xe8,0x04,0xa3,0x30,0x34,0x8e,0xd0,0x36,0xc7,0x06,0x1e,0x00,0x50,0x28,0x36,0xc7
+,0x06,0x0a,0x00,0xff,0xff,0x36,0xc7,0x06,0x1c,0x00,0x80,0x00,0xb8,0xa0,0x01,0xc1
+,0xe8,0x04,0xa3,0x34,0x34,0xa3,0xf2,0x33,0x8e,0xd0,0x8d,0x26,0x80,0x00,0xb8,0x00
+,0x90,0xe7,0x02,0x8d,0x3e,0x70,0x01,0x8b,0xc7,0xc1,0xe8,0x04,0xb9,0x03,0x00,0x89
+,0x45,0x0e,0x89,0x45,0x02,0xc7,0x05,0xff,0xff,0x83,0xc7,0x10,0x05,0x01,0x00,0xe2
+,0xee,0xe8,0x5b,0x01,0xe5,0xce,0xa3,0xb5,0x36,0xe8,0x21,0x00,0xe8,0x45,0x01,0xa1
+,0x32,0x34,0x8c,0xcb,0xcd,0x37,0x0e,0x58,0xa9,0x00,0xf0,0x74,0x07,0x33,0xf6,0x89
+,0x36,0xff,0x34,0xc3,0x8d,0x36,0x30,0x61,0x89,0x36,0xff,0x34,0xc3,0x33,0xc0,0x8b
+,0xd0,0x8b,0xf2,0xb9,0x68,0x00,0x2e,0x80,0xbc,0xac,0x17,0x80,0x75,0x01,0xef,0x83
+,0xc2,0x02,0x46,0xe2,0xf1,0xb8,0x02,0x00,0xe7,0x50,0xb9,0x5a,0x00,0x33,0xff,0xc7
+,0x05,0x65,0x18,0x8c,0x4d,0x02,0x83,0xc7,0x04,0xe2,0xf4,0x33,0xc0,0x8e,0xc0,0x8c
+,0xc8,0x8e,0xd8,0x8d,0x3e,0x80,0x00,0x8d,0x36,0x9c,0x17,0xb9,0x08,0x00,0xe8,0x37
+,0x00,0x8d,0x36,0x20,0x21,0x8d,0x3e,0xc0,0x00,0xb9,0x0d,0x00,0xe8,0x29,0x00,0x8d
+,0x3e,0x40,0x01,0xb9,0x0a,0x00,0xe8,0x1f,0x00,0xe8,0x4b,0x0e,0x33,0xc0,0x8e,0xd8
+,0xc7,0x06,0x4e,0x37,0x6f,0x17,0xe7,0x48,0xe7,0x4c,0xb8,0x40,0x9c,0xe7,0x4a,0xe5
+,0x48,0x90,0xb8,0x00,0x70,0xe7,0x48,0xc3,0xa5,0x83,0xc7,0x02,0xe2,0xfa,0xc3,0xe5
+,0x4c,0xc3,0x50,0x51,0x56,0x57,0x52,0x06,0x1e,0x33,0xc0,0x8e,0xd8,0xe5,0x58,0xd1
+,0xe0,0x73,0x11,0x8b,0xf0,0xd1,0xe6,0x33,0xc0,0x8e,0xd8,0x8b,0xb4,0x80,0x00,0x83
+,0xc6,0x0b,0xff,0xe6,0x1f,0x07,0x5a,0x5f,0x5e,0x59,0x58,0xcf,0x58,0x1c,0xe4,0x1c
+,0x6c,0x1c,0x8e,0x1a,0xc0,0x1f,0x40,0x1a,0x44,0x1c,0x65,0x18,0x80,0x80,0x80,0xff
+,0x80,0x03,0x02,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
+,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
+,0x80,0x03,0x03,0x43,0x80,0x80,0x02,0x80,0x42,0x03,0x02,0xff,0x03,0x01,0x03,0x01
+,0x01,0x03,0x02,0x03,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x02,0x03,0x01,0x03
+,0x03,0xff,0x01,0x01,0xff,0x01,0xff,0x01,0x01,0x03,0x03,0x03,0xff,0xff,0xff,0xff
+,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
+,0xff,0xff,0xff,0x02,0xb8,0x0f,0x00,0xe7,0x84,0xb8,0x0f,0xf8,0xe7,0x82,0xc3,0xb9
+,0x08,0x00,0x89,0x0e,0xe6,0x3a,0x8d,0x06,0x20,0x03,0x8b,0xd0,0xc1,0xe8,0x04,0xa3
+,0x90,0x01,0x8b,0xc2,0x8b,0xd8,0xc1,0xe8,0x04,0x8e,0xc0,0x05,0x61,0x00,0x26,0xa3
+,0x00,0x00,0xa1,0x30,0x34,0x26,0xa3,0x02,0x00,0x83,0xc3,0x14,0xd1,0xeb,0x26,0x89
+,0x1e,0x08,0x00,0x81,0xc2,0x10,0x06,0xe2,0xd9,0x26,0xc7,0x06,0x00,0x00,0xff,0xff
+,0x8c,0x06,0x92,0x01,0xc3,0x50,0x51,0x56,0x57,0x52,0x06,0x1e,0x33,0xc0,0x8e,0xd8
+,0xe7,0x5a,0xff,0x06,0xbe,0x33,0xba,0xd2,0x00,0xed,0xcf,0x00,0x00,0x00,0x00,0x00
+,0x8c,0xcb,0xa1,0x30,0x34,0xcd,0x37,0xe9,0x06,0xed,0xb8,0x32,0x00,0xc3,0xe8,0x8c
+,0x01,0xfe,0x06,0xe2,0x34,0xe8,0x21,0x01,0x75,0xf0,0xe8,0x53,0x0e,0x81,0x0e,0xaf
+,0x36,0x00,0xc0,0xc7,0x06,0xad,0x36,0x60,0x00,0xf7,0x06,0xe6,0x34,0x80,0x00,0x75
+,0x1a,0xf7,0x06,0xe6,0x34,0x00,0x08,0x74,0x09,0xc7,0x06,0xab,0x36,0x0b,0x00,0xe9
+,0x0f,0x00,0xc7,0x06,0xab,0x36,0x03,0x00,0xe9,0x06,0x00,0xc7,0x06,0xab,0x36,0x11
+,0x9c,0xc7,0x06,0xa9,0x36,0x18,0x00,0xf7,0x06,0xe6,0x34,0x80,0x00,0x75,0x0d,0xf7
+,0x06,0xb5,0x36,0x02,0x00,0x74,0x05,0x83,0x0e,0xa9,0x36,0x20,0xa1,0xa9,0x36,0xe7
+,0x00,0xa1,0xab,0x36,0xe7,0x02,0xf7,0x06,0xe6,0x34,0x80,0x00,0x74,0x2e,0xe8,0xf2
+,0x2f,0x33,0xc0,0x0d,0x41,0x00,0xe7,0x56,0xa1,0xb1,0x36,0x0d,0x00,0x10,0xe7,0x08
+,0xa1,0xb3,0x36,0xe7,0x0a,0xa1,0xaf,0x36,0xe7,0x06,0xb8,0x40,0x00,0xe7,0x4e,0x33
+,0xc0,0xe7,0x0e,0xc7,0x06,0x26,0x02,0x00,0x00,0xe9,0x23,0x00,0xc7,0x06,0x4e,0x37
+,0x3f,0x20,0x8e,0x06,0x30,0x34,0x26,0xf7,0x06,0x0a,0x00,0x00,0x80,0x74,0x07,0x26
+,0x81,0x0e,0x08,0x00,0x00,0x80,0xc6,0x06,0xe0,0x34,0x01,0xb8,0x00,0x00,0xc3,0xfe
+,0x06,0xe1,0x34,0xc6,0x06,0xe0,0x34,0x00,0xa1,0x26,0x02,0x0b,0xc0,0x74,0x01,0xc3
+,0xe8,0x04,0x00,0xb8,0x00,0x00,0xc3,0xa1,0xa9,0x36,0xe7,0x00,0x8b,0x1e,0xab,0x36
+,0x83,0xe3,0x06,0xe5,0x02,0x25,0xf9,0xff,0x0b,0xc3,0x0d,0x10,0x00,0xe7,0x02,0xa1
+,0xad,0x36,0xe7,0x04,0xc3,0xb8,0x0a,0x00,0xe7,0x84,0xfe,0x06,0xe5,0x34,0xc6,0x06
+,0xe3,0x34,0x01,0x8e,0x06,0x30,0x34,0x26,0xf7,0x06,0x0a,0x00,0x00,0x40,0x74,0x07
+,0x26,0x81,0x0e,0x08,0x00,0x00,0x40,0xc3,0xc7,0x06,0x4e,0x37,0x6f,0x17,0xfe,0x06
+,0xe4,0x34,0xc6,0x06,0xe3,0x34,0x00,0xc3,0xc3,0xf6,0x06,0x18,0x34,0x80,0x75,0x0d
+,0xa1,0x18,0x34,0x0b,0x06,0x1a,0x34,0x0b,0x06,0x1c,0x34,0x75,0x01,0xc3,0xa1,0x2e
+,0x34,0x25,0xff,0xfe,0x8b,0x16,0xe7,0x36,0x81,0xe2,0x00,0x01,0x0b,0xc2,0xa3,0x2e
+,0x34,0x8d,0x16,0x10,0x00,0xbf,0x00,0x00,0xb9,0x08,0x00,0x8b,0x85,0x00,0x34,0xef
+,0x83,0xc2,0x10,0x8b,0x85,0x02,0x34,0xef,0x83,0xc2,0x10,0x8b,0x85,0x04,0x34,0xef
+,0x83,0xc2,0xe2,0x83,0xc7,0x06,0x49,0x75,0xe2,0xb8,0x00,0x00,0x8e,0xc0,0xbe,0x00
+,0x34,0xbf,0xb9,0x36,0xb9,0x18,0x00,0xf3,0xa5,0xb8,0x00,0x00,0xc3,0x33,0xc0,0x8e
+,0xc0,0x8d,0x3e,0xb0,0x33,0xb9,0x08,0x00,0xf3,0xab,0x8d,0x3e,0x3e,0x34,0xb9,0x03
+,0x00,0xf3,0xab,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x50,0x51,0x56,0x57,0x52,0x06,0x1e,0x33,0xc0,0x8e,0xd8,0xe7,0x5a,0xff,0x06,0xba
+,0x33,0xe5,0x56,0x0d,0x20,0x00,0xe7,0x56,0xba,0x7a,0x00,0xed,0x08,0x26,0x94,0x36
+,0x33,0xc0,0xb1,0x08,0x32,0xed,0x06,0x8e,0xc0,0x8d,0x3e,0xe0,0xff,0xf3,0xaa,0x8e
+,0x06,0x32,0x34,0x26,0x81,0x0e,0x08,0x00,0x00,0x02,0x07,0xe5,0x56,0x25,0xdf,0xff
+,0xe7,0x56,0xe9,0xf8,0xfc,0x00,0xbd,0x1b,0x10,0x1b,0xd9,0x1a,0xf3,0x1a,0x50,0x51
+,0x56,0x57,0x52,0x06,0x1e,0x33,0xc0,0x8e,0xd8,0xe7,0x5a,0xff,0x06,0xb6,0x33,0x53
+,0x06,0x51,0xe5,0x80,0xa3,0xb4,0x33,0x8b,0xd8,0x8b,0xc8,0x25,0x10,0x00,0xa3,0xed
+,0x34,0x0b,0xc0,0x74,0x14,0xff,0x06,0x80,0x34,0x80,0x3e,0xfe,0x34,0x00,0x74,0x03
+,0xe9,0x06,0x00,0xb8,0x80,0x00,0xe8,0x9d,0x04,0x83,0xe3,0x03,0xd1,0xe3,0x2e,0xff
+,0x97,0x86,0x1a,0x59,0x07,0x5b,0xe9,0xa4,0xfc,0xba,0x20,0x00,0x8e,0x06,0x3c,0x34
+,0x83,0x3e,0x3c,0x34,0x00,0x75,0x03,0xe9,0xf0,0x00,0xc7,0x06,0x3c,0x34,0x00,0x00
+,0xe9,0x2a,0x00,0xba,0x10,0x00,0x8e,0x06,0x3a,0x34,0x83,0x3e,0x3a,0x34,0x00,0x75
+,0x03,0xe9,0xd5,0xff,0xc7,0x06,0x3a,0x34,0x00,0x00,0xe8,0x10,0x00,0xe9,0xc9,0xff
+,0xba,0x10,0x00,0x8e,0x06,0x3a,0x34,0xc7,0x06,0x3a,0x34,0x00,0x00,0x26,0xa1,0x14
+,0x00,0x26,0xa3,0x0c,0x00,0x26,0xa1,0x16,0x00,0x26,0xa3,0x0e,0x00,0x26,0xc6,0x06
+,0x0a,0x00,0x00,0xc1,0xea,0x02,0x23,0xd1,0x74,0x1c,0xba,0x20,0x00,0x26,0xc7,0x06
+,0x0e,0x00,0xea,0x05,0x26,0x0b,0x16,0x0c,0x00,0x26,0x89,0x16,0x0c,0x00,0xff,0x06
+,0x86,0x34,0xff,0x06,0xdc,0x33,0x26,0xa1,0x0c,0x00,0xa9,0x00,0x37,0x74,0x16,0x26
+,0xc6,0x06,0x0a,0x00,0x02,0xa9,0x00,0x30,0x74,0x04,0xff,0x06,0x7a,0x34,0xff,0x06
+,0xda,0x33,0xe9,0x49,0x00,0xc0,0xec,0x07,0x83,0x16,0x8a,0x34,0x00,0x24,0x07,0x3c
+,0x07,0x75,0x04,0xff,0x06,0x8c,0x34,0xff,0x06,0x7e,0x34,0xa1,0x30,0x34,0x8c,0xc3
+,0x8e,0xc0,0x8e,0xdb,0x26,0x83,0x0e,0x08,0x00,0x40,0x8c,0xd8,0x26,0x87,0x06,0x16
+,0x00,0x26,0x83,0x3e,0x14,0x00,0xff,0x74,0x0a,0x8e,0xc0,0x26,0x8c,0x1e,0x00,0x00
+,0xe9,0x05,0x00,0x26,0x8c,0x1e,0x14,0x00,0x33,0xc0,0x8e,0xd8,0xc3,0xc3,0x8c,0xc0
+,0x87,0x06,0x92,0x01,0x3d,0xff,0xff,0x74,0x0d,0x8e,0xd8,0x8c,0x06,0x00,0x00,0x33
+,0xc0,0x8e,0xd8,0xe9,0x04,0x00,0x8c,0x06,0x90,0x01,0xe8,0x01,0x00,0xc3,0x06,0x83
+,0x3e,0x90,0x01,0xff,0x74,0x29,0x83,0x3e,0x3a,0x34,0x00,0x75,0x11,0xba,0x86,0x00
+,0xe8,0x1e,0x00,0x8c,0x06,0x3a,0x34,0x83,0x3e,0x90,0x01,0xff,0x74,0x11,0x83,0x3e
+,0x3c,0x34,0x00,0x75,0x0a,0xba,0x88,0x00,0xe8,0x06,0x00,0x8c,0x06,0x3c,0x34,0x07
+,0xc3,0xa1,0x90,0x01,0x8e,0xc0,0x26,0xa1,0x08,0x00,0xef,0x26,0xa1,0x00,0x00,0x26
+,0xc7,0x06,0x00,0x00,0xff,0xff,0xa3,0x90,0x01,0x3d,0xff,0xff,0x75,0x03,0xa3,0x92
+,0x01,0x83,0x3e,0xed,0x34,0x00,0x74,0x0b,0xb8,0x10,0x00,0xe7,0x84,0xc7,0x06,0xed
+,0x34,0x00,0x00,0xc3,0x50,0x51,0x56,0x57,0x52,0x06,0x1e,0x33,0xc0,0x8e,0xd8,0xe7
+,0x5a,0xff,0x06,0xbc,0x33,0xe9,0x25,0xfb,0x50,0x51,0x56,0x57,0x52,0x06,0x1e,0x33
+,0xc0,0x8e,0xd8,0xe7,0x5a,0xff,0x06,0xb0,0x33,0xe9,0x11,0xfb,0x50,0x51,0x56,0x57
+,0x52,0x06,0x1e,0x33,0xc0,0x8e,0xd8,0xe7,0x5a,0xff,0x06,0xb4,0x33,0x06,0xff,0x06
+,0x76,0x34,0x80,0x3e,0xfe,0x34,0x00,0x74,0x04,0x07,0xe9,0xf0,0xfa,0xb8,0x80,0x00
+,0xe8,0xd3,0x02,0x07,0xe9,0xe6,0xfa,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0xc6,0x1d,0x08,0x1d,0x91,0x1e,0x5d,0x1e,0x73,0x1e,0x89,0x1e,0x91,0x1e,0xa8,0x1d
+,0x91,0x1e,0x91,0x1e,0xaf,0x1e,0xaf,0x1e,0x15,0x1d,0x15,0x1d,0x91,0x1e,0x99,0x1f
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00
+,0x00,0x01,0x00,0x10,0x00,0x01,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00
+,0x07,0xe9,0x99,0xfa,0x50,0x51,0x56,0x57,0x52,0x06,0x1e,0x33,0xc0,0x8e,0xd8,0xe7
+,0x5a,0xff,0x06,0xb2,0x33,0x06,0x68,0xf6,0x1c,0xe5,0x06,0xa3,0xb2,0x33,0x8b,0xf0
+,0x83,0xe6,0x1e,0x2e,0xff,0xa4,0xa0,0x1c,0xe5,0x0c,0xa9,0x80,0x00,0x74,0x06,0xe8
+,0xa4,0x01,0xe5,0x06,0xc3,0x53,0xe5,0x0c,0x8b,0xd8,0xa9,0x01,0x00,0x74,0x14,0x83
+,0x3e,0xe0,0x3a,0x00,0x74,0x0d,0x8e,0x06,0x38,0x34,0xe8,0xbf,0x06,0xc7,0x06,0xe0
+,0x3a,0x00,0x00,0xe5,0x00,0x0d,0x18,0x00,0xe7,0x00,0xe5,0x02,0x0d,0x11,0x00,0xe7
+,0x02,0x8b,0xc3,0x5b,0xa9,0x01,0x00,0x74,0x01,0xc3,0x8b,0xd0,0xb8,0x00,0x08,0xe7
+,0x84,0x8b,0xc2,0x8e,0x06,0x38,0x34,0x26,0xa3,0x0c,0x00,0x8b,0xd0,0xc1,0xe0,0x03
+,0x83,0x16,0x88,0x34,0x00,0xff,0x06,0x7c,0x34,0x26,0x83,0x3e,0x06,0x00,0x0a,0x75
+,0x21,0x8b,0xc2,0x25,0x40,0x18,0x3d,0x40,0x00,0x74,0x0c,0x3d,0x00,0x10,0x75,0x12
+,0x26,0xfe,0x0e,0x0a,0x00,0x74,0x0b,0xf7,0x06,0xef,0x34,0x20,0x00,0x75,0x03,0xe9
+,0x5a,0x06,0x8c,0xc0,0x26,0x8e,0x06,0x02,0x00,0x26,0x83,0x0e,0x08,0x00,0x20,0x26
+,0xa3,0x12,0x00,0x26,0xa3,0x10,0x00,0xc3,0xff,0x06,0xc4,0x33,0xe5,0x0c,0xa9,0x01
+,0x00,0x75,0x01,0xc3,0xa9,0xf0,0x07,0x74,0x01,0xc3,0xff,0x06,0xd4,0x33,0xe5,0x00
+,0x0d,0x18,0x00,0xe7,0x00,0xc3,0xff,0x06,0xca,0x33,0x80,0x3e,0xa0,0x36,0x08,0x75
+,0x14,0x8e,0x06,0x30,0x34,0x26,0xf7,0x06,0x0a,0x00,0x00,0x08,0x74,0x07,0x26,0x81
+,0x0e,0x08,0x00,0x00,0x08,0xe5,0x82,0x25,0xfd,0xff,0xe7,0x82,0xe5,0x0c,0x50,0xe5
+,0x80,0x25,0x00,0x07,0xa3,0xe4,0x3a,0xe5,0x8c,0x25,0x00,0x80,0xa3,0xe2,0x3a,0x58
+,0xa9,0x02,0x00,0x75,0x25,0x83,0x3e,0xe2,0x3a,0x00,0x75,0x1e,0x83,0x3e,0xe4,0x3a
+,0x00,0x75,0x17,0xe5,0x08,0x0d,0x00,0x04,0x25,0xff,0x04,0xe7,0x08,0xe8,0x6a,0x01
+,0xe5,0x82,0x0d,0x02,0x00,0xe7,0x82,0xe9,0x21,0x00,0xe8,0x1a,0x06,0x80,0x3e,0xe8
+,0xff,0x00,0x74,0x0a,0x80,0x3e,0xe8,0xff,0x04,0x74,0x03,0xe9,0x0d,0x00,0xc6,0x06
+,0xe8,0xff,0x01,0xba,0x0c,0x01,0xb8,0x08,0x08,0xef,0xed,0x80,0x3e,0x9f,0x36,0x06
+,0x75,0x05,0x83,0x0e,0x99,0x36,0x40,0xb8,0x00,0x01,0xe9,0x09,0x01,0xff,0x06,0xcc
+,0x33,0x81,0x26,0xaf,0x36,0xff,0xf7,0xa1,0xaf,0x36,0xe7,0x06,0xff,0x06,0xc6,0x34
+,0xe9,0x1e,0x00,0xff,0x06,0xce,0x33,0xff,0x06,0x95,0x37,0x81,0x26,0xaf,0x36,0xff
+,0xef,0xa1,0xaf,0x36,0xe7,0x06,0xe9,0x08,0x00,0xff,0x06,0xd0,0x33,0xff,0x06,0x7a
+,0x34,0xff,0x06,0xd2,0x33,0xd1,0xe6,0x8e,0x06,0x30,0x34,0x2e,0x8b,0x84,0xc0,0x1c
+,0x26,0x09,0x06,0x08,0x00,0x2e,0x8b,0x84,0xc2,0x1c,0x09,0x06,0x66,0x37,0xc3,0xe5
+,0x0c,0xa9,0x80,0x00,0x74,0x56,0x50,0xe8,0xf0,0x00,0x58,0xa9,0x00,0x01,0x75,0x07
+,0xff,0x06,0xc6,0x33,0xe9,0x08,0x00,0xff,0x06,0x78,0x34,0xff,0x06,0xc8,0x33,0xe5
+,0x82,0x25,0xfd,0xff,0xe7,0x82,0xe8,0x6e,0x05,0xba,0x10,0x01,0xed,0x80,0x3e,0xe8
+,0xff,0x00,0x74,0x0a,0x80,0x3e,0xe8,0xff,0x04,0x74,0x03,0xe9,0x1d,0x00,0xc6,0x06
+,0xe8,0xff,0x01,0xba,0x0c,0x01,0xb8,0x08,0x08,0xef,0xed,0xe9,0x0d,0x00,0xc6,0x06
+,0xe8,0xff,0x03,0xba,0x0c,0x01,0xb8,0x08,0x08,0xef,0xed,0xc3,0xa9,0x01,0x00,0x74
+,0x1c,0xe8,0x2c,0x00,0x83,0x3e,0xe0,0x3a,0x00,0x74,0x0f,0x06,0x8e,0x06,0x38,0x34
+,0xe8,0xc9,0x04,0xc7,0x06,0xe0,0x3a,0x00,0x00,0x07,0xe9,0x5d,0x00,0x8b,0xd0,0x8e
+,0x06,0x38,0x34,0x26,0xa3,0x0c,0x00,0xe8,0x06,0x00,0x68,0x69,0x1d,0xe9,0x4a,0x00
+,0xa9,0x00,0x04,0x74,0x0a,0xb8,0x00,0x04,0xff,0x06,0xd8,0x33,0xe9,0x17,0x00,0xa9
+,0x00,0x01,0x74,0x0a,0xff,0x06,0x39,0x37,0xb8,0x00,0x01,0xe9,0x08,0x00,0xa9,0x10
+,0x00,0xb8,0x10,0x00,0x74,0x1d,0x09,0x06,0x66,0x37,0x8c,0xc0,0x8e,0x06,0x30,0x34
+,0x26,0xf7,0x06,0x0a,0x00,0x00,0x01,0x74,0x07,0x26,0x81,0x0e,0x08,0x00,0x00,0x01
+,0x8e,0xc0,0xc3,0xff,0x06,0xc2,0x33,0xe9,0xf8,0xff,0xe5,0x00,0x0d,0x18,0x00,0xe7
+,0x00,0xe5,0x02,0x0d,0x11,0x00,0xe7,0x02,0xc3,0x58,0xe9,0x43,0xfd,0xe5,0x08,0x0d
+,0x00,0x04,0x25,0xff,0x04,0xe7,0x08,0xe9,0xe0,0xff,0xe5,0x0e,0xa9,0x00,0x08,0x75
+,0x01,0xc3,0xe9,0xf5,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x50,0x51,0x56,0x57,0x52,0x06,0x1e,0x33,0xc0,0x8e,0xd8,0xe7,0x5a,0xff,0x06,0xb8
+,0x33,0xe5,0x48,0x06,0x53,0x57,0xff,0x16,0x4e,0x37,0x5f,0x5b,0x83,0x3e,0x80,0x01
+,0xff,0x74,0x58,0x8e,0x06,0x80,0x01,0x26,0xff,0x0e,0x08,0x00,0x75,0x4d,0x26,0xa1
+,0x00,0x00,0xa3,0x80,0x01,0x26,0xc7,0x06,0x00,0x00,0xff,0xff,0x8c,0xc0,0x26,0x8e
+,0x06,0x02,0x00,0x26,0x81,0x0e,0x08,0x00,0x80,0x00,0x8b,0xd0,0x26,0x87,0x06,0x1a
+,0x00,0x26,0x83,0x3e,0x18,0x00,0xff,0x74,0x0a,0x8e,0xc0,0x26,0x89,0x16,0x00,0x00
+,0xe9,0x05,0x00,0x26,0x89,0x16,0x18,0x00,0x83,0x3e,0x80,0x01,0xff,0x74,0x0c,0x8e
+,0x06,0x80,0x01,0x26,0x83,0x3e,0x08,0x00,0x00,0x74,0xb3,0x07,0xe9,0x3e,0xf7,0xe5
+,0x4c,0x90,0xe5,0x02,0xa9,0x00,0x20,0x74,0x0d,0x25,0xff,0xdf,0x0d,0x01,0x00,0xe7
+,0x02,0x0d,0x00,0x20,0xe7,0x02,0xe5,0x0a,0x8b,0xd8,0xa3,0xf4,0x33,0x25,0xc3,0x57
+,0x0d,0x00,0x10,0xe7,0x0a,0xf7,0x06,0x9b,0x36,0x00,0x80,0x74,0x37,0xf7,0xc3,0x00
+,0x80,0x74,0x06,0xf7,0xc3,0x00,0x08,0x74,0x5d,0x81,0x26,0xc2,0x34,0x7f,0xff,0xc7
+,0x06,0x35,0x37,0x05,0x00,0xb8,0x80,0x03,0xcd,0x39,0x81,0x26,0x9b,0x36,0xff,0x7f
+,0xc7,0x06,0x0f,0x37,0x04,0x00,0xf7,0x06,0x9b,0x36,0x40,0x00,0x75,0x06,0xc7,0x06
+,0x0f,0x37,0x03,0x00,0xf7,0x06,0x9b,0x36,0x00,0x20,0x74,0x2a,0xf7,0xc3,0x00,0x08
+,0x74,0x24,0x80,0x3e,0x9d,0x36,0x06,0x7c,0x1d,0xff,0x06,0x94,0x34,0x83,0x0e,0x66
+,0x37,0x20,0x8e,0x06,0x30,0x34,0x26,0xf7,0x06,0x0a,0x00,0x00,0x01,0x74,0x07,0x26
+,0x81,0x0e,0x08,0x00,0x00,0x01,0xf7,0xc3,0x00,0x20,0x75,0x3b,0xf7,0x06,0x9a,0x37
+,0x80,0x00,0x74,0x0b,0xff,0x06,0x89,0x37,0x33,0xc0,0xe7,0x0e,0xe9,0x04,0x00,0xff
+,0x06,0x3b,0x37,0xf7,0x06,0x9b,0x36,0x00,0x20,0x74,0x1c,0x80,0x26,0x9e,0x36,0xff
+,0x75,0x15,0x8e,0x06,0x30,0x34,0x26,0xf7,0x06,0x0a,0x00,0x00,0x08,0x74,0x07,0x26
+,0x81,0x0e,0x08,0x00,0x00,0x08,0xc3,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x02,0x23,0x02,0x23,0x02,0x23,0x02,0x23,0x03,0x23,0xdd,0x22,0x02,0x23,0xfd,0x21
+,0x02,0x23,0xa4,0x24,0xf3,0x24,0x02,0x23,0x8d,0x22,0x7a,0x23,0x02,0x23,0x97,0x24
+,0x1b,0x24,0x75,0x24,0x02,0x23,0x02,0x23,0x8e,0x25,0xfb,0x8e,0x06,0x7e,0x01,0xfb
+,0x26,0x83,0x3e,0x00,0x00,0xff,0x74,0xf2,0x26,0x8e,0x06,0x00,0x00,0xfa,0x26,0x8b
+,0x1e,0x08,0x00,0x26,0x23,0x1e,0x0a,0x00,0x74,0xe5,0x8c,0xc0,0x8e,0xd0,0x26,0x8b
+,0x26,0x02,0x00,0x8c,0x16,0xf2,0x33,0x22,0xff,0x75,0x6a,0x26,0xa1,0x1c,0x00,0x8a
+,0xe3,0x8a,0xdc,0x22,0xd8,0x75,0x0d,0xd0,0xe8,0x24,0xf8,0x0a,0xc0,0x75,0xf2,0xb0
+,0x80,0xe9,0xed,0xff,0xd0,0xe8,0x24,0xf8,0x0a,0xc0,0x75,0x02,0xb0,0x80,0x32,0xe4
+,0x26,0xa3,0x1c,0x00,0xf7,0xc3,0x08,0x00,0x75,0x47,0x2e,0x8a,0x9f,0xc5,0x25,0x2e
+,0x8b,0xbf,0xc5,0x26,0x80,0xc3,0x10,0x26,0x8e,0x1d,0x26,0x8c,0x1e,0x06,0x00,0x8b
+,0x16,0x00,0x00,0xc7,0x06,0x00,0x00,0xff,0xff,0x26,0x89,0x15,0x83,0xfa,0xff,0x75
+,0x0a,0x2e,0x8b,0x97,0xcd,0x26,0x26,0x21,0x16,0x08,0x00,0x33,0xc0,0x8e,0xd8,0x26
+,0x89,0x1e,0x04,0x00,0xc3,0x8a,0xdf,0xb7,0x00,0x2e,0x8a,0x9f,0xc5,0x25,0xe9,0xe0
+,0xff,0x26,0x83,0x26,0x08,0x00,0xf7,0x83,0xc3,0x10,0xe9,0xde,0xff,0x60,0x06,0x1e
+,0x68,0x87,0x25,0x6a,0x00,0x1f,0x8e,0x06,0xf2,0x33,0x8b,0x0e,0x34,0x34,0x39,0x0e
+,0xf2,0x33,0x74,0x0e,0x26,0x81,0x0e,0x0a,0x00,0x00,0x02,0x26,0x81,0x0e,0x08,0x00
+,0x00,0x02,0x26,0x89,0x26,0x02,0x00,0xa3,0xf2,0x33,0x8e,0xd0,0x8d,0x26,0x80,0x00
+,0x36,0x89,0x26,0x02,0x00,0x36,0x89,0x1e,0x20,0x00,0x36,0xc7,0x06,0x08,0x00,0x00
+,0x00,0xb9,0x04,0x00,0xbe,0x00,0x00,0x2e,0x8b,0xbc,0xc5,0x26,0x36,0xc7,0x05,0xff
+,0xff,0x36,0xc7,0x45,0x02,0xff,0xff,0x83,0xc6,0x02,0xe2,0xeb,0x8e,0x06,0x7e,0x01
+,0x36,0x8b,0x0e,0x22,0x00,0x8c,0xc0,0x26,0x83,0x3e,0x00,0x00,0xff,0x26,0x8e,0x06
+,0x00,0x00,0x74,0x07,0x26,0x3b,0x0e,0x22,0x00,0x7d,0xea,0x36,0x8c,0x06,0x00,0x00
+,0x8e,0xc0,0x26,0x8c,0x16,0x00,0x00,0xfb,0x36,0xff,0x2e,0x1e,0x00,0x06,0x1e,0x68
+,0x8b,0x25,0x6a,0x00,0x1f,0x26,0x09,0x36,0x08,0x00,0xf7,0xc6,0x00,0xff,0x74,0x01
+,0xc3,0x56,0x52,0x2e,0x8b,0xb4,0xc5,0x25,0x81,0xe6,0xff,0x00,0x2e,0x8b,0xb4,0xc5
+,0x26,0x8c,0xc2,0x8e,0xc0,0x26,0xc7,0x06,0x00,0x00,0xff,0xff,0x8e,0xc2,0x26,0x83
+,0x3c,0xff,0x74,0x0f,0x8b,0xd0,0x26,0x87,0x54,0x02,0x8e,0xc2,0x26,0xa3,0x00,0x00
+,0xe9,0x07,0x00,0x26,0x89,0x44,0x02,0x26,0x89,0x04,0x5a,0x5e,0xc3,0x06,0x1e,0x68
+,0x8b,0x25,0x6a,0x00,0x1f,0x8e,0x06,0xf2,0x33,0x26,0xa3,0x0a,0x00,0x26,0x89,0x26
+,0x02,0x00,0xa1,0x34,0x34,0x8e,0xd0,0x8d,0x26,0x80,0x00,0x8c,0x16,0xf2,0x33,0xe9
+,0x4d,0xfe,0xcf,0x50,0x1e,0x52,0x53,0x33,0xc0,0x8e,0xd8,0x26,0x83,0x3e,0x04,0x00
+,0xff,0x26,0xc7,0x06,0x04,0x00,0x00,0x00,0x74,0x03,0xe9,0x1a,0x00,0x83,0x3e,0xe6
+,0x3a,0x02,0x76,0x13,0xff,0x06,0xd6,0x33,0x8c,0xc0,0x8e,0x06,0x32,0x34,0xbe,0x40
+,0x00,0x68,0x3a,0x23,0xe9,0x5e,0xff,0xe8,0x84,0xf8,0x5b,0x5a,0x1f,0x58,0xcf,0xe8
+,0xe1,0x00,0x26,0xc6,0x06,0x18,0x00,0x10,0x26,0x8a,0x1e,0x29,0x00,0x88,0x1e,0x1b
+,0x37,0x26,0xc7,0x06,0x0c,0x00,0xff,0x7f,0x26,0xa1,0x0e,0x00,0xe7,0x9c,0x26,0xa1
+,0x08,0x00,0xe7,0x9a,0xe5,0x00,0x80,0xfb,0x08,0x74,0x09,0x0d,0x18,0xac,0xe7,0x00
+,0x07,0x1f,0x58,0xcf,0x0d,0x18,0x00,0xe9,0xf4,0xff,0x50,0x1e,0x06,0x33,0xc0,0x8e
+,0xd8,0x83,0x3e,0xa1,0x36,0x00,0x75,0xb7,0x26,0x8b,0x36,0x06,0x00,0x2e,0xff,0x94
+,0xdc,0x23,0x07,0x1f,0x58,0xcf,0xe8,0x8a,0x00,0xe5,0x00,0x0d,0x18,0x00,0xe7,0x00
+,0xe8,0x49,0x00,0xc3,0x53,0xf7,0x06,0xef,0x34,0x20,0x00,0x75,0x2d,0xe5,0x8c,0x25
+,0x00,0x70,0x8b,0xd8,0xe5,0x8c,0x25,0x00,0x70,0x3b,0xc3,0x74,0x05,0x8b,0xd8,0xe9
+,0xf2,0xff,0x3d,0x00,0x30,0x75,0x10,0xe5,0x02,0x25,0xef,0xff,0xe7,0x02,0xc7,0x06
+,0xe0,0x3a,0xff,0xff,0xe9,0x03,0x00,0xe8,0x12,0x00,0x5b,0xc3,0xa3,0x23,0x96,0x23
+,0xa4,0x23,0xa4,0x23,0x96,0x23,0xa4,0x23,0x96,0x23,0x96,0x23,0x26,0xa0,0x29,0x00
+,0xa2,0x1b,0x37,0x26,0xc7,0x06,0x0c,0x00,0xff,0x7f,0x26,0xa1,0x0e,0x00,0xe7,0x9c
+,0x26,0xa1,0x08,0x00,0xe7,0x9a,0xe5,0x00,0x25,0xff,0x53,0x26,0x8b,0x36,0x06,0x00
+,0x83,0xe6,0x0e,0x2e,0x0b,0x84,0xad,0x25,0xe7,0x00,0xc3,0x06,0x1e,0x68,0x8b,0x25
+,0x6a,0x00,0x1f,0x83,0x0e,0xef,0x34,0x20,0x83,0x0e,0x9b,0x36,0x08,0xe5,0x00,0x25
+,0xef,0xff,0x0d,0x08,0x00,0xe7,0x00,0xe5,0x00,0xa9,0x10,0x00,0x75,0x01,0xc3,0xe5
+,0x00,0xa9,0x10,0x00,0x75,0xf9,0xc3,0x50,0x53,0x51,0x56,0x06,0x1e,0x33,0xc0,0x8e
+,0xd8,0xb8,0x05,0x00,0xe7,0x84,0xe5,0x08,0x0d,0x00,0x04,0x25,0xff,0x04,0xe7,0x08
+,0xe5,0x00,0x0d,0x18,0x00,0xe7,0x00,0xe5,0x02,0x0d,0x11,0x00,0xe7,0x02,0x1f,0x07
+,0x5e,0x59,0x5b,0x58,0xc3,0x50,0x1e,0x33,0xc0,0x8e,0xd8,0xc7,0x06,0xef,0x34,0x00
+,0x00,0x83,0x26,0x9b,0x36,0xf7,0xe5,0x00,0x0d,0x18,0x00,0xe7,0x00,0xe5,0x02,0x0d
+,0x11,0x00,0xe7,0x02,0x1f,0x58,0xcf,0x60,0x06,0x1e,0x68,0x87,0x25,0x6a,0x00,0x1f
+,0xe8,0x16,0xf5,0xc3,0x06,0x1e,0x68,0x8b,0x25,0x6a,0x00,0x1f,0x8e,0xc0,0x26,0x83
+,0x3e,0x0a,0x00,0x00,0x74,0x03,0xe8,0x43,0x00,0x26,0xc7,0x06,0x0a,0x00,0xff,0xff
+,0x26,0x8b,0x16,0x06,0x00,0x8e,0x1e,0x8e,0x01,0x8c,0xd8,0x8b,0xca,0x83,0x3e,0x00
+,0x00,0xff,0x8e,0x1e,0x00,0x00,0x74,0x0a,0x2b,0x16,0x08,0x00,0x73,0xeb,0x29,0x0e
+,0x08,0x00,0x26,0x89,0x0e,0x08,0x00,0x26,0x8c,0x1e,0x00,0x00,0x8e,0xd8,0x8c,0x06
+,0x00,0x00,0xc3,0x60,0x06,0x1e,0x68,0x87,0x25,0x6a,0x00,0x1f,0x8e,0xc0,0x8b,0xc8
+,0x8e,0x1e,0x8e,0x01,0x26,0xc7,0x06,0x0a,0x00,0x00,0x00,0x8c,0xd8,0x83,0x3e,0x00
+,0x00,0xff,0x74,0x25,0x3b,0x0e,0x00,0x00,0x8e,0x1e,0x00,0x00,0x75,0xed,0x8e,0xd8
+,0x26,0xa1,0x00,0x00,0xa3,0x00,0x00,0x3d,0xff,0xff,0x74,0x56,0x8e,0xd8,0x26,0xa1
+,0x08,0x00,0x01,0x06,0x08,0x00,0xe9,0x49,0x00,0x26,0x8e,0x1e,0x02,0x00,0xbe,0x18
+,0x00,0x83,0x3c,0xff,0x74,0x3c,0x39,0x0c,0x74,0x19,0x8e,0x1c,0xbe,0x00,0x00,0x83
+,0x3e,0x00,0x00,0xff,0x74,0x2c,0x39,0x0e,0x00,0x00,0x74,0x07,0x8e,0x1e,0x00,0x00
+,0xe9,0xec,0xff,0x26,0xa1,0x00,0x00,0x89,0x04,0x33,0xc9,0x8e,0xd9,0x3d,0xff,0xff
+,0x75,0x10,0x83,0xfe,0x18,0x75,0x0b,0x26,0x8e,0x1e,0x02,0x00,0x81,0x26,0x08,0x00
+,0x7f,0xff,0x33,0xc0,0x8e,0xd8,0xc3,0x1f,0x07,0x61,0xcf,0x1f,0x07,0xcf,0x60,0x06
+,0x1e,0x68,0x87,0x25,0x6a,0x00,0x1f,0xe5,0x06,0x25,0x1e,0x00,0x3d,0x1e,0x00,0x75
+,0xf6,0xb9,0x08,0x00,0xe5,0x58,0xe7,0x5a,0x23,0xc0,0xe0,0xf8,0xc3,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x00,0x00,0x00,0xa8,0x00,0x8c,0x02,0x04,0x00
+,0x00,0x08,0x10,0x20,0x00,0xff,0x0e,0x0c,0x0c,0x0a,0x0a,0x0a,0x0a,0x08,0x08,0x08
+,0x08,0x08,0x08,0x08,0x08,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06
+,0x06,0x06,0x06,0x06,0x06,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04
+,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04
+,0x04,0x04,0x04,0x04,0x04,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
+,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
+,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
+,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02
+,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x14,0x00,0x10,0x00,0x0c,0x00,0xff,0x7f,0xff
+,0xbf,0xff,0xdf,0xff,0xef,0xff,0xf7,0xff,0xfb,0xff,0xfd,0xff,0xfe,0x7f,0xff,0xbf
+,0xff,0xdf,0xff,0xef,0xff,0xf7,0xff,0xfb,0xff,0xfd,0xff,0xfe,0xff,0x00,0x00,0x00
+,0x80,0x3e,0xe2,0x34,0x01,0x76,0x03,0xe9,0xa5,0x00,0xb8,0x00,0x00,0xe7,0x4e,0xb9
+,0x28,0x00,0xe2,0xfe,0xc6,0x06,0x45,0x37,0x02,0xbf,0x3f,0x28,0x2e,0x8b,0x45,0x08
+,0xe7,0x4e,0xb9,0x28,0x00,0xe2,0xfe,0x2e,0x8b,0x1d,0xc7,0x06,0xb3,0x36,0x40,0x11
+,0xc7,0x06,0xb1,0x36,0x27,0x00,0xc7,0x06,0x46,0x37,0x02,0x00,0xc7,0x06,0x48,0x37
+,0x64,0x00,0xf7,0x06,0xb5,0x36,0x02,0x00,0x75,0x1c,0x2e,0x0b,0x5d,0x02,0x81,0x26
+,0xb3,0x36,0xff,0xfe,0xc7,0x06,0xb1,0x36,0x9c,0x00,0xc7,0x06,0x46,0x37,0x08,0x00
+,0xc7,0x06,0x48,0x37,0x90,0x01,0x89,0x1e,0xb7,0x36,0x89,0x1e,0xfe,0x33,0xbe,0x20
+,0x00,0x8b,0xc3,0xe7,0x4e,0xb9,0x28,0x00,0xe2,0xfe,0x2e,0x8b,0x45,0x04,0xe7,0x4e
+,0xb9,0x28,0x00,0xe2,0xfe,0xe5,0x4e,0x8b,0xcb,0x2e,0x23,0x45,0x06,0x2e,0x23,0x4d
+,0x06,0x3a,0xc1,0x74,0x36,0x4e,0x75,0xd9,0x80,0x3e,0x45,0x37,0x00,0x74,0x0b,0xc6
+,0x06,0x45,0x37,0x00,0xbf,0x2f,0x28,0xe9,0x72,0xff,0xc6,0x06,0x45,0x37,0x01,0xf7
+,0x06,0xb5,0x36,0x02,0x00,0x74,0x14,0xe5,0xce,0x25,0xfd,0xff,0xe7,0xce,0xe8,0x43
+,0x00,0xe5,0xce,0x0d,0x02,0x00,0xe7,0xce,0xe8,0x39,0x00,0x80,0x3e,0xe2,0x34,0x01
+,0x76,0x01,0xc3,0xb8,0xea,0x05,0xe7,0x8c,0xfa,0xe8,0x12,0xf4,0xfb,0x8d,0x06,0xd0
+,0x39,0x8b,0xd8,0xc1,0xe8,0x04,0xa3,0x38,0x34,0x8e,0xc0,0xa1,0x30,0x34,0x26,0xa3
+,0x02,0x00,0x26,0xc7,0x06,0x00,0x00,0xff,0xff,0x83,0xc3,0x18,0xd1,0xeb,0x26,0x89
+,0x1e,0x08,0x00,0xc3,0xe5,0x02,0x0d,0x00,0x40,0xe7,0x02,0xe5,0x00,0x0d,0x04,0x00
+,0xe7,0x00,0xb8,0x00,0x00,0xe7,0x0a,0xe5,0x0a,0xa9,0x00,0x80,0x75,0x14,0xe5,0x08
+,0x0d,0x00,0x10,0xe7,0x08,0xe5,0x0a,0x0d,0x00,0x08,0xb9,0x05,0x00,0xe7,0x0a,0xe2
+,0xfc,0xc3,0xe5,0x08,0x0d,0x00,0x10,0xb9,0x05,0x00,0xe7,0x08,0xe2,0xfc,0xc3,0x04
+,0x0c,0x20,0x00,0x01,0x0c,0x7e,0xff,0x00,0x0c,0x02,0x00,0x10,0x00,0x40,0x00,0x0c
+,0xc6,0x01,0x00,0x00,0xc0,0xf7,0xff,0x00,0xc0,0x02,0x00,0x10,0x00,0x40,0x00,0x00
+,0x33,0xc0,0x8e,0xd8,0x8d,0x3e,0x72,0x49,0x8d,0x36,0xb0,0x37,0xb9,0x14,0x00,0x8b
+,0x1e,0x30,0x34,0x89,0x5c,0x02,0x2e,0x8b,0x45,0x02,0x89,0x44,0x06,0x2e,0x8b,0x05
+,0x89,0x44,0x04,0x83,0xc7,0x04,0x83,0xc6,0x10,0xe2,0xe8,0xc6,0x06,0x9e,0x36,0x0e
+,0xe8,0xfd,0x26,0x68,0x83,0x28,0xa1,0xaa,0x02,0xcd,0x35,0x83,0x3e,0xa1,0x36,0x00
+,0x74,0x03,0xe9,0x3b,0x27,0x33,0xff,0x8e,0x06,0xa6,0x02,0x8b,0x36,0xa4,0x02,0x2e
+,0xff,0xa4,0x2e,0x30,0x83,0x0e,0x99,0x36,0x04,0xc7,0x06,0x37,0x37,0x01,0x00,0xc6
+,0x06,0xca,0x34,0x01,0xe9,0x7d,0x19,0x80,0x3e,0xa0,0x36,0x08,0x74,0xe6,0x80,0x26
+,0x9e,0x36,0xff,0x75,0x1a,0xf7,0x06,0x9b,0x36,0x00,0x20,0x74,0x12,0xf7,0x06,0x9b
+,0x36,0x03,0x00,0x75,0x0a,0x83,0x0e,0x66,0x37,0x10,0xc6,0x06,0xa0,0x36,0x08,0xe9
+,0xfb,0x01,0x80,0x3e,0x9e,0x36,0x02,0x75,0xce,0xc6,0x06,0xa0,0x36,0x06,0xe9,0xec
+,0x01,0xc3,0xe9,0xe8,0x01,0x26,0xc7,0x06,0x0a,0x00,0x00,0x00,0x26,0xff,0x26,0x04
+,0x00,0xa1,0xd1,0x36,0x26,0x39,0x06,0x1a,0x00,0x75,0x22,0xa1,0xd3,0x36,0x26,0x39
+,0x06,0x1c,0x00,0x75,0x18,0xa1,0xd5,0x36,0x26,0x39,0x06,0x1e,0x00,0x75,0x0e,0x26
+,0xf7,0x06,0x0c,0x00,0x40,0x00,0x74,0x05,0x83,0x0e,0x66,0x37,0x40,0x81,0x0e,0xaf
+,0x36,0x00,0x10,0xa1,0xaf,0x36,0xe7,0x06,0x80,0x3e,0x9d,0x36,0x02,0x75,0x06,0xcd
+,0x34,0xe9,0xa2,0x1a,0xc3,0xf7,0x06,0x9b,0x36,0x10,0x00,0x75,0x54,0x26,0xf6,0x06
+,0x0a,0x00,0xff,0x75,0x4c,0x26,0xa0,0x19,0x00,0x24,0xc0,0x3c,0x40,0x75,0x11,0x80
+,0x3e,0x95,0x36,0x00,0x74,0x3b,0x26,0xc7,0x06,0x04,0x00,0xff,0xff,0xe9,0x31,0x00
+,0xe8,0xf1,0x04,0xf7,0x06,0x9b,0x36,0x03,0x00,0x74,0x2f,0x8b,0xd8,0xb8,0x7d,0x03
+,0xcd,0x3a,0x8b,0xc3,0xc6,0x06,0xa0,0x36,0x06,0xf7,0x06,0x9b,0x36,0x02,0x00,0x75
+,0x05,0xc6,0x06,0xa0,0x36,0x04,0x81,0x0e,0x9b,0x36,0x80,0x00,0x83,0x26,0x9b,0x36
+,0xfc,0xe9,0x23,0x01,0xe8,0x87,0x1d,0xe9,0x33,0x01,0x50,0x26,0xa1,0x0c,0x00,0x25
+,0x07,0x00,0x3d,0x07,0x00,0x75,0x03,0xe9,0x84,0x00,0x3d,0x05,0x00,0x75,0x03,0xe9
+,0x7c,0x00,0x83,0x3e,0xe8,0x3a,0x04,0x74,0x75,0x83,0x3e,0xe8,0x3a,0x02,0x74,0x6e
+,0xf7,0x06,0xe6,0x34,0x18,0x80,0x75,0x03,0xe9,0x6a,0x00,0xf7,0x06,0xe6,0x34,0x00
+,0x80,0x74,0x35,0x26,0x80,0x3e,0x29,0x00,0x02,0x75,0x2d,0x51,0x56,0x57,0x8d,0x36
+,0x3e,0x34,0x8d,0x3e,0x20,0x00,0xb9,0x06,0x00,0xf3,0xa6,0x5f,0x5e,0x59,0x74,0x45
+,0x26,0xa1,0x20,0x00,0xa3,0x3e,0x34,0x26,0xa1,0x22,0x00,0xa3,0x40,0x34,0x26,0xa1
+,0x24,0x00,0xa3,0x42,0x34,0xe9,0x26,0x00,0xf7,0x06,0xe6,0x34,0x08,0x00,0x74,0x0b
+,0x26,0x80,0x3e,0x19,0x00,0x00,0x74,0x03,0xe9,0x13,0x00,0xf7,0x06,0xe6,0x34,0x10
+,0x00,0x74,0x12,0x26,0xa0,0x28,0x00,0xc0,0xe8,0x04,0x22,0xc0,0x74,0x07,0x26,0xc7
+,0x06,0x04,0x00,0xff,0xff,0x58,0x23,0xc0,0x74,0x03,0xe9,0x57,0xff,0x81,0x26,0x9b
+,0x36,0xff,0xfe,0x83,0xfe,0x06,0x7f,0x24,0x26,0xa1,0x20,0x00,0x3b,0x06,0xd1,0x36
+,0x75,0x1a,0x26,0xa1,0x22,0x00,0x3b,0x06,0xd3,0x36,0x75,0x10,0x26,0xa1,0x24,0x00
+,0x3b,0x06,0xd5,0x36,0x75,0x06,0x81,0x0e,0x9b,0x36,0x00,0x01,0x26,0xa1,0x20,0x00
+,0x25,0x7f,0xff,0xa3,0xb8,0x34,0x26,0xa1,0x22,0x00,0xa3,0xba,0x34,0x26,0xa1,0x24
+,0x00,0xa3,0xbc,0x34,0x8b,0xc6,0x86,0xc4,0xa3,0xc0,0x34,0xd1,0xe6,0x80,0xfc,0x09
+,0x74,0x03,0xe8,0xaa,0x1c,0x8b,0xc6,0x2e,0xff,0xa4,0x30,0x49,0x26,0xa1,0x0c,0x00
+,0x3d,0xff,0x7f,0x74,0x0f,0x26,0xff,0x26,0x04,0x00,0x8e,0x06,0x38,0x34,0xe8,0x36
+,0x06,0xcd,0x50,0xc3,0xe9,0x16,0x00,0xcd,0x34,0xe9,0x11,0x00,0xcd,0x34,0x89,0x36
+,0x3d,0x37,0xa1,0x9d,0x36,0xa3,0x3f,0x37,0xc6,0x06,0xa0,0x36,0x0c,0xe8,0x8e,0x00
+,0xa1,0x9f,0x36,0x22,0xe4,0x75,0x32,0xf7,0x06,0x4c,0x37,0x01,0x00,0x75,0x2a,0xf6
+,0x06,0x9d,0x36,0x80,0x74,0x07,0x88,0x26,0x9e,0x36,0xe9,0x31,0x00,0x3a,0x06,0x9d
+,0x36,0xa3,0x9d,0x36,0x74,0x28,0x8b,0xf0,0x2e,0xff,0xa4,0x0d,0x2b,0x44,0x29,0xee
+,0x42,0x19,0x44,0xcd,0x44,0x2f,0x45,0x5a,0x45,0x3a,0x26,0x9e,0x36,0x75,0x01,0xc3
+,0x32,0xc0,0x86,0xc4,0x8b,0xf0,0xa2,0x9e,0x36,0x2e,0xff,0xa4,0x20,0x49,0x8b,0x2e
+,0x99,0x36,0x23,0xed,0x75,0x01,0xc3,0xbf,0x01,0x00,0xbe,0x00,0x00,0x85,0xfd,0x75
+,0x1a,0x46,0xd1,0xe7,0xe9,0xf6,0xff,0x2a,0x00,0x29,0x00,0x28,0x00,0x27,0x00,0x25
+,0x00,0x05,0x00,0x07,0x00,0x26,0x00,0x06,0x00,0x20,0x00,0xf7,0xd7,0x21,0x3e,0x99
+,0x36,0xd1,0xe6,0x2e,0x8b,0xb4,0x47,0x2b,0xe9,0x4f,0xff,0xe9,0x56,0xff,0x80,0x26
+,0x9e,0x36,0xff,0x75,0x17,0xf7,0x06,0x4c,0x37,0x01,0x00,0x75,0x0f,0xf6,0x06,0x9d
+,0x36,0x80,0x74,0x08,0xf7,0x06,0x66,0x37,0xff,0xff,0x75,0x07,0xc7,0x06,0x66,0x37
+,0x00,0x00,0xc3,0xf7,0x06,0x41,0x37,0x01,0x00,0x75,0x0b,0xb8,0x7f,0x03,0xcd,0x39
+,0xc7,0x06,0x41,0x37,0x01,0x00,0x33,0xf6,0xb8,0x00,0x40,0x85,0x06,0x66,0x37,0x74
+,0x21,0x80,0xbc,0x54,0x37,0xff,0x74,0x04,0xfe,0x84,0x54,0x37,0x80,0xbc,0x96,0x34
+,0xff,0x74,0x04,0xfe,0x84,0x96,0x34,0x31,0x06,0x66,0x37,0x83,0x3e,0x66,0x37,0x00
+,0x74,0x05,0x46,0xd1,0xe8,0x73,0xd4,0xc3,0xa1,0xf4,0x33,0xa9,0x00,0x88,0x74,0x0b
+,0xa9,0x00,0x10,0x75,0x09,0x8b,0x1e,0x43,0x37,0xff,0xe3,0xe9,0xd7,0x00,0xc7,0x06
+,0x35,0x37,0x05,0x00,0xc7,0x06,0x43,0x37,0x1e,0x2c,0xf7,0x06,0xf4,0x33,0x00,0x08
+,0x74,0x06,0xc7,0x06,0x43,0x37,0x10,0x2c,0xb8,0x80,0x03,0xcd,0x39,0xe9,0xcd,0xfe
+,0xa9,0x00,0x08,0x74,0xd9,0xff,0x0e,0x35,0x37,0x75,0xed,0xe9,0x66,0x00,0xa9,0x00
+,0x08,0x75,0xcb,0xff,0x0e,0x35,0x37,0x75,0xdf,0x81,0x0e,0xc2,0x34,0xc0,0x00,0xf6
+,0x06,0x9d,0x36,0x80,0x74,0x48,0x81,0x0e,0x9b,0x36,0x00,0x80,0xf7,0x06,0x9b,0x36
+,0x01,0x00,0x74,0x1e,0xb8,0x7d,0x03,0xcd,0x3a,0x81,0x0e,0x9b,0x36,0x80,0x00,0x83
+,0x26,0x9b,0x36,0xfe,0xc7,0x06,0x0f,0x37,0x02,0x00,0xc6,0x06,0xa0,0x36,0x04,0xe9
+,0x7b,0xfe,0x80,0x3e,0xa0,0x36,0x04,0x75,0x07,0x83,0x3e,0x0f,0x37,0x01,0x75,0x05
+,0xc6,0x06,0xa0,0x36,0x06,0xc7,0x06,0x0f,0x37,0x02,0x00,0xe9,0x5f,0xfe,0xbe,0x02
+,0x00,0xe9,0x4a,0xfe,0x80,0x26,0x9e,0x36,0xff,0x75,0x3a,0xf6,0x06,0x9d,0x36,0x80
+,0x74,0x2d,0xf7,0x06,0x9b,0x36,0x00,0x20,0x75,0x2b,0xc6,0x06,0xa0,0x36,0x06,0xff
+,0x06,0x94,0x34,0x83,0x0e,0x66,0x37,0x20,0x8e,0x06,0x30,0x34,0x26,0xf7,0x06,0x0a
+,0x00,0x00,0x01,0x74,0x07,0x26,0x81,0x0e,0x08,0x00,0x00,0x01,0xe9,0x06,0x00,0xbe
+,0x04,0x00,0xe9,0x09,0xfe,0x81,0x0e,0xaf,0x36,0x00,0x08,0xa1,0xaf,0x36,0xe7,0x06
+,0xe5,0x0a,0xa9,0x00,0x80,0x74,0x0e,0x81,0x26,0xaf,0x36,0xff,0xf7,0xa1,0xaf,0x36
+,0xe7,0x06,0xe9,0x09,0xff,0xe9,0xf5,0xfd,0xc7,0x06,0x41,0x37,0x00,0x00,0x83,0x0e
+,0x99,0x36,0x02,0xe9,0xe7,0xfd,0x80,0x26,0x9e,0x36,0xff,0x75,0x1d,0xf7,0x06,0x9b
+,0x36,0x00,0x40,0x75,0x05,0x83,0x0e,0x99,0x36,0x08,0x83,0x0e,0x99,0x36,0x20,0x81
+,0x26,0x9b,0x36,0xff,0xbf,0xb8,0x85,0x03,0xcd,0x39,0xe9,0xc0,0xfd,0x80,0x3e,0x9e
+,0x36,0x06,0x74,0x07,0x80,0x3e,0x9e,0x36,0x0a,0x75,0x34,0xf6,0x06,0x9d,0x36,0x80
+,0x75,0x06,0xbe,0x07,0x00,0xe9,0x96,0xfd,0xc6,0x06,0xa0,0x36,0x04,0x83,0x3e,0x0f
+,0x37,0x02,0x74,0x1b,0xc7,0x06,0x0f,0x37,0x04,0x00,0x80,0x3e,0x9e,0x36,0x06,0x75
+,0x0e,0xf7,0x06,0x9b,0x36,0x40,0x00,0x75,0x06,0xc7,0x06,0x0f,0x37,0x03,0x00,0xe9
+,0x7b,0xfd,0x80,0x3e,0x9d,0x36,0x04,0x75,0x12,0x81,0x0e,0xc2,0x34,0x00,0x40,0xff
+,0x06,0x92,0x34,0xc6,0x06,0xa0,0x36,0x06,0xe9,0x62,0xfd,0xbe,0x05,0x00,0xe9,0x4d
+,0xfd,0xf6,0x06,0x9d,0x36,0x80,0x75,0x19,0x83,0x0e,0xc2,0x34,0x04,0xbe,0x06,0x00
+,0xe9,0x3b,0xfd,0x80,0x26,0x9e,0x36,0xff,0x75,0xc5,0xff,0x06,0x31,0x37,0xe9,0x00
+,0x00,0x83,0x26,0xc2,0x34,0xbf,0xc6,0x06,0xa0,0x36,0x06,0xe9,0x2f,0xfd,0xe5,0x0a
+,0x50,0x25,0xc3,0xbf,0xe7,0x0a,0x58,0x80,0x26,0x9e,0x36,0xff,0x75,0x0d,0xa9,0x00
+,0x40,0x75,0x08,0xc6,0x06,0xa0,0x36,0x06,0xe9,0x12,0xfd,0xb8,0x83,0x03,0xcd,0x39
+,0xc3,0xb8,0x7c,0x03,0xcd,0x39,0xf7,0x06,0xf4,0x33,0x00,0x10,0x75,0x09,0xc7,0x06
+,0x33,0x37,0x02,0x00,0xe9,0xf6,0xfc,0xff,0x0e,0x33,0x37,0x74,0x03,0xe9,0xed,0xfc
+,0xff,0x06,0x8e,0x34,0xe8,0xf7,0x19,0x83,0x0e,0xc2,0x34,0x08,0xbe,0x03,0x00,0xe9
+,0xcc,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x04,0x05
+,0x04,0x04,0x04,0x00,0x03,0x00,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x04,0x00,0x08,0x08,0x05,0x08,0x08,0x08,0x00,0x03,0x00,0x03,0x03,0x00,0x00
+,0x02,0x04,0x04,0x04,0x04,0x00,0x00,0x08,0x00,0x00,0x0a,0x14,0x00,0x00,0x1a,0x00
+,0x1c,0x00,0x1e,0x20,0x00,0x00,0x04,0x41,0x06,0x0b,0x08,0xc2,0xff,0xe7,0x04,0x03
+,0x06,0x04,0x04,0x05,0x04,0x06,0x04,0x87,0x04,0x03,0x06,0x04,0x04,0x85,0x4e,0xa2
+,0x04,0xcf,0x04,0xcd,0xc7,0x06,0xa2,0x37,0x00,0x00,0xc7,0x06,0xa6,0x37,0x00,0x00
+,0x26,0xa1,0x20,0x00,0x25,0x7f,0xff,0xa3,0xf5,0x36,0x26,0xa1,0x22,0x00,0xa3,0xf7
+,0x36,0x26,0xa1,0x24,0x00,0xa3,0xf9,0x36,0xe8,0x3b,0x19,0x8b,0xf0,0x26,0x8b,0x0e
+,0x0e,0x00,0x2b,0xc8,0x83,0xe9,0x0e,0xb8,0x01,0x80,0x83,0xf9,0x04,0x7c,0x51,0x26
+,0x8a,0x54,0x28,0x88,0x16,0x1c,0x37,0x40,0x26,0x8b,0x6c,0x26,0x86,0xcd,0x3b,0xcd
+,0x86,0xcd,0x89,0x0e,0xa4,0x37,0x75,0x38,0x40,0x32,0xff,0x26,0x8a,0x5c,0x29,0x80
+,0xfb,0x15,0x77,0x25,0x80,0xfb,0x0a,0x74,0x20,0x80,0xfb,0x01,0x74,0x1b,0xb8,0x04
+,0x80,0x2e,0x3a,0x97,0x02,0x2e,0x74,0x07,0x2e,0x3a,0x97,0x18,0x2e,0x75,0x11,0x33
+,0xc0,0x80,0xfb,0x09,0x75,0x4f,0x8b,0xf3,0xc3,0x26,0xc7,0x06,0x04,0x00,0xff,0xff
+,0x50,0x52,0xa1,0xa4,0x37,0x86,0xc4,0x26,0x3b,0x06,0x26,0x00,0x7c,0x32,0x26,0x81
+,0x3e,0x26,0x00,0x00,0x04,0x7e,0x29,0x8d,0x74,0x2a,0x26,0x8b,0x14,0x22,0xd2,0x74
+,0x1f,0x80,0xe6,0xbf,0x80,0xfe,0x09,0x75,0x17,0xc7,0x06,0xa2,0x37,0x01,0x00,0x80
+,0xfa,0x04,0x75,0x0c,0x26,0x8b,0x44,0x02,0xa3,0x03,0x37,0x86,0xc4,0xa3,0xd0,0x34
+,0x5a,0x58,0xe9,0xb1,0xff,0xbd,0x72,0x37,0x2e,0x8a,0x87,0x2e,0x2e,0x22,0xc0,0x74
+,0x16,0x05,0x44,0x2e,0x8b,0xf8,0x2e,0x8b,0x05,0x3e,0x89,0x46,0x00,0x83,0xc5,0x02
+,0x83,0xc7,0x02,0x22,0xe4,0x7d,0xef,0x8d,0x74,0x2a,0x83,0xe9,0x04,0x75,0x03,0xe9
+,0xa1,0x00,0x26,0x8b,0x14,0x22,0xd2,0x75,0x03,0xe9,0x7c,0x00,0xc7,0x06,0xa6,0x37
+,0x01,0x00,0xbf,0x72,0x37,0x8b,0x05,0x83,0xc7,0x02,0x80,0xe6,0xbf,0x80,0xe4,0x3f
+,0x80,0xfe,0x09,0x75,0x22,0x80,0xfa,0x04,0x75,0x5e,0xc7,0x06,0xa2,0x37,0x01,0x00
+,0x26,0x8b,0x44,0x02,0xa3,0x03,0x37,0x86,0xc4,0xa3,0xd0,0x34,0x86,0xc4,0xc7,0x06
+,0xa6,0x37,0x00,0x00,0xe9,0x47,0x00,0x3b,0xfd,0x7e,0x15,0x26,0x8b,0x04,0xa8,0x40
+,0x74,0x06,0xb8,0x07,0x80,0xe9,0x38,0xff,0x32,0xc0,0x26,0x8b,0x04,0xe9,0x2e,0x00
+,0x3a,0xf4,0x75,0xb1,0xc7,0x45,0xfe,0x00,0x00,0x80,0xfe,0x22,0x75,0x0d,0x3a,0xd0
+,0x77,0x16,0xc7,0x06,0xa6,0x37,0x00,0x00,0xe9,0x13,0x00,0x3a,0xd0,0x75,0x09,0xc7
+,0x06,0xa6,0x37,0x00,0x00,0xe9,0x06,0x00,0xb8,0x05,0x80,0xe9,0x02,0xff,0x32,0xf6
+,0x03,0xf2,0x2b,0xca,0xb8,0x05,0x80,0x23,0xc9,0x76,0x03,0xe9,0x64,0xff,0x74,0x03
+,0xe9,0xed,0xfe,0x33,0xc0,0xbf,0x72,0x37,0x8b,0x15,0x47,0x47,0x3b,0xfd,0x7f,0x1b
+,0xf6,0xc6,0x80,0x74,0x16,0xf7,0x06,0xa6,0x37,0x01,0x00,0x74,0x06,0xb8,0x08,0x80
+,0xe9,0xc3,0xfe,0xf6,0xc6,0x40,0x74,0xe0,0xb8,0x07,0x80,0xe9,0xb8,0xfe,0x7d,0x42
+,0xa3,0x45,0x44,0x29,0x44,0x29,0xb7,0x28,0xe2,0x28,0xee,0x2b,0xf2,0x28,0xf5,0x28
+,0x01,0x29,0xac,0x2a,0x44,0x29,0x44,0x29,0x44,0x29,0x44,0x29,0x44,0x29,0x00,0x00
+,0x73,0x36,0x00,0x00,0x03,0x36,0xc5,0x35,0x83,0x35,0x45,0x35,0x07,0x35,0xd2,0x34
+,0x45,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0xa6,0x38,0x00,0x00,0xe0,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0xf2,0x33,0x00,0x00,0xa6,0x33,0x60,0x33,0xfd,0x32,0xbc,0x32,0x77,0x32,0x3c,0x32
+,0xfb,0x31,0x6a,0x31,0x0a,0x31,0xe0,0xe0,0x10,0x10,0x10,0xe0,0xe0,0xe0,0xe0,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0
+,0xe0,0x33,0xff,0x26,0xf6,0x06,0x1a,0x00,0x80,0x74,0x1b,0x26,0x80,0x26,0x1a,0x00
+,0x7f,0x26,0x8b,0x3e,0x26,0x00,0x83,0xe7,0x1f,0x74,0x0b,0x26,0x80,0x0e,0x20,0x00
+,0x80,0x26,0x01,0x3e,0x0e,0x00,0xc3,0x60,0x2e,0x8b,0x84,0xa6,0x30,0x26,0xa3,0x18
+,0x00,0xd1,0xe6,0x2e,0xff,0x94,0x50,0x30,0x61,0xc3,0x26,0xc7,0x06,0x04,0x00,0xc4
+,0x2a,0x26,0xc7,0x06,0x0e,0x00,0x16,0x00,0x26,0xc7,0x06,0x06,0x00,0x06,0x00,0x26
+,0xc6,0x06,0x19,0x00,0x00,0xe8,0xbf,0x05,0xe8,0x98,0x05,0x26,0xc7,0x06,0x26,0x00
+,0x00,0x08,0x26,0xc6,0x06,0x28,0x00,0x40,0x26,0xc6,0x06,0x29,0x00,0x2a,0xbf,0x2a
+,0x00,0x26,0xc6,0x05,0x04,0x26,0xc6,0x45,0x01,0x2a,0xa1,0x93,0x37,0x33,0xdb,0xa9
+,0x40,0x00,0x75,0x02,0xb3,0x01,0xa9,0x00,0x10,0x74,0x02,0xb7,0x88,0xa9,0x00,0x08
+,0x74,0x03,0x80,0xcf,0x44,0x26,0x89,0x5d,0x02,0xc3,0x83,0x0e,0xc2,0x34,0x20,0x26
+,0xc7,0x06,0x04,0x00,0x6b,0x2b,0x26,0xc7,0x06,0x0e,0x00,0x30,0x00,0x26,0xc7,0x06
+,0x06,0x00,0x0a,0x00,0x26,0xc7,0x06,0x0a,0x00,0x04,0x00,0x26,0xc6,0x06,0x19,0x00
+,0x00,0xe8,0x69,0x05,0xe8,0x2c,0x05,0x26,0xc7,0x06,0x26,0x00,0x00,0x22,0x26,0xc6
+,0x06,0x28,0x00,0x60,0x26,0xc6,0x06,0x29,0x00,0x29,0xbf,0x2a,0x00,0x26,0xc6,0x05
+,0x08,0x26,0xc6,0x45,0x01,0x2d,0x8d,0x7d,0x02,0xbe,0x54,0x37,0xb9,0x03,0x00,0xf3
+,0xa5,0x26,0xc6,0x05,0x08,0x26,0xc6,0x45,0x01,0x2e,0x8d,0x7d,0x02,0xbe,0x5a,0x37
+,0xb9,0x03,0x00,0xf3,0xa5,0xe8,0xd4,0x05,0xe8,0x64,0x05,0xb9,0x06,0x00,0xbe,0x54
+,0x37,0x8d,0x2e,0x2c,0x00,0x26,0x8b,0x46,0x00,0x29,0x04,0x83,0xc6,0x02,0x83,0xc5
+,0x02,0x83,0xf9,0x04,0x75,0x02,0x45,0x45,0xe2,0xeb,0xc3,0x26,0xc7,0x06,0x04,0x00
+,0xc4,0x2a,0x26,0xc7,0x06,0x0e,0x00,0x24,0x00,0x26,0xc7,0x06,0x06,0x00,0x06,0x00
+,0x26,0xc6,0x06,0x19,0x00,0x00,0xe8,0xe4,0x04,0xe8,0xa7,0x04,0x26,0xc7,0x06,0x26
+,0x00,0x00,0x16,0x26,0xc6,0x06,0x28,0x00,0x60,0x26,0xc6,0x06,0x29,0x00,0x28,0xbf
+,0x2a,0x00,0xe8,0x5b,0x06,0xe8,0x74,0x05,0xe8,0x04,0x05,0xc3,0x26,0xc7,0x06,0x04
+,0x00,0xc4,0x2a,0x26,0xc7,0x06,0x0e,0x00,0x1a,0x00,0x26,0xc7,0x06,0x06,0x00,0x06
+,0x00,0x26,0xc6,0x06,0x19,0x00,0x00,0xe8,0xa3,0x04,0xe8,0x66,0x04,0x26,0xc7,0x06
+,0x26,0x00,0x00,0x0c,0x26,0xc6,0x06,0x28,0x00,0x60,0x26,0xc6,0x06,0x29,0x00,0x27
+,0xbf,0x2a,0x00,0xe8,0x21,0x05,0xc3,0x26,0xc7,0x06,0x04,0x00,0xc4,0x2a,0x26,0xc7
+,0x06,0x0e,0x00,0x20,0x00,0x26,0xc7,0x06,0x06,0x00,0x0a,0x00,0x26,0xc7,0x06,0x0a
+,0x00,0x04,0x00,0x26,0xc6,0x06,0x19,0x00,0x00,0xe8,0x4b,0x04,0xe8,0x24,0x04,0x26
+,0xc7,0x06,0x26,0x00,0x00,0x12,0x26,0xc6,0x06,0x28,0x00,0x40,0x26,0xc6,0x06,0x29
+,0x00,0x26,0xbf,0x2a,0x00,0xe8,0xf4,0x04,0xe8,0x84,0x04,0xc3,0x26,0xc7,0x06,0x04
+,0x00,0xc4,0x2a,0x26,0xc7,0x06,0x0e,0x00,0x34,0x00,0x26,0xc7,0x06,0x06,0x00,0x06
+,0x00,0x26,0xc6,0x06,0x19,0x00,0x00,0xe8,0x0d,0x04,0xe8,0xe6,0x03,0x26,0xc7,0x06
+,0x26,0x00,0x00,0x26,0x26,0xc6,0x06,0x28,0x00,0x40,0x26,0xc6,0x06,0x29,0x00,0x25
+,0xbf,0x2a,0x00,0xe8,0xb6,0x04,0xe8,0x46,0x04,0xe8,0xfa,0x04,0xc3,0x26,0xc7,0x06
+,0x04,0x00,0xc4,0x2a,0x26,0xc7,0x06,0x0e,0x00,0x38,0x00,0xa1,0xa2,0x37,0x50,0x0b
+,0xc0,0x75,0x07,0x26,0xc7,0x06,0x0e,0x00,0x34,0x00,0x26,0xc7,0x06,0x06,0x00,0x06
+,0x00,0x26,0xc6,0x06,0x19,0x00,0x00,0xe8,0x99,0x03,0xe8,0xa4,0xfd,0x26,0xc7,0x45
+,0x26,0x00,0x2a,0x58,0x0b,0xc0,0x75,0x06,0x26,0xc7,0x45,0x26,0x00,0x26,0xa1,0x1c
+,0x37,0xc1,0xe0,0x04,0x26,0x88,0x45,0x28,0x26,0xc6,0x45,0x29,0x24,0x83,0xc7,0x2a
+,0xe8,0x29,0x04,0xe8,0xa0,0x04,0xe8,0x22,0x05,0xe8,0xf8,0x03,0xe8,0x09,0x04,0xc3
+,0x26,0xc7,0x06,0x04,0x00,0xc4,0x2a,0x26,0xc7,0x06,0x0e,0x00,0x32,0x00,0x26,0xc7
+,0x06,0x06,0x00,0x06,0x00,0x26,0xc6,0x06,0x19,0x00,0x00,0xe8,0x45,0x03,0xe8,0x50
+,0xfd,0x26,0xc7,0x45,0x26,0x00,0x24,0xa1,0x1c,0x37,0xc1,0xe0,0x04,0x26,0x88,0x45
+,0x28,0x26,0xc6,0x45,0x29,0x23,0x83,0xc7,0x2a,0xe8,0xe0,0x03,0xe8,0x6c,0x04,0xe8
+,0x8a,0x04,0xe8,0x9c,0x04,0xc3,0x26,0xc7,0x06,0x04,0x00,0xc4,0x2a,0x26,0xc7,0x06
+,0x0e,0x00,0x34,0x00,0x26,0xc7,0x06,0x06,0x00,0x06,0x00,0x26,0xc6,0x06,0x19,0x00
+,0x00,0xe8,0xff,0x02,0xe8,0x0a,0xfd,0x26,0xc7,0x45,0x26,0x00,0x26,0xa1,0x1c,0x37
+,0xc1,0xe0,0x04,0x26,0x88,0x45,0x28,0x26,0xc6,0x45,0x29,0x22,0x83,0xc7,0x2a,0xe8
+,0x9a,0x03,0xe8,0xc7,0x03,0xe8,0x57,0x03,0xe8,0xf8,0x03,0xe8,0x78,0x04,0xe8,0x8a
+,0x04,0xc3,0x26,0xc7,0x06,0x04,0x00,0x74,0x45,0x26,0xc7,0x06,0x0e,0x00,0x3e,0x00
+,0x26,0xc7,0x06,0x06,0x00,0x06,0x00,0x26,0xc7,0x06,0x0a,0x00,0x04,0x00,0x26,0xc6
+,0x06,0x19,0x00,0x00,0xe8,0xfc,0x02,0xe8,0xa9,0x02,0x83,0x3e,0x8d,0x37,0x03,0x75
+,0x01,0x90,0x26,0xc7,0x06,0x26,0x00,0x00,0x30,0x26,0xc6,0x06,0x28,0x00,0x50,0x26
+,0xc6,0x06,0x29,0x00,0x20,0xbf,0x2a,0x00,0xe8,0xd0,0x03,0xe8,0x01,0x03,0xe8,0xb5
+,0x03,0xe8,0x9f,0x03,0xc3,0x26,0xc7,0x06,0x04,0x00,0x61,0x43,0xb9,0xf0,0x00,0x83
+,0xe9,0x02,0x26,0x89,0x0e,0x0e,0x00,0x26,0xc7,0x06,0x06,0x00,0x02,0x00,0x26,0xc6
+,0x06,0x19,0x00,0x00,0x26,0xc7,0x06,0x1a,0x00,0x00,0x00,0x26,0xc7,0x06,0x1c,0x00
+,0x00,0x00,0x26,0xc7,0x06,0x1e,0x00,0x00,0x00,0xe8,0x47,0x02,0x83,0xe9,0x0e,0x86
+,0xcd,0x26,0x89,0x0e,0x26,0x00,0x86,0xcd,0x26,0xc6,0x06,0x28,0x00,0x00,0x26,0xc6
+,0x06,0x29,0x00,0x08,0xbf,0x2a,0x00,0x83,0xe9,0x04,0x26,0x89,0x0d,0x26,0xc6,0x45
+,0x01,0x26,0x8d,0x7d,0x02,0x83,0xe9,0x02,0xbb,0x01,0x00,0xb8,0x30,0x30,0x4b,0x75
+,0x17,0xbb,0x0a,0x00,0x8a,0xc4,0x26,0x88,0x05,0xb0,0x31,0x80,0xc4,0x01,0x80,0xfc
+,0x3a,0x75,0x0a,0xb4,0x61,0xe9,0x05,0x00,0x26,0x88,0x05,0x04,0x01,0x47,0x49,0x75
+,0xdd,0xc3,0x26,0xc7,0x06,0x04,0x00,0x04,0x45,0x26,0xc7,0x06,0x0e,0x00,0x12,0x00
+,0x26,0xc7,0x06,0x06,0x00,0x06,0x00,0x26,0xc6,0x06,0x19,0x00,0x01,0xe8,0xe5,0x01
+,0xe8,0xd0,0x01,0x26,0xc7,0x06,0x26,0x00,0x00,0x04,0x26,0xc6,0x06,0x28,0x00,0x00
+,0x26,0xc6,0x06,0x29,0x00,0x07,0xc3,0x26,0xc7,0x06,0x04,0x00,0xc4,0x2a,0x26,0xc7
+,0x06,0x0e,0x00,0x20,0x00,0x26,0xc7,0x06,0x06,0x00,0x06,0x00,0x26,0xc6,0x06,0x19
+,0x00,0x06,0xe8,0x04,0x02,0xe8,0x9b,0x01,0x26,0xc7,0x06,0x26,0x00,0x00,0x12,0x26
+,0xc6,0x06,0x28,0x00,0x00,0x26,0xc6,0x06,0x29,0x00,0x06,0xbf,0x2a,0x00,0xe8,0x6b
+,0x02,0xe8,0xfb,0x01,0xc3,0x26,0xc7,0x06,0x04,0x00,0xc4,0x2a,0x26,0xc7,0x06,0x0e
+,0x00,0x20,0x00,0x26,0xc7,0x06,0x06,0x00,0x06,0x00,0x26,0xc6,0x06,0x19,0x00,0x05
+,0xe8,0xc6,0x01,0xe8,0x5d,0x01,0x26,0xc7,0x06,0x26,0x00,0x00,0x12,0x26,0xc6,0x06
+,0x28,0x00,0x00,0x26,0xc6,0x06,0x29,0x00,0x05,0xbf,0x2a,0x00,0xe8,0x2d,0x02,0xe8
+,0xbd,0x01,0xc3,0xff,0x06,0x82,0x34,0x26,0xc7,0x06,0x04,0x00,0x3d,0x41,0x26,0xc7
+,0x06,0x0e,0x00,0x20,0x00,0x26,0xc7,0x06,0x06,0x00,0x0e,0x00,0x26,0xc6,0x06,0x19
+,0x00,0x04,0xe8,0x84,0x01,0xe8,0x1b,0x01,0x26,0xc7,0x06,0x26,0x00,0x00,0x12,0x26
+,0xc6,0x06,0x28,0x00,0x00,0x26,0xc6,0x06,0x29,0x00,0x04,0xbf,0x2a,0x00,0xe8,0xeb
+,0x01,0xe8,0x7b,0x01,0xc3,0x26,0xc7,0x06,0x04,0x00,0x67,0x42,0x26,0xc7,0x06,0x0e
+,0x00,0x20,0x00,0x26,0xc7,0x06,0x06,0x00,0x08,0x00,0x26,0xc6,0x06,0x19,0x00,0x03
+,0xe8,0x46,0x01,0xe8,0xdd,0x00,0x26,0xc7,0x06,0x26,0x00,0x00,0x12,0x26,0xc6,0x06
+,0x28,0x00,0x00,0x26,0xc6,0x06,0x29,0x00,0x03,0xbf,0x2a,0x00,0xe8,0xad,0x01,0xe8
+,0x3d,0x01,0xc3,0xff,0x06,0x84,0x34,0x26,0xc7,0x06,0x04,0x00,0x67,0x42,0x26,0xc7
+,0x06,0x0e,0x00,0x24,0x00,0x26,0xc7,0x06,0x06,0x00,0x08,0x00,0x26,0xc6,0x06,0x19
+,0x00,0x02,0xe8,0x04,0x01,0xe8,0x9b,0x00,0x26,0xc7,0x06,0x26,0x00,0x00,0x16,0x26
+,0xc6,0x06,0x28,0x00,0x00,0x26,0xc6,0x06,0x29,0x00,0x02,0xbf,0x2a,0x00,0x26,0xc6
+,0x05,0x04,0x26,0xc6,0x45,0x01,0x01,0xa1,0x0f,0x37,0x86,0xe0,0xf6,0x06,0x6f,0x37
+,0x01,0x75,0x0f,0x39,0x06,0xcc,0x34,0x74,0x09,0x8b,0xd8,0xb8,0x89,0x03,0xcd,0x39
+,0x8b,0xc3,0xa3,0xcc,0x34,0x26,0x89,0x45,0x02,0x8d,0x7d,0x04,0xe8,0x3d,0x01,0xe8
+,0xcd,0x00,0xc3,0x26,0xc7,0x06,0x04,0x00,0xc4,0x2a,0x26,0xc7,0x06,0x0e,0x00,0x1c
+,0x00,0xa1,0xa2,0x37,0x50,0x0b,0xc0,0x75,0x07,0x26,0xc7,0x06,0x0e,0x00,0x18,0x00
+,0x26,0xc7,0x06,0x06,0x00,0x06,0x00,0x26,0xc6,0x06,0x19,0x00,0x00,0xe8,0x23,0x00
+,0xe8,0x2e,0xfa,0x26,0xc7,0x45,0x26,0x00,0x0e,0x58,0x0b,0xc0,0x75,0x06,0x26,0xc7
+,0x45,0x26,0x00,0x0a,0x26,0xc6,0x45,0x29,0x00,0x83,0xc7,0x2a,0xe8,0xbd,0x00,0xe8
+,0xff,0x00,0xc3,0x56,0x57,0x51,0xb9,0x03,0x00,0xbe,0xd1,0x36,0xbf,0x20,0x00,0xf3
+,0xa5,0x59,0x5f,0x5e,0xc3,0x56,0x57,0x51,0xb9,0x03,0x00,0xbe,0xd1,0x36,0xbf,0x1a
+,0x00,0xf3,0xa5,0x59,0x5f,0x5e,0xc3,0x26,0xc7,0x06,0x1a,0x00,0xc0,0x00,0x26,0xc7
+,0x06,0x1c,0x00,0x00,0x00,0x26,0xc7,0x06,0x1e,0x00,0x00,0x10,0xc3,0x26,0xc7,0x06
+,0x1a,0x00,0xc0,0x00,0x26,0xc7,0x06,0x1c,0x00,0x00,0x00,0x26,0xc7,0x06,0x1e,0x00
+,0x00,0x08,0xc3,0x26,0xc7,0x06,0x1a,0x00,0xc0,0x00,0x26,0xc7,0x06,0x1c,0x00,0x00
+,0x00,0x26,0xc7,0x06,0x1e,0x00,0x00,0x02,0xc3,0x26,0xc7,0x06,0x1a,0x00,0xc0,0x00
+,0x26,0xc7,0x06,0x1c,0x00,0xff,0xff,0x26,0xc7,0x06,0x1e,0x00,0xff,0xff,0xc3,0x26
+,0xc6,0x05,0x08,0x26,0xc6,0x45,0x01,0x02,0x8d,0x7d,0x02,0xbe,0x05,0x37,0xb9,0x03
+,0x00,0xf3,0xa5,0xc3,0x26,0xc6,0x05,0x04,0x26,0xc6,0x45,0x01,0x06,0xa1,0x0d,0x37
+,0x26,0x89,0x45,0x02,0x8d,0x7d,0x04,0xc3,0x26,0xc6,0x05,0x04,0x26,0xc6,0x45,0x01
+,0x07,0xa1,0x0b,0x37,0x26,0x89,0x45,0x02,0x83,0xc7,0x04,0xc3,0xa1,0xa2,0x37,0x0b
+,0xc0,0x74,0x13,0x26,0xc6,0x05,0x04,0x26,0xc6,0x45,0x01,0x09,0xa1,0x03,0x37,0x26
+,0x89,0x45,0x02,0x83,0xc7,0x04,0xc3,0x26,0xc6,0x05,0x08,0x26,0xc6,0x45,0x01,0x02
+,0x8d,0x7d,0x02,0xbe,0x05,0x37,0xb9,0x03,0x00,0xf3,0xa5,0xc3,0x26,0xc6,0x05,0x06
+,0x26,0xc6,0x45,0x01,0x0b,0x8d,0x7d,0x02,0xbe,0xef,0x36,0xb9,0x02,0x00,0xf3,0xa5
+,0xc3,0x26,0xc6,0x05,0x06,0x26,0xc6,0x45,0x01,0x20,0xa1,0x68,0x37,0x26,0x89,0x45
+,0x02,0xa1,0x6a,0x37,0x26,0x88,0x65,0x05,0xc1,0xe0,0x04,0x26,0x88,0x45,0x04,0x83
+,0xc7,0x06,0xc3,0x26,0xc6,0x05,0x04,0x26,0xc6,0x45,0x01,0x21,0x26,0xc7,0x45,0x02
+,0x00,0x00,0x83,0xc7,0x04,0xc3,0x26,0xc6,0x05,0x14,0x26,0xc6,0x45,0x01,0x22,0x8d
+,0x7d,0x02,0xbe,0x1f,0x37,0xb9,0x09,0x00,0xf3,0xa5,0xc3,0x26,0xc6,0x05,0x0c,0x26
+,0xc6,0x45,0x01,0x23,0x8d,0x7d,0x02,0x1e,0x0e,0x1f,0x8d,0x36,0x40,0x54,0xb9,0x03
+,0x00,0xf3,0xa5,0x33,0xc0,0xb9,0x02,0x00,0xf3,0xab,0x1f,0xc3,0x26,0xc6,0x05,0x08
+,0x26,0xc6,0x45,0x01,0x28,0x8d,0x7d,0x02,0xbe,0xd1,0x36,0xb9,0x03,0x00,0xf3,0xa5
+,0xc3,0x26,0xc6,0x05,0x08,0x26,0xc6,0x45,0x01,0x29,0xa1,0xc2,0x34,0x86,0xe0,0x26
+,0x89,0x45,0x02,0xa1,0x9b,0x36,0x26,0x89,0x45,0x04,0x26,0x88,0x45,0x06,0x26,0x88
+,0x45,0x07,0x8d,0x7d,0x08,0xc3,0x26,0xc6,0x05,0x06,0x26,0xc6,0x45,0x01,0x2b,0x8d
+,0x7d,0x02,0xbe,0xbb,0x36,0xb9,0x02,0x00,0xf3,0xa5,0xc3,0x26,0xc6,0x05,0x06,0x26
+,0xc6,0x45,0x01,0x2c,0x8d,0x7d,0x02,0xbe,0xe5,0x36,0xb9,0x02,0x00,0xf3,0xa5,0xc3
+,0x26,0xc6,0x05,0x04,0x26,0xc6,0x45,0x01,0x30,0xa1,0x37,0x37,0x86,0xe0,0x26,0x89
+,0x45,0x02,0x8d,0x7d,0x04,0xc3,0x26,0xc7,0x06,0x0e,0x00,0x1e,0x00,0x26,0xc7,0x06
+,0x06,0x00,0x02,0x00,0x26,0xc6,0x06,0x19,0x00,0x00,0xe8,0x6c,0xfe,0xe8,0x03,0xfe
+,0x26,0xc7,0x06,0x26,0x00,0x00,0x10,0x26,0xc6,0x06,0x28,0x00,0x30,0x26,0xc6,0x06
+,0x29,0x00,0x11,0xbf,0x2a,0x00,0xe8,0x35,0x00,0xe8,0x45,0x00,0xe8,0x55,0x00,0xc3
+,0x26,0xc7,0x06,0x0e,0x00,0x12,0x00,0x26,0xc7,0x06,0x06,0x00,0x02,0x00,0x26,0xc6
+,0x06,0x19,0x00,0x00,0xe8,0x32,0xfe,0xe8,0xc9,0xfd,0x26,0xc7,0x06,0x26,0x00,0x00
+,0x04,0x26,0xc6,0x06,0x28,0x00,0x30,0x26,0xc6,0x06,0x29,0x00,0x13,0xc3,0x26,0xc6
+,0x05,0x04,0x26,0xc6,0x45,0x01,0x0c,0x26,0xc7,0x45,0x02,0x00,0x01,0x83,0xc7,0x04
+,0xc3,0x26,0xc6,0x05,0x04,0x26,0xc6,0x45,0x01,0x0e,0x26,0xc7,0x45,0x02,0x00,0x02
+,0x83,0xc7,0x04,0xc3,0x26,0xc6,0x05,0x04,0x26,0xc6,0x45,0x01,0x21,0x26,0xc7,0x45
+,0x02,0x00,0x00,0x83,0xc7,0x04,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0xb3,0x39,0xc9,0x39,0x83,0x3a,0xb3,0x39,0xb3,0x39,0xb3,0x39,0x1c,0x3a,0x1c,0x3a
+,0xa3,0xb6,0x34,0xa1,0xe9,0x36,0xa3,0x11,0x37,0xa3,0xd2,0x34,0xa1,0xeb,0x36,0xa3
+,0x13,0x37,0xa3,0xd4,0x34,0xa1,0xed,0x36,0xa3,0x15,0x37,0xa3,0xd6,0x34,0xa1,0x01
+,0x37,0xa3,0xce,0x34,0xa1,0xf7,0x36,0xa3,0x17,0x37,0xa3,0xdc,0x34,0xa1,0xf9,0x36
+,0xa3,0x19,0x37,0xa3,0xde,0x34,0xf7,0x06,0x9b,0x36,0x02,0x00,0x75,0x0c,0x33,0xc0
+,0xa0,0x9e,0x36,0x8b,0xf0,0x2e,0xff,0xa4,0x50,0x39,0xe9,0x0f,0x01,0xbe,0x07,0x00
+,0xe9,0x19,0xf1,0xf6,0x06,0x9d,0x36,0x80,0x74,0xf3,0xc6,0x06,0xa0,0x36,0x02,0xc6
+,0x06,0x6e,0x37,0x08,0xc6,0x06,0x70,0x37,0x02,0xb8,0x88,0x03,0xcd,0x39,0xf6,0x06
+,0x6f,0x37,0x01,0x75,0x4a,0xa1,0xd1,0x36,0x3a,0x06,0xe9,0x36,0x75,0x41,0x3a,0x26
+,0xea,0x36,0x75,0x3b,0xa1,0xd3,0x36,0x3a,0x06,0xeb,0x36,0x75,0x32,0x3a,0x26,0xec
+,0x36,0x75,0x2c,0xa1,0xd5,0x36,0x3a,0x06,0xed,0x36,0x75,0x23,0x3a,0x26,0xee,0x36
+,0x75,0x1d,0xc6,0x06,0x70,0x37,0x02,0xfe,0x0e,0x6e,0x37,0x75,0x0f,0xb8,0x88,0x03
+,0xcd,0x3a,0x83,0x0e,0x9b,0x36,0x12,0xc6,0x06,0xa0,0x36,0x0c,0xe9,0xa8,0xf0,0xa1
+,0x05,0x37,0x26,0x3b,0x06,0x20,0x00,0x75,0x40,0xa1,0x07,0x37,0x26,0x3b,0x06,0x22
+,0x00,0x75,0x36,0xa1,0x09,0x37,0x26,0x3b,0x06,0x24,0x00,0x75,0x2c,0xa0,0x9e,0x36
+,0x3c,0x02,0x75,0x08,0x26,0xf6,0x06,0x18,0x00,0x08,0x75,0x47,0xc6,0x06,0x6e,0x37
+,0x08,0xfe,0x0e,0x70,0x37,0x75,0x1c,0xc6,0x06,0x70,0x37,0x02,0xe5,0x02,0x0d,0x01
+,0x04,0x25,0xef,0xff,0xe7,0x02,0xe9,0x5e,0xf0,0xc6,0x06,0x70,0x37,0x02,0xc6,0x06
+,0x6e,0x37,0x08,0xe5,0x02,0x25,0xff,0xfb,0x0d,0x01,0x00,0x25,0xef,0xff,0xe7,0x02
+,0xe9,0x44,0xf0,0xf7,0x06,0x9b,0x36,0x00,0x01,0x74,0x25,0x26,0xf6,0x06,0x18,0x00
+,0x08,0x75,0xed,0x81,0x26,0x9b,0x36,0x7f,0xff,0xb8,0x89,0x03,0xcd,0x3a,0xb8,0x84
+,0x03,0xcd,0x3a,0xc6,0x06,0xa0,0x36,0x06,0x83,0x26,0xc2,0x34,0xaf,0xe9,0x17,0xf0
+,0xa1,0x01,0x37,0x3a,0x26,0x0f,0x37,0x7f,0xc7,0xe9,0xf7,0xfe,0x83,0x26,0x9b,0x36
+,0xec,0xe8,0x2a,0x0d,0x81,0x0e,0x9b,0x36,0x80,0x00,0xbb,0xff,0x7f,0xcd,0x53,0xc6
+,0x06,0xa0,0x36,0x02,0xe9,0xf0,0xef,0x83,0x0e,0x9b,0x36,0x11,0xc6,0x06,0xa0,0x36
+,0x0c,0xe9,0xf9,0xef,0x44,0x3b,0x2c,0x3b,0xc7,0x2a,0x6b,0x3b,0x44,0x3b,0xc7,0x2a
+,0xc7,0x2a,0xc7,0x2a,0xa3,0xb6,0x34,0x81,0x0e,0xc2,0x34,0x00,0x20,0xf7,0x06,0x41
+,0x37,0x01,0x00,0x74,0x1b,0x8c,0xc3,0xc7,0x06,0x41,0x37,0x00,0x00,0xb8,0x7f,0x03
+,0xcd,0x3a,0x33,0xc0,0x8e,0xc0,0xbf,0x54,0x37,0xb9,0x06,0x00,0xf3,0xab,0x8e,0xc3
+,0x33,0xc0,0xa0,0x9e,0x36,0x8b,0xf0,0x2e,0xff,0xa4,0xe4,0x3a,0xf7,0x06,0x9b,0x36
+,0x00,0x01,0x75,0x21,0x83,0x26,0xc2,0x34,0xbf,0xa1,0xa9,0x36,0xe7,0x00,0xa1,0x9b
+,0x36,0xe9,0x09,0x00,0xa1,0x9b,0x36,0x81,0x26,0x9b,0x36,0xff,0xdf,0xa9,0x00,0x20
+,0x75,0x06,0xe9,0x6e,0x00,0xe9,0x6f,0xef,0x83,0x0e,0x99,0x36,0x04,0xc7,0x06,0x37
+,0x37,0x01,0x00,0xc6,0x06,0xca,0x34,0x01,0xe9,0x58,0x00,0x83,0x0e,0x9b,0x36,0x40
+,0xe8,0x58,0x00,0xa1,0x05,0x37,0x3b,0x06,0xe9,0x36,0x75,0x37,0xa1,0x07,0x37,0x3b
+,0x06,0xeb,0x36,0x75,0x2e,0xa1,0x09,0x37,0x3b,0x06,0xed,0x36,0x75,0x25,0xfe,0x0e
+,0x71,0x37,0x75,0x1c,0xb8,0x87,0x03,0xcd,0x3a,0x83,0x0e,0x99,0x36,0x10,0xa1,0x50
+,0x37,0xc7,0x06,0x50,0x37,0x00,0x00,0x09,0x06,0x99,0x36,0xc6,0x06,0xa0,0x36,0x08
+,0xe9,0x14,0xef,0x83,0x0e,0x99,0x36,0x04,0xc7,0x06,0x37,0x37,0x03,0x00,0xc6,0x06
+,0xca,0x34,0x03,0xc6,0x06,0xa0,0x36,0x0a,0xe9,0xfc,0xee,0xa1,0xd1,0x36,0x26,0x3b
+,0x06,0x20,0x00,0x75,0x15,0xa1,0xd3,0x36,0x26,0x3b,0x06,0x22,0x00,0x75,0x12,0xa1
+,0xd5,0x36,0x26,0x3b,0x06,0x24,0x00,0x75,0x0f,0xc3,0x8d,0x36,0x20,0x00,0xe9,0x0b
+,0x00,0x8d,0x36,0x22,0x00,0xe9,0x04,0x00,0x8d,0x36,0x24,0x00,0x83,0xc4,0x02,0xf7
+,0x06,0xe6,0x34,0x01,0x00,0x74,0x15,0x26,0x3a,0x04,0x77,0x08,0x72,0x0e,0x26,0x3a
+,0x64,0x01,0x72,0x08,0xc6,0x06,0xa0,0x36,0x06,0xe9,0xab,0xee,0xe8,0x7c,0x0a,0x8c
+,0xc0,0x3d,0xff,0xff,0x74,0x1b,0x26,0xc6,0x06,0x18,0x00,0x10,0x26,0xc7,0x06,0x04
+,0x00,0x49,0x3c,0x26,0xc7,0x06,0x06,0x00,0x0c,0x00,0xcd,0x50,0xb9,0x4e,0x00,0xe2
+,0xfe,0xc6,0x06,0xa0,0x36,0x0a,0xe9,0x94,0xee,0xe9,0x7b,0xee,0x8f,0x3c,0x06,0x3d
+,0x06,0x3d,0x06,0x3d,0xd2,0x3c,0xea,0x3c,0x06,0x3d,0x06,0x3d,0xa3,0xb6,0x34,0x81
+,0x26,0xc2,0x34,0xaf,0xdf,0xc7,0x06,0x4c,0x37,0x00,0x00,0xb8,0x8a,0x03,0xcd,0x3a
+,0x80,0x3e,0x9d,0x36,0x04,0x75,0x0c,0x80,0x3e,0x9e,0x36,0x06,0x74,0x05,0xc6,0x06
+,0x9f,0x36,0x06,0x33,0xc0,0xa0,0x9e,0x36,0x8b,0xf0,0x2e,0xff,0xa4,0x4c,0x3c,0xf7
+,0x06,0x9b,0x36,0x00,0x20,0x75,0x0e,0x81,0x26,0x9b,0x36,0xff,0xbf,0xb8,0x8b,0x03
+,0xcd,0x3a,0xe9,0x54,0x00,0xf7,0x06,0x9b,0x36,0x00,0x01,0x74,0x03,0xe9,0x17,0xee
+,0xc7,0x06,0x37,0x37,0x02,0x00,0xc6,0x06,0xca,0x34,0x02,0x83,0x0e,0x99,0x36,0x04
+,0x83,0x0e,0x50,0x37,0x04,0xf6,0x06,0x9d,0x36,0x80,0x75,0x2a,0xe8,0x1f,0x0b,0xe9
+,0x27,0x00,0xf7,0x06,0x9b,0x36,0x00,0x01,0x75,0xd3,0xc7,0x06,0x37,0x37,0x02,0x00
+,0xc6,0x06,0xca,0x34,0x02,0x83,0x0e,0x99,0x36,0x04,0xc6,0x06,0xa0,0x36,0x00,0xf6
+,0x06,0x9d,0x36,0x80,0x74,0x03,0xe8,0xde,0x0a,0x81,0x26,0x9b,0x36,0x7c,0xff,0xbb
+,0xff,0xff,0xcd,0x53,0xcd,0x54,0xe9,0xbe,0xed,0xa3,0xb6,0x34,0xe8,0xad,0x01,0xb8
+,0x86,0x03,0xcd,0x39,0xc7,0x06,0x4c,0x37,0x00,0x00,0x81,0x26,0xc2,0x34,0xaf,0xdf
+,0xf6,0x06,0x9d,0x36,0x80,0x74,0x34,0xf7,0x06,0x9b,0x36,0x00,0x20,0x74,0x56,0xf7
+,0x06,0x9b,0x36,0x00,0x01,0x74,0x27,0xe8,0x35,0x01,0x72,0x1c,0xbe,0x00,0x40,0x85
+,0x36,0xc2,0x34,0x75,0x08,0x09,0x36,0xc2,0x34,0xff,0x06,0x92,0x34,0xe8,0x8b,0x01
+,0x73,0x06,0x81,0x0e,0x99,0x36,0x80,0x00,0xe9,0x6c,0xed,0xe9,0xb5,0x00,0xc7,0x06
+,0x37,0x37,0x02,0x00,0xc6,0x06,0xca,0x34,0x02,0x83,0x0e,0x99,0x36,0x04,0x83,0x0e
+,0x50,0x37,0x04,0x80,0x3e,0x9e,0x36,0x08,0x74,0x03,0xe8,0x5a,0x0a,0xe8,0xef,0x00
+,0x72,0xd6,0xe9,0xc8,0xff,0x80,0x3e,0x9e,0x36,0x0a,0x75,0x12,0xc6,0x06,0xa0,0x36
+,0x00,0xf7,0x06,0x9b,0x36,0x08,0x00,0x74,0x02,0xcd,0x54,0xe8,0x39,0x0a,0x81,0x26
+,0x9b,0x36,0xff,0xbf,0xe8,0xc8,0x00,0x72,0xaf,0xb8,0x8b,0x03,0xcd,0x39,0xe9,0x9c
+,0xff,0xf6,0x06,0x9e,0x36,0xff,0x75,0x58,0xa3,0xb6,0x34,0xe8,0xfe,0x00,0x81,0x26
+,0xc2,0x34,0xff,0xbf,0xf6,0x06,0x9d,0x36,0x80,0x74,0x48,0xf7,0x06,0x9b,0x36,0x00
+,0x20,0x74,0x22,0xf7,0x06,0x9b,0x36,0x00,0x40,0x75,0x08,0xe8,0x91,0x00,0x72,0x30
+,0xe9,0x22,0x00,0x26,0xa1,0x0c,0x00,0xa9,0x60,0x00,0x75,0x24,0x81,0x0e,0x66,0x37
+,0x00,0x08,0xe9,0xd2,0xec,0xc7,0x06,0x4c,0x37,0x00,0x00,0xe8,0x71,0x00,0x72,0x10
+,0xb8,0x8b,0x03,0xcd,0x39,0xe8,0xd3,0x00,0x73,0x06,0x81,0x0e,0x99,0x36,0x80,0x00
+,0xe9,0xb4,0xec,0x80,0x3e,0x9d,0x36,0x04,0x75,0x0c,0x80,0x3e,0x9e,0x36,0x06,0x74
+,0x46,0xc6,0x06,0x9f,0x36,0x06,0xf7,0x06,0x9b,0x36,0x00,0x01,0x74,0x0c,0x80,0x3e
+,0x9d,0x36,0x08,0x75,0x05,0xc6,0x06,0x9f,0x36,0x0a,0xe8,0x32,0x00,0x72,0xd1,0xe8
+,0x99,0x00,0x80,0x3e,0x9d,0x36,0x08,0x75,0x13,0x81,0x0e,0x99,0x36,0x80,0x00,0xf7
+,0x06,0x9b,0x36,0x00,0x20,0x75,0x08,0xb8,0x8b,0x03,0xcd,0x39,0xe9,0x68,0xec,0xc6
+,0x06,0x9f,0x36,0x0a,0xe9,0x60,0xec,0xb8,0x86,0x03,0xcd,0x3a,0xe9,0x58,0xec,0x26
+,0xa1,0x0c,0x00,0xa9,0x60,0x00,0x74,0x08,0x81,0x26,0xc2,0x34,0xff,0xbf,0xf9,0xc3
+,0xf7,0x06,0x9b,0x36,0x00,0x40,0x74,0x13,0x81,0x0e,0x66,0x37,0x00,0x08,0xe8,0x4a
+,0x00,0x73,0x06,0x81,0x0e,0x99,0x36,0x80,0x00,0xf9,0xc3,0x81,0x0e,0x9b,0x36,0x00
+,0x40,0x80,0x26,0x6f,0x37,0xfe,0x81,0x26,0x9b,0x36,0x7f,0xff,0xc6,0x06,0xa0,0x36
+,0x00,0xf8,0xc3,0x81,0x0e,0x99,0x36,0x00,0x01,0xe9,0x21,0xec,0x26,0xa1,0x20,0x00
+,0xa3,0xfb,0x36,0xa3,0xaa,0x34,0x26,0xa1,0x22,0x00,0xa3,0xfd,0x36,0xa3,0xac,0x34
+,0x26,0xa1,0x24,0x00,0xa3,0xff,0x36,0xa3,0xae,0x34,0xc3,0xa1,0x05,0x37,0x26,0x3b
+,0x06,0x20,0x00,0x75,0x19,0xa1,0x07,0x37,0x26,0x3b,0x06,0x22,0x00,0x75,0x0f,0xa1
+,0x09,0x37,0x26,0x3b,0x06,0x24,0x00,0x75,0x05,0xe8,0x02,0x00,0xf8,0xc3,0x51,0x1e
+,0x06,0x8b,0xc7,0x8d,0x36,0x20,0x00,0xbf,0x05,0x37,0xb9,0x03,0x00,0x1e,0x06,0x1f
+,0x07,0xf3,0xa5,0x8b,0xf8,0x8d,0x36,0x20,0x00,0xbf,0xa0,0x34,0xb9,0x03,0x00,0xf3
+,0xa5,0x07,0x1f,0x59,0x8b,0xf8,0xa1,0x07,0x37,0xa3,0xa6,0x34,0xa1,0x09,0x37,0xa3
+,0xa8,0x34,0xf9,0xc3,0xc6,0x06,0xb6,0x34,0x01,0xe9,0x8b,0xeb,0xe8,0x87,0x08,0x8b
+,0xf0,0x05,0x12,0x00,0x26,0x29,0x06,0x0e,0x00,0x26,0x8b,0x44,0x2a,0x26,0x3a,0x06
+,0x0e,0x00,0x75,0x5b,0x26,0x83,0x2e,0x0e,0x00,0x02,0x80,0xfc,0x27,0x75,0x50,0x26
+,0x8b,0x44,0x2c,0xa9,0xff,0xff,0x75,0x47,0x8b,0xfe,0x33,0xc0,0x26,0xf6,0x45,0x3c
+,0x80,0x74,0x06,0x26,0x8a,0x45,0x3a,0x24,0x1f,0x03,0xf8,0x26,0x80,0x7d,0x45,0x09
+,0x75,0x2d,0x8c,0xc2,0x8e,0x06,0x38,0x34,0x8e,0xda,0x8b,0x0e,0x0e,0x00,0x26,0x89
+,0x0e,0x0e,0x00,0x8d,0x74,0x2c,0xbf,0x18,0x00,0xf3,0xa4,0x33,0xc0,0x8e,0xd8,0x26
+,0xc7,0x06,0x04,0x00,0xb5,0x3f,0x26,0xc7,0x06,0x06,0x00,0x06,0x00,0xcd,0x50,0xb8
+,0x06,0x80,0xe9,0xef,0xe9,0x26,0xa1,0x0c,0x00,0xa3,0x93,0x37,0x83,0x0e,0x99,0x36
+,0x01,0xe9,0x00,0xeb,0x26,0x80,0x3e,0x1c,0x00,0xff,0x75,0x2f,0x26,0x80,0x3e,0x1e
+,0x00,0xff,0x75,0x27,0x26,0xf7,0x06,0x0c,0x00,0x40,0x00,0x75,0x1b,0xa1,0xd1,0x36
+,0x26,0xa3,0x1a,0x00,0xa1,0xd3,0x36,0x26,0xa3,0x1c,0x00,0xa1,0xd5,0x36,0x26,0xa3
+,0x1e,0x00,0xb8,0x0a,0x80,0xe8,0x36,0x07,0xe9,0xe2,0xea,0xff,0x06,0x90,0x34,0xbe
+,0x0a,0x00,0xc6,0x06,0xb6,0x34,0x01,0xf6,0x06,0x9d,0x36,0x80,0x75,0x05,0x83,0x0e
+,0xc2,0x34,0x01,0xe9,0xb6,0xea,0x80,0x3e,0x9d,0x36,0x0a,0x75,0x0f,0x26,0xa1,0x0c
+,0x00,0x25,0x07,0x00,0x3d,0x04,0x00,0x75,0x03,0xe8,0x79,0x00,0xa1,0xf3,0x36,0x86
+,0xe0,0xe7,0x1e,0xa3,0xe3,0x36,0x81,0x26,0x0b,0x37,0x00,0x03,0x81,0x26,0x0d,0x37
+,0x7b,0x7f,0x83,0x0e,0x0d,0x37,0x48,0xe8,0x1e,0x00,0x26,0xa1,0x0c,0x00,0x25,0x07
+,0x00,0x3d,0x04,0x00,0x74,0x09,0x26,0xf7,0x06,0x0c,0x00,0x20,0x00,0x75,0x06,0xb8
+,0x01,0x00,0xe9,0x3f,0xe9,0xe9,0x5f,0xea,0xc7,0x06,0x41,0x37,0x00,0x00,0xb8,0x7f
+,0x03,0xcd,0x3a,0xa1,0x1d,0x37,0xa3,0xc4,0x34,0x86,0xe0,0x68,0x7f,0x03,0x1f,0xa3
+,0x06,0x00,0x33,0xc0,0x8e,0xd8,0xa1,0x0b,0x37,0xa3,0xb2,0x34,0xa1,0x0d,0x37,0xa3
+,0xb4,0x34,0xa1,0xf3,0x36,0xa3,0xc8,0x34,0xa1,0xef,0x36,0xa3,0x9c,0x34,0xa1,0xf1
+,0x36,0xa3,0x9e,0x34,0xc3,0x80,0x0e,0x9d,0x36,0x80,0xbe,0x00,0x00,0xe8,0xb4,0x07
+,0xb8,0x7b,0x03,0xcd,0x3a,0xb8,0x7c,0x03,0xcd,0x39,0xc7,0x06,0x33,0x37,0x02,0x00
+,0xa1,0xe5,0x36,0xe7,0x2e,0xa1,0xe7,0x36,0xe7,0x3e,0xb8,0x82,0x03,0xcd,0x3a,0xf7
+,0x06,0x9b,0x36,0x00,0x20,0x75,0x03,0xe8,0xfd,0x06,0xa1,0xd3,0x36,0xa3,0xef,0x36
+,0xa3,0x9c,0x34,0xa1,0xd5,0x36,0xa3,0xf1,0x36,0xa3,0x9e,0x34,0xc3,0xf6,0x06,0x9d
+,0x36,0x80,0x74,0x31,0xbe,0x22,0x00,0xe9,0x17,0x00,0xf6,0x06,0x9d,0x36,0x80,0x74
+,0x24,0xbe,0x23,0x00,0xe9,0x0a,0x00,0xf6,0x06,0x9d,0x36,0x80,0x74,0x17,0xbe,0x24
+,0x00,0x56,0xe8,0xa8,0x05,0x8c,0xc0,0x3d,0xff,0xff,0x5e,0x74,0x05,0xe8,0xd7,0xef
+,0xcd,0x50,0xe9,0x1f,0xe8,0xe9,0x9f,0xe9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0xb8,0x84,0x03,0xcd,0x3a,0xb8,0x8a,0x03,0xcd,0x39,0xe9,0xf7,0x00,0x80,0x3e,0xa0
+,0x36,0x08,0x75,0x2e,0xa9,0xd0,0x07,0x75,0x2c,0xa1,0xb1,0x36,0x0d,0x00,0x04,0xe7
+,0x08,0xe5,0x00,0x25,0xff,0x73,0xe7,0x00,0xb8,0x8a,0x03,0xcd,0x3a,0xe8,0xc3,0x06
+,0x33,0xc0,0xe7,0x0e,0xe5,0x0a,0x25,0xc3,0x17,0xe7,0x0a,0xcd,0x54,0xc6,0x06,0xa0
+,0x36,0x00,0xe9,0x68,0xe9,0xbe,0x04,0x00,0xe9,0x3f,0xe9,0x83,0x26,0x9b,0x36,0xbf
+,0xc6,0x06,0x71,0x37,0x03,0xb8,0x86,0x03,0xcd,0x3a,0xb8,0x88,0x03,0xcd,0x3a,0xb8
+,0x83,0x03,0xcd,0x3a,0xb8,0x87,0x03,0xcd,0x39,0x81,0x0e,0xc2,0x34,0x00,0x20,0xe9
+,0x92,0x00,0xe8,0x49,0x06,0xb8,0x87,0x03,0xcd,0x39,0xbb,0xff,0x7f,0xcd,0x53,0xb8
+,0x84,0x03,0xcd,0x3a,0xb8,0x88,0x03,0xcd,0x3a,0xb8,0x8b,0x03,0xcd,0x3a,0xb8,0x83
+,0x03,0xcd,0x3a,0xb8,0x86,0x03,0xcd,0x3a,0xb8,0x85,0x03,0xcd,0x3a,0xc3,0xe5,0x00
+,0x25,0xff,0x53,0xe7,0x00,0x83,0x0e,0xc2,0x34,0x40,0x83,0x26,0xc2,0x34,0xef,0xe8
+,0x0c,0x06,0xbb,0xff,0x7f,0xcd,0x53,0xb8,0x8a,0x03,0xcd,0x3a,0xb8,0x85,0x03,0xcd
+,0x3a,0xb8,0x86,0x03,0xcd,0x3a,0xb8,0x83,0x03,0xcd,0x3a,0xb8,0x87,0x03,0xcd,0x3a
+,0xb8,0x8b,0x03,0xcd,0x3a,0xb8,0x84,0x03,0xcd,0x3a,0xb8,0x89,0x03,0xcd,0x3a,0xc3
+,0x83,0x0e,0xc2,0x34,0x50,0xe8,0x18,0x04,0xe8,0xd3,0x05,0xf6,0x06,0x6f,0x37,0x01
+,0x75,0x12,0xb8,0x89,0x03,0xcd,0x39,0x83,0x3e,0x0f,0x37,0x00,0x75,0x06,0xc7,0x06
+,0x0f,0x37,0x04,0x00,0xa1,0x9d,0x36,0x80,0xfc,0x08,0x74,0x05,0xb8,0x84,0x03,0xcd
+,0x39,0xe5,0x02,0x0d,0x01,0x08,0x25,0xef,0xff,0xe7,0x02,0xa1,0x9d,0x36,0x86,0xe0
+,0x32,0xe4,0x8b,0xf0,0xd1,0xee,0x33,0xc0,0x0d,0x20,0x00,0x09,0x06,0xad,0x36,0xa1
+,0xad,0x36,0xe7,0x04,0xe9,0x53,0xe8,0xe9,0x5a,0xe8,0x33,0xc0,0xa0,0x1b,0x37,0xd1
+,0xe0,0x3a,0x06,0xa0,0x36,0x75,0x03,0xe9,0xba,0xff,0xe9,0x60,0xe8,0xc7,0x06,0x41
+,0x37,0x00,0x00,0xe8,0xc1,0xe1,0xe8,0x6a,0x06,0x33,0xc0,0x0d,0x41,0x00,0xe7,0x56
+,0xa1,0xb1,0x36,0x0d,0x00,0x10,0xe7,0x08,0xe5,0x02,0x25,0xf9,0xff,0x0d,0x03,0x00
+,0xe7,0x02,0xa1,0xb3,0x36,0xe7,0x0a,0xa1,0xaf,0x36,0xe7,0x06,0xa1,0xad,0x36,0xe7
+,0x04,0xe8,0x7c,0x03,0xe8,0x9f,0x03,0xc7,0x06,0x1d,0x37,0x00,0xc8,0xc7,0x06,0x0b
+,0x37,0x00,0x03,0xc7,0x06,0x0d,0x37,0x7b,0x7f,0x33,0xc0,0xa3,0x99,0x36,0xa3,0x9b
+,0x36,0xa3,0x9d,0x36,0xa3,0x9f,0x36,0xa3,0x4c,0x37,0xa3,0xf3,0x36,0xa3,0xef,0x36
+,0xa3,0xf1,0x36,0xe8,0x82,0xfd,0xc6,0x06,0x9f,0x36,0x02,0xe9,0xef,0xe7,0xe5,0x02
+,0x0d,0x01,0x88,0x25,0xef,0xff,0x0d,0x00,0x40,0x0d,0x00,0x04,0xe7,0x02,0xe8,0xf2
+,0x05,0xe5,0x0a,0x0d,0x40,0x00,0xe7,0x0a,0x33,0xc0,0xa3,0x81,0x37,0xa3,0x85,0x37
+,0xa3,0x83,0x37,0xa3,0x87,0x37,0xa3,0x89,0x37,0xe5,0x00,0x0d,0x00,0x84,0xe7,0x00
+,0xb8,0x8c,0x03,0xcd,0x39,0xb8,0x80,0x00,0xcd,0x35,0xc7,0x06,0xaa,0x02,0xff,0xff
+,0xe5,0x00,0x25,0xff,0x7b,0xe7,0x00,0x81,0x0e,0x9a,0x37,0x80,0x00,0xb8,0x7e,0x03
+,0xcd,0x39,0x33,0xc0,0xe7,0x0e,0xbe,0x08,0x00,0x8e,0x06,0x38,0x34,0xe8,0xa7,0xed
+,0x83,0x26,0xef,0x34,0xdf,0xff,0x06,0x81,0x37,0xcd,0x50,0x83,0x0e,0xef,0x34,0x20
+,0xc3,0xf7,0x06,0x9a,0x37,0x80,0x00,0x74,0x3d,0xa9,0xd0,0x07,0x74,0x10,0xa9,0x00
+,0x04,0x74,0x12,0x33,0xc0,0xe7,0x0e,0xff,0x06,0x87,0x37,0xe9,0xd2,0xff,0xff,0x06
+,0x85,0x37,0xe9,0xcb,0xff,0xff,0x06,0x83,0x37,0xe9,0xc4,0xff,0x83,0x26,0x9a,0x37
+,0x7f,0xa1,0x89,0x37,0x03,0x06,0x87,0x37,0x3d,0x05,0x00,0x7f,0x01,0xc3,0xbb,0xff
+,0x7f,0xcd,0x53,0xe9,0x00,0x00,0xe5,0x02,0x25,0xff,0xfb,0x25,0xef,0xff,0x0d,0x01
+,0x00,0xe7,0x02,0xa1,0x83,0x37,0x3b,0x06,0x46,0x37,0x7f,0x2a,0xa1,0x85,0x37,0x3b
+,0x06,0x48,0x37,0x7c,0x21,0xa1,0x89,0x37,0x03,0x06,0x87,0x37,0x3d,0x05,0x00,0x7f
+,0x15,0xc6,0x06,0x9f,0x36,0x04,0xe5,0x02,0x25,0xff,0xf7,0x0d,0x01,0x00,0x25,0xef
+,0xff,0xe7,0x02,0xe9,0xf7,0xe6,0xbe,0x01,0x00,0xf7,0x06,0x9b,0x36,0x03,0x00,0x74
+,0x0a,0x83,0x26,0x9b,0x36,0xfc,0x83,0x0e,0xc2,0x34,0x04,0xe9,0xd0,0xe6,0xb8,0x7b
+,0x03,0xcd,0x39,0xe5,0x02,0x0d,0x01,0x60,0x25,0xef,0xff,0xe7,0x02,0xc7,0x06,0xf1
+,0x34,0x20,0x03,0xb8,0x8e,0x03,0xcd,0x39,0xc3,0x81,0x26,0xc2,0x34,0x7f,0xff,0x80
+,0x0e,0x6f,0x37,0x01,0xf7,0x06,0x9b,0x36,0x03,0x00,0x74,0xd2,0xb8,0x7b,0x03,0xcd
+,0x3a,0xb8,0x7d,0x03,0xcd,0x39,0x83,0x26,0x9b,0x36,0xef,0x33,0xc0,0xb0,0x8a,0xa2
+,0x9f,0x36,0xa2,0x9d,0x36,0xc7,0x06,0x4c,0x37,0x01,0x00,0xc7,0x06,0x0f,0x37,0x04
+,0x00,0xf7,0x06,0x9b,0x36,0x40,0x00,0x75,0x06,0xc7,0x06,0x0f,0x37,0x03,0x00,0xb8
+,0x8d,0x03,0xcd,0x39,0xe8,0x00,0xd5,0xe5,0x02,0x0d,0x01,0x40,0x25,0xef,0xff,0x8b
+,0xd8,0xb8,0x7c,0x03,0xcd,0x39,0xc7,0x06,0x33,0x37,0x02,0x00,0x8b,0xc3,0x0d,0x00
+,0x20,0x25,0xf9,0xff,0x0b,0x06,0xe8,0x3a,0xe7,0x02,0xc3,0xff,0x0e,0xf1,0x34,0x75
+,0x01,0xc3,0xe5,0x4e,0xa9,0x01,0x00,0x75,0x12,0xe5,0x00,0xa9,0x00,0x04,0x75,0x05
+,0x0d,0x00,0x04,0xe7,0x00,0xb8,0x8e,0x03,0xcd,0x39,0xc3,0xe5,0x00,0xa9,0x00,0x04
+,0x74,0xf3,0x25,0xff,0xfb,0xe7,0x00,0xe9,0xeb,0xff,0xc6,0x06,0xa0,0x36,0x04,0x83
+,0x26,0x9b,0x36,0xfc,0x81,0x0e,0x9b,0x36,0x80,0x00,0xe9,0x10,0xe6,0xb8,0x8e,0x03
+,0xcd,0x3a,0xcd,0x54,0x81,0x0e,0xaf,0x36,0x00,0x18,0xa1,0xaf,0x36,0xe7,0x06,0xb8
+,0x7b,0x03,0xcd,0x39,0xa1,0xd3,0x36,0xa3,0x8f,0x37,0xa1,0xd5,0x36,0xa3,0x91,0x37
+,0xc7,0x06,0x8b,0x37,0x02,0x00,0xc7,0x06,0x8d,0x37,0x02,0x00,0x83,0x0e,0x99,0x36
+,0x40,0xe9,0xd9,0xe5,0x80,0x3e,0x9f,0x36,0x06,0x75,0x15,0xa9,0xd0,0x07,0x75,0xec
+,0x25,0x00,0x18,0x75,0x0e,0xff,0x0e,0x8b,0x37,0x75,0xe1,0xc6,0x06,0x9f,0x36,0x08
+,0xe9,0xba,0xe5,0xff,0x0e,0x8d,0x37,0x75,0xd3,0xbe,0x08,0x00,0xe9,0x9f,0xe5,0xb8
+,0x7b,0x03,0xcd,0x39,0xf7,0x06,0x9b,0x36,0x00,0x20,0x74,0x08,0xc6,0x06,0x9f,0x36
+,0x0a,0xe9,0x0d,0x00,0xf7,0x06,0x9b,0x36,0x00,0x40,0x74,0x0b,0xb8,0x8b,0x03,0xcd
+,0x39,0x81,0x0e,0x99,0x36,0x80,0x00,0xe9,0x83,0xe5,0xb8,0x7b,0x03,0xcd,0x39,0xc7
+,0x06,0x8b,0x37,0x04,0x00,0xc7,0x06,0x8d,0x37,0x04,0x00,0x81,0x0e,0x99,0x36,0x00
+,0x02,0xe9,0x69,0xe5,0xf6,0x06,0x9d,0x36,0x80,0x75,0x1b,0xa9,0xd0,0x07,0x75,0xeb
+,0xa9,0x00,0x18,0x75,0x0c,0xff,0x0e,0x8d,0x37,0x75,0xe0,0xe8,0x17,0xfb,0xe9,0x4c
+,0xe5,0xb8,0x82,0x03,0xcd,0x39,0xc3,0xff,0x0e,0x8b,0x37,0x75,0xce,0xbe,0x09,0x00
+,0xe9,0x2b,0xe5,0xc7,0x06,0x3d,0x37,0x00,0x00,0xc7,0x06,0x9b,0x36,0x00,0x00,0xe8
+,0x3c,0x02,0x81,0x26,0xaf,0x36,0xff,0xe7,0xa1,0xaf,0x36,0xe7,0x06,0x81,0x26,0x9b
+,0x36,0xff,0x7f,0xe5,0x02,0x0d,0x01,0x00,0x25,0xef,0xff,0x25,0xff,0xdf,0xe7,0x02
+,0xbb,0xff,0x7f,0xcd,0x53,0x33,0xc0,0xa3,0x9d,0x36,0xa3,0x9f,0x36,0xe8,0x50,0x00
+,0xe8,0x73,0x00,0xb8,0x81,0x03,0xcd,0x39,0xc3,0xf7,0x06,0x9b,0x36,0x03,0x00,0x74
+,0x0d,0xc6,0x06,0x9f,0x36,0x02,0xc6,0x06,0xa0,0x36,0x00,0xe9,0xdf,0xe4,0x83,0x0e
+,0x9b,0x36,0x10,0xc7,0x06,0x99,0x36,0x00,0x00,0xe8,0xe7,0x02,0xe5,0x56,0x0d,0x02
+,0x00,0xe7,0x56,0xc7,0x06,0xa8,0x02,0x00,0x00,0x8b,0x36,0x3d,0x37,0xe8,0x44,0x02
+,0xc6,0x06,0xa0,0x36,0x0e,0xe9,0xb5,0xe4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x06,0xb8,0x8a,0x03,0xcd,0x3a,0xb8,0x85,0x03,0xcd,0x3a,0xb8,0x86,0x03,0xcd,0x3a
+,0xb8,0x83,0x03,0xcd,0x3a,0xb8,0x87,0x03,0xcd,0x3a,0xb8,0x8b,0x03,0xcd,0x3a,0xb8
+,0x88,0x03,0xcd,0x3a,0x07,0xc3,0x06,0xb8,0x88,0x03,0xcd,0x3a,0xb8,0x7b,0x03,0xcd
+,0x3a,0xb8,0x82,0x03,0xcd,0x3a,0xb8,0x7f,0x03,0xcd,0x3a,0xb8,0x7c,0x03,0xcd,0x3a
+,0xb8,0x7e,0x03,0xcd,0x3a,0xb8,0x80,0x03,0xcd,0x3a,0xb8,0x81,0x03,0xcd,0x3a,0xb8
+,0x84,0x03,0xcd,0x3a,0xb8,0x89,0x03,0xcd,0x3a,0xb8,0x7d,0x03,0xcd,0x3a,0xb8,0x8d
+,0x03,0xcd,0x3a,0xc7,0x06,0x41,0x37,0x00,0x00,0x07,0xc3,0x06,0x8e,0x06,0x38,0x34
+,0x1f,0x8b,0x0e,0x0e,0x00,0x26,0x89,0x0e,0x0e,0x00,0xbe,0x18,0x00,0xbf,0x18,0x00
+,0xf3,0xa4,0x06,0x1e,0x07,0xcd,0x34,0x07,0x33,0xc0,0x8e,0xd8,0xc3,0x26,0xf6,0x06
+,0x20,0x00,0x80,0x74,0x44,0x33,0xc0,0x26,0xa0,0x26,0x00,0x24,0x1f,0x8b,0xf0,0x26
+,0x8b,0x5c,0x28,0x89,0x1e,0x6a,0x37,0x06,0x8e,0x06,0x38,0x34,0x1f,0xc0,0xe3,0x04
+,0x26,0x88,0x5c,0x28,0x8b,0xc6,0xb9,0x06,0x00,0xbe,0x20,0x00,0xbf,0x1a,0x00,0xf3
+,0xa4,0x8b,0xc8,0x83,0xc7,0x06,0xf3,0xa4,0x26,0x81,0x26,0x26,0x00,0x1f,0x80,0x26
+,0x81,0x36,0x26,0x00,0x00,0x80,0xe9,0xa9,0xff,0x26,0x8b,0x1e,0x28,0x00,0x89,0x1e
+,0x6a,0x37,0x06,0x8e,0x06,0x38,0x34,0x1f,0xc0,0xe3,0x04,0x26,0x88,0x1e,0x28,0x00
+,0xb9,0x06,0x00,0xbe,0x20,0x00,0xbf,0x1a,0x00,0xf3,0xa4,0xe9,0x84,0xff,0x86,0xc4
+,0xa3,0x68,0x37,0xe8,0x87,0xff,0xf7,0x06,0x6a,0x37,0x0f,0x00,0x74,0x10,0x80,0x3e
+,0x9e,0x36,0x00,0x75,0x09,0xbe,0x00,0x00,0xe8,0xac,0xe9,0xcd,0x50,0xc3,0xc3,0x50
+,0x56,0x06,0x33,0xc0,0x26,0xf6,0x06,0x20,0x00,0x80,0x74,0x06,0x26,0xa0,0x26,0x00
+,0x24,0x1f,0x8b,0xf0,0x26,0x8b,0x5c,0x26,0x86,0xfb,0x83,0xeb,0x04,0x74,0x4f,0x83
+,0xc6,0x2a,0x8c,0xc0,0x8e,0xd8,0xb9,0x07,0x00,0x33,0xc0,0x8e,0xc0,0xbf,0x72,0x37
+,0xf3,0xab,0x33,0xc9,0x8a,0x0c,0x80,0xf9,0x00,0x75,0x03,0xe9,0x30,0x00,0x3b,0xd9
+,0x73,0x03,0xe9,0x29,0x00,0x2b,0xd9,0x8a,0x44,0x01,0x25,0x3f,0x00,0x74,0x19,0x3d
+,0x0b,0x00,0x7d,0x14,0xd1,0xe0,0x8b,0xf8,0x2e,0x8b,0xbd,0x5c,0x49,0x8d,0x74,0x02
+,0x83,0xe9,0x02,0xf3,0xa4,0xe9,0x02,0x00,0x03,0xf1,0x23,0xdb,0x75,0xc4,0x33,0xc0
+,0x8e,0xd8,0x07,0x5e,0x58,0xc3,0x33,0xc0,0x26,0xf6,0x06,0x20,0x00,0x80,0x74,0x06
+,0x26,0xa0,0x26,0x00,0x24,0x1f,0xc3,0xe5,0x0a,0x25,0xc3,0xbf,0xe7,0x0a,0xb8,0x86
+,0x03,0xcd,0x39,0xb8,0x83,0x03,0xcd,0x39,0x81,0x26,0x9b,0x36,0x7c,0xdf,0xb8,0x85
+,0x03,0xcd,0x3a,0xe5,0x02,0x25,0xff,0xf3,0x0d,0x01,0x00,0x25,0xef,0xff,0xe7,0x02
+,0xe5,0x00,0x25,0xff,0x53,0xe7,0x00,0xa1,0xe7,0x36,0x25,0xff,0xfe,0xa3,0xe7,0x36
+,0xe7,0x3e,0x83,0x26,0x99,0x36,0xcf,0x81,0x0e,0xaf,0x36,0x00,0x10,0xa1,0xaf,0x36
+,0xe7,0x06,0xc3,0xe5,0x02,0x0d,0x01,0x0c,0x25,0xef,0xff,0xe7,0x02,0xa1,0xe7,0x36
+,0x0d,0x00,0x01,0xe7,0x3e,0xa3,0xe7,0x36,0x81,0x0e,0x9b,0x36,0x00,0x20,0x83,0x0e
+,0x99,0x36,0x20,0x81,0x26,0x9b,0x36,0x7c,0xbf,0x81,0x0e,0xaf,0x36,0x00,0x10,0xa1
+,0xaf,0x36,0xe7,0x06,0xb8,0x86,0x03,0xcd,0x39,0xb8,0x85,0x03,0xcd,0x39,0xb8,0x83
+,0x03,0xcd,0x3a,0xc3,0x0b,0xf6,0x75,0x49,0x06,0x8e,0x06,0x32,0x34,0x80,0x3e,0xe0
+,0x34,0x01,0x75,0x1b,0x26,0x89,0x36,0x06,0x00,0x8e,0x06,0x32,0x34,0x26,0xf7,0x06
+,0x0a,0x00,0x00,0x20,0x74,0x07,0x26,0x81,0x0e,0x08,0x00,0x00,0x20,0x07,0xc3,0x80
+,0x3e,0xe3,0x34,0x01,0x75,0x19,0x26,0x89,0x36,0x06,0x00,0x8e,0x06,0x32,0x34,0x26
+,0xf7,0x06,0x0a,0x00,0x00,0x10,0x74,0x07,0x26,0x81,0x0e,0x08,0x00,0x00,0x10,0x07
+,0xc3,0xe9,0xb4,0xff,0x50,0x51,0x57,0x33,0xc0,0xb9,0x06,0x00,0x8e,0xc0,0xbf,0xd1
+,0x36,0xf3,0xae,0x5f,0x74,0x0c,0x26,0xf6,0x06,0x00,0x00,0xc0,0x75,0x04,0xf8,0x59
+,0x58,0xc3,0xf9,0xe9,0xf9,0xff,0x8b,0x05,0x0b,0x45,0x02,0x0b,0x45,0x04,0xc3,0x52
+,0x50,0xe5,0x06,0x25,0x1e,0x00,0x3d,0x1e,0x00,0x75,0xf6,0xb8,0x01,0x80,0xe7,0x5a
+,0x58,0x5a,0xc3,0xe8,0xe9,0xff,0x50,0xe5,0x02,0x25,0xff,0x7f,0x0d,0x01,0x00,0x25
+,0xef,0xff,0xe7,0x02,0x0d,0x00,0x80,0xe7,0x02,0xa1,0xad,0x36,0xe7,0x04,0xa1,0xaf
+,0x36,0xe7,0x06,0x58,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x2e,0x2b,0xce,0x41,0x10,0x42,0x7b,0x41,0x30,0x41,0xa2,0x41,0xaf,0x45,0x44,0x29
+,0xc7,0x2a,0xc7,0x2a,0x60,0x39,0xf4,0x3a,0x5c,0x3c,0x09,0x3d,0xb1,0x3d,0x34,0x3f
+,0xc7,0x2a,0x3c,0x3f,0xc7,0x2a,0xc4,0x3f,0x16,0x40,0x16,0x40,0xed,0x40,0xfa,0x40
+,0x07,0x41,0xc7,0x2a,0xc7,0x2a,0xc7,0x2a,0xc7,0x2a,0xd6,0x52,0x00,0x00,0x01,0x37
+,0xe9,0x36,0xf3,0x36,0xef,0x36,0x1d,0x37,0x0d,0x37,0x0b,0x37,0x9c,0x37,0x03,0x37
+,0xfb,0x36,0x62,0x2d,0x40,0x06,0xd1,0x2d,0xf4,0x01,0xba,0x44,0x40,0x06,0x8c,0x43
+,0x64,0x00,0xe8,0x2c,0xc8,0x00,0xd8,0x2b,0x05,0x00,0xe9,0x45,0x50,0x00,0x97,0x45
+,0xfa,0x00,0xae,0x2d,0x04,0x01,0x6a,0x42,0x02,0x00,0xf6,0x2c,0xbc,0x02,0x93,0x2d
+,0xdc,0x05,0x1d,0x2d,0x64,0x00,0xa1,0x2d,0x14,0x00,0xd7,0x3a,0x08,0x07,0x81,0x2d
+,0x64,0x00,0xb3,0x3e,0x02,0x00,0x30,0x43,0x64,0x00,0xc5,0x2c,0xf4,0x01,0x8b,0x44
+,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x80,0x3e,0xfd,0x34,0x02,0x74,0x0c,0xe8,0x20,0x05,0xc7,0x06,0xa1,0x36,0x00,0x00
+,0xe9,0x9a,0xf8,0xff,0x06,0xc0,0x33,0xe8,0x10,0x05,0x8b,0x36,0x3d,0x37,0xe8,0x73
+,0xfe,0xc3,0xcd,0x34,0xe9,0xe8,0x05,0xc7,0x06,0xa3,0x36,0x00,0x00,0xc7,0x06,0x41
+,0x37,0x00,0x00,0xe8,0xed,0xfe,0x33,0xc0,0x0d,0x41,0x00,0xe7,0x56,0xa1,0xb1,0x36
+,0x0d,0x00,0x10,0xe7,0x08,0xa1,0xb3,0x36,0xe7,0x0a,0xa1,0xaf,0x36,0xe7,0x06,0xa1
+,0xad,0x36,0xe7,0x04,0xe8,0x2b,0x09,0xc7,0x06,0x1d,0x37,0x00,0xc8,0xc7,0x06,0x0b
+,0x37,0x00,0x03,0xc7,0x06,0x0d,0x37,0x7b,0x7f,0x33,0xc0,0xa3,0x9b,0x36,0xa3,0x9d
+,0x36,0xc7,0x06,0x4c,0x37,0x01,0x00,0xc6,0x06,0x9e,0x36,0xff,0xc7,0x06,0x05,0x37
+,0x00,0x00,0xc7,0x06,0x07,0x37,0x00,0x00,0xc7,0x06,0x09,0x37,0x00,0x00,0xa3,0xf3
+,0x36,0xa3,0xef,0x36,0xa3,0xf1,0x36,0xe8,0xfe,0xf5,0xe5,0x02,0x25,0xf9,0xff,0x0d
+,0x03,0x00,0x0d,0x00,0x88,0x25,0xef,0xff,0x0d,0x00,0x40,0x0d,0x00,0x04,0xe7,0x02
+,0xb8,0x8f,0x03,0xcd,0x39,0xb8,0x80,0x00,0xcd,0x35,0xc7,0x06,0xaa,0x02,0xff,0xff
+,0xa1,0xa9,0x36,0xa3,0xa7,0x36,0x0d,0x00,0xa4,0x0d,0x00,0x08,0xe7,0x00,0xa3,0xa9
+,0x36,0xc7,0x06,0xa3,0x36,0x01,0x00,0xc7,0x06,0xa5,0x36,0x0c,0x00,0x83,0x3e,0xa5
+,0x36,0x00,0x75,0x09,0xc7,0x06,0x3d,0x37,0x05,0x00,0xe9,0x13,0xff,0xff,0x0e,0xa5
+,0x36,0xbe,0x11,0x00,0xe8,0x22,0x05,0xb8,0x90,0x03,0xcd,0x39,0xc3,0x83,0x3e,0xa3
+,0x36,0x01,0x74,0xd9,0xc3,0xb8,0x90,0x03,0xcd,0x3a,0x26,0xa0,0x2b,0x00,0x26,0x8b
+,0x1e,0x2c,0x00,0xcd,0x34,0x83,0x3e,0xa3,0x36,0x01,0x74,0x03,0xe9,0xf0,0x04,0x3c
+,0x0f,0x75,0x1e,0x81,0xfb,0x00,0x02,0x75,0x18,0x26,0xa1,0x20,0x00,0xa3,0x05,0x37
+,0x26,0xa1,0x22,0x00,0xa3,0x07,0x37,0x26,0xa1,0x24,0x00,0xa3,0x09,0x37,0xe9,0x09
+,0x00,0xc7,0x06,0x3d,0x37,0x01,0x00,0xe9,0xb6,0xfe,0xc7,0x06,0xa3,0x36,0x02,0x00
+,0xc6,0x06,0x9e,0x36,0xff,0xe8,0xcb,0xfd,0xe8,0x1c,0xd9,0x33,0xc0,0xa3,0x85,0x37
+,0xa3,0x83,0x37,0xa3,0x87,0x37,0xa3,0x89,0x37,0xb8,0x91,0x03,0xcd,0x39,0xb8,0x80
+,0x00,0xcd,0x35,0xc7,0x06,0xaa,0x02,0xff,0xff,0xe5,0x00,0x25,0xff,0x53,0xe7,0x00
+,0x81,0x0e,0x9a,0x37,0x80,0x00,0xb8,0x92,0x03,0xcd,0x39,0x33,0xc0,0xe7,0x0e,0xbe
+,0x08,0x00,0x8e,0x06,0x38,0x34,0xe8,0x8e,0xe5,0x26,0xc7,0x06,0x04,0x00,0x7d,0x4b
+,0x83,0x26,0xef,0x34,0xdf,0xcd,0x50,0x83,0x0e,0xef,0x34,0x20,0xc3,0xf7,0x06,0x9a
+,0x37,0x80,0x00,0x74,0x32,0xa9,0xd0,0x07,0x74,0x0c,0xa9,0x00,0x04,0x74,0x0e,0x33
+,0xc0,0xe7,0x0e,0xe9,0xda,0xff,0xff,0x06,0x85,0x37,0xe9,0xd3,0xff,0xff,0x06,0x83
+,0x37,0xe9,0xcc,0xff,0xc7,0x06,0x3d,0x37,0x01,0x00,0xe9,0x36,0xfe,0x83,0x26,0x9a
+,0x37,0x7f,0xbb,0xff,0x7f,0xcd,0x53,0xe5,0x00,0x0d,0x00,0xac,0xe7,0x00,0xe5,0x02
+,0x25,0xff,0xfb,0x25,0xef,0xff,0x25,0xff,0xf7,0x0d,0x01,0x00,0xe7,0x02,0xa1,0x83
+,0x37,0x3b,0x06,0x46,0x37,0x7f,0xcd,0xa1,0x85,0x37,0x3b,0x06,0x48,0x37,0x7c,0xc4
+,0xc7,0x06,0xa3,0x36,0x03,0x00,0xbe,0x13,0x00,0xe8,0xfd,0x03,0xb8,0x93,0x03,0xcd
+,0x39,0xb8,0x94,0x03,0xcd,0x39,0xb8,0x96,0x03,0xcd,0x39,0xb8,0x95,0x03,0xcd,0x39
+,0xbe,0x06,0x00,0xe8,0xe3,0x03,0xe9,0xd6,0x03,0x83,0x3e,0xa3,0x36,0x03,0x74,0x01
+,0xc3,0xbe,0x13,0x00,0xe8,0xd2,0x03,0xb8,0x94,0x03,0xcd,0x39,0xc3,0xb8,0x94,0x03
+,0xcd,0x3a,0x26,0xa0,0x2b,0x00,0x26,0x8b,0x1e,0x2c,0x00,0xcd,0x34,0x83,0x3e,0xa3
+,0x36,0x03,0x74,0x03,0xe9,0xa8,0x03,0x3c,0x0d,0x75,0x3e,0x83,0xfb,0x00,0x75,0x39
+,0xe5,0x02,0x0d,0x00,0x20,0xe7,0x02,0xb8,0x93,0x03,0xcd,0x3a,0xc7,0x06,0xa3,0x36
+,0x04,0x00,0xbe,0x00,0x00,0xe8,0x0c,0xfc,0xc6,0x06,0x9d,0x36,0x80,0xc6,0x06,0x9e
+,0x36,0x00,0xc7,0x06,0x33,0x37,0x02,0x00,0xb8,0x9a,0x03,0xcd,0x39,0xe8,0xfc,0x00
+,0xc7,0x06,0x4c,0x37,0x00,0x00,0xe9,0x66,0x03,0xc7,0x06,0x3d,0x37,0x08,0x00,0xe9
+,0x61,0xfd,0x83,0x3e,0xa3,0x36,0x03,0x75,0x09,0xc7,0x06,0x3d,0x37,0x05,0x00,0xe9
+,0x51,0xfd,0xe9,0x4a,0x03,0x83,0x3e,0xa3,0x36,0x04,0x74,0x12,0x83,0x3e,0xa3,0x36
+,0x05,0x74,0x0b,0xcd,0x34,0xc7,0x06,0x3d,0x37,0x07,0x00,0xe9,0x35,0xfd,0xc7,0x06
+,0xa3,0x36,0x06,0x00,0xc6,0x06,0x9e,0x36,0xff,0xb8,0x9a,0x03,0xcd,0x3a,0xb8,0x99
+,0x03,0xcd,0x3a,0xb8,0x96,0x03,0xcd,0x3a,0xb8,0x97,0x03,0xcd,0x39,0xb8,0x98,0x03
+,0xcd,0x39,0xb8,0x9b,0x03,0xcd,0x39,0xe9,0x18,0xfd,0xcd,0x34,0x83,0x3e,0xa3,0x36
+,0x04,0x77,0x18,0x83,0x3e,0xa3,0x36,0x03,0x75,0x08,0xf7,0x06,0x9b,0x36,0x00,0x01
+,0x75,0x09,0xc7,0x06,0x3d,0x37,0x01,0x00,0xe9,0xe8,0xfc,0xe9,0xe1,0x02,0xcd,0x34
+,0x83,0x3e,0xa3,0x36,0x02,0x77,0x09,0xc7,0x06,0x3d,0x37,0x01,0x00,0xe9,0xd3,0xfc
+,0x83,0x3e,0xa3,0x36,0x04,0x77,0x05,0xb8,0x96,0x03,0xcd,0x39,0xe9,0xc0,0x02,0x83
+,0x3e,0xa3,0x36,0x03,0x75,0x10,0x26,0xa1,0x0c,0x00,0x25,0x07,0x00,0x50,0x3d,0x04
+,0x00,0x75,0x03,0xe8,0x36,0x00,0xa1,0xf3,0x36,0x86,0xe0,0xe7,0x1e,0xa3,0xe3,0x36
+,0x81,0x26,0x0b,0x37,0x00,0x03,0x81,0x26,0x0d,0x37,0x7b,0x7f,0x83,0x0e,0x0d,0x37
+,0x48,0xe8,0x14,0xf3,0x58,0x3d,0x04,0x00,0x74,0x09,0x26,0xf7,0x06,0x0c,0x00,0x20
+,0x00,0x75,0x06,0xb8,0x01,0x00,0xe9,0x7a,0x02,0xe9,0x86,0xfc,0xa1,0xe5,0x36,0xe7
+,0x2e,0xa1,0xe7,0x36,0xe7,0x3e,0xa1,0xd3,0x36,0xa3,0x9c,0x34,0xa1,0xd5,0x36,0xa3
+,0x9e,0x34,0xc3,0x26,0x80,0x3e,0x1c,0x00,0xff,0x75,0x2f,0x26,0x80,0x3e,0x1e,0x00
+,0xff,0x75,0x27,0x26,0xf7,0x06,0x0c,0x00,0x40,0x00,0x75,0x1b,0xa1,0xd1,0x36,0x26
+,0xa3,0x1a,0x00,0xa1,0xd3,0x36,0x26,0xa3,0x1c,0x00,0xa1,0xd5,0x36,0x26,0xa3,0x1e
+,0x00,0xb8,0x0a,0x80,0xe9,0x2c,0x02,0xe9,0x38,0xfc,0xff,0x06,0x90,0x34,0xbe,0x0a
+,0x00,0xc6,0x06,0xb6,0x34,0x01,0xf6,0x06,0x9d,0x36,0x80,0x75,0x05,0x83,0x0e,0xc2
+,0x34,0x01,0xcd,0x34,0xe9,0x0c,0xfc,0x83,0x3e,0xa3,0x36,0x03,0x75,0x09,0xc7,0x06
+,0x3d,0x37,0x05,0x00,0xe9,0xfc,0xfb,0xe5,0x02,0x0d,0x03,0x00,0x0d,0x00,0x88,0x0d
+,0x00,0x40,0x0d,0x00,0x04,0xe7,0x02,0xc7,0x06,0xa3,0x36,0x05,0x00,0xc6,0x06,0x9e
+,0x36,0xff,0xbe,0x02,0x00,0xe8,0xe1,0x01,0xb8,0x89,0x03,0xcd,0x3a,0xb8,0x9a,0x03
+,0xcd,0x3a,0xb8,0x99,0x03,0xcd,0x39,0xb8,0x97,0x03,0xcd,0x39,0xb8,0x98,0x03,0xcd
+,0x39,0xe9,0xbb,0x01,0x83,0x3e,0xa3,0x36,0x03,0x74,0x0a,0x83,0x3e,0xa3,0x36,0x04
+,0x74,0x03,0xe9,0xaa,0x01,0xbe,0x06,0x00,0xe8,0xae,0x01,0xb8,0x95,0x03,0xcd,0x39
+,0xe9,0x9c,0x01,0x83,0x3e,0xa3,0x36,0x05,0x74,0x03,0xe9,0x92,0x01,0xbe,0x02,0x00
+,0xe8,0x96,0x01,0xb8,0x99,0x03,0xcd,0x39,0xe9,0x84,0x01,0xc7,0x06,0x0f,0x37,0x05
+,0x00,0xe9,0x7b,0x01,0xe5,0x02,0x25,0xff,0xdf,0xe7,0x02,0xc7,0x06,0xa3,0x36,0x07
+,0x00,0xc7,0x06,0x0f,0x37,0x05,0x00,0xe9,0x65,0x01,0xe8,0xd5,0x04,0xc6,0x06,0x9d
+,0x36,0x00,0xc7,0x06,0x9b,0x36,0x00,0x00,0xc7,0x06,0x0f,0x37,0x05,0x00,0xc7,0x06
+,0xa8,0x02,0x00,0x00,0xc7,0x06,0x4c,0x37,0x01,0x00,0xe5,0x02,0x25,0xf9,0xff,0x0d
+,0x03,0x00,0x0d,0x00,0x88,0x25,0xef,0xff,0x0d,0x00,0x40,0x0d,0x00,0x04,0xe7,0x02
+,0xe9,0x67,0xfc,0xb8,0x9a,0x03,0xcd,0x39,0xf7,0x06,0xf4,0x33,0x00,0x10,0x75,0x09
+,0xc7,0x06,0x33,0x37,0x02,0x00,0xe9,0x16,0x01,0xff,0x0e,0x33,0x37,0x74,0x03,0xe9
+,0x0d,0x01,0xff,0x06,0x8e,0x34,0x83,0x0e,0xc2,0x34,0x08,0xc7,0x06,0x3d,0x37,0x03
+,0x00,0xe9,0xff,0xfa,0xc3,0x52,0x50,0xba,0xe0,0x00,0xb8,0x00,0x10,0xef,0x58,0x5a
+,0xc3,0xc7,0x06,0x3d,0x37,0x00,0x00,0xe9,0xe9,0xfa,0xfa,0xe8,0x54,0x04,0xb8,0x80
+,0x03,0x8e,0xc0,0x26,0xc7,0x06,0x04,0x00,0xd8,0x2b,0xb8,0x7f,0x03,0x8e,0xc0,0x26
+,0xc7,0x06,0x04,0x00,0xe8,0x2c,0x33,0xc0,0x8e,0xc0,0xa1,0xa7,0x36,0xa3,0xa9,0x36
+,0xa1,0xa9,0x36,0xe7,0x00,0xa1,0xab,0x36,0xe7,0x02,0xc7,0x06,0x05,0x37,0x00,0x00
+,0xc7,0x06,0x07,0x37,0x00,0x00,0xc7,0x06,0x09,0x37,0x00,0x00,0xc6,0x06,0x9d,0x36
+,0x00,0xc6,0x06,0x9e,0x36,0xff,0xc7,0x06,0x9b,0x36,0x00,0x00,0xc7,0x06,0xa3,0x36
+,0x00,0x00,0xc7,0x06,0x0f,0x37,0x00,0x00,0xc7,0x06,0xa8,0x02,0x00,0x00,0xc7,0x06
+,0x4c,0x37,0x01,0x00,0x81,0x26,0xaf,0x36,0xff,0xe7,0xa1,0xaf,0x36,0xe7,0x06,0xbb
+,0xff,0x7f,0xcd,0x53,0xe8,0x7c,0xf9,0xe5,0x56,0x0d,0x02,0x00,0xe7,0x56,0xfb,0xc3
+,0x8d,0x3e,0xc0,0x53,0x8d,0x36,0xf0,0x38,0xb9,0x0e,0x00,0x8b,0x1e,0x30,0x34,0x89
+,0x5c,0x02,0x2e,0x8b,0x45,0x02,0x89,0x44,0x06,0x2e,0x8b,0x05,0x89,0x44,0x04,0x83
+,0xc7,0x04,0x83,0xc6,0x10,0xe2,0xe8,0xb8,0x80,0x03,0x8e,0xc0,0x26,0xc7,0x06,0x04
+,0x00,0xe2,0x51,0xb8,0x7f,0x03,0x8e,0xc0,0x26,0xc7,0x06,0x04,0x00,0xb2,0x52,0x33
+,0xc0,0x8e,0xc0,0xc7,0x06,0xa1,0x36,0x01,0x00,0xc7,0x06,0x0f,0x37,0x05,0x00,0xc3
+,0x33,0xff,0x8e,0x06,0xa6,0x02,0x8b,0x36,0xa4,0x02,0x2e,0xff,0xa4,0xa0,0x53,0xe8
+,0x8c,0xdb,0xc3,0xe8,0x48,0xf7,0xe9,0xf6,0xff,0x8e,0x06,0x38,0x34,0xe8,0x07,0xe1
+,0x26,0xc7,0x06,0x04,0x00,0xdf,0x4f,0xcd,0x50,0xc3,0x26,0xc7,0x06,0x0a,0x00,0x00
+,0x00,0x26,0xff,0x26,0x04,0x00,0xcd,0x34,0xe9,0xd4,0xff,0xa1,0xd1,0x36,0x26,0x39
+,0x06,0x1a,0x00,0x75,0x22,0xa1,0xd3,0x36,0x26,0x39,0x06,0x1c,0x00,0x75,0x18,0xa1
+,0xd5,0x36,0x26,0x39,0x06,0x1e,0x00,0x75,0x0e,0x26,0xf7,0x06,0x0c,0x00,0x40,0x00
+,0x74,0x05,0x83,0x0e,0x66,0x37,0x40,0x81,0x0e,0xaf,0x36,0x00,0x10,0xa1,0xaf,0x36
+,0xe7,0x06,0x83,0x3e,0xa3,0x36,0x02,0x75,0x05,0xcd,0x34,0xe9,0x56,0xfb,0x83,0x3e
+,0xa3,0x36,0x00,0x74,0xb1,0x83,0x3e,0xa3,0x36,0x05,0x77,0xaa,0x26,0xf6,0x06,0x0a
+,0x00,0xff,0x75,0xa2,0xe8,0xfd,0xdd,0x50,0xf6,0x06,0x93,0x36,0x20,0x75,0x03,0xe9
+,0x8c,0x00,0x26,0xa1,0x0c,0x00,0x25,0x07,0x00,0x3d,0x07,0x00,0x75,0x03,0xe9,0x76
+,0x00,0x3d,0x05,0x00,0x75,0x03,0xe9,0x6e,0x00,0xf7,0x06,0xe6,0x34,0x18,0x80,0x75
+,0x03,0xe9,0x6a,0x00,0xf7,0x06,0xe6,0x34,0x00,0x80,0x74,0x35,0x26,0x80,0x3e,0x29
+,0x00,0x02,0x75,0x2d,0x51,0x56,0x57,0x8d,0x36,0x3e,0x34,0x8d,0x3e,0x20,0x00,0xb9
+,0x06,0x00,0xf3,0xa6,0x5f,0x5e,0x59,0x75,0x45,0x26,0xa1,0x20,0x00,0xa3,0x3e,0x34
+,0x26,0xa1,0x22,0x00,0xa3,0x40,0x34,0x26,0xa1,0x24,0x00,0xa3,0x42,0x34,0xe9,0x26
+,0x00,0xf7,0x06,0xe6,0x34,0x08,0x00,0x74,0x0b,0x26,0x80,0x3e,0x19,0x00,0x00,0x74
+,0x03,0xe9,0x13,0x00,0xf7,0x06,0xe6,0x34,0x10,0x00,0x74,0x12,0x26,0xa0,0x28,0x00
+,0xc0,0xe8,0x04,0x22,0xc0,0x74,0x07,0x26,0xc7,0x06,0x04,0x00,0xff,0xff,0x58,0x23
+,0xc0,0x74,0x03,0xe9,0xdd,0xfe,0x81,0x26,0x9b,0x36,0xff,0xfe,0x26,0xa1,0x20,0x00
+,0x3b,0x06,0xd1,0x36,0x75,0x1a,0x26,0xa1,0x22,0x00,0x3b,0x06,0xd3,0x36,0x75,0x10
+,0x26,0xa1,0x24,0x00,0x3b,0x06,0xd5,0x36,0x75,0x06,0x81,0x0e,0x9b,0x36,0x00,0x01
+,0x26,0xa1,0x20,0x00,0x25,0x7f,0xff,0xa3,0xb8,0x34,0x26,0xa1,0x22,0x00,0xa3,0xba
+,0x34,0x26,0xa1,0x24,0x00,0xa3,0xbc,0x34,0x8b,0xc6,0x86,0xc4,0xa3,0xc0,0x34,0xd1
+,0xe6,0x80,0xfc,0x09,0x74,0x03,0xe8,0xf6,0xf5,0xa1,0x05,0x37,0x0b,0x06,0x07,0x37
+,0x0b,0x06,0x09,0x37,0x74,0x3e,0x26,0xa1,0x20,0x00,0x3b,0x06,0x05,0x37,0x75,0x17
+,0x26,0xa1,0x22,0x00,0x3b,0x06,0x07,0x37,0x75,0x0d,0x26,0xa1,0x24,0x00,0x3b,0x06
+,0x09,0x37,0x75,0x03,0xe9,0x1d,0x00,0x26,0xa0,0x28,0x00,0x24,0x0f,0x3c,0x03,0x74
+,0x1b,0x3c,0x00,0x75,0x0f,0x83,0x3e,0xa3,0x36,0x04,0x74,0x10,0xf7,0x06,0x9b,0x36
+,0x00,0x01,0x74,0x08,0x2e,0xff,0x94,0xf8,0x53,0xe9,0x33,0xfe,0xcd,0x34,0xc7,0x06
+,0x3d,0x37,0x01,0x00,0xe9,0x2c,0xf8,0x83,0x3e,0xa3,0x36,0x05,0x74,0x10,0x83,0x3e
+,0xa3,0x36,0x01,0x7e,0x09,0x83,0xee,0x16,0x2e,0xff,0x94,0x24,0x54,0xc3,0xcd,0x34
+,0xc3,0x26,0xa1,0x0c,0x00,0x3d,0xff,0x7f,0x74,0x05,0x26,0xff,0x26,0x04,0x00,0xe9
+,0xfd,0xfd,0xa1,0xf4,0x33,0xa9,0x00,0x88,0x74,0x0b,0xa9,0x00,0x10,0x75,0x09,0x8b
+,0x1e,0x43,0x37,0xff,0xe3,0xe9,0x97,0x00,0xc7,0x06,0x35,0x37,0x05,0x00,0xc7,0x06
+,0x43,0x37,0x28,0x52,0xf7,0x06,0xf4,0x33,0x00,0x08,0x74,0x06,0xc7,0x06,0x43,0x37
+,0x1a,0x52,0xb8,0x80,0x03,0xcd,0x39,0xe9,0xc5,0xfd,0xa9,0x00,0x08,0x74,0xd9,0xff
+,0x0e,0x35,0x37,0x75,0xed,0xe9,0x30,0x00,0xa9,0x00,0x08,0x75,0xcb,0xff,0x0e,0x35
+,0x37,0x75,0xdf,0x81,0x0e,0xc2,0x34,0xc0,0x00,0xf6,0x06,0x9d,0x36,0x80,0x74,0x0f
+,0x81,0x0e,0x9b,0x36,0x00,0x80,0xc7,0x06,0x0f,0x37,0x02,0x00,0xe9,0x90,0xfd,0xc7
+,0x06,0x3d,0x37,0x02,0x00,0xe9,0x8b,0xf7,0x80,0x26,0x9e,0x36,0xff,0x75,0x30,0xf6
+,0x06,0x9d,0x36,0x80,0x74,0x20,0xff,0x06,0x94,0x34,0x83,0x0e,0x66,0x37,0x20,0x8e
+,0x06,0x30,0x34,0x26,0xf7,0x06,0x0a,0x00,0x00,0x01,0x74,0x07,0x26,0x81,0x0e,0x08
+,0x00,0x00,0x01,0xe9,0x09,0x00,0xc7,0x06,0x3d,0x37,0x04,0x00,0xe9,0x54,0xf7,0x81
+,0x0e,0xaf,0x36,0x00,0x08,0xa1,0xaf,0x36,0xe7,0x06,0xe5,0x0a,0xa9,0x00,0x80,0x74
+,0x0e,0x81,0x26,0xaf,0x36,0xff,0xf7,0xa1,0xaf,0x36,0xe7,0x06,0xe9,0x49,0xff,0xe9
+,0x2d,0xfd,0xc7,0x06,0x41,0x37,0x00,0x00,0xbe,0x29,0x00,0xe8,0x2b,0xfd,0xe9,0x1e
+,0xfd,0xcd,0x34,0x83,0x3e,0xa3,0x36,0x04,0x77,0x09,0xc7,0x06,0x3d,0x37,0x01,0x00
+,0xe9,0x10,0xf7,0xe9,0x09,0xfd,0xcd,0x34,0xc3,0xc7,0x06,0x9b,0x36,0x00,0x00,0xe8
+,0x0c,0xf5,0x81,0x26,0xaf,0x36,0xff,0xe7,0xa1,0xaf,0x36,0xe7,0x06,0x81,0x26,0x9b
+,0x36,0xff,0x7f,0xe5,0x02,0x0d,0x01,0x00,0x25,0xef,0xff,0x25,0xff,0xdf,0xe7,0x02
+,0xbb,0xff,0x7f,0xcd,0x53,0x33,0xc0,0xa3,0x9d,0x36,0xa3,0x9f,0x36,0xe8,0x20,0xf3
+,0xe8,0x43,0xf3,0x83,0x0e,0x9b,0x36,0x10,0xc7,0x06,0x99,0x36,0x00,0x00,0xe8,0xd2
+,0xf5,0xe5,0x56,0x0d,0x02,0x00,0xe7,0x56,0xc7,0x06,0xa8,0x02,0x00,0x00,0xbe,0x00
+,0x00,0xe8,0x30,0xf5,0xc6,0x06,0xa0,0x36,0x0e,0xb8,0x9c,0x03,0xcd,0x39,0xb8,0x80
+,0x00,0xcd,0x35,0xc7,0x06,0xaa,0x02,0xff,0xff,0xc7,0x06,0xa1,0x36,0x01,0x00,0xe9
+,0xa5,0xf6,0x06,0xb8,0x8f,0x03,0xcd,0x3a,0xb8,0x90,0x03,0xcd,0x3a,0xb8,0x91,0x03
+,0xcd,0x3a,0xb8,0x92,0x03,0xcd,0x3a,0xb8,0x93,0x03,0xcd,0x3a,0xb8,0x94,0x03,0xcd
+,0x3a,0xb8,0x95,0x03,0xcd,0x3a,0xb8,0x96,0x03,0xcd,0x3a,0xb8,0x97,0x03,0xcd,0x3a
+,0xb8,0x98,0x03,0xcd,0x3a,0xb8,0x99,0x03,0xcd,0x3a,0xb8,0x9a,0x03,0xcd,0x3a,0xb8
+,0x9b,0x03,0xcd,0x3a,0xb8,0x7f,0x03,0xcd,0x3a,0xb8,0x80,0x03,0xcd,0x3a,0x07,0xc3
+,0xf7,0x49,0xf1,0x4e,0xdf,0x4f,0xdf,0x4f,0xdf,0x4f,0xdf,0x4f,0xf8,0x51,0xdf,0x4f
+,0xfa,0x4f,0x0b,0x50,0xd1,0x51,0xdf,0x4f,0xdf,0x4f,0xdf,0x4f,0xdf,0x4f,0xdf,0x4f
+,0xe4,0x4e,0x06,0x00,0xcd,0x4a,0x04,0x00,0xe4,0x4e,0x19,0x00,0xad,0x4b,0xfa,0x00
+,0x82,0x4c,0x08,0x07,0x09,0x4c,0x14,0x00,0x24,0x4e,0x64,0x00,0xd7,0x4d,0xf4,0x01
+,0x64,0x4e,0xbc,0x02,0x7a,0x4e,0xe8,0x03,0x43,0x4e,0x02,0x00,0xb3,0x4e,0xf4,0x01
+,0x5b,0x4e,0xf4,0x01,0xe5,0x4e,0x14,0x00,0x06,0x50,0x06,0x50,0x95,0x4c,0xc1,0x52
+,0xc1,0x52,0xfe,0x4c,0xda,0x4c,0x06,0x50,0x06,0x50,0x06,0x50,0x06,0x50,0xb7,0x51
+,0xb7,0x51,0xb7,0x51,0xb7,0x51,0xb7,0x51,0xb7,0x51,0x06,0x50,0xd5,0x4a,0x06,0x50
+,0x1d,0x4c,0x06,0x50,0x83,0x4d,0x1f,0x4d,0x1f,0x4d,0xed,0x40,0xfa,0x40,0x07,0x41
+,0x37,0x37,0x2e,0x37,0x37,0x20,0x20,0x79,0x79,0x2f,0x79,0x79,0x2f,0x79,0x79,0x20
+,0x30,0x31,0x2e,0x39,0x30,0x20,0x20,0x30,0x32,0x2f,0x31,0x37,0x2f,0x39,0x39,0x20
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+,0x90,0xea,0xc0,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x06
+} ;
diff --git a/drivers/net/tokenring/Kconfig b/drivers/net/tokenring/Kconfig
new file mode 100644
index 00000000000..23d0fa4bbce
--- /dev/null
+++ b/drivers/net/tokenring/Kconfig
@@ -0,0 +1,186 @@
+#
+# Token Ring driver configuration
+#
+
+menu "Token Ring devices"
+ depends on NETDEVICES
+
+# So far, we only have PCI, ISA, and MCA token ring devices
+config TR
+ bool "Token Ring driver support"
+ depends on (PCI || ISA || MCA || CCW)
+ select LLC
+ help
+ Token Ring is IBM's way of communication on a local network; the
+ rest of the world uses Ethernet. To participate on a Token Ring
+ network, you need a special Token ring network card. If you are
+ connected to such a Token Ring network and want to use your Token
+ Ring card under Linux, say Y here and to the driver for your
+ particular card below and read the Token-Ring mini-HOWTO, available
+ from <http://www.tldp.org/docs.html#howto>. Most people can
+ say N here.
+
+config IBMTR
+ tristate "IBM Tropic chipset based adapter support"
+ depends on TR && (ISA || MCA)
+ ---help---
+ This is support for all IBM Token Ring cards that don't use DMA. If
+ you have such a beast, say Y and read the Token-Ring mini-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ Warning: this driver will almost definitely fail if more than one
+ active Token Ring card is present.
+
+ To compile this driver as a module, choose M here: the module will be
+ called ibmtr.
+
+config IBMOL
+ tristate "IBM Olympic chipset PCI adapter support"
+ depends on TR && PCI
+ ---help---
+ This is support for all non-Lanstreamer IBM PCI Token Ring Cards.
+ Specifically this is all IBM PCI, PCI Wake On Lan, PCI II, PCI II
+ Wake On Lan, and PCI 100/16/4 adapters.
+
+ If you have such an adapter, say Y and read the Token-Ring
+ mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here: the module will be
+ called olympic.
+
+ Also read <file:Documentation/networking/olympic.txt> or check the
+ Linux Token Ring Project site for the latest information at
+ <http://www.linuxtr.net/>.
+
+config IBMLS
+ tristate "IBM Lanstreamer chipset PCI adapter support"
+ depends on TR && PCI && !64BIT
+ help
+ This is support for IBM Lanstreamer PCI Token Ring Cards.
+
+ If you have such an adapter, say Y and read the Token-Ring
+ mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here: the module will be
+ called lanstreamer.
+
+config 3C359
+ tristate "3Com 3C359 Token Link Velocity XL adapter support"
+ depends on TR && PCI
+ ---help---
+ This is support for the 3Com PCI Velocity XL cards, specifically
+ the 3Com 3C359, please note this is not for the 3C339 cards, you
+ should use the tms380 driver instead.
+
+ If you have such an adapter, say Y and read the Token-Ring
+ mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here: the module will be
+ called 3c359.
+
+ Also read the file <file:Documentation/networking/3c359.txt> or check the
+ Linux Token Ring Project site for the latest information at
+ <http://www.linuxtr.net>
+
+config TMS380TR
+ tristate "Generic TMS380 Token Ring ISA/PCI adapter support"
+ depends on TR && (PCI || ISA)
+ select FW_LOADER
+ ---help---
+ This driver provides generic support for token ring adapters
+ based on the Texas Instruments TMS380 series chipsets. This
+ includes the SysKonnect TR4/16(+) ISA (SK-4190), SysKonnect
+ TR4/16(+) PCI (SK-4590), SysKonnect TR4/16 PCI (SK-4591),
+ Compaq 4/16 PCI, Thomas-Conrad TC4048 4/16 PCI, and several
+ Madge adapters. If you say Y here, you will be asked to select
+ which cards to support below. If you're using modules, each
+ class of card will be supported by a separate module.
+
+ If you have such an adapter and would like to use it, say Y and
+ read the Token-Ring mini-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Also read the file <file:Documentation/networking/tms380tr.txt> or
+ check <http://www.auk.cx/tms380tr/>.
+
+ To compile this driver as a module, choose M here: the module will be
+ called tms380tr.
+
+config TMSPCI
+ tristate "Generic TMS380 PCI support"
+ depends on TR && TMS380TR && PCI
+ ---help---
+ This tms380 module supports generic TMS380-based PCI cards.
+
+ These cards are known to work:
+ - Compaq 4/16 TR PCI
+ - SysKonnect TR4/16 PCI (SK-4590/SK-4591)
+ - Thomas-Conrad TC4048 PCI 4/16
+ - 3Com Token Link Velocity
+
+ To compile this driver as a module, choose M here: the module will be
+ called tmspci.
+
+config SKISA
+ tristate "SysKonnect TR4/16 ISA support"
+ depends on TR && TMS380TR && ISA
+ help
+ This tms380 module supports SysKonnect TR4/16 ISA cards.
+
+ These cards are known to work:
+ - SysKonnect TR4/16 ISA (SK-4190)
+
+ To compile this driver as a module, choose M here: the module will be
+ called skisa.
+
+config PROTEON
+ tristate "Proteon ISA support"
+ depends on TR && TMS380TR && ISA
+ help
+ This tms380 module supports Proteon ISA cards.
+
+ These cards are known to work:
+ - Proteon 1392
+ - Proteon 1392 plus
+
+ To compile this driver as a module, choose M here: the module will be
+ called proteon.
+
+config ABYSS
+ tristate "Madge Smart 16/4 PCI Mk2 support"
+ depends on TR && TMS380TR && PCI
+ help
+ This tms380 module supports the Madge Smart 16/4 PCI Mk2
+ cards (51-02).
+
+ To compile this driver as a module, choose M here: the module will be
+ called abyss.
+
+config MADGEMC
+ tristate "Madge Smart 16/4 Ringnode MicroChannel"
+ depends on TR && TMS380TR && MCA_LEGACY
+ help
+ This tms380 module supports the Madge Smart 16/4 MC16 and MC32
+ MicroChannel adapters.
+
+ To compile this driver as a module, choose M here: the module will be
+ called madgemc.
+
+config SMCTR
+ tristate "SMC ISA/MCA adapter support"
+ depends on TR && (ISA || MCA_LEGACY) && (BROKEN || !64BIT)
+ ---help---
+ This is support for the ISA and MCA SMC Token Ring cards,
+ specifically SMC TokenCard Elite (8115T) and SMC TokenCard Elite/A
+ (8115T/A) adapters.
+
+ If you have such an adapter and would like to use it, say Y or M and
+ read the Token-Ring mini-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto> and the file
+ <file:Documentation/networking/smctr.txt>.
+
+ To compile this driver as a module, choose M here: the module will be
+ called smctr.
+
+endmenu
+
diff --git a/drivers/net/tokenring/Makefile b/drivers/net/tokenring/Makefile
new file mode 100644
index 00000000000..c88b0a5e538
--- /dev/null
+++ b/drivers/net/tokenring/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for drivers/net/tokenring
+#
+
+obj-$(CONFIG_IBMTR) += ibmtr.o
+obj-$(CONFIG_IBMOL) += olympic.o
+obj-$(CONFIG_IBMLS) += lanstreamer.o
+obj-$(CONFIG_TMS380TR) += tms380tr.o
+obj-$(CONFIG_ABYSS) += abyss.o
+obj-$(CONFIG_MADGEMC) += madgemc.o
+obj-$(CONFIG_PROTEON) += proteon.o
+obj-$(CONFIG_TMSPCI) += tmspci.o
+obj-$(CONFIG_SKISA) += skisa.o
+obj-$(CONFIG_SMCTR) += smctr.o
+obj-$(CONFIG_3C359) += 3c359.o
diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c
new file mode 100644
index 00000000000..bd4a2bccf86
--- /dev/null
+++ b/drivers/net/tokenring/abyss.c
@@ -0,0 +1,481 @@
+/*
+ * abyss.c: Network driver for the Madge Smart 16/4 PCI Mk2 token ring card.
+ *
+ * Written 1999-2000 by Adam Fritzler
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * This driver module supports the following cards:
+ * - Madge Smart 16/4 PCI Mk2
+ *
+ * Maintainer(s):
+ * AF Adam Fritzler mid@auk.cx
+ *
+ * Modification History:
+ * 30-Dec-99 AF Split off from the tms380tr driver.
+ * 22-Jan-00 AF Updated to use indirect read/writes
+ * 23-Nov-00 JG New PCI API, cleanups
+ *
+ *
+ * TODO:
+ * 1. See if we can use MMIO instead of inb/outb/inw/outw
+ * 2. Add support for Mk1 (has AT24 attached to the PCI
+ * config registers)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/trdevice.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "tms380tr.h"
+#include "abyss.h" /* Madge-specific constants */
+
+static char version[] __devinitdata =
+"abyss.c: v1.02 23/11/2000 by Adam Fritzler\n";
+
+#define ABYSS_IO_EXTENT 64
+
+static struct pci_device_id abyss_pci_tbl[] = {
+ { PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_MK2,
+ PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_TOKEN_RING << 8, 0x00ffffff, },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, abyss_pci_tbl);
+
+MODULE_LICENSE("GPL");
+
+static int abyss_open(struct net_device *dev);
+static int abyss_close(struct net_device *dev);
+static void abyss_enable(struct net_device *dev);
+static int abyss_chipset_init(struct net_device *dev);
+static void abyss_read_eeprom(struct net_device *dev);
+static unsigned short abyss_setnselout_pins(struct net_device *dev);
+
+static void at24_writedatabyte(unsigned long regaddr, unsigned char byte);
+static int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char addr);
+static int at24_sendcmd(unsigned long regaddr, unsigned char cmd);
+static unsigned char at24_readdatabit(unsigned long regaddr);
+static unsigned char at24_readdatabyte(unsigned long regaddr);
+static int at24_waitforack(unsigned long regaddr);
+static int at24_waitfornack(unsigned long regaddr);
+static void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char data);
+static void at24_start(unsigned long regaddr);
+static unsigned char at24_readb(unsigned long regaddr, unsigned char addr);
+
+static unsigned short abyss_sifreadb(struct net_device *dev, unsigned short reg)
+{
+ return inb(dev->base_addr + reg);
+}
+
+static unsigned short abyss_sifreadw(struct net_device *dev, unsigned short reg)
+{
+ return inw(dev->base_addr + reg);
+}
+
+static void abyss_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg)
+{
+ outb(val, dev->base_addr + reg);
+}
+
+static void abyss_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg)
+{
+ outw(val, dev->base_addr + reg);
+}
+
+static int __devinit abyss_attach(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ static int versionprinted;
+ struct net_device *dev;
+ struct net_local *tp;
+ int i, ret, pci_irq_line;
+ unsigned long pci_ioaddr;
+
+ if (versionprinted++ == 0)
+ printk("%s", version);
+
+ if (pci_enable_device(pdev))
+ return -EIO;
+
+ /* Remove I/O space marker in bit 0. */
+ pci_irq_line = pdev->irq;
+ pci_ioaddr = pci_resource_start (pdev, 0);
+
+ /* At this point we have found a valid card. */
+
+ dev = alloc_trdev(sizeof(struct net_local));
+ if (!dev)
+ return -ENOMEM;
+
+ SET_MODULE_OWNER(dev);
+
+ if (!request_region(pci_ioaddr, ABYSS_IO_EXTENT, dev->name)) {
+ ret = -EBUSY;
+ goto err_out_trdev;
+ }
+
+ ret = request_irq(pdev->irq, tms380tr_interrupt, SA_SHIRQ,
+ dev->name, dev);
+ if (ret)
+ goto err_out_region;
+
+ dev->base_addr = pci_ioaddr;
+ dev->irq = pci_irq_line;
+
+ printk("%s: Madge Smart 16/4 PCI Mk2 (Abyss)\n", dev->name);
+ printk("%s: IO: %#4lx IRQ: %d\n",
+ dev->name, pci_ioaddr, dev->irq);
+ /*
+ * The TMS SIF registers lay 0x10 above the card base address.
+ */
+ dev->base_addr += 0x10;
+
+ ret = tmsdev_init(dev, PCI_MAX_ADDRESS, pdev);
+ if (ret) {
+ printk("%s: unable to get memory for dev->priv.\n",
+ dev->name);
+ goto err_out_irq;
+ }
+
+ abyss_read_eeprom(dev);
+
+ printk("%s: Ring Station Address: ", dev->name);
+ printk("%2.2x", dev->dev_addr[0]);
+ for (i = 1; i < 6; i++)
+ printk(":%2.2x", dev->dev_addr[i]);
+ printk("\n");
+
+ tp = netdev_priv(dev);
+ tp->setnselout = abyss_setnselout_pins;
+ tp->sifreadb = abyss_sifreadb;
+ tp->sifreadw = abyss_sifreadw;
+ tp->sifwriteb = abyss_sifwriteb;
+ tp->sifwritew = abyss_sifwritew;
+
+ memcpy(tp->ProductID, "Madge PCI 16/4 Mk2", PROD_ID_SIZE + 1);
+
+ dev->open = abyss_open;
+ dev->stop = abyss_close;
+
+ pci_set_drvdata(pdev, dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ ret = register_netdev(dev);
+ if (ret)
+ goto err_out_tmsdev;
+ return 0;
+
+err_out_tmsdev:
+ pci_set_drvdata(pdev, NULL);
+ tmsdev_term(dev);
+err_out_irq:
+ free_irq(pdev->irq, dev);
+err_out_region:
+ release_region(pci_ioaddr, ABYSS_IO_EXTENT);
+err_out_trdev:
+ free_netdev(dev);
+ return ret;
+}
+
+static unsigned short abyss_setnselout_pins(struct net_device *dev)
+{
+ unsigned short val = 0;
+ struct net_local *tp = netdev_priv(dev);
+
+ if(tp->DataRate == SPEED_4)
+ val |= 0x01; /* Set 4Mbps */
+ else
+ val |= 0x00; /* Set 16Mbps */
+
+ return val;
+}
+
+/*
+ * The following Madge boards should use this code:
+ * - Smart 16/4 PCI Mk2 (Abyss)
+ * - Smart 16/4 PCI Mk1 (PCI T)
+ * - Smart 16/4 Client Plus PnP (Big Apple)
+ * - Smart 16/4 Cardbus Mk2
+ *
+ * These access an Atmel AT24 SEEPROM using their glue chip registers.
+ *
+ */
+static void at24_writedatabyte(unsigned long regaddr, unsigned char byte)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ at24_setlines(regaddr, 0, (byte >> (7-i))&0x01);
+ at24_setlines(regaddr, 1, (byte >> (7-i))&0x01);
+ at24_setlines(regaddr, 0, (byte >> (7-i))&0x01);
+ }
+}
+
+static int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char addr)
+{
+ if (at24_sendcmd(regaddr, cmd)) {
+ at24_writedatabyte(regaddr, addr);
+ return at24_waitforack(regaddr);
+ }
+ return 0;
+}
+
+static int at24_sendcmd(unsigned long regaddr, unsigned char cmd)
+{
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ at24_start(regaddr);
+ at24_writedatabyte(regaddr, cmd);
+ if (at24_waitforack(regaddr))
+ return 1;
+ }
+ return 0;
+}
+
+static unsigned char at24_readdatabit(unsigned long regaddr)
+{
+ unsigned char val;
+
+ at24_setlines(regaddr, 0, 1);
+ at24_setlines(regaddr, 1, 1);
+ val = (inb(regaddr) & AT24_DATA)?1:0;
+ at24_setlines(regaddr, 1, 1);
+ at24_setlines(regaddr, 0, 1);
+ return val;
+}
+
+static unsigned char at24_readdatabyte(unsigned long regaddr)
+{
+ unsigned char data = 0;
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ data <<= 1;
+ data |= at24_readdatabit(regaddr);
+ }
+
+ return data;
+}
+
+static int at24_waitforack(unsigned long regaddr)
+{
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ if ((at24_readdatabit(regaddr) & 0x01) == 0x00)
+ return 1;
+ }
+ return 0;
+}
+
+static int at24_waitfornack(unsigned long regaddr)
+{
+ int i;
+ for (i = 0; i < 10; i++) {
+ if ((at24_readdatabit(regaddr) & 0x01) == 0x01)
+ return 1;
+ }
+ return 0;
+}
+
+static void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char data)
+{
+ unsigned char val = AT24_ENABLE;
+ if (clock)
+ val |= AT24_CLOCK;
+ if (data)
+ val |= AT24_DATA;
+
+ outb(val, regaddr);
+ tms380tr_wait(20); /* Very necessary. */
+}
+
+static void at24_start(unsigned long regaddr)
+{
+ at24_setlines(regaddr, 0, 1);
+ at24_setlines(regaddr, 1, 1);
+ at24_setlines(regaddr, 1, 0);
+ at24_setlines(regaddr, 0, 1);
+}
+
+static unsigned char at24_readb(unsigned long regaddr, unsigned char addr)
+{
+ unsigned char data = 0xff;
+
+ if (at24_sendfullcmd(regaddr, AT24_WRITE, addr)) {
+ if (at24_sendcmd(regaddr, AT24_READ)) {
+ data = at24_readdatabyte(regaddr);
+ if (!at24_waitfornack(regaddr))
+ data = 0xff;
+ }
+ }
+ return data;
+}
+
+
+/*
+ * Enable basic functions of the Madge chipset needed
+ * for initialization.
+ */
+static void abyss_enable(struct net_device *dev)
+{
+ unsigned char reset_reg;
+ unsigned long ioaddr;
+
+ ioaddr = dev->base_addr;
+ reset_reg = inb(ioaddr + PCIBM2_RESET_REG);
+ reset_reg |= PCIBM2_RESET_REG_CHIP_NRES;
+ outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
+ tms380tr_wait(100);
+}
+
+/*
+ * Enable the functions of the Madge chipset needed for
+ * full working order.
+ */
+static int abyss_chipset_init(struct net_device *dev)
+{
+ unsigned char reset_reg;
+ unsigned long ioaddr;
+
+ ioaddr = dev->base_addr;
+
+ reset_reg = inb(ioaddr + PCIBM2_RESET_REG);
+
+ reset_reg |= PCIBM2_RESET_REG_CHIP_NRES;
+ outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
+
+ reset_reg &= ~(PCIBM2_RESET_REG_CHIP_NRES |
+ PCIBM2_RESET_REG_FIFO_NRES |
+ PCIBM2_RESET_REG_SIF_NRES);
+ outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
+
+ tms380tr_wait(100);
+
+ reset_reg |= PCIBM2_RESET_REG_CHIP_NRES;
+ outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
+
+ reset_reg |= PCIBM2_RESET_REG_SIF_NRES;
+ outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
+
+ reset_reg |= PCIBM2_RESET_REG_FIFO_NRES;
+ outb(reset_reg, ioaddr + PCIBM2_RESET_REG);
+
+ outb(PCIBM2_INT_CONTROL_REG_SINTEN |
+ PCIBM2_INT_CONTROL_REG_PCI_ERR_ENABLE,
+ ioaddr + PCIBM2_INT_CONTROL_REG);
+
+ outb(30, ioaddr + PCIBM2_FIFO_THRESHOLD);
+
+ return 0;
+}
+
+static inline void abyss_chipset_close(struct net_device *dev)
+{
+ unsigned long ioaddr;
+
+ ioaddr = dev->base_addr;
+ outb(0, ioaddr + PCIBM2_RESET_REG);
+}
+
+/*
+ * Read configuration data from the AT24 SEEPROM on Madge cards.
+ *
+ */
+static void abyss_read_eeprom(struct net_device *dev)
+{
+ struct net_local *tp;
+ unsigned long ioaddr;
+ unsigned short val;
+ int i;
+
+ tp = netdev_priv(dev);
+ ioaddr = dev->base_addr;
+
+ /* Must enable glue chip first */
+ abyss_enable(dev);
+
+ val = at24_readb(ioaddr + PCIBM2_SEEPROM_REG,
+ PCIBM2_SEEPROM_RING_SPEED);
+ tp->DataRate = val?SPEED_4:SPEED_16; /* set open speed */
+ printk("%s: SEEPROM: ring speed: %dMb/sec\n", dev->name, tp->DataRate);
+
+ val = at24_readb(ioaddr + PCIBM2_SEEPROM_REG,
+ PCIBM2_SEEPROM_RAM_SIZE) * 128;
+ printk("%s: SEEPROM: adapter RAM: %dkb\n", dev->name, val);
+
+ dev->addr_len = 6;
+ for (i = 0; i < 6; i++)
+ dev->dev_addr[i] = at24_readb(ioaddr + PCIBM2_SEEPROM_REG,
+ PCIBM2_SEEPROM_BIA+i);
+}
+
+static int abyss_open(struct net_device *dev)
+{
+ abyss_chipset_init(dev);
+ tms380tr_open(dev);
+ return 0;
+}
+
+static int abyss_close(struct net_device *dev)
+{
+ tms380tr_close(dev);
+ abyss_chipset_close(dev);
+ return 0;
+}
+
+static void __devexit abyss_detach (struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ if (!dev)
+ BUG();
+ unregister_netdev(dev);
+ release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT);
+ free_irq(dev->irq, dev);
+ tmsdev_term(dev);
+ free_netdev(dev);
+ pci_set_drvdata(pdev, NULL);
+}
+
+static struct pci_driver abyss_driver = {
+ .name = "abyss",
+ .id_table = abyss_pci_tbl,
+ .probe = abyss_attach,
+ .remove = __devexit_p(abyss_detach),
+};
+
+static int __init abyss_init (void)
+{
+ return pci_register_driver(&abyss_driver);
+}
+
+static void __exit abyss_rmmod (void)
+{
+ pci_unregister_driver (&abyss_driver);
+}
+
+module_init(abyss_init);
+module_exit(abyss_rmmod);
+
+
+/*
+ * Local variables:
+ * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c abyss.c"
+ * alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c abyss.c"
+ * c-set-style "K&R"
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/drivers/net/tokenring/abyss.h b/drivers/net/tokenring/abyss.h
new file mode 100644
index 00000000000..0ee6e4f085b
--- /dev/null
+++ b/drivers/net/tokenring/abyss.h
@@ -0,0 +1,58 @@
+/*
+ * abyss.h: Header for the abyss tms380tr module
+ *
+ * Authors:
+ * - Adam Fritzler <mid@auk.cx>
+ */
+
+#ifndef __LINUX_MADGETR_H
+#define __LINUX_MADGETR_H
+
+#ifdef __KERNEL__
+
+/*
+ * For Madge Smart 16/4 PCI Mk2. Since we increment the base address
+ * to get everything correct for the TMS SIF, we do these as negatives
+ * as they fall below the SIF in addressing.
+ */
+#define PCIBM2_INT_STATUS_REG ((short)-15)/* 0x01 */
+#define PCIBM2_INT_CONTROL_REG ((short)-14)/* 0x02 */
+#define PCIBM2_RESET_REG ((short)-12)/* 0x04 */
+#define PCIBM2_SEEPROM_REG ((short)-9) /* 0x07 */
+
+#define PCIBM2_INT_CONTROL_REG_SINTEN 0x02
+#define PCIBM2_INT_CONTROL_REG_PCI_ERR_ENABLE 0x80
+#define PCIBM2_INT_STATUS_REG_PCI_ERR 0x80
+
+#define PCIBM2_RESET_REG_CHIP_NRES 0x01
+#define PCIBM2_RESET_REG_FIFO_NRES 0x02
+#define PCIBM2_RESET_REG_SIF_NRES 0x04
+
+#define PCIBM2_FIFO_THRESHOLD 0x21
+#define PCIBM2_BURST_LENGTH 0x22
+
+/*
+ * Bits in PCIBM2_SEEPROM_REG.
+ */
+#define AT24_ENABLE 0x04
+#define AT24_DATA 0x02
+#define AT24_CLOCK 0x01
+
+/*
+ * AT24 Commands.
+ */
+#define AT24_WRITE 0xA0
+#define AT24_READ 0xA1
+
+/*
+ * Addresses in AT24 SEEPROM.
+ */
+#define PCIBM2_SEEPROM_BIA 0x12
+#define PCIBM2_SEEPROM_RING_SPEED 0x18
+#define PCIBM2_SEEPROM_RAM_SIZE 0x1A
+#define PCIBM2_SEEPROM_HWF1 0x1C
+#define PCIBM2_SEEPROM_HWF2 0x1E
+
+
+#endif /* __KERNEL__ */
+#endif /* __LINUX_MADGETR_H */
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
new file mode 100644
index 00000000000..c098863bdd9
--- /dev/null
+++ b/drivers/net/tokenring/ibmtr.c
@@ -0,0 +1,1987 @@
+/* ibmtr.c: A shared-memory IBM Token Ring 16/4 driver for linux
+ *
+ * Written 1993 by Mark Swanson and Peter De Schrijver.
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * This device driver should work with Any IBM Token Ring Card that does
+ * not use DMA.
+ *
+ * I used Donald Becker's (becker@scyld.com) device driver work
+ * as a base for most of my initial work.
+ *
+ * Changes by Peter De Schrijver
+ * (Peter.Deschrijver@linux.cc.kuleuven.ac.be) :
+ *
+ * + changed name to ibmtr.c in anticipation of other tr boards.
+ * + changed reset code and adapter open code.
+ * + added SAP open code.
+ * + a first attempt to write interrupt, transmit and receive routines.
+ *
+ * Changes by David W. Morris (dwm@shell.portal.com) :
+ * 941003 dwm: - Restructure tok_probe for multiple adapters, devices.
+ * + Add comments, misc reorg for clarity.
+ * + Flatten interrupt handler levels.
+ *
+ * Changes by Farzad Farid (farzy@zen.via.ecp.fr)
+ * and Pascal Andre (andre@chimay.via.ecp.fr) (March 9 1995) :
+ * + multi ring support clean up.
+ * + RFC1042 compliance enhanced.
+ *
+ * Changes by Pascal Andre (andre@chimay.via.ecp.fr) (September 7 1995) :
+ * + bug correction in tr_tx
+ * + removed redundant information display
+ * + some code reworking
+ *
+ * Changes by Michel Lespinasse (walken@via.ecp.fr),
+ * Yann Doussot (doussot@via.ecp.fr) and Pascal Andre (andre@via.ecp.fr)
+ * (February 18, 1996) :
+ * + modified shared memory and mmio access port the driver to
+ * alpha platform (structure access -> readb/writeb)
+ *
+ * Changes by Steve Kipisz (bungy@ibm.net or kipisz@vnet.ibm.com)
+ * (January 18 1996):
+ * + swapped WWOR and WWCR in ibmtr.h
+ * + moved some init code from tok_probe into trdev_init. The
+ * PCMCIA code can call trdev_init to complete initializing
+ * the driver.
+ * + added -DPCMCIA to support PCMCIA
+ * + detecting PCMCIA Card Removal in interrupt handler. If
+ * ISRP is FF, then a PCMCIA card has been removed
+ * 10/2000 Burt needed a new method to avoid crashing the OS
+ *
+ * Changes by Paul Norton (pnorton@cts.com) :
+ * + restructured the READ.LOG logic to prevent the transmit SRB
+ * from being rudely overwritten before the transmit cycle is
+ * complete. (August 15 1996)
+ * + completed multiple adapter support. (November 20 1996)
+ * + implemented csum_partial_copy in tr_rx and increased receive
+ * buffer size and count. Minor fixes. (March 15, 1997)
+ *
+ * Changes by Christopher Turcksin <wabbit@rtfc.demon.co.uk>
+ * + Now compiles ok as a module again.
+ *
+ * Changes by Paul Norton (pnorton@ieee.org) :
+ * + moved the header manipulation code in tr_tx and tr_rx to
+ * net/802/tr.c. (July 12 1997)
+ * + add retry and timeout on open if cable disconnected. (May 5 1998)
+ * + lifted 2000 byte mtu limit. now depends on shared-RAM size.
+ * May 25 1998)
+ * + can't allocate 2k recv buff at 8k shared-RAM. (20 October 1998)
+ *
+ * Changes by Joel Sloan (jjs@c-me.com) :
+ * + disable verbose debug messages by default - to enable verbose
+ * debugging, edit the IBMTR_DEBUG_MESSAGES define below
+ *
+ * Changes by Mike Phillips <phillim@amtrak.com> :
+ * + Added extra #ifdef's to work with new PCMCIA Token Ring Code.
+ * The PCMCIA code now just sets up the card so it can be recognized
+ * by ibmtr_probe. Also checks allocated memory vs. on-board memory
+ * for correct figure to use.
+ *
+ * Changes by Tim Hockin (thockin@isunix.it.ilstu.edu) :
+ * + added spinlocks for SMP sanity (10 March 1999)
+ *
+ * Changes by Jochen Friedrich to enable RFC1469 Option 2 multicasting
+ * i.e. using functional address C0 00 00 04 00 00 to transmit and
+ * receive multicast packets.
+ *
+ * Changes by Mike Sullivan (based on original sram patch by Dave Grothe
+ * to support windowing into on adapter shared ram.
+ * i.e. Use LANAID to setup a PnP configuration with 16K RAM. Paging
+ * will shift this 16K window over the entire available shared RAM.
+ *
+ * Changes by Peter De Schrijver (p2@mind.be) :
+ * + fixed a problem with PCMCIA card removal
+ *
+ * Change by Mike Sullivan et al.:
+ * + added turbo card support. No need to use lanaid to configure
+ * the adapter into isa compatiblity mode.
+ *
+ * Changes by Burt Silverman to allow the computer to behave nicely when
+ * a cable is pulled or not in place, or a PCMCIA card is removed hot.
+ */
+
+/* change the define of IBMTR_DEBUG_MESSAGES to a nonzero value
+in the event that chatty debug messages are desired - jjs 12/30/98 */
+
+#define IBMTR_DEBUG_MESSAGES 0
+
+#include <linux/module.h>
+
+#ifdef PCMCIA /* required for ibmtr_cs.c to build */
+#undef MODULE /* yes, really */
+#undef ENABLE_PAGING
+#else
+#define ENABLE_PAGING 1
+#endif
+
+#define FALSE 0
+#define TRUE (!FALSE)
+
+/* changes the output format of driver initialization */
+#define TR_VERBOSE 0
+
+/* some 95 OS send many non UI frame; this allow removing the warning */
+#define TR_FILTERNONUI 1
+
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/ip.h>
+#include <linux/trdevice.h>
+#include <linux/ibmtr.h>
+
+#include <net/checksum.h>
+
+#include <asm/io.h>
+
+#define DPRINTK(format, args...) printk("%s: " format, dev->name , ## args)
+#define DPRINTD(format, args...) DummyCall("%s: " format, dev->name , ## args)
+
+/* version and credits */
+#ifndef PCMCIA
+static char version[] __initdata =
+ "\nibmtr.c: v1.3.57 8/ 7/94 Peter De Schrijver and Mark Swanson\n"
+ " v2.1.125 10/20/98 Paul Norton <pnorton@ieee.org>\n"
+ " v2.2.0 12/30/98 Joel Sloan <jjs@c-me.com>\n"
+ " v2.2.1 02/08/00 Mike Sullivan <sullivam@us.ibm.com>\n"
+ " v2.2.2 07/27/00 Burt Silverman <burts@us.ibm.com>\n"
+ " v2.4.0 03/01/01 Mike Sullivan <sullivan@us.ibm.com>\n";
+#endif
+
+/* this allows displaying full adapter information */
+
+char *channel_def[] __devinitdata = { "ISA", "MCA", "ISA P&P" };
+
+static char pcchannelid[] __devinitdata = {
+ 0x05, 0x00, 0x04, 0x09,
+ 0x04, 0x03, 0x04, 0x0f,
+ 0x03, 0x06, 0x03, 0x01,
+ 0x03, 0x01, 0x03, 0x00,
+ 0x03, 0x09, 0x03, 0x09,
+ 0x03, 0x00, 0x02, 0x00
+};
+
+static char mcchannelid[] __devinitdata = {
+ 0x04, 0x0d, 0x04, 0x01,
+ 0x05, 0x02, 0x05, 0x03,
+ 0x03, 0x06, 0x03, 0x03,
+ 0x05, 0x08, 0x03, 0x04,
+ 0x03, 0x05, 0x03, 0x01,
+ 0x03, 0x08, 0x02, 0x00
+};
+
+char __devinit *adapter_def(char type)
+{
+ switch (type) {
+ case 0xF: return "PC Adapter | PC Adapter II | Adapter/A";
+ case 0xE: return "16/4 Adapter | 16/4 Adapter/A (long)";
+ case 0xD: return "16/4 Adapter/A (short) | 16/4 ISA-16 Adapter";
+ case 0xC: return "Auto 16/4 Adapter";
+ default: return "adapter (unknown type)";
+ };
+};
+
+#define TRC_INIT 0x01 /* Trace initialization & PROBEs */
+#define TRC_INITV 0x02 /* verbose init trace points */
+unsigned char ibmtr_debug_trace = 0;
+
+static int ibmtr_probe(struct net_device *dev);
+static int ibmtr_probe1(struct net_device *dev, int ioaddr);
+static unsigned char get_sram_size(struct tok_info *adapt_info);
+static int trdev_init(struct net_device *dev);
+static int tok_open(struct net_device *dev);
+static int tok_init_card(struct net_device *dev);
+void tok_open_adapter(unsigned long dev_addr);
+static void open_sap(unsigned char type, struct net_device *dev);
+static void tok_set_multicast_list(struct net_device *dev);
+static int tok_send_packet(struct sk_buff *skb, struct net_device *dev);
+static int tok_close(struct net_device *dev);
+irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void initial_tok_int(struct net_device *dev);
+static void tr_tx(struct net_device *dev);
+static void tr_rx(struct net_device *dev);
+void ibmtr_reset_timer(struct timer_list*tmr,struct net_device *dev);
+static void tok_rerun(unsigned long dev_addr);
+void ibmtr_readlog(struct net_device *dev);
+static struct net_device_stats *tok_get_stats(struct net_device *dev);
+int ibmtr_change_mtu(struct net_device *dev, int mtu);
+static void find_turbo_adapters(int *iolist);
+
+static int ibmtr_portlist[IBMTR_MAX_ADAPTERS+1] __devinitdata = {
+ 0xa20, 0xa24, 0, 0, 0
+};
+static int __devinitdata turbo_io[IBMTR_MAX_ADAPTERS] = {0};
+static int __devinitdata turbo_irq[IBMTR_MAX_ADAPTERS] = {0};
+static int __devinitdata turbo_searched = 0;
+
+#ifndef PCMCIA
+static __u32 ibmtr_mem_base __initdata = 0xd0000;
+#endif
+
+static void __devinit PrtChanID(char *pcid, short stride)
+{
+ short i, j;
+ for (i = 0, j = 0; i < 24; i++, j += stride)
+ printk("%1x", ((int) pcid[j]) & 0x0f);
+ printk("\n");
+}
+
+static void __devinit HWPrtChanID(void __iomem *pcid, short stride)
+{
+ short i, j;
+ for (i = 0, j = 0; i < 24; i++, j += stride)
+ printk("%1x", ((int) readb(pcid + j)) & 0x0f);
+ printk("\n");
+}
+
+/* We have to ioremap every checked address, because isa_readb is
+ * going away.
+ */
+
+static void __devinit find_turbo_adapters(int *iolist)
+{
+ int ram_addr;
+ int index=0;
+ void __iomem *chanid;
+ int found_turbo=0;
+ unsigned char *tchanid, ctemp;
+ int i, j;
+ unsigned long jif;
+ void __iomem *ram_mapped ;
+
+ if (turbo_searched == 1) return;
+ turbo_searched=1;
+ for (ram_addr=0xC0000; ram_addr < 0xE0000; ram_addr+=0x2000) {
+
+ __u32 intf_tbl=0;
+
+ found_turbo=1;
+ ram_mapped = ioremap((u32)ram_addr,0x1fff) ;
+ if (ram_mapped==NULL)
+ continue ;
+ chanid=(CHANNEL_ID + ram_mapped);
+ tchanid=pcchannelid;
+ ctemp=readb(chanid) & 0x0f;
+ if (ctemp != *tchanid) continue;
+ for (i=2,j=1; i<=46; i=i+2,j++) {
+ if ((readb(chanid+i) & 0x0f) != tchanid[j]){
+ found_turbo=0;
+ break;
+ }
+ }
+ if (!found_turbo) continue;
+
+ writeb(0x90, ram_mapped+0x1E01);
+ for(i=2; i<0x0f; i++) {
+ writeb(0x00, ram_mapped+0x1E01+i);
+ }
+ writeb(0x00, ram_mapped+0x1E01);
+ for(jif=jiffies+TR_BUSY_INTERVAL; time_before_eq(jiffies,jif););
+ intf_tbl=ntohs(readw(ram_mapped+ACA_OFFSET+ACA_RW+WRBR_EVEN));
+ if (intf_tbl) {
+#if IBMTR_DEBUG_MESSAGES
+ printk("ibmtr::find_turbo_adapters, Turbo found at "
+ "ram_addr %x\n",ram_addr);
+ printk("ibmtr::find_turbo_adapters, interface_table ");
+ for(i=0; i<6; i++) {
+ printk("%x:",readb(ram_addr+intf_tbl+i));
+ }
+ printk("\n");
+#endif
+ turbo_io[index]=ntohs(readw(ram_mapped+intf_tbl+4));
+ turbo_irq[index]=readb(ram_mapped+intf_tbl+3);
+ outb(0, turbo_io[index] + ADAPTRESET);
+ for(jif=jiffies+TR_RST_TIME;time_before_eq(jiffies,jif););
+ outb(0, turbo_io[index] + ADAPTRESETREL);
+ index++;
+ continue;
+ }
+#if IBMTR_DEBUG_MESSAGES
+ printk("ibmtr::find_turbo_adapters, ibmtr card found at"
+ " %x but not a Turbo model\n",ram_addr);
+#endif
+ iounmap(ram_mapped) ;
+ } /* for */
+ for(i=0; i<IBMTR_MAX_ADAPTERS; i++) {
+ if(!turbo_io[i]) break;
+ for (j=0; j<IBMTR_MAX_ADAPTERS; j++) {
+ if ( iolist[j] && iolist[j] != turbo_io[i]) continue;
+ iolist[j]=turbo_io[i];
+ break;
+ }
+ }
+}
+
+static void ibmtr_cleanup_card(struct net_device *dev)
+{
+ if (dev->base_addr) {
+ outb(0,dev->base_addr+ADAPTRESET);
+
+ schedule_timeout(TR_RST_TIME); /* wait 50ms */
+
+ outb(0,dev->base_addr+ADAPTRESETREL);
+ }
+
+#ifndef PCMCIA
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr, IBMTR_IO_EXTENT);
+
+ {
+ struct tok_info *ti = (struct tok_info *) dev->priv;
+ iounmap(ti->mmio);
+ iounmap(ti->sram_virt);
+ }
+#endif
+}
+
+int ibmtr_probe_card(struct net_device *dev)
+{
+ int err = ibmtr_probe(dev);
+ if (!err) {
+ err = register_netdev(dev);
+ if (err)
+ ibmtr_cleanup_card(dev);
+ }
+ return err;
+}
+
+/****************************************************************************
+ * ibmtr_probe(): Routine specified in the network device structure
+ * to probe for an IBM Token Ring Adapter. Routine outline:
+ * I. Interrogate hardware to determine if an adapter exists
+ * and what the speeds and feeds are
+ * II. Setup data structures to control execution based upon
+ * adapter characteristics.
+ *
+ * We expect ibmtr_probe to be called once for each device entry
+ * which references it.
+ ****************************************************************************/
+
+static int ibmtr_probe(struct net_device *dev)
+{
+ int i;
+ int base_addr = dev->base_addr;
+
+ if (base_addr && base_addr <= 0x1ff) /* Don't probe at all. */
+ return -ENXIO;
+ if (base_addr > 0x1ff) { /* Check a single specified location. */
+ if (!ibmtr_probe1(dev, base_addr)) return 0;
+ return -ENODEV;
+ }
+ find_turbo_adapters(ibmtr_portlist);
+ for (i = 0; ibmtr_portlist[i]; i++) {
+ int ioaddr = ibmtr_portlist[i];
+
+ if (!ibmtr_probe1(dev, ioaddr)) return 0;
+ }
+ return -ENODEV;
+}
+
+/*****************************************************************************/
+
+static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr)
+{
+
+ unsigned char segment, intr=0, irq=0, i, j, cardpresent=NOTOK, temp=0;
+ void __iomem * t_mmio = NULL;
+ struct tok_info *ti = dev->priv;
+ void __iomem *cd_chanid;
+ unsigned char *tchanid, ctemp;
+#ifndef PCMCIA
+ unsigned char t_irq=0;
+ unsigned long timeout;
+ static int version_printed;
+#endif
+
+ /* Query the adapter PIO base port which will return
+ * indication of where MMIO was placed. We also have a
+ * coded interrupt number.
+ */
+ segment = inb(PIOaddr);
+ if (segment < 0x40 || segment > 0xe0) {
+ /* Out of range values so we'll assume non-existent IO device
+ * but this is not necessarily a problem, esp if a turbo
+ * adapter is being used. */
+#if IBMTR_DEBUG_MESSAGES
+ DPRINTK("ibmtr_probe1(): unhappy that inb(0x%X) == 0x%X, "
+ "Hardware Problem?\n",PIOaddr,segment);
+#endif
+ return -ENODEV;
+ }
+ /*
+ * Compute the linear base address of the MMIO area
+ * as LINUX doesn't care about segments
+ */
+ t_mmio = ioremap(((__u32) (segment & 0xfc) << 11) + 0x80000,2048);
+ if (!t_mmio) {
+ DPRINTK("Cannot remap mmiobase memory area") ;
+ return -ENODEV ;
+ }
+ intr = segment & 0x03; /* low bits is coded interrupt # */
+ if (ibmtr_debug_trace & TRC_INIT)
+ DPRINTK("PIOaddr: %4hx seg/intr: %2x mmio base: %p intr: %d\n"
+ , PIOaddr, (int) segment, t_mmio, (int) intr);
+
+ /*
+ * Now we will compare expected 'channelid' strings with
+ * what we is there to learn of ISA/MCA or not TR card
+ */
+#ifdef PCMCIA
+ iounmap(t_mmio);
+ t_mmio = ti->mmio; /*BMS to get virtual address */
+ irq = ti->irq; /*BMS to display the irq! */
+#endif
+ cd_chanid = (CHANNEL_ID + t_mmio); /* for efficiency */
+ tchanid = pcchannelid;
+ cardpresent = TR_ISA; /* try ISA */
+
+ /* Suboptimize knowing first byte different */
+ ctemp = readb(cd_chanid) & 0x0f;
+ if (ctemp != *tchanid) { /* NOT ISA card, try MCA */
+ tchanid = mcchannelid;
+ cardpresent = TR_MCA;
+ if (ctemp != *tchanid) /* Neither ISA nor MCA */
+ cardpresent = NOTOK;
+ }
+ if (cardpresent != NOTOK) {
+ /* Know presumed type, try rest of ID */
+ for (i = 2, j = 1; i <= 46; i = i + 2, j++) {
+ if( (readb(cd_chanid+i)&0x0f) == tchanid[j]) continue;
+ /* match failed, not TR card */
+ cardpresent = NOTOK;
+ break;
+ }
+ }
+ /*
+ * If we have an ISA board check for the ISA P&P version,
+ * as it has different IRQ settings
+ */
+ if (cardpresent == TR_ISA && (readb(AIPFID + t_mmio) == 0x0e))
+ cardpresent = TR_ISAPNP;
+ if (cardpresent == NOTOK) { /* "channel_id" did not match, report */
+ if (!(ibmtr_debug_trace & TRC_INIT)) {
+#ifndef PCMCIA
+ iounmap(t_mmio);
+#endif
+ return -ENODEV;
+ }
+ DPRINTK( "Channel ID string not found for PIOaddr: %4hx\n",
+ PIOaddr);
+ DPRINTK("Expected for ISA: ");
+ PrtChanID(pcchannelid, 1);
+ DPRINTK(" found: ");
+/* BMS Note that this can be misleading, when hardware is flaky, because you
+ are reading it a second time here. So with my flaky hardware, I'll see my-
+ self in this block, with the HW ID matching the ISA ID exactly! */
+ HWPrtChanID(cd_chanid, 2);
+ DPRINTK("Expected for MCA: ");
+ PrtChanID(mcchannelid, 1);
+ }
+ /* Now, setup some of the pl0 buffers for this driver.. */
+ /* If called from PCMCIA, it is already set up, so no need to
+ waste the memory, just use the existing structure */
+#ifndef PCMCIA
+ ti->mmio = t_mmio;
+ for (i = 0; i < IBMTR_MAX_ADAPTERS; i++) {
+ if (turbo_io[i] != PIOaddr)
+ continue;
+#if IBMTR_DEBUG_MESSAGES
+ printk("ibmtr::tr_probe1, setting PIOaddr %x to Turbo\n",
+ PIOaddr);
+#endif
+ ti->turbo = 1;
+ t_irq = turbo_irq[i];
+ }
+#endif /* !PCMCIA */
+ ti->readlog_pending = 0;
+ init_waitqueue_head(&ti->wait_for_reset);
+
+ /* if PCMCIA, the card can be recognized as either TR_ISA or TR_ISAPNP
+ * depending which card is inserted. */
+
+#ifndef PCMCIA
+ switch (cardpresent) {
+ case TR_ISA:
+ if (intr == 0) irq = 9; /* irq2 really is irq9 */
+ if (intr == 1) irq = 3;
+ if (intr == 2) irq = 6;
+ if (intr == 3) irq = 7;
+ ti->adapter_int_enable = PIOaddr + ADAPTINTREL;
+ break;
+ case TR_MCA:
+ if (intr == 0) irq = 9;
+ if (intr == 1) irq = 3;
+ if (intr == 2) irq = 10;
+ if (intr == 3) irq = 11;
+ ti->global_int_enable = 0;
+ ti->adapter_int_enable = 0;
+ ti->sram_phys=(__u32)(inb(PIOaddr+ADAPTRESETREL) & 0xfe) << 12;
+ break;
+ case TR_ISAPNP:
+ if (!t_irq) {
+ if (intr == 0) irq = 9;
+ if (intr == 1) irq = 3;
+ if (intr == 2) irq = 10;
+ if (intr == 3) irq = 11;
+ } else
+ irq=t_irq;
+ timeout = jiffies + TR_SPIN_INTERVAL;
+ while (!readb(ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN)){
+ if (!time_after(jiffies, timeout)) continue;
+ DPRINTK( "Hardware timeout during initialization.\n");
+ iounmap(t_mmio);
+ kfree(ti);
+ return -ENODEV;
+ }
+ ti->sram_phys =
+ ((__u32)readb(ti->mmio+ACA_OFFSET+ACA_RW+RRR_EVEN)<<12);
+ ti->adapter_int_enable = PIOaddr + ADAPTINTREL;
+ break;
+ } /*end switch (cardpresent) */
+#endif /*not PCMCIA */
+
+ if (ibmtr_debug_trace & TRC_INIT) { /* just report int */
+ DPRINTK("irq=%d", irq);
+ printk(", sram_phys=0x%x", ti->sram_phys);
+ if(ibmtr_debug_trace&TRC_INITV){ /* full chat in verbose only */
+ DPRINTK(", ti->mmio=%p", ti->mmio);
+ printk(", segment=%02X", segment);
+ }
+ printk(".\n");
+ }
+
+ /* Get hw address of token ring card */
+ j = 0;
+ for (i = 0; i < 0x18; i = i + 2) {
+ /* technical reference states to do this */
+ temp = readb(ti->mmio + AIP + i) & 0x0f;
+ ti->hw_address[j] = temp;
+ if (j & 1)
+ dev->dev_addr[(j / 2)] =
+ ti->hw_address[j]+ (ti->hw_address[j - 1] << 4);
+ ++j;
+ }
+ /* get Adapter type: 'F' = Adapter/A, 'E' = 16/4 Adapter II,... */
+ ti->adapter_type = readb(ti->mmio + AIPADAPTYPE);
+
+ /* get Data Rate: F=4Mb, E=16Mb, D=4Mb & 16Mb ?? */
+ ti->data_rate = readb(ti->mmio + AIPDATARATE);
+
+ /* Get Early Token Release support?: F=no, E=4Mb, D=16Mb, C=4&16Mb */
+ ti->token_release = readb(ti->mmio + AIPEARLYTOKEN);
+
+ /* How much shared RAM is on adapter ? */
+ if (ti->turbo) {
+ ti->avail_shared_ram=127;
+ } else {
+ ti->avail_shared_ram = get_sram_size(ti);/*in 512 byte units */
+ }
+ /* We need to set or do a bunch of work here based on previous results*/
+ /* Support paging? What sizes?: F=no, E=16k, D=32k, C=16 & 32k */
+ ti->shared_ram_paging = readb(ti->mmio + AIPSHRAMPAGE);
+
+ /* Available DHB 4Mb size: F=2048, E=4096, D=4464 */
+ switch (readb(ti->mmio + AIP4MBDHB)) {
+ case 0xe: ti->dhb_size4mb = 4096; break;
+ case 0xd: ti->dhb_size4mb = 4464; break;
+ default: ti->dhb_size4mb = 2048; break;
+ }
+
+ /* Available DHB 16Mb size: F=2048, E=4096, D=8192, C=16384, B=17960 */
+ switch (readb(ti->mmio + AIP16MBDHB)) {
+ case 0xe: ti->dhb_size16mb = 4096; break;
+ case 0xd: ti->dhb_size16mb = 8192; break;
+ case 0xc: ti->dhb_size16mb = 16384; break;
+ case 0xb: ti->dhb_size16mb = 17960; break;
+ default: ti->dhb_size16mb = 2048; break;
+ }
+
+ /* We must figure out how much shared memory space this adapter
+ * will occupy so that if there are two adapters we can fit both
+ * in. Given a choice, we will limit this adapter to 32K. The
+ * maximum space will will use for two adapters is 64K so if the
+ * adapter we are working on demands 64K (it also doesn't support
+ * paging), then only one adapter can be supported.
+ */
+
+ /*
+ * determine how much of total RAM is mapped into PC space
+ */
+ ti->mapped_ram_size= /*sixteen to onehundredtwentyeight 512byte blocks*/
+ 1<< ((readb(ti->mmio+ACA_OFFSET+ACA_RW+RRR_ODD) >> 2 & 0x03) + 4);
+ ti->page_mask = 0;
+ if (ti->turbo) ti->page_mask=0xf0;
+ else if (ti->shared_ram_paging == 0xf); /* No paging in adapter */
+ else {
+#ifdef ENABLE_PAGING
+ unsigned char pg_size = 0;
+ /* BMS: page size: PCMCIA, use configuration register;
+ ISAPNP, use LANAIDC config tool from www.ibm.com */
+ switch (ti->shared_ram_paging) {
+ case 0xf:
+ break;
+ case 0xe:
+ ti->page_mask = (ti->mapped_ram_size == 32) ? 0xc0 : 0;
+ pg_size = 32; /* 16KB page size */
+ break;
+ case 0xd:
+ ti->page_mask = (ti->mapped_ram_size == 64) ? 0x80 : 0;
+ pg_size = 64; /* 32KB page size */
+ break;
+ case 0xc:
+ switch (ti->mapped_ram_size) {
+ case 32:
+ ti->page_mask = 0xc0;
+ pg_size = 32;
+ break;
+ case 64:
+ ti->page_mask = 0x80;
+ pg_size = 64;
+ break;
+ }
+ break;
+ default:
+ DPRINTK("Unknown shared ram paging info %01X\n",
+ ti->shared_ram_paging);
+ iounmap(t_mmio);
+ kfree(ti);
+ return -ENODEV;
+ break;
+ } /*end switch shared_ram_paging */
+
+ if (ibmtr_debug_trace & TRC_INIT)
+ DPRINTK("Shared RAM paging code: %02X, "
+ "mapped RAM size: %dK, shared RAM size: %dK, "
+ "page mask: %02X\n:",
+ ti->shared_ram_paging, ti->mapped_ram_size / 2,
+ ti->avail_shared_ram / 2, ti->page_mask);
+#endif /*ENABLE_PAGING */
+ }
+
+#ifndef PCMCIA
+ /* finish figuring the shared RAM address */
+ if (cardpresent == TR_ISA) {
+ static __u32 ram_bndry_mask[] =
+ { 0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000 };
+ __u32 new_base, rrr_32, chk_base, rbm;
+
+ rrr_32=readb(ti->mmio+ACA_OFFSET+ACA_RW+RRR_ODD) >> 2 & 0x03;
+ rbm = ram_bndry_mask[rrr_32];
+ new_base = (ibmtr_mem_base + (~rbm)) & rbm;/* up to boundary */
+ chk_base = new_base + (ti->mapped_ram_size << 9);
+ if (chk_base > (ibmtr_mem_base + IBMTR_SHARED_RAM_SIZE)) {
+ DPRINTK("Shared RAM for this adapter (%05x) exceeds "
+ "driver limit (%05x), adapter not started.\n",
+ chk_base, ibmtr_mem_base + IBMTR_SHARED_RAM_SIZE);
+ iounmap(t_mmio);
+ kfree(ti);
+ return -ENODEV;
+ } else { /* seems cool, record what we have figured out */
+ ti->sram_base = new_base >> 12;
+ ibmtr_mem_base = chk_base;
+ }
+ }
+ else ti->sram_base = ti->sram_phys >> 12;
+
+ /* The PCMCIA has already got the interrupt line and the io port,
+ so no chance of anybody else getting it - MLP */
+ if (request_irq(dev->irq = irq, &tok_interrupt, 0, "ibmtr", dev) != 0) {
+ DPRINTK("Could not grab irq %d. Halting Token Ring driver.\n",
+ irq);
+ iounmap(t_mmio);
+ kfree(ti);
+ return -ENODEV;
+ }
+ /*?? Now, allocate some of the PIO PORTs for this driver.. */
+ /* record PIOaddr range as busy */
+ if (!request_region(PIOaddr, IBMTR_IO_EXTENT, "ibmtr")) {
+ DPRINTK("Could not grab PIO range. Halting driver.\n");
+ free_irq(dev->irq, dev);
+ iounmap(t_mmio);
+ kfree(ti);
+ return -EBUSY;
+ }
+
+ if (!version_printed++) {
+ printk(version);
+ }
+#endif /* !PCMCIA */
+ DPRINTK("%s %s found\n",
+ channel_def[cardpresent - 1], adapter_def(ti->adapter_type));
+ DPRINTK("using irq %d, PIOaddr %hx, %dK shared RAM.\n",
+ irq, PIOaddr, ti->mapped_ram_size / 2);
+ DPRINTK("Hardware address : %02X:%02X:%02X:%02X:%02X:%02X\n",
+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+ if (ti->page_mask)
+ DPRINTK("Shared RAM paging enabled. "
+ "Page size: %uK Shared Ram size %dK\n",
+ ((ti->page_mask^0xff)+1) >>2, ti->avail_shared_ram / 2);
+ else
+ DPRINTK("Shared RAM paging disabled. ti->page_mask %x\n",
+ ti->page_mask);
+
+ /* Calculate the maximum DHB we can use */
+ /* two cases where avail_shared_ram doesn't equal mapped_ram_size:
+ 1. avail_shared_ram is 127 but mapped_ram_size is 128 (typical)
+ 2. user has configured adapter for less than avail_shared_ram
+ but is not using paging (she should use paging, I believe)
+ */
+ if (!ti->page_mask) {
+ ti->avail_shared_ram=
+ min(ti->mapped_ram_size,ti->avail_shared_ram);
+ }
+
+ switch (ti->avail_shared_ram) {
+ case 16: /* 8KB shared RAM */
+ ti->dhb_size4mb = min(ti->dhb_size4mb, (unsigned short)2048);
+ ti->rbuf_len4 = 1032;
+ ti->rbuf_cnt4=2;
+ ti->dhb_size16mb = min(ti->dhb_size16mb, (unsigned short)2048);
+ ti->rbuf_len16 = 1032;
+ ti->rbuf_cnt16=2;
+ break;
+ case 32: /* 16KB shared RAM */
+ ti->dhb_size4mb = min(ti->dhb_size4mb, (unsigned short)4464);
+ ti->rbuf_len4 = 1032;
+ ti->rbuf_cnt4=4;
+ ti->dhb_size16mb = min(ti->dhb_size16mb, (unsigned short)4096);
+ ti->rbuf_len16 = 1032; /*1024 usable */
+ ti->rbuf_cnt16=4;
+ break;
+ case 64: /* 32KB shared RAM */
+ ti->dhb_size4mb = min(ti->dhb_size4mb, (unsigned short)4464);
+ ti->rbuf_len4 = 1032;
+ ti->rbuf_cnt4=6;
+ ti->dhb_size16mb = min(ti->dhb_size16mb, (unsigned short)10240);
+ ti->rbuf_len16 = 1032;
+ ti->rbuf_cnt16=6;
+ break;
+ case 127: /* 63.5KB shared RAM */
+ ti->dhb_size4mb = min(ti->dhb_size4mb, (unsigned short)4464);
+ ti->rbuf_len4 = 1032;
+ ti->rbuf_cnt4=6;
+ ti->dhb_size16mb = min(ti->dhb_size16mb, (unsigned short)16384);
+ ti->rbuf_len16 = 1032;
+ ti->rbuf_cnt16=16;
+ break;
+ case 128: /* 64KB shared RAM */
+ ti->dhb_size4mb = min(ti->dhb_size4mb, (unsigned short)4464);
+ ti->rbuf_len4 = 1032;
+ ti->rbuf_cnt4=6;
+ ti->dhb_size16mb = min(ti->dhb_size16mb, (unsigned short)17960);
+ ti->rbuf_len16 = 1032;
+ ti->rbuf_cnt16=16;
+ break;
+ default:
+ ti->dhb_size4mb = 2048;
+ ti->rbuf_len4 = 1032;
+ ti->rbuf_cnt4=2;
+ ti->dhb_size16mb = 2048;
+ ti->rbuf_len16 = 1032;
+ ti->rbuf_cnt16=2;
+ break;
+ }
+ /* this formula is not smart enough for the paging case
+ ti->rbuf_cnt<x> = (ti->avail_shared_ram * BLOCKSZ - ADAPT_PRIVATE -
+ ARBLENGTH - SSBLENGTH - DLC_MAX_SAP * SAPLENGTH -
+ DLC_MAX_STA * STALENGTH - ti->dhb_size<x>mb * NUM_DHB -
+ SRBLENGTH - ASBLENGTH) / ti->rbuf_len<x>;
+ */
+ ti->maxmtu16 = (ti->rbuf_len16 - 8) * ti->rbuf_cnt16 - TR_HLEN;
+ ti->maxmtu4 = (ti->rbuf_len4 - 8) * ti->rbuf_cnt4 - TR_HLEN;
+ /*BMS assuming 18 bytes of Routing Information (usually works) */
+ DPRINTK("Maximum Receive Internet Protocol MTU 16Mbps: %d, 4Mbps: %d\n",
+ ti->maxmtu16, ti->maxmtu4);
+
+ dev->base_addr = PIOaddr; /* set the value for device */
+ dev->mem_start = ti->sram_base << 12;
+ dev->mem_end = dev->mem_start + (ti->mapped_ram_size << 9) - 1;
+ trdev_init(dev);
+ return 0; /* Return 0 to indicate we have found a Token Ring card. */
+} /*ibmtr_probe1() */
+
+/*****************************************************************************/
+
+/* query the adapter for the size of shared RAM */
+/* the function returns the RAM size in units of 512 bytes */
+
+static unsigned char __devinit get_sram_size(struct tok_info *adapt_info)
+{
+ unsigned char avail_sram_code;
+ static unsigned char size_code[] = { 0, 16, 32, 64, 127, 128 };
+ /* Adapter gives
+ 'F' -- use RRR bits 3,2
+ 'E' -- 8kb 'D' -- 16kb
+ 'C' -- 32kb 'A' -- 64KB
+ 'B' - 64KB less 512 bytes at top
+ (WARNING ... must zero top bytes in INIT */
+
+ avail_sram_code = 0xf - readb(adapt_info->mmio + AIPAVAILSHRAM);
+ if (avail_sram_code) return size_code[avail_sram_code];
+ else /* for code 'F', must compute size from RRR(3,2) bits */
+ return 1 <<
+ ((readb(adapt_info->mmio+ACA_OFFSET+ACA_RW+RRR_ODD)>>2&3)+4);
+}
+
+/*****************************************************************************/
+
+static int __devinit trdev_init(struct net_device *dev)
+{
+ struct tok_info *ti = (struct tok_info *) dev->priv;
+
+ SET_PAGE(ti->srb_page);
+ ti->open_failure = NO ;
+ dev->open = tok_open;
+ dev->stop = tok_close;
+ dev->hard_start_xmit = tok_send_packet;
+ dev->get_stats = tok_get_stats;
+ dev->set_multicast_list = tok_set_multicast_list;
+ dev->change_mtu = ibmtr_change_mtu;
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+static int tok_init_card(struct net_device *dev)
+{
+ struct tok_info *ti;
+ short PIOaddr;
+ unsigned long i;
+
+ PIOaddr = dev->base_addr;
+ ti = (struct tok_info *) dev->priv;
+ /* Special processing for first interrupt after reset */
+ ti->do_tok_int = FIRST_INT;
+ /* Reset adapter */
+ writeb(~INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN);
+ outb(0, PIOaddr + ADAPTRESET);
+
+ current->state=TASK_UNINTERRUPTIBLE;
+ schedule_timeout(TR_RST_TIME); /* wait 50ms */
+
+ outb(0, PIOaddr + ADAPTRESETREL);
+#ifdef ENABLE_PAGING
+ if (ti->page_mask)
+ writeb(SRPR_ENABLE_PAGING,ti->mmio+ACA_OFFSET+ACA_RW+SRPR_EVEN);
+#endif
+ writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN);
+ i = sleep_on_timeout(&ti->wait_for_reset, 4 * HZ);
+ return i? 0 : -EAGAIN;
+}
+
+/*****************************************************************************/
+static int tok_open(struct net_device *dev)
+{
+ struct tok_info *ti = (struct tok_info *) dev->priv;
+ int i;
+
+ /*the case we were left in a failure state during a previous open */
+ if (ti->open_failure == YES) {
+ DPRINTK("Last time you were disconnected, how about now?\n");
+ printk("You can't insert with an ICS connector half-cocked.\n");
+ }
+
+ ti->open_status = CLOSED; /* CLOSED or OPEN */
+ ti->sap_status = CLOSED; /* CLOSED or OPEN */
+ ti->open_failure = NO; /* NO or YES */
+ ti->open_mode = MANUAL; /* MANUAL or AUTOMATIC */
+ /* 12/2000 not typical Linux, but we can use RUNNING to let us know when
+ the network has crapped out or cables are disconnected. Useful because
+ the IFF_UP flag stays up the whole time, until ifconfig tr0 down.
+ */
+ dev->flags &= ~IFF_RUNNING;
+
+ ti->sram_phys &= ~1; /* to reverse what we do in tok_close */
+ /* init the spinlock */
+ spin_lock_init(&ti->lock);
+ init_timer(&ti->tr_timer);
+
+ i = tok_init_card(dev);
+ if (i) return i;
+
+ while (1){
+ tok_open_adapter((unsigned long) dev);
+ i= interruptible_sleep_on_timeout(&ti->wait_for_reset, 25 * HZ);
+ /* sig catch: estimate opening adapter takes more than .5 sec*/
+ if (i>(245*HZ)/10) break; /* fancier than if (i==25*HZ) */
+ if (i==0) break;
+ if (ti->open_status == OPEN && ti->sap_status==OPEN) {
+ netif_start_queue(dev);
+ DPRINTK("Adapter is up and running\n");
+ return 0;
+ }
+ current->state=TASK_INTERRUPTIBLE;
+ i=schedule_timeout(TR_RETRY_INTERVAL); /* wait 30 seconds */
+ if(i!=0) break; /*prob. a signal, like the i>24*HZ case above */
+ }
+ outb(0, dev->base_addr + ADAPTRESET);/* kill pending interrupts*/
+ DPRINTK("TERMINATED via signal\n"); /*BMS useful */
+ return -EAGAIN;
+}
+
+/*****************************************************************************/
+
+#define COMMAND_OFST 0
+#define OPEN_OPTIONS_OFST 8
+#define NUM_RCV_BUF_OFST 24
+#define RCV_BUF_LEN_OFST 26
+#define DHB_LENGTH_OFST 28
+#define NUM_DHB_OFST 30
+#define DLC_MAX_SAP_OFST 32
+#define DLC_MAX_STA_OFST 33
+
+void tok_open_adapter(unsigned long dev_addr)
+{
+ struct net_device *dev = (struct net_device *) dev_addr;
+ struct tok_info *ti;
+ int i;
+
+ ti = (struct tok_info *) dev->priv;
+ SET_PAGE(ti->init_srb_page);
+ writeb(~SRB_RESP_INT, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD);
+ for (i = 0; i < sizeof(struct dir_open_adapter); i++)
+ writeb(0, ti->init_srb + i);
+ writeb(DIR_OPEN_ADAPTER, ti->init_srb + COMMAND_OFST);
+ writew(htons(OPEN_PASS_BCON_MAC), ti->init_srb + OPEN_OPTIONS_OFST);
+ if (ti->ring_speed == 16) {
+ writew(htons(ti->dhb_size16mb), ti->init_srb + DHB_LENGTH_OFST);
+ writew(htons(ti->rbuf_cnt16), ti->init_srb + NUM_RCV_BUF_OFST);
+ writew(htons(ti->rbuf_len16), ti->init_srb + RCV_BUF_LEN_OFST);
+ } else {
+ writew(htons(ti->dhb_size4mb), ti->init_srb + DHB_LENGTH_OFST);
+ writew(htons(ti->rbuf_cnt4), ti->init_srb + NUM_RCV_BUF_OFST);
+ writew(htons(ti->rbuf_len4), ti->init_srb + RCV_BUF_LEN_OFST);
+ }
+ writeb(NUM_DHB, /* always 2 */ ti->init_srb + NUM_DHB_OFST);
+ writeb(DLC_MAX_SAP, ti->init_srb + DLC_MAX_SAP_OFST);
+ writeb(DLC_MAX_STA, ti->init_srb + DLC_MAX_STA_OFST);
+ ti->srb = ti->init_srb; /* We use this one in the interrupt handler */
+ ti->srb_page = ti->init_srb_page;
+ DPRINTK("Opening adapter: Xmit bfrs: %d X %d, Rcv bfrs: %d X %d\n",
+ readb(ti->init_srb + NUM_DHB_OFST),
+ ntohs(readw(ti->init_srb + DHB_LENGTH_OFST)),
+ ntohs(readw(ti->init_srb + NUM_RCV_BUF_OFST)),
+ ntohs(readw(ti->init_srb + RCV_BUF_LEN_OFST)));
+ writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN);
+ writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
+}
+
+/*****************************************************************************/
+
+static void open_sap(unsigned char type, struct net_device *dev)
+{
+ int i;
+ struct tok_info *ti = (struct tok_info *) dev->priv;
+
+ SET_PAGE(ti->srb_page);
+ for (i = 0; i < sizeof(struct dlc_open_sap); i++)
+ writeb(0, ti->srb + i);
+
+#define MAX_I_FIELD_OFST 14
+#define SAP_VALUE_OFST 16
+#define SAP_OPTIONS_OFST 17
+#define STATION_COUNT_OFST 18
+
+ writeb(DLC_OPEN_SAP, ti->srb + COMMAND_OFST);
+ writew(htons(MAX_I_FIELD), ti->srb + MAX_I_FIELD_OFST);
+ writeb(SAP_OPEN_IND_SAP | SAP_OPEN_PRIORITY, ti->srb+ SAP_OPTIONS_OFST);
+ writeb(SAP_OPEN_STATION_CNT, ti->srb + STATION_COUNT_OFST);
+ writeb(type, ti->srb + SAP_VALUE_OFST);
+ writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
+}
+
+
+/*****************************************************************************/
+
+static void tok_set_multicast_list(struct net_device *dev)
+{
+ struct tok_info *ti = (struct tok_info *) dev->priv;
+ struct dev_mc_list *mclist;
+ unsigned char address[4];
+
+ int i;
+
+ /*BMS the next line is CRUCIAL or you may be sad when you */
+ /*BMS ifconfig tr down or hot unplug a PCMCIA card ??hownowbrowncow*/
+ if (/*BMSHELPdev->start == 0 ||*/ ti->open_status != OPEN) return;
+ address[0] = address[1] = address[2] = address[3] = 0;
+ mclist = dev->mc_list;
+ for (i = 0; i < dev->mc_count; i++) {
+ address[0] |= mclist->dmi_addr[2];
+ address[1] |= mclist->dmi_addr[3];
+ address[2] |= mclist->dmi_addr[4];
+ address[3] |= mclist->dmi_addr[5];
+ mclist = mclist->next;
+ }
+ SET_PAGE(ti->srb_page);
+ for (i = 0; i < sizeof(struct srb_set_funct_addr); i++)
+ writeb(0, ti->srb + i);
+
+#define FUNCT_ADDRESS_OFST 6
+
+ writeb(DIR_SET_FUNC_ADDR, ti->srb + COMMAND_OFST);
+ for (i = 0; i < 4; i++)
+ writeb(address[i], ti->srb + FUNCT_ADDRESS_OFST + i);
+ writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
+#if TR_VERBOSE
+ DPRINTK("Setting functional address: ");
+ for (i=0;i<4;i++) printk("%02X ", address[i]);
+ printk("\n");
+#endif
+}
+
+/*****************************************************************************/
+
+#define STATION_ID_OFST 4
+
+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;
+
+ 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;
+ SET_PAGE(ti->srb_page);
+ writeb(XMIT_UI_FRAME, ti->srb + COMMAND_OFST);
+ writew(ti->exsap_station_id, ti->srb + STATION_ID_OFST);
+ writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
+ spin_unlock_irqrestore(&(ti->lock), flags);
+ dev->trans_start = jiffies;
+ return 0;
+}
+
+/*****************************************************************************/
+
+static int tok_close(struct net_device *dev)
+{
+ struct tok_info *ti = (struct tok_info *) dev->priv;
+
+ /* Important for PCMCIA hot unplug, otherwise, we'll pull the card, */
+ /* unloading the module from memory, and then if a timer pops, ouch */
+ del_timer_sync(&ti->tr_timer);
+ outb(0, dev->base_addr + ADAPTRESET);
+ ti->sram_phys |= 1;
+ ti->open_status = CLOSED;
+
+ netif_stop_queue(dev);
+ DPRINTK("Adapter is closed.\n");
+ return 0;
+}
+
+/*****************************************************************************/
+
+#define RETCODE_OFST 2
+#define OPEN_ERROR_CODE_OFST 6
+#define ASB_ADDRESS_OFST 8
+#define SRB_ADDRESS_OFST 10
+#define ARB_ADDRESS_OFST 12
+#define SSB_ADDRESS_OFST 14
+
+static char *printphase[]= {"Lobe media test","Physical insertion",
+ "Address verification","Roll call poll","Request Parameters"};
+static char *printerror[]={"Function failure","Signal loss","Reserved",
+ "Frequency error","Timeout","Ring failure","Ring beaconing",
+ "Duplicate node address",
+ "Parameter request-retry count exceeded","Remove received",
+ "IMPL force received","Duplicate modifier",
+ "No monitor detected","Monitor contention failed for RPL"};
+
+static void __iomem *map_address(struct tok_info *ti, unsigned index, __u8 *page)
+{
+ if (ti->page_mask) {
+ *page = (index >> 8) & ti->page_mask;
+ index &= ~(ti->page_mask << 8);
+ }
+ return ti->sram_virt + index;
+}
+
+void dir_open_adapter (struct net_device *dev)
+{
+ struct tok_info *ti = (struct tok_info *) dev->priv;
+ unsigned char ret_code;
+ __u16 err;
+
+ ti->srb = map_address(ti,
+ ntohs(readw(ti->init_srb + SRB_ADDRESS_OFST)),
+ &ti->srb_page);
+ ti->ssb = map_address(ti,
+ ntohs(readw(ti->init_srb + SSB_ADDRESS_OFST)),
+ &ti->ssb_page);
+ ti->arb = map_address(ti,
+ ntohs(readw(ti->init_srb + ARB_ADDRESS_OFST)),
+ &ti->arb_page);
+ ti->asb = map_address(ti,
+ ntohs(readw(ti->init_srb + ASB_ADDRESS_OFST)),
+ &ti->asb_page);
+ ti->current_skb = NULL;
+ ret_code = readb(ti->init_srb + RETCODE_OFST);
+ err = ntohs(readw(ti->init_srb + OPEN_ERROR_CODE_OFST));
+ if (!ret_code) {
+ ti->open_status = OPEN; /* TR adapter is now available */
+ if (ti->open_mode == AUTOMATIC) {
+ DPRINTK("Adapter reopened.\n");
+ }
+ writeb(~SRB_RESP_INT, ti->mmio+ACA_OFFSET+ACA_RESET+ISRP_ODD);
+ open_sap(EXTENDED_SAP, dev);
+ return;
+ }
+ ti->open_failure = YES;
+ if (ret_code == 7){
+ if (err == 0x24) {
+ if (!ti->auto_speedsave) {
+ DPRINTK("Open failed: Adapter speed must match "
+ "ring speed if Automatic Ring Speed Save is "
+ "disabled.\n");
+ ti->open_action = FAIL;
+ }else
+ DPRINTK("Retrying open to adjust to "
+ "ring speed, ");
+ } else if (err == 0x2d) {
+ DPRINTK("Physical Insertion: No Monitor Detected, ");
+ printk("retrying after %ds delay...\n",
+ TR_RETRY_INTERVAL/HZ);
+ } else if (err == 0x11) {
+ DPRINTK("Lobe Media Function Failure (0x11), ");
+ printk(" retrying after %ds delay...\n",
+ TR_RETRY_INTERVAL/HZ);
+ } else {
+ char **prphase = printphase;
+ char **prerror = printerror;
+ DPRINTK("TR Adapter misc open failure, error code = ");
+ printk("0x%x, Phase: %s, Error: %s\n",
+ err, prphase[err/16 -1], prerror[err%16 -1]);
+ printk(" retrying after %ds delay...\n",
+ TR_RETRY_INTERVAL/HZ);
+ }
+ } else DPRINTK("open failed: ret_code = %02X..., ", ret_code);
+ if (ti->open_action != FAIL) {
+ if (ti->open_mode==AUTOMATIC){
+ ti->open_action = REOPEN;
+ ibmtr_reset_timer(&(ti->tr_timer), dev);
+ return;
+ }
+ wake_up(&ti->wait_for_reset);
+ return;
+ }
+ DPRINTK("FAILURE, CAPUT\n");
+}
+
+/******************************************************************************/
+
+irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned char status;
+ /* unsigned char status_even ; */
+ struct tok_info *ti;
+ struct net_device *dev;
+#ifdef ENABLE_PAGING
+ unsigned char save_srpr;
+#endif
+
+ dev = dev_id;
+#if TR_VERBOSE
+ DPRINTK("Int from tok_driver, dev : %p irq%d regs=%p\n", dev,irq,regs);
+#endif
+ ti = (struct tok_info *) dev->priv;
+ if (ti->sram_phys & 1)
+ return IRQ_NONE; /* PCMCIA card extraction flag */
+ spin_lock(&(ti->lock));
+#ifdef ENABLE_PAGING
+ save_srpr = readb(ti->mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN);
+#endif
+
+ /* Disable interrupts till processing is finished */
+ writeb((~INT_ENABLE), ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN);
+
+ /* Reset interrupt for ISA boards */
+ if (ti->adapter_int_enable)
+ outb(0, ti->adapter_int_enable);
+ else /* used for PCMCIA cards */
+ outb(0, ti->global_int_enable);
+ if (ti->do_tok_int == FIRST_INT){
+ initial_tok_int(dev);
+#ifdef ENABLE_PAGING
+ writeb(save_srpr, ti->mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN);
+#endif
+ spin_unlock(&(ti->lock));
+ return IRQ_HANDLED;
+ }
+ /* Begin interrupt handler HERE inline to avoid the extra
+ levels of logic and call depth for the original solution. */
+ status = readb(ti->mmio + ACA_OFFSET + ACA_RW + ISRP_ODD);
+ /*BMSstatus_even = readb (ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN) */
+ /*BMSdebugprintk("tok_interrupt: ISRP_ODD = 0x%x ISRP_EVEN = 0x%x\n", */
+ /*BMS status,status_even); */
+
+ if (status & ADAP_CHK_INT) {
+ int i;
+ void __iomem *check_reason;
+ __u8 check_reason_page = 0;
+ check_reason = map_address(ti,
+ ntohs(readw(ti->mmio+ ACA_OFFSET+ACA_RW + WWCR_EVEN)),
+ &check_reason_page);
+ SET_PAGE(check_reason_page);
+
+ DPRINTK("Adapter check interrupt\n");
+ DPRINTK("8 reason bytes follow: ");
+ for (i = 0; i < 8; i++, check_reason++)
+ printk("%02X ", (int) readb(check_reason));
+ printk("\n");
+ writeb(~ADAP_CHK_INT, ti->mmio+ ACA_OFFSET+ACA_RESET+ ISRP_ODD);
+ status = readb(ti->mmio + ACA_OFFSET + ACA_RW + ISRA_EVEN);
+ DPRINTK("ISRA_EVEN == 0x02%x\n",status);
+ ti->open_status = CLOSED;
+ ti->sap_status = CLOSED;
+ ti->open_mode = AUTOMATIC;
+ dev->flags &= ~IFF_RUNNING;
+ netif_stop_queue(dev);
+ ti->open_action = RESTART;
+ outb(0, dev->base_addr + ADAPTRESET);
+ ibmtr_reset_timer(&(ti->tr_timer), dev);/*BMS try to reopen*/
+ spin_unlock(&(ti->lock));
+ return IRQ_HANDLED;
+ }
+ if (readb(ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN)
+ & (TCR_INT | ERR_INT | ACCESS_INT)) {
+ DPRINTK("adapter error: ISRP_EVEN : %02x\n",
+ (int)readb(ti->mmio+ ACA_OFFSET + ACA_RW + ISRP_EVEN));
+ writeb(~(TCR_INT | ERR_INT | ACCESS_INT),
+ ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN);
+ status= readb(ti->mmio+ ACA_OFFSET + ACA_RW + ISRA_EVEN);/*BMS*/
+ DPRINTK("ISRA_EVEN == 0x02%x\n",status);/*BMS*/
+ writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN);
+#ifdef ENABLE_PAGING
+ writeb(save_srpr, ti->mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN);
+#endif
+ spin_unlock(&(ti->lock));
+ return IRQ_HANDLED;
+ }
+ if (status & SRB_RESP_INT) { /* SRB response */
+ SET_PAGE(ti->srb_page);
+#if TR_VERBOSE
+ DPRINTK("SRB resp: cmd=%02X rsp=%02X\n",
+ readb(ti->srb), readb(ti->srb + RETCODE_OFST));
+#endif
+ switch (readb(ti->srb)) { /* SRB command check */
+ case XMIT_DIR_FRAME:{
+ unsigned char xmit_ret_code;
+ xmit_ret_code = readb(ti->srb + RETCODE_OFST);
+ if (xmit_ret_code == 0xff) break;
+ DPRINTK("error on xmit_dir_frame request: %02X\n",
+ xmit_ret_code);
+ if (ti->current_skb) {
+ dev_kfree_skb_irq(ti->current_skb);
+ ti->current_skb = NULL;
+ }
+ /*dev->tbusy = 0;*/
+ netif_wake_queue(dev);
+ if (ti->readlog_pending)
+ ibmtr_readlog(dev);
+ break;
+ }
+ case XMIT_UI_FRAME:{
+ unsigned char xmit_ret_code;
+
+ xmit_ret_code = readb(ti->srb + RETCODE_OFST);
+ if (xmit_ret_code == 0xff) break;
+ DPRINTK("error on xmit_ui_frame request: %02X\n",
+ xmit_ret_code);
+ if (ti->current_skb) {
+ dev_kfree_skb_irq(ti->current_skb);
+ ti->current_skb = NULL;
+ }
+ netif_wake_queue(dev);
+ if (ti->readlog_pending)
+ ibmtr_readlog(dev);
+ break;
+ }
+ case DIR_OPEN_ADAPTER:
+ dir_open_adapter(dev);
+ break;
+ case DLC_OPEN_SAP:
+ if (readb(ti->srb + RETCODE_OFST)) {
+ DPRINTK("open_sap failed: ret_code = %02X, "
+ "retrying\n",
+ (int) readb(ti->srb + RETCODE_OFST));
+ ti->open_action = REOPEN;
+ ibmtr_reset_timer(&(ti->tr_timer), dev);
+ break;
+ }
+ ti->exsap_station_id = readw(ti->srb + STATION_ID_OFST);
+ ti->sap_status = OPEN;/* TR adapter is now available */
+ if (ti->open_mode==MANUAL){
+ wake_up(&ti->wait_for_reset);
+ break;
+ }
+ netif_wake_queue(dev);
+ dev->flags |= IFF_RUNNING;/*BMS 12/2000*/
+ break;
+ case DIR_INTERRUPT:
+ case DIR_MOD_OPEN_PARAMS:
+ case DIR_SET_GRP_ADDR:
+ case DIR_SET_FUNC_ADDR:
+ case DLC_CLOSE_SAP:
+ if (readb(ti->srb + RETCODE_OFST))
+ DPRINTK("error on %02X: %02X\n",
+ (int) readb(ti->srb + COMMAND_OFST),
+ (int) readb(ti->srb + RETCODE_OFST));
+ break;
+ case DIR_READ_LOG:
+ if (readb(ti->srb + RETCODE_OFST)){
+ DPRINTK("error on dir_read_log: %02X\n",
+ (int) readb(ti->srb + RETCODE_OFST));
+ netif_wake_queue(dev);
+ break;
+ }
+#if IBMTR_DEBUG_MESSAGES
+
+#define LINE_ERRORS_OFST 0
+#define INTERNAL_ERRORS_OFST 1
+#define BURST_ERRORS_OFST 2
+#define AC_ERRORS_OFST 3
+#define ABORT_DELIMITERS_OFST 4
+#define LOST_FRAMES_OFST 6
+#define RECV_CONGEST_COUNT_OFST 7
+#define FRAME_COPIED_ERRORS_OFST 8
+#define FREQUENCY_ERRORS_OFST 9
+#define TOKEN_ERRORS_OFST 10
+
+ DPRINTK("Line errors %02X, Internal errors %02X, "
+ "Burst errors %02X\n" "A/C errors %02X, "
+ "Abort delimiters %02X, Lost frames %02X\n"
+ "Receive congestion count %02X, "
+ "Frame copied errors %02X\nFrequency errors %02X, "
+ "Token errors %02X\n",
+ (int) readb(ti->srb + LINE_ERRORS_OFST),
+ (int) readb(ti->srb + INTERNAL_ERRORS_OFST),
+ (int) readb(ti->srb + BURST_ERRORS_OFST),
+ (int) readb(ti->srb + AC_ERRORS_OFST),
+ (int) readb(ti->srb + ABORT_DELIMITERS_OFST),
+ (int) readb(ti->srb + LOST_FRAMES_OFST),
+ (int) readb(ti->srb + RECV_CONGEST_COUNT_OFST),
+ (int) readb(ti->srb + FRAME_COPIED_ERRORS_OFST),
+ (int) readb(ti->srb + FREQUENCY_ERRORS_OFST),
+ (int) readb(ti->srb + TOKEN_ERRORS_OFST));
+#endif
+ netif_wake_queue(dev);
+ break;
+ default:
+ DPRINTK("Unknown command %02X encountered\n",
+ (int) readb(ti->srb));
+ } /* end switch SRB command check */
+ writeb(~SRB_RESP_INT, ti->mmio+ ACA_OFFSET+ACA_RESET+ ISRP_ODD);
+ } /* if SRB response */
+ if (status & ASB_FREE_INT) { /* ASB response */
+ SET_PAGE(ti->asb_page);
+#if TR_VERBOSE
+ DPRINTK("ASB resp: cmd=%02X\n", readb(ti->asb));
+#endif
+
+ switch (readb(ti->asb)) { /* ASB command check */
+ case REC_DATA:
+ case XMIT_UI_FRAME:
+ case XMIT_DIR_FRAME:
+ break;
+ default:
+ DPRINTK("unknown command in asb %02X\n",
+ (int) readb(ti->asb));
+ } /* switch ASB command check */
+ if (readb(ti->asb + 2) != 0xff) /* checks ret_code */
+ DPRINTK("ASB error %02X in cmd %02X\n",
+ (int) readb(ti->asb + 2), (int) readb(ti->asb));
+ writeb(~ASB_FREE_INT, ti->mmio+ ACA_OFFSET+ACA_RESET+ ISRP_ODD);
+ } /* if ASB response */
+
+#define STATUS_OFST 6
+#define NETW_STATUS_OFST 6
+
+ if (status & ARB_CMD_INT) { /* ARB response */
+ SET_PAGE(ti->arb_page);
+#if TR_VERBOSE
+ DPRINTK("ARB resp: cmd=%02X\n", readb(ti->arb));
+#endif
+
+ switch (readb(ti->arb)) { /* ARB command check */
+ case DLC_STATUS:
+ DPRINTK("DLC_STATUS new status: %02X on station %02X\n",
+ ntohs(readw(ti->arb + STATUS_OFST)),
+ ntohs(readw(ti->arb+ STATION_ID_OFST)));
+ break;
+ case REC_DATA:
+ tr_rx(dev);
+ break;
+ case RING_STAT_CHANGE:{
+ unsigned short ring_status;
+ ring_status= ntohs(readw(ti->arb + NETW_STATUS_OFST));
+ if (ibmtr_debug_trace & TRC_INIT)
+ DPRINTK("Ring Status Change...(0x%x)\n",
+ ring_status);
+ if(ring_status& (REMOVE_RECV|AUTO_REMOVAL|LOBE_FAULT)){
+ netif_stop_queue(dev);
+ dev->flags &= ~IFF_RUNNING;/*not typical Linux*/
+ DPRINTK("Remove received, or Auto-removal error"
+ ", or Lobe fault\n");
+ DPRINTK("We'll try to reopen the closed adapter"
+ " after a %d second delay.\n",
+ TR_RETRY_INTERVAL/HZ);
+ /*I was confused: I saw the TR reopening but */
+ /*forgot:with an RJ45 in an RJ45/ICS adapter */
+ /*but adapter not in the ring, the TR will */
+ /* open, and then soon close and come here. */
+ ti->open_mode = AUTOMATIC;
+ ti->open_status = CLOSED; /*12/2000 BMS*/
+ ti->open_action = REOPEN;
+ ibmtr_reset_timer(&(ti->tr_timer), dev);
+ } else if (ring_status & LOG_OVERFLOW) {
+ if(netif_queue_stopped(dev))
+ ti->readlog_pending = 1;
+ else
+ ibmtr_readlog(dev);
+ }
+ break;
+ }
+ case XMIT_DATA_REQ:
+ tr_tx(dev);
+ break;
+ default:
+ DPRINTK("Unknown command %02X in arb\n",
+ (int) readb(ti->arb));
+ break;
+ } /* switch ARB command check */
+ writeb(~ARB_CMD_INT, ti->mmio+ ACA_OFFSET+ACA_RESET + ISRP_ODD);
+ writeb(ARB_FREE, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
+ } /* if ARB response */
+ if (status & SSB_RESP_INT) { /* SSB response */
+ unsigned char retcode;
+ SET_PAGE(ti->ssb_page);
+#if TR_VERBOSE
+ DPRINTK("SSB resp: cmd=%02X rsp=%02X\n",
+ readb(ti->ssb), readb(ti->ssb + 2));
+#endif
+
+ switch (readb(ti->ssb)) { /* SSB command check */
+ case XMIT_DIR_FRAME:
+ case XMIT_UI_FRAME:
+ retcode = readb(ti->ssb + 2);
+ if (retcode && (retcode != 0x22))/* checks ret_code */
+ DPRINTK("xmit ret_code: %02X xmit error code: "
+ "%02X\n",
+ (int)retcode, (int)readb(ti->ssb + 6));
+ else
+ ti->tr_stats.tx_packets++;
+ break;
+ case XMIT_XID_CMD:
+ DPRINTK("xmit xid ret_code: %02X\n",
+ (int) readb(ti->ssb + 2));
+ default:
+ DPRINTK("Unknown command %02X in ssb\n",
+ (int) readb(ti->ssb));
+ } /* SSB command check */
+ writeb(~SSB_RESP_INT, ti->mmio+ ACA_OFFSET+ACA_RESET+ ISRP_ODD);
+ writeb(SSB_FREE, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
+ } /* if SSB response */
+#ifdef ENABLE_PAGING
+ writeb(save_srpr, ti->mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN);
+#endif
+ writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN);
+ spin_unlock(&(ti->lock));
+ return IRQ_HANDLED;
+} /*tok_interrupt */
+
+/*****************************************************************************/
+
+#define INIT_STATUS_OFST 1
+#define INIT_STATUS_2_OFST 2
+#define ENCODED_ADDRESS_OFST 8
+
+static void initial_tok_int(struct net_device *dev)
+{
+
+ __u32 encoded_addr, hw_encoded_addr;
+ struct tok_info *ti;
+ unsigned char init_status; /*BMS 12/2000*/
+
+ ti = (struct tok_info *) dev->priv;
+
+ ti->do_tok_int = NOT_FIRST;
+
+ /* we assign the shared-ram address for ISA devices */
+ writeb(ti->sram_base, ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN);
+#ifndef PCMCIA
+ ti->sram_virt = ioremap(((__u32)ti->sram_base << 12), ti->avail_shared_ram);
+#endif
+ ti->init_srb = map_address(ti,
+ ntohs(readw(ti->mmio + ACA_OFFSET + WRBR_EVEN)),
+ &ti->init_srb_page);
+ if (ti->page_mask && ti->avail_shared_ram == 127) {
+ void __iomem *last_512;
+ __u8 last_512_page=0;
+ int i;
+ last_512 = map_address(ti, 0xfe00, &last_512_page);
+ /* initialize high section of ram (if necessary) */
+ SET_PAGE(last_512_page);
+ for (i = 0; i < 512; i++)
+ writeb(0, last_512 + i);
+ }
+ SET_PAGE(ti->init_srb_page);
+
+#if TR_VERBOSE
+ {
+ int i;
+
+ DPRINTK("ti->init_srb_page=0x%x\n", ti->init_srb_page);
+ DPRINTK("init_srb(%p):", ti->init_srb );
+ for (i = 0; i < 20; i++)
+ printk("%02X ", (int) readb(ti->init_srb + i));
+ printk("\n");
+ }
+#endif
+
+ hw_encoded_addr = readw(ti->init_srb + ENCODED_ADDRESS_OFST);
+ encoded_addr = ntohs(hw_encoded_addr);
+ init_status= /*BMS 12/2000 check for shallow mode possibility (Turbo)*/
+ readb(ti->init_srb+offsetof(struct srb_init_response,init_status));
+ /*printk("Initial interrupt: init_status= 0x%02x\n",init_status);*/
+ ti->ring_speed = init_status & 0x01 ? 16 : 4;
+ DPRINTK("Initial interrupt : %d Mbps, shared RAM base %08x.\n",
+ ti->ring_speed, (unsigned int)dev->mem_start);
+ ti->auto_speedsave=readb(ti->init_srb+INIT_STATUS_2_OFST)&4?TRUE:FALSE;
+
+ if (ti->open_mode == MANUAL) wake_up(&ti->wait_for_reset);
+ else tok_open_adapter((unsigned long)dev);
+
+} /*initial_tok_int() */
+
+/*****************************************************************************/
+
+#define CMD_CORRELATE_OFST 1
+#define DHB_ADDRESS_OFST 6
+
+#define FRAME_LENGTH_OFST 6
+#define HEADER_LENGTH_OFST 8
+#define RSAP_VALUE_OFST 9
+
+static void tr_tx(struct net_device *dev)
+{
+ struct tok_info *ti = (struct tok_info *) dev->priv;
+ struct trh_hdr *trhdr = (struct trh_hdr *) ti->current_skb->data;
+ unsigned int hdr_len;
+ __u32 dhb=0,dhb_base;
+ void __iomem *dhbuf = NULL;
+ unsigned char xmit_command;
+ int i,dhb_len=0x4000,src_len,src_offset;
+ struct trllc *llc;
+ struct srb_xmit xsrb;
+ __u8 dhb_page = 0;
+ __u8 llc_ssap;
+
+ SET_PAGE(ti->asb_page);
+
+ if (readb(ti->asb+RETCODE_OFST) != 0xFF) DPRINTK("ASB not free !!!\n");
+
+ /* in providing the transmit interrupts, is telling us it is ready for
+ data and providing a shared memory address for us to stuff with data.
+ Here we compute the effective address where we will place data.
+ */
+ SET_PAGE(ti->arb_page);
+ dhb=dhb_base=ntohs(readw(ti->arb + DHB_ADDRESS_OFST));
+ if (ti->page_mask) {
+ dhb_page = (dhb_base >> 8) & ti->page_mask;
+ dhb=dhb_base & ~(ti->page_mask << 8);
+ }
+ dhbuf = ti->sram_virt + dhb;
+
+ /* Figure out the size of the 802.5 header */
+ if (!(trhdr->saddr[0] & 0x80)) /* RIF present? */
+ hdr_len = sizeof(struct trh_hdr) - TR_MAXRIFLEN;
+ else
+ hdr_len = ((ntohs(trhdr->rcf) & TR_RCF_LEN_MASK) >> 8)
+ + sizeof(struct trh_hdr) - TR_MAXRIFLEN;
+
+ llc = (struct trllc *) (ti->current_skb->data + hdr_len);
+
+ llc_ssap = llc->ssap;
+ SET_PAGE(ti->srb_page);
+ memcpy_fromio(&xsrb, ti->srb, sizeof(xsrb));
+ SET_PAGE(ti->asb_page);
+ xmit_command = xsrb.command;
+
+ writeb(xmit_command, ti->asb + COMMAND_OFST);
+ writew(xsrb.station_id, ti->asb + STATION_ID_OFST);
+ writeb(llc_ssap, ti->asb + RSAP_VALUE_OFST);
+ writeb(xsrb.cmd_corr, ti->asb + CMD_CORRELATE_OFST);
+ writeb(0, ti->asb + RETCODE_OFST);
+ if ((xmit_command == XMIT_XID_CMD) || (xmit_command == XMIT_TEST_CMD)) {
+ writew(htons(0x11), ti->asb + FRAME_LENGTH_OFST);
+ writeb(0x0e, ti->asb + HEADER_LENGTH_OFST);
+ SET_PAGE(dhb_page);
+ writeb(AC, dhbuf);
+ writeb(LLC_FRAME, dhbuf + 1);
+ for (i = 0; i < TR_ALEN; i++)
+ writeb((int) 0x0FF, dhbuf + i + 2);
+ for (i = 0; i < TR_ALEN; i++)
+ writeb(0, dhbuf + i + TR_ALEN + 2);
+ writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
+ return;
+ }
+ /*
+ * the token ring packet is copied from sk_buff to the adapter
+ * buffer identified in the command data received with the interrupt.
+ */
+ writeb(hdr_len, ti->asb + HEADER_LENGTH_OFST);
+ writew(htons(ti->current_skb->len), ti->asb + FRAME_LENGTH_OFST);
+ src_len=ti->current_skb->len;
+ src_offset=0;
+ dhb=dhb_base;
+ while(1) {
+ if (ti->page_mask) {
+ dhb_page=(dhb >> 8) & ti->page_mask;
+ dhb=dhb & ~(ti->page_mask << 8);
+ dhb_len=0x4000-dhb; /* remaining size of this page */
+ }
+ dhbuf = ti->sram_virt + dhb;
+ SET_PAGE(dhb_page);
+ if (src_len > dhb_len) {
+ memcpy_toio(dhbuf,&ti->current_skb->data[src_offset],
+ dhb_len);
+ src_len -= dhb_len;
+ src_offset += dhb_len;
+ dhb_base+=dhb_len;
+ dhb=dhb_base;
+ continue;
+ }
+ memcpy_toio(dhbuf, &ti->current_skb->data[src_offset], src_len);
+ break;
+ }
+ writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
+ ti->tr_stats.tx_bytes += ti->current_skb->len;
+ dev_kfree_skb_irq(ti->current_skb);
+ ti->current_skb = NULL;
+ netif_wake_queue(dev);
+ if (ti->readlog_pending)
+ ibmtr_readlog(dev);
+} /*tr_tx */
+
+/*****************************************************************************/
+
+
+#define RECEIVE_BUFFER_OFST 6
+#define LAN_HDR_LENGTH_OFST 8
+#define DLC_HDR_LENGTH_OFST 9
+
+#define DSAP_OFST 0
+#define SSAP_OFST 1
+#define LLC_OFST 2
+#define PROTID_OFST 3
+#define ETHERTYPE_OFST 6
+
+static void tr_rx(struct net_device *dev)
+{
+ struct tok_info *ti = (struct tok_info *) dev->priv;
+ __u32 rbuffer;
+ void __iomem *rbuf, *rbufdata, *llc;
+ __u8 rbuffer_page = 0;
+ unsigned char *data;
+ unsigned int rbuffer_len, lan_hdr_len, hdr_len, ip_len, length;
+ unsigned char dlc_hdr_len;
+ struct sk_buff *skb;
+ unsigned int skb_size = 0;
+ int IPv4_p = 0;
+ unsigned int chksum = 0;
+ struct iphdr *iph;
+ struct arb_rec_req rarb;
+
+ SET_PAGE(ti->arb_page);
+ memcpy_fromio(&rarb, ti->arb, sizeof(rarb));
+ rbuffer = ntohs(rarb.rec_buf_addr) ;
+ rbuf = map_address(ti, rbuffer, &rbuffer_page);
+
+ SET_PAGE(ti->asb_page);
+
+ if (readb(ti->asb + RETCODE_OFST) !=0xFF) DPRINTK("ASB not free !!!\n");
+
+ writeb(REC_DATA, ti->asb + COMMAND_OFST);
+ writew(rarb.station_id, ti->asb + STATION_ID_OFST);
+ writew(rarb.rec_buf_addr, ti->asb + RECEIVE_BUFFER_OFST);
+
+ lan_hdr_len = rarb.lan_hdr_len;
+ if (lan_hdr_len > sizeof(struct trh_hdr)) {
+ DPRINTK("Linux cannot handle greater than 18 bytes RIF\n");
+ return;
+ } /*BMS I added this above just to be very safe */
+ dlc_hdr_len = readb(ti->arb + DLC_HDR_LENGTH_OFST);
+ hdr_len = lan_hdr_len + sizeof(struct trllc) + sizeof(struct iphdr);
+
+ SET_PAGE(rbuffer_page);
+ llc = rbuf + offsetof(struct rec_buf, data) + lan_hdr_len;
+
+#if TR_VERBOSE
+ DPRINTK("offsetof data: %02X lan_hdr_len: %02X\n",
+ (__u32) offsetof(struct rec_buf, data), (unsigned int) lan_hdr_len);
+ DPRINTK("llc: %08X rec_buf_addr: %04X dev->mem_start: %lX\n",
+ llc, ntohs(rarb.rec_buf_addr), dev->mem_start);
+ DPRINTK("dsap: %02X, ssap: %02X, llc: %02X, protid: %02X%02X%02X, "
+ "ethertype: %04X\n",
+ (int) readb(llc + DSAP_OFST), (int) readb(llc + SSAP_OFST),
+ (int) readb(llc + LLC_OFST), (int) readb(llc + PROTID_OFST),
+ (int) readb(llc+PROTID_OFST+1),(int)readb(llc+PROTID_OFST + 2),
+ (int) ntohs(readw(llc + ETHERTYPE_OFST)));
+#endif
+ if (readb(llc + offsetof(struct trllc, llc)) != UI_CMD) {
+ SET_PAGE(ti->asb_page);
+ writeb(DATA_LOST, ti->asb + RETCODE_OFST);
+ ti->tr_stats.rx_dropped++;
+ writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
+ return;
+ }
+ length = ntohs(rarb.frame_len);
+ if (readb(llc + DSAP_OFST) == EXTENDED_SAP &&
+ readb(llc + SSAP_OFST) == EXTENDED_SAP &&
+ length >= hdr_len) IPv4_p = 1;
+#if TR_VERBOSE
+#define SADDR_OFST 8
+#define DADDR_OFST 2
+
+ if (!IPv4_p) {
+
+ void __iomem *trhhdr = rbuf + offsetof(struct rec_buf, data);
+
+ DPRINTK("Probably non-IP frame received.\n");
+ DPRINTK("ssap: %02X dsap: %02X "
+ "saddr: %02X:%02X:%02X:%02X:%02X:%02X "
+ "daddr: %02X:%02X:%02X:%02X:%02X:%02X\n",
+ readb(llc + SSAP_OFST), readb(llc + DSAP_OFST),
+ readb(trhhdr+SADDR_OFST), readb(trhhdr+ SADDR_OFST+1),
+ readb(trhhdr+SADDR_OFST+2), readb(trhhdr+SADDR_OFST+3),
+ readb(trhhdr+SADDR_OFST+4), readb(trhhdr+SADDR_OFST+5),
+ readb(trhhdr+DADDR_OFST), readb(trhhdr+DADDR_OFST + 1),
+ readb(trhhdr+DADDR_OFST+2), readb(trhhdr+DADDR_OFST+3),
+ readb(trhhdr+DADDR_OFST+4), readb(trhhdr+DADDR_OFST+5));
+ }
+#endif
+
+ /*BMS handle the case she comes in with few hops but leaves with many */
+ skb_size=length-lan_hdr_len+sizeof(struct trh_hdr)+sizeof(struct trllc);
+
+ if (!(skb = dev_alloc_skb(skb_size))) {
+ DPRINTK("out of memory. frame dropped.\n");
+ ti->tr_stats.rx_dropped++;
+ SET_PAGE(ti->asb_page);
+ writeb(DATA_LOST, ti->asb + offsetof(struct asb_rec, ret_code));
+ writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
+ return;
+ }
+ /*BMS again, if she comes in with few but leaves with many */
+ skb_reserve(skb, sizeof(struct trh_hdr) - lan_hdr_len);
+ skb_put(skb, length);
+ skb->dev = dev;
+ data = skb->data;
+ rbuffer_len = ntohs(readw(rbuf + offsetof(struct rec_buf, buf_len)));
+ rbufdata = rbuf + offsetof(struct rec_buf, data);
+
+ if (IPv4_p) {
+ /* Copy the headers without checksumming */
+ memcpy_fromio(data, rbufdata, hdr_len);
+
+ /* Watch for padded packets and bogons */
+ iph= (struct iphdr *)(data+ lan_hdr_len + sizeof(struct trllc));
+ ip_len = ntohs(iph->tot_len) - sizeof(struct iphdr);
+ length -= hdr_len;
+ if ((ip_len <= length) && (ip_len > 7))
+ length = ip_len;
+ data += hdr_len;
+ rbuffer_len -= hdr_len;
+ rbufdata += hdr_len;
+ }
+ /* Copy the payload... */
+#define BUFFER_POINTER_OFST 2
+#define BUFFER_LENGTH_OFST 6
+ for (;;) {
+ if (ibmtr_debug_trace&TRC_INITV && length < rbuffer_len)
+ DPRINTK("CURIOUS, length=%d < rbuffer_len=%d\n",
+ length,rbuffer_len);
+ if (IPv4_p)
+ chksum=csum_partial_copy_nocheck((void*)rbufdata,
+ data,length<rbuffer_len?length:rbuffer_len,chksum);
+ else
+ memcpy_fromio(data, rbufdata, rbuffer_len);
+ rbuffer = ntohs(readw(rbuf+BUFFER_POINTER_OFST)) ;
+ if (!rbuffer)
+ break;
+ rbuffer -= 2;
+ length -= rbuffer_len;
+ data += rbuffer_len;
+ rbuf = map_address(ti, rbuffer, &rbuffer_page);
+ SET_PAGE(rbuffer_page);
+ rbuffer_len = ntohs(readw(rbuf + BUFFER_LENGTH_OFST));
+ rbufdata = rbuf + offsetof(struct rec_buf, data);
+ }
+
+ SET_PAGE(ti->asb_page);
+ writeb(0, ti->asb + offsetof(struct asb_rec, ret_code));
+
+ writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
+
+ ti->tr_stats.rx_bytes += skb->len;
+ ti->tr_stats.rx_packets++;
+
+ skb->protocol = tr_type_trans(skb, dev);
+ if (IPv4_p) {
+ skb->csum = chksum;
+ skb->ip_summed = 1;
+ }
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+} /*tr_rx */
+
+/*****************************************************************************/
+
+void ibmtr_reset_timer(struct timer_list *tmr, struct net_device *dev)
+{
+ tmr->expires = jiffies + TR_RETRY_INTERVAL;
+ tmr->data = (unsigned long) dev;
+ tmr->function = tok_rerun;
+ init_timer(tmr);
+ add_timer(tmr);
+}
+
+/*****************************************************************************/
+
+void tok_rerun(unsigned long dev_addr){
+
+ struct net_device *dev = (struct net_device *)dev_addr;
+ struct tok_info *ti = (struct tok_info *) dev->priv;
+
+ if ( ti->open_action == RESTART){
+ ti->do_tok_int = FIRST_INT;
+ outb(0, dev->base_addr + ADAPTRESETREL);
+#ifdef ENABLE_PAGING
+ if (ti->page_mask)
+ writeb(SRPR_ENABLE_PAGING,
+ ti->mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN);
+#endif
+
+ writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN);
+ } else
+ tok_open_adapter(dev_addr);
+}
+
+/*****************************************************************************/
+
+void ibmtr_readlog(struct net_device *dev)
+{
+ struct tok_info *ti;
+
+ ti = (struct tok_info *) dev->priv;
+
+ ti->readlog_pending = 0;
+ SET_PAGE(ti->srb_page);
+ writeb(DIR_READ_LOG, ti->srb);
+ writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN);
+ writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
+
+ netif_stop_queue(dev);
+
+}
+
+/*****************************************************************************/
+
+/* tok_get_stats(): Basically a scaffold routine which will return
+ the address of the tr_statistics structure associated with
+ this device -- the tr.... structure is an ethnet look-alike
+ so at least for this iteration may suffice. */
+
+static struct net_device_stats *tok_get_stats(struct net_device *dev)
+{
+
+ struct tok_info *toki;
+ toki = (struct tok_info *) dev->priv;
+ return (struct net_device_stats *) &toki->tr_stats;
+}
+
+/*****************************************************************************/
+
+int ibmtr_change_mtu(struct net_device *dev, int mtu)
+{
+ struct tok_info *ti = (struct tok_info *) dev->priv;
+
+ if (ti->ring_speed == 16 && mtu > ti->maxmtu16)
+ return -EINVAL;
+ if (ti->ring_speed == 4 && mtu > ti->maxmtu4)
+ return -EINVAL;
+ dev->mtu = mtu;
+ return 0;
+}
+
+/*****************************************************************************/
+#ifdef MODULE
+
+/* 3COM 3C619C supports 8 interrupts, 32 I/O ports */
+static struct net_device *dev_ibmtr[IBMTR_MAX_ADAPTERS];
+static int io[IBMTR_MAX_ADAPTERS] = { 0xa20, 0xa24 };
+static int irq[IBMTR_MAX_ADAPTERS];
+static int mem[IBMTR_MAX_ADAPTERS];
+
+MODULE_LICENSE("GPL");
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(mem, int, NULL, 0);
+
+static int __init ibmtr_init(void)
+{
+ int i;
+ int count=0;
+
+ find_turbo_adapters(io);
+
+ for (i = 0; io[i] && (i < IBMTR_MAX_ADAPTERS); i++) {
+ struct net_device *dev;
+ irq[i] = 0;
+ mem[i] = 0;
+ dev = alloc_trdev(sizeof(struct tok_info));
+ if (dev == NULL) {
+ if (i == 0)
+ return -ENOMEM;
+ break;
+ }
+ dev->base_addr = io[i];
+ dev->irq = irq[i];
+ dev->mem_start = mem[i];
+
+ if (ibmtr_probe_card(dev)) {
+ free_netdev(dev);
+ continue;
+ }
+ dev_ibmtr[i] = dev;
+ count++;
+ }
+ if (count) return 0;
+ printk("ibmtr: register_netdev() returned non-zero.\n");
+ return -EIO;
+}
+module_init(ibmtr_init);
+
+static void __exit ibmtr_cleanup(void)
+{
+ int i;
+
+ for (i = 0; i < IBMTR_MAX_ADAPTERS; i++){
+ if (!dev_ibmtr[i])
+ continue;
+ unregister_netdev(dev_ibmtr[i]);
+ ibmtr_cleanup_card(dev_ibmtr[i]);
+ free_netdev(dev_ibmtr[i]);
+ }
+}
+module_exit(ibmtr_cleanup);
+#endif
diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c
new file mode 100644
index 00000000000..99e0b03b69a
--- /dev/null
+++ b/drivers/net/tokenring/lanstreamer.c
@@ -0,0 +1,2011 @@
+/*
+ * lanstreamer.c -- driver for the IBM Auto LANStreamer PCI Adapter
+ *
+ * Written By: Mike Sullivan, IBM Corporation
+ *
+ * Copyright (C) 1999 IBM Corporation
+ *
+ * Linux driver for IBM PCI tokenring cards based on the LanStreamer MPC
+ * chipset.
+ *
+ * This driver is based on the olympic driver for IBM PCI TokenRing cards (Pit/Pit-Phy/Olympic
+ * chipsets) written by:
+ * 1999 Peter De Schrijver All Rights Reserved
+ * 1999 Mike Phillips (phillim@amtrak.com)
+ *
+ * Base Driver Skeleton:
+ * Written 1993-94 by Donald Becker.
+ *
+ * Copyright 1993 United States Government as represented by the
+ * Director, National Security Agency.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+ *
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *
+ * 12/10/99 - Alpha Release 0.1.0
+ * First release to the public
+ * 03/03/00 - Merged to kernel, indented -kr -i8 -bri0, fixed some missing
+ * malloc free checks, reviewed code. <alan@redhat.com>
+ * 03/13/00 - Added spinlocks for smp
+ * 03/08/01 - Added support for module_init() and module_exit()
+ * 08/15/01 - Added ioctl() functionality for debugging, changed netif_*_queue
+ * calls and other incorrectness - Kent Yoder <yoder1@us.ibm.com>
+ * 11/05/01 - Restructured the interrupt function, added delays, reduced the
+ * the number of TX descriptors to 1, which together can prevent
+ * the card from locking up the box - <yoder1@us.ibm.com>
+ * 09/27/02 - New PCI interface + bug fix. - <yoder1@us.ibm.com>
+ * 11/13/02 - Removed free_irq calls which could cause a hang, added
+ * netif_carrier_{on|off} - <yoder1@us.ibm.com>
+ *
+ * To Do:
+ *
+ *
+ * If Problems do Occur
+ * Most problems can be rectified by either closing and opening the interface
+ * (ifconfig down and up) or rmmod and insmod'ing the driver (a bit difficult
+ * if compiled into the kernel).
+ */
+
+/* Change STREAMER_DEBUG to 1 to get verbose, and I mean really verbose, messages */
+
+#define STREAMER_DEBUG 0
+#define STREAMER_DEBUG_PACKETS 0
+
+/* Change STREAMER_NETWORK_MONITOR to receive mac frames through the arb channel.
+ * Will also create a /proc/net/streamer_tr entry if proc_fs is compiled into the
+ * kernel.
+ * Intended to be used to create a ring-error reporting network module
+ * i.e. it will give you the source address of beaconers on the ring
+ */
+
+#define STREAMER_NETWORK_MONITOR 0
+
+/* #define CONFIG_PROC_FS */
+
+/*
+ * Allow or disallow ioctl's for debugging
+ */
+
+#define STREAMER_IOCTL 0
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/string.h>
+#include <linux/proc_fs.h>
+#include <linux/ptrace.h>
+#include <linux/skbuff.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/trdevice.h>
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/version.h>
+#include <linux/bitops.h>
+
+#include <net/checksum.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "lanstreamer.h"
+
+#if (BITS_PER_LONG == 64)
+#error broken on 64-bit: stores pointer to rx_ring->buffer in 32-bit int
+#endif
+
+
+/* I've got to put some intelligence into the version number so that Peter and I know
+ * which version of the code somebody has got.
+ * Version Number = a.b.c.d where a.b.c is the level of code and d is the latest author.
+ * So 0.0.1.pds = Peter, 0.0.1.mlp = Mike
+ *
+ * Official releases will only have an a.b.c version number format.
+ */
+
+static char version[] = "LanStreamer.c v0.4.0 03/08/01 - Mike Sullivan\n"
+ " v0.5.3 11/13/02 - Kent Yoder";
+
+static struct pci_device_id streamer_pci_tbl[] = {
+ { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_TR, PCI_ANY_ID, PCI_ANY_ID,},
+ {} /* terminating entry */
+};
+MODULE_DEVICE_TABLE(pci,streamer_pci_tbl);
+
+
+static char *open_maj_error[] = {
+ "No error", "Lobe Media Test", "Physical Insertion",
+ "Address Verification", "Neighbor Notification (Ring Poll)",
+ "Request Parameters", "FDX Registration Request",
+ "FDX Lobe Media Test", "FDX Duplicate Address Check",
+ "Unknown stage"
+};
+
+static char *open_min_error[] = {
+ "No error", "Function Failure", "Signal Lost", "Wire Fault",
+ "Ring Speed Mismatch", "Timeout", "Ring Failure", "Ring Beaconing",
+ "Duplicate Node Address", "Request Parameters", "Remove Received",
+ "Reserved", "Reserved", "No Monitor Detected for RPL",
+ "Monitor Contention failer for RPL", "FDX Protocol Error"
+};
+
+/* Module paramters */
+
+/* Ring Speed 0,4,16
+ * 0 = Autosense
+ * 4,16 = Selected speed only, no autosense
+ * This allows the card to be the first on the ring
+ * and become the active monitor.
+ *
+ * WARNING: Some hubs will allow you to insert
+ * at the wrong speed
+ */
+
+static int ringspeed[STREAMER_MAX_ADAPTERS] = { 0, };
+
+module_param_array(ringspeed, int, NULL, 0);
+
+/* Packet buffer size */
+
+static int pkt_buf_sz[STREAMER_MAX_ADAPTERS] = { 0, };
+
+module_param_array(pkt_buf_sz, int, NULL, 0);
+
+/* Message Level */
+
+static int message_level[STREAMER_MAX_ADAPTERS] = { 1, };
+
+module_param_array(message_level, int, NULL, 0);
+
+#if STREAMER_IOCTL
+static int streamer_ioctl(struct net_device *, struct ifreq *, int);
+#endif
+
+static int streamer_reset(struct net_device *dev);
+static int streamer_open(struct net_device *dev);
+static int streamer_xmit(struct sk_buff *skb, struct net_device *dev);
+static int streamer_close(struct net_device *dev);
+static void streamer_set_rx_mode(struct net_device *dev);
+static irqreturn_t streamer_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs);
+static struct net_device_stats *streamer_get_stats(struct net_device *dev);
+static int streamer_set_mac_address(struct net_device *dev, void *addr);
+static void streamer_arb_cmd(struct net_device *dev);
+static int streamer_change_mtu(struct net_device *dev, int mtu);
+static void streamer_srb_bh(struct net_device *dev);
+static void streamer_asb_bh(struct net_device *dev);
+#if STREAMER_NETWORK_MONITOR
+#ifdef CONFIG_PROC_FS
+static int streamer_proc_info(char *buffer, char **start, off_t offset,
+ int length, int *eof, void *data);
+static int sprintf_info(char *buffer, struct net_device *dev);
+struct streamer_private *dev_streamer=NULL;
+#endif
+#endif
+
+static int __devinit streamer_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct net_device *dev;
+ struct streamer_private *streamer_priv;
+ unsigned long pio_start, pio_end, pio_flags, pio_len;
+ unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
+ int rc = 0;
+ static int card_no=-1;
+ u16 pcr;
+
+#if STREAMER_DEBUG
+ printk("lanstreamer::streamer_init_one, entry pdev %p\n",pdev);
+#endif
+
+ card_no++;
+ dev = alloc_trdev(sizeof(*streamer_priv));
+ if (dev==NULL) {
+ printk(KERN_ERR "lanstreamer: out of memory.\n");
+ return -ENOMEM;
+ }
+
+ SET_MODULE_OWNER(dev);
+ streamer_priv = dev->priv;
+
+#if STREAMER_NETWORK_MONITOR
+#ifdef CONFIG_PROC_FS
+ if (!dev_streamer)
+ create_proc_read_entry("net/streamer_tr", 0, 0,
+ streamer_proc_info, NULL);
+ streamer_priv->next = dev_streamer;
+ dev_streamer = streamer_priv;
+#endif
+#endif
+
+ rc = pci_set_dma_mask(pdev, 0xFFFFFFFFULL);
+ if (rc) {
+ printk(KERN_ERR "%s: No suitable PCI mapping available.\n",
+ dev->name);
+ rc = -ENODEV;
+ goto err_out;
+ }
+
+ rc = pci_enable_device(pdev);
+ if (rc) {
+ printk(KERN_ERR "lanstreamer: unable to enable pci device\n");
+ rc=-EIO;
+ goto err_out;
+ }
+
+ pci_set_master(pdev);
+
+ rc = pci_set_mwi(pdev);
+ if (rc) {
+ printk(KERN_ERR "lanstreamer: unable to enable MWI on pci device\n");
+ goto err_out_disable;
+ }
+
+ pio_start = pci_resource_start(pdev, 0);
+ pio_end = pci_resource_end(pdev, 0);
+ pio_flags = pci_resource_flags(pdev, 0);
+ pio_len = pci_resource_len(pdev, 0);
+
+ mmio_start = pci_resource_start(pdev, 1);
+ mmio_end = pci_resource_end(pdev, 1);
+ mmio_flags = pci_resource_flags(pdev, 1);
+ mmio_len = pci_resource_len(pdev, 1);
+
+#if STREAMER_DEBUG
+ printk("lanstreamer: pio_start %x pio_end %x pio_len %x pio_flags %x\n",
+ pio_start, pio_end, pio_len, pio_flags);
+ printk("lanstreamer: mmio_start %x mmio_end %x mmio_len %x mmio_flags %x\n",
+ mmio_start, mmio_end, mmio_flags, mmio_len);
+#endif
+
+ if (!request_region(pio_start, pio_len, "lanstreamer")) {
+ printk(KERN_ERR "lanstreamer: unable to get pci io addr %lx\n",
+ pio_start);
+ rc= -EBUSY;
+ goto err_out_mwi;
+ }
+
+ if (!request_mem_region(mmio_start, mmio_len, "lanstreamer")) {
+ printk(KERN_ERR "lanstreamer: unable to get pci mmio addr %lx\n",
+ mmio_start);
+ rc= -EBUSY;
+ goto err_out_free_pio;
+ }
+
+ streamer_priv->streamer_mmio=ioremap(mmio_start, mmio_len);
+ if (streamer_priv->streamer_mmio == NULL) {
+ printk(KERN_ERR "lanstreamer: unable to remap MMIO %lx\n",
+ mmio_start);
+ rc= -EIO;
+ goto err_out_free_mmio;
+ }
+
+ init_waitqueue_head(&streamer_priv->srb_wait);
+ init_waitqueue_head(&streamer_priv->trb_wait);
+
+ dev->open = &streamer_open;
+ dev->hard_start_xmit = &streamer_xmit;
+ dev->change_mtu = &streamer_change_mtu;
+ dev->stop = &streamer_close;
+#if STREAMER_IOCTL
+ dev->do_ioctl = &streamer_ioctl;
+#else
+ dev->do_ioctl = NULL;
+#endif
+ dev->set_multicast_list = &streamer_set_rx_mode;
+ dev->get_stats = &streamer_get_stats;
+ dev->set_mac_address = &streamer_set_mac_address;
+ dev->irq = pdev->irq;
+ dev->base_addr=pio_start;
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ streamer_priv->streamer_card_name = (char *)pdev->resource[0].name;
+ streamer_priv->pci_dev = pdev;
+
+ if ((pkt_buf_sz[card_no] < 100) || (pkt_buf_sz[card_no] > 18000))
+ streamer_priv->pkt_buf_sz = PKT_BUF_SZ;
+ else
+ streamer_priv->pkt_buf_sz = pkt_buf_sz[card_no];
+
+ streamer_priv->streamer_ring_speed = ringspeed[card_no];
+ streamer_priv->streamer_message_level = message_level[card_no];
+
+ pci_set_drvdata(pdev, dev);
+
+ spin_lock_init(&streamer_priv->streamer_lock);
+
+ pci_read_config_word (pdev, PCI_COMMAND, &pcr);
+ pcr |= PCI_COMMAND_SERR;
+ pci_write_config_word (pdev, PCI_COMMAND, pcr);
+
+ printk("%s \n", version);
+ printk("%s: %s. I/O at %hx, MMIO at %p, using irq %d\n",dev->name,
+ streamer_priv->streamer_card_name,
+ (unsigned int) dev->base_addr,
+ streamer_priv->streamer_mmio,
+ dev->irq);
+
+ if (streamer_reset(dev))
+ goto err_out_unmap;
+
+ rc = register_netdev(dev);
+ if (rc)
+ goto err_out_unmap;
+ return 0;
+
+err_out_unmap:
+ iounmap(streamer_priv->streamer_mmio);
+err_out_free_mmio:
+ release_mem_region(mmio_start, mmio_len);
+err_out_free_pio:
+ release_region(pio_start, pio_len);
+err_out_mwi:
+ pci_clear_mwi(pdev);
+err_out_disable:
+ pci_disable_device(pdev);
+err_out:
+ free_netdev(dev);
+#if STREAMER_DEBUG
+ printk("lanstreamer: Exit error %x\n",rc);
+#endif
+ return rc;
+}
+
+static void __devexit streamer_remove_one(struct pci_dev *pdev)
+{
+ struct net_device *dev=pci_get_drvdata(pdev);
+ struct streamer_private *streamer_priv;
+
+#if STREAMER_DEBUG
+ printk("lanstreamer::streamer_remove_one entry pdev %p\n",pdev);
+#endif
+
+ if (dev == NULL) {
+ printk(KERN_ERR "lanstreamer::streamer_remove_one, ERROR dev is NULL\n");
+ return;
+ }
+
+ streamer_priv=dev->priv;
+ if (streamer_priv == NULL) {
+ printk(KERN_ERR "lanstreamer::streamer_remove_one, ERROR dev->priv is NULL\n");
+ return;
+ }
+
+#if STREAMER_NETWORK_MONITOR
+#ifdef CONFIG_PROC_FS
+ {
+ struct streamer_private **p, **next;
+
+ for (p = &dev_streamer; *p; p = next) {
+ next = &(*p)->next;
+ if (*p == streamer_priv) {
+ *p = *next;
+ break;
+ }
+ }
+ if (!dev_streamer)
+ remove_proc_entry("net/streamer_tr", NULL);
+ }
+#endif
+#endif
+
+ unregister_netdev(dev);
+ iounmap(streamer_priv->streamer_mmio);
+ release_mem_region(pci_resource_start(pdev, 1), pci_resource_len(pdev,1));
+ release_region(pci_resource_start(pdev, 0), pci_resource_len(pdev,0));
+ pci_clear_mwi(pdev);
+ pci_disable_device(pdev);
+ free_netdev(dev);
+ pci_set_drvdata(pdev, NULL);
+}
+
+
+static int streamer_reset(struct net_device *dev)
+{
+ struct streamer_private *streamer_priv;
+ __u8 __iomem *streamer_mmio;
+ unsigned long t;
+ unsigned int uaa_addr;
+ struct sk_buff *skb = NULL;
+ __u16 misr;
+
+ streamer_priv = (struct streamer_private *) dev->priv;
+ streamer_mmio = streamer_priv->streamer_mmio;
+
+ writew(readw(streamer_mmio + BCTL) | BCTL_SOFTRESET, streamer_mmio + BCTL);
+ t = jiffies;
+ /* Hold soft reset bit for a while */
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout(HZ);
+
+ writew(readw(streamer_mmio + BCTL) & ~BCTL_SOFTRESET,
+ streamer_mmio + BCTL);
+
+#if STREAMER_DEBUG
+ printk("BCTL: %x\n", readw(streamer_mmio + BCTL));
+ printk("GPR: %x\n", readw(streamer_mmio + GPR));
+ printk("SISRMASK: %x\n", readw(streamer_mmio + SISR_MASK));
+#endif
+ writew(readw(streamer_mmio + BCTL) | (BCTL_RX_FIFO_8 | BCTL_TX_FIFO_8), streamer_mmio + BCTL );
+
+ if (streamer_priv->streamer_ring_speed == 0) { /* Autosense */
+ writew(readw(streamer_mmio + GPR) | GPR_AUTOSENSE,
+ streamer_mmio + GPR);
+ if (streamer_priv->streamer_message_level)
+ printk(KERN_INFO "%s: Ringspeed autosense mode on\n",
+ dev->name);
+ } else if (streamer_priv->streamer_ring_speed == 16) {
+ if (streamer_priv->streamer_message_level)
+ printk(KERN_INFO "%s: Trying to open at 16 Mbps as requested\n",
+ dev->name);
+ writew(GPR_16MBPS, streamer_mmio + GPR);
+ } else if (streamer_priv->streamer_ring_speed == 4) {
+ if (streamer_priv->streamer_message_level)
+ printk(KERN_INFO "%s: Trying to open at 4 Mbps as requested\n",
+ dev->name);
+ writew(0, streamer_mmio + GPR);
+ }
+
+ skb = dev_alloc_skb(streamer_priv->pkt_buf_sz);
+ if (!skb) {
+ printk(KERN_INFO "%s: skb allocation for diagnostics failed...proceeding\n",
+ dev->name);
+ } else {
+ struct streamer_rx_desc *rx_ring;
+ u8 *data;
+
+ rx_ring=(struct streamer_rx_desc *)skb->data;
+ data=((u8 *)skb->data)+sizeof(struct streamer_rx_desc);
+ rx_ring->forward=0;
+ rx_ring->status=0;
+ rx_ring->buffer=cpu_to_le32(pci_map_single(streamer_priv->pci_dev, data,
+ 512, PCI_DMA_FROMDEVICE));
+ rx_ring->framelen_buflen=512;
+ writel(cpu_to_le32(pci_map_single(streamer_priv->pci_dev, rx_ring, 512, PCI_DMA_FROMDEVICE)),
+ streamer_mmio+RXBDA);
+ }
+
+#if STREAMER_DEBUG
+ printk("GPR = %x\n", readw(streamer_mmio + GPR));
+#endif
+ /* start solo init */
+ writew(SISR_MI, streamer_mmio + SISR_MASK_SUM);
+
+ while (!((readw(streamer_mmio + SISR)) & SISR_SRB_REPLY)) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(HZ/10);
+ if (jiffies - t > 40 * HZ) {
+ printk(KERN_ERR
+ "IBM PCI tokenring card not responding\n");
+ release_region(dev->base_addr, STREAMER_IO_SPACE);
+ if (skb)
+ dev_kfree_skb(skb);
+ return -1;
+ }
+ }
+ writew(~SISR_SRB_REPLY, streamer_mmio + SISR_RUM);
+ misr = readw(streamer_mmio + MISR_RUM);
+ writew(~misr, streamer_mmio + MISR_RUM);
+
+ if (skb)
+ dev_kfree_skb(skb); /* release skb used for diagnostics */
+
+#if STREAMER_DEBUG
+ printk("LAPWWO: %x, LAPA: %x LAPE: %x\n",
+ readw(streamer_mmio + LAPWWO), readw(streamer_mmio + LAPA),
+ readw(streamer_mmio + LAPE));
+#endif
+
+#if STREAMER_DEBUG
+ {
+ int i;
+ writew(readw(streamer_mmio + LAPWWO),
+ streamer_mmio + LAPA);
+ printk("initialization response srb dump: ");
+ for (i = 0; i < 10; i++)
+ printk("%x:",
+ ntohs(readw(streamer_mmio + LAPDINC)));
+ printk("\n");
+ }
+#endif
+
+ writew(readw(streamer_mmio + LAPWWO) + 6, streamer_mmio + LAPA);
+ if (readw(streamer_mmio + LAPD)) {
+ printk(KERN_INFO "tokenring card initialization failed. errorcode : %x\n",
+ ntohs(readw(streamer_mmio + LAPD)));
+ release_region(dev->base_addr, STREAMER_IO_SPACE);
+ return -1;
+ }
+
+ writew(readw(streamer_mmio + LAPWWO) + 8, streamer_mmio + LAPA);
+ uaa_addr = ntohs(readw(streamer_mmio + LAPDINC));
+ readw(streamer_mmio + LAPDINC); /* skip over Level.Addr field */
+ streamer_priv->streamer_addr_table_addr = ntohs(readw(streamer_mmio + LAPDINC));
+ streamer_priv->streamer_parms_addr = ntohs(readw(streamer_mmio + LAPDINC));
+
+#if STREAMER_DEBUG
+ printk("UAA resides at %x\n", uaa_addr);
+#endif
+
+ /* setup uaa area for access with LAPD */
+ {
+ int i;
+ __u16 addr;
+ writew(uaa_addr, streamer_mmio + LAPA);
+ for (i = 0; i < 6; i += 2) {
+ addr=ntohs(readw(streamer_mmio+LAPDINC));
+ dev->dev_addr[i]= (addr >> 8) & 0xff;
+ dev->dev_addr[i+1]= addr & 0xff;
+ }
+#if STREAMER_DEBUG
+ printk("Adapter address: ");
+ for (i = 0; i < 6; i++) {
+ printk("%02x:", dev->dev_addr[i]);
+ }
+ printk("\n");
+#endif
+ }
+ return 0;
+}
+
+static int streamer_open(struct net_device *dev)
+{
+ struct streamer_private *streamer_priv = (struct streamer_private *) dev->priv;
+ __u8 __iomem *streamer_mmio = streamer_priv->streamer_mmio;
+ unsigned long flags;
+ char open_error[255];
+ int i, open_finished = 1;
+ __u16 srb_word;
+ __u16 srb_open;
+ int rc;
+
+ if (readw(streamer_mmio+BMCTL_SUM) & BMCTL_RX_ENABLED) {
+ rc=streamer_reset(dev);
+ }
+
+ if (request_irq(dev->irq, &streamer_interrupt, SA_SHIRQ, "lanstreamer", dev)) {
+ return -EAGAIN;
+ }
+#if STREAMER_DEBUG
+ printk("BMCTL: %x\n", readw(streamer_mmio + BMCTL_SUM));
+ printk("pending ints: %x\n", readw(streamer_mmio + SISR));
+#endif
+
+ writew(SISR_MI | SISR_SRB_REPLY, streamer_mmio + SISR_MASK); /* more ints later, doesn't stop arb cmd interrupt */
+ writew(LISR_LIE, streamer_mmio + LISR); /* more ints later */
+
+ /* adapter is closed, so SRB is pointed to by LAPWWO */
+ writew(readw(streamer_mmio + LAPWWO), streamer_mmio + LAPA);
+
+#if STREAMER_DEBUG
+ printk("LAPWWO: %x, LAPA: %x\n", readw(streamer_mmio + LAPWWO),
+ readw(streamer_mmio + LAPA));
+ printk("LAPE: %x\n", readw(streamer_mmio + LAPE));
+ printk("SISR Mask = %04x\n", readw(streamer_mmio + SISR_MASK));
+#endif
+ do {
+ int i;
+
+ for (i = 0; i < SRB_COMMAND_SIZE; i += 2) {
+ writew(0, streamer_mmio + LAPDINC);
+ }
+
+ writew(readw(streamer_mmio+LAPWWO),streamer_mmio+LAPA);
+ writew(htons(SRB_OPEN_ADAPTER<<8),streamer_mmio+LAPDINC) ; /* open */
+ writew(htons(STREAMER_CLEAR_RET_CODE<<8),streamer_mmio+LAPDINC);
+ writew(STREAMER_CLEAR_RET_CODE, streamer_mmio + LAPDINC);
+
+ writew(readw(streamer_mmio + LAPWWO) + 8, streamer_mmio + LAPA);
+#if STREAMER_NETWORK_MONITOR
+ /* If Network Monitor, instruct card to copy MAC frames through the ARB */
+ writew(htons(OPEN_ADAPTER_ENABLE_FDX | OPEN_ADAPTER_PASS_ADC_MAC | OPEN_ADAPTER_PASS_ATT_MAC | OPEN_ADAPTER_PASS_BEACON), streamer_mmio + LAPDINC); /* offset 8 word contains open options */
+#else
+ writew(htons(OPEN_ADAPTER_ENABLE_FDX), streamer_mmio + LAPDINC); /* Offset 8 word contains Open.Options */
+#endif
+
+ if (streamer_priv->streamer_laa[0]) {
+ writew(readw(streamer_mmio + LAPWWO) + 12, streamer_mmio + LAPA);
+ writew(htons((streamer_priv->streamer_laa[0] << 8) |
+ streamer_priv->streamer_laa[1]),streamer_mmio+LAPDINC);
+ writew(htons((streamer_priv->streamer_laa[2] << 8) |
+ streamer_priv->streamer_laa[3]),streamer_mmio+LAPDINC);
+ writew(htons((streamer_priv->streamer_laa[4] << 8) |
+ streamer_priv->streamer_laa[5]),streamer_mmio+LAPDINC);
+ memcpy(dev->dev_addr, streamer_priv->streamer_laa, dev->addr_len);
+ }
+
+ /* save off srb open offset */
+ srb_open = readw(streamer_mmio + LAPWWO);
+#if STREAMER_DEBUG
+ writew(readw(streamer_mmio + LAPWWO),
+ streamer_mmio + LAPA);
+ printk("srb open request: \n");
+ for (i = 0; i < 16; i++) {
+ printk("%x:", ntohs(readw(streamer_mmio + LAPDINC)));
+ }
+ printk("\n");
+#endif
+ spin_lock_irqsave(&streamer_priv->streamer_lock, flags);
+ streamer_priv->srb_queued = 1;
+
+ /* signal solo that SRB command has been issued */
+ writew(LISR_SRB_CMD, streamer_mmio + LISR_SUM);
+ spin_unlock_irqrestore(&streamer_priv->streamer_lock, flags);
+
+ while (streamer_priv->srb_queued) {
+ interruptible_sleep_on_timeout(&streamer_priv->srb_wait, 5 * HZ);
+ if (signal_pending(current)) {
+ printk(KERN_WARNING "%s: SRB timed out.\n", dev->name);
+ printk(KERN_WARNING "SISR=%x MISR=%x, LISR=%x\n",
+ readw(streamer_mmio + SISR),
+ readw(streamer_mmio + MISR_RUM),
+ readw(streamer_mmio + LISR));
+ streamer_priv->srb_queued = 0;
+ break;
+ }
+ }
+
+#if STREAMER_DEBUG
+ printk("SISR_MASK: %x\n", readw(streamer_mmio + SISR_MASK));
+ printk("srb open response:\n");
+ writew(srb_open, streamer_mmio + LAPA);
+ for (i = 0; i < 10; i++) {
+ printk("%x:",
+ ntohs(readw(streamer_mmio + LAPDINC)));
+ }
+#endif
+
+ /* If we get the same return response as we set, the interrupt wasn't raised and the open
+ * timed out.
+ */
+ writew(srb_open + 2, streamer_mmio + LAPA);
+ srb_word = ntohs(readw(streamer_mmio + LAPD)) >> 8;
+ if (srb_word == STREAMER_CLEAR_RET_CODE) {
+ printk(KERN_WARNING "%s: Adapter Open time out or error.\n",
+ dev->name);
+ return -EIO;
+ }
+
+ if (srb_word != 0) {
+ if (srb_word == 0x07) {
+ if (!streamer_priv->streamer_ring_speed && open_finished) { /* Autosense , first time around */
+ printk(KERN_WARNING "%s: Retrying at different ring speed \n",
+ dev->name);
+ open_finished = 0;
+ } else {
+ __u16 error_code;
+
+ writew(srb_open + 6, streamer_mmio + LAPA);
+ error_code = ntohs(readw(streamer_mmio + LAPD));
+ strcpy(open_error, open_maj_error[(error_code & 0xf0) >> 4]);
+ strcat(open_error, " - ");
+ strcat(open_error, open_min_error[(error_code & 0x0f)]);
+
+ if (!streamer_priv->streamer_ring_speed
+ && ((error_code & 0x0f) == 0x0d))
+ {
+ printk(KERN_WARNING "%s: Tried to autosense ring speed with no monitors present\n", dev->name);
+ printk(KERN_WARNING "%s: Please try again with a specified ring speed \n", dev->name);
+ free_irq(dev->irq, dev);
+ return -EIO;
+ }
+
+ printk(KERN_WARNING "%s: %s\n",
+ dev->name, open_error);
+ free_irq(dev->irq, dev);
+ return -EIO;
+
+ } /* if autosense && open_finished */
+ } else {
+ printk(KERN_WARNING "%s: Bad OPEN response: %x\n",
+ dev->name, srb_word);
+ free_irq(dev->irq, dev);
+ return -EIO;
+ }
+ } else
+ open_finished = 1;
+ } while (!(open_finished)); /* Will only loop if ring speed mismatch re-open attempted && autosense is on */
+
+ writew(srb_open + 18, streamer_mmio + LAPA);
+ srb_word=ntohs(readw(streamer_mmio+LAPD)) >> 8;
+ if (srb_word & (1 << 3))
+ if (streamer_priv->streamer_message_level)
+ printk(KERN_INFO "%s: Opened in FDX Mode\n", dev->name);
+
+ if (srb_word & 1)
+ streamer_priv->streamer_ring_speed = 16;
+ else
+ streamer_priv->streamer_ring_speed = 4;
+
+ if (streamer_priv->streamer_message_level)
+ printk(KERN_INFO "%s: Opened in %d Mbps mode\n",
+ dev->name,
+ streamer_priv->streamer_ring_speed);
+
+ writew(srb_open + 8, streamer_mmio + LAPA);
+ streamer_priv->asb = ntohs(readw(streamer_mmio + LAPDINC));
+ streamer_priv->srb = ntohs(readw(streamer_mmio + LAPDINC));
+ streamer_priv->arb = ntohs(readw(streamer_mmio + LAPDINC));
+ readw(streamer_mmio + LAPDINC); /* offset 14 word is rsvd */
+ streamer_priv->trb = ntohs(readw(streamer_mmio + LAPDINC));
+
+ streamer_priv->streamer_receive_options = 0x00;
+ streamer_priv->streamer_copy_all_options = 0;
+
+ /* setup rx ring */
+ /* enable rx channel */
+ writew(~BMCTL_RX_DIS, streamer_mmio + BMCTL_RUM);
+
+ /* setup rx descriptors */
+ streamer_priv->streamer_rx_ring=
+ kmalloc( sizeof(struct streamer_rx_desc)*
+ STREAMER_RX_RING_SIZE,GFP_KERNEL);
+ if (!streamer_priv->streamer_rx_ring) {
+ printk(KERN_WARNING "%s ALLOC of streamer rx ring FAILED!!\n",dev->name);
+ return -EIO;
+ }
+
+ for (i = 0; i < STREAMER_RX_RING_SIZE; i++) {
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(streamer_priv->pkt_buf_sz);
+ if (skb == NULL)
+ break;
+
+ skb->dev = dev;
+
+ streamer_priv->streamer_rx_ring[i].forward =
+ cpu_to_le32(pci_map_single(streamer_priv->pci_dev, &streamer_priv->streamer_rx_ring[i + 1],
+ sizeof(struct streamer_rx_desc), PCI_DMA_FROMDEVICE));
+ streamer_priv->streamer_rx_ring[i].status = 0;
+ streamer_priv->streamer_rx_ring[i].buffer =
+ cpu_to_le32(pci_map_single(streamer_priv->pci_dev, skb->data,
+ streamer_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE));
+ streamer_priv->streamer_rx_ring[i].framelen_buflen = streamer_priv->pkt_buf_sz;
+ streamer_priv->rx_ring_skb[i] = skb;
+ }
+ streamer_priv->streamer_rx_ring[STREAMER_RX_RING_SIZE - 1].forward =
+ cpu_to_le32(pci_map_single(streamer_priv->pci_dev, &streamer_priv->streamer_rx_ring[0],
+ sizeof(struct streamer_rx_desc), PCI_DMA_FROMDEVICE));
+
+ if (i == 0) {
+ printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers. Adapter disabled\n", dev->name);
+ free_irq(dev->irq, dev);
+ return -EIO;
+ }
+
+ streamer_priv->rx_ring_last_received = STREAMER_RX_RING_SIZE - 1; /* last processed rx status */
+
+ writel(cpu_to_le32(pci_map_single(streamer_priv->pci_dev, &streamer_priv->streamer_rx_ring[0],
+ sizeof(struct streamer_rx_desc), PCI_DMA_TODEVICE)),
+ streamer_mmio + RXBDA);
+ writel(cpu_to_le32(pci_map_single(streamer_priv->pci_dev, &streamer_priv->streamer_rx_ring[STREAMER_RX_RING_SIZE - 1],
+ sizeof(struct streamer_rx_desc), PCI_DMA_TODEVICE)),
+ streamer_mmio + RXLBDA);
+
+ /* set bus master interrupt event mask */
+ writew(MISR_RX_NOBUF | MISR_RX_EOF, streamer_mmio + MISR_MASK);
+
+
+ /* setup tx ring */
+ streamer_priv->streamer_tx_ring=kmalloc(sizeof(struct streamer_tx_desc)*
+ STREAMER_TX_RING_SIZE,GFP_KERNEL);
+ if (!streamer_priv->streamer_tx_ring) {
+ printk(KERN_WARNING "%s ALLOC of streamer_tx_ring FAILED\n",dev->name);
+ return -EIO;
+ }
+
+ writew(~BMCTL_TX2_DIS, streamer_mmio + BMCTL_RUM); /* Enables TX channel 2 */
+ for (i = 0; i < STREAMER_TX_RING_SIZE; i++) {
+ streamer_priv->streamer_tx_ring[i].forward = cpu_to_le32(pci_map_single(streamer_priv->pci_dev,
+ &streamer_priv->streamer_tx_ring[i + 1],
+ sizeof(struct streamer_tx_desc),
+ PCI_DMA_TODEVICE));
+ streamer_priv->streamer_tx_ring[i].status = 0;
+ streamer_priv->streamer_tx_ring[i].bufcnt_framelen = 0;
+ streamer_priv->streamer_tx_ring[i].buffer = 0;
+ streamer_priv->streamer_tx_ring[i].buflen = 0;
+ streamer_priv->streamer_tx_ring[i].rsvd1 = 0;
+ streamer_priv->streamer_tx_ring[i].rsvd2 = 0;
+ streamer_priv->streamer_tx_ring[i].rsvd3 = 0;
+ }
+ streamer_priv->streamer_tx_ring[STREAMER_TX_RING_SIZE - 1].forward =
+ cpu_to_le32(pci_map_single(streamer_priv->pci_dev, &streamer_priv->streamer_tx_ring[0],
+ sizeof(struct streamer_tx_desc), PCI_DMA_TODEVICE));
+
+ streamer_priv->free_tx_ring_entries = STREAMER_TX_RING_SIZE;
+ streamer_priv->tx_ring_free = 0; /* next entry in tx ring to use */
+ streamer_priv->tx_ring_last_status = STREAMER_TX_RING_SIZE - 1;
+
+ /* set Busmaster interrupt event mask (handle receives on interrupt only */
+ writew(MISR_TX2_EOF | MISR_RX_NOBUF | MISR_RX_EOF, streamer_mmio + MISR_MASK);
+ /* set system event interrupt mask */
+ writew(SISR_ADAPTER_CHECK | SISR_ARB_CMD | SISR_TRB_REPLY | SISR_ASB_FREE, streamer_mmio + SISR_MASK_SUM);
+
+#if STREAMER_DEBUG
+ printk("BMCTL: %x\n", readw(streamer_mmio + BMCTL_SUM));
+ printk("SISR MASK: %x\n", readw(streamer_mmio + SISR_MASK));
+#endif
+
+#if STREAMER_NETWORK_MONITOR
+
+ writew(streamer_priv->streamer_addr_table_addr, streamer_mmio + LAPA);
+ printk("%s: Node Address: %04x:%04x:%04x\n", dev->name,
+ ntohs(readw(streamer_mmio + LAPDINC)),
+ ntohs(readw(streamer_mmio + LAPDINC)),
+ ntohs(readw(streamer_mmio + LAPDINC)));
+ readw(streamer_mmio + LAPDINC);
+ readw(streamer_mmio + LAPDINC);
+ printk("%s: Functional Address: %04x:%04x\n", dev->name,
+ ntohs(readw(streamer_mmio + LAPDINC)),
+ ntohs(readw(streamer_mmio + LAPDINC)));
+
+ writew(streamer_priv->streamer_parms_addr + 4,
+ streamer_mmio + LAPA);
+ printk("%s: NAUN Address: %04x:%04x:%04x\n", dev->name,
+ ntohs(readw(streamer_mmio + LAPDINC)),
+ ntohs(readw(streamer_mmio + LAPDINC)),
+ ntohs(readw(streamer_mmio + LAPDINC)));
+#endif
+
+ netif_start_queue(dev);
+ netif_carrier_on(dev);
+ return 0;
+}
+
+/*
+ * When we enter the rx routine we do not know how many frames have been
+ * queued on the rx channel. Therefore we start at the next rx status
+ * position and travel around the receive ring until we have completed
+ * all the frames.
+ *
+ * This means that we may process the frame before we receive the end
+ * of frame interrupt. This is why we always test the status instead
+ * of blindly processing the next frame.
+ *
+ */
+static void streamer_rx(struct net_device *dev)
+{
+ struct streamer_private *streamer_priv =
+ (struct streamer_private *) dev->priv;
+ __u8 __iomem *streamer_mmio = streamer_priv->streamer_mmio;
+ struct streamer_rx_desc *rx_desc;
+ int rx_ring_last_received, length, frame_length, buffer_cnt = 0;
+ struct sk_buff *skb, *skb2;
+
+ /* setup the next rx descriptor to be received */
+ rx_desc = &streamer_priv->streamer_rx_ring[(streamer_priv->rx_ring_last_received + 1) & (STREAMER_RX_RING_SIZE - 1)];
+ rx_ring_last_received = streamer_priv->rx_ring_last_received;
+
+ while (rx_desc->status & 0x01000000) { /* While processed descriptors are available */
+ if (rx_ring_last_received != streamer_priv->rx_ring_last_received)
+ {
+ printk(KERN_WARNING "RX Error 1 rx_ring_last_received not the same %x %x\n",
+ rx_ring_last_received, streamer_priv->rx_ring_last_received);
+ }
+ streamer_priv->rx_ring_last_received = (streamer_priv->rx_ring_last_received + 1) & (STREAMER_RX_RING_SIZE - 1);
+ rx_ring_last_received = streamer_priv->rx_ring_last_received;
+
+ length = rx_desc->framelen_buflen & 0xffff; /* buffer length */
+ frame_length = (rx_desc->framelen_buflen >> 16) & 0xffff;
+
+ if (rx_desc->status & 0x7E830000) { /* errors */
+ if (streamer_priv->streamer_message_level) {
+ printk(KERN_WARNING "%s: Rx Error %x \n",
+ dev->name, rx_desc->status);
+ }
+ } else { /* received without errors */
+ if (rx_desc->status & 0x80000000) { /* frame complete */
+ buffer_cnt = 1;
+ skb = dev_alloc_skb(streamer_priv->pkt_buf_sz);
+ } else {
+ skb = dev_alloc_skb(frame_length);
+ }
+
+ if (skb == NULL)
+ {
+ printk(KERN_WARNING "%s: Not enough memory to copy packet to upper layers. \n", dev->name);
+ streamer_priv->streamer_stats.rx_dropped++;
+ } else { /* we allocated an skb OK */
+ skb->dev = dev;
+
+ if (buffer_cnt == 1) {
+ /* release the DMA mapping */
+ pci_unmap_single(streamer_priv->pci_dev,
+ le32_to_cpu(streamer_priv->streamer_rx_ring[rx_ring_last_received].buffer),
+ streamer_priv->pkt_buf_sz,
+ PCI_DMA_FROMDEVICE);
+ skb2 = streamer_priv->rx_ring_skb[rx_ring_last_received];
+#if STREAMER_DEBUG_PACKETS
+ {
+ int i;
+ printk("streamer_rx packet print: skb->data2 %p skb->head %p\n", skb2->data, skb2->head);
+ for (i = 0; i < frame_length; i++)
+ {
+ printk("%x:", skb2->data[i]);
+ if (((i + 1) % 16) == 0)
+ printk("\n");
+ }
+ printk("\n");
+ }
+#endif
+ skb_put(skb2, length);
+ skb2->protocol = tr_type_trans(skb2, dev);
+ /* recycle this descriptor */
+ streamer_priv->streamer_rx_ring[rx_ring_last_received].status = 0;
+ streamer_priv->streamer_rx_ring[rx_ring_last_received].framelen_buflen = streamer_priv->pkt_buf_sz;
+ streamer_priv->streamer_rx_ring[rx_ring_last_received].buffer =
+ cpu_to_le32(pci_map_single(streamer_priv->pci_dev, skb->data, streamer_priv->pkt_buf_sz,
+ PCI_DMA_FROMDEVICE));
+ streamer_priv->rx_ring_skb[rx_ring_last_received] = skb;
+ /* place recycled descriptor back on the adapter */
+ writel(cpu_to_le32(pci_map_single(streamer_priv->pci_dev,
+ &streamer_priv->streamer_rx_ring[rx_ring_last_received],
+ sizeof(struct streamer_rx_desc), PCI_DMA_FROMDEVICE)),
+ streamer_mmio + RXLBDA);
+ /* pass the received skb up to the protocol */
+ netif_rx(skb2);
+ } else {
+ do { /* Walk the buffers */
+ pci_unmap_single(streamer_priv->pci_dev, le32_to_cpu(rx_desc->buffer), length, PCI_DMA_FROMDEVICE),
+ memcpy(skb_put(skb, length), (void *)rx_desc->buffer, length); /* copy this fragment */
+ streamer_priv->streamer_rx_ring[rx_ring_last_received].status = 0;
+ streamer_priv->streamer_rx_ring[rx_ring_last_received].framelen_buflen = streamer_priv->pkt_buf_sz;
+
+ /* give descriptor back to the adapter */
+ writel(cpu_to_le32(pci_map_single(streamer_priv->pci_dev,
+ &streamer_priv->streamer_rx_ring[rx_ring_last_received],
+ length, PCI_DMA_FROMDEVICE)),
+ streamer_mmio + RXLBDA);
+
+ if (rx_desc->status & 0x80000000)
+ break; /* this descriptor completes the frame */
+
+ /* else get the next pending descriptor */
+ if (rx_ring_last_received!= streamer_priv->rx_ring_last_received)
+ {
+ printk("RX Error rx_ring_last_received not the same %x %x\n",
+ rx_ring_last_received,
+ streamer_priv->rx_ring_last_received);
+ }
+ rx_desc = &streamer_priv->streamer_rx_ring[(streamer_priv->rx_ring_last_received+1) & (STREAMER_RX_RING_SIZE-1)];
+
+ length = rx_desc->framelen_buflen & 0xffff; /* buffer length */
+ streamer_priv->rx_ring_last_received = (streamer_priv->rx_ring_last_received+1) & (STREAMER_RX_RING_SIZE - 1);
+ rx_ring_last_received = streamer_priv->rx_ring_last_received;
+ } while (1);
+
+ skb->protocol = tr_type_trans(skb, dev);
+ /* send up to the protocol */
+ netif_rx(skb);
+ }
+ dev->last_rx = jiffies;
+ streamer_priv->streamer_stats.rx_packets++;
+ streamer_priv->streamer_stats.rx_bytes += length;
+ } /* if skb == null */
+ } /* end received without errors */
+
+ /* try the next one */
+ rx_desc = &streamer_priv->streamer_rx_ring[(rx_ring_last_received + 1) & (STREAMER_RX_RING_SIZE - 1)];
+ } /* end for all completed rx descriptors */
+}
+
+static irqreturn_t streamer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *) dev_id;
+ struct streamer_private *streamer_priv =
+ (struct streamer_private *) dev->priv;
+ __u8 __iomem *streamer_mmio = streamer_priv->streamer_mmio;
+ __u16 sisr;
+ __u16 misr;
+ u8 max_intr = MAX_INTR;
+
+ spin_lock(&streamer_priv->streamer_lock);
+ sisr = readw(streamer_mmio + SISR);
+
+ while((sisr & (SISR_MI | SISR_SRB_REPLY | SISR_ADAPTER_CHECK | SISR_ASB_FREE |
+ SISR_ARB_CMD | SISR_TRB_REPLY | SISR_PAR_ERR | SISR_SERR_ERR))
+ && (max_intr > 0)) {
+
+ if(sisr & SISR_PAR_ERR) {
+ writew(~SISR_PAR_ERR, streamer_mmio + SISR_RUM);
+ (void)readw(streamer_mmio + SISR_RUM);
+ }
+
+ else if(sisr & SISR_SERR_ERR) {
+ writew(~SISR_SERR_ERR, streamer_mmio + SISR_RUM);
+ (void)readw(streamer_mmio + SISR_RUM);
+ }
+
+ else if(sisr & SISR_MI) {
+ misr = readw(streamer_mmio + MISR_RUM);
+
+ if (misr & MISR_TX2_EOF) {
+ while(streamer_priv->streamer_tx_ring[(streamer_priv->tx_ring_last_status + 1) & (STREAMER_TX_RING_SIZE - 1)].status) {
+ streamer_priv->tx_ring_last_status = (streamer_priv->tx_ring_last_status + 1) & (STREAMER_TX_RING_SIZE - 1);
+ streamer_priv->free_tx_ring_entries++;
+ streamer_priv->streamer_stats.tx_bytes += streamer_priv->tx_ring_skb[streamer_priv->tx_ring_last_status]->len;
+ streamer_priv->streamer_stats.tx_packets++;
+ dev_kfree_skb_irq(streamer_priv->tx_ring_skb[streamer_priv->tx_ring_last_status]);
+ streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].buffer = 0xdeadbeef;
+ streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].status = 0;
+ streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].bufcnt_framelen = 0;
+ streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].buflen = 0;
+ streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].rsvd1 = 0;
+ streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].rsvd2 = 0;
+ streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].rsvd3 = 0;
+ }
+ netif_wake_queue(dev);
+ }
+
+ if (misr & MISR_RX_EOF) {
+ streamer_rx(dev);
+ }
+ /* MISR_RX_EOF */
+
+ if (misr & MISR_RX_NOBUF) {
+ /* According to the documentation, we don't have to do anything,
+ * but trapping it keeps it out of /var/log/messages.
+ */
+ } /* SISR_RX_NOBUF */
+
+ writew(~misr, streamer_mmio + MISR_RUM);
+ (void)readw(streamer_mmio + MISR_RUM);
+ }
+
+ else if (sisr & SISR_SRB_REPLY) {
+ if (streamer_priv->srb_queued == 1) {
+ wake_up_interruptible(&streamer_priv->srb_wait);
+ } else if (streamer_priv->srb_queued == 2) {
+ streamer_srb_bh(dev);
+ }
+ streamer_priv->srb_queued = 0;
+
+ writew(~SISR_SRB_REPLY, streamer_mmio + SISR_RUM);
+ (void)readw(streamer_mmio + SISR_RUM);
+ }
+
+ else if (sisr & SISR_ADAPTER_CHECK) {
+ printk(KERN_WARNING "%s: Adapter Check Interrupt Raised, 8 bytes of information follow:\n", dev->name);
+ writel(readl(streamer_mmio + LAPWWO), streamer_mmio + LAPA);
+ printk(KERN_WARNING "%s: Words %x:%x:%x:%x:\n",
+ dev->name, readw(streamer_mmio + LAPDINC),
+ ntohs(readw(streamer_mmio + LAPDINC)),
+ ntohs(readw(streamer_mmio + LAPDINC)),
+ ntohs(readw(streamer_mmio + LAPDINC)));
+ netif_stop_queue(dev);
+ netif_carrier_off(dev);
+ printk(KERN_WARNING "%s: Adapter must be manually reset.\n", dev->name);
+ }
+
+ /* SISR_ADAPTER_CHECK */
+ else if (sisr & SISR_ASB_FREE) {
+ /* Wake up anything that is waiting for the asb response */
+ if (streamer_priv->asb_queued) {
+ streamer_asb_bh(dev);
+ }
+ writew(~SISR_ASB_FREE, streamer_mmio + SISR_RUM);
+ (void)readw(streamer_mmio + SISR_RUM);
+ }
+ /* SISR_ASB_FREE */
+ else if (sisr & SISR_ARB_CMD) {
+ streamer_arb_cmd(dev);
+ writew(~SISR_ARB_CMD, streamer_mmio + SISR_RUM);
+ (void)readw(streamer_mmio + SISR_RUM);
+ }
+ /* SISR_ARB_CMD */
+ else if (sisr & SISR_TRB_REPLY) {
+ /* Wake up anything that is waiting for the trb response */
+ if (streamer_priv->trb_queued) {
+ wake_up_interruptible(&streamer_priv->
+ trb_wait);
+ }
+ streamer_priv->trb_queued = 0;
+ writew(~SISR_TRB_REPLY, streamer_mmio + SISR_RUM);
+ (void)readw(streamer_mmio + SISR_RUM);
+ }
+ /* SISR_TRB_REPLY */
+
+ sisr = readw(streamer_mmio + SISR);
+ max_intr--;
+ } /* while() */
+
+ spin_unlock(&streamer_priv->streamer_lock) ;
+ return IRQ_HANDLED;
+}
+
+static int streamer_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct streamer_private *streamer_priv =
+ (struct streamer_private *) dev->priv;
+ __u8 __iomem *streamer_mmio = streamer_priv->streamer_mmio;
+ unsigned long flags ;
+
+ spin_lock_irqsave(&streamer_priv->streamer_lock, flags);
+
+ if (streamer_priv->free_tx_ring_entries) {
+ streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].status = 0;
+ streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].bufcnt_framelen = 0x00020000 | skb->len;
+ streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].buffer =
+ cpu_to_le32(pci_map_single(streamer_priv->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE));
+ streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].rsvd1 = skb->len;
+ streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].rsvd2 = 0;
+ streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].rsvd3 = 0;
+ streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].buflen = skb->len;
+
+ streamer_priv->tx_ring_skb[streamer_priv->tx_ring_free] = skb;
+ streamer_priv->free_tx_ring_entries--;
+#if STREAMER_DEBUG_PACKETS
+ {
+ int i;
+ printk("streamer_xmit packet print:\n");
+ for (i = 0; i < skb->len; i++) {
+ printk("%x:", skb->data[i]);
+ if (((i + 1) % 16) == 0)
+ printk("\n");
+ }
+ printk("\n");
+ }
+#endif
+
+ writel(cpu_to_le32(pci_map_single(streamer_priv->pci_dev,
+ &streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free],
+ sizeof(struct streamer_tx_desc), PCI_DMA_TODEVICE)),
+ streamer_mmio + TX2LFDA);
+ (void)readl(streamer_mmio + TX2LFDA);
+
+ streamer_priv->tx_ring_free = (streamer_priv->tx_ring_free + 1) & (STREAMER_TX_RING_SIZE - 1);
+ spin_unlock_irqrestore(&streamer_priv->streamer_lock,flags);
+ return 0;
+ } else {
+ netif_stop_queue(dev);
+ spin_unlock_irqrestore(&streamer_priv->streamer_lock,flags);
+ return 1;
+ }
+}
+
+
+static int streamer_close(struct net_device *dev)
+{
+ struct streamer_private *streamer_priv =
+ (struct streamer_private *) dev->priv;
+ __u8 __iomem *streamer_mmio = streamer_priv->streamer_mmio;
+ unsigned long flags;
+ int i;
+
+ netif_stop_queue(dev);
+ netif_carrier_off(dev);
+ writew(streamer_priv->srb, streamer_mmio + LAPA);
+ writew(htons(SRB_CLOSE_ADAPTER << 8),streamer_mmio+LAPDINC);
+ writew(htons(STREAMER_CLEAR_RET_CODE << 8), streamer_mmio+LAPDINC);
+
+ spin_lock_irqsave(&streamer_priv->streamer_lock, flags);
+
+ streamer_priv->srb_queued = 1;
+ writew(LISR_SRB_CMD, streamer_mmio + LISR_SUM);
+
+ spin_unlock_irqrestore(&streamer_priv->streamer_lock, flags);
+
+ while (streamer_priv->srb_queued)
+ {
+ interruptible_sleep_on_timeout(&streamer_priv->srb_wait,
+ jiffies + 60 * HZ);
+ if (signal_pending(current))
+ {
+ printk(KERN_WARNING "%s: SRB timed out.\n", dev->name);
+ printk(KERN_WARNING "SISR=%x MISR=%x LISR=%x\n",
+ readw(streamer_mmio + SISR),
+ readw(streamer_mmio + MISR_RUM),
+ readw(streamer_mmio + LISR));
+ streamer_priv->srb_queued = 0;
+ break;
+ }
+ }
+
+ streamer_priv->rx_ring_last_received = (streamer_priv->rx_ring_last_received + 1) & (STREAMER_RX_RING_SIZE - 1);
+
+ for (i = 0; i < STREAMER_RX_RING_SIZE; i++) {
+ if (streamer_priv->rx_ring_skb[streamer_priv->rx_ring_last_received]) {
+ dev_kfree_skb(streamer_priv->rx_ring_skb[streamer_priv->rx_ring_last_received]);
+ }
+ streamer_priv->rx_ring_last_received = (streamer_priv->rx_ring_last_received + 1) & (STREAMER_RX_RING_SIZE - 1);
+ }
+
+ /* reset tx/rx fifo's and busmaster logic */
+
+ /* TBD. Add graceful way to reset the LLC channel without doing a soft reset.
+ writel(readl(streamer_mmio+BCTL)|(3<<13),streamer_mmio+BCTL);
+ udelay(1);
+ writel(readl(streamer_mmio+BCTL)&~(3<<13),streamer_mmio+BCTL);
+ */
+
+#if STREAMER_DEBUG
+ writew(streamer_priv->srb, streamer_mmio + LAPA);
+ printk("srb): ");
+ for (i = 0; i < 2; i++) {
+ printk("%x ", ntohs(readw(streamer_mmio + LAPDINC)));
+ }
+ printk("\n");
+#endif
+ free_irq(dev->irq, dev);
+ return 0;
+}
+
+static void streamer_set_rx_mode(struct net_device *dev)
+{
+ struct streamer_private *streamer_priv =
+ (struct streamer_private *) dev->priv;
+ __u8 __iomem *streamer_mmio = streamer_priv->streamer_mmio;
+ __u8 options = 0;
+ struct dev_mc_list *dmi;
+ unsigned char dev_mc_address[5];
+ int i;
+
+ writel(streamer_priv->srb, streamer_mmio + LAPA);
+ options = streamer_priv->streamer_copy_all_options;
+
+ if (dev->flags & IFF_PROMISC)
+ options |= (3 << 5); /* All LLC and MAC frames, all through the main rx channel */
+ else
+ options &= ~(3 << 5);
+
+ /* Only issue the srb if there is a change in options */
+
+ if ((options ^ streamer_priv->streamer_copy_all_options))
+ {
+ /* Now to issue the srb command to alter the copy.all.options */
+ writew(htons(SRB_MODIFY_RECEIVE_OPTIONS << 8), streamer_mmio+LAPDINC);
+ writew(htons(STREAMER_CLEAR_RET_CODE << 8), streamer_mmio+LAPDINC);
+ writew(htons((streamer_priv->streamer_receive_options << 8) | options),streamer_mmio+LAPDINC);
+ writew(htons(0x4a41),streamer_mmio+LAPDINC);
+ writew(htons(0x4d45),streamer_mmio+LAPDINC);
+ writew(htons(0x5320),streamer_mmio+LAPDINC);
+ writew(0x2020, streamer_mmio + LAPDINC);
+
+ streamer_priv->srb_queued = 2; /* Can't sleep, use srb_bh */
+
+ writel(LISR_SRB_CMD, streamer_mmio + LISR_SUM);
+
+ streamer_priv->streamer_copy_all_options = options;
+ return;
+ }
+
+ /* Set the functional addresses we need for multicast */
+ writel(streamer_priv->srb,streamer_mmio+LAPA);
+ dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ;
+
+ for (i=0,dmi=dev->mc_list;i < dev->mc_count; i++,dmi = dmi->next)
+ {
+ dev_mc_address[0] |= dmi->dmi_addr[2] ;
+ dev_mc_address[1] |= dmi->dmi_addr[3] ;
+ dev_mc_address[2] |= dmi->dmi_addr[4] ;
+ dev_mc_address[3] |= dmi->dmi_addr[5] ;
+ }
+
+ writew(htons(SRB_SET_FUNC_ADDRESS << 8),streamer_mmio+LAPDINC);
+ writew(htons(STREAMER_CLEAR_RET_CODE << 8), streamer_mmio+LAPDINC);
+ writew(0,streamer_mmio+LAPDINC);
+ writew(htons( (dev_mc_address[0] << 8) | dev_mc_address[1]),streamer_mmio+LAPDINC);
+ writew(htons( (dev_mc_address[2] << 8) | dev_mc_address[3]),streamer_mmio+LAPDINC);
+ streamer_priv->srb_queued = 2 ;
+ writel(LISR_SRB_CMD,streamer_mmio+LISR_SUM);
+}
+
+static void streamer_srb_bh(struct net_device *dev)
+{
+ struct streamer_private *streamer_priv = (struct streamer_private *) dev->priv;
+ __u8 __iomem *streamer_mmio = streamer_priv->streamer_mmio;
+ __u16 srb_word;
+
+ writew(streamer_priv->srb, streamer_mmio + LAPA);
+ srb_word=ntohs(readw(streamer_mmio+LAPDINC)) >> 8;
+
+ switch (srb_word) {
+
+ /* SRB_MODIFY_RECEIVE_OPTIONS i.e. set_multicast_list options (promiscuous)
+ * At some point we should do something if we get an error, such as
+ * resetting the IFF_PROMISC flag in dev
+ */
+
+ case SRB_MODIFY_RECEIVE_OPTIONS:
+ srb_word=ntohs(readw(streamer_mmio+LAPDINC)) >> 8;
+
+ switch (srb_word) {
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized srb command\n", dev->name);
+ break;
+ case 0x04:
+ printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n", dev->name);
+ break;
+ default:
+ if (streamer_priv->streamer_message_level)
+ printk(KERN_WARNING "%s: Receive Options Modified to %x,%x\n",
+ dev->name,
+ streamer_priv->streamer_copy_all_options,
+ streamer_priv->streamer_receive_options);
+ break;
+ } /* switch srb[2] */
+ break;
+
+
+ /* SRB_SET_GROUP_ADDRESS - Multicast group setting
+ */
+ case SRB_SET_GROUP_ADDRESS:
+ srb_word=ntohs(readw(streamer_mmio+LAPDINC)) >> 8;
+ switch (srb_word) {
+ case 0x00:
+ break;
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name);
+ break;
+ case 0x04:
+ printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n", dev->name);
+ break;
+ case 0x3c:
+ printk(KERN_WARNING "%s: Group/Functional address indicator bits not set correctly\n", dev->name);
+ break;
+ case 0x3e: /* If we ever implement individual multicast addresses, will need to deal with this */
+ printk(KERN_WARNING "%s: Group address registers full\n", dev->name);
+ break;
+ case 0x55:
+ printk(KERN_INFO "%s: Group Address already set.\n", dev->name);
+ break;
+ default:
+ break;
+ } /* switch srb[2] */
+ break;
+
+
+ /* SRB_RESET_GROUP_ADDRESS - Remove a multicast address from group list
+ */
+ case SRB_RESET_GROUP_ADDRESS:
+ srb_word=ntohs(readw(streamer_mmio+LAPDINC)) >> 8;
+ switch (srb_word) {
+ case 0x00:
+ break;
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized srb command \n", dev->name);
+ break;
+ case 0x04:
+ printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n", dev->name);
+ break;
+ case 0x39: /* Must deal with this if individual multicast addresses used */
+ printk(KERN_INFO "%s: Group address not found \n", dev->name);
+ break;
+ default:
+ break;
+ } /* switch srb[2] */
+ break;
+
+
+ /* SRB_SET_FUNC_ADDRESS - Called by the set_rx_mode
+ */
+
+ case SRB_SET_FUNC_ADDRESS:
+ srb_word=ntohs(readw(streamer_mmio+LAPDINC)) >> 8;
+ switch (srb_word) {
+ case 0x00:
+ if (streamer_priv->streamer_message_level)
+ printk(KERN_INFO "%s: Functional Address Mask Set \n", dev->name);
+ break;
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized srb command \n", dev->name);
+ break;
+ case 0x04:
+ printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n", dev->name);
+ break;
+ default:
+ break;
+ } /* switch srb[2] */
+ break;
+
+ /* SRB_READ_LOG - Read and reset the adapter error counters
+ */
+
+ case SRB_READ_LOG:
+ srb_word=ntohs(readw(streamer_mmio+LAPDINC)) >> 8;
+ switch (srb_word) {
+ case 0x00:
+ {
+ int i;
+ if (streamer_priv->streamer_message_level)
+ printk(KERN_INFO "%s: Read Log command complete\n", dev->name);
+ printk("Read Log statistics: ");
+ writew(streamer_priv->srb + 6,
+ streamer_mmio + LAPA);
+ for (i = 0; i < 5; i++) {
+ printk("%x:", ntohs(readw(streamer_mmio + LAPDINC)));
+ }
+ printk("\n");
+ }
+ break;
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized srb command \n", dev->name);
+ break;
+ case 0x04:
+ printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n", dev->name);
+ break;
+
+ } /* switch srb[2] */
+ break;
+
+ /* SRB_READ_SR_COUNTERS - Read and reset the source routing bridge related counters */
+
+ case SRB_READ_SR_COUNTERS:
+ srb_word=ntohs(readw(streamer_mmio+LAPDINC)) >> 8;
+ switch (srb_word) {
+ case 0x00:
+ if (streamer_priv->streamer_message_level)
+ printk(KERN_INFO "%s: Read Source Routing Counters issued\n", dev->name);
+ break;
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized srb command \n", dev->name);
+ break;
+ case 0x04:
+ printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n", dev->name);
+ break;
+ default:
+ break;
+ } /* switch srb[2] */
+ break;
+
+ default:
+ printk(KERN_WARNING "%s: Unrecognized srb bh return value.\n", dev->name);
+ break;
+ } /* switch srb[0] */
+}
+
+static struct net_device_stats *streamer_get_stats(struct net_device *dev)
+{
+ struct streamer_private *streamer_priv;
+ streamer_priv = (struct streamer_private *) dev->priv;
+ return (struct net_device_stats *) &streamer_priv->streamer_stats;
+}
+
+static int streamer_set_mac_address(struct net_device *dev, void *addr)
+{
+ struct sockaddr *saddr = addr;
+ struct streamer_private *streamer_priv = (struct streamer_private *) dev->priv;
+
+ if (netif_running(dev))
+ {
+ printk(KERN_WARNING "%s: Cannot set mac/laa address while card is open\n", dev->name);
+ return -EIO;
+ }
+
+ memcpy(streamer_priv->streamer_laa, saddr->sa_data, dev->addr_len);
+
+ if (streamer_priv->streamer_message_level) {
+ printk(KERN_INFO "%s: MAC/LAA Set to = %x.%x.%x.%x.%x.%x\n",
+ dev->name, streamer_priv->streamer_laa[0],
+ streamer_priv->streamer_laa[1],
+ streamer_priv->streamer_laa[2],
+ streamer_priv->streamer_laa[3],
+ streamer_priv->streamer_laa[4],
+ streamer_priv->streamer_laa[5]);
+ }
+ return 0;
+}
+
+static void streamer_arb_cmd(struct net_device *dev)
+{
+ struct streamer_private *streamer_priv =
+ (struct streamer_private *) dev->priv;
+ __u8 __iomem *streamer_mmio = streamer_priv->streamer_mmio;
+ __u8 header_len;
+ __u16 frame_len, buffer_len;
+ struct sk_buff *mac_frame;
+ __u8 frame_data[256];
+ __u16 buff_off;
+ __u16 lan_status = 0, lan_status_diff; /* Initialize to stop compiler warning */
+ __u8 fdx_prot_error;
+ __u16 next_ptr;
+ __u16 arb_word;
+
+#if STREAMER_NETWORK_MONITOR
+ struct trh_hdr *mac_hdr;
+#endif
+
+ writew(streamer_priv->arb, streamer_mmio + LAPA);
+ arb_word=ntohs(readw(streamer_mmio+LAPD)) >> 8;
+
+ if (arb_word == ARB_RECEIVE_DATA) { /* Receive.data, MAC frames */
+ writew(streamer_priv->arb + 6, streamer_mmio + LAPA);
+ streamer_priv->mac_rx_buffer = buff_off = ntohs(readw(streamer_mmio + LAPDINC));
+ header_len=ntohs(readw(streamer_mmio+LAPDINC)) >> 8; /* 802.5 Token-Ring Header Length */
+ frame_len = ntohs(readw(streamer_mmio + LAPDINC));
+
+#if STREAMER_DEBUG
+ {
+ int i;
+ __u16 next;
+ __u8 status;
+ __u16 len;
+
+ writew(ntohs(buff_off), streamer_mmio + LAPA); /*setup window to frame data */
+ next = htons(readw(streamer_mmio + LAPDINC));
+ status =
+ ntohs(readw(streamer_mmio + LAPDINC)) & 0xff;
+ len = ntohs(readw(streamer_mmio + LAPDINC));
+
+ /* print out 1st 14 bytes of frame data */
+ for (i = 0; i < 7; i++) {
+ printk("Loc %d = %04x\n", i,
+ ntohs(readw
+ (streamer_mmio + LAPDINC)));
+ }
+
+ printk("next %04x, fs %02x, len %04x \n", next,
+ status, len);
+ }
+#endif
+ if (!(mac_frame = dev_alloc_skb(frame_len))) {
+ printk(KERN_WARNING "%s: Memory squeeze, dropping frame.\n",
+ dev->name);
+ goto drop_frame;
+ }
+ /* Walk the buffer chain, creating the frame */
+
+ do {
+ int i;
+ __u16 rx_word;
+
+ writew(htons(buff_off), streamer_mmio + LAPA); /* setup window to frame data */
+ next_ptr = ntohs(readw(streamer_mmio + LAPDINC));
+ readw(streamer_mmio + LAPDINC); /* read thru status word */
+ buffer_len = ntohs(readw(streamer_mmio + LAPDINC));
+
+ if (buffer_len > 256)
+ break;
+
+ i = 0;
+ while (i < buffer_len) {
+ rx_word=ntohs(readw(streamer_mmio+LAPDINC));
+ frame_data[i]=rx_word >> 8;
+ frame_data[i+1]=rx_word & 0xff;
+ i += 2;
+ }
+
+ memcpy(skb_put(mac_frame, buffer_len),
+ frame_data, buffer_len);
+ } while (next_ptr && (buff_off = next_ptr));
+
+#if STREAMER_NETWORK_MONITOR
+ printk(KERN_WARNING "%s: Received MAC Frame, details: \n",
+ dev->name);
+ mac_hdr = (struct trh_hdr *) mac_frame->data;
+ printk(KERN_WARNING
+ "%s: MAC Frame Dest. Addr: %02x:%02x:%02x:%02x:%02x:%02x \n",
+ dev->name, mac_hdr->daddr[0], mac_hdr->daddr[1],
+ mac_hdr->daddr[2], mac_hdr->daddr[3],
+ mac_hdr->daddr[4], mac_hdr->daddr[5]);
+ printk(KERN_WARNING
+ "%s: MAC Frame Srce. Addr: %02x:%02x:%02x:%02x:%02x:%02x \n",
+ dev->name, mac_hdr->saddr[0], mac_hdr->saddr[1],
+ mac_hdr->saddr[2], mac_hdr->saddr[3],
+ mac_hdr->saddr[4], mac_hdr->saddr[5]);
+#endif
+ mac_frame->dev = dev;
+ mac_frame->protocol = tr_type_trans(mac_frame, dev);
+ netif_rx(mac_frame);
+
+ /* Now tell the card we have dealt with the received frame */
+drop_frame:
+ /* Set LISR Bit 1 */
+ writel(LISR_ARB_FREE, streamer_priv->streamer_mmio + LISR_SUM);
+
+ /* Is the ASB free ? */
+
+ if (!(readl(streamer_priv->streamer_mmio + SISR) & SISR_ASB_FREE))
+ {
+ streamer_priv->asb_queued = 1;
+ writel(LISR_ASB_FREE_REQ, streamer_priv->streamer_mmio + LISR_SUM);
+ return;
+ /* Drop out and wait for the bottom half to be run */
+ }
+
+
+ writew(streamer_priv->asb, streamer_mmio + LAPA);
+ writew(htons(ASB_RECEIVE_DATA << 8), streamer_mmio+LAPDINC);
+ writew(htons(STREAMER_CLEAR_RET_CODE << 8), streamer_mmio+LAPDINC);
+ writew(0, streamer_mmio + LAPDINC);
+ writew(htons(streamer_priv->mac_rx_buffer), streamer_mmio + LAPD);
+
+ writel(LISR_ASB_REPLY | LISR_ASB_FREE_REQ, streamer_priv->streamer_mmio + LISR_SUM);
+
+ streamer_priv->asb_queued = 2;
+ return;
+
+ } else if (arb_word == ARB_LAN_CHANGE_STATUS) { /* Lan.change.status */
+ writew(streamer_priv->arb + 6, streamer_mmio + LAPA);
+ lan_status = ntohs(readw(streamer_mmio + LAPDINC));
+ fdx_prot_error = ntohs(readw(streamer_mmio+LAPD)) >> 8;
+
+ /* Issue ARB Free */
+ writew(LISR_ARB_FREE, streamer_priv->streamer_mmio + LISR_SUM);
+
+ lan_status_diff = (streamer_priv->streamer_lan_status ^ lan_status) &
+ lan_status;
+
+ if (lan_status_diff & (LSC_LWF | LSC_ARW | LSC_FPE | LSC_RR))
+ {
+ if (lan_status_diff & LSC_LWF)
+ printk(KERN_WARNING "%s: Short circuit detected on the lobe\n", dev->name);
+ if (lan_status_diff & LSC_ARW)
+ printk(KERN_WARNING "%s: Auto removal error\n", dev->name);
+ if (lan_status_diff & LSC_FPE)
+ printk(KERN_WARNING "%s: FDX Protocol Error\n", dev->name);
+ if (lan_status_diff & LSC_RR)
+ printk(KERN_WARNING "%s: Force remove MAC frame received\n", dev->name);
+
+ /* Adapter has been closed by the hardware */
+
+ /* reset tx/rx fifo's and busmaster logic */
+
+ /* @TBD. no llc reset on autostreamer writel(readl(streamer_mmio+BCTL)|(3<<13),streamer_mmio+BCTL);
+ udelay(1);
+ writel(readl(streamer_mmio+BCTL)&~(3<<13),streamer_mmio+BCTL); */
+
+ netif_stop_queue(dev);
+ netif_carrier_off(dev);
+ printk(KERN_WARNING "%s: Adapter must be manually reset.\n", dev->name);
+ }
+ /* If serious error */
+ if (streamer_priv->streamer_message_level) {
+ if (lan_status_diff & LSC_SIG_LOSS)
+ printk(KERN_WARNING "%s: No receive signal detected \n", dev->name);
+ if (lan_status_diff & LSC_HARD_ERR)
+ printk(KERN_INFO "%s: Beaconing \n", dev->name);
+ if (lan_status_diff & LSC_SOFT_ERR)
+ printk(KERN_WARNING "%s: Adapter transmitted Soft Error Report Mac Frame \n", dev->name);
+ if (lan_status_diff & LSC_TRAN_BCN)
+ printk(KERN_INFO "%s: We are tranmitting the beacon, aaah\n", dev->name);
+ if (lan_status_diff & LSC_SS)
+ printk(KERN_INFO "%s: Single Station on the ring \n", dev->name);
+ if (lan_status_diff & LSC_RING_REC)
+ printk(KERN_INFO "%s: Ring recovery ongoing\n", dev->name);
+ if (lan_status_diff & LSC_FDX_MODE)
+ printk(KERN_INFO "%s: Operating in FDX mode\n", dev->name);
+ }
+
+ if (lan_status_diff & LSC_CO) {
+ if (streamer_priv->streamer_message_level)
+ printk(KERN_INFO "%s: Counter Overflow \n", dev->name);
+
+ /* Issue READ.LOG command */
+
+ writew(streamer_priv->srb, streamer_mmio + LAPA);
+ writew(htons(SRB_READ_LOG << 8),streamer_mmio+LAPDINC);
+ writew(htons(STREAMER_CLEAR_RET_CODE << 8), streamer_mmio+LAPDINC);
+ writew(0, streamer_mmio + LAPDINC);
+ streamer_priv->srb_queued = 2; /* Can't sleep, use srb_bh */
+
+ writew(LISR_SRB_CMD, streamer_mmio + LISR_SUM);
+ }
+
+ if (lan_status_diff & LSC_SR_CO) {
+ if (streamer_priv->streamer_message_level)
+ printk(KERN_INFO "%s: Source routing counters overflow\n", dev->name);
+
+ /* Issue a READ.SR.COUNTERS */
+ writew(streamer_priv->srb, streamer_mmio + LAPA);
+ writew(htons(SRB_READ_SR_COUNTERS << 8),
+ streamer_mmio+LAPDINC);
+ writew(htons(STREAMER_CLEAR_RET_CODE << 8),
+ streamer_mmio+LAPDINC);
+ streamer_priv->srb_queued = 2; /* Can't sleep, use srb_bh */
+ writew(LISR_SRB_CMD, streamer_mmio + LISR_SUM);
+
+ }
+ streamer_priv->streamer_lan_status = lan_status;
+ } /* Lan.change.status */
+ else
+ printk(KERN_WARNING "%s: Unknown arb command \n", dev->name);
+}
+
+static void streamer_asb_bh(struct net_device *dev)
+{
+ struct streamer_private *streamer_priv =
+ (struct streamer_private *) dev->priv;
+ __u8 __iomem *streamer_mmio = streamer_priv->streamer_mmio;
+
+ if (streamer_priv->asb_queued == 1)
+ {
+ /* Dropped through the first time */
+
+ writew(streamer_priv->asb, streamer_mmio + LAPA);
+ writew(htons(ASB_RECEIVE_DATA << 8),streamer_mmio+LAPDINC);
+ writew(htons(STREAMER_CLEAR_RET_CODE << 8), streamer_mmio+LAPDINC);
+ writew(0, streamer_mmio + LAPDINC);
+ writew(htons(streamer_priv->mac_rx_buffer), streamer_mmio + LAPD);
+
+ writel(LISR_ASB_REPLY | LISR_ASB_FREE_REQ, streamer_priv->streamer_mmio + LISR_SUM);
+ streamer_priv->asb_queued = 2;
+
+ return;
+ }
+
+ if (streamer_priv->asb_queued == 2) {
+ __u8 rc;
+ writew(streamer_priv->asb + 2, streamer_mmio + LAPA);
+ rc=ntohs(readw(streamer_mmio+LAPD)) >> 8;
+ switch (rc) {
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized command code \n", dev->name);
+ break;
+ case 0x26:
+ printk(KERN_WARNING "%s: Unrecognized buffer address \n", dev->name);
+ break;
+ case 0xFF:
+ /* Valid response, everything should be ok again */
+ break;
+ default:
+ printk(KERN_WARNING "%s: Invalid return code in asb\n", dev->name);
+ break;
+ }
+ }
+ streamer_priv->asb_queued = 0;
+}
+
+static int streamer_change_mtu(struct net_device *dev, int mtu)
+{
+ struct streamer_private *streamer_priv =
+ (struct streamer_private *) dev->priv;
+ __u16 max_mtu;
+
+ if (streamer_priv->streamer_ring_speed == 4)
+ max_mtu = 4500;
+ else
+ max_mtu = 18000;
+
+ if (mtu > max_mtu)
+ return -EINVAL;
+ if (mtu < 100)
+ return -EINVAL;
+
+ dev->mtu = mtu;
+ streamer_priv->pkt_buf_sz = mtu + TR_HLEN;
+
+ return 0;
+}
+
+#if STREAMER_NETWORK_MONITOR
+#ifdef CONFIG_PROC_FS
+static int streamer_proc_info(char *buffer, char **start, off_t offset,
+ int length, int *eof, void *data)
+{
+ struct streamer_private *sdev=NULL;
+ struct pci_dev *pci_device = NULL;
+ int len = 0;
+ off_t begin = 0;
+ off_t pos = 0;
+ int size;
+
+ struct net_device *dev;
+
+ size = sprintf(buffer, "IBM LanStreamer/MPC Chipset Token Ring Adapters\n");
+
+ pos += size;
+ len += size;
+
+ for(sdev=dev_streamer; sdev; sdev=sdev->next) {
+ pci_device=sdev->pci_dev;
+ dev=pci_get_drvdata(pci_device);
+
+ size = sprintf_info(buffer + len, dev);
+ len += size;
+ pos = begin + len;
+
+ if (pos < offset) {
+ len = 0;
+ begin = pos;
+ }
+ if (pos > offset + length)
+ break;
+ } /* for */
+
+ *start = buffer + (offset - begin); /* Start of wanted data */
+ len -= (offset - begin); /* Start slop */
+ if (len > length)
+ len = length; /* Ending slop */
+ return len;
+}
+
+static int sprintf_info(char *buffer, struct net_device *dev)
+{
+ struct streamer_private *streamer_priv =
+ (struct streamer_private *) dev->priv;
+ __u8 __iomem *streamer_mmio = streamer_priv->streamer_mmio;
+ struct streamer_adapter_addr_table sat;
+ struct streamer_parameters_table spt;
+ int size = 0;
+ int i;
+
+ writew(streamer_priv->streamer_addr_table_addr, streamer_mmio + LAPA);
+ for (i = 0; i < 14; i += 2) {
+ __u16 io_word;
+ __u8 *datap = (__u8 *) & sat;
+ io_word=ntohs(readw(streamer_mmio+LAPDINC));
+ datap[size]=io_word >> 8;
+ datap[size+1]=io_word & 0xff;
+ }
+ writew(streamer_priv->streamer_parms_addr, streamer_mmio + LAPA);
+ for (i = 0; i < 68; i += 2) {
+ __u16 io_word;
+ __u8 *datap = (__u8 *) & spt;
+ io_word=ntohs(readw(streamer_mmio+LAPDINC));
+ datap[size]=io_word >> 8;
+ datap[size+1]=io_word & 0xff;
+ }
+
+
+ size = sprintf(buffer, "\n%6s: Adapter Address : Node Address : Functional Addr\n", dev->name);
+
+ size += sprintf(buffer + size,
+ "%6s: %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x\n",
+ dev->name, dev->dev_addr[0], dev->dev_addr[1],
+ dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4],
+ dev->dev_addr[5], sat.node_addr[0], sat.node_addr[1],
+ sat.node_addr[2], sat.node_addr[3], sat.node_addr[4],
+ sat.node_addr[5], sat.func_addr[0], sat.func_addr[1],
+ sat.func_addr[2], sat.func_addr[3]);
+
+ size += sprintf(buffer + size, "\n%6s: Token Ring Parameters Table:\n", dev->name);
+
+ size += sprintf(buffer + size, "%6s: Physical Addr : Up Node Address : Poll Address : AccPri : Auth Src : Att Code :\n", dev->name);
+
+ size += sprintf(buffer + size,
+ "%6s: %02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x:%02x:%02x : %04x : %04x : %04x :\n",
+ dev->name, spt.phys_addr[0], spt.phys_addr[1],
+ spt.phys_addr[2], spt.phys_addr[3],
+ spt.up_node_addr[0], spt.up_node_addr[1],
+ spt.up_node_addr[2], spt.up_node_addr[3],
+ spt.up_node_addr[4], spt.up_node_addr[4],
+ spt.poll_addr[0], spt.poll_addr[1], spt.poll_addr[2],
+ spt.poll_addr[3], spt.poll_addr[4], spt.poll_addr[5],
+ ntohs(spt.acc_priority), ntohs(spt.auth_source_class),
+ ntohs(spt.att_code));
+
+ size += sprintf(buffer + size, "%6s: Source Address : Bcn T : Maj. V : Lan St : Lcl Rg : Mon Err : Frame Correl : \n", dev->name);
+
+ size += sprintf(buffer + size,
+ "%6s: %02x:%02x:%02x:%02x:%02x:%02x : %04x : %04x : %04x : %04x : %04x : %04x : \n",
+ dev->name, spt.source_addr[0], spt.source_addr[1],
+ spt.source_addr[2], spt.source_addr[3],
+ spt.source_addr[4], spt.source_addr[5],
+ ntohs(spt.beacon_type), ntohs(spt.major_vector),
+ ntohs(spt.lan_status), ntohs(spt.local_ring),
+ ntohs(spt.mon_error), ntohs(spt.frame_correl));
+
+ size += sprintf(buffer + size, "%6s: Beacon Details : Tx : Rx : NAUN Node Address : NAUN Node Phys : \n",
+ dev->name);
+
+ size += sprintf(buffer + size,
+ "%6s: : %02x : %02x : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x : \n",
+ dev->name, ntohs(spt.beacon_transmit),
+ ntohs(spt.beacon_receive), spt.beacon_naun[0],
+ spt.beacon_naun[1], spt.beacon_naun[2],
+ spt.beacon_naun[3], spt.beacon_naun[4],
+ spt.beacon_naun[5], spt.beacon_phys[0],
+ spt.beacon_phys[1], spt.beacon_phys[2],
+ spt.beacon_phys[3]);
+ return size;
+}
+#endif
+#endif
+
+#if STREAMER_IOCTL && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+static int streamer_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ int i;
+ struct streamer_private *streamer_priv = (struct streamer_private *) dev->priv;
+ u8 __iomem *streamer_mmio = streamer_priv->streamer_mmio;
+
+ switch(cmd) {
+ case IOCTL_SISR_MASK:
+ writew(SISR_MI, streamer_mmio + SISR_MASK_SUM);
+ break;
+ case IOCTL_SPIN_LOCK_TEST:
+ printk(KERN_INFO "spin_lock() called.\n");
+ spin_lock(&streamer_priv->streamer_lock);
+ spin_unlock(&streamer_priv->streamer_lock);
+ printk(KERN_INFO "spin_unlock() finished.\n");
+ break;
+ case IOCTL_PRINT_BDAS:
+ printk(KERN_INFO "bdas: RXBDA: %x RXLBDA: %x TX2FDA: %x TX2LFDA: %x\n",
+ readw(streamer_mmio + RXBDA),
+ readw(streamer_mmio + RXLBDA),
+ readw(streamer_mmio + TX2FDA),
+ readw(streamer_mmio + TX2LFDA));
+ break;
+ case IOCTL_PRINT_REGISTERS:
+ printk(KERN_INFO "registers:\n");
+ printk(KERN_INFO "SISR: %04x MISR: %04x LISR: %04x BCTL: %04x BMCTL: %04x\nmask %04x mask %04x\n",
+ readw(streamer_mmio + SISR),
+ readw(streamer_mmio + MISR_RUM),
+ readw(streamer_mmio + LISR),
+ readw(streamer_mmio + BCTL),
+ readw(streamer_mmio + BMCTL_SUM),
+ readw(streamer_mmio + SISR_MASK),
+ readw(streamer_mmio + MISR_MASK));
+ break;
+ case IOCTL_PRINT_RX_BUFS:
+ printk(KERN_INFO "Print rx bufs:\n");
+ for(i=0; i<STREAMER_RX_RING_SIZE; i++)
+ printk(KERN_INFO "rx_ring %d status: 0x%x\n", i,
+ streamer_priv->streamer_rx_ring[i].status);
+ break;
+ case IOCTL_PRINT_TX_BUFS:
+ printk(KERN_INFO "Print tx bufs:\n");
+ for(i=0; i<STREAMER_TX_RING_SIZE; i++)
+ printk(KERN_INFO "tx_ring %d status: 0x%x\n", i,
+ streamer_priv->streamer_tx_ring[i].status);
+ break;
+ case IOCTL_RX_CMD:
+ streamer_rx(dev);
+ printk(KERN_INFO "Sent rx command.\n");
+ break;
+ default:
+ printk(KERN_INFO "Bad ioctl!\n");
+ }
+ return 0;
+}
+#endif
+
+static struct pci_driver streamer_pci_driver = {
+ .name = "lanstreamer",
+ .id_table = streamer_pci_tbl,
+ .probe = streamer_init_one,
+ .remove = __devexit_p(streamer_remove_one),
+};
+
+static int __init streamer_init_module(void) {
+ return pci_module_init(&streamer_pci_driver);
+}
+
+static void __exit streamer_cleanup_module(void) {
+ pci_unregister_driver(&streamer_pci_driver);
+}
+
+module_init(streamer_init_module);
+module_exit(streamer_cleanup_module);
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/tokenring/lanstreamer.h b/drivers/net/tokenring/lanstreamer.h
new file mode 100644
index 00000000000..5557d8e1e22
--- /dev/null
+++ b/drivers/net/tokenring/lanstreamer.h
@@ -0,0 +1,358 @@
+/*
+ * lanstreamer.h -- driver for the IBM Auto LANStreamer PCI Adapter
+ *
+ * Written By: Mike Sullivan, IBM Corporation
+ *
+ * Copyright (C) 1999 IBM Corporation
+ *
+ * Linux driver for IBM PCI tokenring cards based on the LanStreamer MPC
+ * chipset.
+ *
+ * This driver is based on the olympic driver for IBM PCI TokenRing cards (Pit/Pit-Phy/Olympic
+ * chipsets) written by:
+ * 1999 Peter De Schrijver All Rights Reserved
+ * 1999 Mike Phillips (phillim@amtrak.com)
+ *
+ * Base Driver Skeleton:
+ * Written 1993-94 by Donald Becker.
+ *
+ * Copyright 1993 United States Government as represented by the
+ * Director, National Security Agency.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+ *
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *
+ * 12/10/99 - Alpha Release 0.1.0
+ * First release to the public
+ * 08/15/01 - Added ioctl() definitions and others - Kent Yoder <yoder1@us.ibm.com>
+ *
+ */
+
+#include <linux/version.h>
+
+#if STREAMER_IOCTL && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+#include <asm/ioctl.h>
+#define IOCTL_PRINT_RX_BUFS SIOCDEVPRIVATE
+#define IOCTL_PRINT_TX_BUFS SIOCDEVPRIVATE+1
+#define IOCTL_RX_CMD SIOCDEVPRIVATE+2
+#define IOCTL_TX_CMD SIOCDEVPRIVATE+3
+#define IOCTL_PRINT_REGISTERS SIOCDEVPRIVATE+4
+#define IOCTL_PRINT_BDAS SIOCDEVPRIVATE+5
+#define IOCTL_SPIN_LOCK_TEST SIOCDEVPRIVATE+6
+#define IOCTL_SISR_MASK SIOCDEVPRIVATE+7
+#endif
+
+/* MAX_INTR - the maximum number of times we can loop
+ * inside the interrupt function before returning
+ * control to the OS (maximum value is 256)
+ */
+#define MAX_INTR 5
+
+#define CLS 0x0C
+#define MLR 0x86
+#define LTR 0x0D
+
+#define BCTL 0x60
+#define BCTL_SOFTRESET (1<<15)
+#define BCTL_RX_FIFO_8 (1<<1)
+#define BCTL_TX_FIFO_8 (1<<3)
+
+#define GPR 0x4a
+#define GPR_AUTOSENSE (1<<2)
+#define GPR_16MBPS (1<<3)
+
+#define LISR 0x10
+#define LISR_SUM 0x12
+#define LISR_RUM 0x14
+
+#define LISR_LIE (1<<15)
+#define LISR_SLIM (1<<13)
+#define LISR_SLI (1<<12)
+#define LISR_BPEI (1<<9)
+#define LISR_BPE (1<<8)
+#define LISR_SRB_CMD (1<<5)
+#define LISR_ASB_REPLY (1<<4)
+#define LISR_ASB_FREE_REQ (1<<2)
+#define LISR_ARB_FREE (1<<1)
+#define LISR_TRB_FRAME (1<<0)
+
+#define SISR 0x16
+#define SISR_SUM 0x18
+#define SISR_RUM 0x1A
+#define SISR_MASK 0x54
+#define SISR_MASK_SUM 0x56
+#define SISR_MASK_RUM 0x58
+
+#define SISR_MI (1<<15)
+#define SISR_SERR_ERR (1<<14)
+#define SISR_TIMER (1<<11)
+#define SISR_LAP_PAR_ERR (1<<10)
+#define SISR_LAP_ACC_ERR (1<<9)
+#define SISR_PAR_ERR (1<<8)
+#define SISR_ADAPTER_CHECK (1<<6)
+#define SISR_SRB_REPLY (1<<5)
+#define SISR_ASB_FREE (1<<4)
+#define SISR_ARB_CMD (1<<3)
+#define SISR_TRB_REPLY (1<<2)
+
+#define MISR_RUM 0x5A
+#define MISR_MASK 0x5C
+#define MISR_MASK_RUM 0x5E
+
+#define MISR_TX2_IDLE (1<<15)
+#define MISR_TX2_NO_STATUS (1<<14)
+#define MISR_TX2_HALT (1<<13)
+#define MISR_TX2_EOF (1<<12)
+#define MISR_TX1_IDLE (1<<11)
+#define MISR_TX1_NO_STATUS (1<<10)
+#define MISR_TX1_HALT (1<<9)
+#define MISR_TX1_EOF (1<<8)
+#define MISR_RX_NOBUF (1<<5)
+#define MISR_RX_EOB (1<<4)
+#define MISR_RX_NO_STATUS (1<<2)
+#define MISR_RX_HALT (1<<1)
+#define MISR_RX_EOF (1<<0)
+
+#define LAPA 0x62
+#define LAPE 0x64
+#define LAPD 0x66
+#define LAPDINC 0x68
+#define LAPWWO 0x6A
+#define LAPWWC 0x6C
+#define LAPCTL 0x6E
+
+#define TIMER 0x4E4
+
+#define BMCTL_SUM 0x50
+#define BMCTL_RUM 0x52
+#define BMCTL_TX1_DIS (1<<14)
+#define BMCTL_TX2_DIS (1<<10)
+#define BMCTL_RX_DIS (1<<6)
+#define BMCTL_RX_ENABLED (1<<5)
+
+#define RXLBDA 0x90
+#define RXBDA 0x94
+#define RXSTAT 0x98
+#define RXDBA 0x9C
+
+#define TX1LFDA 0xA0
+#define TX1FDA 0xA4
+#define TX1STAT 0xA8
+#define TX1DBA 0xAC
+#define TX2LFDA 0xB0
+#define TX2FDA 0xB4
+#define TX2STAT 0xB8
+#define TX2DBA 0xBC
+
+#define STREAMER_IO_SPACE 256
+
+#define SRB_COMMAND_SIZE 50
+
+#define STREAMER_MAX_ADAPTERS 8 /* 0x08 __MODULE_STRING can't hand 0xnn */
+
+/* Defines for LAN STATUS CHANGE reports */
+#define LSC_SIG_LOSS 0x8000
+#define LSC_HARD_ERR 0x4000
+#define LSC_SOFT_ERR 0x2000
+#define LSC_TRAN_BCN 0x1000
+#define LSC_LWF 0x0800
+#define LSC_ARW 0x0400
+#define LSC_FPE 0x0200
+#define LSC_RR 0x0100
+#define LSC_CO 0x0080
+#define LSC_SS 0x0040
+#define LSC_RING_REC 0x0020
+#define LSC_SR_CO 0x0010
+#define LSC_FDX_MODE 0x0004
+
+/* Defines for OPEN ADAPTER command */
+
+#define OPEN_ADAPTER_EXT_WRAP (1<<15)
+#define OPEN_ADAPTER_DIS_HARDEE (1<<14)
+#define OPEN_ADAPTER_DIS_SOFTERR (1<<13)
+#define OPEN_ADAPTER_PASS_ADC_MAC (1<<12)
+#define OPEN_ADAPTER_PASS_ATT_MAC (1<<11)
+#define OPEN_ADAPTER_ENABLE_EC (1<<10)
+#define OPEN_ADAPTER_CONTENDER (1<<8)
+#define OPEN_ADAPTER_PASS_BEACON (1<<7)
+#define OPEN_ADAPTER_ENABLE_FDX (1<<6)
+#define OPEN_ADAPTER_ENABLE_RPL (1<<5)
+#define OPEN_ADAPTER_INHIBIT_ETR (1<<4)
+#define OPEN_ADAPTER_INTERNAL_WRAP (1<<3)
+
+
+/* Defines for SRB Commands */
+#define SRB_CLOSE_ADAPTER 0x04
+#define SRB_CONFIGURE_BRIDGE 0x0c
+#define SRB_CONFIGURE_HP_CHANNEL 0x13
+#define SRB_MODIFY_BRIDGE_PARMS 0x15
+#define SRB_MODIFY_OPEN_OPTIONS 0x01
+#define SRB_MODIFY_RECEIVE_OPTIONS 0x17
+#define SRB_NO_OPERATION 0x00
+#define SRB_OPEN_ADAPTER 0x03
+#define SRB_READ_LOG 0x08
+#define SRB_READ_SR_COUNTERS 0x16
+#define SRB_RESET_GROUP_ADDRESS 0x02
+#define SRB_RESET_TARGET_SEGMETN 0x14
+#define SRB_SAVE_CONFIGURATION 0x1b
+#define SRB_SET_BRIDGE_PARMS 0x09
+#define SRB_SET_FUNC_ADDRESS 0x07
+#define SRB_SET_GROUP_ADDRESS 0x06
+#define SRB_SET_TARGET_SEGMENT 0x05
+
+/* Clear return code */
+#define STREAMER_CLEAR_RET_CODE 0xfe
+
+/* ARB Commands */
+#define ARB_RECEIVE_DATA 0x81
+#define ARB_LAN_CHANGE_STATUS 0x84
+
+/* ASB Response commands */
+#define ASB_RECEIVE_DATA 0x81
+
+
+/* Streamer defaults for buffers */
+
+#define STREAMER_RX_RING_SIZE 16 /* should be a power of 2 */
+/* Setting the number of TX descriptors to 1 is a workaround for an
+ * undocumented hardware problem with the lanstreamer board. Setting
+ * this to something higher may slightly increase the throughput you
+ * can get from the card, but at the risk of locking up the box. -
+ * <yoder1@us.ibm.com>
+ */
+#define STREAMER_TX_RING_SIZE 1 /* should be a power of 2 */
+
+#define PKT_BUF_SZ 4096 /* Default packet size */
+
+/* Streamer data structures */
+
+struct streamer_tx_desc {
+ __u32 forward;
+ __u32 status;
+ __u32 bufcnt_framelen;
+ __u32 buffer;
+ __u32 buflen;
+ __u32 rsvd1;
+ __u32 rsvd2;
+ __u32 rsvd3;
+};
+
+struct streamer_rx_desc {
+ __u32 forward;
+ __u32 status;
+ __u32 buffer;
+ __u32 framelen_buflen;
+};
+
+struct mac_receive_buffer {
+ __u16 next;
+ __u8 padding;
+ __u8 frame_status;
+ __u16 buffer_length;
+ __u8 frame_data;
+};
+
+struct streamer_private {
+
+ __u16 srb;
+ __u16 trb;
+ __u16 arb;
+ __u16 asb;
+
+ struct streamer_private *next;
+ struct pci_dev *pci_dev;
+ __u8 __iomem *streamer_mmio;
+ char *streamer_card_name;
+
+ spinlock_t streamer_lock;
+
+ volatile int srb_queued; /* True if an SRB is still posted */
+ wait_queue_head_t srb_wait;
+
+ volatile int asb_queued; /* True if an ASB is posted */
+
+ volatile int trb_queued; /* True if a TRB is posted */
+ wait_queue_head_t trb_wait;
+
+ struct streamer_rx_desc *streamer_rx_ring;
+ struct streamer_tx_desc *streamer_tx_ring;
+ struct sk_buff *tx_ring_skb[STREAMER_TX_RING_SIZE],
+ *rx_ring_skb[STREAMER_RX_RING_SIZE];
+ int tx_ring_free, tx_ring_last_status, rx_ring_last_received,
+ free_tx_ring_entries;
+
+ struct net_device_stats streamer_stats;
+ __u16 streamer_lan_status;
+ __u8 streamer_ring_speed;
+ __u16 pkt_buf_sz;
+ __u8 streamer_receive_options, streamer_copy_all_options,
+ streamer_message_level;
+ __u16 streamer_addr_table_addr, streamer_parms_addr;
+ __u16 mac_rx_buffer;
+ __u8 streamer_laa[6];
+};
+
+struct streamer_adapter_addr_table {
+
+ __u8 node_addr[6];
+ __u8 reserved[4];
+ __u8 func_addr[4];
+};
+
+struct streamer_parameters_table {
+
+ __u8 phys_addr[4];
+ __u8 up_node_addr[6];
+ __u8 up_phys_addr[4];
+ __u8 poll_addr[6];
+ __u16 reserved;
+ __u16 acc_priority;
+ __u16 auth_source_class;
+ __u16 att_code;
+ __u8 source_addr[6];
+ __u16 beacon_type;
+ __u16 major_vector;
+ __u16 lan_status;
+ __u16 soft_error_time;
+ __u16 reserved1;
+ __u16 local_ring;
+ __u16 mon_error;
+ __u16 beacon_transmit;
+ __u16 beacon_receive;
+ __u16 frame_correl;
+ __u8 beacon_naun[6];
+ __u32 reserved2;
+ __u8 beacon_phys[4];
+};
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c
new file mode 100644
index 00000000000..cfae2bbf216
--- /dev/null
+++ b/drivers/net/tokenring/madgemc.c
@@ -0,0 +1,800 @@
+/*
+ * madgemc.c: Driver for the Madge Smart 16/4 MC16 MCA token ring card.
+ *
+ * Written 2000 by Adam Fritzler
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * This driver module supports the following cards:
+ * - Madge Smart 16/4 Ringnode MC16
+ * - Madge Smart 16/4 Ringnode MC32 (??)
+ *
+ * Maintainer(s):
+ * AF Adam Fritzler mid@auk.cx
+ *
+ * Modification History:
+ * 16-Jan-00 AF Created
+ *
+ */
+static const char version[] = "madgemc.c: v0.91 23/01/2000 by Adam Fritzler\n";
+
+#include <linux/module.h>
+#include <linux/mca-legacy.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/trdevice.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "tms380tr.h"
+#include "madgemc.h" /* Madge-specific constants */
+
+#define MADGEMC_IO_EXTENT 32
+#define MADGEMC_SIF_OFFSET 0x08
+
+struct madgemc_card {
+ struct net_device *dev;
+
+ /*
+ * These are read from the BIA ROM.
+ */
+ unsigned int manid;
+ unsigned int cardtype;
+ unsigned int cardrev;
+ unsigned int ramsize;
+
+ /*
+ * These are read from the MCA POS registers.
+ */
+ unsigned int burstmode:2;
+ unsigned int fairness:1; /* 0 = Fair, 1 = Unfair */
+ unsigned int arblevel:4;
+ unsigned int ringspeed:2; /* 0 = 4mb, 1 = 16, 2 = Auto/none */
+ unsigned int cabletype:1; /* 0 = RJ45, 1 = DB9 */
+
+ struct madgemc_card *next;
+};
+static struct madgemc_card *madgemc_card_list;
+
+
+static int madgemc_open(struct net_device *dev);
+static int madgemc_close(struct net_device *dev);
+static int madgemc_chipset_init(struct net_device *dev);
+static void madgemc_read_rom(struct madgemc_card *card);
+static unsigned short madgemc_setnselout_pins(struct net_device *dev);
+static void madgemc_setcabletype(struct net_device *dev, int type);
+
+static int madgemc_mcaproc(char *buf, int slot, void *d);
+
+static void madgemc_setregpage(struct net_device *dev, int page);
+static void madgemc_setsifsel(struct net_device *dev, int val);
+static void madgemc_setint(struct net_device *dev, int val);
+
+static irqreturn_t madgemc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+/*
+ * These work around paging, however they don't guarentee you're on the
+ * right page.
+ */
+#define SIFREADB(reg) (inb(dev->base_addr + ((reg<0x8)?reg:reg-0x8)))
+#define SIFWRITEB(val, reg) (outb(val, dev->base_addr + ((reg<0x8)?reg:reg-0x8)))
+#define SIFREADW(reg) (inw(dev->base_addr + ((reg<0x8)?reg:reg-0x8)))
+#define SIFWRITEW(val, reg) (outw(val, dev->base_addr + ((reg<0x8)?reg:reg-0x8)))
+
+/*
+ * Read a byte-length value from the register.
+ */
+static unsigned short madgemc_sifreadb(struct net_device *dev, unsigned short reg)
+{
+ unsigned short ret;
+ if (reg<0x8)
+ ret = SIFREADB(reg);
+ else {
+ madgemc_setregpage(dev, 1);
+ ret = SIFREADB(reg);
+ madgemc_setregpage(dev, 0);
+ }
+ return ret;
+}
+
+/*
+ * Write a byte-length value to a register.
+ */
+static void madgemc_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg)
+{
+ if (reg<0x8)
+ SIFWRITEB(val, reg);
+ else {
+ madgemc_setregpage(dev, 1);
+ SIFWRITEB(val, reg);
+ madgemc_setregpage(dev, 0);
+ }
+ return;
+}
+
+/*
+ * Read a word-length value from a register
+ */
+static unsigned short madgemc_sifreadw(struct net_device *dev, unsigned short reg)
+{
+ unsigned short ret;
+ if (reg<0x8)
+ ret = SIFREADW(reg);
+ else {
+ madgemc_setregpage(dev, 1);
+ ret = SIFREADW(reg);
+ madgemc_setregpage(dev, 0);
+ }
+ return ret;
+}
+
+/*
+ * Write a word-length value to a register.
+ */
+static void madgemc_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg)
+{
+ if (reg<0x8)
+ SIFWRITEW(val, reg);
+ else {
+ madgemc_setregpage(dev, 1);
+ SIFWRITEW(val, reg);
+ madgemc_setregpage(dev, 0);
+ }
+ return;
+}
+
+
+
+static int __init madgemc_probe(void)
+{
+ static int versionprinted;
+ struct net_device *dev;
+ struct net_local *tp;
+ struct madgemc_card *card;
+ int i,slot = 0;
+ __u8 posreg[4];
+
+ if (!MCA_bus)
+ return -1;
+
+ while (slot != MCA_NOTFOUND) {
+ /*
+ * Currently we only support the MC16/32 (MCA ID 002d)
+ */
+ slot = mca_find_unused_adapter(0x002d, slot);
+ if (slot == MCA_NOTFOUND)
+ break;
+
+ /*
+ * If we get here, we have an adapter.
+ */
+ if (versionprinted++ == 0)
+ printk("%s", version);
+
+ dev = alloc_trdev(sizeof(struct net_local));
+ if (dev == NULL) {
+ printk("madgemc: unable to allocate dev space\n");
+ if (madgemc_card_list)
+ return 0;
+ return -1;
+ }
+
+ SET_MODULE_OWNER(dev);
+ dev->dma = 0;
+
+ /*
+ * Fetch MCA config registers
+ */
+ for(i=0;i<4;i++)
+ posreg[i] = mca_read_stored_pos(slot, i+2);
+
+ card = kmalloc(sizeof(struct madgemc_card), GFP_KERNEL);
+ if (card==NULL) {
+ printk("madgemc: unable to allocate card struct\n");
+ free_netdev(dev);
+ if (madgemc_card_list)
+ return 0;
+ return -1;
+ }
+ card->dev = dev;
+
+ /*
+ * Parse configuration information. This all comes
+ * directly from the publicly available @002d.ADF.
+ * Get it from Madge or your local ADF library.
+ */
+
+ /*
+ * Base address
+ */
+ dev->base_addr = 0x0a20 +
+ ((posreg[2] & MC16_POS2_ADDR2)?0x0400:0) +
+ ((posreg[0] & MC16_POS0_ADDR1)?0x1000:0) +
+ ((posreg[3] & MC16_POS3_ADDR3)?0x2000:0);
+
+ /*
+ * Interrupt line
+ */
+ switch(posreg[0] >> 6) { /* upper two bits */
+ case 0x1: dev->irq = 3; break;
+ case 0x2: dev->irq = 9; break; /* IRQ 2 = IRQ 9 */
+ case 0x3: dev->irq = 10; break;
+ default: dev->irq = 0; break;
+ }
+
+ if (dev->irq == 0) {
+ printk("%s: invalid IRQ\n", dev->name);
+ goto getout1;
+ }
+
+ if (!request_region(dev->base_addr, MADGEMC_IO_EXTENT,
+ "madgemc")) {
+ printk(KERN_INFO "madgemc: unable to setup Smart MC in slot %d because of I/O base conflict at 0x%04lx\n", slot, dev->base_addr);
+ dev->base_addr += MADGEMC_SIF_OFFSET;
+ goto getout1;
+ }
+ dev->base_addr += MADGEMC_SIF_OFFSET;
+
+ /*
+ * Arbitration Level
+ */
+ card->arblevel = ((posreg[0] >> 1) & 0x7) + 8;
+
+ /*
+ * Burst mode and Fairness
+ */
+ card->burstmode = ((posreg[2] >> 6) & 0x3);
+ card->fairness = ((posreg[2] >> 4) & 0x1);
+
+ /*
+ * Ring Speed
+ */
+ if ((posreg[1] >> 2)&0x1)
+ card->ringspeed = 2; /* not selected */
+ else if ((posreg[2] >> 5) & 0x1)
+ card->ringspeed = 1; /* 16Mb */
+ else
+ card->ringspeed = 0; /* 4Mb */
+
+ /*
+ * Cable type
+ */
+ if ((posreg[1] >> 6)&0x1)
+ card->cabletype = 1; /* STP/DB9 */
+ else
+ card->cabletype = 0; /* UTP/RJ-45 */
+
+
+ /*
+ * ROM Info. This requires us to actually twiddle
+ * bits on the card, so we must ensure above that
+ * the base address is free of conflict (request_region above).
+ */
+ madgemc_read_rom(card);
+
+ if (card->manid != 0x4d) { /* something went wrong */
+ printk(KERN_INFO "%s: Madge MC ROM read failed (unknown manufacturer ID %02x)\n", dev->name, card->manid);
+ goto getout;
+ }
+
+ if ((card->cardtype != 0x08) && (card->cardtype != 0x0d)) {
+ printk(KERN_INFO "%s: Madge MC ROM read failed (unknown card ID %02x)\n", dev->name, card->cardtype);
+ goto getout;
+ }
+
+ /* All cards except Rev 0 and 1 MC16's have 256kb of RAM */
+ if ((card->cardtype == 0x08) && (card->cardrev <= 0x01))
+ card->ramsize = 128;
+ else
+ card->ramsize = 256;
+
+ printk("%s: %s Rev %d at 0x%04lx IRQ %d\n",
+ dev->name,
+ (card->cardtype == 0x08)?MADGEMC16_CARDNAME:
+ MADGEMC32_CARDNAME, card->cardrev,
+ dev->base_addr, dev->irq);
+
+ if (card->cardtype == 0x0d)
+ printk("%s: Warning: MC32 support is experimental and highly untested\n", dev->name);
+
+ if (card->ringspeed==2) { /* Unknown */
+ printk("%s: Warning: Ring speed not set in POS -- Please run the reference disk and set it!\n", dev->name);
+ card->ringspeed = 1; /* default to 16mb */
+ }
+
+ printk("%s: RAM Size: %dKB\n", dev->name, card->ramsize);
+
+ printk("%s: Ring Speed: %dMb/sec on %s\n", dev->name,
+ (card->ringspeed)?16:4,
+ card->cabletype?"STP/DB9":"UTP/RJ-45");
+ printk("%s: Arbitration Level: %d\n", dev->name,
+ card->arblevel);
+
+ printk("%s: Burst Mode: ", dev->name);
+ switch(card->burstmode) {
+ case 0: printk("Cycle steal"); break;
+ case 1: printk("Limited burst"); break;
+ case 2: printk("Delayed release"); break;
+ case 3: printk("Immediate release"); break;
+ }
+ printk(" (%s)\n", (card->fairness)?"Unfair":"Fair");
+
+
+ /*
+ * Enable SIF before we assign the interrupt handler,
+ * just in case we get spurious interrupts that need
+ * handling.
+ */
+ outb(0, dev->base_addr + MC_CONTROL_REG0); /* sanity */
+ madgemc_setsifsel(dev, 1);
+ if (request_irq(dev->irq, madgemc_interrupt, SA_SHIRQ,
+ "madgemc", dev))
+ goto getout;
+
+ madgemc_chipset_init(dev); /* enables interrupts! */
+ madgemc_setcabletype(dev, card->cabletype);
+
+ /* Setup MCA structures */
+ mca_set_adapter_name(slot, (card->cardtype == 0x08)?MADGEMC16_CARDNAME:MADGEMC32_CARDNAME);
+ mca_set_adapter_procfn(slot, madgemc_mcaproc, dev);
+ mca_mark_as_used(slot);
+
+ printk("%s: Ring Station Address: ", dev->name);
+ printk("%2.2x", dev->dev_addr[0]);
+ for (i = 1; i < 6; i++)
+ printk(":%2.2x", dev->dev_addr[i]);
+ printk("\n");
+
+ /* XXX is ISA_MAX_ADDRESS correct here? */
+ if (tmsdev_init(dev, ISA_MAX_ADDRESS, NULL)) {
+ printk("%s: unable to get memory for dev->priv.\n",
+ dev->name);
+ release_region(dev->base_addr-MADGEMC_SIF_OFFSET,
+ MADGEMC_IO_EXTENT);
+
+ kfree(card);
+ tmsdev_term(dev);
+ free_netdev(dev);
+ if (madgemc_card_list)
+ return 0;
+ return -1;
+ }
+ tp = netdev_priv(dev);
+
+ /*
+ * The MC16 is physically a 32bit card. However, Madge
+ * insists on calling it 16bit, so I'll assume here that
+ * they know what they're talking about. Cut off DMA
+ * at 16mb.
+ */
+ tp->setnselout = madgemc_setnselout_pins;
+ tp->sifwriteb = madgemc_sifwriteb;
+ tp->sifreadb = madgemc_sifreadb;
+ tp->sifwritew = madgemc_sifwritew;
+ tp->sifreadw = madgemc_sifreadw;
+ tp->DataRate = (card->ringspeed)?SPEED_16:SPEED_4;
+
+ memcpy(tp->ProductID, "Madge MCA 16/4 ", PROD_ID_SIZE + 1);
+
+ dev->open = madgemc_open;
+ dev->stop = madgemc_close;
+
+ if (register_netdev(dev) == 0) {
+ /* Enlist in the card list */
+ card->next = madgemc_card_list;
+ madgemc_card_list = card;
+ slot++;
+ continue; /* successful, try to find another */
+ }
+
+ free_irq(dev->irq, dev);
+ getout:
+ release_region(dev->base_addr-MADGEMC_SIF_OFFSET,
+ MADGEMC_IO_EXTENT);
+ getout1:
+ kfree(card);
+ free_netdev(dev);
+ slot++;
+ }
+
+ if (madgemc_card_list)
+ return 0;
+ return -1;
+}
+
+/*
+ * Handle interrupts generated by the card
+ *
+ * The MicroChannel Madge cards need slightly more handling
+ * after an interrupt than other TMS380 cards do.
+ *
+ * First we must make sure it was this card that generated the
+ * interrupt (since interrupt sharing is allowed). Then,
+ * because we're using level-triggered interrupts (as is
+ * standard on MCA), we must toggle the interrupt line
+ * on the card in order to claim and acknowledge the interrupt.
+ * Once that is done, the interrupt should be handlable in
+ * the normal tms380tr_interrupt() routine.
+ *
+ * There's two ways we can check to see if the interrupt is ours,
+ * both with their own disadvantages...
+ *
+ * 1) Read in the SIFSTS register from the TMS controller. This
+ * is guarenteed to be accurate, however, there's a fairly
+ * large performance penalty for doing so: the Madge chips
+ * must request the register from the Eagle, the Eagle must
+ * read them from its internal bus, and then take the route
+ * back out again, for a 16bit read.
+ *
+ * 2) Use the MC_CONTROL_REG0_SINTR bit from the Madge ASICs.
+ * The major disadvantage here is that the accuracy of the
+ * bit is in question. However, it cuts out the extra read
+ * cycles it takes to read the Eagle's SIF, as its only an
+ * 8bit read, and theoretically the Madge bit is directly
+ * connected to the interrupt latch coming out of the Eagle
+ * hardware (that statement is not verified).
+ *
+ * I can't determine which of these methods has the best win. For now,
+ * we make a compromise. Use the Madge way for the first interrupt,
+ * which should be the fast-path, and then once we hit the first
+ * interrupt, keep on trying using the SIF method until we've
+ * exhausted all contiguous interrupts.
+ *
+ */
+static irqreturn_t madgemc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int pending,reg1;
+ struct net_device *dev;
+
+ if (!dev_id) {
+ printk("madgemc_interrupt: was not passed a dev_id!\n");
+ return IRQ_NONE;
+ }
+
+ dev = (struct net_device *)dev_id;
+
+ /* Make sure its really us. -- the Madge way */
+ pending = inb(dev->base_addr + MC_CONTROL_REG0);
+ if (!(pending & MC_CONTROL_REG0_SINTR))
+ return IRQ_NONE; /* not our interrupt */
+
+ /*
+ * Since we're level-triggered, we may miss the rising edge
+ * of the next interrupt while we're off handling this one,
+ * so keep checking until the SIF verifies that it has nothing
+ * left for us to do.
+ */
+ pending = STS_SYSTEM_IRQ;
+ do {
+ if (pending & STS_SYSTEM_IRQ) {
+
+ /* Toggle the interrupt to reset the latch on card */
+ reg1 = inb(dev->base_addr + MC_CONTROL_REG1);
+ outb(reg1 ^ MC_CONTROL_REG1_SINTEN,
+ dev->base_addr + MC_CONTROL_REG1);
+ outb(reg1, dev->base_addr + MC_CONTROL_REG1);
+
+ /* Continue handling as normal */
+ tms380tr_interrupt(irq, dev_id, regs);
+
+ pending = SIFREADW(SIFSTS); /* restart - the SIF way */
+
+ } else
+ return IRQ_HANDLED;
+ } while (1);
+
+ return IRQ_HANDLED; /* not reachable */
+}
+
+/*
+ * Set the card to the prefered ring speed.
+ *
+ * Unlike newer cards, the MC16/32 have their speed selection
+ * circuit connected to the Madge ASICs and not to the TMS380
+ * NSELOUT pins. Set the ASIC bits correctly here, and return
+ * zero to leave the TMS NSELOUT bits unaffected.
+ *
+ */
+unsigned short madgemc_setnselout_pins(struct net_device *dev)
+{
+ unsigned char reg1;
+ struct net_local *tp = netdev_priv(dev);
+
+ reg1 = inb(dev->base_addr + MC_CONTROL_REG1);
+
+ if(tp->DataRate == SPEED_16)
+ reg1 |= MC_CONTROL_REG1_SPEED_SEL; /* add for 16mb */
+ else if (reg1 & MC_CONTROL_REG1_SPEED_SEL)
+ reg1 ^= MC_CONTROL_REG1_SPEED_SEL; /* remove for 4mb */
+ outb(reg1, dev->base_addr + MC_CONTROL_REG1);
+
+ return 0; /* no change */
+}
+
+/*
+ * Set the register page. This equates to the SRSX line
+ * on the TMS380Cx6.
+ *
+ * Register selection is normally done via three contiguous
+ * bits. However, some boards (such as the MC16/32) use only
+ * two bits, plus a separate bit in the glue chip. This
+ * sets the SRSX bit (the top bit). See page 4-17 in the
+ * Yellow Book for which registers are affected.
+ *
+ */
+static void madgemc_setregpage(struct net_device *dev, int page)
+{
+ static int reg1;
+
+ reg1 = inb(dev->base_addr + MC_CONTROL_REG1);
+ if ((page == 0) && (reg1 & MC_CONTROL_REG1_SRSX)) {
+ outb(reg1 ^ MC_CONTROL_REG1_SRSX,
+ dev->base_addr + MC_CONTROL_REG1);
+ }
+ else if (page == 1) {
+ outb(reg1 | MC_CONTROL_REG1_SRSX,
+ dev->base_addr + MC_CONTROL_REG1);
+ }
+ reg1 = inb(dev->base_addr + MC_CONTROL_REG1);
+
+ return;
+}
+
+/*
+ * The SIF registers are not mapped into register space by default
+ * Set this to 1 to map them, 0 to map the BIA ROM.
+ *
+ */
+static void madgemc_setsifsel(struct net_device *dev, int val)
+{
+ unsigned int reg0;
+
+ reg0 = inb(dev->base_addr + MC_CONTROL_REG0);
+ if ((val == 0) && (reg0 & MC_CONTROL_REG0_SIFSEL)) {
+ outb(reg0 ^ MC_CONTROL_REG0_SIFSEL,
+ dev->base_addr + MC_CONTROL_REG0);
+ } else if (val == 1) {
+ outb(reg0 | MC_CONTROL_REG0_SIFSEL,
+ dev->base_addr + MC_CONTROL_REG0);
+ }
+ reg0 = inb(dev->base_addr + MC_CONTROL_REG0);
+
+ return;
+}
+
+/*
+ * Enable SIF interrupts
+ *
+ * This does not enable interrupts in the SIF, but rather
+ * enables SIF interrupts to be passed onto the host.
+ *
+ */
+static void madgemc_setint(struct net_device *dev, int val)
+{
+ unsigned int reg1;
+
+ reg1 = inb(dev->base_addr + MC_CONTROL_REG1);
+ if ((val == 0) && (reg1 & MC_CONTROL_REG1_SINTEN)) {
+ outb(reg1 ^ MC_CONTROL_REG1_SINTEN,
+ dev->base_addr + MC_CONTROL_REG1);
+ } else if (val == 1) {
+ outb(reg1 | MC_CONTROL_REG1_SINTEN,
+ dev->base_addr + MC_CONTROL_REG1);
+ }
+
+ return;
+}
+
+/*
+ * Cable type is set via control register 7. Bit zero high
+ * for UTP, low for STP.
+ */
+static void madgemc_setcabletype(struct net_device *dev, int type)
+{
+ outb((type==0)?MC_CONTROL_REG7_CABLEUTP:MC_CONTROL_REG7_CABLESTP,
+ dev->base_addr + MC_CONTROL_REG7);
+}
+
+/*
+ * Enable the functions of the Madge chipset needed for
+ * full working order.
+ */
+static int madgemc_chipset_init(struct net_device *dev)
+{
+ outb(0, dev->base_addr + MC_CONTROL_REG1); /* pull SRESET low */
+ tms380tr_wait(100); /* wait for card to reset */
+
+ /* bring back into normal operating mode */
+ outb(MC_CONTROL_REG1_NSRESET, dev->base_addr + MC_CONTROL_REG1);
+
+ /* map SIF registers */
+ madgemc_setsifsel(dev, 1);
+
+ /* enable SIF interrupts */
+ madgemc_setint(dev, 1);
+
+ return 0;
+}
+
+/*
+ * Disable the board, and put back into power-up state.
+ */
+void madgemc_chipset_close(struct net_device *dev)
+{
+ /* disable interrupts */
+ madgemc_setint(dev, 0);
+ /* unmap SIF registers */
+ madgemc_setsifsel(dev, 0);
+
+ return;
+}
+
+/*
+ * Read the card type (MC16 or MC32) from the card.
+ *
+ * The configuration registers are stored in two separate
+ * pages. Pages are flipped by clearing bit 3 of CONTROL_REG0 (PAGE)
+ * for page zero, or setting bit 3 for page one.
+ *
+ * Page zero contains the following data:
+ * Byte 0: Manufacturer ID (0x4D -- ASCII "M")
+ * Byte 1: Card type:
+ * 0x08 for MC16
+ * 0x0D for MC32
+ * Byte 2: Card revision
+ * Byte 3: Mirror of POS config register 0
+ * Byte 4: Mirror of POS 1
+ * Byte 5: Mirror of POS 2
+ *
+ * Page one contains the following data:
+ * Byte 0: Unused
+ * Byte 1-6: BIA, MSB to LSB.
+ *
+ * Note that to read the BIA, we must unmap the SIF registers
+ * by clearing bit 2 of CONTROL_REG0 (SIFSEL), as the data
+ * will reside in the same logical location. For this reason,
+ * _never_ read the BIA while the Eagle processor is running!
+ * The SIF will be completely inaccessible until the BIA operation
+ * is complete.
+ *
+ */
+static void madgemc_read_rom(struct madgemc_card *card)
+{
+ unsigned long ioaddr;
+ unsigned char reg0, reg1, tmpreg0, i;
+
+ ioaddr = card->dev->base_addr;
+
+ reg0 = inb(ioaddr + MC_CONTROL_REG0);
+ reg1 = inb(ioaddr + MC_CONTROL_REG1);
+
+ /* Switch to page zero and unmap SIF */
+ tmpreg0 = reg0 & ~(MC_CONTROL_REG0_PAGE + MC_CONTROL_REG0_SIFSEL);
+ outb(tmpreg0, ioaddr + MC_CONTROL_REG0);
+
+ card->manid = inb(ioaddr + MC_ROM_MANUFACTURERID);
+ card->cardtype = inb(ioaddr + MC_ROM_ADAPTERID);
+ card->cardrev = inb(ioaddr + MC_ROM_REVISION);
+
+ /* Switch to rom page one */
+ outb(tmpreg0 | MC_CONTROL_REG0_PAGE, ioaddr + MC_CONTROL_REG0);
+
+ /* Read BIA */
+ card->dev->addr_len = 6;
+ for (i = 0; i < 6; i++)
+ card->dev->dev_addr[i] = inb(ioaddr + MC_ROM_BIA_START + i);
+
+ /* Restore original register values */
+ outb(reg0, ioaddr + MC_CONTROL_REG0);
+ outb(reg1, ioaddr + MC_CONTROL_REG1);
+
+ return;
+}
+
+static int madgemc_open(struct net_device *dev)
+{
+ /*
+ * Go ahead and reinitialize the chipset again, just to
+ * make sure we didn't get left in a bad state.
+ */
+ madgemc_chipset_init(dev);
+ tms380tr_open(dev);
+ return 0;
+}
+
+static int madgemc_close(struct net_device *dev)
+{
+ tms380tr_close(dev);
+ madgemc_chipset_close(dev);
+ return 0;
+}
+
+/*
+ * Give some details available from /proc/mca/slotX
+ */
+static int madgemc_mcaproc(char *buf, int slot, void *d)
+{
+ struct net_device *dev = (struct net_device *)d;
+ struct madgemc_card *curcard = madgemc_card_list;
+ int len = 0;
+
+ while (curcard) { /* search for card struct */
+ if (curcard->dev == dev)
+ break;
+ curcard = curcard->next;
+ }
+ len += sprintf(buf+len, "-------\n");
+ if (curcard) {
+ struct net_local *tp = netdev_priv(dev);
+ int i;
+
+ len += sprintf(buf+len, "Card Revision: %d\n", curcard->cardrev);
+ len += sprintf(buf+len, "RAM Size: %dkb\n", curcard->ramsize);
+ len += sprintf(buf+len, "Cable type: %s\n", (curcard->cabletype)?"STP/DB9":"UTP/RJ-45");
+ len += sprintf(buf+len, "Configured ring speed: %dMb/sec\n", (curcard->ringspeed)?16:4);
+ len += sprintf(buf+len, "Running ring speed: %dMb/sec\n", (tp->DataRate==SPEED_16)?16:4);
+ len += sprintf(buf+len, "Device: %s\n", dev->name);
+ len += sprintf(buf+len, "IO Port: 0x%04lx\n", dev->base_addr);
+ len += sprintf(buf+len, "IRQ: %d\n", dev->irq);
+ len += sprintf(buf+len, "Arbitration Level: %d\n", curcard->arblevel);
+ len += sprintf(buf+len, "Burst Mode: ");
+ switch(curcard->burstmode) {
+ case 0: len += sprintf(buf+len, "Cycle steal"); break;
+ case 1: len += sprintf(buf+len, "Limited burst"); break;
+ case 2: len += sprintf(buf+len, "Delayed release"); break;
+ case 3: len += sprintf(buf+len, "Immediate release"); break;
+ }
+ len += sprintf(buf+len, " (%s)\n", (curcard->fairness)?"Unfair":"Fair");
+
+ len += sprintf(buf+len, "Ring Station Address: ");
+ len += sprintf(buf+len, "%2.2x", dev->dev_addr[0]);
+ for (i = 1; i < 6; i++)
+ len += sprintf(buf+len, " %2.2x", dev->dev_addr[i]);
+ len += sprintf(buf+len, "\n");
+ } else
+ len += sprintf(buf+len, "Card not configured\n");
+
+ return len;
+}
+
+static void __exit madgemc_exit(void)
+{
+ struct net_device *dev;
+ struct madgemc_card *this_card;
+
+ while (madgemc_card_list) {
+ dev = madgemc_card_list->dev;
+ unregister_netdev(dev);
+ release_region(dev->base_addr-MADGEMC_SIF_OFFSET, MADGEMC_IO_EXTENT);
+ free_irq(dev->irq, dev);
+ tmsdev_term(dev);
+ free_netdev(dev);
+ this_card = madgemc_card_list;
+ madgemc_card_list = this_card->next;
+ kfree(this_card);
+ }
+}
+
+module_init(madgemc_probe);
+module_exit(madgemc_exit);
+
+MODULE_LICENSE("GPL");
+
+
+/*
+ * Local variables:
+ * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c madgemc.c"
+ * alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c madgemc.c"
+ * c-set-style "K&R"
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
+
diff --git a/drivers/net/tokenring/madgemc.h b/drivers/net/tokenring/madgemc.h
new file mode 100644
index 00000000000..2dd82220380
--- /dev/null
+++ b/drivers/net/tokenring/madgemc.h
@@ -0,0 +1,70 @@
+/*
+ * madgemc.h: Header for the madgemc tms380tr module
+ *
+ * Authors:
+ * - Adam Fritzler <mid@auk.cx>
+ */
+
+#ifndef __LINUX_MADGEMC_H
+#define __LINUX_MADGEMC_H
+
+#ifdef __KERNEL__
+
+#define MADGEMC16_CARDNAME "Madge Smart 16/4 MC16 Ringnode"
+#define MADGEMC32_CARDNAME "Madge Smart 16/4 MC32 Ringnode"
+
+/*
+ * Bit definitions for the POS config registers
+ */
+#define MC16_POS0_ADDR1 0x20
+#define MC16_POS2_ADDR2 0x04
+#define MC16_POS3_ADDR3 0x20
+
+#define MC_CONTROL_REG0 ((long)-8) /* 0x00 */
+#define MC_CONTROL_REG1 ((long)-7) /* 0x01 */
+#define MC_ADAPTER_POS_REG0 ((long)-6) /* 0x02 */
+#define MC_ADAPTER_POS_REG1 ((long)-5) /* 0x03 */
+#define MC_ADAPTER_POS_REG2 ((long)-4) /* 0x04 */
+#define MC_ADAPTER_REG5_UNUSED ((long)-3) /* 0x05 */
+#define MC_ADAPTER_REG6_UNUSED ((long)-2) /* 0x06 */
+#define MC_CONTROL_REG7 ((long)-1) /* 0x07 */
+
+#define MC_CONTROL_REG0_UNKNOWN1 0x01
+#define MC_CONTROL_REG0_UNKNOWN2 0x02
+#define MC_CONTROL_REG0_SIFSEL 0x04
+#define MC_CONTROL_REG0_PAGE 0x08
+#define MC_CONTROL_REG0_TESTINTERRUPT 0x10
+#define MC_CONTROL_REG0_UNKNOWN20 0x20
+#define MC_CONTROL_REG0_SINTR 0x40
+#define MC_CONTROL_REG0_UNKNOWN80 0x80
+
+#define MC_CONTROL_REG1_SINTEN 0x01
+#define MC_CONTROL_REG1_BITOFDEATH 0x02
+#define MC_CONTROL_REG1_NSRESET 0x04
+#define MC_CONTROL_REG1_UNKNOWN8 0x08
+#define MC_CONTROL_REG1_UNKNOWN10 0x10
+#define MC_CONTROL_REG1_UNKNOWN20 0x20
+#define MC_CONTROL_REG1_SRSX 0x40
+#define MC_CONTROL_REG1_SPEED_SEL 0x80
+
+#define MC_CONTROL_REG7_CABLESTP 0x00
+#define MC_CONTROL_REG7_CABLEUTP 0x01
+
+/*
+ * ROM Page Zero
+ */
+#define MC_ROM_MANUFACTURERID 0x00
+#define MC_ROM_ADAPTERID 0x01
+#define MC_ROM_REVISION 0x02
+#define MC_ROM_CONFIG0 0x03
+#define MC_ROM_CONFIG1 0x04
+#define MC_ROM_CONFIG2 0x05
+
+/*
+ * ROM Page One
+ */
+#define MC_ROM_UNUSED_BYTE 0x00
+#define MC_ROM_BIA_START 0x01
+
+#endif /* __KERNEL__ */
+#endif /* __LINUX_MADGEMC_H */
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
new file mode 100644
index 00000000000..9e7923192a4
--- /dev/null
+++ b/drivers/net/tokenring/olympic.c
@@ -0,0 +1,1786 @@
+/*
+ * olympic.c (c) 1999 Peter De Schrijver All Rights Reserved
+ * 1999/2000 Mike Phillips (mikep@linuxtr.net)
+ *
+ * Linux driver for IBM PCI tokenring cards based on the Pit/Pit-Phy/Olympic
+ * chipset.
+ *
+ * Base Driver Skeleton:
+ * Written 1993-94 by Donald Becker.
+ *
+ * Copyright 1993 United States Government as represented by the
+ * Director, National Security Agency.
+ *
+ * Thanks to Erik De Cock, Adrian Bridgett and Frank Fiene for their
+ * assistance and perserverance with the testing of this driver.
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * 4/27/99 - Alpha Release 0.1.0
+ * First release to the public
+ *
+ * 6/8/99 - Official Release 0.2.0
+ * Merged into the kernel code
+ * 8/18/99 - Updated driver for 2.3.13 kernel to use new pci
+ * resource. Driver also reports the card name returned by
+ * the pci resource.
+ * 1/11/00 - Added spinlocks for smp
+ * 2/23/00 - Updated to dev_kfree_irq
+ * 3/10/00 - Fixed FDX enable which triggered other bugs also
+ * squashed.
+ * 5/20/00 - Changes to handle Olympic on LinuxPPC. Endian changes.
+ * The odd thing about the changes is that the fix for
+ * endian issues with the big-endian data in the arb, asb...
+ * was to always swab() the bytes, no matter what CPU.
+ * That's because the read[wl]() functions always swap the
+ * bytes on the way in on PPC.
+ * Fixing the hardware descriptors was another matter,
+ * because they weren't going through read[wl](), there all
+ * the results had to be in memory in le32 values. kdaaker
+ *
+ * 12/23/00 - Added minimal Cardbus support (Thanks Donald).
+ *
+ * 03/09/01 - Add new pci api, dev_base_lock, general clean up.
+ *
+ * 03/27/01 - Add new dma pci (Thanks to Kyle Lucke) and alloc_trdev
+ * Change proc_fs behaviour, now one entry per adapter.
+ *
+ * 04/09/01 - Couple of bug fixes to the dma unmaps and ejecting the
+ * adapter when live does not take the system down with it.
+ *
+ * 06/02/01 - Clean up, copy skb for small packets
+ *
+ * 06/22/01 - Add EISR error handling routines
+ *
+ * 07/19/01 - Improve bad LAA reporting, strip out freemem
+ * into a separate function, its called from 3
+ * different places now.
+ * 02/09/02 - Replaced sleep_on.
+ * 03/01/02 - Replace access to several registers from 32 bit to
+ * 16 bit. Fixes alignment errors on PPC 64 bit machines.
+ * Thanks to Al Trautman for this one.
+ * 03/10/02 - Fix BUG in arb_cmd. Bug was there all along but was
+ * silently ignored until the error checking code
+ * went into version 1.0.0
+ * 06/04/02 - Add correct start up sequence for the cardbus adapters.
+ * Required for strict compliance with pci power mgmt specs.
+ * To Do:
+ *
+ * Wake on lan
+ *
+ * If Problems do Occur
+ * Most problems can be rectified by either closing and opening the interface
+ * (ifconfig down and up) or rmmod and insmod'ing the driver (a bit difficult
+ * if compiled into the kernel).
+ */
+
+/* Change OLYMPIC_DEBUG to 1 to get verbose, and I mean really verbose, messages */
+
+#define OLYMPIC_DEBUG 0
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/string.h>
+#include <linux/proc_fs.h>
+#include <linux/ptrace.h>
+#include <linux/skbuff.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/trdevice.h>
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+
+#include <net/checksum.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "olympic.h"
+
+/* I've got to put some intelligence into the version number so that Peter and I know
+ * which version of the code somebody has got.
+ * Version Number = a.b.c.d where a.b.c is the level of code and d is the latest author.
+ * So 0.0.1.pds = Peter, 0.0.1.mlp = Mike
+ *
+ * Official releases will only have an a.b.c version number format.
+ */
+
+static char version[] __devinitdata =
+"Olympic.c v1.0.5 6/04/02 - Peter De Schrijver & Mike Phillips" ;
+
+static char *open_maj_error[] = {"No error", "Lobe Media Test", "Physical Insertion",
+ "Address Verification", "Neighbor Notification (Ring Poll)",
+ "Request Parameters","FDX Registration Request",
+ "FDX Duplicate Address Check", "Station registration Query Wait",
+ "Unknown stage"};
+
+static char *open_min_error[] = {"No error", "Function Failure", "Signal Lost", "Wire Fault",
+ "Ring Speed Mismatch", "Timeout","Ring Failure","Ring Beaconing",
+ "Duplicate Node Address","Request Parameters","Remove Received",
+ "Reserved", "Reserved", "No Monitor Detected for RPL",
+ "Monitor Contention failer for RPL", "FDX Protocol Error"};
+
+/* Module paramters */
+
+MODULE_AUTHOR("Mike Phillips <mikep@linuxtr.net>") ;
+MODULE_DESCRIPTION("Olympic PCI/Cardbus Chipset Driver") ;
+
+/* Ring Speed 0,4,16,100
+ * 0 = Autosense
+ * 4,16 = Selected speed only, no autosense
+ * This allows the card to be the first on the ring
+ * and become the active monitor.
+ * 100 = Nothing at present, 100mbps is autodetected
+ * if FDX is turned on. May be implemented in the future to
+ * fail if 100mpbs is not detected.
+ *
+ * WARNING: Some hubs will allow you to insert
+ * at the wrong speed
+ */
+
+static int ringspeed[OLYMPIC_MAX_ADAPTERS] = {0,} ;
+module_param_array(ringspeed, int, NULL, 0);
+
+/* Packet buffer size */
+
+static int pkt_buf_sz[OLYMPIC_MAX_ADAPTERS] = {0,} ;
+module_param_array(pkt_buf_sz, int, NULL, 0) ;
+
+/* Message Level */
+
+static int message_level[OLYMPIC_MAX_ADAPTERS] = {0,} ;
+module_param_array(message_level, int, NULL, 0) ;
+
+/* Change network_monitor to receive mac frames through the arb channel.
+ * Will also create a /proc/net/olympic_tr%d entry, where %d is the tr
+ * device, i.e. tr0, tr1 etc.
+ * Intended to be used to create a ring-error reporting network module
+ * i.e. it will give you the source address of beaconers on the ring
+ */
+static int network_monitor[OLYMPIC_MAX_ADAPTERS] = {0,};
+module_param_array(network_monitor, int, NULL, 0);
+
+static struct pci_device_id olympic_pci_tbl[] = {
+ {PCI_VENDOR_ID_IBM,PCI_DEVICE_ID_IBM_TR_WAKE,PCI_ANY_ID,PCI_ANY_ID,},
+ { } /* Terminating Entry */
+};
+MODULE_DEVICE_TABLE(pci,olympic_pci_tbl) ;
+
+
+static int olympic_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static int olympic_init(struct net_device *dev);
+static int olympic_open(struct net_device *dev);
+static int olympic_xmit(struct sk_buff *skb, struct net_device *dev);
+static int olympic_close(struct net_device *dev);
+static void olympic_set_rx_mode(struct net_device *dev);
+static void olympic_freemem(struct net_device *dev) ;
+static irqreturn_t olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static struct net_device_stats * olympic_get_stats(struct net_device *dev);
+static int olympic_set_mac_address(struct net_device *dev, void *addr) ;
+static void olympic_arb_cmd(struct net_device *dev);
+static int olympic_change_mtu(struct net_device *dev, int mtu);
+static void olympic_srb_bh(struct net_device *dev) ;
+static void olympic_asb_bh(struct net_device *dev) ;
+static int olympic_proc_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data) ;
+
+static int __devinit olympic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct net_device *dev ;
+ struct olympic_private *olympic_priv;
+ static int card_no = -1 ;
+ int i ;
+
+ card_no++ ;
+
+ if ((i = pci_enable_device(pdev))) {
+ return i ;
+ }
+
+ pci_set_master(pdev);
+
+ if ((i = pci_request_regions(pdev,"olympic"))) {
+ goto op_disable_dev;
+ }
+
+ dev = alloc_trdev(sizeof(struct olympic_private)) ;
+ if (!dev) {
+ i = -ENOMEM;
+ goto op_free_dev;
+ }
+
+ olympic_priv = dev->priv ;
+
+ spin_lock_init(&olympic_priv->olympic_lock) ;
+
+ init_waitqueue_head(&olympic_priv->srb_wait);
+ init_waitqueue_head(&olympic_priv->trb_wait);
+#if OLYMPIC_DEBUG
+ printk(KERN_INFO "pci_device: %p, dev:%p, dev->priv: %p\n", pdev, dev, dev->priv);
+#endif
+ dev->irq=pdev->irq;
+ dev->base_addr=pci_resource_start(pdev, 0);
+ olympic_priv->olympic_card_name = pci_name(pdev);
+ olympic_priv->pdev = pdev;
+ olympic_priv->olympic_mmio = ioremap(pci_resource_start(pdev,1),256);
+ olympic_priv->olympic_lap = ioremap(pci_resource_start(pdev,2),2048);
+ if (!olympic_priv->olympic_mmio || !olympic_priv->olympic_lap) {
+ goto op_free_iomap;
+ }
+
+ if ((pkt_buf_sz[card_no] < 100) || (pkt_buf_sz[card_no] > 18000) )
+ olympic_priv->pkt_buf_sz = PKT_BUF_SZ ;
+ else
+ olympic_priv->pkt_buf_sz = pkt_buf_sz[card_no] ;
+
+ dev->mtu = olympic_priv->pkt_buf_sz - TR_HLEN ;
+ olympic_priv->olympic_ring_speed = ringspeed[card_no] ;
+ olympic_priv->olympic_message_level = message_level[card_no] ;
+ olympic_priv->olympic_network_monitor = network_monitor[card_no];
+
+ if ((i = olympic_init(dev))) {
+ goto op_free_iomap;
+ }
+
+ dev->open=&olympic_open;
+ dev->hard_start_xmit=&olympic_xmit;
+ dev->change_mtu=&olympic_change_mtu;
+ dev->stop=&olympic_close;
+ dev->do_ioctl=NULL;
+ dev->set_multicast_list=&olympic_set_rx_mode;
+ dev->get_stats=&olympic_get_stats ;
+ dev->set_mac_address=&olympic_set_mac_address ;
+ SET_MODULE_OWNER(dev) ;
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ pci_set_drvdata(pdev,dev) ;
+ register_netdev(dev) ;
+ printk("Olympic: %s registered as: %s\n",olympic_priv->olympic_card_name,dev->name);
+ if (olympic_priv->olympic_network_monitor) { /* Must go after register_netdev as we need the device name */
+ char proc_name[20] ;
+ strcpy(proc_name,"net/olympic_") ;
+ strcat(proc_name,dev->name) ;
+ create_proc_read_entry(proc_name,0,NULL,olympic_proc_info,(void *)dev) ;
+ printk("Olympic: Network Monitor information: /proc/%s\n",proc_name);
+ }
+ return 0 ;
+
+op_free_iomap:
+ if (olympic_priv->olympic_mmio)
+ iounmap(olympic_priv->olympic_mmio);
+ if (olympic_priv->olympic_lap)
+ iounmap(olympic_priv->olympic_lap);
+
+op_free_dev:
+ free_netdev(dev);
+ pci_release_regions(pdev);
+
+op_disable_dev:
+ pci_disable_device(pdev);
+ return i;
+}
+
+static int __devinit olympic_init(struct net_device *dev)
+{
+ struct olympic_private *olympic_priv;
+ u8 __iomem *olympic_mmio, *init_srb,*adapter_addr;
+ unsigned long t;
+ unsigned int uaa_addr;
+
+ olympic_priv=(struct olympic_private *)dev->priv;
+ olympic_mmio=olympic_priv->olympic_mmio;
+
+ printk("%s \n", version);
+ printk("%s. I/O at %hx, MMIO at %p, LAP at %p, using irq %d\n", olympic_priv->olympic_card_name, (unsigned int) dev->base_addr,olympic_priv->olympic_mmio, olympic_priv->olympic_lap, dev->irq);
+
+ writel(readl(olympic_mmio+BCTL) | BCTL_SOFTRESET,olympic_mmio+BCTL);
+ t=jiffies;
+ while((readl(olympic_mmio+BCTL)) & BCTL_SOFTRESET) {
+ schedule();
+ if(jiffies-t > 40*HZ) {
+ printk(KERN_ERR "IBM PCI tokenring card not responding.\n");
+ return -ENODEV;
+ }
+ }
+
+
+ /* Needed for cardbus */
+ if(!(readl(olympic_mmio+BCTL) & BCTL_MODE_INDICATOR)) {
+ writel(readl(olympic_priv->olympic_mmio+FERMASK)|FERMASK_INT_BIT, olympic_mmio+FERMASK);
+ }
+
+#if OLYMPIC_DEBUG
+ printk("BCTL: %x\n",readl(olympic_mmio+BCTL));
+ printk("GPR: %x\n",readw(olympic_mmio+GPR));
+ printk("SISRMASK: %x\n",readl(olympic_mmio+SISR_MASK));
+#endif
+ /* Aaaahhh, You have got to be real careful setting GPR, the card
+ holds the previous values from flash memory, including autosense
+ and ring speed */
+
+ writel(readl(olympic_mmio+BCTL)|BCTL_MIMREB,olympic_mmio+BCTL);
+
+ if (olympic_priv->olympic_ring_speed == 0) { /* Autosense */
+ writew(readw(olympic_mmio+GPR)|GPR_AUTOSENSE,olympic_mmio+GPR);
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Ringspeed autosense mode on\n",olympic_priv->olympic_card_name);
+ } else if (olympic_priv->olympic_ring_speed == 16) {
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Trying to open at 16 Mbps as requested\n", olympic_priv->olympic_card_name);
+ writew(GPR_16MBPS, olympic_mmio+GPR);
+ } else if (olympic_priv->olympic_ring_speed == 4) {
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Trying to open at 4 Mbps as requested\n", olympic_priv->olympic_card_name) ;
+ writew(0, olympic_mmio+GPR);
+ }
+
+ writew(readw(olympic_mmio+GPR)|GPR_NEPTUNE_BF,olympic_mmio+GPR);
+
+#if OLYMPIC_DEBUG
+ printk("GPR = %x\n",readw(olympic_mmio + GPR) ) ;
+#endif
+ /* Solo has been paused to meet the Cardbus power
+ * specs if the adapter is cardbus. Check to
+ * see its been paused and then restart solo. The
+ * adapter should set the pause bit within 1 second.
+ */
+
+ if(!(readl(olympic_mmio+BCTL) & BCTL_MODE_INDICATOR)) {
+ t=jiffies;
+ while (!readl(olympic_mmio+CLKCTL) & CLKCTL_PAUSE) {
+ schedule() ;
+ if(jiffies-t > 2*HZ) {
+ printk(KERN_ERR "IBM Cardbus tokenring adapter not responsing.\n") ;
+ return -ENODEV;
+ }
+ }
+ writel(readl(olympic_mmio+CLKCTL) & ~CLKCTL_PAUSE, olympic_mmio+CLKCTL) ;
+ }
+
+ /* start solo init */
+ writel((1<<15),olympic_mmio+SISR_MASK_SUM);
+
+ t=jiffies;
+ while(!((readl(olympic_mmio+SISR_RR)) & SISR_SRB_REPLY)) {
+ schedule();
+ if(jiffies-t > 15*HZ) {
+ printk(KERN_ERR "IBM PCI tokenring card not responding.\n");
+ return -ENODEV;
+ }
+ }
+
+ writel(readw(olympic_mmio+LAPWWO),olympic_mmio+LAPA);
+
+#if OLYMPIC_DEBUG
+ printk("LAPWWO: %x, LAPA: %x\n",readl(olympic_mmio+LAPWWO), readl(olympic_mmio+LAPA));
+#endif
+
+ init_srb=olympic_priv->olympic_lap + ((readw(olympic_mmio+LAPWWO)) & (~0xf800));
+
+#if OLYMPIC_DEBUG
+{
+ int i;
+ printk("init_srb(%p): ",init_srb);
+ for(i=0;i<20;i++)
+ printk("%x ",readb(init_srb+i));
+ printk("\n");
+}
+#endif
+ if(readw(init_srb+6)) {
+ printk(KERN_INFO "tokenring card initialization failed. errorcode : %x\n",readw(init_srb+6));
+ return -ENODEV;
+ }
+
+ if (olympic_priv->olympic_message_level) {
+ if ( readb(init_srb +2) & 0x40) {
+ printk(KERN_INFO "Olympic: Adapter is FDX capable.\n") ;
+ } else {
+ printk(KERN_INFO "Olympic: Adapter cannot do FDX.\n");
+ }
+ }
+
+ uaa_addr=swab16(readw(init_srb+8));
+
+#if OLYMPIC_DEBUG
+ printk("UAA resides at %x\n",uaa_addr);
+#endif
+
+ writel(uaa_addr,olympic_mmio+LAPA);
+ adapter_addr=olympic_priv->olympic_lap + (uaa_addr & (~0xf800));
+
+#if OLYMPIC_DEBUG
+ printk("adapter address: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ readb(adapter_addr), readb(adapter_addr+1),readb(adapter_addr+2),
+ readb(adapter_addr+3),readb(adapter_addr+4),readb(adapter_addr+5));
+#endif
+
+ memcpy_fromio(&dev->dev_addr[0], adapter_addr,6);
+
+ olympic_priv->olympic_addr_table_addr = swab16(readw(init_srb + 12));
+ olympic_priv->olympic_parms_addr = swab16(readw(init_srb + 14));
+
+ return 0;
+
+}
+
+static int olympic_open(struct net_device *dev)
+{
+ struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+ u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio,*init_srb;
+ unsigned long flags, t;
+ int i, open_finished = 1 ;
+ u8 resp, err;
+
+ DECLARE_WAITQUEUE(wait,current) ;
+
+ olympic_init(dev);
+
+ if(request_irq(dev->irq, &olympic_interrupt, SA_SHIRQ , "olympic", dev)) {
+ return -EAGAIN;
+ }
+
+#if OLYMPIC_DEBUG
+ printk("BMCTL: %x\n",readl(olympic_mmio+BMCTL_SUM));
+ printk("pending ints: %x\n",readl(olympic_mmio+SISR_RR));
+#endif
+
+ writel(SISR_MI,olympic_mmio+SISR_MASK_SUM);
+
+ writel(SISR_MI | SISR_SRB_REPLY, olympic_mmio+SISR_MASK); /* more ints later, doesn't stop arb cmd interrupt */
+
+ writel(LISR_LIE,olympic_mmio+LISR); /* more ints later */
+
+ /* adapter is closed, so SRB is pointed to by LAPWWO */
+
+ writel(readw(olympic_mmio+LAPWWO),olympic_mmio+LAPA);
+ init_srb=olympic_priv->olympic_lap + ((readw(olympic_mmio+LAPWWO)) & (~0xf800));
+
+#if OLYMPIC_DEBUG
+ printk("LAPWWO: %x, LAPA: %x\n",readw(olympic_mmio+LAPWWO), readl(olympic_mmio+LAPA));
+ printk("SISR Mask = %04x\n", readl(olympic_mmio+SISR_MASK));
+ printk("Before the open command \n");
+#endif
+ do {
+ memset_io(init_srb,0,SRB_COMMAND_SIZE);
+
+ writeb(SRB_OPEN_ADAPTER,init_srb) ; /* open */
+ writeb(OLYMPIC_CLEAR_RET_CODE,init_srb+2);
+
+ /* If Network Monitor, instruct card to copy MAC frames through the ARB */
+ if (olympic_priv->olympic_network_monitor)
+ writew(swab16(OPEN_ADAPTER_ENABLE_FDX | OPEN_ADAPTER_PASS_ADC_MAC | OPEN_ADAPTER_PASS_ATT_MAC | OPEN_ADAPTER_PASS_BEACON), init_srb+8);
+ else
+ writew(swab16(OPEN_ADAPTER_ENABLE_FDX), init_srb+8);
+
+ /* Test OR of first 3 bytes as its totally possible for
+ * someone to set the first 2 bytes to be zero, although this
+ * is an error, the first byte must have bit 6 set to 1 */
+
+ if (olympic_priv->olympic_laa[0] | olympic_priv->olympic_laa[1] | olympic_priv->olympic_laa[2]) {
+ writeb(olympic_priv->olympic_laa[0],init_srb+12);
+ writeb(olympic_priv->olympic_laa[1],init_srb+13);
+ writeb(olympic_priv->olympic_laa[2],init_srb+14);
+ writeb(olympic_priv->olympic_laa[3],init_srb+15);
+ writeb(olympic_priv->olympic_laa[4],init_srb+16);
+ writeb(olympic_priv->olympic_laa[5],init_srb+17);
+ memcpy(dev->dev_addr,olympic_priv->olympic_laa,dev->addr_len) ;
+ }
+ writeb(1,init_srb+30);
+
+ spin_lock_irqsave(&olympic_priv->olympic_lock,flags);
+ olympic_priv->srb_queued=1;
+
+ writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+ spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
+
+ t = jiffies ;
+
+ add_wait_queue(&olympic_priv->srb_wait,&wait) ;
+ set_current_state(TASK_INTERRUPTIBLE) ;
+
+ while(olympic_priv->srb_queued) {
+ schedule() ;
+ if(signal_pending(current)) {
+ printk(KERN_WARNING "%s: Signal received in open.\n",
+ dev->name);
+ printk(KERN_WARNING "SISR=%x LISR=%x\n",
+ readl(olympic_mmio+SISR),
+ readl(olympic_mmio+LISR));
+ olympic_priv->srb_queued=0;
+ break;
+ }
+ if ((jiffies-t) > 10*HZ) {
+ printk(KERN_WARNING "%s: SRB timed out. \n",dev->name) ;
+ olympic_priv->srb_queued=0;
+ break ;
+ }
+ set_current_state(TASK_INTERRUPTIBLE) ;
+ }
+ remove_wait_queue(&olympic_priv->srb_wait,&wait) ;
+ set_current_state(TASK_RUNNING) ;
+ olympic_priv->srb_queued = 0 ;
+#if OLYMPIC_DEBUG
+ printk("init_srb(%p): ",init_srb);
+ for(i=0;i<20;i++)
+ printk("%02x ",readb(init_srb+i));
+ printk("\n");
+#endif
+
+ /* If we get the same return response as we set, the interrupt wasn't raised and the open
+ * timed out.
+ */
+
+ switch (resp = readb(init_srb+2)) {
+ case OLYMPIC_CLEAR_RET_CODE:
+ printk(KERN_WARNING "%s: Adapter Open time out or error.\n", dev->name) ;
+ goto out;
+ case 0:
+ open_finished = 1;
+ break;
+ case 0x07:
+ if (!olympic_priv->olympic_ring_speed && open_finished) { /* Autosense , first time around */
+ printk(KERN_WARNING "%s: Retrying at different ring speed \n", dev->name);
+ open_finished = 0 ;
+ continue;
+ }
+
+ err = readb(init_srb+7);
+
+ if (!olympic_priv->olympic_ring_speed && ((err & 0x0f) == 0x0d)) {
+ printk(KERN_WARNING "%s: Tried to autosense ring speed with no monitors present\n",dev->name);
+ printk(KERN_WARNING "%s: Please try again with a specified ring speed \n",dev->name);
+ } else {
+ printk(KERN_WARNING "%s: %s - %s\n", dev->name,
+ open_maj_error[(err & 0xf0) >> 4],
+ open_min_error[(err & 0x0f)]);
+ }
+ goto out;
+
+ case 0x32:
+ printk(KERN_WARNING "%s: Invalid LAA: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ dev->name,
+ olympic_priv->olympic_laa[0],
+ olympic_priv->olympic_laa[1],
+ olympic_priv->olympic_laa[2],
+ olympic_priv->olympic_laa[3],
+ olympic_priv->olympic_laa[4],
+ olympic_priv->olympic_laa[5]) ;
+ goto out;
+
+ default:
+ printk(KERN_WARNING "%s: Bad OPEN response: %x\n", dev->name, resp);
+ goto out;
+
+ }
+ } while (!(open_finished)) ; /* Will only loop if ring speed mismatch re-open attempted && autosense is on */
+
+ if (readb(init_srb+18) & (1<<3))
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Opened in FDX Mode\n",dev->name);
+
+ if (readb(init_srb+18) & (1<<1))
+ olympic_priv->olympic_ring_speed = 100 ;
+ else if (readb(init_srb+18) & 1)
+ olympic_priv->olympic_ring_speed = 16 ;
+ else
+ olympic_priv->olympic_ring_speed = 4 ;
+
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Opened in %d Mbps mode\n",dev->name, olympic_priv->olympic_ring_speed);
+
+ olympic_priv->asb = swab16(readw(init_srb+8));
+ olympic_priv->srb = swab16(readw(init_srb+10));
+ olympic_priv->arb = swab16(readw(init_srb+12));
+ olympic_priv->trb = swab16(readw(init_srb+16));
+
+ olympic_priv->olympic_receive_options = 0x01 ;
+ olympic_priv->olympic_copy_all_options = 0 ;
+
+ /* setup rx ring */
+
+ writel((3<<16),olympic_mmio+BMCTL_RWM); /* Ensure end of frame generated interrupts */
+
+ writel(BMCTL_RX_DIS|3,olympic_mmio+BMCTL_RWM); /* Yes, this the enables RX channel */
+
+ for(i=0;i<OLYMPIC_RX_RING_SIZE;i++) {
+
+ struct sk_buff *skb;
+
+ skb=dev_alloc_skb(olympic_priv->pkt_buf_sz);
+ if(skb == NULL)
+ break;
+
+ skb->dev = dev;
+
+ olympic_priv->olympic_rx_ring[i].buffer = cpu_to_le32(pci_map_single(olympic_priv->pdev,
+ skb->data,olympic_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE)) ;
+ olympic_priv->olympic_rx_ring[i].res_length = cpu_to_le32(olympic_priv->pkt_buf_sz);
+ olympic_priv->rx_ring_skb[i]=skb;
+ }
+
+ if (i==0) {
+ printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers. Adapter disabled\n",dev->name);
+ goto out;
+ }
+
+ olympic_priv->rx_ring_dma_addr = pci_map_single(olympic_priv->pdev,olympic_priv->olympic_rx_ring,
+ sizeof(struct olympic_rx_desc) * OLYMPIC_RX_RING_SIZE, PCI_DMA_TODEVICE);
+ writel(olympic_priv->rx_ring_dma_addr, olympic_mmio+RXDESCQ);
+ writel(olympic_priv->rx_ring_dma_addr, olympic_mmio+RXCDA);
+ writew(i, olympic_mmio+RXDESCQCNT);
+
+ olympic_priv->rx_status_ring_dma_addr = pci_map_single(olympic_priv->pdev, olympic_priv->olympic_rx_status_ring,
+ sizeof(struct olympic_rx_status) * OLYMPIC_RX_RING_SIZE, PCI_DMA_FROMDEVICE);
+ writel(olympic_priv->rx_status_ring_dma_addr, olympic_mmio+RXSTATQ);
+ writel(olympic_priv->rx_status_ring_dma_addr, olympic_mmio+RXCSA);
+
+ olympic_priv->rx_ring_last_received = OLYMPIC_RX_RING_SIZE - 1; /* last processed rx status */
+ olympic_priv->rx_status_last_received = OLYMPIC_RX_RING_SIZE - 1;
+
+ writew(i, olympic_mmio+RXSTATQCNT);
+
+#if OLYMPIC_DEBUG
+ printk("# of rx buffers: %d, RXENQ: %x\n",i, readw(olympic_mmio+RXENQ));
+ printk("RXCSA: %x, rx_status_ring[0]: %p\n",readl(olympic_mmio+RXCSA),&olympic_priv->olympic_rx_status_ring[0]);
+ printk(" stat_ring[1]: %p, stat_ring[2]: %p, stat_ring[3]: %p\n", &(olympic_priv->olympic_rx_status_ring[1]), &(olympic_priv->olympic_rx_status_ring[2]), &(olympic_priv->olympic_rx_status_ring[3]) );
+ printk(" stat_ring[4]: %p, stat_ring[5]: %p, stat_ring[6]: %p\n", &(olympic_priv->olympic_rx_status_ring[4]), &(olympic_priv->olympic_rx_status_ring[5]), &(olympic_priv->olympic_rx_status_ring[6]) );
+ printk(" stat_ring[7]: %p\n", &(olympic_priv->olympic_rx_status_ring[7]) );
+
+ printk("RXCDA: %x, rx_ring[0]: %p\n",readl(olympic_mmio+RXCDA),&olympic_priv->olympic_rx_ring[0]);
+ printk("Rx_ring_dma_addr = %08x, rx_status_dma_addr = %08x\n",
+ olympic_priv->rx_ring_dma_addr,olympic_priv->rx_status_ring_dma_addr) ;
+#endif
+
+ writew((((readw(olympic_mmio+RXENQ)) & 0x8000) ^ 0x8000) | i,olympic_mmio+RXENQ);
+
+#if OLYMPIC_DEBUG
+ printk("# of rx buffers: %d, RXENQ: %x\n",i, readw(olympic_mmio+RXENQ));
+ printk("RXCSA: %x, rx_ring[0]: %p\n",readl(olympic_mmio+RXCSA),&olympic_priv->olympic_rx_status_ring[0]);
+ printk("RXCDA: %x, rx_ring[0]: %p\n",readl(olympic_mmio+RXCDA),&olympic_priv->olympic_rx_ring[0]);
+#endif
+
+ writel(SISR_RX_STATUS | SISR_RX_NOBUF,olympic_mmio+SISR_MASK_SUM);
+
+ /* setup tx ring */
+
+ writel(BMCTL_TX1_DIS,olympic_mmio+BMCTL_RWM); /* Yes, this enables TX channel 1 */
+ for(i=0;i<OLYMPIC_TX_RING_SIZE;i++)
+ olympic_priv->olympic_tx_ring[i].buffer=0xdeadbeef;
+
+ olympic_priv->free_tx_ring_entries=OLYMPIC_TX_RING_SIZE;
+ olympic_priv->tx_ring_dma_addr = pci_map_single(olympic_priv->pdev,olympic_priv->olympic_tx_ring,
+ sizeof(struct olympic_tx_desc) * OLYMPIC_TX_RING_SIZE,PCI_DMA_TODEVICE) ;
+ writel(olympic_priv->tx_ring_dma_addr, olympic_mmio+TXDESCQ_1);
+ writel(olympic_priv->tx_ring_dma_addr, olympic_mmio+TXCDA_1);
+ writew(OLYMPIC_TX_RING_SIZE, olympic_mmio+TXDESCQCNT_1);
+
+ olympic_priv->tx_status_ring_dma_addr = pci_map_single(olympic_priv->pdev, olympic_priv->olympic_tx_status_ring,
+ sizeof(struct olympic_tx_status) * OLYMPIC_TX_RING_SIZE, PCI_DMA_FROMDEVICE);
+ writel(olympic_priv->tx_status_ring_dma_addr,olympic_mmio+TXSTATQ_1);
+ writel(olympic_priv->tx_status_ring_dma_addr,olympic_mmio+TXCSA_1);
+ writew(OLYMPIC_TX_RING_SIZE,olympic_mmio+TXSTATQCNT_1);
+
+ olympic_priv->tx_ring_free=0; /* next entry in tx ring to use */
+ olympic_priv->tx_ring_last_status=OLYMPIC_TX_RING_SIZE-1; /* last processed tx status */
+
+ writel(0xffffffff, olympic_mmio+EISR_RWM) ; /* clean the eisr */
+ writel(0,olympic_mmio+EISR) ;
+ writel(EISR_MASK_OPTIONS,olympic_mmio+EISR_MASK) ; /* enables most of the TX error interrupts */
+ writel(SISR_TX1_EOF | SISR_ADAPTER_CHECK | SISR_ARB_CMD | SISR_TRB_REPLY | SISR_ASB_FREE | SISR_ERR,olympic_mmio+SISR_MASK_SUM);
+
+#if OLYMPIC_DEBUG
+ printk("BMCTL: %x\n",readl(olympic_mmio+BMCTL_SUM));
+ printk("SISR MASK: %x\n",readl(olympic_mmio+SISR_MASK));
+#endif
+
+ if (olympic_priv->olympic_network_monitor) {
+ u8 __iomem *oat ;
+ u8 __iomem *opt ;
+ oat = (olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ;
+ opt = (olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ;
+
+ printk("%s: Node Address: %02x:%02x:%02x:%02x:%02x:%02x\n",dev->name,
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+1),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+2),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+3),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+4),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+5));
+ printk("%s: Functional Address: %02x:%02x:%02x:%02x\n",dev->name,
+ readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+1),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+2),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+3));
+ printk("%s: NAUN Address: %02x:%02x:%02x:%02x:%02x:%02x\n",dev->name,
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+1),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+2),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+3),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+4),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+5));
+ }
+
+ netif_start_queue(dev);
+ return 0;
+
+out:
+ free_irq(dev->irq, dev);
+ return -EIO;
+}
+
+/*
+ * When we enter the rx routine we do not know how many frames have been
+ * queued on the rx channel. Therefore we start at the next rx status
+ * position and travel around the receive ring until we have completed
+ * all the frames.
+ *
+ * This means that we may process the frame before we receive the end
+ * of frame interrupt. This is why we always test the status instead
+ * of blindly processing the next frame.
+ *
+ * We also remove the last 4 bytes from the packet as well, these are
+ * just token ring trailer info and upset protocols that don't check
+ * their own length, i.e. SNA.
+ *
+ */
+static void olympic_rx(struct net_device *dev)
+{
+ struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+ u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio;
+ struct olympic_rx_status *rx_status;
+ struct olympic_rx_desc *rx_desc ;
+ int rx_ring_last_received,length, buffer_cnt, cpy_length, frag_len;
+ struct sk_buff *skb, *skb2;
+ int i;
+
+ rx_status=&(olympic_priv->olympic_rx_status_ring[(olympic_priv->rx_status_last_received + 1) & (OLYMPIC_RX_RING_SIZE - 1)]) ;
+
+ while (rx_status->status_buffercnt) {
+ u32 l_status_buffercnt;
+
+ olympic_priv->rx_status_last_received++ ;
+ olympic_priv->rx_status_last_received &= (OLYMPIC_RX_RING_SIZE -1);
+#if OLYMPIC_DEBUG
+ printk("rx status: %x rx len: %x \n", le32_to_cpu(rx_status->status_buffercnt), le32_to_cpu(rx_status->fragmentcnt_framelen));
+#endif
+ length = le32_to_cpu(rx_status->fragmentcnt_framelen) & 0xffff;
+ buffer_cnt = le32_to_cpu(rx_status->status_buffercnt) & 0xffff;
+ i = buffer_cnt ; /* Need buffer_cnt later for rxenq update */
+ frag_len = le32_to_cpu(rx_status->fragmentcnt_framelen) >> 16;
+
+#if OLYMPIC_DEBUG
+ printk("length: %x, frag_len: %x, buffer_cnt: %x\n", length, frag_len, buffer_cnt);
+#endif
+ l_status_buffercnt = le32_to_cpu(rx_status->status_buffercnt);
+ if(l_status_buffercnt & 0xC0000000) {
+ if (l_status_buffercnt & 0x3B000000) {
+ if (olympic_priv->olympic_message_level) {
+ if (l_status_buffercnt & (1<<29)) /* Rx Frame Truncated */
+ printk(KERN_WARNING "%s: Rx Frame Truncated \n",dev->name);
+ if (l_status_buffercnt & (1<<28)) /*Rx receive overrun */
+ printk(KERN_WARNING "%s: Rx Frame Receive overrun \n",dev->name);
+ if (l_status_buffercnt & (1<<27)) /* No receive buffers */
+ printk(KERN_WARNING "%s: No receive buffers \n",dev->name);
+ if (l_status_buffercnt & (1<<25)) /* Receive frame error detect */
+ printk(KERN_WARNING "%s: Receive frame error detect \n",dev->name);
+ if (l_status_buffercnt & (1<<24)) /* Received Error Detect */
+ printk(KERN_WARNING "%s: Received Error Detect \n",dev->name);
+ }
+ olympic_priv->rx_ring_last_received += i ;
+ olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1) ;
+ olympic_priv->olympic_stats.rx_errors++;
+ } else {
+
+ if (buffer_cnt == 1) {
+ skb = dev_alloc_skb(max_t(int, olympic_priv->pkt_buf_sz,length)) ;
+ } else {
+ skb = dev_alloc_skb(length) ;
+ }
+
+ if (skb == NULL) {
+ printk(KERN_WARNING "%s: Not enough memory to copy packet to upper layers. \n",dev->name) ;
+ olympic_priv->olympic_stats.rx_dropped++ ;
+ /* Update counters even though we don't transfer the frame */
+ olympic_priv->rx_ring_last_received += i ;
+ olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1) ;
+ } else {
+ skb->dev = dev ;
+
+ /* Optimise based upon number of buffers used.
+ If only one buffer is used we can simply swap the buffers around.
+ If more than one then we must use the new buffer and copy the information
+ first. Ideally all frames would be in a single buffer, this can be tuned by
+ altering the buffer size. If the length of the packet is less than
+ 1500 bytes we're going to copy it over anyway to stop packets getting
+ dropped from sockets with buffers smaller than our pkt_buf_sz. */
+
+ if (buffer_cnt==1) {
+ olympic_priv->rx_ring_last_received++ ;
+ olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1);
+ rx_ring_last_received = olympic_priv->rx_ring_last_received ;
+ if (length > 1500) {
+ skb2=olympic_priv->rx_ring_skb[rx_ring_last_received] ;
+ /* unmap buffer */
+ pci_unmap_single(olympic_priv->pdev,
+ le32_to_cpu(olympic_priv->olympic_rx_ring[rx_ring_last_received].buffer),
+ olympic_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ;
+ skb_put(skb2,length-4);
+ skb2->protocol = tr_type_trans(skb2,dev);
+ olympic_priv->olympic_rx_ring[rx_ring_last_received].buffer =
+ cpu_to_le32(pci_map_single(olympic_priv->pdev, skb->data,
+ olympic_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE));
+ olympic_priv->olympic_rx_ring[rx_ring_last_received].res_length =
+ cpu_to_le32(olympic_priv->pkt_buf_sz);
+ olympic_priv->rx_ring_skb[rx_ring_last_received] = skb ;
+ netif_rx(skb2) ;
+ } else {
+ pci_dma_sync_single_for_cpu(olympic_priv->pdev,
+ le32_to_cpu(olympic_priv->olympic_rx_ring[rx_ring_last_received].buffer),
+ olympic_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ;
+ memcpy(skb_put(skb,length-4),olympic_priv->rx_ring_skb[rx_ring_last_received]->data,length-4) ;
+ pci_dma_sync_single_for_device(olympic_priv->pdev,
+ le32_to_cpu(olympic_priv->olympic_rx_ring[rx_ring_last_received].buffer),
+ olympic_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ;
+ skb->protocol = tr_type_trans(skb,dev) ;
+ netif_rx(skb) ;
+ }
+ } else {
+ do { /* Walk the buffers */
+ olympic_priv->rx_ring_last_received++ ;
+ olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1);
+ rx_ring_last_received = olympic_priv->rx_ring_last_received ;
+ pci_dma_sync_single_for_cpu(olympic_priv->pdev,
+ le32_to_cpu(olympic_priv->olympic_rx_ring[rx_ring_last_received].buffer),
+ olympic_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ;
+ rx_desc = &(olympic_priv->olympic_rx_ring[rx_ring_last_received]);
+ cpy_length = (i == 1 ? frag_len : le32_to_cpu(rx_desc->res_length));
+ memcpy(skb_put(skb, cpy_length), olympic_priv->rx_ring_skb[rx_ring_last_received]->data, cpy_length) ;
+ pci_dma_sync_single_for_device(olympic_priv->pdev,
+ le32_to_cpu(olympic_priv->olympic_rx_ring[rx_ring_last_received].buffer),
+ olympic_priv->pkt_buf_sz,PCI_DMA_FROMDEVICE) ;
+ } while (--i) ;
+ skb_trim(skb,skb->len-4) ;
+ skb->protocol = tr_type_trans(skb,dev);
+ netif_rx(skb) ;
+ }
+ dev->last_rx = jiffies ;
+ olympic_priv->olympic_stats.rx_packets++ ;
+ olympic_priv->olympic_stats.rx_bytes += length ;
+ } /* if skb == null */
+ } /* If status & 0x3b */
+
+ } else { /*if buffercnt & 0xC */
+ olympic_priv->rx_ring_last_received += i ;
+ olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE - 1) ;
+ }
+
+ rx_status->fragmentcnt_framelen = 0 ;
+ rx_status->status_buffercnt = 0 ;
+ rx_status = &(olympic_priv->olympic_rx_status_ring[(olympic_priv->rx_status_last_received+1) & (OLYMPIC_RX_RING_SIZE -1) ]);
+
+ writew((((readw(olympic_mmio+RXENQ)) & 0x8000) ^ 0x8000) | buffer_cnt , olympic_mmio+RXENQ);
+ } /* while */
+
+}
+
+static void olympic_freemem(struct net_device *dev)
+{
+ struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+ int i;
+
+ for(i=0;i<OLYMPIC_RX_RING_SIZE;i++) {
+ if (olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received] != NULL) {
+ dev_kfree_skb_irq(olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received]);
+ olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received] = NULL;
+ }
+ if (olympic_priv->olympic_rx_ring[olympic_priv->rx_status_last_received].buffer != 0xdeadbeef) {
+ pci_unmap_single(olympic_priv->pdev,
+ le32_to_cpu(olympic_priv->olympic_rx_ring[olympic_priv->rx_status_last_received].buffer),
+ olympic_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE);
+ }
+ olympic_priv->rx_status_last_received++;
+ olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;
+ }
+ /* unmap rings */
+ pci_unmap_single(olympic_priv->pdev, olympic_priv->rx_status_ring_dma_addr,
+ sizeof(struct olympic_rx_status) * OLYMPIC_RX_RING_SIZE, PCI_DMA_FROMDEVICE);
+ pci_unmap_single(olympic_priv->pdev, olympic_priv->rx_ring_dma_addr,
+ sizeof(struct olympic_rx_desc) * OLYMPIC_RX_RING_SIZE, PCI_DMA_TODEVICE);
+
+ pci_unmap_single(olympic_priv->pdev, olympic_priv->tx_status_ring_dma_addr,
+ sizeof(struct olympic_tx_status) * OLYMPIC_TX_RING_SIZE, PCI_DMA_FROMDEVICE);
+ pci_unmap_single(olympic_priv->pdev, olympic_priv->tx_ring_dma_addr,
+ sizeof(struct olympic_tx_desc) * OLYMPIC_TX_RING_SIZE, PCI_DMA_TODEVICE);
+
+ return ;
+}
+
+static irqreturn_t olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev= (struct net_device *)dev_id;
+ struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+ u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio;
+ u32 sisr;
+ u8 __iomem *adapter_check_area ;
+
+ /*
+ * Read sisr but don't reset it yet.
+ * The indication bit may have been set but the interrupt latch
+ * bit may not be set, so we'd lose the interrupt later.
+ */
+ sisr=readl(olympic_mmio+SISR) ;
+ if (!(sisr & SISR_MI)) /* Interrupt isn't for us */
+ return IRQ_NONE;
+ sisr=readl(olympic_mmio+SISR_RR) ; /* Read & Reset sisr */
+
+ spin_lock(&olympic_priv->olympic_lock);
+
+ /* Hotswap gives us this on removal */
+ if (sisr == 0xffffffff) {
+ printk(KERN_WARNING "%s: Hotswap adapter removal.\n",dev->name) ;
+ spin_unlock(&olympic_priv->olympic_lock) ;
+ return IRQ_NONE;
+ }
+
+ 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 | SISR_ERR)) {
+
+ /* If we ever get this the adapter is seriously dead. Only a reset is going to
+ * bring it back to life. We're talking pci bus errors and such like :( */
+ if((sisr & SISR_ERR) && (readl(olympic_mmio+EISR) & EISR_MASK_OPTIONS)) {
+ printk(KERN_ERR "Olympic: EISR Error, EISR=%08x\n",readl(olympic_mmio+EISR)) ;
+ printk(KERN_ERR "The adapter must be reset to clear this condition.\n") ;
+ printk(KERN_ERR "Please report this error to the driver maintainer and/\n") ;
+ printk(KERN_ERR "or the linux-tr mailing list.\n") ;
+ wake_up_interruptible(&olympic_priv->srb_wait);
+ spin_unlock(&olympic_priv->olympic_lock) ;
+ return IRQ_HANDLED;
+ } /* SISR_ERR */
+
+ if(sisr & SISR_SRB_REPLY) {
+ if(olympic_priv->srb_queued==1) {
+ wake_up_interruptible(&olympic_priv->srb_wait);
+ } else if (olympic_priv->srb_queued==2) {
+ olympic_srb_bh(dev) ;
+ }
+ olympic_priv->srb_queued=0;
+ } /* SISR_SRB_REPLY */
+
+ /* We shouldn't ever miss the Tx interrupt, but the you never know, hence the loop to ensure
+ we get all tx completions. */
+ if (sisr & SISR_TX1_EOF) {
+ while(olympic_priv->olympic_tx_status_ring[(olympic_priv->tx_ring_last_status + 1) & (OLYMPIC_TX_RING_SIZE-1)].status) {
+ olympic_priv->tx_ring_last_status++;
+ olympic_priv->tx_ring_last_status &= (OLYMPIC_TX_RING_SIZE-1);
+ olympic_priv->free_tx_ring_entries++;
+ olympic_priv->olympic_stats.tx_bytes += olympic_priv->tx_ring_skb[olympic_priv->tx_ring_last_status]->len;
+ olympic_priv->olympic_stats.tx_packets++ ;
+ pci_unmap_single(olympic_priv->pdev,
+ le32_to_cpu(olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_last_status].buffer),
+ olympic_priv->tx_ring_skb[olympic_priv->tx_ring_last_status]->len,PCI_DMA_TODEVICE);
+ dev_kfree_skb_irq(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;
+ }
+ netif_wake_queue(dev);
+ } /* SISR_TX1_EOF */
+
+ if (sisr & SISR_RX_STATUS) {
+ olympic_rx(dev);
+ } /* SISR_RX_STATUS */
+
+ if (sisr & SISR_ADAPTER_CHECK) {
+ netif_stop_queue(dev);
+ printk(KERN_WARNING "%s: Adapter Check Interrupt Raised, 8 bytes of information follow:\n", dev->name);
+ writel(readl(olympic_mmio+LAPWWC),olympic_mmio+LAPA);
+ adapter_check_area = olympic_priv->olympic_lap + ((readl(olympic_mmio+LAPWWC)) & (~0xf800)) ;
+ 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)) ;
+ spin_unlock(&olympic_priv->olympic_lock) ;
+ return IRQ_HANDLED;
+ } /* SISR_ADAPTER_CHECK */
+
+ if (sisr & SISR_ASB_FREE) {
+ /* Wake up anything that is waiting for the asb response */
+ if (olympic_priv->asb_queued) {
+ olympic_asb_bh(dev) ;
+ }
+ } /* SISR_ASB_FREE */
+
+ if (sisr & SISR_ARB_CMD) {
+ olympic_arb_cmd(dev) ;
+ } /* SISR_ARB_CMD */
+
+ if (sisr & SISR_TRB_REPLY) {
+ /* Wake up anything that is waiting for the trb response */
+ if (olympic_priv->trb_queued) {
+ wake_up_interruptible(&olympic_priv->trb_wait);
+ }
+ olympic_priv->trb_queued = 0 ;
+ } /* SISR_TRB_REPLY */
+
+ if (sisr & SISR_RX_NOBUF) {
+ /* According to the documentation, we don't have to do anything, but trapping it keeps it out of
+ /var/log/messages. */
+ } /* SISR_RX_NOBUF */
+ } else {
+ printk(KERN_WARNING "%s: Unexpected interrupt: %x\n",dev->name, sisr);
+ printk(KERN_WARNING "%s: SISR_MASK: %x\n",dev->name, readl(olympic_mmio+SISR_MASK)) ;
+ } /* One if the interrupts we want */
+ writel(SISR_MI,olympic_mmio+SISR_MASK_SUM);
+
+ spin_unlock(&olympic_priv->olympic_lock) ;
+ return IRQ_HANDLED;
+}
+
+static int olympic_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+ u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio;
+ unsigned long flags ;
+
+ spin_lock_irqsave(&olympic_priv->olympic_lock, flags);
+
+ netif_stop_queue(dev);
+
+ if(olympic_priv->free_tx_ring_entries) {
+ olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].buffer =
+ cpu_to_le32(pci_map_single(olympic_priv->pdev, skb->data, skb->len,PCI_DMA_TODEVICE));
+ olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].status_length = cpu_to_le32(skb->len | (0x80000000));
+ olympic_priv->tx_ring_skb[olympic_priv->tx_ring_free]=skb;
+ olympic_priv->free_tx_ring_entries--;
+
+ olympic_priv->tx_ring_free++;
+ olympic_priv->tx_ring_free &= (OLYMPIC_TX_RING_SIZE-1);
+ writew((((readw(olympic_mmio+TXENQ_1)) & 0x8000) ^ 0x8000) | 1,olympic_mmio+TXENQ_1);
+ netif_wake_queue(dev);
+ spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
+ return 0;
+ } else {
+ spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
+ return 1;
+ }
+
+}
+
+
+static int olympic_close(struct net_device *dev)
+{
+ struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+ u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio,*srb;
+ unsigned long t,flags;
+
+ DECLARE_WAITQUEUE(wait,current) ;
+
+ netif_stop_queue(dev);
+
+ writel(olympic_priv->srb,olympic_mmio+LAPA);
+ srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800));
+
+ writeb(SRB_CLOSE_ADAPTER,srb+0);
+ writeb(0,srb+1);
+ writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+
+ add_wait_queue(&olympic_priv->srb_wait,&wait) ;
+ set_current_state(TASK_INTERRUPTIBLE) ;
+
+ spin_lock_irqsave(&olympic_priv->olympic_lock,flags);
+ olympic_priv->srb_queued=1;
+
+ writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+ spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
+
+ while(olympic_priv->srb_queued) {
+
+ t = schedule_timeout(60*HZ);
+
+ if(signal_pending(current)) {
+ printk(KERN_WARNING "%s: SRB timed out.\n",dev->name);
+ printk(KERN_WARNING "SISR=%x MISR=%x\n",readl(olympic_mmio+SISR),readl(olympic_mmio+LISR));
+ olympic_priv->srb_queued=0;
+ break;
+ }
+
+ if (t == 0) {
+ printk(KERN_WARNING "%s: SRB timed out. May not be fatal. \n",dev->name) ;
+ }
+ olympic_priv->srb_queued=0;
+ }
+ remove_wait_queue(&olympic_priv->srb_wait,&wait) ;
+
+ olympic_priv->rx_status_last_received++;
+ olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;
+
+ olympic_freemem(dev) ;
+
+ /* reset tx/rx fifo's and busmaster logic */
+
+ writel(readl(olympic_mmio+BCTL)|(3<<13),olympic_mmio+BCTL);
+ udelay(1);
+ writel(readl(olympic_mmio+BCTL)&~(3<<13),olympic_mmio+BCTL);
+
+#if OLYMPIC_DEBUG
+ {
+ int i ;
+ printk("srb(%p): ",srb);
+ for(i=0;i<4;i++)
+ printk("%x ",readb(srb+i));
+ printk("\n");
+ }
+#endif
+ free_irq(dev->irq,dev);
+
+ return 0;
+
+}
+
+static void olympic_set_rx_mode(struct net_device *dev)
+{
+ struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ;
+ u8 __iomem *olympic_mmio = olympic_priv->olympic_mmio ;
+ u8 options = 0;
+ u8 __iomem *srb;
+ struct dev_mc_list *dmi ;
+ unsigned char dev_mc_address[4] ;
+ int i ;
+
+ writel(olympic_priv->srb,olympic_mmio+LAPA);
+ srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800));
+ options = olympic_priv->olympic_copy_all_options;
+
+ if (dev->flags&IFF_PROMISC)
+ options |= 0x61 ;
+ else
+ options &= ~0x61 ;
+
+ /* Only issue the srb if there is a change in options */
+
+ if ((options ^ olympic_priv->olympic_copy_all_options)) {
+
+ /* Now to issue the srb command to alter the copy.all.options */
+
+ writeb(SRB_MODIFY_RECEIVE_OPTIONS,srb);
+ writeb(0,srb+1);
+ writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+ writeb(0,srb+3);
+ writeb(olympic_priv->olympic_receive_options,srb+4);
+ writeb(options,srb+5);
+
+ olympic_priv->srb_queued=2; /* Can't sleep, use srb_bh */
+
+ writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+
+ olympic_priv->olympic_copy_all_options = options ;
+
+ return ;
+ }
+
+ /* Set the functional addresses we need for multicast */
+
+ dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ;
+
+ for (i=0,dmi=dev->mc_list;i < dev->mc_count; i++,dmi = dmi->next) {
+ dev_mc_address[0] |= dmi->dmi_addr[2] ;
+ dev_mc_address[1] |= dmi->dmi_addr[3] ;
+ dev_mc_address[2] |= dmi->dmi_addr[4] ;
+ dev_mc_address[3] |= dmi->dmi_addr[5] ;
+ }
+
+ writeb(SRB_SET_FUNC_ADDRESS,srb+0);
+ writeb(0,srb+1);
+ writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+ writeb(0,srb+3);
+ writeb(0,srb+4);
+ writeb(0,srb+5);
+ writeb(dev_mc_address[0],srb+6);
+ writeb(dev_mc_address[1],srb+7);
+ writeb(dev_mc_address[2],srb+8);
+ writeb(dev_mc_address[3],srb+9);
+
+ olympic_priv->srb_queued = 2 ;
+ writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+
+}
+
+static void olympic_srb_bh(struct net_device *dev)
+{
+ struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ;
+ u8 __iomem *olympic_mmio = olympic_priv->olympic_mmio ;
+ u8 __iomem *srb;
+
+ writel(olympic_priv->srb,olympic_mmio+LAPA);
+ srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800));
+
+ switch (readb(srb)) {
+
+ /* SRB_MODIFY_RECEIVE_OPTIONS i.e. set_multicast_list options (promiscuous)
+ * At some point we should do something if we get an error, such as
+ * resetting the IFF_PROMISC flag in dev
+ */
+
+ case SRB_MODIFY_RECEIVE_OPTIONS:
+ switch (readb(srb+2)) {
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized srb command\n",dev->name) ;
+ break ;
+ case 0x04:
+ printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name);
+ break ;
+ default:
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_WARNING "%s: Receive Options Modified to %x,%x\n",dev->name,olympic_priv->olympic_copy_all_options, olympic_priv->olympic_receive_options) ;
+ break ;
+ } /* switch srb[2] */
+ break ;
+
+ /* SRB_SET_GROUP_ADDRESS - Multicast group setting
+ */
+
+ case SRB_SET_GROUP_ADDRESS:
+ switch (readb(srb+2)) {
+ case 0x00:
+ break ;
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ;
+ break ;
+ case 0x04:
+ printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name);
+ break ;
+ case 0x3c:
+ printk(KERN_WARNING "%s: Group/Functional address indicator bits not set correctly\n",dev->name) ;
+ break ;
+ case 0x3e: /* If we ever implement individual multicast addresses, will need to deal with this */
+ printk(KERN_WARNING "%s: Group address registers full\n",dev->name) ;
+ break ;
+ case 0x55:
+ printk(KERN_INFO "%s: Group Address already set.\n",dev->name) ;
+ break ;
+ default:
+ break ;
+ } /* switch srb[2] */
+ break ;
+
+ /* SRB_RESET_GROUP_ADDRESS - Remove a multicast address from group list
+ */
+
+ case SRB_RESET_GROUP_ADDRESS:
+ switch (readb(srb+2)) {
+ case 0x00:
+ break ;
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ;
+ break ;
+ case 0x04:
+ printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ;
+ break ;
+ case 0x39: /* Must deal with this if individual multicast addresses used */
+ printk(KERN_INFO "%s: Group address not found \n",dev->name);
+ break ;
+ default:
+ break ;
+ } /* switch srb[2] */
+ break ;
+
+
+ /* SRB_SET_FUNC_ADDRESS - Called by the set_rx_mode
+ */
+
+ case SRB_SET_FUNC_ADDRESS:
+ switch (readb(srb+2)) {
+ case 0x00:
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Functional Address Mask Set \n",dev->name) ;
+ break ;
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ;
+ break ;
+ case 0x04:
+ printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ;
+ break ;
+ default:
+ break ;
+ } /* switch srb[2] */
+ break ;
+
+ /* SRB_READ_LOG - Read and reset the adapter error counters
+ */
+
+ case SRB_READ_LOG:
+ switch (readb(srb+2)) {
+ case 0x00:
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Read Log issued\n",dev->name) ;
+ break ;
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ;
+ break ;
+ case 0x04:
+ printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ;
+ break ;
+
+ } /* switch srb[2] */
+ break ;
+
+ /* SRB_READ_SR_COUNTERS - Read and reset the source routing bridge related counters */
+
+ case SRB_READ_SR_COUNTERS:
+ switch (readb(srb+2)) {
+ case 0x00:
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Read Source Routing Counters issued\n",dev->name) ;
+ break ;
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ;
+ break ;
+ case 0x04:
+ printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ;
+ break ;
+ default:
+ break ;
+ } /* switch srb[2] */
+ break ;
+
+ default:
+ printk(KERN_WARNING "%s: Unrecognized srb bh return value.\n",dev->name);
+ break ;
+ } /* switch srb[0] */
+
+}
+
+static struct net_device_stats * olympic_get_stats(struct net_device *dev)
+{
+ struct olympic_private *olympic_priv ;
+ olympic_priv=(struct olympic_private *) dev->priv;
+ return (struct net_device_stats *) &olympic_priv->olympic_stats;
+}
+
+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 (netif_running(dev)) {
+ printk(KERN_WARNING "%s: Cannot set mac/laa address while card is open\n", dev->name) ;
+ return -EIO ;
+ }
+
+ memcpy(olympic_priv->olympic_laa, saddr->sa_data,dev->addr_len) ;
+
+ if (olympic_priv->olympic_message_level) {
+ printk(KERN_INFO "%s: MAC/LAA Set to = %x.%x.%x.%x.%x.%x\n",dev->name, olympic_priv->olympic_laa[0],
+ olympic_priv->olympic_laa[1], olympic_priv->olympic_laa[2],
+ olympic_priv->olympic_laa[3], olympic_priv->olympic_laa[4],
+ olympic_priv->olympic_laa[5]);
+ }
+
+ return 0 ;
+}
+
+static void olympic_arb_cmd(struct net_device *dev)
+{
+ struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv;
+ u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio;
+ u8 __iomem *arb_block, *asb_block, *srb ;
+ u8 header_len ;
+ u16 frame_len, buffer_len ;
+ struct sk_buff *mac_frame ;
+ u8 __iomem *buf_ptr ;
+ u8 __iomem *frame_data ;
+ u16 buff_off ;
+ u16 lan_status = 0, lan_status_diff ; /* Initialize to stop compiler warning */
+ u8 fdx_prot_error ;
+ u16 next_ptr;
+
+ arb_block = (olympic_priv->olympic_lap + olympic_priv->arb) ;
+ asb_block = (olympic_priv->olympic_lap + olympic_priv->asb) ;
+ srb = (olympic_priv->olympic_lap + olympic_priv->srb) ;
+
+ if (readb(arb_block+0) == ARB_RECEIVE_DATA) { /* Receive.data, MAC frames */
+
+ header_len = readb(arb_block+8) ; /* 802.5 Token-Ring Header Length */
+ frame_len = swab16(readw(arb_block + 10)) ;
+
+ buff_off = swab16(readw(arb_block + 6)) ;
+
+ buf_ptr = olympic_priv->olympic_lap + buff_off ;
+
+#if OLYMPIC_DEBUG
+{
+ int i;
+ frame_data = buf_ptr+offsetof(struct mac_receive_buffer,frame_data) ;
+
+ for (i=0 ; i < 14 ; i++) {
+ printk("Loc %d = %02x\n",i,readb(frame_data + i));
+ }
+
+ printk("next %04x, fs %02x, len %04x \n",readw(buf_ptr+offsetof(struct mac_receive_buffer,next)), readb(buf_ptr+offsetof(struct mac_receive_buffer,frame_status)), readw(buf_ptr+offsetof(struct mac_receive_buffer,buffer_length)));
+}
+#endif
+ mac_frame = dev_alloc_skb(frame_len) ;
+ if (!mac_frame) {
+ printk(KERN_WARNING "%s: Memory squeeze, dropping frame.\n", dev->name);
+ goto drop_frame;
+ }
+
+ /* Walk the buffer chain, creating the frame */
+
+ do {
+ frame_data = buf_ptr+offsetof(struct mac_receive_buffer,frame_data) ;
+ buffer_len = swab16(readw(buf_ptr+offsetof(struct mac_receive_buffer,buffer_length)));
+ memcpy_fromio(skb_put(mac_frame, buffer_len), frame_data , buffer_len ) ;
+ next_ptr=readw(buf_ptr+offsetof(struct mac_receive_buffer,next));
+ } while (next_ptr && (buf_ptr=olympic_priv->olympic_lap + ntohs(next_ptr)));
+
+ if (olympic_priv->olympic_network_monitor) {
+ struct trh_hdr *mac_hdr ;
+ printk(KERN_WARNING "%s: Received MAC Frame, details: \n",dev->name) ;
+ mac_hdr = (struct trh_hdr *)mac_frame->data ;
+ printk(KERN_WARNING "%s: MAC Frame Dest. Addr: %02x:%02x:%02x:%02x:%02x:%02x \n", dev->name , mac_hdr->daddr[0], mac_hdr->daddr[1], mac_hdr->daddr[2], mac_hdr->daddr[3], mac_hdr->daddr[4], mac_hdr->daddr[5]) ;
+ printk(KERN_WARNING "%s: MAC Frame Srce. Addr: %02x:%02x:%02x:%02x:%02x:%02x \n", dev->name , mac_hdr->saddr[0], mac_hdr->saddr[1], mac_hdr->saddr[2], mac_hdr->saddr[3], mac_hdr->saddr[4], mac_hdr->saddr[5]) ;
+ }
+ mac_frame->dev = dev ;
+ mac_frame->protocol = tr_type_trans(mac_frame,dev);
+ netif_rx(mac_frame) ;
+ dev->last_rx = jiffies;
+
+drop_frame:
+ /* Now tell the card we have dealt with the received frame */
+
+ /* Set LISR Bit 1 */
+ writel(LISR_ARB_FREE,olympic_priv->olympic_mmio + LISR_SUM);
+
+ /* Is the ASB free ? */
+
+ if (readb(asb_block + 2) != 0xff) {
+ olympic_priv->asb_queued = 1 ;
+ writel(LISR_ASB_FREE_REQ,olympic_priv->olympic_mmio+LISR_SUM);
+ return ;
+ /* Drop out and wait for the bottom half to be run */
+ }
+
+ writeb(ASB_RECEIVE_DATA,asb_block); /* Receive data */
+ writeb(OLYMPIC_CLEAR_RET_CODE,asb_block+2); /* Necessary ?? */
+ writeb(readb(arb_block+6),asb_block+6); /* Must send the address back to the adapter */
+ writeb(readb(arb_block+7),asb_block+7); /* To let it know we have dealt with the data */
+
+ writel(LISR_ASB_REPLY | LISR_ASB_FREE_REQ,olympic_priv->olympic_mmio+LISR_SUM);
+
+ olympic_priv->asb_queued = 2 ;
+
+ return ;
+
+ } else if (readb(arb_block) == ARB_LAN_CHANGE_STATUS) { /* Lan.change.status */
+ lan_status = swab16(readw(arb_block+6));
+ fdx_prot_error = readb(arb_block+8) ;
+
+ /* Issue ARB Free */
+ writel(LISR_ARB_FREE,olympic_priv->olympic_mmio+LISR_SUM);
+
+ lan_status_diff = olympic_priv->olympic_lan_status ^ lan_status ;
+
+ if (lan_status_diff & (LSC_LWF | LSC_ARW | LSC_FPE | LSC_RR) ) {
+ if (lan_status_diff & LSC_LWF)
+ printk(KERN_WARNING "%s: Short circuit detected on the lobe\n",dev->name);
+ if (lan_status_diff & LSC_ARW)
+ printk(KERN_WARNING "%s: Auto removal error\n",dev->name);
+ if (lan_status_diff & LSC_FPE)
+ printk(KERN_WARNING "%s: FDX Protocol Error\n",dev->name);
+ if (lan_status_diff & LSC_RR)
+ printk(KERN_WARNING "%s: Force remove MAC frame received\n",dev->name);
+
+ /* Adapter has been closed by the hardware */
+
+ /* reset tx/rx fifo's and busmaster logic */
+
+ writel(readl(olympic_mmio+BCTL)|(3<<13),olympic_mmio+BCTL);
+ udelay(1);
+ writel(readl(olympic_mmio+BCTL)&~(3<<13),olympic_mmio+BCTL);
+ netif_stop_queue(dev);
+ olympic_priv->srb = readw(olympic_priv->olympic_lap + LAPWWO) ;
+ printk(KERN_WARNING "%s: Adapter has been closed \n", dev->name) ;
+ } /* If serious error */
+
+ if (olympic_priv->olympic_message_level) {
+ if (lan_status_diff & LSC_SIG_LOSS)
+ printk(KERN_WARNING "%s: No receive signal detected \n", dev->name) ;
+ if (lan_status_diff & LSC_HARD_ERR)
+ printk(KERN_INFO "%s: Beaconing \n",dev->name);
+ if (lan_status_diff & LSC_SOFT_ERR)
+ printk(KERN_WARNING "%s: Adapter transmitted Soft Error Report Mac Frame \n",dev->name);
+ if (lan_status_diff & LSC_TRAN_BCN)
+ printk(KERN_INFO "%s: We are tranmitting the beacon, aaah\n",dev->name);
+ if (lan_status_diff & LSC_SS)
+ printk(KERN_INFO "%s: Single Station on the ring \n", dev->name);
+ if (lan_status_diff & LSC_RING_REC)
+ printk(KERN_INFO "%s: Ring recovery ongoing\n",dev->name);
+ if (lan_status_diff & LSC_FDX_MODE)
+ printk(KERN_INFO "%s: Operating in FDX mode\n",dev->name);
+ }
+
+ if (lan_status_diff & LSC_CO) {
+
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Counter Overflow \n", dev->name);
+
+ /* Issue READ.LOG command */
+
+ writeb(SRB_READ_LOG, srb);
+ writeb(0,srb+1);
+ writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+ writeb(0,srb+3);
+ writeb(0,srb+4);
+ writeb(0,srb+5);
+
+ olympic_priv->srb_queued=2; /* Can't sleep, use srb_bh */
+
+ writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+
+ }
+
+ if (lan_status_diff & LSC_SR_CO) {
+
+ if (olympic_priv->olympic_message_level)
+ printk(KERN_INFO "%s: Source routing counters overflow\n", dev->name);
+
+ /* Issue a READ.SR.COUNTERS */
+
+ writeb(SRB_READ_SR_COUNTERS,srb);
+ writeb(0,srb+1);
+ writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+ writeb(0,srb+3);
+
+ olympic_priv->srb_queued=2; /* Can't sleep, use srb_bh */
+
+ writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+
+ }
+
+ olympic_priv->olympic_lan_status = lan_status ;
+
+ } /* Lan.change.status */
+ else
+ printk(KERN_WARNING "%s: Unknown arb command \n", dev->name);
+}
+
+static void olympic_asb_bh(struct net_device *dev)
+{
+ struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ;
+ u8 __iomem *arb_block, *asb_block ;
+
+ arb_block = (olympic_priv->olympic_lap + olympic_priv->arb) ;
+ asb_block = (olympic_priv->olympic_lap + olympic_priv->asb) ;
+
+ if (olympic_priv->asb_queued == 1) { /* Dropped through the first time */
+
+ writeb(ASB_RECEIVE_DATA,asb_block); /* Receive data */
+ writeb(OLYMPIC_CLEAR_RET_CODE,asb_block+2); /* Necessary ?? */
+ writeb(readb(arb_block+6),asb_block+6); /* Must send the address back to the adapter */
+ writeb(readb(arb_block+7),asb_block+7); /* To let it know we have dealt with the data */
+
+ writel(LISR_ASB_REPLY | LISR_ASB_FREE_REQ,olympic_priv->olympic_mmio+LISR_SUM);
+ olympic_priv->asb_queued = 2 ;
+
+ return ;
+ }
+
+ if (olympic_priv->asb_queued == 2) {
+ switch (readb(asb_block+2)) {
+ case 0x01:
+ printk(KERN_WARNING "%s: Unrecognized command code \n", dev->name);
+ break ;
+ case 0x26:
+ printk(KERN_WARNING "%s: Unrecognized buffer address \n", dev->name);
+ break ;
+ case 0xFF:
+ /* Valid response, everything should be ok again */
+ break ;
+ default:
+ printk(KERN_WARNING "%s: Invalid return code in asb\n",dev->name);
+ break ;
+ }
+ }
+ olympic_priv->asb_queued = 0 ;
+}
+
+static int olympic_change_mtu(struct net_device *dev, int mtu)
+{
+ struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv;
+ u16 max_mtu ;
+
+ if (olympic_priv->olympic_ring_speed == 4)
+ max_mtu = 4500 ;
+ else
+ max_mtu = 18000 ;
+
+ if (mtu > max_mtu)
+ return -EINVAL ;
+ if (mtu < 100)
+ return -EINVAL ;
+
+ dev->mtu = mtu ;
+ olympic_priv->pkt_buf_sz = mtu + TR_HLEN ;
+
+ return 0 ;
+}
+
+static int olympic_proc_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+{
+ struct net_device *dev = (struct net_device *)data ;
+ struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+ u8 __iomem *oat = (olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ;
+ u8 __iomem *opt = (olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ;
+ int size = 0 ;
+ int len=0;
+ off_t begin=0;
+ off_t pos=0;
+
+ size = sprintf(buffer,
+ "IBM Pit/Pit-Phy/Olympic Chipset Token Ring Adapter %s\n",dev->name);
+ size += sprintf(buffer+size, "\n%6s: Adapter Address : Node Address : Functional Addr\n",
+ dev->name);
+
+ size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x\n",
+ dev->name,
+ dev->dev_addr[0],
+ dev->dev_addr[1],
+ dev->dev_addr[2],
+ dev->dev_addr[3],
+ dev->dev_addr[4],
+ dev->dev_addr[5],
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+1),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+2),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+3),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+4),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+5),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+1),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+2),
+ readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+3));
+
+ size += sprintf(buffer+size, "\n%6s: Token Ring Parameters Table:\n", dev->name);
+
+ size += sprintf(buffer+size, "%6s: Physical Addr : Up Node Address : Poll Address : AccPri : Auth Src : Att Code :\n",
+ dev->name) ;
+
+ size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x:%02x:%02x : %04x : %04x : %04x :\n",
+ dev->name,
+ readb(opt+offsetof(struct olympic_parameters_table, phys_addr)),
+ readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+1),
+ readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+2),
+ readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+3),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+1),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+2),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+3),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+4),
+ readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+5),
+ readb(opt+offsetof(struct olympic_parameters_table, poll_addr)),
+ readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+1),
+ readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+2),
+ readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+3),
+ readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+4),
+ readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+5),
+ swab16(readw(opt+offsetof(struct olympic_parameters_table, acc_priority))),
+ swab16(readw(opt+offsetof(struct olympic_parameters_table, auth_source_class))),
+ swab16(readw(opt+offsetof(struct olympic_parameters_table, att_code))));
+
+ size += sprintf(buffer+size, "%6s: Source Address : Bcn T : Maj. V : Lan St : Lcl Rg : Mon Err : Frame Correl : \n",
+ dev->name) ;
+
+ size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x:%02x:%02x : %04x : %04x : %04x : %04x : %04x : %04x : \n",
+ dev->name,
+ readb(opt+offsetof(struct olympic_parameters_table, source_addr)),
+ readb(opt+offsetof(struct olympic_parameters_table, source_addr)+1),
+ readb(opt+offsetof(struct olympic_parameters_table, source_addr)+2),
+ readb(opt+offsetof(struct olympic_parameters_table, source_addr)+3),
+ readb(opt+offsetof(struct olympic_parameters_table, source_addr)+4),
+ readb(opt+offsetof(struct olympic_parameters_table, source_addr)+5),
+ swab16(readw(opt+offsetof(struct olympic_parameters_table, beacon_type))),
+ swab16(readw(opt+offsetof(struct olympic_parameters_table, major_vector))),
+ swab16(readw(opt+offsetof(struct olympic_parameters_table, lan_status))),
+ swab16(readw(opt+offsetof(struct olympic_parameters_table, local_ring))),
+ swab16(readw(opt+offsetof(struct olympic_parameters_table, mon_error))),
+ swab16(readw(opt+offsetof(struct olympic_parameters_table, frame_correl))));
+
+ size += sprintf(buffer+size, "%6s: Beacon Details : Tx : Rx : NAUN Node Address : NAUN Node Phys : \n",
+ dev->name) ;
+
+ size += sprintf(buffer+size, "%6s: : %02x : %02x : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x : \n",
+ dev->name,
+ swab16(readw(opt+offsetof(struct olympic_parameters_table, beacon_transmit))),
+ swab16(readw(opt+offsetof(struct olympic_parameters_table, beacon_receive))),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+1),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+2),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+3),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+4),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+5),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+1),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+2),
+ readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+3));
+
+ len=size;
+ pos=begin+size;
+ if (pos<offset) {
+ len=0;
+ begin=pos;
+ }
+ *start=buffer+(offset-begin); /* Start of wanted data */
+ len-=(offset-begin); /* Start slop */
+ if(len>length)
+ len=length; /* Ending slop */
+ return len;
+}
+
+static void __devexit olympic_remove_one(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev) ;
+ struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+
+ if (olympic_priv->olympic_network_monitor) {
+ char proc_name[20] ;
+ strcpy(proc_name,"net/olympic_") ;
+ strcat(proc_name,dev->name) ;
+ remove_proc_entry(proc_name,NULL);
+ }
+ unregister_netdev(dev) ;
+ iounmap(olympic_priv->olympic_mmio) ;
+ iounmap(olympic_priv->olympic_lap) ;
+ pci_release_regions(pdev) ;
+ pci_set_drvdata(pdev,NULL) ;
+ free_netdev(dev) ;
+}
+
+static struct pci_driver olympic_driver = {
+ .name = "olympic",
+ .id_table = olympic_pci_tbl,
+ .probe = olympic_probe,
+ .remove = __devexit_p(olympic_remove_one),
+};
+
+static int __init olympic_pci_init(void)
+{
+ return pci_module_init (&olympic_driver) ;
+}
+
+static void __exit olympic_pci_cleanup(void)
+{
+ pci_unregister_driver(&olympic_driver) ;
+}
+
+
+module_init(olympic_pci_init) ;
+module_exit(olympic_pci_cleanup) ;
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/tokenring/olympic.h b/drivers/net/tokenring/olympic.h
new file mode 100644
index 00000000000..2fc59c99746
--- /dev/null
+++ b/drivers/net/tokenring/olympic.h
@@ -0,0 +1,322 @@
+/*
+ * olympic.h (c) 1999 Peter De Schrijver All Rights Reserved
+ * 1999,2000 Mike Phillips (mikep@linuxtr.net)
+ *
+ * Linux driver for IBM PCI tokenring cards based on the olympic and the PIT/PHY chipset.
+ *
+ * Base Driver Skeleton:
+ * Written 1993-94 by Donald Becker.
+ *
+ * Copyright 1993 United States Government as represented by the
+ * Director, National Security Agency.
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+#define CID 0x4e
+
+#define BCTL 0x70
+#define BCTL_SOFTRESET (1<<15)
+#define BCTL_MIMREB (1<<6)
+#define BCTL_MODE_INDICATOR (1<<5)
+
+#define GPR 0x4a
+#define GPR_OPTI_BF (1<<6)
+#define GPR_NEPTUNE_BF (1<<4)
+#define GPR_AUTOSENSE (1<<2)
+#define GPR_16MBPS (1<<3)
+
+#define PAG 0x85
+#define LBC 0x8e
+
+#define LISR 0x10
+#define LISR_SUM 0x14
+#define LISR_RWM 0x18
+
+#define LISR_LIE (1<<15)
+#define LISR_SLIM (1<<13)
+#define LISR_SLI (1<<12)
+#define LISR_PCMSRMASK (1<<11)
+#define LISR_PCMSRINT (1<<10)
+#define LISR_WOLMASK (1<<9)
+#define LISR_WOL (1<<8)
+#define LISR_SRB_CMD (1<<5)
+#define LISR_ASB_REPLY (1<<4)
+#define LISR_ASB_FREE_REQ (1<<2)
+#define LISR_ARB_FREE (1<<1)
+#define LISR_TRB_FRAME (1<<0)
+
+#define SISR 0x20
+#define SISR_SUM 0x24
+#define SISR_RWM 0x28
+#define SISR_RR 0x2C
+#define SISR_RESMASK 0x30
+#define SISR_MASK 0x54
+#define SISR_MASK_SUM 0x58
+#define SISR_MASK_RWM 0x5C
+
+#define SISR_TX2_IDLE (1<<31)
+#define SISR_TX2_HALT (1<<29)
+#define SISR_TX2_EOF (1<<28)
+#define SISR_TX1_IDLE (1<<27)
+#define SISR_TX1_HALT (1<<25)
+#define SISR_TX1_EOF (1<<24)
+#define SISR_TIMEOUT (1<<23)
+#define SISR_RX_NOBUF (1<<22)
+#define SISR_RX_STATUS (1<<21)
+#define SISR_RX_HALT (1<<18)
+#define SISR_RX_EOF_EARLY (1<<16)
+#define SISR_MI (1<<15)
+#define SISR_PI (1<<13)
+#define SISR_ERR (1<<9)
+#define SISR_ADAPTER_CHECK (1<<6)
+#define SISR_SRB_REPLY (1<<5)
+#define SISR_ASB_FREE (1<<4)
+#define SISR_ARB_CMD (1<<3)
+#define SISR_TRB_REPLY (1<<2)
+
+#define EISR 0x34
+#define EISR_RWM 0x38
+#define EISR_MASK 0x3c
+#define EISR_MASK_OPTIONS 0x001FFF7F
+
+#define LAPA 0x60
+#define LAPWWO 0x64
+#define LAPWWC 0x68
+#define LAPCTL 0x6C
+#define LAIPD 0x78
+#define LAIPDDINC 0x7C
+
+#define TIMER 0x50
+
+#define CLKCTL 0x74
+#define CLKCTL_PAUSE (1<<15)
+
+#define PM_CON 0x4
+
+#define BMCTL_SUM 0x40
+#define BMCTL_RWM 0x44
+#define BMCTL_TX2_DIS (1<<30)
+#define BMCTL_TX1_DIS (1<<26)
+#define BMCTL_RX_DIS (1<<22)
+
+#define BMASR 0xcc
+
+#define RXDESCQ 0x90
+#define RXDESCQCNT 0x94
+#define RXCDA 0x98
+#define RXENQ 0x9C
+#define RXSTATQ 0xA0
+#define RXSTATQCNT 0xA4
+#define RXCSA 0xA8
+#define RXCLEN 0xAC
+#define RXHLEN 0xAE
+
+#define TXDESCQ_1 0xb0
+#define TXDESCQ_2 0xd0
+#define TXDESCQCNT_1 0xb4
+#define TXDESCQCNT_2 0xd4
+#define TXCDA_1 0xb8
+#define TXCDA_2 0xd8
+#define TXENQ_1 0xbc
+#define TXENQ_2 0xdc
+#define TXSTATQ_1 0xc0
+#define TXSTATQ_2 0xe0
+#define TXSTATQCNT_1 0xc4
+#define TXSTATQCNT_2 0xe4
+#define TXCSA_1 0xc8
+#define TXCSA_2 0xe8
+/* Cardbus */
+#define FERMASK 0xf4
+#define FERMASK_INT_BIT (1<<15)
+
+#define OLYMPIC_IO_SPACE 256
+
+#define SRB_COMMAND_SIZE 50
+
+#define OLYMPIC_MAX_ADAPTERS 8 /* 0x08 __MODULE_STRING can't hand 0xnn */
+
+/* Defines for LAN STATUS CHANGE reports */
+#define LSC_SIG_LOSS 0x8000
+#define LSC_HARD_ERR 0x4000
+#define LSC_SOFT_ERR 0x2000
+#define LSC_TRAN_BCN 0x1000
+#define LSC_LWF 0x0800
+#define LSC_ARW 0x0400
+#define LSC_FPE 0x0200
+#define LSC_RR 0x0100
+#define LSC_CO 0x0080
+#define LSC_SS 0x0040
+#define LSC_RING_REC 0x0020
+#define LSC_SR_CO 0x0010
+#define LSC_FDX_MODE 0x0004
+
+/* Defines for OPEN ADAPTER command */
+
+#define OPEN_ADAPTER_EXT_WRAP (1<<15)
+#define OPEN_ADAPTER_DIS_HARDEE (1<<14)
+#define OPEN_ADAPTER_DIS_SOFTERR (1<<13)
+#define OPEN_ADAPTER_PASS_ADC_MAC (1<<12)
+#define OPEN_ADAPTER_PASS_ATT_MAC (1<<11)
+#define OPEN_ADAPTER_ENABLE_EC (1<<10)
+#define OPEN_ADAPTER_CONTENDER (1<<8)
+#define OPEN_ADAPTER_PASS_BEACON (1<<7)
+#define OPEN_ADAPTER_ENABLE_FDX (1<<6)
+#define OPEN_ADAPTER_ENABLE_RPL (1<<5)
+#define OPEN_ADAPTER_INHIBIT_ETR (1<<4)
+#define OPEN_ADAPTER_INTERNAL_WRAP (1<<3)
+#define OPEN_ADAPTER_USE_OPTS2 (1<<0)
+
+#define OPEN_ADAPTER_2_ENABLE_ONNOW (1<<15)
+
+/* Defines for SRB Commands */
+
+#define SRB_ACCESS_REGISTER 0x1f
+#define SRB_CLOSE_ADAPTER 0x04
+#define SRB_CONFIGURE_BRIDGE 0x0c
+#define SRB_CONFIGURE_WAKEUP_EVENT 0x1a
+#define SRB_MODIFY_BRIDGE_PARMS 0x15
+#define SRB_MODIFY_OPEN_OPTIONS 0x01
+#define SRB_MODIFY_RECEIVE_OPTIONS 0x17
+#define SRB_NO_OPERATION 0x00
+#define SRB_OPEN_ADAPTER 0x03
+#define SRB_READ_LOG 0x08
+#define SRB_READ_SR_COUNTERS 0x16
+#define SRB_RESET_GROUP_ADDRESS 0x02
+#define SRB_SAVE_CONFIGURATION 0x1b
+#define SRB_SET_BRIDGE_PARMS 0x09
+#define SRB_SET_BRIDGE_TARGETS 0x10
+#define SRB_SET_FUNC_ADDRESS 0x07
+#define SRB_SET_GROUP_ADDRESS 0x06
+#define SRB_SET_GROUP_ADDR_OPTIONS 0x11
+#define SRB_UPDATE_WAKEUP_PATTERN 0x19
+
+/* Clear return code */
+
+#define OLYMPIC_CLEAR_RET_CODE 0xfe
+
+/* ARB Commands */
+#define ARB_RECEIVE_DATA 0x81
+#define ARB_LAN_CHANGE_STATUS 0x84
+/* ASB Response commands */
+
+#define ASB_RECEIVE_DATA 0x81
+
+
+/* Olympic defaults for buffers */
+
+#define OLYMPIC_RX_RING_SIZE 16 /* should be a power of 2 */
+#define OLYMPIC_TX_RING_SIZE 8 /* should be a power of 2 */
+
+#define PKT_BUF_SZ 4096 /* Default packet size */
+
+/* Olympic data structures */
+
+/* xxxx These structures are all little endian in hardware. */
+
+struct olympic_tx_desc {
+ u32 buffer;
+ u32 status_length;
+};
+
+struct olympic_tx_status {
+ u32 status;
+};
+
+struct olympic_rx_desc {
+ u32 buffer;
+ u32 res_length;
+};
+
+struct olympic_rx_status {
+ u32 fragmentcnt_framelen;
+ u32 status_buffercnt;
+};
+/* xxxx END These structures are all little endian in hardware. */
+/* xxxx There may be more, but I'm pretty sure about these */
+
+struct mac_receive_buffer {
+ u16 next ;
+ u8 padding ;
+ u8 frame_status ;
+ u16 buffer_length ;
+ u8 frame_data ;
+};
+
+struct olympic_private {
+
+ u16 srb; /* be16 */
+ u16 trb; /* be16 */
+ u16 arb; /* be16 */
+ u16 asb; /* be16 */
+
+ u8 __iomem *olympic_mmio;
+ u8 __iomem *olympic_lap;
+ struct pci_dev *pdev ;
+ char *olympic_card_name ;
+
+ spinlock_t olympic_lock ;
+
+ volatile int srb_queued; /* True if an SRB is still posted */
+ wait_queue_head_t srb_wait;
+
+ volatile int asb_queued; /* True if an ASB is posted */
+
+ volatile int trb_queued; /* True if a TRB is posted */
+ wait_queue_head_t trb_wait ;
+
+ /* These must be on a 4 byte boundary. */
+ struct olympic_rx_desc olympic_rx_ring[OLYMPIC_RX_RING_SIZE];
+ struct olympic_tx_desc olympic_tx_ring[OLYMPIC_TX_RING_SIZE];
+ struct olympic_rx_status olympic_rx_status_ring[OLYMPIC_RX_RING_SIZE];
+ struct olympic_tx_status olympic_tx_status_ring[OLYMPIC_TX_RING_SIZE];
+
+ struct sk_buff *tx_ring_skb[OLYMPIC_TX_RING_SIZE], *rx_ring_skb[OLYMPIC_RX_RING_SIZE];
+ int tx_ring_free, tx_ring_last_status, rx_ring_last_received,rx_status_last_received, free_tx_ring_entries;
+
+ struct net_device_stats olympic_stats ;
+ u16 olympic_lan_status ;
+ u8 olympic_ring_speed ;
+ u16 pkt_buf_sz ;
+ u8 olympic_receive_options, olympic_copy_all_options,olympic_message_level, olympic_network_monitor;
+ u16 olympic_addr_table_addr, olympic_parms_addr ;
+ u8 olympic_laa[6] ;
+ u32 rx_ring_dma_addr;
+ u32 rx_status_ring_dma_addr;
+ u32 tx_ring_dma_addr;
+ u32 tx_status_ring_dma_addr;
+};
+
+struct olympic_adapter_addr_table {
+
+ u8 node_addr[6] ;
+ u8 reserved[4] ;
+ u8 func_addr[4] ;
+} ;
+
+struct olympic_parameters_table {
+
+ u8 phys_addr[4] ;
+ u8 up_node_addr[6] ;
+ u8 up_phys_addr[4] ;
+ u8 poll_addr[6] ;
+ u16 reserved ;
+ u16 acc_priority ;
+ u16 auth_source_class ;
+ u16 att_code ;
+ u8 source_addr[6] ;
+ u16 beacon_type ;
+ u16 major_vector ;
+ u16 lan_status ;
+ u16 soft_error_time ;
+ u16 reserved1 ;
+ u16 local_ring ;
+ u16 mon_error ;
+ u16 beacon_transmit ;
+ u16 beacon_receive ;
+ u16 frame_correl ;
+ u8 beacon_naun[6] ;
+ u32 reserved2 ;
+ u8 beacon_phys[4] ;
+};
diff --git a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c
new file mode 100644
index 00000000000..675b063508e
--- /dev/null
+++ b/drivers/net/tokenring/proteon.c
@@ -0,0 +1,432 @@
+/*
+ * proteon.c: A network driver for Proteon ISA token ring cards.
+ *
+ * Based on tmspci written 1999 by Adam Fritzler
+ *
+ * Written 2003 by Jochen Friedrich
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * This driver module supports the following cards:
+ * - Proteon 1392, 1392+
+ *
+ * Maintainer(s):
+ * AF Adam Fritzler mid@auk.cx
+ * JF Jochen Friedrich jochen@scram.de
+ *
+ * Modification History:
+ * 02-Jan-03 JF Created
+ *
+ */
+static const char version[] = "proteon.c: v1.00 02/01/2003 by Jochen Friedrich\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/trdevice.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pci.h>
+#include <asm/dma.h>
+
+#include "tms380tr.h"
+
+#define PROTEON_IO_EXTENT 32
+
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int portlist[] __initdata = {
+ 0x0A20, 0x0E20, 0x1A20, 0x1E20, 0x2A20, 0x2E20, 0x3A20, 0x3E20,// Prot.
+ 0x4A20, 0x4E20, 0x5A20, 0x5E20, 0x6A20, 0x6E20, 0x7A20, 0x7E20,// Prot.
+ 0x8A20, 0x8E20, 0x9A20, 0x9E20, 0xAA20, 0xAE20, 0xBA20, 0xBE20,// Prot.
+ 0xCA20, 0xCE20, 0xDA20, 0xDE20, 0xEA20, 0xEE20, 0xFA20, 0xFE20,// Prot.
+ 0
+};
+
+/* A zero-terminated list of IRQs to be probed. */
+static unsigned short irqlist[] = {
+ 7, 6, 5, 4, 3, 12, 11, 10, 9,
+ 0
+};
+
+/* A zero-terminated list of DMAs to be probed. */
+static int dmalist[] __initdata = {
+ 5, 6, 7,
+ 0
+};
+
+static char cardname[] = "Proteon 1392\0";
+
+struct net_device *proteon_probe(int unit);
+static int proteon_open(struct net_device *dev);
+static void proteon_read_eeprom(struct net_device *dev);
+static unsigned short proteon_setnselout_pins(struct net_device *dev);
+
+static unsigned short proteon_sifreadb(struct net_device *dev, unsigned short reg)
+{
+ return inb(dev->base_addr + reg);
+}
+
+static unsigned short proteon_sifreadw(struct net_device *dev, unsigned short reg)
+{
+ return inw(dev->base_addr + reg);
+}
+
+static void proteon_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg)
+{
+ outb(val, dev->base_addr + reg);
+}
+
+static void proteon_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg)
+{
+ outw(val, dev->base_addr + reg);
+}
+
+static int __init proteon_probe1(struct net_device *dev, int ioaddr)
+{
+ unsigned char chk1, chk2;
+ int i;
+
+ if (!request_region(ioaddr, PROTEON_IO_EXTENT, cardname))
+ return -ENODEV;
+
+
+ chk1 = inb(ioaddr + 0x1f); /* Get Proteon ID reg 1 */
+ if (chk1 != 0x1f)
+ goto nodev;
+
+ chk1 = inb(ioaddr + 0x1e) & 0x07; /* Get Proteon ID reg 0 */
+ for (i=0; i<16; i++) {
+ chk2 = inb(ioaddr + 0x1e) & 0x07;
+ if (((chk1 + 1) & 0x07) != chk2)
+ goto nodev;
+ chk1 = chk2;
+ }
+
+ dev->base_addr = ioaddr;
+ return (0);
+nodev:
+ release_region(ioaddr, PROTEON_IO_EXTENT);
+ return -ENODEV;
+}
+
+static int __init setup_card(struct net_device *dev)
+{
+ struct net_local *tp;
+ static int versionprinted;
+ const unsigned *port;
+ int j,err = 0;
+
+ if (!dev)
+ return -ENOMEM;
+
+ SET_MODULE_OWNER(dev);
+ if (dev->base_addr) /* probe specific location */
+ err = proteon_probe1(dev, dev->base_addr);
+ else {
+ for (port = portlist; *port; port++) {
+ err = proteon_probe1(dev, *port);
+ if (!err)
+ break;
+ }
+ }
+ if (err)
+ goto out4;
+
+ /* At this point we have found a valid card. */
+
+ if (versionprinted++ == 0)
+ printk(KERN_DEBUG "%s", version);
+
+ err = -EIO;
+ if (tmsdev_init(dev, ISA_MAX_ADDRESS, NULL))
+ goto out4;
+
+ dev->base_addr &= ~3;
+
+ proteon_read_eeprom(dev);
+
+ printk(KERN_DEBUG "%s: Ring Station Address: ", dev->name);
+ printk("%2.2x", dev->dev_addr[0]);
+ for (j = 1; j < 6; j++)
+ printk(":%2.2x", dev->dev_addr[j]);
+ printk("\n");
+
+ tp = netdev_priv(dev);
+ tp->setnselout = proteon_setnselout_pins;
+
+ tp->sifreadb = proteon_sifreadb;
+ tp->sifreadw = proteon_sifreadw;
+ tp->sifwriteb = proteon_sifwriteb;
+ tp->sifwritew = proteon_sifwritew;
+
+ memcpy(tp->ProductID, cardname, PROD_ID_SIZE + 1);
+
+ tp->tmspriv = NULL;
+
+ dev->open = proteon_open;
+ dev->stop = tms380tr_close;
+
+ if (dev->irq == 0)
+ {
+ for(j = 0; irqlist[j] != 0; j++)
+ {
+ dev->irq = irqlist[j];
+ if (!request_irq(dev->irq, tms380tr_interrupt, 0,
+ cardname, dev))
+ break;
+ }
+
+ if(irqlist[j] == 0)
+ {
+ printk(KERN_INFO "%s: AutoSelect no IRQ available\n", dev->name);
+ goto out3;
+ }
+ }
+ else
+ {
+ for(j = 0; irqlist[j] != 0; j++)
+ if (irqlist[j] == dev->irq)
+ break;
+ if (irqlist[j] == 0)
+ {
+ printk(KERN_INFO "%s: Illegal IRQ %d specified\n",
+ dev->name, dev->irq);
+ goto out3;
+ }
+ if (request_irq(dev->irq, tms380tr_interrupt, 0,
+ cardname, dev))
+ {
+ printk(KERN_INFO "%s: Selected IRQ %d not available\n",
+ dev->name, dev->irq);
+ goto out3;
+ }
+ }
+
+ if (dev->dma == 0)
+ {
+ for(j = 0; dmalist[j] != 0; j++)
+ {
+ dev->dma = dmalist[j];
+ if (!request_dma(dev->dma, cardname))
+ break;
+ }
+
+ if(dmalist[j] == 0)
+ {
+ printk(KERN_INFO "%s: AutoSelect no DMA available\n", dev->name);
+ goto out2;
+ }
+ }
+ else
+ {
+ for(j = 0; dmalist[j] != 0; j++)
+ if (dmalist[j] == dev->dma)
+ break;
+ if (dmalist[j] == 0)
+ {
+ printk(KERN_INFO "%s: Illegal DMA %d specified\n",
+ dev->name, dev->dma);
+ goto out2;
+ }
+ if (request_dma(dev->dma, cardname))
+ {
+ printk(KERN_INFO "%s: Selected DMA %d not available\n",
+ dev->name, dev->dma);
+ goto out2;
+ }
+ }
+
+ printk(KERN_DEBUG "%s: IO: %#4lx IRQ: %d DMA: %d\n",
+ dev->name, dev->base_addr, dev->irq, dev->dma);
+
+ err = register_netdev(dev);
+ if (err)
+ goto out;
+
+ return 0;
+out:
+ free_dma(dev->dma);
+out2:
+ free_irq(dev->irq, dev);
+out3:
+ tmsdev_term(dev);
+out4:
+ release_region(dev->base_addr, PROTEON_IO_EXTENT);
+ return err;
+}
+
+struct net_device * __init proteon_probe(int unit)
+{
+ struct net_device *dev = alloc_trdev(sizeof(struct net_local));
+ int err = 0;
+
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
+
+ if (unit >= 0) {
+ sprintf(dev->name, "tr%d", unit);
+ netdev_boot_setup_check(dev);
+ }
+
+ err = setup_card(dev);
+ if (err)
+ goto out;
+
+ return dev;
+
+out:
+ free_netdev(dev);
+ return ERR_PTR(err);
+}
+
+/*
+ * Reads MAC address from adapter RAM, which should've read it from
+ * the onboard ROM.
+ *
+ * Calling this on a board that does not support it can be a very
+ * dangerous thing. The Madge board, for instance, will lock your
+ * machine hard when this is called. Luckily, its supported in a
+ * separate driver. --ASF
+ */
+static void proteon_read_eeprom(struct net_device *dev)
+{
+ int i;
+
+ /* Address: 0000:0000 */
+ proteon_sifwritew(dev, 0, SIFADX);
+ proteon_sifwritew(dev, 0, SIFADR);
+
+ /* Read six byte MAC address data */
+ dev->addr_len = 6;
+ for(i = 0; i < 6; i++)
+ dev->dev_addr[i] = proteon_sifreadw(dev, SIFINC) >> 8;
+}
+
+unsigned short proteon_setnselout_pins(struct net_device *dev)
+{
+ return 0;
+}
+
+static int proteon_open(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned short val = 0;
+ int i;
+
+ /* Proteon reset sequence */
+ outb(0, dev->base_addr + 0x11);
+ mdelay(20);
+ outb(0x04, dev->base_addr + 0x11);
+ mdelay(20);
+ outb(0, dev->base_addr + 0x11);
+ mdelay(100);
+
+ /* set control/status reg */
+ val = inb(dev->base_addr + 0x11);
+ val |= 0x78;
+ val &= 0xf9;
+ if(tp->DataRate == SPEED_4)
+ val |= 0x20;
+ else
+ val &= ~0x20;
+
+ outb(val, dev->base_addr + 0x11);
+ outb(0xff, dev->base_addr + 0x12);
+ for(i = 0; irqlist[i] != 0; i++)
+ {
+ if(irqlist[i] == dev->irq)
+ break;
+ }
+ val = i;
+ i = (7 - dev->dma) << 4;
+ val |= i;
+ outb(val, dev->base_addr + 0x13);
+
+ return tms380tr_open(dev);
+}
+
+#ifdef MODULE
+
+#define ISATR_MAX_ADAPTERS 3
+
+static int io[ISATR_MAX_ADAPTERS];
+static int irq[ISATR_MAX_ADAPTERS];
+static int dma[ISATR_MAX_ADAPTERS];
+
+MODULE_LICENSE("GPL");
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(dma, int, NULL, 0);
+
+static struct net_device *proteon_dev[ISATR_MAX_ADAPTERS];
+
+int init_module(void)
+{
+ struct net_device *dev;
+ int i, num = 0, err = 0;
+
+ for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {
+ dev = alloc_trdev(sizeof(struct net_local));
+ if (!dev)
+ continue;
+
+ dev->base_addr = io[i];
+ dev->irq = irq[i];
+ dev->dma = dma[i];
+ err = setup_card(dev);
+ if (!err) {
+ proteon_dev[i] = dev;
+ ++num;
+ } else {
+ free_netdev(dev);
+ }
+ }
+
+ printk(KERN_NOTICE "proteon.c: %d cards found.\n", num);
+ /* Probe for cards. */
+ if (num == 0) {
+ printk(KERN_NOTICE "proteon.c: No cards found.\n");
+ return (-ENODEV);
+ }
+ return (0);
+}
+
+void cleanup_module(void)
+{
+ int i;
+
+ for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {
+ struct net_device *dev = proteon_dev[i];
+
+ if (!dev)
+ continue;
+
+ unregister_netdev(dev);
+ release_region(dev->base_addr, PROTEON_IO_EXTENT);
+ free_irq(dev->irq, dev);
+ free_dma(dev->dma);
+ tmsdev_term(dev);
+ free_netdev(dev);
+ }
+}
+#endif /* MODULE */
+
+
+/*
+ * Local variables:
+ * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c proteon.c"
+ * alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c proteon.c"
+ * c-set-style "K&R"
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/drivers/net/tokenring/skisa.c b/drivers/net/tokenring/skisa.c
new file mode 100644
index 00000000000..3fab54a2646
--- /dev/null
+++ b/drivers/net/tokenring/skisa.c
@@ -0,0 +1,442 @@
+/*
+ * skisa.c: A network driver for SK-NET TMS380-based ISA token ring cards.
+ *
+ * Based on tmspci written 1999 by Adam Fritzler
+ *
+ * Written 2000 by Jochen Friedrich
+ * Dedicated to my girlfriend Steffi Bopp
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * This driver module supports the following cards:
+ * - SysKonnect TR4/16(+) ISA (SK-4190)
+ *
+ * Maintainer(s):
+ * AF Adam Fritzler mid@auk.cx
+ * JF Jochen Friedrich jochen@scram.de
+ *
+ * Modification History:
+ * 14-Jan-01 JF Created
+ * 28-Oct-02 JF Fixed probe of card for static compilation.
+ * Fixed module init to not make hotplug go wild.
+ * 09-Nov-02 JF Fixed early bail out on out of memory
+ * situations if multiple cards are found.
+ * Cleaned up some unnecessary console SPAM.
+ * 09-Dec-02 JF Fixed module reference counting.
+ * 02-Jan-03 JF Renamed to skisa.c
+ *
+ */
+static const char version[] = "skisa.c: v1.03 09/12/2002 by Jochen Friedrich\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/trdevice.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pci.h>
+#include <asm/dma.h>
+
+#include "tms380tr.h"
+
+#define SK_ISA_IO_EXTENT 32
+
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int portlist[] __initdata = {
+ 0x0A20, 0x1A20, 0x0B20, 0x1B20, 0x0980, 0x1980, 0x0900, 0x1900,// SK
+ 0
+};
+
+/* A zero-terminated list of IRQs to be probed.
+ * Used again after initial probe for sktr_chipset_init, called from sktr_open.
+ */
+static const unsigned short irqlist[] = {
+ 3, 5, 9, 10, 11, 12, 15,
+ 0
+};
+
+/* A zero-terminated list of DMAs to be probed. */
+static int dmalist[] __initdata = {
+ 5, 6, 7,
+ 0
+};
+
+static char isa_cardname[] = "SK NET TR 4/16 ISA\0";
+
+struct net_device *sk_isa_probe(int unit);
+static int sk_isa_open(struct net_device *dev);
+static void sk_isa_read_eeprom(struct net_device *dev);
+static unsigned short sk_isa_setnselout_pins(struct net_device *dev);
+
+static unsigned short sk_isa_sifreadb(struct net_device *dev, unsigned short reg)
+{
+ return inb(dev->base_addr + reg);
+}
+
+static unsigned short sk_isa_sifreadw(struct net_device *dev, unsigned short reg)
+{
+ return inw(dev->base_addr + reg);
+}
+
+static void sk_isa_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg)
+{
+ outb(val, dev->base_addr + reg);
+}
+
+static void sk_isa_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg)
+{
+ outw(val, dev->base_addr + reg);
+}
+
+
+static int __init sk_isa_probe1(struct net_device *dev, int ioaddr)
+{
+ unsigned char old, chk1, chk2;
+
+ if (!request_region(ioaddr, SK_ISA_IO_EXTENT, isa_cardname))
+ return -ENODEV;
+
+ old = inb(ioaddr + SIFADR); /* Get the old SIFADR value */
+
+ chk1 = 0; /* Begin with check value 0 */
+ do {
+ /* Write new SIFADR value */
+ outb(chk1, ioaddr + SIFADR);
+
+ /* Read, invert and write */
+ chk2 = inb(ioaddr + SIFADD);
+ chk2 ^= 0x0FE;
+ outb(chk2, ioaddr + SIFADR);
+
+ /* Read, invert and compare */
+ chk2 = inb(ioaddr + SIFADD);
+ chk2 ^= 0x0FE;
+
+ if(chk1 != chk2) {
+ release_region(ioaddr, SK_ISA_IO_EXTENT);
+ return -ENODEV;
+ }
+
+ chk1 -= 2;
+ } while(chk1 != 0); /* Repeat 128 times (all byte values) */
+
+ /* Restore the SIFADR value */
+ outb(old, ioaddr + SIFADR);
+
+ dev->base_addr = ioaddr;
+ return 0;
+}
+
+static int __init setup_card(struct net_device *dev)
+{
+ struct net_local *tp;
+ static int versionprinted;
+ const unsigned *port;
+ int j, err = 0;
+
+ if (!dev)
+ return -ENOMEM;
+
+ SET_MODULE_OWNER(dev);
+ if (dev->base_addr) /* probe specific location */
+ err = sk_isa_probe1(dev, dev->base_addr);
+ else {
+ for (port = portlist; *port; port++) {
+ err = sk_isa_probe1(dev, *port);
+ if (!err)
+ break;
+ }
+ }
+ if (err)
+ goto out4;
+
+ /* At this point we have found a valid card. */
+
+ if (versionprinted++ == 0)
+ printk(KERN_DEBUG "%s", version);
+
+ err = -EIO;
+ if (tmsdev_init(dev, ISA_MAX_ADDRESS, NULL))
+ goto out4;
+
+ dev->base_addr &= ~3;
+
+ sk_isa_read_eeprom(dev);
+
+ printk(KERN_DEBUG "%s: Ring Station Address: ", dev->name);
+ printk("%2.2x", dev->dev_addr[0]);
+ for (j = 1; j < 6; j++)
+ printk(":%2.2x", dev->dev_addr[j]);
+ printk("\n");
+
+ tp = netdev_priv(dev);
+ tp->setnselout = sk_isa_setnselout_pins;
+
+ tp->sifreadb = sk_isa_sifreadb;
+ tp->sifreadw = sk_isa_sifreadw;
+ tp->sifwriteb = sk_isa_sifwriteb;
+ tp->sifwritew = sk_isa_sifwritew;
+
+ memcpy(tp->ProductID, isa_cardname, PROD_ID_SIZE + 1);
+
+ tp->tmspriv = NULL;
+
+ dev->open = sk_isa_open;
+ dev->stop = tms380tr_close;
+
+ if (dev->irq == 0)
+ {
+ for(j = 0; irqlist[j] != 0; j++)
+ {
+ dev->irq = irqlist[j];
+ if (!request_irq(dev->irq, tms380tr_interrupt, 0,
+ isa_cardname, dev))
+ break;
+ }
+
+ if(irqlist[j] == 0)
+ {
+ printk(KERN_INFO "%s: AutoSelect no IRQ available\n", dev->name);
+ goto out3;
+ }
+ }
+ else
+ {
+ for(j = 0; irqlist[j] != 0; j++)
+ if (irqlist[j] == dev->irq)
+ break;
+ if (irqlist[j] == 0)
+ {
+ printk(KERN_INFO "%s: Illegal IRQ %d specified\n",
+ dev->name, dev->irq);
+ goto out3;
+ }
+ if (request_irq(dev->irq, tms380tr_interrupt, 0,
+ isa_cardname, dev))
+ {
+ printk(KERN_INFO "%s: Selected IRQ %d not available\n",
+ dev->name, dev->irq);
+ goto out3;
+ }
+ }
+
+ if (dev->dma == 0)
+ {
+ for(j = 0; dmalist[j] != 0; j++)
+ {
+ dev->dma = dmalist[j];
+ if (!request_dma(dev->dma, isa_cardname))
+ break;
+ }
+
+ if(dmalist[j] == 0)
+ {
+ printk(KERN_INFO "%s: AutoSelect no DMA available\n", dev->name);
+ goto out2;
+ }
+ }
+ else
+ {
+ for(j = 0; dmalist[j] != 0; j++)
+ if (dmalist[j] == dev->dma)
+ break;
+ if (dmalist[j] == 0)
+ {
+ printk(KERN_INFO "%s: Illegal DMA %d specified\n",
+ dev->name, dev->dma);
+ goto out2;
+ }
+ if (request_dma(dev->dma, isa_cardname))
+ {
+ printk(KERN_INFO "%s: Selected DMA %d not available\n",
+ dev->name, dev->dma);
+ goto out2;
+ }
+ }
+
+ printk(KERN_DEBUG "%s: IO: %#4lx IRQ: %d DMA: %d\n",
+ dev->name, dev->base_addr, dev->irq, dev->dma);
+
+ err = register_netdev(dev);
+ if (err)
+ goto out;
+
+ return 0;
+out:
+ free_dma(dev->dma);
+out2:
+ free_irq(dev->irq, dev);
+out3:
+ tmsdev_term(dev);
+out4:
+ release_region(dev->base_addr, SK_ISA_IO_EXTENT);
+ return err;
+}
+
+struct net_device * __init sk_isa_probe(int unit)
+{
+ struct net_device *dev = alloc_trdev(sizeof(struct net_local));
+ int err = 0;
+
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
+
+ if (unit >= 0) {
+ sprintf(dev->name, "tr%d", unit);
+ netdev_boot_setup_check(dev);
+ }
+
+ err = setup_card(dev);
+ if (err)
+ goto out;
+
+ return dev;
+out:
+ free_netdev(dev);
+ return ERR_PTR(err);
+}
+
+/*
+ * Reads MAC address from adapter RAM, which should've read it from
+ * the onboard ROM.
+ *
+ * Calling this on a board that does not support it can be a very
+ * dangerous thing. The Madge board, for instance, will lock your
+ * machine hard when this is called. Luckily, its supported in a
+ * separate driver. --ASF
+ */
+static void sk_isa_read_eeprom(struct net_device *dev)
+{
+ int i;
+
+ /* Address: 0000:0000 */
+ sk_isa_sifwritew(dev, 0, SIFADX);
+ sk_isa_sifwritew(dev, 0, SIFADR);
+
+ /* Read six byte MAC address data */
+ dev->addr_len = 6;
+ for(i = 0; i < 6; i++)
+ dev->dev_addr[i] = sk_isa_sifreadw(dev, SIFINC) >> 8;
+}
+
+unsigned short sk_isa_setnselout_pins(struct net_device *dev)
+{
+ return 0;
+}
+
+static int sk_isa_open(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned short val = 0;
+ unsigned short oldval;
+ int i;
+
+ val = 0;
+ for(i = 0; irqlist[i] != 0; i++)
+ {
+ if(irqlist[i] == dev->irq)
+ break;
+ }
+
+ val |= CYCLE_TIME << 2;
+ val |= i << 4;
+ i = dev->dma - 5;
+ val |= i;
+ if(tp->DataRate == SPEED_4)
+ val |= LINE_SPEED_BIT;
+ else
+ val &= ~LINE_SPEED_BIT;
+ oldval = sk_isa_sifreadb(dev, POSREG);
+ /* Leave cycle bits alone */
+ oldval |= 0xf3;
+ val &= oldval;
+ sk_isa_sifwriteb(dev, val, POSREG);
+
+ return tms380tr_open(dev);
+}
+
+#ifdef MODULE
+
+#define ISATR_MAX_ADAPTERS 3
+
+static int io[ISATR_MAX_ADAPTERS];
+static int irq[ISATR_MAX_ADAPTERS];
+static int dma[ISATR_MAX_ADAPTERS];
+
+MODULE_LICENSE("GPL");
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(dma, int, NULL, 0);
+
+static struct net_device *sk_isa_dev[ISATR_MAX_ADAPTERS];
+
+int init_module(void)
+{
+ struct net_device *dev;
+ int i, num = 0, err = 0;
+
+ for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {
+ dev = alloc_trdev(sizeof(struct net_local));
+ if (!dev)
+ continue;
+
+ dev->base_addr = io[i];
+ dev->irq = irq[i];
+ dev->dma = dma[i];
+ err = setup_card(dev);
+
+ if (!err) {
+ sk_isa_dev[i] = dev;
+ ++num;
+ } else {
+ free_netdev(dev);
+ }
+ }
+
+ printk(KERN_NOTICE "skisa.c: %d cards found.\n", num);
+ /* Probe for cards. */
+ if (num == 0) {
+ printk(KERN_NOTICE "skisa.c: No cards found.\n");
+ return (-ENODEV);
+ }
+ return (0);
+}
+
+void cleanup_module(void)
+{
+ int i;
+
+ for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) {
+ struct net_device *dev = sk_isa_dev[i];
+
+ if (!dev)
+ continue;
+
+ unregister_netdev(dev);
+ release_region(dev->base_addr, SK_ISA_IO_EXTENT);
+ free_irq(dev->irq, dev);
+ free_dma(dev->dma);
+ tmsdev_term(dev);
+ free_netdev(dev);
+ }
+}
+#endif /* MODULE */
+
+
+/*
+ * Local variables:
+ * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c skisa.c"
+ * alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c skisa.c"
+ * c-set-style "K&R"
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
new file mode 100644
index 00000000000..5c8aeacb831
--- /dev/null
+++ b/drivers/net/tokenring/smctr.c
@@ -0,0 +1,5742 @@
+/*
+ * smctr.c: A network driver for the SMC Token Ring Adapters.
+ *
+ * Written by Jay Schulist <jschlst@samba.org>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * This device driver works with the following SMC adapters:
+ * - SMC TokenCard Elite (8115T, chips 825/584)
+ * - SMC TokenCard Elite/A MCA (8115T/A, chips 825/594)
+ *
+ * Source(s):
+ * - SMC TokenCard SDK.
+ *
+ * Maintainer(s):
+ * JS Jay Schulist <jschlst@samba.org>
+ *
+ * Changes:
+ * 07102000 JS Fixed a timing problem in smctr_wait_cmd();
+ * Also added a bit more discriptive error msgs.
+ * 07122000 JS Fixed problem with detecting a card with
+ * module io/irq/mem specified.
+ *
+ * To do:
+ * 1. Multicast support.
+ *
+ * Initial 2.5 cleanup Alan Cox <alan@redhat.com> 2002/10/28
+ */
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/time.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/mca-legacy.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/trdevice.h>
+#include <linux/bitops.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+
+#if BITS_PER_LONG == 64
+#error FIXME: driver does not support 64-bit platforms
+#endif
+
+#include "smctr.h" /* Our Stuff */
+#include "smctr_firmware.h" /* SMC adapter firmware */
+
+static char version[] __initdata = KERN_INFO "smctr.c: v1.4 7/12/00 by jschlst@samba.org\n";
+static const char cardname[] = "smctr";
+
+
+#define SMCTR_IO_EXTENT 20
+
+#ifdef CONFIG_MCA_LEGACY
+static unsigned int smctr_posid = 0x6ec6;
+#endif
+
+static int ringspeed;
+
+/* SMC Name of the Adapter. */
+static char smctr_name[] = "SMC TokenCard";
+char *smctr_model = "Unknown";
+
+/* Use 0 for production, 1 for verification, 2 for debug, and
+ * 3 for very verbose debug.
+ */
+#ifndef SMCTR_DEBUG
+#define SMCTR_DEBUG 1
+#endif
+static unsigned int smctr_debug = SMCTR_DEBUG;
+
+/* smctr.c prototypes and functions are arranged alphabeticly
+ * for clearity, maintainability and pure old fashion fun.
+ */
+/* A */
+static int smctr_alloc_shared_memory(struct net_device *dev);
+
+/* B */
+static int smctr_bypass_state(struct net_device *dev);
+
+/* C */
+static int smctr_checksum_firmware(struct net_device *dev);
+static int __init smctr_chk_isa(struct net_device *dev);
+static int smctr_chg_rx_mask(struct net_device *dev);
+static int smctr_clear_int(struct net_device *dev);
+static int smctr_clear_trc_reset(int ioaddr);
+static int smctr_close(struct net_device *dev);
+
+/* D */
+static int smctr_decode_firmware(struct net_device *dev);
+static int smctr_disable_16bit(struct net_device *dev);
+static int smctr_disable_adapter_ctrl_store(struct net_device *dev);
+static int smctr_disable_bic_int(struct net_device *dev);
+
+/* E */
+static int smctr_enable_16bit(struct net_device *dev);
+static int smctr_enable_adapter_ctrl_store(struct net_device *dev);
+static int smctr_enable_adapter_ram(struct net_device *dev);
+static int smctr_enable_bic_int(struct net_device *dev);
+
+/* G */
+static int __init smctr_get_boardid(struct net_device *dev, int mca);
+static int smctr_get_group_address(struct net_device *dev);
+static int smctr_get_functional_address(struct net_device *dev);
+static unsigned int smctr_get_num_rx_bdbs(struct net_device *dev);
+static int smctr_get_physical_drop_number(struct net_device *dev);
+static __u8 *smctr_get_rx_pointer(struct net_device *dev, short queue);
+static int smctr_get_station_id(struct net_device *dev);
+static struct net_device_stats *smctr_get_stats(struct net_device *dev);
+static FCBlock *smctr_get_tx_fcb(struct net_device *dev, __u16 queue,
+ __u16 bytes_count);
+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);
+static int smctr_init_card_real(struct net_device *dev);
+static int smctr_init_rx_bdbs(struct net_device *dev);
+static int smctr_init_rx_fcbs(struct net_device *dev);
+static int smctr_init_shared_memory(struct net_device *dev);
+static int smctr_init_tx_bdbs(struct net_device *dev);
+static int smctr_init_tx_fcbs(struct net_device *dev);
+static int smctr_internal_self_test(struct net_device *dev);
+static irqreturn_t smctr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static int smctr_issue_enable_int_cmd(struct net_device *dev,
+ __u16 interrupt_enable_mask);
+static int smctr_issue_int_ack(struct net_device *dev, __u16 iack_code,
+ __u16 ibits);
+static int smctr_issue_init_timers_cmd(struct net_device *dev);
+static int smctr_issue_init_txrx_cmd(struct net_device *dev);
+static int smctr_issue_insert_cmd(struct net_device *dev);
+static int smctr_issue_read_ring_status_cmd(struct net_device *dev);
+static int smctr_issue_read_word_cmd(struct net_device *dev, __u16 aword_cnt);
+static int smctr_issue_remove_cmd(struct net_device *dev);
+static int smctr_issue_resume_acb_cmd(struct net_device *dev);
+static int smctr_issue_resume_rx_bdb_cmd(struct net_device *dev, __u16 queue);
+static int smctr_issue_resume_rx_fcb_cmd(struct net_device *dev, __u16 queue);
+static int smctr_issue_resume_tx_fcb_cmd(struct net_device *dev, __u16 queue);
+static int smctr_issue_test_internal_rom_cmd(struct net_device *dev);
+static int smctr_issue_test_hic_cmd(struct net_device *dev);
+static int smctr_issue_test_mac_reg_cmd(struct net_device *dev);
+static int smctr_issue_trc_loopback_cmd(struct net_device *dev);
+static int smctr_issue_tri_loopback_cmd(struct net_device *dev);
+static int smctr_issue_write_byte_cmd(struct net_device *dev,
+ short aword_cnt, void *byte);
+static int smctr_issue_write_word_cmd(struct net_device *dev,
+ short aword_cnt, void *word);
+
+/* J */
+static int smctr_join_complete_state(struct net_device *dev);
+
+/* L */
+static int smctr_link_tx_fcbs_to_bdbs(struct net_device *dev);
+static int smctr_load_firmware(struct net_device *dev);
+static int smctr_load_node_addr(struct net_device *dev);
+static int smctr_lobe_media_test(struct net_device *dev);
+static int smctr_lobe_media_test_cmd(struct net_device *dev);
+static int smctr_lobe_media_test_state(struct net_device *dev);
+
+/* M */
+static int smctr_make_8025_hdr(struct net_device *dev,
+ MAC_HEADER *rmf, MAC_HEADER *tmf, __u16 ac_fc);
+static int smctr_make_access_pri(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv);
+static int smctr_make_addr_mod(struct net_device *dev, MAC_SUB_VECTOR *tsv);
+static int smctr_make_auth_funct_class(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv);
+static int smctr_make_corr(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv, __u16 correlator);
+static int smctr_make_funct_addr(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv);
+static int smctr_make_group_addr(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv);
+static int smctr_make_phy_drop_num(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv);
+static int smctr_make_product_id(struct net_device *dev, MAC_SUB_VECTOR *tsv);
+static int smctr_make_station_id(struct net_device *dev, MAC_SUB_VECTOR *tsv);
+static int smctr_make_ring_station_status(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv);
+static int smctr_make_ring_station_version(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv);
+static int smctr_make_tx_status_code(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv, __u16 tx_fstatus);
+static int smctr_make_upstream_neighbor_addr(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv);
+static int smctr_make_wrap_data(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv);
+
+/* O */
+static int smctr_open(struct net_device *dev);
+static int smctr_open_tr(struct net_device *dev);
+
+/* P */
+struct net_device *smctr_probe(int unit);
+static int __init smctr_probe1(struct net_device *dev, int ioaddr);
+static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
+ struct net_device *dev, __u16 rx_status);
+
+/* R */
+static int smctr_ram_memory_test(struct net_device *dev);
+static int smctr_rcv_chg_param(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 *correlator);
+static int smctr_rcv_init(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 *correlator);
+static int smctr_rcv_tx_forward(struct net_device *dev, MAC_HEADER *rmf);
+static int smctr_rcv_rq_addr_state_attch(struct net_device *dev,
+ MAC_HEADER *rmf, __u16 *correlator);
+static int smctr_rcv_unknown(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 *correlator);
+static int smctr_reset_adapter(struct net_device *dev);
+static int smctr_restart_tx_chain(struct net_device *dev, short queue);
+static int smctr_ring_status_chg(struct net_device *dev);
+static int smctr_rx_frame(struct net_device *dev);
+
+/* S */
+static int smctr_send_dat(struct net_device *dev);
+static int smctr_send_packet(struct sk_buff *skb, struct net_device *dev);
+static int smctr_send_lobe_media_test(struct net_device *dev);
+static int smctr_send_rpt_addr(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 correlator);
+static int smctr_send_rpt_attch(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 correlator);
+static int smctr_send_rpt_state(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 correlator);
+static int smctr_send_rpt_tx_forward(struct net_device *dev,
+ MAC_HEADER *rmf, __u16 tx_fstatus);
+static int smctr_send_rsp(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 rcode, __u16 correlator);
+static int smctr_send_rq_init(struct net_device *dev);
+static int smctr_send_tx_forward(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 *tx_fstatus);
+static int smctr_set_auth_access_pri(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv);
+static int smctr_set_auth_funct_class(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv);
+static int smctr_set_corr(struct net_device *dev, MAC_SUB_VECTOR *rsv,
+ __u16 *correlator);
+static int smctr_set_error_timer_value(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv);
+static int smctr_set_frame_forward(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv, __u8 dc_sc);
+static int smctr_set_local_ring_num(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv);
+static unsigned short smctr_set_ctrl_attention(struct net_device *dev);
+static void smctr_set_multicast_list(struct net_device *dev);
+static int smctr_set_page(struct net_device *dev, __u8 *buf);
+static int smctr_set_phy_drop(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv);
+static int smctr_set_ring_speed(struct net_device *dev);
+static int smctr_set_rx_look_ahead(struct net_device *dev);
+static int smctr_set_trc_reset(int ioaddr);
+static int smctr_setup_single_cmd(struct net_device *dev,
+ __u16 command, __u16 subcommand);
+static int smctr_setup_single_cmd_w_data(struct net_device *dev,
+ __u16 command, __u16 subcommand);
+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);
+static unsigned short smctr_tx_move_frame(struct net_device *dev,
+ struct sk_buff *skb, __u8 *pbuff, unsigned int bytes);
+
+/* U */
+static int smctr_update_err_stats(struct net_device *dev);
+static int smctr_update_rx_chain(struct net_device *dev, __u16 queue);
+static int smctr_update_tx_chain(struct net_device *dev, FCBlock *fcb,
+ __u16 queue);
+
+/* W */
+static int smctr_wait_cmd(struct net_device *dev);
+static int smctr_wait_while_cbusy(struct net_device *dev);
+
+#define TO_256_BYTE_BOUNDRY(X) (((X + 0xff) & 0xff00) - X)
+#define TO_PARAGRAPH_BOUNDRY(X) (((X + 0x0f) & 0xfff0) - X)
+#define PARAGRAPH_BOUNDRY(X) smctr_malloc(dev, TO_PARAGRAPH_BOUNDRY(X))
+
+/* Allocate Adapter Shared Memory.
+ * IMPORTANT NOTE: Any changes to this function MUST be mirrored in the
+ * function "get_num_rx_bdbs" below!!!
+ *
+ * Order of memory allocation:
+ *
+ * 0. Initial System Configuration Block Pointer
+ * 1. System Configuration Block
+ * 2. System Control Block
+ * 3. Action Command Block
+ * 4. Interrupt Status Block
+ *
+ * 5. MAC TX FCB'S
+ * 6. NON-MAC TX FCB'S
+ * 7. MAC TX BDB'S
+ * 8. NON-MAC TX BDB'S
+ * 9. MAC RX FCB'S
+ * 10. NON-MAC RX FCB'S
+ * 11. MAC RX BDB'S
+ * 12. NON-MAC RX BDB'S
+ * 13. MAC TX Data Buffer( 1, 256 byte buffer)
+ * 14. MAC RX Data Buffer( 1, 256 byte buffer)
+ *
+ * 15. NON-MAC TX Data Buffer
+ * 16. NON-MAC RX Data Buffer
+ */
+static int smctr_alloc_shared_memory(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_alloc_shared_memory\n", dev->name);
+
+ /* Allocate initial System Control Block pointer.
+ * This pointer is located in the last page, last offset - 4.
+ */
+ tp->iscpb_ptr = (ISCPBlock *)(tp->ram_access + ((__u32)64 * 0x400)
+ - (long)ISCP_BLOCK_SIZE);
+
+ /* Allocate System Control Blocks. */
+ tp->scgb_ptr = (SCGBlock *)smctr_malloc(dev, sizeof(SCGBlock));
+ PARAGRAPH_BOUNDRY(tp->sh_mem_used);
+
+ tp->sclb_ptr = (SCLBlock *)smctr_malloc(dev, sizeof(SCLBlock));
+ PARAGRAPH_BOUNDRY(tp->sh_mem_used);
+
+ tp->acb_head = (ACBlock *)smctr_malloc(dev,
+ sizeof(ACBlock)*tp->num_acbs);
+ PARAGRAPH_BOUNDRY(tp->sh_mem_used);
+
+ tp->isb_ptr = (ISBlock *)smctr_malloc(dev, sizeof(ISBlock));
+ PARAGRAPH_BOUNDRY(tp->sh_mem_used);
+
+ tp->misc_command_data = (__u16 *)smctr_malloc(dev, MISC_DATA_SIZE);
+ PARAGRAPH_BOUNDRY(tp->sh_mem_used);
+
+ /* Allocate transmit FCBs. */
+ tp->tx_fcb_head[MAC_QUEUE] = (FCBlock *)smctr_malloc(dev,
+ sizeof(FCBlock) * tp->num_tx_fcbs[MAC_QUEUE]);
+
+ tp->tx_fcb_head[NON_MAC_QUEUE] = (FCBlock *)smctr_malloc(dev,
+ sizeof(FCBlock) * tp->num_tx_fcbs[NON_MAC_QUEUE]);
+
+ tp->tx_fcb_head[BUG_QUEUE] = (FCBlock *)smctr_malloc(dev,
+ sizeof(FCBlock) * tp->num_tx_fcbs[BUG_QUEUE]);
+
+ /* Allocate transmit BDBs. */
+ tp->tx_bdb_head[MAC_QUEUE] = (BDBlock *)smctr_malloc(dev,
+ sizeof(BDBlock) * tp->num_tx_bdbs[MAC_QUEUE]);
+
+ tp->tx_bdb_head[NON_MAC_QUEUE] = (BDBlock *)smctr_malloc(dev,
+ sizeof(BDBlock) * tp->num_tx_bdbs[NON_MAC_QUEUE]);
+
+ tp->tx_bdb_head[BUG_QUEUE] = (BDBlock *)smctr_malloc(dev,
+ sizeof(BDBlock) * tp->num_tx_bdbs[BUG_QUEUE]);
+
+ /* Allocate receive FCBs. */
+ tp->rx_fcb_head[MAC_QUEUE] = (FCBlock *)smctr_malloc(dev,
+ sizeof(FCBlock) * tp->num_rx_fcbs[MAC_QUEUE]);
+
+ tp->rx_fcb_head[NON_MAC_QUEUE] = (FCBlock *)smctr_malloc(dev,
+ sizeof(FCBlock) * tp->num_rx_fcbs[NON_MAC_QUEUE]);
+
+ /* Allocate receive BDBs. */
+ tp->rx_bdb_head[MAC_QUEUE] = (BDBlock *)smctr_malloc(dev,
+ sizeof(BDBlock) * tp->num_rx_bdbs[MAC_QUEUE]);
+
+ tp->rx_bdb_end[MAC_QUEUE] = (BDBlock *)smctr_malloc(dev, 0);
+
+ tp->rx_bdb_head[NON_MAC_QUEUE] = (BDBlock *)smctr_malloc(dev,
+ sizeof(BDBlock) * tp->num_rx_bdbs[NON_MAC_QUEUE]);
+
+ tp->rx_bdb_end[NON_MAC_QUEUE] = (BDBlock *)smctr_malloc(dev, 0);
+
+ /* Allocate MAC transmit buffers.
+ * MAC Tx Buffers doen't have to be on an ODD Boundry.
+ */
+ tp->tx_buff_head[MAC_QUEUE]
+ = (__u16 *)smctr_malloc(dev, tp->tx_buff_size[MAC_QUEUE]);
+ tp->tx_buff_curr[MAC_QUEUE] = tp->tx_buff_head[MAC_QUEUE];
+ tp->tx_buff_end [MAC_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
+
+ /* Allocate BUG transmit buffers. */
+ tp->tx_buff_head[BUG_QUEUE]
+ = (__u16 *)smctr_malloc(dev, tp->tx_buff_size[BUG_QUEUE]);
+ tp->tx_buff_curr[BUG_QUEUE] = tp->tx_buff_head[BUG_QUEUE];
+ tp->tx_buff_end[BUG_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
+
+ /* Allocate MAC receive data buffers.
+ * MAC Rx buffer doesn't have to be on a 256 byte boundary.
+ */
+ tp->rx_buff_head[MAC_QUEUE] = (__u16 *)smctr_malloc(dev,
+ RX_DATA_BUFFER_SIZE * tp->num_rx_bdbs[MAC_QUEUE]);
+ tp->rx_buff_end[MAC_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
+
+ /* Allocate Non-MAC transmit buffers.
+ * ?? For maximum Netware performance, put Tx Buffers on
+ * ODD Boundry and then restore malloc to Even Boundrys.
+ */
+ smctr_malloc(dev, 1L);
+ tp->tx_buff_head[NON_MAC_QUEUE]
+ = (__u16 *)smctr_malloc(dev, tp->tx_buff_size[NON_MAC_QUEUE]);
+ tp->tx_buff_curr[NON_MAC_QUEUE] = tp->tx_buff_head[NON_MAC_QUEUE];
+ tp->tx_buff_end [NON_MAC_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
+ smctr_malloc(dev, 1L);
+
+ /* Allocate Non-MAC receive data buffers.
+ * To guarantee a minimum of 256 contigous memory to
+ * UM_Receive_Packet's lookahead pointer, before a page
+ * change or ring end is encountered, place each rx buffer on
+ * a 256 byte boundary.
+ */
+ smctr_malloc(dev, TO_256_BYTE_BOUNDRY(tp->sh_mem_used));
+ tp->rx_buff_head[NON_MAC_QUEUE] = (__u16 *)smctr_malloc(dev,
+ RX_DATA_BUFFER_SIZE * tp->num_rx_bdbs[NON_MAC_QUEUE]);
+ tp->rx_buff_end[NON_MAC_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
+
+ return (0);
+}
+
+/* Enter Bypass state. */
+static int smctr_bypass_state(struct net_device *dev)
+{
+ int err;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_bypass_state\n", dev->name);
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_CHANGE_JOIN_STATE, JS_BYPASS_STATE);
+
+ return (err);
+}
+
+static int smctr_checksum_firmware(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ __u16 i, checksum = 0;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_checksum_firmware\n", dev->name);
+
+ smctr_enable_adapter_ctrl_store(dev);
+
+ for(i = 0; i < CS_RAM_SIZE; i += 2)
+ checksum += *((__u16 *)(tp->ram_access + i));
+
+ tp->microcode_version = *(__u16 *)(tp->ram_access
+ + CS_RAM_VERSION_OFFSET);
+ tp->microcode_version >>= 8;
+
+ smctr_disable_adapter_ctrl_store(dev);
+
+ if(checksum)
+ return (checksum);
+
+ return (0);
+}
+
+static int __init smctr_chk_mca(struct net_device *dev)
+{
+#ifdef CONFIG_MCA_LEGACY
+ struct net_local *tp = netdev_priv(dev);
+ int current_slot;
+ __u8 r1, r2, r3, r4, r5;
+
+ current_slot = mca_find_unused_adapter(smctr_posid, 0);
+ if(current_slot == MCA_NOTFOUND)
+ return (-ENODEV);
+
+ mca_set_adapter_name(current_slot, smctr_name);
+ mca_mark_as_used(current_slot);
+ tp->slot_num = current_slot;
+
+ r1 = mca_read_stored_pos(tp->slot_num, 2);
+ r2 = mca_read_stored_pos(tp->slot_num, 3);
+
+ if(tp->slot_num)
+ outb(CNFG_POS_CONTROL_REG, (__u8)((tp->slot_num - 1) | CNFG_SLOT_ENABLE_BIT));
+ else
+ outb(CNFG_POS_CONTROL_REG, (__u8)((tp->slot_num) | CNFG_SLOT_ENABLE_BIT));
+
+ r1 = inb(CNFG_POS_REG1);
+ r2 = inb(CNFG_POS_REG0);
+
+ tp->bic_type = BIC_594_CHIP;
+
+ /* IO */
+ r2 = mca_read_stored_pos(tp->slot_num, 2);
+ r2 &= 0xF0;
+ dev->base_addr = ((__u16)r2 << 8) + (__u16)0x800;
+ request_region(dev->base_addr, SMCTR_IO_EXTENT, smctr_name);
+
+ /* IRQ */
+ r5 = mca_read_stored_pos(tp->slot_num, 5);
+ r5 &= 0xC;
+ switch(r5)
+ {
+ case 0:
+ dev->irq = 3;
+ break;
+
+ case 0x4:
+ dev->irq = 4;
+ break;
+
+ case 0x8:
+ dev->irq = 10;
+ break;
+
+ default:
+ dev->irq = 15;
+ break;
+ }
+ if (request_irq(dev->irq, smctr_interrupt, SA_SHIRQ, smctr_name, dev)) {
+ release_region(dev->base_addr, SMCTR_IO_EXTENT);
+ return -ENODEV;
+ }
+
+ /* Get RAM base */
+ r3 = mca_read_stored_pos(tp->slot_num, 3);
+ tp->ram_base = ((__u32)(r3 & 0x7) << 13) + 0x0C0000;
+ if (r3 & 0x8)
+ tp->ram_base += 0x010000;
+ if (r3 & 0x80)
+ tp->ram_base += 0xF00000;
+
+ /* Get Ram Size */
+ r3 &= 0x30;
+ r3 >>= 4;
+
+ tp->ram_usable = (__u16)CNFG_SIZE_8KB << r3;
+ tp->ram_size = (__u16)CNFG_SIZE_64KB;
+ tp->board_id |= TOKEN_MEDIA;
+
+ r4 = mca_read_stored_pos(tp->slot_num, 4);
+ tp->rom_base = ((__u32)(r4 & 0x7) << 13) + 0x0C0000;
+ if (r4 & 0x8)
+ tp->rom_base += 0x010000;
+
+ /* Get ROM size. */
+ r4 >>= 4;
+ switch (r4) {
+ case 0:
+ tp->rom_size = CNFG_SIZE_8KB;
+ break;
+ case 1:
+ tp->rom_size = CNFG_SIZE_16KB;
+ break;
+ case 2:
+ tp->rom_size = CNFG_SIZE_32KB;
+ break;
+ default:
+ tp->rom_size = ROM_DISABLE;
+ }
+
+ /* Get Media Type. */
+ r5 = mca_read_stored_pos(tp->slot_num, 5);
+ r5 &= CNFG_MEDIA_TYPE_MASK;
+ switch(r5)
+ {
+ case (0):
+ tp->media_type = MEDIA_STP_4;
+ break;
+
+ case (1):
+ tp->media_type = MEDIA_STP_16;
+ break;
+
+ case (3):
+ tp->media_type = MEDIA_UTP_16;
+ break;
+
+ default:
+ tp->media_type = MEDIA_UTP_4;
+ break;
+ }
+ tp->media_menu = 14;
+
+ r2 = mca_read_stored_pos(tp->slot_num, 2);
+ if(!(r2 & 0x02))
+ tp->mode_bits |= EARLY_TOKEN_REL;
+
+ /* Disable slot */
+ outb(CNFG_POS_CONTROL_REG, 0);
+
+ tp->board_id = smctr_get_boardid(dev, 1);
+ switch(tp->board_id & 0xffff)
+ {
+ case WD8115TA:
+ smctr_model = "8115T/A";
+ break;
+
+ case WD8115T:
+ if(tp->extra_info & CHIP_REV_MASK)
+ smctr_model = "8115T rev XE";
+ else
+ smctr_model = "8115T rev XD";
+ break;
+
+ default:
+ smctr_model = "Unknown";
+ break;
+ }
+
+ return (0);
+#else
+ return (-1);
+#endif /* CONFIG_MCA_LEGACY */
+}
+
+static int smctr_chg_rx_mask(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int err = 0;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_chg_rx_mask\n", dev->name);
+
+ smctr_enable_16bit(dev);
+ smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+ if(tp->mode_bits & LOOPING_MODE_MASK)
+ tp->config_word0 |= RX_OWN_BIT;
+ else
+ tp->config_word0 &= ~RX_OWN_BIT;
+
+ if(tp->receive_mask & PROMISCUOUS_MODE)
+ tp->config_word0 |= PROMISCUOUS_BIT;
+ else
+ tp->config_word0 &= ~PROMISCUOUS_BIT;
+
+ if(tp->receive_mask & ACCEPT_ERR_PACKETS)
+ tp->config_word0 |= SAVBAD_BIT;
+ else
+ tp->config_word0 &= ~SAVBAD_BIT;
+
+ if(tp->receive_mask & ACCEPT_ATT_MAC_FRAMES)
+ tp->config_word0 |= RXATMAC;
+ else
+ tp->config_word0 &= ~RXATMAC;
+
+ if(tp->receive_mask & ACCEPT_MULTI_PROM)
+ tp->config_word1 |= MULTICAST_ADDRESS_BIT;
+ else
+ tp->config_word1 &= ~MULTICAST_ADDRESS_BIT;
+
+ if(tp->receive_mask & ACCEPT_SOURCE_ROUTING_SPANNING)
+ tp->config_word1 |= SOURCE_ROUTING_SPANNING_BITS;
+ else
+ {
+ if(tp->receive_mask & ACCEPT_SOURCE_ROUTING)
+ tp->config_word1 |= SOURCE_ROUTING_EXPLORER_BIT;
+ else
+ tp->config_word1 &= ~SOURCE_ROUTING_SPANNING_BITS;
+ }
+
+ if((err = smctr_issue_write_word_cmd(dev, RW_CONFIG_REGISTER_0,
+ &tp->config_word0)))
+ {
+ return (err);
+ }
+
+ if((err = smctr_issue_write_word_cmd(dev, RW_CONFIG_REGISTER_1,
+ &tp->config_word1)))
+ {
+ return (err);
+ }
+
+ smctr_disable_16bit(dev);
+
+ return (0);
+}
+
+static int smctr_clear_int(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ outb((tp->trc_mask | CSR_CLRTINT), dev->base_addr + CSR);
+
+ return (0);
+}
+
+static int smctr_clear_trc_reset(int ioaddr)
+{
+ __u8 r;
+
+ r = inb(ioaddr + MSR);
+ outb(~MSR_RST & r, ioaddr + MSR);
+
+ return (0);
+}
+
+/*
+ * The inverse routine to smctr_open().
+ */
+static int smctr_close(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ struct sk_buff *skb;
+ int err;
+
+ netif_stop_queue(dev);
+
+ tp->cleanup = 1;
+
+ /* Check to see if adapter is already in a closed state. */
+ if(tp->status != OPEN)
+ return (0);
+
+ smctr_enable_16bit(dev);
+ smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+ if((err = smctr_issue_remove_cmd(dev)))
+ {
+ smctr_disable_16bit(dev);
+ return (err);
+ }
+
+ for(;;)
+ {
+ skb = skb_dequeue(&tp->SendSkbQueue);
+ if(skb == NULL)
+ break;
+ tp->QueueSkb++;
+ dev_kfree_skb(skb);
+ }
+
+
+ return (0);
+}
+
+static int smctr_decode_firmware(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ short bit = 0x80, shift = 12;
+ DECODE_TREE_NODE *tree;
+ short branch, tsize;
+ __u16 buff = 0;
+ long weight;
+ __u8 *ucode;
+ __u16 *mem;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_decode_firmware\n", dev->name);
+
+ weight = *(long *)(tp->ptr_ucode + WEIGHT_OFFSET);
+ tsize = *(__u8 *)(tp->ptr_ucode + TREE_SIZE_OFFSET);
+ tree = (DECODE_TREE_NODE *)(tp->ptr_ucode + TREE_OFFSET);
+ ucode = (__u8 *)(tp->ptr_ucode + TREE_OFFSET
+ + (tsize * sizeof(DECODE_TREE_NODE)));
+ mem = (__u16 *)(tp->ram_access);
+
+ while(weight)
+ {
+ branch = ROOT;
+ while((tree + branch)->tag != LEAF && weight)
+ {
+ branch = *ucode & bit ? (tree + branch)->llink
+ : (tree + branch)->rlink;
+
+ bit >>= 1;
+ weight--;
+
+ if(bit == 0)
+ {
+ bit = 0x80;
+ ucode++;
+ }
+ }
+
+ buff |= (tree + branch)->info << shift;
+ shift -= 4;
+
+ if(shift < 0)
+ {
+ *(mem++) = SWAP_BYTES(buff);
+ buff = 0;
+ shift = 12;
+ }
+ }
+
+ /* The following assumes the Control Store Memory has
+ * been initialized to zero. If the last partial word
+ * is zero, it will not be written.
+ */
+ if(buff)
+ *(mem++) = SWAP_BYTES(buff);
+
+ return (0);
+}
+
+static int smctr_disable_16bit(struct net_device *dev)
+{
+ return (0);
+}
+
+/*
+ * On Exit, Adapter is:
+ * 1. TRC is in a reset state and un-initialized.
+ * 2. Adapter memory is enabled.
+ * 3. Control Store memory is out of context (-WCSS is 1).
+ */
+static int smctr_disable_adapter_ctrl_store(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int ioaddr = dev->base_addr;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_disable_adapter_ctrl_store\n", dev->name);
+
+ tp->trc_mask |= CSR_WCSS;
+ outb(tp->trc_mask, ioaddr + CSR);
+
+ return (0);
+}
+
+static int smctr_disable_bic_int(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int ioaddr = dev->base_addr;
+
+ tp->trc_mask = CSR_MSK_ALL | CSR_MSKCBUSY
+ | CSR_MSKTINT | CSR_WCSS;
+ outb(tp->trc_mask, ioaddr + CSR);
+
+ return (0);
+}
+
+static int smctr_enable_16bit(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ __u8 r;
+
+ if(tp->adapter_bus == BUS_ISA16_TYPE)
+ {
+ r = inb(dev->base_addr + LAAR);
+ outb((r | LAAR_MEM16ENB), dev->base_addr + LAAR);
+ }
+
+ return (0);
+}
+
+/*
+ * To enable the adapter control store memory:
+ * 1. Adapter must be in a RESET state.
+ * 2. Adapter memory must be enabled.
+ * 3. Control Store Memory is in context (-WCSS is 0).
+ */
+static int smctr_enable_adapter_ctrl_store(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int ioaddr = dev->base_addr;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_enable_adapter_ctrl_store\n", dev->name);
+
+ smctr_set_trc_reset(ioaddr);
+ smctr_enable_adapter_ram(dev);
+
+ tp->trc_mask &= ~CSR_WCSS;
+ outb(tp->trc_mask, ioaddr + CSR);
+
+ return (0);
+}
+
+static int smctr_enable_adapter_ram(struct net_device *dev)
+{
+ int ioaddr = dev->base_addr;
+ __u8 r;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_enable_adapter_ram\n", dev->name);
+
+ r = inb(ioaddr + MSR);
+ outb(MSR_MEMB | r, ioaddr + MSR);
+
+ return (0);
+}
+
+static int smctr_enable_bic_int(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int ioaddr = dev->base_addr;
+ __u8 r;
+
+ switch(tp->bic_type)
+ {
+ case (BIC_584_CHIP):
+ tp->trc_mask = CSR_MSKCBUSY | CSR_WCSS;
+ outb(tp->trc_mask, ioaddr + CSR);
+ r = inb(ioaddr + IRR);
+ outb(r | IRR_IEN, ioaddr + IRR);
+ break;
+
+ case (BIC_594_CHIP):
+ tp->trc_mask = CSR_MSKCBUSY | CSR_WCSS;
+ outb(tp->trc_mask, ioaddr + CSR);
+ r = inb(ioaddr + IMCCR);
+ outb(r | IMCCR_EIL, ioaddr + IMCCR);
+ break;
+ }
+
+ return (0);
+}
+
+static int __init smctr_chk_isa(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int ioaddr = dev->base_addr;
+ __u8 r1, r2, b, chksum = 0;
+ __u16 r;
+ int i;
+ int err = -ENODEV;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_chk_isa %#4x\n", dev->name, ioaddr);
+
+ if((ioaddr & 0x1F) != 0)
+ goto out;
+
+ /* Grab the region so that no one else tries to probe our ioports. */
+ if (!request_region(ioaddr, SMCTR_IO_EXTENT, smctr_name)) {
+ err = -EBUSY;
+ goto out;
+ }
+
+ /* Checksum SMC node address */
+ for(i = 0; i < 8; i++)
+ {
+ b = inb(ioaddr + LAR0 + i);
+ chksum += b;
+ }
+
+ if (chksum != NODE_ADDR_CKSUM)
+ goto out2;
+
+ b = inb(ioaddr + BDID);
+ if(b != BRD_ID_8115T)
+ {
+ printk(KERN_ERR "%s: The adapter found is not supported\n", dev->name);
+ goto out2;
+ }
+
+ /* Check for 8115T Board ID */
+ r2 = 0;
+ for(r = 0; r < 8; r++)
+ {
+ r1 = inb(ioaddr + 0x8 + r);
+ r2 += r1;
+ }
+
+ /* value of RegF adds up the sum to 0xFF */
+ if((r2 != 0xFF) && (r2 != 0xEE))
+ goto out2;
+
+ /* Get adapter ID */
+ tp->board_id = smctr_get_boardid(dev, 0);
+ switch(tp->board_id & 0xffff)
+ {
+ case WD8115TA:
+ smctr_model = "8115T/A";
+ break;
+
+ case WD8115T:
+ if(tp->extra_info & CHIP_REV_MASK)
+ smctr_model = "8115T rev XE";
+ else
+ smctr_model = "8115T rev XD";
+ break;
+
+ default:
+ smctr_model = "Unknown";
+ break;
+ }
+
+ /* Store BIC type. */
+ tp->bic_type = BIC_584_CHIP;
+ tp->nic_type = NIC_825_CHIP;
+
+ /* Copy Ram Size */
+ tp->ram_usable = CNFG_SIZE_16KB;
+ tp->ram_size = CNFG_SIZE_64KB;
+
+ /* Get 58x Ram Base */
+ r1 = inb(ioaddr);
+ r1 &= 0x3F;
+
+ r2 = inb(ioaddr + CNFG_LAAR_584);
+ r2 &= CNFG_LAAR_MASK;
+ r2 <<= 3;
+ r2 |= ((r1 & 0x38) >> 3);
+
+ tp->ram_base = ((__u32)r2 << 16) + (((__u32)(r1 & 0x7)) << 13);
+
+ /* Get 584 Irq */
+ r1 = 0;
+ r1 = inb(ioaddr + CNFG_ICR_583);
+ r1 &= CNFG_ICR_IR2_584;
+
+ r2 = inb(ioaddr + CNFG_IRR_583);
+ r2 &= CNFG_IRR_IRQS; /* 0x60 */
+ r2 >>= 5;
+
+ switch(r2)
+ {
+ case 0:
+ if(r1 == 0)
+ dev->irq = 2;
+ else
+ dev->irq = 10;
+ break;
+
+ case 1:
+ if(r1 == 0)
+ dev->irq = 3;
+ else
+ dev->irq = 11;
+ break;
+
+ case 2:
+ if(r1 == 0)
+ {
+ if(tp->extra_info & ALTERNATE_IRQ_BIT)
+ dev->irq = 5;
+ else
+ dev->irq = 4;
+ }
+ else
+ dev->irq = 15;
+ break;
+
+ case 3:
+ if(r1 == 0)
+ dev->irq = 7;
+ else
+ dev->irq = 4;
+ break;
+
+ default:
+ printk(KERN_ERR "%s: No IRQ found aborting\n", dev->name);
+ goto out2;
+ }
+
+ if (request_irq(dev->irq, smctr_interrupt, SA_SHIRQ, smctr_name, dev))
+ goto out2;
+
+ /* Get 58x Rom Base */
+ r1 = inb(ioaddr + CNFG_BIO_583);
+ r1 &= 0x3E;
+ r1 |= 0x40;
+
+ tp->rom_base = (__u32)r1 << 13;
+
+ /* Get 58x Rom Size */
+ r1 = inb(ioaddr + CNFG_BIO_583);
+ r1 &= 0xC0;
+ if(r1 == 0)
+ tp->rom_size = ROM_DISABLE;
+ else
+ {
+ r1 >>= 6;
+ tp->rom_size = (__u16)CNFG_SIZE_8KB << r1;
+ }
+
+ /* Get 58x Boot Status */
+ r1 = inb(ioaddr + CNFG_GP2);
+
+ tp->mode_bits &= (~BOOT_STATUS_MASK);
+
+ if(r1 & CNFG_GP2_BOOT_NIBBLE)
+ tp->mode_bits |= BOOT_TYPE_1;
+
+ /* Get 58x Zero Wait State */
+ tp->mode_bits &= (~ZERO_WAIT_STATE_MASK);
+
+ r1 = inb(ioaddr + CNFG_IRR_583);
+
+ if(r1 & CNFG_IRR_ZWS)
+ tp->mode_bits |= ZERO_WAIT_STATE_8_BIT;
+
+ if(tp->board_id & BOARD_16BIT)
+ {
+ r1 = inb(ioaddr + CNFG_LAAR_584);
+
+ if(r1 & CNFG_LAAR_ZWS)
+ tp->mode_bits |= ZERO_WAIT_STATE_16_BIT;
+ }
+
+ /* Get 584 Media Menu */
+ tp->media_menu = 14;
+ r1 = inb(ioaddr + CNFG_IRR_583);
+
+ tp->mode_bits &= 0xf8ff; /* (~CNFG_INTERFACE_TYPE_MASK) */
+ if((tp->board_id & TOKEN_MEDIA) == TOKEN_MEDIA)
+ {
+ /* Get Advanced Features */
+ if(((r1 & 0x6) >> 1) == 0x3)
+ tp->media_type |= MEDIA_UTP_16;
+ else
+ {
+ if(((r1 & 0x6) >> 1) == 0x2)
+ tp->media_type |= MEDIA_STP_16;
+ else
+ {
+ if(((r1 & 0x6) >> 1) == 0x1)
+ tp->media_type |= MEDIA_UTP_4;
+
+ else
+ tp->media_type |= MEDIA_STP_4;
+ }
+ }
+
+ r1 = inb(ioaddr + CNFG_GP2);
+ if(!(r1 & 0x2) ) /* GP2_ETRD */
+ tp->mode_bits |= EARLY_TOKEN_REL;
+
+ /* see if the chip is corrupted
+ if(smctr_read_584_chksum(ioaddr))
+ {
+ printk(KERN_ERR "%s: EEPROM Checksum Failure\n", dev->name);
+ free_irq(dev->irq, dev);
+ goto out2;
+ }
+ */
+ }
+
+ return (0);
+
+out2:
+ release_region(ioaddr, SMCTR_IO_EXTENT);
+out:
+ return err;
+}
+
+static int __init smctr_get_boardid(struct net_device *dev, int mca)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int ioaddr = dev->base_addr;
+ __u8 r, r1, IdByte;
+ __u16 BoardIdMask;
+
+ tp->board_id = BoardIdMask = 0;
+
+ if(mca)
+ {
+ BoardIdMask |= (MICROCHANNEL+INTERFACE_CHIP+TOKEN_MEDIA+PAGED_RAM+BOARD_16BIT);
+ tp->extra_info |= (INTERFACE_594_CHIP+RAM_SIZE_64K+NIC_825_BIT+ALTERNATE_IRQ_BIT+SLOT_16BIT);
+ }
+ else
+ {
+ BoardIdMask|=(INTERFACE_CHIP+TOKEN_MEDIA+PAGED_RAM+BOARD_16BIT);
+ tp->extra_info |= (INTERFACE_584_CHIP + RAM_SIZE_64K
+ + NIC_825_BIT + ALTERNATE_IRQ_BIT);
+ }
+
+ if(!mca)
+ {
+ r = inb(ioaddr + BID_REG_1);
+ r &= 0x0c;
+ outb(r, ioaddr + BID_REG_1);
+ r = inb(ioaddr + BID_REG_1);
+
+ if(r & BID_SIXTEEN_BIT_BIT)
+ {
+ tp->extra_info |= SLOT_16BIT;
+ tp->adapter_bus = BUS_ISA16_TYPE;
+ }
+ else
+ tp->adapter_bus = BUS_ISA8_TYPE;
+ }
+ else
+ tp->adapter_bus = BUS_MCA_TYPE;
+
+ /* Get Board Id Byte */
+ IdByte = inb(ioaddr + BID_BOARD_ID_BYTE);
+
+ /* if Major version > 1.0 then
+ * return;
+ */
+ if(IdByte & 0xF8)
+ return (-1);
+
+ r1 = inb(ioaddr + BID_REG_1);
+ r1 &= BID_ICR_MASK;
+ r1 |= BID_OTHER_BIT;
+
+ outb(r1, ioaddr + BID_REG_1);
+ r1 = inb(ioaddr + BID_REG_3);
+
+ r1 &= BID_EAR_MASK;
+ r1 |= BID_ENGR_PAGE;
+
+ outb(r1, ioaddr + BID_REG_3);
+ r1 = inb(ioaddr + BID_REG_1);
+ r1 &= BID_ICR_MASK;
+ r1 |= (BID_RLA | BID_OTHER_BIT);
+
+ outb(r1, ioaddr + BID_REG_1);
+
+ r1 = inb(ioaddr + BID_REG_1);
+ while(r1 & BID_RECALL_DONE_MASK)
+ r1 = inb(ioaddr + BID_REG_1);
+
+ r = inb(ioaddr + BID_LAR_0 + BID_REG_6);
+
+ /* clear chip rev bits */
+ tp->extra_info &= ~CHIP_REV_MASK;
+ tp->extra_info |= ((r & BID_EEPROM_CHIP_REV_MASK) << 6);
+
+ r1 = inb(ioaddr + BID_REG_1);
+ r1 &= BID_ICR_MASK;
+ r1 |= BID_OTHER_BIT;
+
+ outb(r1, ioaddr + BID_REG_1);
+ r1 = inb(ioaddr + BID_REG_3);
+
+ r1 &= BID_EAR_MASK;
+ r1 |= BID_EA6;
+
+ outb(r1, ioaddr + BID_REG_3);
+ r1 = inb(ioaddr + BID_REG_1);
+
+ r1 &= BID_ICR_MASK;
+ r1 |= BID_RLA;
+
+ outb(r1, ioaddr + BID_REG_1);
+ r1 = inb(ioaddr + BID_REG_1);
+
+ while(r1 & BID_RECALL_DONE_MASK)
+ r1 = inb(ioaddr + BID_REG_1);
+
+ return (BoardIdMask);
+}
+
+static int smctr_get_group_address(struct net_device *dev)
+{
+ smctr_issue_read_word_cmd(dev, RW_INDIVIDUAL_GROUP_ADDR);
+
+ return(smctr_wait_cmd(dev));
+}
+
+static int smctr_get_functional_address(struct net_device *dev)
+{
+ smctr_issue_read_word_cmd(dev, RW_FUNCTIONAL_ADDR);
+
+ return(smctr_wait_cmd(dev));
+}
+
+/* Calculate number of Non-MAC receive BDB's and data buffers.
+ * This function must simulate allocateing shared memory exactly
+ * as the allocate_shared_memory function above.
+ */
+static unsigned int smctr_get_num_rx_bdbs(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int mem_used = 0;
+
+ /* Allocate System Control Blocks. */
+ mem_used += sizeof(SCGBlock);
+
+ mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
+ mem_used += sizeof(SCLBlock);
+
+ mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
+ mem_used += sizeof(ACBlock) * tp->num_acbs;
+
+ mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
+ mem_used += sizeof(ISBlock);
+
+ mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
+ mem_used += MISC_DATA_SIZE;
+
+ /* Allocate transmit FCB's. */
+ mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
+
+ mem_used += sizeof(FCBlock) * tp->num_tx_fcbs[MAC_QUEUE];
+ mem_used += sizeof(FCBlock) * tp->num_tx_fcbs[NON_MAC_QUEUE];
+ mem_used += sizeof(FCBlock) * tp->num_tx_fcbs[BUG_QUEUE];
+
+ /* Allocate transmit BDBs. */
+ mem_used += sizeof(BDBlock) * tp->num_tx_bdbs[MAC_QUEUE];
+ mem_used += sizeof(BDBlock) * tp->num_tx_bdbs[NON_MAC_QUEUE];
+ mem_used += sizeof(BDBlock) * tp->num_tx_bdbs[BUG_QUEUE];
+
+ /* Allocate receive FCBs. */
+ mem_used += sizeof(FCBlock) * tp->num_rx_fcbs[MAC_QUEUE];
+ mem_used += sizeof(FCBlock) * tp->num_rx_fcbs[NON_MAC_QUEUE];
+
+ /* Allocate receive BDBs. */
+ mem_used += sizeof(BDBlock) * tp->num_rx_bdbs[MAC_QUEUE];
+
+ /* Allocate MAC transmit buffers.
+ * MAC transmit buffers don't have to be on an ODD Boundry.
+ */
+ mem_used += tp->tx_buff_size[MAC_QUEUE];
+
+ /* Allocate BUG transmit buffers. */
+ mem_used += tp->tx_buff_size[BUG_QUEUE];
+
+ /* Allocate MAC receive data buffers.
+ * MAC receive buffers don't have to be on a 256 byte boundary.
+ */
+ mem_used += RX_DATA_BUFFER_SIZE * tp->num_rx_bdbs[MAC_QUEUE];
+
+ /* Allocate Non-MAC transmit buffers.
+ * For maximum Netware performance, put Tx Buffers on
+ * ODD Boundry,and then restore malloc to Even Boundrys.
+ */
+ mem_used += 1L;
+ mem_used += tp->tx_buff_size[NON_MAC_QUEUE];
+ mem_used += 1L;
+
+ /* CALCULATE NUMBER OF NON-MAC RX BDB'S
+ * AND NON-MAC RX DATA BUFFERS
+ *
+ * Make sure the mem_used offset at this point is the
+ * same as in allocate_shared memory or the following
+ * boundary adjustment will be incorrect (i.e. not allocating
+ * the non-mac receive buffers above cannot change the 256
+ * byte offset).
+ *
+ * Since this cannot be guaranteed, adding the full 256 bytes
+ * to the amount of shared memory used at this point will guaranteed
+ * that the rx data buffers do not overflow shared memory.
+ */
+ mem_used += 0x100;
+
+ return((0xffff - mem_used) / (RX_DATA_BUFFER_SIZE + sizeof(BDBlock)));
+}
+
+static int smctr_get_physical_drop_number(struct net_device *dev)
+{
+ smctr_issue_read_word_cmd(dev, RW_PHYSICAL_DROP_NUMBER);
+
+ return(smctr_wait_cmd(dev));
+}
+
+static __u8 * smctr_get_rx_pointer(struct net_device *dev, short queue)
+{
+ struct net_local *tp = netdev_priv(dev);
+ BDBlock *bdb;
+
+ bdb = (BDBlock *)((__u32)tp->ram_access
+ + (__u32)(tp->rx_fcb_curr[queue]->trc_bdb_ptr));
+
+ tp->rx_fcb_curr[queue]->bdb_ptr = bdb;
+
+ return ((__u8 *)bdb->data_block_ptr);
+}
+
+static int smctr_get_station_id(struct net_device *dev)
+{
+ smctr_issue_read_word_cmd(dev, RW_INDIVIDUAL_MAC_ADDRESS);
+
+ return(smctr_wait_cmd(dev));
+}
+
+/*
+ * Get the current statistics. This may be called with the card open
+ * or closed.
+ */
+static struct net_device_stats *smctr_get_stats(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ return ((struct net_device_stats *)&tp->MacStat);
+}
+
+static FCBlock *smctr_get_tx_fcb(struct net_device *dev, __u16 queue,
+ __u16 bytes_count)
+{
+ struct net_local *tp = netdev_priv(dev);
+ FCBlock *pFCB;
+ BDBlock *pbdb;
+ unsigned short alloc_size;
+ unsigned short *temp;
+
+ if(smctr_debug > 20)
+ printk(KERN_DEBUG "smctr_get_tx_fcb\n");
+
+ /* check if there is enough FCB blocks */
+ if(tp->num_tx_fcbs_used[queue] >= tp->num_tx_fcbs[queue])
+ return ((FCBlock *)(-1L));
+
+ /* round off the input pkt size to the nearest even number */
+ alloc_size = (bytes_count + 1) & 0xfffe;
+
+ /* check if enough mem */
+ if((tp->tx_buff_used[queue] + alloc_size) > tp->tx_buff_size[queue])
+ return ((FCBlock *)(-1L));
+
+ /* check if past the end ;
+ * if exactly enough mem to end of ring, alloc from front.
+ * this avoids update of curr when curr = end
+ */
+ if(((unsigned long)(tp->tx_buff_curr[queue]) + alloc_size)
+ >= (unsigned long)(tp->tx_buff_end[queue]))
+ {
+ /* check if enough memory from ring head */
+ alloc_size = alloc_size +
+ (__u16)((__u32)tp->tx_buff_end[queue]
+ - (__u32)tp->tx_buff_curr[queue]);
+
+ if((tp->tx_buff_used[queue] + alloc_size)
+ > tp->tx_buff_size[queue])
+ {
+ return ((FCBlock *)(-1L));
+ }
+
+ /* ring wrap */
+ tp->tx_buff_curr[queue] = tp->tx_buff_head[queue];
+ }
+
+ tp->tx_buff_used[queue] += alloc_size;
+ tp->num_tx_fcbs_used[queue]++;
+ tp->tx_fcb_curr[queue]->frame_length = bytes_count;
+ tp->tx_fcb_curr[queue]->memory_alloc = alloc_size;
+ temp = tp->tx_buff_curr[queue];
+ tp->tx_buff_curr[queue]
+ = (__u16 *)((__u32)temp + (__u32)((bytes_count + 1) & 0xfffe));
+
+ pbdb = tp->tx_fcb_curr[queue]->bdb_ptr;
+ pbdb->buffer_length = bytes_count;
+ pbdb->data_block_ptr = temp;
+ pbdb->trc_data_block_ptr = TRC_POINTER(temp);
+
+ pFCB = tp->tx_fcb_curr[queue];
+ tp->tx_fcb_curr[queue] = tp->tx_fcb_curr[queue]->next_ptr;
+
+ return (pFCB);
+}
+
+static int smctr_get_upstream_neighbor_addr(struct net_device *dev)
+{
+ smctr_issue_read_word_cmd(dev, RW_UPSTREAM_NEIGHBOR_ADDRESS);
+
+ return(smctr_wait_cmd(dev));
+}
+
+static int smctr_hardware_send_packet(struct net_device *dev,
+ struct net_local *tp)
+{
+ struct tr_statistics *tstat = &tp->MacStat;
+ struct sk_buff *skb;
+ FCBlock *fcb;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG"%s: smctr_hardware_send_packet\n", dev->name);
+
+ if(tp->status != OPEN)
+ return (-1);
+
+ if(tp->monitor_state_ready != 1)
+ return (-1);
+
+ for(;;)
+ {
+ /* Send first buffer from queue */
+ skb = skb_dequeue(&tp->SendSkbQueue);
+ if(skb == NULL)
+ return (-1);
+
+ tp->QueueSkb++;
+
+ if(skb->len < SMC_HEADER_SIZE || skb->len > tp->max_packet_size) return (-1);
+
+ smctr_enable_16bit(dev);
+ smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+ if((fcb = smctr_get_tx_fcb(dev, NON_MAC_QUEUE, skb->len))
+ == (FCBlock *)(-1L))
+ {
+ smctr_disable_16bit(dev);
+ return (-1);
+ }
+
+ smctr_tx_move_frame(dev, skb,
+ (__u8 *)fcb->bdb_ptr->data_block_ptr, skb->len);
+
+ smctr_set_page(dev, (__u8 *)fcb);
+
+ smctr_trc_send_packet(dev, fcb, NON_MAC_QUEUE);
+ dev_kfree_skb(skb);
+
+ tstat->tx_packets++;
+
+ smctr_disable_16bit(dev);
+ }
+
+ return (0);
+}
+
+static int smctr_init_acbs(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int i;
+ ACBlock *acb;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_init_acbs\n", dev->name);
+
+ acb = tp->acb_head;
+ acb->cmd_done_status = (ACB_COMMAND_DONE | ACB_COMMAND_SUCCESSFUL);
+ acb->cmd_info = ACB_CHAIN_END;
+ acb->cmd = 0;
+ acb->subcmd = 0;
+ acb->data_offset_lo = 0;
+ acb->data_offset_hi = 0;
+ acb->next_ptr
+ = (ACBlock *)(((char *)acb) + sizeof(ACBlock));
+ acb->trc_next_ptr = TRC_POINTER(acb->next_ptr);
+
+ for(i = 1; i < tp->num_acbs; i++)
+ {
+ acb = acb->next_ptr;
+ acb->cmd_done_status
+ = (ACB_COMMAND_DONE | ACB_COMMAND_SUCCESSFUL);
+ acb->cmd_info = ACB_CHAIN_END;
+ acb->cmd = 0;
+ acb->subcmd = 0;
+ acb->data_offset_lo = 0;
+ acb->data_offset_hi = 0;
+ acb->next_ptr
+ = (ACBlock *)(((char *)acb) + sizeof(ACBlock));
+ acb->trc_next_ptr = TRC_POINTER(acb->next_ptr);
+ }
+
+ acb->next_ptr = tp->acb_head;
+ acb->trc_next_ptr = TRC_POINTER(tp->acb_head);
+ tp->acb_next = tp->acb_head->next_ptr;
+ tp->acb_curr = tp->acb_head->next_ptr;
+ tp->num_acbs_used = 0;
+
+ return (0);
+}
+
+static int smctr_init_adapter(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int err;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_init_adapter\n", dev->name);
+
+ tp->status = CLOSED;
+ tp->page_offset_mask = (tp->ram_usable * 1024) - 1;
+ skb_queue_head_init(&tp->SendSkbQueue);
+ tp->QueueSkb = MAX_TX_QUEUE;
+
+ if(!(tp->group_address_0 & 0x0080))
+ tp->group_address_0 |= 0x00C0;
+
+ if(!(tp->functional_address_0 & 0x00C0))
+ tp->functional_address_0 |= 0x00C0;
+
+ tp->functional_address[0] &= 0xFF7F;
+
+ if(tp->authorized_function_classes == 0)
+ tp->authorized_function_classes = 0x7FFF;
+
+ if(tp->authorized_access_priority == 0)
+ tp->authorized_access_priority = 0x06;
+
+ smctr_disable_bic_int(dev);
+ smctr_set_trc_reset(dev->base_addr);
+
+ smctr_enable_16bit(dev);
+ smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+ if(smctr_checksum_firmware(dev))
+ {
+ printk(KERN_ERR "%s: Previously loaded firmware is missing\n",dev->name); return (-ENOENT);
+ }
+
+ if((err = smctr_ram_memory_test(dev)))
+ {
+ printk(KERN_ERR "%s: RAM memory test failed.\n", dev->name);
+ return (-EIO);
+ }
+
+ smctr_set_rx_look_ahead(dev);
+ smctr_load_node_addr(dev);
+
+ /* Initialize adapter for Internal Self Test. */
+ smctr_reset_adapter(dev);
+ if((err = smctr_init_card_real(dev)))
+ {
+ printk(KERN_ERR "%s: Initialization of card failed (%d)\n",
+ dev->name, err);
+ return (-EINVAL);
+ }
+
+ /* This routine clobbers the TRC's internal registers. */
+ if((err = smctr_internal_self_test(dev)))
+ {
+ printk(KERN_ERR "%s: Card failed internal self test (%d)\n",
+ dev->name, err);
+ return (-EINVAL);
+ }
+
+ /* Re-Initialize adapter's internal registers */
+ smctr_reset_adapter(dev);
+ if((err = smctr_init_card_real(dev)))
+ {
+ printk(KERN_ERR "%s: Initialization of card failed (%d)\n",
+ dev->name, err);
+ return (-EINVAL);
+ }
+
+ smctr_enable_bic_int(dev);
+
+ if((err = smctr_issue_enable_int_cmd(dev, TRC_INTERRUPT_ENABLE_MASK)))
+ return (err);
+
+ smctr_disable_16bit(dev);
+
+ return (0);
+}
+
+static int smctr_init_card_real(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int err = 0;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_init_card_real\n", dev->name);
+
+ tp->sh_mem_used = 0;
+ tp->num_acbs = NUM_OF_ACBS;
+
+ /* Range Check Max Packet Size */
+ if(tp->max_packet_size < 256)
+ tp->max_packet_size = 256;
+ else
+ {
+ if(tp->max_packet_size > NON_MAC_TX_BUFFER_MEMORY)
+ tp->max_packet_size = NON_MAC_TX_BUFFER_MEMORY;
+ }
+
+ tp->num_of_tx_buffs = (NON_MAC_TX_BUFFER_MEMORY
+ / tp->max_packet_size) - 1;
+
+ if(tp->num_of_tx_buffs > NUM_NON_MAC_TX_FCBS)
+ tp->num_of_tx_buffs = NUM_NON_MAC_TX_FCBS;
+ else
+ {
+ if(tp->num_of_tx_buffs == 0)
+ tp->num_of_tx_buffs = 1;
+ }
+
+ /* Tx queue constants */
+ tp->num_tx_fcbs [BUG_QUEUE] = NUM_BUG_TX_FCBS;
+ tp->num_tx_bdbs [BUG_QUEUE] = NUM_BUG_TX_BDBS;
+ tp->tx_buff_size [BUG_QUEUE] = BUG_TX_BUFFER_MEMORY;
+ tp->tx_buff_used [BUG_QUEUE] = 0;
+ tp->tx_queue_status [BUG_QUEUE] = NOT_TRANSMITING;
+
+ tp->num_tx_fcbs [MAC_QUEUE] = NUM_MAC_TX_FCBS;
+ tp->num_tx_bdbs [MAC_QUEUE] = NUM_MAC_TX_BDBS;
+ tp->tx_buff_size [MAC_QUEUE] = MAC_TX_BUFFER_MEMORY;
+ tp->tx_buff_used [MAC_QUEUE] = 0;
+ tp->tx_queue_status [MAC_QUEUE] = NOT_TRANSMITING;
+
+ tp->num_tx_fcbs [NON_MAC_QUEUE] = NUM_NON_MAC_TX_FCBS;
+ tp->num_tx_bdbs [NON_MAC_QUEUE] = NUM_NON_MAC_TX_BDBS;
+ tp->tx_buff_size [NON_MAC_QUEUE] = NON_MAC_TX_BUFFER_MEMORY;
+ tp->tx_buff_used [NON_MAC_QUEUE] = 0;
+ tp->tx_queue_status [NON_MAC_QUEUE] = NOT_TRANSMITING;
+
+ /* Receive Queue Constants */
+ tp->num_rx_fcbs[MAC_QUEUE] = NUM_MAC_RX_FCBS;
+ tp->num_rx_bdbs[MAC_QUEUE] = NUM_MAC_RX_BDBS;
+
+ if(tp->extra_info & CHIP_REV_MASK)
+ tp->num_rx_fcbs[NON_MAC_QUEUE] = 78; /* 825 Rev. XE */
+ else
+ tp->num_rx_fcbs[NON_MAC_QUEUE] = 7; /* 825 Rev. XD */
+
+ tp->num_rx_bdbs[NON_MAC_QUEUE] = smctr_get_num_rx_bdbs(dev);
+
+ smctr_alloc_shared_memory(dev);
+ smctr_init_shared_memory(dev);
+
+ if((err = smctr_issue_init_timers_cmd(dev)))
+ return (err);
+
+ if((err = smctr_issue_init_txrx_cmd(dev)))
+ {
+ printk(KERN_ERR "%s: Hardware failure\n", dev->name);
+ return (err);
+ }
+
+ return (0);
+}
+
+static int smctr_init_rx_bdbs(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int i, j;
+ BDBlock *bdb;
+ __u16 *buf;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_init_rx_bdbs\n", dev->name);
+
+ for(i = 0; i < NUM_RX_QS_USED; i++)
+ {
+ bdb = tp->rx_bdb_head[i];
+ buf = tp->rx_buff_head[i];
+ bdb->info = (BDB_CHAIN_END | BDB_NO_WARNING);
+ bdb->buffer_length = RX_DATA_BUFFER_SIZE;
+ bdb->next_ptr = (BDBlock *)(((char *)bdb) + sizeof(BDBlock));
+ bdb->data_block_ptr = buf;
+ bdb->trc_next_ptr = TRC_POINTER(bdb->next_ptr);
+
+ if(i == NON_MAC_QUEUE)
+ bdb->trc_data_block_ptr = RX_BUFF_TRC_POINTER(buf);
+ else
+ bdb->trc_data_block_ptr = TRC_POINTER(buf);
+
+ for(j = 1; j < tp->num_rx_bdbs[i]; j++)
+ {
+ bdb->next_ptr->back_ptr = bdb;
+ bdb = bdb->next_ptr;
+ buf = (__u16 *)((char *)buf + RX_DATA_BUFFER_SIZE);
+ bdb->info = (BDB_NOT_CHAIN_END | BDB_NO_WARNING);
+ bdb->buffer_length = RX_DATA_BUFFER_SIZE;
+ bdb->next_ptr = (BDBlock *)(((char *)bdb) + sizeof(BDBlock));
+ bdb->data_block_ptr = buf;
+ bdb->trc_next_ptr = TRC_POINTER(bdb->next_ptr);
+
+ if(i == NON_MAC_QUEUE)
+ bdb->trc_data_block_ptr = RX_BUFF_TRC_POINTER(buf);
+ else
+ bdb->trc_data_block_ptr = TRC_POINTER(buf);
+ }
+
+ bdb->next_ptr = tp->rx_bdb_head[i];
+ bdb->trc_next_ptr = TRC_POINTER(tp->rx_bdb_head[i]);
+
+ tp->rx_bdb_head[i]->back_ptr = bdb;
+ tp->rx_bdb_curr[i] = tp->rx_bdb_head[i]->next_ptr;
+ }
+
+ return (0);
+}
+
+static int smctr_init_rx_fcbs(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int i, j;
+ FCBlock *fcb;
+
+ for(i = 0; i < NUM_RX_QS_USED; i++)
+ {
+ fcb = tp->rx_fcb_head[i];
+ fcb->frame_status = 0;
+ fcb->frame_length = 0;
+ fcb->info = FCB_CHAIN_END;
+ fcb->next_ptr = (FCBlock *)(((char*)fcb) + sizeof(FCBlock));
+ if(i == NON_MAC_QUEUE)
+ fcb->trc_next_ptr = RX_FCB_TRC_POINTER(fcb->next_ptr);
+ else
+ fcb->trc_next_ptr = TRC_POINTER(fcb->next_ptr);
+
+ for(j = 1; j < tp->num_rx_fcbs[i]; j++)
+ {
+ fcb->next_ptr->back_ptr = fcb;
+ fcb = fcb->next_ptr;
+ fcb->frame_status = 0;
+ fcb->frame_length = 0;
+ fcb->info = FCB_WARNING;
+ fcb->next_ptr
+ = (FCBlock *)(((char *)fcb) + sizeof(FCBlock));
+
+ if(i == NON_MAC_QUEUE)
+ fcb->trc_next_ptr
+ = RX_FCB_TRC_POINTER(fcb->next_ptr);
+ else
+ fcb->trc_next_ptr
+ = TRC_POINTER(fcb->next_ptr);
+ }
+
+ fcb->next_ptr = tp->rx_fcb_head[i];
+
+ if(i == NON_MAC_QUEUE)
+ fcb->trc_next_ptr = RX_FCB_TRC_POINTER(fcb->next_ptr);
+ else
+ fcb->trc_next_ptr = TRC_POINTER(fcb->next_ptr);
+
+ tp->rx_fcb_head[i]->back_ptr = fcb;
+ tp->rx_fcb_curr[i] = tp->rx_fcb_head[i]->next_ptr;
+ }
+
+ return(0);
+}
+
+static int smctr_init_shared_memory(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int i;
+ __u32 *iscpb;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_init_shared_memory\n", dev->name);
+
+ smctr_set_page(dev, (__u8 *)(unsigned int)tp->iscpb_ptr);
+
+ /* Initialize Initial System Configuration Point. (ISCP) */
+ iscpb = (__u32 *)PAGE_POINTER(&tp->iscpb_ptr->trc_scgb_ptr);
+ *iscpb = (__u32)(SWAP_WORDS(TRC_POINTER(tp->scgb_ptr)));
+
+ smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+ /* Initialize System Configuration Pointers. (SCP) */
+ tp->scgb_ptr->config = (SCGB_ADDRESS_POINTER_FORMAT
+ | SCGB_MULTI_WORD_CONTROL | SCGB_DATA_FORMAT
+ | SCGB_BURST_LENGTH);
+
+ tp->scgb_ptr->trc_sclb_ptr = TRC_POINTER(tp->sclb_ptr);
+ tp->scgb_ptr->trc_acb_ptr = TRC_POINTER(tp->acb_head);
+ tp->scgb_ptr->trc_isb_ptr = TRC_POINTER(tp->isb_ptr);
+ tp->scgb_ptr->isbsiz = (sizeof(ISBlock)) - 2;
+
+ /* Initialize System Control Block. (SCB) */
+ tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_CMD_NOP;
+ tp->sclb_ptr->iack_code = 0;
+ tp->sclb_ptr->resume_control = 0;
+ tp->sclb_ptr->int_mask_control = 0;
+ tp->sclb_ptr->int_mask_state = 0;
+
+ /* Initialize Interrupt Status Block. (ISB) */
+ for(i = 0; i < NUM_OF_INTERRUPTS; i++)
+ {
+ tp->isb_ptr->IStatus[i].IType = 0xf0;
+ tp->isb_ptr->IStatus[i].ISubtype = 0;
+ }
+
+ tp->current_isb_index = 0;
+
+ /* Initialize Action Command Block. (ACB) */
+ smctr_init_acbs(dev);
+
+ /* Initialize transmit FCB's and BDB's. */
+ smctr_link_tx_fcbs_to_bdbs(dev);
+ smctr_init_tx_bdbs(dev);
+ smctr_init_tx_fcbs(dev);
+
+ /* Initialize receive FCB's and BDB's. */
+ smctr_init_rx_bdbs(dev);
+ smctr_init_rx_fcbs(dev);
+
+ return (0);
+}
+
+static int smctr_init_tx_bdbs(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int i, j;
+ BDBlock *bdb;
+
+ for(i = 0; i < NUM_TX_QS_USED; i++)
+ {
+ bdb = tp->tx_bdb_head[i];
+ bdb->info = (BDB_NOT_CHAIN_END | BDB_NO_WARNING);
+ bdb->next_ptr = (BDBlock *)(((char *)bdb) + sizeof(BDBlock));
+ bdb->trc_next_ptr = TRC_POINTER(bdb->next_ptr);
+
+ for(j = 1; j < tp->num_tx_bdbs[i]; j++)
+ {
+ bdb->next_ptr->back_ptr = bdb;
+ bdb = bdb->next_ptr;
+ bdb->info = (BDB_NOT_CHAIN_END | BDB_NO_WARNING);
+ bdb->next_ptr
+ = (BDBlock *)(((char *)bdb) + sizeof( BDBlock)); bdb->trc_next_ptr = TRC_POINTER(bdb->next_ptr);
+ }
+
+ bdb->next_ptr = tp->tx_bdb_head[i];
+ bdb->trc_next_ptr = TRC_POINTER(tp->tx_bdb_head[i]);
+ tp->tx_bdb_head[i]->back_ptr = bdb;
+ }
+
+ return (0);
+}
+
+static int smctr_init_tx_fcbs(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int i, j;
+ FCBlock *fcb;
+
+ for(i = 0; i < NUM_TX_QS_USED; i++)
+ {
+ fcb = tp->tx_fcb_head[i];
+ fcb->frame_status = 0;
+ fcb->frame_length = 0;
+ fcb->info = FCB_CHAIN_END;
+ fcb->next_ptr = (FCBlock *)(((char *)fcb) + sizeof(FCBlock));
+ fcb->trc_next_ptr = TRC_POINTER(fcb->next_ptr);
+
+ for(j = 1; j < tp->num_tx_fcbs[i]; j++)
+ {
+ fcb->next_ptr->back_ptr = fcb;
+ fcb = fcb->next_ptr;
+ fcb->frame_status = 0;
+ fcb->frame_length = 0;
+ fcb->info = FCB_CHAIN_END;
+ fcb->next_ptr
+ = (FCBlock *)(((char *)fcb) + sizeof(FCBlock));
+ fcb->trc_next_ptr = TRC_POINTER(fcb->next_ptr);
+ }
+
+ fcb->next_ptr = tp->tx_fcb_head[i];
+ fcb->trc_next_ptr = TRC_POINTER(tp->tx_fcb_head[i]);
+
+ tp->tx_fcb_head[i]->back_ptr = fcb;
+ tp->tx_fcb_end[i] = tp->tx_fcb_head[i]->next_ptr;
+ tp->tx_fcb_curr[i] = tp->tx_fcb_head[i]->next_ptr;
+ tp->num_tx_fcbs_used[i] = 0;
+ }
+
+ return (0);
+}
+
+static int smctr_internal_self_test(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int err;
+
+ if((err = smctr_issue_test_internal_rom_cmd(dev)))
+ return (err);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ if(tp->acb_head->cmd_done_status & 0xff)
+ return (-1);
+
+ if((err = smctr_issue_test_hic_cmd(dev)))
+ return (err);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ if(tp->acb_head->cmd_done_status & 0xff)
+ return (-1);
+
+ if((err = smctr_issue_test_mac_reg_cmd(dev)))
+ return (err);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ if(tp->acb_head->cmd_done_status & 0xff)
+ return (-1);
+
+ return (0);
+}
+
+/*
+ * The typical workload of the driver: Handle the network interface interrupts.
+ */
+static irqreturn_t smctr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct net_local *tp;
+ int ioaddr;
+ __u16 interrupt_unmask_bits = 0, interrupt_ack_code = 0xff00;
+ __u16 err1, err = NOT_MY_INTERRUPT;
+ __u8 isb_type, isb_subtype;
+ __u16 isb_index;
+
+ if(dev == NULL)
+ {
+ printk(KERN_CRIT "%s: irq %d for unknown device.\n", dev->name, irq);
+ return IRQ_NONE;
+ }
+
+ ioaddr = dev->base_addr;
+ tp = netdev_priv(dev);
+
+
+ if(tp->status == NOT_INITIALIZED)
+ return IRQ_NONE;
+
+ spin_lock(&tp->lock);
+
+ smctr_disable_bic_int(dev);
+ smctr_enable_16bit(dev);
+
+ smctr_clear_int(dev);
+
+ /* First read the LSB */
+ while((tp->isb_ptr->IStatus[tp->current_isb_index].IType & 0xf0) == 0)
+ {
+ isb_index = tp->current_isb_index;
+ isb_type = tp->isb_ptr->IStatus[isb_index].IType;
+ isb_subtype = tp->isb_ptr->IStatus[isb_index].ISubtype;
+
+ (tp->current_isb_index)++;
+ if(tp->current_isb_index == NUM_OF_INTERRUPTS)
+ tp->current_isb_index = 0;
+
+ if(isb_type >= 0x10)
+ {
+ smctr_disable_16bit(dev);
+ spin_unlock(&tp->lock);
+ return IRQ_HANDLED;
+ }
+
+ err = HARDWARE_FAILED;
+ interrupt_ack_code = isb_index;
+ tp->isb_ptr->IStatus[isb_index].IType |= 0xf0;
+
+ interrupt_unmask_bits |= (1 << (__u16)isb_type);
+
+ switch(isb_type)
+ {
+ case ISB_IMC_MAC_TYPE_3:
+ smctr_disable_16bit(dev);
+
+ switch(isb_subtype)
+ {
+ case 0:
+ tp->monitor_state = MS_MONITOR_FSM_INACTIVE;
+ break;
+
+ case 1:
+ tp->monitor_state = MS_REPEAT_BEACON_STATE;
+ break;
+
+ case 2:
+ tp->monitor_state = MS_REPEAT_CLAIM_TOKEN_STATE;
+ break;
+
+ case 3:
+ tp->monitor_state = MS_TRANSMIT_CLAIM_TOKEN_STATE; break;
+
+ case 4:
+ tp->monitor_state = MS_STANDBY_MONITOR_STATE;
+ break;
+
+ case 5:
+ tp->monitor_state = MS_TRANSMIT_BEACON_STATE;
+ break;
+
+ case 6:
+ tp->monitor_state = MS_ACTIVE_MONITOR_STATE;
+ break;
+
+ case 7:
+ tp->monitor_state = MS_TRANSMIT_RING_PURGE_STATE;
+ break;
+
+ case 8: /* diagnostic state */
+ break;
+
+ case 9:
+ tp->monitor_state = MS_BEACON_TEST_STATE;
+ if(smctr_lobe_media_test(dev))
+ {
+ tp->ring_status_flags = RING_STATUS_CHANGED;
+ tp->ring_status = AUTO_REMOVAL_ERROR;
+ smctr_ring_status_chg(dev);
+ smctr_bypass_state(dev);
+ }
+ else
+ smctr_issue_insert_cmd(dev);
+ break;
+
+ /* case 0x0a-0xff, illegal states */
+ default:
+ break;
+ }
+
+ tp->ring_status_flags = MONITOR_STATE_CHANGED;
+ err = smctr_ring_status_chg(dev);
+
+ smctr_enable_16bit(dev);
+ break;
+
+ /* Type 0x02 - MAC Error Counters Interrupt
+ * One or more MAC Error Counter is half full
+ * MAC Error Counters
+ * Lost_FR_Error_Counter
+ * RCV_Congestion_Counter
+ * FR_copied_Error_Counter
+ * FREQ_Error_Counter
+ * Token_Error_Counter
+ * Line_Error_Counter
+ * Internal_Error_Count
+ */
+ case ISB_IMC_MAC_ERROR_COUNTERS:
+ /* Read 802.5 Error Counters */
+ err = smctr_issue_read_ring_status_cmd(dev);
+ break;
+
+ /* Type 0x04 - MAC Type 2 Interrupt
+ * HOST needs to enqueue MAC Frame for transmission
+ * SubType Bit 15 - RQ_INIT_PDU( Request Initialization) * Changed from RQ_INIT_PDU to
+ * TRC_Status_Changed_Indicate
+ */
+ case ISB_IMC_MAC_TYPE_2:
+ err = smctr_issue_read_ring_status_cmd(dev);
+ break;
+
+
+ /* Type 0x05 - TX Frame Interrupt (FI). */
+ case ISB_IMC_TX_FRAME:
+ /* BUG QUEUE for TRC stuck receive BUG */
+ if(isb_subtype & TX_PENDING_PRIORITY_2)
+ {
+ if((err = smctr_tx_complete(dev, BUG_QUEUE)) != SUCCESS)
+ break;
+ }
+
+ /* NON-MAC frames only */
+ if(isb_subtype & TX_PENDING_PRIORITY_1)
+ {
+ if((err = smctr_tx_complete(dev, NON_MAC_QUEUE)) != SUCCESS)
+ break;
+ }
+
+ /* MAC frames only */
+ if(isb_subtype & TX_PENDING_PRIORITY_0)
+ err = smctr_tx_complete(dev, MAC_QUEUE); break;
+
+ /* Type 0x06 - TX END OF QUEUE (FE) */
+ case ISB_IMC_END_OF_TX_QUEUE:
+ /* BUG queue */
+ if(isb_subtype & TX_PENDING_PRIORITY_2)
+ {
+ /* ok to clear Receive FIFO overrun
+ * imask send_BUG now completes.
+ */
+ interrupt_unmask_bits |= 0x800;
+
+ tp->tx_queue_status[BUG_QUEUE] = NOT_TRANSMITING;
+ if((err = smctr_tx_complete(dev, BUG_QUEUE)) != SUCCESS)
+ break;
+ if((err = smctr_restart_tx_chain(dev, BUG_QUEUE)) != SUCCESS)
+ break;
+ }
+
+ /* NON-MAC queue only */
+ if(isb_subtype & TX_PENDING_PRIORITY_1)
+ {
+ tp->tx_queue_status[NON_MAC_QUEUE] = NOT_TRANSMITING;
+ if((err = smctr_tx_complete(dev, NON_MAC_QUEUE)) != SUCCESS)
+ break;
+ if((err = smctr_restart_tx_chain(dev, NON_MAC_QUEUE)) != SUCCESS)
+ break;
+ }
+
+ /* MAC queue only */
+ if(isb_subtype & TX_PENDING_PRIORITY_0)
+ {
+ tp->tx_queue_status[MAC_QUEUE] = NOT_TRANSMITING;
+ if((err = smctr_tx_complete(dev, MAC_QUEUE)) != SUCCESS)
+ break;
+
+ err = smctr_restart_tx_chain(dev, MAC_QUEUE);
+ }
+ break;
+
+ /* Type 0x07 - NON-MAC RX Resource Interrupt
+ * Subtype bit 12 - (BW) BDB warning
+ * Subtype bit 13 - (FW) FCB warning
+ * Subtype bit 14 - (BE) BDB End of chain
+ * Subtype bit 15 - (FE) FCB End of chain
+ */
+ case ISB_IMC_NON_MAC_RX_RESOURCE:
+ tp->rx_fifo_overrun_count = 0;
+ tp->receive_queue_number = NON_MAC_QUEUE;
+ err1 = smctr_rx_frame(dev);
+
+ if(isb_subtype & NON_MAC_RX_RESOURCE_FE)
+ {
+ if((err = smctr_issue_resume_rx_fcb_cmd( dev, NON_MAC_QUEUE)) != SUCCESS) break;
+
+ if(tp->ptr_rx_fcb_overruns)
+ (*tp->ptr_rx_fcb_overruns)++;
+ }
+
+ if(isb_subtype & NON_MAC_RX_RESOURCE_BE)
+ {
+ if((err = smctr_issue_resume_rx_bdb_cmd( dev, NON_MAC_QUEUE)) != SUCCESS) break;
+
+ if(tp->ptr_rx_bdb_overruns)
+ (*tp->ptr_rx_bdb_overruns)++;
+ }
+ err = err1;
+ break;
+
+ /* Type 0x08 - MAC RX Resource Interrupt
+ * Subtype bit 12 - (BW) BDB warning
+ * Subtype bit 13 - (FW) FCB warning
+ * Subtype bit 14 - (BE) BDB End of chain
+ * Subtype bit 15 - (FE) FCB End of chain
+ */
+ case ISB_IMC_MAC_RX_RESOURCE:
+ tp->receive_queue_number = MAC_QUEUE;
+ err1 = smctr_rx_frame(dev);
+
+ if(isb_subtype & MAC_RX_RESOURCE_FE)
+ {
+ if((err = smctr_issue_resume_rx_fcb_cmd( dev, MAC_QUEUE)) != SUCCESS)
+ break;
+
+ if(tp->ptr_rx_fcb_overruns)
+ (*tp->ptr_rx_fcb_overruns)++;
+ }
+
+ if(isb_subtype & MAC_RX_RESOURCE_BE)
+ {
+ if((err = smctr_issue_resume_rx_bdb_cmd( dev, MAC_QUEUE)) != SUCCESS)
+ break;
+
+ if(tp->ptr_rx_bdb_overruns)
+ (*tp->ptr_rx_bdb_overruns)++;
+ }
+ err = err1;
+ break;
+
+ /* Type 0x09 - NON_MAC RX Frame Interrupt */
+ case ISB_IMC_NON_MAC_RX_FRAME:
+ tp->rx_fifo_overrun_count = 0;
+ tp->receive_queue_number = NON_MAC_QUEUE;
+ err = smctr_rx_frame(dev);
+ break;
+
+ /* Type 0x0A - MAC RX Frame Interrupt */
+ case ISB_IMC_MAC_RX_FRAME:
+ tp->receive_queue_number = MAC_QUEUE;
+ err = smctr_rx_frame(dev);
+ break;
+
+ /* Type 0x0B - TRC status
+ * TRC has encountered an error condition
+ * subtype bit 14 - transmit FIFO underrun
+ * subtype bit 15 - receive FIFO overrun
+ */
+ case ISB_IMC_TRC_FIFO_STATUS:
+ if(isb_subtype & TRC_FIFO_STATUS_TX_UNDERRUN)
+ {
+ if(tp->ptr_tx_fifo_underruns)
+ (*tp->ptr_tx_fifo_underruns)++;
+ }
+
+ if(isb_subtype & TRC_FIFO_STATUS_RX_OVERRUN)
+ {
+ /* update overrun stuck receive counter
+ * if >= 3, has to clear it by sending
+ * back to back frames. We pick
+ * DAT(duplicate address MAC frame)
+ */
+ tp->rx_fifo_overrun_count++;
+
+ if(tp->rx_fifo_overrun_count >= 3)
+ {
+ tp->rx_fifo_overrun_count = 0;
+
+ /* delay clearing fifo overrun
+ * imask till send_BUG tx
+ * complete posted
+ */
+ interrupt_unmask_bits &= (~0x800);
+ printk(KERN_CRIT "Jay please send bug\n");// smctr_send_bug(dev);
+ }
+
+ if(tp->ptr_rx_fifo_overruns)
+ (*tp->ptr_rx_fifo_overruns)++;
+ }
+
+ err = SUCCESS;
+ break;
+
+ /* Type 0x0C - Action Command Status Interrupt
+ * Subtype bit 14 - CB end of command chain (CE)
+ * Subtype bit 15 - CB command interrupt (CI)
+ */
+ case ISB_IMC_COMMAND_STATUS:
+ err = SUCCESS;
+ if(tp->acb_head->cmd == ACB_CMD_HIC_NOP)
+ {
+ printk(KERN_ERR "i1\n");
+ smctr_disable_16bit(dev);
+
+ /* XXXXXXXXXXXXXXXXX */
+ /* err = UM_Interrupt(dev); */
+
+ smctr_enable_16bit(dev);
+ }
+ else
+ {
+ if((tp->acb_head->cmd
+ == ACB_CMD_READ_TRC_STATUS)
+ && (tp->acb_head->subcmd
+ == RW_TRC_STATUS_BLOCK))
+ {
+ if(tp->ptr_bcn_type != 0)
+ {
+ *(tp->ptr_bcn_type)
+ = (__u32)((SBlock *)tp->misc_command_data)->BCN_Type;
+ }
+
+ if(((SBlock *)tp->misc_command_data)->Status_CHG_Indicate & ERROR_COUNTERS_CHANGED)
+ {
+ smctr_update_err_stats(dev);
+ }
+
+ if(((SBlock *)tp->misc_command_data)->Status_CHG_Indicate & TI_NDIS_RING_STATUS_CHANGED)
+ {
+ tp->ring_status
+ = ((SBlock*)tp->misc_command_data)->TI_NDIS_Ring_Status;
+ smctr_disable_16bit(dev);
+ err = smctr_ring_status_chg(dev);
+ smctr_enable_16bit(dev);
+ if((tp->ring_status & REMOVE_RECEIVED)
+ && (tp->config_word0 & NO_AUTOREMOVE))
+ {
+ smctr_issue_remove_cmd(dev);
+ }
+
+ if(err != SUCCESS)
+ {
+ tp->acb_pending = 0;
+ break;
+ }
+ }
+
+ if(((SBlock *)tp->misc_command_data)->Status_CHG_Indicate & UNA_CHANGED)
+ {
+ if(tp->ptr_una)
+ {
+ tp->ptr_una[0] = SWAP_BYTES(((SBlock *)tp->misc_command_data)->UNA[0]);
+ tp->ptr_una[1] = SWAP_BYTES(((SBlock *)tp->misc_command_data)->UNA[1]);
+ tp->ptr_una[2] = SWAP_BYTES(((SBlock *)tp->misc_command_data)->UNA[2]);
+ }
+
+ }
+
+ if(((SBlock *)tp->misc_command_data)->Status_CHG_Indicate & READY_TO_SEND_RQ_INIT) {
+ err = smctr_send_rq_init(dev);
+ }
+ }
+ }
+
+ tp->acb_pending = 0;
+ break;
+
+ /* Type 0x0D - MAC Type 1 interrupt
+ * Subtype -- 00 FR_BCN received at S12
+ * 01 FR_BCN received at S21
+ * 02 FR_DAT(DA=MA, A<>0) received at S21
+ * 03 TSM_EXP at S21
+ * 04 FR_REMOVE received at S42
+ * 05 TBR_EXP, BR_FLAG_SET at S42
+ * 06 TBT_EXP at S53
+ */
+ case ISB_IMC_MAC_TYPE_1:
+ if(isb_subtype > 8)
+ {
+ err = HARDWARE_FAILED;
+ break;
+ }
+
+ err = SUCCESS;
+ switch(isb_subtype)
+ {
+ case 0:
+ tp->join_state = JS_BYPASS_STATE;
+ if(tp->status != CLOSED)
+ {
+ tp->status = CLOSED;
+ err = smctr_status_chg(dev);
+ }
+ break;
+
+ case 1:
+ tp->join_state = JS_LOBE_TEST_STATE;
+ break;
+
+ case 2:
+ tp->join_state = JS_DETECT_MONITOR_PRESENT_STATE;
+ break;
+
+ case 3:
+ tp->join_state = JS_AWAIT_NEW_MONITOR_STATE;
+ break;
+
+ case 4:
+ tp->join_state = JS_DUPLICATE_ADDRESS_TEST_STATE;
+ break;
+
+ case 5:
+ tp->join_state = JS_NEIGHBOR_NOTIFICATION_STATE;
+ break;
+
+ case 6:
+ tp->join_state = JS_REQUEST_INITIALIZATION_STATE;
+ break;
+
+ case 7:
+ tp->join_state = JS_JOIN_COMPLETE_STATE;
+ tp->status = OPEN;
+ err = smctr_status_chg(dev);
+ break;
+
+ case 8:
+ tp->join_state = JS_BYPASS_WAIT_STATE;
+ break;
+ }
+ break ;
+
+ /* Type 0x0E - TRC Initialization Sequence Interrupt
+ * Subtype -- 00-FF Initializatin sequence complete
+ */
+ case ISB_IMC_TRC_INTRNL_TST_STATUS:
+ tp->status = INITIALIZED;
+ smctr_disable_16bit(dev);
+ err = smctr_status_chg(dev);
+ smctr_enable_16bit(dev);
+ break;
+
+ /* other interrupt types, illegal */
+ default:
+ break;
+ }
+
+ if(err != SUCCESS)
+ break;
+ }
+
+ /* Checking the ack code instead of the unmask bits here is because :
+ * while fixing the stuck receive, DAT frame are sent and mask off
+ * FIFO overrun interrupt temporarily (interrupt_unmask_bits = 0)
+ * but we still want to issue ack to ISB
+ */
+ if(!(interrupt_ack_code & 0xff00))
+ smctr_issue_int_ack(dev, interrupt_ack_code, interrupt_unmask_bits);
+
+ smctr_disable_16bit(dev);
+ smctr_enable_bic_int(dev);
+ spin_unlock(&tp->lock);
+
+ return IRQ_HANDLED;
+}
+
+static int smctr_issue_enable_int_cmd(struct net_device *dev,
+ __u16 interrupt_enable_mask)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int err;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ tp->sclb_ptr->int_mask_control = interrupt_enable_mask;
+ tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_CMD_CLEAR_INTERRUPT_MASK;
+
+ smctr_set_ctrl_attention(dev);
+
+ return (0);
+}
+
+static int smctr_issue_int_ack(struct net_device *dev, __u16 iack_code, __u16 ibits)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ if(smctr_wait_while_cbusy(dev))
+ return (-1);
+
+ tp->sclb_ptr->int_mask_control = ibits;
+ tp->sclb_ptr->iack_code = iack_code << 1; /* use the offset from base */ tp->sclb_ptr->resume_control = 0;
+ tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_IACK_CODE_VALID | SCLB_CMD_CLEAR_INTERRUPT_MASK;
+
+ smctr_set_ctrl_attention(dev);
+
+ return (0);
+}
+
+static int smctr_issue_init_timers_cmd(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int i;
+ int err;
+ __u16 *pTimer_Struc = (__u16 *)tp->misc_command_data;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ tp->config_word0 = THDREN | DMA_TRIGGER | USETPT | NO_AUTOREMOVE;
+ tp->config_word1 = 0;
+
+ if((tp->media_type == MEDIA_STP_16)
+ || (tp->media_type == MEDIA_UTP_16)
+ || (tp->media_type == MEDIA_STP_16_UTP_16))
+ {
+ tp->config_word0 |= FREQ_16MB_BIT;
+ }
+
+ if(tp->mode_bits & EARLY_TOKEN_REL)
+ tp->config_word0 |= ETREN;
+
+ if(tp->mode_bits & LOOPING_MODE_MASK)
+ tp->config_word0 |= RX_OWN_BIT;
+ else
+ tp->config_word0 &= ~RX_OWN_BIT;
+
+ if(tp->receive_mask & PROMISCUOUS_MODE)
+ tp->config_word0 |= PROMISCUOUS_BIT;
+ else
+ tp->config_word0 &= ~PROMISCUOUS_BIT;
+
+ if(tp->receive_mask & ACCEPT_ERR_PACKETS)
+ tp->config_word0 |= SAVBAD_BIT;
+ else
+ tp->config_word0 &= ~SAVBAD_BIT;
+
+ if(tp->receive_mask & ACCEPT_ATT_MAC_FRAMES)
+ tp->config_word0 |= RXATMAC;
+ else
+ tp->config_word0 &= ~RXATMAC;
+
+ if(tp->receive_mask & ACCEPT_MULTI_PROM)
+ tp->config_word1 |= MULTICAST_ADDRESS_BIT;
+ else
+ tp->config_word1 &= ~MULTICAST_ADDRESS_BIT;
+
+ if(tp->receive_mask & ACCEPT_SOURCE_ROUTING_SPANNING)
+ tp->config_word1 |= SOURCE_ROUTING_SPANNING_BITS;
+ else
+ {
+ if(tp->receive_mask & ACCEPT_SOURCE_ROUTING)
+ tp->config_word1 |= SOURCE_ROUTING_EXPLORER_BIT;
+ else
+ tp->config_word1 &= ~SOURCE_ROUTING_SPANNING_BITS;
+ }
+
+ if((tp->media_type == MEDIA_STP_16)
+ || (tp->media_type == MEDIA_UTP_16)
+ || (tp->media_type == MEDIA_STP_16_UTP_16))
+ {
+ tp->config_word1 |= INTERFRAME_SPACING_16;
+ }
+ else
+ tp->config_word1 |= INTERFRAME_SPACING_4;
+
+ *pTimer_Struc++ = tp->config_word0;
+ *pTimer_Struc++ = tp->config_word1;
+
+ if((tp->media_type == MEDIA_STP_4)
+ || (tp->media_type == MEDIA_UTP_4)
+ || (tp->media_type == MEDIA_STP_4_UTP_4))
+ {
+ *pTimer_Struc++ = 0x00FA; /* prescale */
+ *pTimer_Struc++ = 0x2710; /* TPT_limit */
+ *pTimer_Struc++ = 0x2710; /* TQP_limit */
+ *pTimer_Struc++ = 0x0A28; /* TNT_limit */
+ *pTimer_Struc++ = 0x3E80; /* TBT_limit */
+ *pTimer_Struc++ = 0x3A98; /* TSM_limit */
+ *pTimer_Struc++ = 0x1B58; /* TAM_limit */
+ *pTimer_Struc++ = 0x00C8; /* TBR_limit */
+ *pTimer_Struc++ = 0x07D0; /* TER_limit */
+ *pTimer_Struc++ = 0x000A; /* TGT_limit */
+ *pTimer_Struc++ = 0x1162; /* THT_limit */
+ *pTimer_Struc++ = 0x07D0; /* TRR_limit */
+ *pTimer_Struc++ = 0x1388; /* TVX_limit */
+ *pTimer_Struc++ = 0x0000; /* reserved */
+ }
+ else
+ {
+ *pTimer_Struc++ = 0x03E8; /* prescale */
+ *pTimer_Struc++ = 0x9C40; /* TPT_limit */
+ *pTimer_Struc++ = 0x9C40; /* TQP_limit */
+ *pTimer_Struc++ = 0x0A28; /* TNT_limit */
+ *pTimer_Struc++ = 0x3E80; /* TBT_limit */
+ *pTimer_Struc++ = 0x3A98; /* TSM_limit */
+ *pTimer_Struc++ = 0x1B58; /* TAM_limit */
+ *pTimer_Struc++ = 0x00C8; /* TBR_limit */
+ *pTimer_Struc++ = 0x07D0; /* TER_limit */
+ *pTimer_Struc++ = 0x000A; /* TGT_limit */
+ *pTimer_Struc++ = 0x4588; /* THT_limit */
+ *pTimer_Struc++ = 0x1F40; /* TRR_limit */
+ *pTimer_Struc++ = 0x4E20; /* TVX_limit */
+ *pTimer_Struc++ = 0x0000; /* reserved */
+ }
+
+ /* Set node address. */
+ *pTimer_Struc++ = dev->dev_addr[0] << 8
+ | (dev->dev_addr[1] & 0xFF);
+ *pTimer_Struc++ = dev->dev_addr[2] << 8
+ | (dev->dev_addr[3] & 0xFF);
+ *pTimer_Struc++ = dev->dev_addr[4] << 8
+ | (dev->dev_addr[5] & 0xFF);
+
+ /* Set group address. */
+ *pTimer_Struc++ = tp->group_address_0 << 8
+ | tp->group_address_0 >> 8;
+ *pTimer_Struc++ = tp->group_address[0] << 8
+ | tp->group_address[0] >> 8;
+ *pTimer_Struc++ = tp->group_address[1] << 8
+ | tp->group_address[1] >> 8;
+
+ /* Set functional address. */
+ *pTimer_Struc++ = tp->functional_address_0 << 8
+ | tp->functional_address_0 >> 8;
+ *pTimer_Struc++ = tp->functional_address[0] << 8
+ | tp->functional_address[0] >> 8;
+ *pTimer_Struc++ = tp->functional_address[1] << 8
+ | tp->functional_address[1] >> 8;
+
+ /* Set Bit-Wise group address. */
+ *pTimer_Struc++ = tp->bitwise_group_address[0] << 8
+ | tp->bitwise_group_address[0] >> 8;
+ *pTimer_Struc++ = tp->bitwise_group_address[1] << 8
+ | tp->bitwise_group_address[1] >> 8;
+
+ /* Set ring number address. */
+ *pTimer_Struc++ = tp->source_ring_number;
+ *pTimer_Struc++ = tp->target_ring_number;
+
+ /* Physical drop number. */
+ *pTimer_Struc++ = (unsigned short)0;
+ *pTimer_Struc++ = (unsigned short)0;
+
+ /* Product instance ID. */
+ for(i = 0; i < 9; i++)
+ *pTimer_Struc++ = (unsigned short)0;
+
+ err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_INIT_TRC_TIMERS, 0);
+
+ return (err);
+}
+
+static int smctr_issue_init_txrx_cmd(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int i;
+ int err;
+ void **txrx_ptrs = (void *)tp->misc_command_data;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ if((err = smctr_wait_cmd(dev)))
+ {
+ printk(KERN_ERR "%s: Hardware failure\n", dev->name);
+ return (err);
+ }
+
+ /* Initialize Transmit Queue Pointers that are used, to point to
+ * a single FCB.
+ */
+ for(i = 0; i < NUM_TX_QS_USED; i++)
+ *txrx_ptrs++ = (void *)TRC_POINTER(tp->tx_fcb_head[i]);
+
+ /* Initialize Transmit Queue Pointers that are NOT used to ZERO. */
+ for(; i < MAX_TX_QS; i++)
+ *txrx_ptrs++ = (void *)0;
+
+ /* Initialize Receive Queue Pointers (MAC and Non-MAC) that are
+ * used, to point to a single FCB and a BDB chain of buffers.
+ */
+ for(i = 0; i < NUM_RX_QS_USED; i++)
+ {
+ *txrx_ptrs++ = (void *)TRC_POINTER(tp->rx_fcb_head[i]);
+ *txrx_ptrs++ = (void *)TRC_POINTER(tp->rx_bdb_head[i]);
+ }
+
+ /* Initialize Receive Queue Pointers that are NOT used to ZERO. */
+ for(; i < MAX_RX_QS; i++)
+ {
+ *txrx_ptrs++ = (void *)0;
+ *txrx_ptrs++ = (void *)0;
+ }
+
+ err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_INIT_TX_RX, 0);
+
+ return (err);
+}
+
+static int smctr_issue_insert_cmd(struct net_device *dev)
+{
+ int err;
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_INSERT, ACB_SUB_CMD_NOP);
+
+ return (err);
+}
+
+static int smctr_issue_read_ring_status_cmd(struct net_device *dev)
+{
+ int err;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_READ_TRC_STATUS,
+ RW_TRC_STATUS_BLOCK);
+
+ return (err);
+}
+
+static int smctr_issue_read_word_cmd(struct net_device *dev, __u16 aword_cnt)
+{
+ int err;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_READ_VALUE,
+ aword_cnt);
+
+ return (err);
+}
+
+static int smctr_issue_remove_cmd(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int err;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ tp->sclb_ptr->resume_control = 0;
+ tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_CMD_REMOVE;
+
+ smctr_set_ctrl_attention(dev);
+
+ return (0);
+}
+
+static int smctr_issue_resume_acb_cmd(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int err;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ tp->sclb_ptr->resume_control = SCLB_RC_ACB;
+ tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_RESUME_CONTROL_VALID;
+
+ tp->acb_pending = 1;
+
+ smctr_set_ctrl_attention(dev);
+
+ return (0);
+}
+
+static int smctr_issue_resume_rx_bdb_cmd(struct net_device *dev, __u16 queue)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int err;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ if(queue == MAC_QUEUE)
+ tp->sclb_ptr->resume_control = SCLB_RC_RX_MAC_BDB;
+ else
+ tp->sclb_ptr->resume_control = SCLB_RC_RX_NON_MAC_BDB;
+
+ tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_RESUME_CONTROL_VALID;
+
+ smctr_set_ctrl_attention(dev);
+
+ return (0);
+}
+
+static int smctr_issue_resume_rx_fcb_cmd(struct net_device *dev, __u16 queue)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_issue_resume_rx_fcb_cmd\n", dev->name);
+
+ if(smctr_wait_while_cbusy(dev))
+ return (-1);
+
+ if(queue == MAC_QUEUE)
+ tp->sclb_ptr->resume_control = SCLB_RC_RX_MAC_FCB;
+ else
+ tp->sclb_ptr->resume_control = SCLB_RC_RX_NON_MAC_FCB;
+
+ tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_RESUME_CONTROL_VALID;
+
+ smctr_set_ctrl_attention(dev);
+
+ return (0);
+}
+
+static int smctr_issue_resume_tx_fcb_cmd(struct net_device *dev, __u16 queue)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_issue_resume_tx_fcb_cmd\n", dev->name);
+
+ if(smctr_wait_while_cbusy(dev))
+ return (-1);
+
+ tp->sclb_ptr->resume_control = (SCLB_RC_TFCB0 << queue);
+ tp->sclb_ptr->valid_command = SCLB_RESUME_CONTROL_VALID | SCLB_VALID;
+
+ smctr_set_ctrl_attention(dev);
+
+ return (0);
+}
+
+static int smctr_issue_test_internal_rom_cmd(struct net_device *dev)
+{
+ int err;
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
+ TRC_INTERNAL_ROM_TEST);
+
+ return (err);
+}
+
+static int smctr_issue_test_hic_cmd(struct net_device *dev)
+{
+ int err;
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_HIC_TEST,
+ TRC_HOST_INTERFACE_REG_TEST);
+
+ return (err);
+}
+
+static int smctr_issue_test_mac_reg_cmd(struct net_device *dev)
+{
+ int err;
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
+ TRC_MAC_REGISTERS_TEST);
+
+ return (err);
+}
+
+static int smctr_issue_trc_loopback_cmd(struct net_device *dev)
+{
+ int err;
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
+ TRC_INTERNAL_LOOPBACK);
+
+ return (err);
+}
+
+static int smctr_issue_tri_loopback_cmd(struct net_device *dev)
+{
+ int err;
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
+ TRC_TRI_LOOPBACK);
+
+ return (err);
+}
+
+static int smctr_issue_write_byte_cmd(struct net_device *dev,
+ short aword_cnt, void *byte)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int iword, ibyte;
+ int err;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ for(iword = 0, ibyte = 0; iword < (unsigned int)(aword_cnt & 0xff);
+ iword++, ibyte += 2)
+ {
+ tp->misc_command_data[iword] = (*((__u8 *)byte + ibyte) << 8)
+ | (*((__u8 *)byte + ibyte + 1));
+ }
+
+ return (smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_WRITE_VALUE,
+ aword_cnt));
+}
+
+static int smctr_issue_write_word_cmd(struct net_device *dev,
+ short aword_cnt, void *word)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int i, err;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ for(i = 0; i < (unsigned int)(aword_cnt & 0xff); i++)
+ tp->misc_command_data[i] = *((__u16 *)word + i);
+
+ err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_WRITE_VALUE,
+ aword_cnt);
+
+ return (err);
+}
+
+static int smctr_join_complete_state(struct net_device *dev)
+{
+ int err;
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_CHANGE_JOIN_STATE,
+ JS_JOIN_COMPLETE_STATE);
+
+ return (err);
+}
+
+static int smctr_link_tx_fcbs_to_bdbs(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int i, j;
+ FCBlock *fcb;
+ BDBlock *bdb;
+
+ for(i = 0; i < NUM_TX_QS_USED; i++)
+ {
+ fcb = tp->tx_fcb_head[i];
+ bdb = tp->tx_bdb_head[i];
+
+ for(j = 0; j < tp->num_tx_fcbs[i]; j++)
+ {
+ fcb->bdb_ptr = bdb;
+ fcb->trc_bdb_ptr = TRC_POINTER(bdb);
+ fcb = (FCBlock *)((char *)fcb + sizeof(FCBlock));
+ bdb = (BDBlock *)((char *)bdb + sizeof(BDBlock));
+ }
+ }
+
+ return (0);
+}
+
+static int smctr_load_firmware(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ __u16 i, checksum = 0;
+ int err = 0;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_load_firmware\n", dev->name);
+
+ tp->ptr_ucode = smctr_code;
+ tp->num_of_tx_buffs = 4;
+ tp->mode_bits |= UMAC;
+ tp->receive_mask = 0;
+ tp->max_packet_size = 4177;
+
+ /* Can only upload the firmware once per adapter reset. */
+ if(tp->microcode_version != 0)
+ return (UCODE_PRESENT);
+
+ /* Verify the firmware exists and is there in the right amount. */
+ if((tp->ptr_ucode == 0L)
+ || (*(tp->ptr_ucode + UCODE_VERSION_OFFSET) < UCODE_VERSION))
+ {
+ return (UCODE_NOT_PRESENT);
+ }
+
+ /* UCODE_SIZE is not included in Checksum. */
+ for(i = 0; i < *((__u16 *)(tp->ptr_ucode + UCODE_SIZE_OFFSET)); i += 2)
+ checksum += *((__u16 *)(tp->ptr_ucode + 2 + i));
+ if(checksum)
+ return (UCODE_NOT_PRESENT);
+
+ /* At this point we have a valid firmware image, lets kick it on up. */
+ smctr_enable_adapter_ram(dev);
+ smctr_enable_16bit(dev);
+ smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+ if((smctr_checksum_firmware(dev))
+ || (*(tp->ptr_ucode + UCODE_VERSION_OFFSET)
+ > tp->microcode_version))
+ {
+ smctr_enable_adapter_ctrl_store(dev);
+
+ /* Zero out ram space for firmware. */
+ for(i = 0; i < CS_RAM_SIZE; i += 2)
+ *((__u16 *)(tp->ram_access + i)) = 0;
+
+ smctr_decode_firmware(dev);
+
+ tp->microcode_version = *(tp->ptr_ucode + UCODE_VERSION_OFFSET); *((__u16 *)(tp->ram_access + CS_RAM_VERSION_OFFSET))
+ = (tp->microcode_version << 8);
+ *((__u16 *)(tp->ram_access + CS_RAM_CHECKSUM_OFFSET))
+ = ~(tp->microcode_version << 8) + 1;
+
+ smctr_disable_adapter_ctrl_store(dev);
+
+ if(smctr_checksum_firmware(dev))
+ err = HARDWARE_FAILED;
+ }
+ else
+ err = UCODE_PRESENT;
+
+ smctr_disable_16bit(dev);
+
+ return (err);
+}
+
+static int smctr_load_node_addr(struct net_device *dev)
+{
+ int ioaddr = dev->base_addr;
+ unsigned int i;
+ __u8 r;
+
+ for(i = 0; i < 6; i++)
+ {
+ r = inb(ioaddr + LAR0 + i);
+ dev->dev_addr[i] = (char)r;
+ }
+ dev->addr_len = 6;
+
+ return (0);
+}
+
+/* Lobe Media Test.
+ * During the transmission of the initial 1500 lobe media MAC frames,
+ * the phase lock loop in the 805 chip may lock, and then un-lock, causing
+ * the 825 to go into a PURGE state. When performing a PURGE, the MCT
+ * microcode will not transmit any frames given to it by the host, and
+ * will consequently cause a timeout.
+ *
+ * NOTE 1: If the monitor_state is MS_BEACON_TEST_STATE, all transmit
+ * queues other then the one used for the lobe_media_test should be
+ * disabled.!?
+ *
+ * NOTE 2: If the monitor_state is MS_BEACON_TEST_STATE and the receive_mask
+ * has any multi-cast or promiscous bits set, the receive_mask needs to
+ * be changed to clear the multi-cast or promiscous mode bits, the lobe_test
+ * run, and then the receive mask set back to its original value if the test
+ * is successful.
+ */
+static int smctr_lobe_media_test(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int i, perror = 0;
+ unsigned short saved_rcv_mask;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_lobe_media_test\n", dev->name);
+
+ /* Clear receive mask for lobe test. */
+ saved_rcv_mask = tp->receive_mask;
+ tp->receive_mask = 0;
+
+ smctr_chg_rx_mask(dev);
+
+ /* Setup the lobe media test. */
+ smctr_lobe_media_test_cmd(dev);
+ if(smctr_wait_cmd(dev))
+ {
+ smctr_reset_adapter(dev);
+ tp->status = CLOSED;
+ return (LOBE_MEDIA_TEST_FAILED);
+ }
+
+ /* Tx lobe media test frames. */
+ for(i = 0; i < 1500; ++i)
+ {
+ if(smctr_send_lobe_media_test(dev))
+ {
+ if(perror)
+ {
+ smctr_reset_adapter(dev);
+ tp->state = CLOSED;
+ return (LOBE_MEDIA_TEST_FAILED);
+ }
+ else
+ {
+ perror = 1;
+ if(smctr_lobe_media_test_cmd(dev))
+ {
+ smctr_reset_adapter(dev);
+ tp->state = CLOSED;
+ return (LOBE_MEDIA_TEST_FAILED);
+ }
+ }
+ }
+ }
+
+ if(smctr_send_dat(dev))
+ {
+ if(smctr_send_dat(dev))
+ {
+ smctr_reset_adapter(dev);
+ tp->state = CLOSED;
+ return (LOBE_MEDIA_TEST_FAILED);
+ }
+ }
+
+ /* Check if any frames received during test. */
+ if((tp->rx_fcb_curr[MAC_QUEUE]->frame_status)
+ || (tp->rx_fcb_curr[NON_MAC_QUEUE]->frame_status))
+ {
+ smctr_reset_adapter(dev);
+ tp->state = CLOSED;
+ return (LOBE_MEDIA_TEST_FAILED);
+ }
+
+ /* Set receive mask to "Promisc" mode. */
+ tp->receive_mask = saved_rcv_mask;
+
+ smctr_chg_rx_mask(dev);
+
+ return (0);
+}
+
+static int smctr_lobe_media_test_cmd(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int err;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_lobe_media_test_cmd\n", dev->name);
+
+ /* Change to lobe media test state. */
+ if(tp->monitor_state != MS_BEACON_TEST_STATE)
+ {
+ smctr_lobe_media_test_state(dev);
+ if(smctr_wait_cmd(dev))
+ {
+ printk(KERN_ERR "Lobe Failed test state\n");
+ return (LOBE_MEDIA_TEST_FAILED);
+ }
+ }
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
+ TRC_LOBE_MEDIA_TEST);
+
+ return (err);
+}
+
+static int smctr_lobe_media_test_state(struct net_device *dev)
+{
+ int err;
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_CHANGE_JOIN_STATE,
+ JS_LOBE_TEST_STATE);
+
+ return (err);
+}
+
+static int smctr_make_8025_hdr(struct net_device *dev,
+ MAC_HEADER *rmf, MAC_HEADER *tmf, __u16 ac_fc)
+{
+ tmf->ac = MSB(ac_fc); /* msb is access control */
+ tmf->fc = LSB(ac_fc); /* lsb is frame control */
+
+ tmf->sa[0] = dev->dev_addr[0];
+ tmf->sa[1] = dev->dev_addr[1];
+ tmf->sa[2] = dev->dev_addr[2];
+ tmf->sa[3] = dev->dev_addr[3];
+ tmf->sa[4] = dev->dev_addr[4];
+ tmf->sa[5] = dev->dev_addr[5];
+
+ switch(tmf->vc)
+ {
+ /* Send RQ_INIT to RPS */
+ case RQ_INIT:
+ tmf->da[0] = 0xc0;
+ tmf->da[1] = 0x00;
+ tmf->da[2] = 0x00;
+ tmf->da[3] = 0x00;
+ tmf->da[4] = 0x00;
+ tmf->da[5] = 0x02;
+ break;
+
+ /* Send RPT_TX_FORWARD to CRS */
+ case RPT_TX_FORWARD:
+ tmf->da[0] = 0xc0;
+ tmf->da[1] = 0x00;
+ tmf->da[2] = 0x00;
+ tmf->da[3] = 0x00;
+ tmf->da[4] = 0x00;
+ tmf->da[5] = 0x10;
+ break;
+
+ /* Everything else goes to sender */
+ default:
+ tmf->da[0] = rmf->sa[0];
+ tmf->da[1] = rmf->sa[1];
+ tmf->da[2] = rmf->sa[2];
+ tmf->da[3] = rmf->sa[3];
+ tmf->da[4] = rmf->sa[4];
+ tmf->da[5] = rmf->sa[5];
+ break;
+ }
+
+ return (0);
+}
+
+static int smctr_make_access_pri(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ tsv->svi = AUTHORIZED_ACCESS_PRIORITY;
+ tsv->svl = S_AUTHORIZED_ACCESS_PRIORITY;
+
+ tsv->svv[0] = MSB(tp->authorized_access_priority);
+ tsv->svv[1] = LSB(tp->authorized_access_priority);
+
+ return (0);
+}
+
+static int smctr_make_addr_mod(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+ tsv->svi = ADDRESS_MODIFER;
+ tsv->svl = S_ADDRESS_MODIFER;
+
+ tsv->svv[0] = 0;
+ tsv->svv[1] = 0;
+
+ return (0);
+}
+
+static int smctr_make_auth_funct_class(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ tsv->svi = AUTHORIZED_FUNCTION_CLASS;
+ tsv->svl = S_AUTHORIZED_FUNCTION_CLASS;
+
+ tsv->svv[0] = MSB(tp->authorized_function_classes);
+ tsv->svv[1] = LSB(tp->authorized_function_classes);
+
+ return (0);
+}
+
+static int smctr_make_corr(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv, __u16 correlator)
+{
+ tsv->svi = CORRELATOR;
+ tsv->svl = S_CORRELATOR;
+
+ tsv->svv[0] = MSB(correlator);
+ tsv->svv[1] = LSB(correlator);
+
+ return (0);
+}
+
+static int smctr_make_funct_addr(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ smctr_get_functional_address(dev);
+
+ tsv->svi = FUNCTIONAL_ADDRESS;
+ tsv->svl = S_FUNCTIONAL_ADDRESS;
+
+ tsv->svv[0] = MSB(tp->misc_command_data[0]);
+ tsv->svv[1] = LSB(tp->misc_command_data[0]);
+
+ tsv->svv[2] = MSB(tp->misc_command_data[1]);
+ tsv->svv[3] = LSB(tp->misc_command_data[1]);
+
+ return (0);
+}
+
+static int smctr_make_group_addr(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ smctr_get_group_address(dev);
+
+ tsv->svi = GROUP_ADDRESS;
+ tsv->svl = S_GROUP_ADDRESS;
+
+ tsv->svv[0] = MSB(tp->misc_command_data[0]);
+ tsv->svv[1] = LSB(tp->misc_command_data[0]);
+
+ tsv->svv[2] = MSB(tp->misc_command_data[1]);
+ tsv->svv[3] = LSB(tp->misc_command_data[1]);
+
+ /* Set Group Address Sub-vector to all zeros if only the
+ * Group Address/Functional Address Indicator is set.
+ */
+ if(tsv->svv[0] == 0x80 && tsv->svv[1] == 0x00
+ && tsv->svv[2] == 0x00 && tsv->svv[3] == 0x00)
+ tsv->svv[0] = 0x00;
+
+ return (0);
+}
+
+static int smctr_make_phy_drop_num(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ smctr_get_physical_drop_number(dev);
+
+ tsv->svi = PHYSICAL_DROP;
+ tsv->svl = S_PHYSICAL_DROP;
+
+ tsv->svv[0] = MSB(tp->misc_command_data[0]);
+ tsv->svv[1] = LSB(tp->misc_command_data[0]);
+
+ tsv->svv[2] = MSB(tp->misc_command_data[1]);
+ tsv->svv[3] = LSB(tp->misc_command_data[1]);
+
+ return (0);
+}
+
+static int smctr_make_product_id(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+ int i;
+
+ tsv->svi = PRODUCT_INSTANCE_ID;
+ tsv->svl = S_PRODUCT_INSTANCE_ID;
+
+ for(i = 0; i < 18; i++)
+ tsv->svv[i] = 0xF0;
+
+ return (0);
+}
+
+static int smctr_make_station_id(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ smctr_get_station_id(dev);
+
+ tsv->svi = STATION_IDENTIFER;
+ tsv->svl = S_STATION_IDENTIFER;
+
+ tsv->svv[0] = MSB(tp->misc_command_data[0]);
+ tsv->svv[1] = LSB(tp->misc_command_data[0]);
+
+ tsv->svv[2] = MSB(tp->misc_command_data[1]);
+ tsv->svv[3] = LSB(tp->misc_command_data[1]);
+
+ tsv->svv[4] = MSB(tp->misc_command_data[2]);
+ tsv->svv[5] = LSB(tp->misc_command_data[2]);
+
+ return (0);
+}
+
+static int smctr_make_ring_station_status(struct net_device *dev,
+ MAC_SUB_VECTOR * tsv)
+{
+ tsv->svi = RING_STATION_STATUS;
+ tsv->svl = S_RING_STATION_STATUS;
+
+ tsv->svv[0] = 0;
+ tsv->svv[1] = 0;
+ tsv->svv[2] = 0;
+ tsv->svv[3] = 0;
+ tsv->svv[4] = 0;
+ tsv->svv[5] = 0;
+
+ return (0);
+}
+
+static int smctr_make_ring_station_version(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ tsv->svi = RING_STATION_VERSION_NUMBER;
+ tsv->svl = S_RING_STATION_VERSION_NUMBER;
+
+ tsv->svv[0] = 0xe2; /* EBCDIC - S */
+ tsv->svv[1] = 0xd4; /* EBCDIC - M */
+ tsv->svv[2] = 0xc3; /* EBCDIC - C */
+ tsv->svv[3] = 0x40; /* EBCDIC - */
+ tsv->svv[4] = 0xe5; /* EBCDIC - V */
+ tsv->svv[5] = 0xF0 + (tp->microcode_version >> 4);
+ tsv->svv[6] = 0xF0 + (tp->microcode_version & 0x0f);
+ tsv->svv[7] = 0x40; /* EBCDIC - */
+ tsv->svv[8] = 0xe7; /* EBCDIC - X */
+
+ if(tp->extra_info & CHIP_REV_MASK)
+ tsv->svv[9] = 0xc5; /* EBCDIC - E */
+ else
+ tsv->svv[9] = 0xc4; /* EBCDIC - D */
+
+ return (0);
+}
+
+static int smctr_make_tx_status_code(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv, __u16 tx_fstatus)
+{
+ tsv->svi = TRANSMIT_STATUS_CODE;
+ tsv->svl = S_TRANSMIT_STATUS_CODE;
+
+ tsv->svv[0] = ((tx_fstatus & 0x0100 >> 6) || IBM_PASS_SOURCE_ADDR);
+
+ /* Stripped frame status of Transmitted Frame */
+ tsv->svv[1] = tx_fstatus & 0xff;
+
+ return (0);
+}
+
+static int smctr_make_upstream_neighbor_addr(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ smctr_get_upstream_neighbor_addr(dev);
+
+ tsv->svi = UPSTREAM_NEIGHBOR_ADDRESS;
+ tsv->svl = S_UPSTREAM_NEIGHBOR_ADDRESS;
+
+ tsv->svv[0] = MSB(tp->misc_command_data[0]);
+ tsv->svv[1] = LSB(tp->misc_command_data[0]);
+
+ tsv->svv[2] = MSB(tp->misc_command_data[1]);
+ tsv->svv[3] = LSB(tp->misc_command_data[1]);
+
+ tsv->svv[4] = MSB(tp->misc_command_data[2]);
+ tsv->svv[5] = LSB(tp->misc_command_data[2]);
+
+ return (0);
+}
+
+static int smctr_make_wrap_data(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+ tsv->svi = WRAP_DATA;
+ tsv->svl = S_WRAP_DATA;
+
+ return (0);
+}
+
+/*
+ * Open/initialize the board. This is called sometime after
+ * booting when the 'ifconfig' program is run.
+ *
+ * This routine should set everything up anew at each open, even
+ * 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 smctr_open(struct net_device *dev)
+{
+ int err;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_open\n", dev->name);
+
+ err = smctr_init_adapter(dev);
+ if(err < 0)
+ return (err);
+
+ return (err);
+}
+
+/* Interrupt driven open of Token card. */
+static int smctr_open_tr(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned long flags;
+ int err;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_open_tr\n", dev->name);
+
+ /* Now we can actually open the adapter. */
+ if(tp->status == OPEN)
+ return (0);
+ if(tp->status != INITIALIZED)
+ return (-1);
+
+ /* FIXME: it would work a lot better if we masked the irq sources
+ on the card here, then we could skip the locking and poll nicely */
+ spin_lock_irqsave(&tp->lock, flags);
+
+ smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+ if((err = smctr_issue_resume_rx_fcb_cmd(dev, (short)MAC_QUEUE)))
+ goto out;
+
+ if((err = smctr_issue_resume_rx_bdb_cmd(dev, (short)MAC_QUEUE)))
+ goto out;
+
+ if((err = smctr_issue_resume_rx_fcb_cmd(dev, (short)NON_MAC_QUEUE)))
+ goto out;
+
+ if((err = smctr_issue_resume_rx_bdb_cmd(dev, (short)NON_MAC_QUEUE)))
+ goto out;
+
+ tp->status = CLOSED;
+
+ /* Insert into the Ring or Enter Loopback Mode. */
+ if((tp->mode_bits & LOOPING_MODE_MASK) == LOOPBACK_MODE_1)
+ {
+ tp->status = CLOSED;
+
+ if(!(err = smctr_issue_trc_loopback_cmd(dev)))
+ {
+ if(!(err = smctr_wait_cmd(dev)))
+ tp->status = OPEN;
+ }
+
+ smctr_status_chg(dev);
+ }
+ else
+ {
+ if((tp->mode_bits & LOOPING_MODE_MASK) == LOOPBACK_MODE_2)
+ {
+ tp->status = CLOSED;
+ if(!(err = smctr_issue_tri_loopback_cmd(dev)))
+ {
+ if(!(err = smctr_wait_cmd(dev)))
+ tp->status = OPEN;
+ }
+
+ smctr_status_chg(dev);
+ }
+ else
+ {
+ if((tp->mode_bits & LOOPING_MODE_MASK)
+ == LOOPBACK_MODE_3)
+ {
+ tp->status = CLOSED;
+ if(!(err = smctr_lobe_media_test_cmd(dev)))
+ {
+ if(!(err = smctr_wait_cmd(dev)))
+ tp->status = OPEN;
+ }
+ smctr_status_chg(dev);
+ }
+ else
+ {
+ if(!(err = smctr_lobe_media_test(dev)))
+ err = smctr_issue_insert_cmd(dev);
+ else
+ {
+ if(err == LOBE_MEDIA_TEST_FAILED)
+ printk(KERN_WARNING "%s: Lobe Media Test Failure - Check cable?\n", dev->name);
+ }
+ }
+ }
+ }
+
+out:
+ spin_unlock_irqrestore(&tp->lock, flags);
+
+ return (err);
+}
+
+/* Check for a network adapter of this type,
+ * and return device structure if one exists.
+ */
+struct net_device __init *smctr_probe(int unit)
+{
+ struct net_device *dev = alloc_trdev(sizeof(struct net_local));
+ static const unsigned ports[] = {
+ 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, 0x300,
+ 0x320, 0x340, 0x360, 0x380, 0
+ };
+ const unsigned *port;
+ int err = 0;
+
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
+
+ SET_MODULE_OWNER(dev);
+
+ if (unit >= 0) {
+ sprintf(dev->name, "tr%d", unit);
+ netdev_boot_setup_check(dev);
+ }
+
+ if (dev->base_addr > 0x1ff) /* Check a single specified location. */
+ err = smctr_probe1(dev, dev->base_addr);
+ else if(dev->base_addr != 0) /* Don't probe at all. */
+ err =-ENXIO;
+ else {
+ for (port = ports; *port; port++) {
+ err = smctr_probe1(dev, *port);
+ if (!err)
+ break;
+ }
+ }
+ if (err)
+ goto out;
+ err = register_netdev(dev);
+ if (err)
+ goto out1;
+ return dev;
+out1:
+#ifdef CONFIG_MCA_LEGACY
+ { struct net_local *tp = netdev_priv(dev);
+ if (tp->slot_num)
+ mca_mark_as_unused(tp->slot_num);
+ }
+#endif
+ release_region(dev->base_addr, SMCTR_IO_EXTENT);
+ free_irq(dev->irq, dev);
+out:
+ free_netdev(dev);
+ return ERR_PTR(err);
+}
+
+
+static int __init smctr_probe1(struct net_device *dev, int ioaddr)
+{
+ static unsigned version_printed;
+ struct net_local *tp = netdev_priv(dev);
+ int err;
+ __u32 *ram;
+
+ if(smctr_debug && version_printed++ == 0)
+ printk(version);
+
+ spin_lock_init(&tp->lock);
+ dev->base_addr = ioaddr;
+
+ /* Actually detect an adapter now. */
+ err = smctr_chk_isa(dev);
+ if(err < 0)
+ {
+ if ((err = smctr_chk_mca(dev)) < 0) {
+ err = -ENODEV;
+ goto out;
+ }
+ }
+
+ tp = netdev_priv(dev);
+ dev->mem_start = tp->ram_base;
+ dev->mem_end = dev->mem_start + 0x10000;
+ ram = (__u32 *)phys_to_virt(dev->mem_start);
+ tp->ram_access = *(__u32 *)&ram;
+ tp->status = NOT_INITIALIZED;
+
+ err = smctr_load_firmware(dev);
+ if(err != UCODE_PRESENT && err != SUCCESS)
+ {
+ printk(KERN_ERR "%s: Firmware load failed (%d)\n", dev->name, err);
+ err = -EIO;
+ goto out;
+ }
+
+ /* Allow user to specify ring speed on module insert. */
+ if(ringspeed == 4)
+ tp->media_type = MEDIA_UTP_4;
+ else
+ tp->media_type = MEDIA_UTP_16;
+
+ printk(KERN_INFO "%s: %s %s at Io %#4x, Irq %d, Rom %#4x, Ram %#4x.\n",
+ dev->name, smctr_name, smctr_model,
+ (unsigned int)dev->base_addr,
+ dev->irq, tp->rom_base, tp->ram_base);
+
+ 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;
+ return (0);
+
+out:
+ return err;
+}
+
+static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
+ struct net_device *dev, __u16 rx_status)
+{
+ struct net_local *tp = netdev_priv(dev);
+ struct sk_buff *skb;
+ __u16 rcode, correlator;
+ int err = 0;
+ __u8 xframe = 1;
+ __u16 tx_fstatus;
+
+ rmf->vl = SWAP_BYTES(rmf->vl);
+ if(rx_status & FCB_RX_STATUS_DA_MATCHED)
+ {
+ switch(rmf->vc)
+ {
+ /* Received MAC Frames Processed by RS. */
+ case INIT:
+ if((rcode = smctr_rcv_init(dev, rmf, &correlator)) == HARDWARE_FAILED)
+ {
+ return (rcode);
+ }
+
+ if((err = smctr_send_rsp(dev, rmf, rcode,
+ correlator)))
+ {
+ return (err);
+ }
+ break;
+
+ case CHG_PARM:
+ if((rcode = smctr_rcv_chg_param(dev, rmf,
+ &correlator)) ==HARDWARE_FAILED)
+ {
+ return (rcode);
+ }
+
+ if((err = smctr_send_rsp(dev, rmf, rcode,
+ correlator)))
+ {
+ return (err);
+ }
+ break;
+
+ case RQ_ADDR:
+ if((rcode = smctr_rcv_rq_addr_state_attch(dev,
+ rmf, &correlator)) != POSITIVE_ACK)
+ {
+ if(rcode == HARDWARE_FAILED)
+ return (rcode);
+ else
+ return (smctr_send_rsp(dev, rmf,
+ rcode, correlator));
+ }
+
+ if((err = smctr_send_rpt_addr(dev, rmf,
+ correlator)))
+ {
+ return (err);
+ }
+ break;
+
+ case RQ_ATTCH:
+ if((rcode = smctr_rcv_rq_addr_state_attch(dev,
+ rmf, &correlator)) != POSITIVE_ACK)
+ {
+ if(rcode == HARDWARE_FAILED)
+ return (rcode);
+ else
+ return (smctr_send_rsp(dev, rmf,
+ rcode,
+ correlator));
+ }
+
+ if((err = smctr_send_rpt_attch(dev, rmf,
+ correlator)))
+ {
+ return (err);
+ }
+ break;
+
+ case RQ_STATE:
+ if((rcode = smctr_rcv_rq_addr_state_attch(dev,
+ rmf, &correlator)) != POSITIVE_ACK)
+ {
+ if(rcode == HARDWARE_FAILED)
+ return (rcode);
+ else
+ return (smctr_send_rsp(dev, rmf,
+ rcode,
+ correlator));
+ }
+
+ if((err = smctr_send_rpt_state(dev, rmf,
+ correlator)))
+ {
+ return (err);
+ }
+ break;
+
+ case TX_FORWARD:
+ if((rcode = smctr_rcv_tx_forward(dev, rmf))
+ != POSITIVE_ACK)
+ {
+ if(rcode == HARDWARE_FAILED)
+ return (rcode);
+ else
+ return (smctr_send_rsp(dev, rmf,
+ rcode,
+ correlator));
+ }
+
+ if((err = smctr_send_tx_forward(dev, rmf,
+ &tx_fstatus)) == HARDWARE_FAILED)
+ {
+ return (err);
+ }
+
+ if(err == A_FRAME_WAS_FORWARDED)
+ {
+ if((err = smctr_send_rpt_tx_forward(dev,
+ rmf, tx_fstatus))
+ == HARDWARE_FAILED)
+ {
+ return (err);
+ }
+ }
+ break;
+
+ /* Received MAC Frames Processed by CRS/REM/RPS. */
+ case RSP:
+ case RQ_INIT:
+ case RPT_NEW_MON:
+ case RPT_SUA_CHG:
+ case RPT_ACTIVE_ERR:
+ case RPT_NN_INCMP:
+ case RPT_ERROR:
+ case RPT_ATTCH:
+ case RPT_STATE:
+ case RPT_ADDR:
+ break;
+
+ /* Rcvd Att. MAC Frame (if RXATMAC set) or UNKNOWN */
+ default:
+ xframe = 0;
+ if(!(tp->receive_mask & ACCEPT_ATT_MAC_FRAMES))
+ {
+ rcode = smctr_rcv_unknown(dev, rmf,
+ &correlator);
+ if((err = smctr_send_rsp(dev, rmf,rcode,
+ correlator)))
+ {
+ return (err);
+ }
+ }
+
+ break;
+ }
+ }
+ else
+ {
+ /* 1. DA doesn't match (Promiscuous Mode).
+ * 2. Parse for Extended MAC Frame Type.
+ */
+ switch(rmf->vc)
+ {
+ case RSP:
+ case INIT:
+ case RQ_INIT:
+ case RQ_ADDR:
+ case RQ_ATTCH:
+ case RQ_STATE:
+ case CHG_PARM:
+ case RPT_ADDR:
+ case RPT_ERROR:
+ case RPT_ATTCH:
+ case RPT_STATE:
+ case RPT_NEW_MON:
+ case RPT_SUA_CHG:
+ case RPT_NN_INCMP:
+ case RPT_ACTIVE_ERR:
+ break;
+
+ default:
+ xframe = 0;
+ break;
+ }
+ }
+
+ /* NOTE: UNKNOWN MAC frames will NOT be passed up unless
+ * ACCEPT_ATT_MAC_FRAMES is set.
+ */
+ if(((tp->receive_mask & ACCEPT_ATT_MAC_FRAMES)
+ && (xframe == (__u8)0))
+ || ((tp->receive_mask & ACCEPT_EXT_MAC_FRAMES)
+ && (xframe == (__u8)1)))
+ {
+ rmf->vl = SWAP_BYTES(rmf->vl);
+
+ if (!(skb = dev_alloc_skb(size)))
+ return -ENOMEM;
+ skb->len = size;
+
+ /* Slide data into a sleek skb. */
+ skb_put(skb, skb->len);
+ memcpy(skb->data, rmf, skb->len);
+
+ /* Update Counters */
+ tp->MacStat.rx_packets++;
+ tp->MacStat.rx_bytes += skb->len;
+
+ /* Kick the packet on up. */
+ skb->dev = dev;
+ skb->protocol = tr_type_trans(skb, dev);
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+ err = 0;
+ }
+
+ return (err);
+}
+
+/* Adapter RAM test. Incremental word ODD boundary data test. */
+static int smctr_ram_memory_test(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ __u16 page, pages_of_ram, start_pattern = 0, word_pattern = 0,
+ word_read = 0, err_word = 0, err_pattern = 0;
+ unsigned int err_offset;
+ __u32 j, pword;
+ __u8 err = 0;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_ram_memory_test\n", dev->name);
+
+ start_pattern = 0x0001;
+ pages_of_ram = tp->ram_size / tp->ram_usable;
+ pword = tp->ram_access;
+
+ /* Incremental word ODD boundary test. */
+ for(page = 0; (page < pages_of_ram) && (~err);
+ page++, start_pattern += 0x8000)
+ {
+ smctr_set_page(dev, (__u8 *)(tp->ram_access
+ + (page * tp->ram_usable * 1024) + 1));
+ word_pattern = start_pattern;
+
+ for(j = 1; j < (__u32)(tp->ram_usable * 1024) - 1; j += 2)
+ *(__u16 *)(pword + j) = word_pattern++;
+
+ word_pattern = start_pattern;
+
+ for(j = 1; j < (__u32)(tp->ram_usable * 1024) - 1
+ && (~err); j += 2, word_pattern++)
+ {
+ word_read = *(__u16 *)(pword + j);
+ if(word_read != word_pattern)
+ {
+ err = (__u8)1;
+ err_offset = j;
+ err_word = word_read;
+ err_pattern = word_pattern;
+ return (RAM_TEST_FAILED);
+ }
+ }
+ }
+
+ /* Zero out memory. */
+ for(page = 0; page < pages_of_ram && (~err); page++)
+ {
+ smctr_set_page(dev, (__u8 *)(tp->ram_access
+ + (page * tp->ram_usable * 1024)));
+ word_pattern = 0;
+
+ for(j = 0; j < (__u32)tp->ram_usable * 1024; j +=2)
+ *(__u16 *)(pword + j) = word_pattern;
+
+ for(j =0; j < (__u32)tp->ram_usable * 1024
+ && (~err); j += 2)
+ {
+ word_read = *(__u16 *)(pword + j);
+ if(word_read != word_pattern)
+ {
+ err = (__u8)1;
+ err_offset = j;
+ err_word = word_read;
+ err_pattern = word_pattern;
+ return (RAM_TEST_FAILED);
+ }
+ }
+ }
+
+ smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+ return (0);
+}
+
+static int smctr_rcv_chg_param(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 *correlator)
+{
+ MAC_SUB_VECTOR *rsv;
+ signed short vlen;
+ __u16 rcode = POSITIVE_ACK;
+ unsigned int svectors = F_NO_SUB_VECTORS_FOUND;
+
+ /* This Frame can only come from a CRS */
+ if((rmf->dc_sc & SC_MASK) != SC_CRS)
+ return(E_INAPPROPRIATE_SOURCE_CLASS);
+
+ /* Remove MVID Length from total length. */
+ vlen = (signed short)rmf->vl - 4;
+
+ /* Point to First SVID */
+ rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
+
+ /* Search for Appropriate SVID's. */
+ while((vlen > 0) && (rcode == POSITIVE_ACK))
+ {
+ switch(rsv->svi)
+ {
+ case CORRELATOR:
+ svectors |= F_CORRELATOR;
+ rcode = smctr_set_corr(dev, rsv, correlator);
+ break;
+
+ case LOCAL_RING_NUMBER:
+ svectors |= F_LOCAL_RING_NUMBER;
+ rcode = smctr_set_local_ring_num(dev, rsv);
+ break;
+
+ case ASSIGN_PHYSICAL_DROP:
+ svectors |= F_ASSIGN_PHYSICAL_DROP;
+ rcode = smctr_set_phy_drop(dev, rsv);
+ break;
+
+ case ERROR_TIMER_VALUE:
+ svectors |= F_ERROR_TIMER_VALUE;
+ rcode = smctr_set_error_timer_value(dev, rsv);
+ break;
+
+ case AUTHORIZED_FUNCTION_CLASS:
+ svectors |= F_AUTHORIZED_FUNCTION_CLASS;
+ rcode = smctr_set_auth_funct_class(dev, rsv);
+ break;
+
+ case AUTHORIZED_ACCESS_PRIORITY:
+ svectors |= F_AUTHORIZED_ACCESS_PRIORITY;
+ rcode = smctr_set_auth_access_pri(dev, rsv);
+ break;
+
+ default:
+ rcode = E_SUB_VECTOR_UNKNOWN;
+ break;
+ }
+
+ /* Let Sender Know if SUM of SV length's is
+ * larger then length in MVID length field
+ */
+ if((vlen -= rsv->svl) < 0)
+ rcode = E_VECTOR_LENGTH_ERROR;
+
+ rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
+ }
+
+ if(rcode == POSITIVE_ACK)
+ {
+ /* Let Sender Know if MVID length field
+ * is larger then SUM of SV length's
+ */
+ if(vlen != 0)
+ rcode = E_VECTOR_LENGTH_ERROR;
+ else
+ {
+ /* Let Sender Know if Expected SVID Missing */
+ if((svectors & R_CHG_PARM) ^ R_CHG_PARM)
+ rcode = E_MISSING_SUB_VECTOR;
+ }
+ }
+
+ return (rcode);
+}
+
+static int smctr_rcv_init(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 *correlator)
+{
+ MAC_SUB_VECTOR *rsv;
+ signed short vlen;
+ __u16 rcode = POSITIVE_ACK;
+ unsigned int svectors = F_NO_SUB_VECTORS_FOUND;
+
+ /* This Frame can only come from a RPS */
+ if((rmf->dc_sc & SC_MASK) != SC_RPS)
+ return (E_INAPPROPRIATE_SOURCE_CLASS);
+
+ /* Remove MVID Length from total length. */
+ vlen = (signed short)rmf->vl - 4;
+
+ /* Point to First SVID */
+ rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
+
+ /* Search for Appropriate SVID's */
+ while((vlen > 0) && (rcode == POSITIVE_ACK))
+ {
+ switch(rsv->svi)
+ {
+ case CORRELATOR:
+ svectors |= F_CORRELATOR;
+ rcode = smctr_set_corr(dev, rsv, correlator);
+ break;
+
+ case LOCAL_RING_NUMBER:
+ svectors |= F_LOCAL_RING_NUMBER;
+ rcode = smctr_set_local_ring_num(dev, rsv);
+ break;
+
+ case ASSIGN_PHYSICAL_DROP:
+ svectors |= F_ASSIGN_PHYSICAL_DROP;
+ rcode = smctr_set_phy_drop(dev, rsv);
+ break;
+
+ case ERROR_TIMER_VALUE:
+ svectors |= F_ERROR_TIMER_VALUE;
+ rcode = smctr_set_error_timer_value(dev, rsv);
+ break;
+
+ default:
+ rcode = E_SUB_VECTOR_UNKNOWN;
+ break;
+ }
+
+ /* Let Sender Know if SUM of SV length's is
+ * larger then length in MVID length field
+ */
+ if((vlen -= rsv->svl) < 0)
+ rcode = E_VECTOR_LENGTH_ERROR;
+
+ rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
+ }
+
+ if(rcode == POSITIVE_ACK)
+ {
+ /* Let Sender Know if MVID length field
+ * is larger then SUM of SV length's
+ */
+ if(vlen != 0)
+ rcode = E_VECTOR_LENGTH_ERROR;
+ else
+ {
+ /* Let Sender Know if Expected SV Missing */
+ if((svectors & R_INIT) ^ R_INIT)
+ rcode = E_MISSING_SUB_VECTOR;
+ }
+ }
+
+ return (rcode);
+}
+
+static int smctr_rcv_tx_forward(struct net_device *dev, MAC_HEADER *rmf)
+{
+ MAC_SUB_VECTOR *rsv;
+ signed short vlen;
+ __u16 rcode = POSITIVE_ACK;
+ unsigned int svectors = F_NO_SUB_VECTORS_FOUND;
+
+ /* This Frame can only come from a CRS */
+ if((rmf->dc_sc & SC_MASK) != SC_CRS)
+ return (E_INAPPROPRIATE_SOURCE_CLASS);
+
+ /* Remove MVID Length from total length */
+ vlen = (signed short)rmf->vl - 4;
+
+ /* Point to First SVID */
+ rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
+
+ /* Search for Appropriate SVID's */
+ while((vlen > 0) && (rcode == POSITIVE_ACK))
+ {
+ switch(rsv->svi)
+ {
+ case FRAME_FORWARD:
+ svectors |= F_FRAME_FORWARD;
+ rcode = smctr_set_frame_forward(dev, rsv,
+ rmf->dc_sc);
+ break;
+
+ default:
+ rcode = E_SUB_VECTOR_UNKNOWN;
+ break;
+ }
+
+ /* Let Sender Know if SUM of SV length's is
+ * larger then length in MVID length field
+ */
+ if((vlen -= rsv->svl) < 0)
+ rcode = E_VECTOR_LENGTH_ERROR;
+
+ rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
+ }
+
+ if(rcode == POSITIVE_ACK)
+ {
+ /* Let Sender Know if MVID length field
+ * is larger then SUM of SV length's
+ */
+ if(vlen != 0)
+ rcode = E_VECTOR_LENGTH_ERROR;
+ else
+ {
+ /* Let Sender Know if Expected SV Missing */
+ if((svectors & R_TX_FORWARD) ^ R_TX_FORWARD)
+ rcode = E_MISSING_SUB_VECTOR;
+ }
+ }
+
+ return (rcode);
+}
+
+static int smctr_rcv_rq_addr_state_attch(struct net_device *dev,
+ MAC_HEADER *rmf, __u16 *correlator)
+{
+ MAC_SUB_VECTOR *rsv;
+ signed short vlen;
+ __u16 rcode = POSITIVE_ACK;
+ unsigned int svectors = F_NO_SUB_VECTORS_FOUND;
+
+ /* Remove MVID Length from total length */
+ vlen = (signed short)rmf->vl - 4;
+
+ /* Point to First SVID */
+ rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
+
+ /* Search for Appropriate SVID's */
+ while((vlen > 0) && (rcode == POSITIVE_ACK))
+ {
+ switch(rsv->svi)
+ {
+ case CORRELATOR:
+ svectors |= F_CORRELATOR;
+ rcode = smctr_set_corr(dev, rsv, correlator);
+ break;
+
+ default:
+ rcode = E_SUB_VECTOR_UNKNOWN;
+ break;
+ }
+
+ /* Let Sender Know if SUM of SV length's is
+ * larger then length in MVID length field
+ */
+ if((vlen -= rsv->svl) < 0)
+ rcode = E_VECTOR_LENGTH_ERROR;
+
+ rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
+ }
+
+ if(rcode == POSITIVE_ACK)
+ {
+ /* Let Sender Know if MVID length field
+ * is larger then SUM of SV length's
+ */
+ if(vlen != 0)
+ rcode = E_VECTOR_LENGTH_ERROR;
+ else
+ {
+ /* Let Sender Know if Expected SVID Missing */
+ if((svectors & R_RQ_ATTCH_STATE_ADDR)
+ ^ R_RQ_ATTCH_STATE_ADDR)
+ rcode = E_MISSING_SUB_VECTOR;
+ }
+ }
+
+ return (rcode);
+}
+
+static int smctr_rcv_unknown(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 *correlator)
+{
+ MAC_SUB_VECTOR *rsv;
+ signed short vlen;
+
+ *correlator = 0;
+
+ /* Remove MVID Length from total length */
+ vlen = (signed short)rmf->vl - 4;
+
+ /* Point to First SVID */
+ rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
+
+ /* Search for CORRELATOR for RSP to UNKNOWN */
+ while((vlen > 0) && (*correlator == 0))
+ {
+ switch(rsv->svi)
+ {
+ case CORRELATOR:
+ smctr_set_corr(dev, rsv, correlator);
+ break;
+
+ default:
+ break;
+ }
+
+ vlen -= rsv->svl;
+ rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
+ }
+
+ return (E_UNRECOGNIZED_VECTOR_ID);
+}
+
+/*
+ * Reset the 825 NIC and exit w:
+ * 1. The NIC reset cleared (non-reset state), halted and un-initialized.
+ * 2. TINT masked.
+ * 3. CBUSY masked.
+ * 4. TINT clear.
+ * 5. CBUSY clear.
+ */
+static int smctr_reset_adapter(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int ioaddr = dev->base_addr;
+
+ /* Reseting the NIC will put it in a halted and un-initialized state. */ smctr_set_trc_reset(ioaddr);
+ mdelay(200); /* ~2 ms */
+
+ smctr_clear_trc_reset(ioaddr);
+ mdelay(200); /* ~2 ms */
+
+ /* Remove any latched interrupts that occurred prior to reseting the
+ * adapter or possibily caused by line glitches due to the reset.
+ */
+ outb(tp->trc_mask | CSR_CLRTINT | CSR_CLRCBUSY, ioaddr + CSR);
+
+ return (0);
+}
+
+static int smctr_restart_tx_chain(struct net_device *dev, short queue)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int err = 0;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_restart_tx_chain\n", dev->name);
+
+ if(tp->num_tx_fcbs_used[queue] != 0
+ && tp->tx_queue_status[queue] == NOT_TRANSMITING)
+ {
+ tp->tx_queue_status[queue] = TRANSMITING;
+ err = smctr_issue_resume_tx_fcb_cmd(dev, queue);
+ }
+
+ return (err);
+}
+
+static int smctr_ring_status_chg(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_ring_status_chg\n", dev->name);
+
+ /* Check for ring_status_flag: whenever MONITOR_STATE_BIT
+ * Bit is set, check value of monitor_state, only then we
+ * enable and start transmit/receive timeout (if and only
+ * if it is MS_ACTIVE_MONITOR_STATE or MS_STANDBY_MONITOR_STATE)
+ */
+ if(tp->ring_status_flags == MONITOR_STATE_CHANGED)
+ {
+ if((tp->monitor_state == MS_ACTIVE_MONITOR_STATE)
+ || (tp->monitor_state == MS_STANDBY_MONITOR_STATE))
+ {
+ tp->monitor_state_ready = 1;
+ }
+ else
+ {
+ /* if adapter is NOT in either active monitor
+ * or standby monitor state => Disable
+ * transmit/receive timeout.
+ */
+ tp->monitor_state_ready = 0;
+
+ /* Ring speed problem, switching to auto mode. */
+ if(tp->monitor_state == MS_MONITOR_FSM_INACTIVE
+ && !tp->cleanup)
+ {
+ printk(KERN_INFO "%s: Incorrect ring speed switching.\n",
+ dev->name);
+ smctr_set_ring_speed(dev);
+ }
+ }
+ }
+
+ if(!(tp->ring_status_flags & RING_STATUS_CHANGED))
+ return (0);
+
+ switch(tp->ring_status)
+ {
+ case RING_RECOVERY:
+ printk(KERN_INFO "%s: Ring Recovery\n", dev->name);
+ tp->current_ring_status |= RING_RECOVERY;
+ break;
+
+ case SINGLE_STATION:
+ printk(KERN_INFO "%s: Single Statinon\n", dev->name);
+ tp->current_ring_status |= SINGLE_STATION;
+ break;
+
+ case COUNTER_OVERFLOW:
+ printk(KERN_INFO "%s: Counter Overflow\n", dev->name);
+ tp->current_ring_status |= COUNTER_OVERFLOW;
+ break;
+
+ case REMOVE_RECEIVED:
+ printk(KERN_INFO "%s: Remove Received\n", dev->name);
+ tp->current_ring_status |= REMOVE_RECEIVED;
+ break;
+
+ case AUTO_REMOVAL_ERROR:
+ printk(KERN_INFO "%s: Auto Remove Error\n", dev->name);
+ tp->current_ring_status |= AUTO_REMOVAL_ERROR;
+ break;
+
+ case LOBE_WIRE_FAULT:
+ printk(KERN_INFO "%s: Lobe Wire Fault\n", dev->name);
+ tp->current_ring_status |= LOBE_WIRE_FAULT;
+ break;
+
+ case TRANSMIT_BEACON:
+ printk(KERN_INFO "%s: Transmit Beacon\n", dev->name);
+ tp->current_ring_status |= TRANSMIT_BEACON;
+ break;
+
+ case SOFT_ERROR:
+ printk(KERN_INFO "%s: Soft Error\n", dev->name);
+ tp->current_ring_status |= SOFT_ERROR;
+ break;
+
+ case HARD_ERROR:
+ printk(KERN_INFO "%s: Hard Error\n", dev->name);
+ tp->current_ring_status |= HARD_ERROR;
+ break;
+
+ case SIGNAL_LOSS:
+ printk(KERN_INFO "%s: Signal Loss\n", dev->name);
+ tp->current_ring_status |= SIGNAL_LOSS;
+ break;
+
+ default:
+ printk(KERN_INFO "%s: Unknown ring status change\n",
+ dev->name);
+ break;
+ }
+
+ return (0);
+}
+
+static int smctr_rx_frame(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ __u16 queue, status, rx_size, err = 0;
+ __u8 *pbuff;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_rx_frame\n", dev->name);
+
+ queue = tp->receive_queue_number;
+
+ while((status = tp->rx_fcb_curr[queue]->frame_status) != SUCCESS)
+ {
+ err = HARDWARE_FAILED;
+
+ if(((status & 0x007f) == 0)
+ || ((tp->receive_mask & ACCEPT_ERR_PACKETS) != 0))
+ {
+ /* frame length less the CRC (4 bytes) + FS (1 byte) */
+ rx_size = tp->rx_fcb_curr[queue]->frame_length - 5;
+
+ pbuff = smctr_get_rx_pointer(dev, queue);
+
+ smctr_set_page(dev, pbuff);
+ smctr_disable_16bit(dev);
+
+ /* pbuff points to addr within one page */
+ pbuff = (__u8 *)PAGE_POINTER(pbuff);
+
+ if(queue == NON_MAC_QUEUE)
+ {
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(rx_size);
+ if (skb) {
+ skb_put(skb, rx_size);
+
+ memcpy(skb->data, pbuff, rx_size);
+
+ /* Update Counters */
+ tp->MacStat.rx_packets++;
+ tp->MacStat.rx_bytes += skb->len;
+
+ /* Kick the packet on up. */
+ skb->dev = dev;
+ skb->protocol = tr_type_trans(skb, dev);
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+ } else {
+ }
+ }
+ else
+ smctr_process_rx_packet((MAC_HEADER *)pbuff,
+ rx_size, dev, status);
+ }
+
+ smctr_enable_16bit(dev);
+ smctr_set_page(dev, (__u8 *)tp->ram_access);
+ smctr_update_rx_chain(dev, queue);
+
+ if(err != SUCCESS)
+ break;
+ }
+
+ return (err);
+}
+
+static int smctr_send_dat(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int i, err;
+ MAC_HEADER *tmf;
+ FCBlock *fcb;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_send_dat\n", dev->name);
+
+ if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE,
+ sizeof(MAC_HEADER))) == (FCBlock *)(-1L))
+ {
+ return (OUT_OF_RESOURCES);
+ }
+
+ /* Initialize DAT Data Fields. */
+ tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+ tmf->ac = MSB(AC_FC_DAT);
+ tmf->fc = LSB(AC_FC_DAT);
+
+ for(i = 0; i < 6; i++)
+ {
+ tmf->sa[i] = dev->dev_addr[i];
+ tmf->da[i] = dev->dev_addr[i];
+
+ }
+
+ tmf->vc = DAT;
+ tmf->dc_sc = DC_RS | SC_RS;
+ tmf->vl = 4;
+ tmf->vl = SWAP_BYTES(tmf->vl);
+
+ /* Start Transmit. */
+ if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
+ return (err);
+
+ /* Wait for Transmit to Complete */
+ for(i = 0; i < 10000; i++)
+ {
+ if(fcb->frame_status & FCB_COMMAND_DONE)
+ break;
+ mdelay(1);
+ }
+
+ /* Check if GOOD frame Tx'ed. */
+ if(!(fcb->frame_status & FCB_COMMAND_DONE)
+ || fcb->frame_status & (FCB_TX_STATUS_E | FCB_TX_AC_BITS))
+ {
+ return (INITIALIZE_FAILED);
+ }
+
+ /* De-allocated Tx FCB and Frame Buffer
+ * The FCB must be de-allocated manually if executing with
+ * interrupts disabled, other wise the ISR (LM_Service_Events)
+ * will de-allocate it when the interrupt occurs.
+ */
+ tp->tx_queue_status[MAC_QUEUE] = NOT_TRANSMITING;
+ smctr_update_tx_chain(dev, fcb, MAC_QUEUE);
+
+ 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
+ */
+static int smctr_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_send_packet\n", dev->name);
+
+ /*
+ * Block a transmit overlap
+ */
+
+ netif_stop_queue(dev);
+
+ if(tp->QueueSkb == 0)
+ return (1); /* Return with tbusy set: queue full */
+
+ tp->QueueSkb--;
+ skb_queue_tail(&tp->SendSkbQueue, skb);
+ smctr_hardware_send_packet(dev, tp);
+ if(tp->QueueSkb > 0)
+ netif_wake_queue(dev);
+
+ return (0);
+}
+
+static int smctr_send_lobe_media_test(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ MAC_SUB_VECTOR *tsv;
+ MAC_HEADER *tmf;
+ FCBlock *fcb;
+ __u32 i;
+ int err;
+
+ if(smctr_debug > 15)
+ printk(KERN_DEBUG "%s: smctr_send_lobe_media_test\n", dev->name);
+
+ if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(struct trh_hdr)
+ + S_WRAP_DATA + S_WRAP_DATA)) == (FCBlock *)(-1L))
+ {
+ return (OUT_OF_RESOURCES);
+ }
+
+ /* Initialize DAT Data Fields. */
+ tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+ tmf->ac = MSB(AC_FC_LOBE_MEDIA_TEST);
+ tmf->fc = LSB(AC_FC_LOBE_MEDIA_TEST);
+
+ for(i = 0; i < 6; i++)
+ {
+ tmf->da[i] = 0;
+ tmf->sa[i] = dev->dev_addr[i];
+ }
+
+ tmf->vc = LOBE_MEDIA_TEST;
+ tmf->dc_sc = DC_RS | SC_RS;
+ tmf->vl = 4;
+
+ tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+ smctr_make_wrap_data(dev, tsv);
+ tmf->vl += tsv->svl;
+
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_wrap_data(dev, tsv);
+ tmf->vl += tsv->svl;
+
+ /* Start Transmit. */
+ tmf->vl = SWAP_BYTES(tmf->vl);
+ if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
+ return (err);
+
+ /* Wait for Transmit to Complete. (10 ms). */
+ for(i=0; i < 10000; i++)
+ {
+ if(fcb->frame_status & FCB_COMMAND_DONE)
+ break;
+ mdelay(1);
+ }
+
+ /* Check if GOOD frame Tx'ed */
+ if(!(fcb->frame_status & FCB_COMMAND_DONE)
+ || fcb->frame_status & (FCB_TX_STATUS_E | FCB_TX_AC_BITS))
+ {
+ return (LOBE_MEDIA_TEST_FAILED);
+ }
+
+ /* De-allocated Tx FCB and Frame Buffer
+ * The FCB must be de-allocated manually if executing with
+ * interrupts disabled, other wise the ISR (LM_Service_Events)
+ * will de-allocate it when the interrupt occurs.
+ */
+ tp->tx_queue_status[MAC_QUEUE] = NOT_TRANSMITING;
+ smctr_update_tx_chain(dev, fcb, MAC_QUEUE);
+
+ return (0);
+}
+
+static int smctr_send_rpt_addr(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 correlator)
+{
+ MAC_HEADER *tmf;
+ MAC_SUB_VECTOR *tsv;
+ FCBlock *fcb;
+
+ if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+ + S_CORRELATOR + S_PHYSICAL_DROP + S_UPSTREAM_NEIGHBOR_ADDRESS
+ + S_ADDRESS_MODIFER + S_GROUP_ADDRESS + S_FUNCTIONAL_ADDRESS))
+ == (FCBlock *)(-1L))
+ {
+ return (0);
+ }
+
+ tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+ tmf->vc = RPT_ADDR;
+ tmf->dc_sc = (rmf->dc_sc & SC_MASK) << 4;
+ tmf->vl = 4;
+
+ smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RPT_ADDR);
+
+ tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+ smctr_make_corr(dev, tsv, correlator);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_phy_drop_num(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_upstream_neighbor_addr(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_addr_mod(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_group_addr(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_funct_addr(dev, tsv);
+
+ tmf->vl += tsv->svl;
+
+ /* Subtract out MVID and MVL which is
+ * include in both vl and MAC_HEADER
+ */
+/* fcb->frame_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+ fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+*/
+ tmf->vl = SWAP_BYTES(tmf->vl);
+
+ return (smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+}
+
+static int smctr_send_rpt_attch(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 correlator)
+{
+ MAC_HEADER *tmf;
+ MAC_SUB_VECTOR *tsv;
+ FCBlock *fcb;
+
+ if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+ + S_CORRELATOR + S_PRODUCT_INSTANCE_ID + S_FUNCTIONAL_ADDRESS
+ + S_AUTHORIZED_FUNCTION_CLASS + S_AUTHORIZED_ACCESS_PRIORITY))
+ == (FCBlock *)(-1L))
+ {
+ return (0);
+ }
+
+ tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+ tmf->vc = RPT_ATTCH;
+ tmf->dc_sc = (rmf->dc_sc & SC_MASK) << 4;
+ tmf->vl = 4;
+
+ smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RPT_ATTCH);
+
+ tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+ smctr_make_corr(dev, tsv, correlator);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_product_id(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_funct_addr(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_auth_funct_class(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_access_pri(dev, tsv);
+
+ tmf->vl += tsv->svl;
+
+ /* Subtract out MVID and MVL which is
+ * include in both vl and MAC_HEADER
+ */
+/* fcb->frame_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+ fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+*/
+ tmf->vl = SWAP_BYTES(tmf->vl);
+
+ return (smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+}
+
+static int smctr_send_rpt_state(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 correlator)
+{
+ MAC_HEADER *tmf;
+ MAC_SUB_VECTOR *tsv;
+ FCBlock *fcb;
+
+ if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+ + S_CORRELATOR + S_RING_STATION_VERSION_NUMBER
+ + S_RING_STATION_STATUS + S_STATION_IDENTIFER))
+ == (FCBlock *)(-1L))
+ {
+ return (0);
+ }
+
+ tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+ tmf->vc = RPT_STATE;
+ tmf->dc_sc = (rmf->dc_sc & SC_MASK) << 4;
+ tmf->vl = 4;
+
+ smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RPT_STATE);
+
+ tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+ smctr_make_corr(dev, tsv, correlator);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_ring_station_version(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_ring_station_status(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_station_id(dev, tsv);
+
+ tmf->vl += tsv->svl;
+
+ /* Subtract out MVID and MVL which is
+ * include in both vl and MAC_HEADER
+ */
+/* fcb->frame_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+ fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+*/
+ tmf->vl = SWAP_BYTES(tmf->vl);
+
+ return (smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+}
+
+static int smctr_send_rpt_tx_forward(struct net_device *dev,
+ MAC_HEADER *rmf, __u16 tx_fstatus)
+{
+ MAC_HEADER *tmf;
+ MAC_SUB_VECTOR *tsv;
+ FCBlock *fcb;
+
+ if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+ + S_TRANSMIT_STATUS_CODE)) == (FCBlock *)(-1L))
+ {
+ return (0);
+ }
+
+ tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+ tmf->vc = RPT_TX_FORWARD;
+ tmf->dc_sc = (rmf->dc_sc & SC_MASK) << 4;
+ tmf->vl = 4;
+
+ smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RPT_TX_FORWARD);
+
+ tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+ smctr_make_tx_status_code(dev, tsv, tx_fstatus);
+
+ tmf->vl += tsv->svl;
+
+ /* Subtract out MVID and MVL which is
+ * include in both vl and MAC_HEADER
+ */
+/* fcb->frame_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+ fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+*/
+ tmf->vl = SWAP_BYTES(tmf->vl);
+
+ return(smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+}
+
+static int smctr_send_rsp(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 rcode, __u16 correlator)
+{
+ MAC_HEADER *tmf;
+ MAC_SUB_VECTOR *tsv;
+ FCBlock *fcb;
+
+ if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+ + S_CORRELATOR + S_RESPONSE_CODE)) == (FCBlock *)(-1L))
+ {
+ return (0);
+ }
+
+ tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+ tmf->vc = RSP;
+ tmf->dc_sc = (rmf->dc_sc & SC_MASK) << 4;
+ tmf->vl = 4;
+
+ smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RSP);
+
+ tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+ smctr_make_corr(dev, tsv, correlator);
+
+ return (0);
+}
+
+static int smctr_send_rq_init(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ MAC_HEADER *tmf;
+ MAC_SUB_VECTOR *tsv;
+ FCBlock *fcb;
+ unsigned int i, count = 0;
+ __u16 fstatus;
+ int err;
+
+ do {
+ if(((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+ + S_PRODUCT_INSTANCE_ID + S_UPSTREAM_NEIGHBOR_ADDRESS
+ + S_RING_STATION_VERSION_NUMBER + S_ADDRESS_MODIFER))
+ == (FCBlock *)(-1L)))
+ {
+ return (0);
+ }
+
+ tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+ tmf->vc = RQ_INIT;
+ tmf->dc_sc = DC_RPS | SC_RS;
+ tmf->vl = 4;
+
+ smctr_make_8025_hdr(dev, NULL, tmf, AC_FC_RQ_INIT);
+
+ tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+ smctr_make_product_id(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_upstream_neighbor_addr(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_ring_station_version(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_addr_mod(dev, tsv);
+
+ tmf->vl += tsv->svl;
+
+ /* Subtract out MVID and MVL which is
+ * include in both vl and MAC_HEADER
+ */
+/* fcb->frame_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+ fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+*/
+ tmf->vl = SWAP_BYTES(tmf->vl);
+
+ if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
+ return (err);
+
+ /* Wait for Transmit to Complete */
+ for(i = 0; i < 10000; i++)
+ {
+ if(fcb->frame_status & FCB_COMMAND_DONE)
+ break;
+ mdelay(1);
+ }
+
+ /* Check if GOOD frame Tx'ed */
+ fstatus = fcb->frame_status;
+
+ if(!(fstatus & FCB_COMMAND_DONE))
+ return (HARDWARE_FAILED);
+
+ if(!(fstatus & FCB_TX_STATUS_E))
+ count++;
+
+ /* De-allocated Tx FCB and Frame Buffer
+ * The FCB must be de-allocated manually if executing with
+ * interrupts disabled, other wise the ISR (LM_Service_Events)
+ * will de-allocate it when the interrupt occurs.
+ */
+ tp->tx_queue_status[MAC_QUEUE] = NOT_TRANSMITING;
+ smctr_update_tx_chain(dev, fcb, MAC_QUEUE);
+ } while(count < 4 && ((fstatus & FCB_TX_AC_BITS) ^ FCB_TX_AC_BITS));
+
+ return (smctr_join_complete_state(dev));
+}
+
+static int smctr_send_tx_forward(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 *tx_fstatus)
+{
+ struct net_local *tp = netdev_priv(dev);
+ FCBlock *fcb;
+ unsigned int i;
+ int err;
+
+ /* Check if this is the END POINT of the Transmit Forward Chain. */
+ if(rmf->vl <= 18)
+ return (0);
+
+ /* Allocate Transmit FCB only by requesting 0 bytes
+ * of data buffer.
+ */
+ if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, 0)) == (FCBlock *)(-1L))
+ return (0);
+
+ /* Set pointer to Transmit Frame Buffer to the data
+ * portion of the received TX Forward frame, making
+ * sure to skip over the Vector Code (vc) and Vector
+ * length (vl).
+ */
+ fcb->bdb_ptr->trc_data_block_ptr = TRC_POINTER((__u32)rmf
+ + sizeof(MAC_HEADER) + 2);
+ fcb->bdb_ptr->data_block_ptr = (__u16 *)((__u32)rmf
+ + sizeof(MAC_HEADER) + 2);
+
+ fcb->frame_length = rmf->vl - 4 - 2;
+ fcb->bdb_ptr->buffer_length = rmf->vl - 4 - 2;
+
+ if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
+ return (err);
+
+ /* Wait for Transmit to Complete */
+ for(i = 0; i < 10000; i++)
+ {
+ if(fcb->frame_status & FCB_COMMAND_DONE)
+ break;
+ mdelay(1);
+ }
+
+ /* Check if GOOD frame Tx'ed */
+ if(!(fcb->frame_status & FCB_COMMAND_DONE))
+ {
+ if((err = smctr_issue_resume_tx_fcb_cmd(dev, MAC_QUEUE)))
+ return (err);
+
+ for(i = 0; i < 10000; i++)
+ {
+ if(fcb->frame_status & FCB_COMMAND_DONE)
+ break;
+ mdelay(1);
+ }
+
+ if(!(fcb->frame_status & FCB_COMMAND_DONE))
+ return (HARDWARE_FAILED);
+ }
+
+ *tx_fstatus = fcb->frame_status;
+
+ return (A_FRAME_WAS_FORWARDED);
+}
+
+static int smctr_set_auth_access_pri(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ if(rsv->svl != S_AUTHORIZED_ACCESS_PRIORITY)
+ return (E_SUB_VECTOR_LENGTH_ERROR);
+
+ tp->authorized_access_priority = (rsv->svv[0] << 8 | rsv->svv[1]);
+
+ return (POSITIVE_ACK);
+}
+
+static int smctr_set_auth_funct_class(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ if(rsv->svl != S_AUTHORIZED_FUNCTION_CLASS)
+ return (E_SUB_VECTOR_LENGTH_ERROR);
+
+ tp->authorized_function_classes = (rsv->svv[0] << 8 | rsv->svv[1]);
+
+ return (POSITIVE_ACK);
+}
+
+static int smctr_set_corr(struct net_device *dev, MAC_SUB_VECTOR *rsv,
+ __u16 *correlator)
+{
+ if(rsv->svl != S_CORRELATOR)
+ return (E_SUB_VECTOR_LENGTH_ERROR);
+
+ *correlator = (rsv->svv[0] << 8 | rsv->svv[1]);
+
+ return (POSITIVE_ACK);
+}
+
+static int smctr_set_error_timer_value(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv)
+{
+ __u16 err_tval;
+ int err;
+
+ if(rsv->svl != S_ERROR_TIMER_VALUE)
+ return (E_SUB_VECTOR_LENGTH_ERROR);
+
+ err_tval = (rsv->svv[0] << 8 | rsv->svv[1])*10;
+
+ smctr_issue_write_word_cmd(dev, RW_TER_THRESHOLD, &err_tval);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ return (POSITIVE_ACK);
+}
+
+static int smctr_set_frame_forward(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv, __u8 dc_sc)
+{
+ if((rsv->svl < 2) || (rsv->svl > S_FRAME_FORWARD))
+ return (E_SUB_VECTOR_LENGTH_ERROR);
+
+ if((dc_sc & DC_MASK) != DC_CRS)
+ {
+ if(rsv->svl >= 2 && rsv->svl < 20)
+ return (E_TRANSMIT_FORWARD_INVALID);
+
+ if((rsv->svv[0] != 0) || (rsv->svv[1] != 0))
+ return (E_TRANSMIT_FORWARD_INVALID);
+ }
+
+ return (POSITIVE_ACK);
+}
+
+static int smctr_set_local_ring_num(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ if(rsv->svl != S_LOCAL_RING_NUMBER)
+ return (E_SUB_VECTOR_LENGTH_ERROR);
+
+ if(tp->ptr_local_ring_num)
+ *(__u16 *)(tp->ptr_local_ring_num)
+ = (rsv->svv[0] << 8 | rsv->svv[1]);
+
+ return (POSITIVE_ACK);
+}
+
+static unsigned short smctr_set_ctrl_attention(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int ioaddr = dev->base_addr;
+
+ if(tp->bic_type == BIC_585_CHIP)
+ outb((tp->trc_mask | HWR_CA), ioaddr + HWR);
+ else
+ {
+ outb((tp->trc_mask | CSR_CA), ioaddr + CSR);
+ outb(tp->trc_mask, ioaddr + CSR);
+ }
+
+ return (0);
+}
+
+static void smctr_set_multicast_list(struct net_device *dev)
+{
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_set_multicast_list\n", dev->name);
+
+ return;
+}
+
+static int smctr_set_page(struct net_device *dev, __u8 *buf)
+{
+ struct net_local *tp = netdev_priv(dev);
+ __u8 amask;
+ __u32 tptr;
+
+ tptr = (__u32)buf - (__u32)tp->ram_access;
+ amask = (__u8)((tptr & PR_PAGE_MASK) >> 8);
+ outb(amask, dev->base_addr + PR);
+
+ return (0);
+}
+
+static int smctr_set_phy_drop(struct net_device *dev, MAC_SUB_VECTOR *rsv)
+{
+ int err;
+
+ if(rsv->svl != S_PHYSICAL_DROP)
+ return (E_SUB_VECTOR_LENGTH_ERROR);
+
+ smctr_issue_write_byte_cmd(dev, RW_PHYSICAL_DROP_NUMBER, &rsv->svv[0]);
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ return (POSITIVE_ACK);
+}
+
+/* Reset the ring speed to the opposite of what it was. This auto-pilot
+ * mode requires a complete reset and re-init of the adapter.
+ */
+static int smctr_set_ring_speed(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int err;
+
+ if(tp->media_type == MEDIA_UTP_16)
+ tp->media_type = MEDIA_UTP_4;
+ else
+ tp->media_type = MEDIA_UTP_16;
+
+ smctr_enable_16bit(dev);
+
+ /* Re-Initialize adapter's internal registers */
+ smctr_reset_adapter(dev);
+
+ if((err = smctr_init_card_real(dev)))
+ return (err);
+
+ smctr_enable_bic_int(dev);
+
+ if((err = smctr_issue_enable_int_cmd(dev, TRC_INTERRUPT_ENABLE_MASK)))
+ return (err);
+
+ smctr_disable_16bit(dev);
+
+ return (0);
+}
+
+static int smctr_set_rx_look_ahead(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ __u16 sword, rword;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_set_rx_look_ahead_flag\n", dev->name);
+
+ tp->adapter_flags &= ~(FORCED_16BIT_MODE);
+ tp->adapter_flags |= RX_VALID_LOOKAHEAD;
+
+ if(tp->adapter_bus == BUS_ISA16_TYPE)
+ {
+ sword = *((__u16 *)(tp->ram_access));
+ *((__u16 *)(tp->ram_access)) = 0x1234;
+
+ smctr_disable_16bit(dev);
+ rword = *((__u16 *)(tp->ram_access));
+ smctr_enable_16bit(dev);
+
+ if(rword != 0x1234)
+ tp->adapter_flags |= FORCED_16BIT_MODE;
+
+ *((__u16 *)(tp->ram_access)) = sword;
+ }
+
+ return (0);
+}
+
+static int smctr_set_trc_reset(int ioaddr)
+{
+ __u8 r;
+
+ r = inb(ioaddr + MSR);
+ outb(MSR_RST | r, ioaddr + MSR);
+
+ return (0);
+}
+
+/*
+ * This function can be called if the adapter is busy or not.
+ */
+static int smctr_setup_single_cmd(struct net_device *dev,
+ __u16 command, __u16 subcommand)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int err;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_setup_single_cmd\n", dev->name);
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ if((err = (unsigned int)smctr_wait_cmd(dev)))
+ return (err);
+
+ tp->acb_head->cmd_done_status = 0;
+ tp->acb_head->cmd = command;
+ tp->acb_head->subcmd = subcommand;
+
+ err = smctr_issue_resume_acb_cmd(dev);
+
+ return (err);
+}
+
+/*
+ * This function can not be called with the adapter busy.
+ */
+static int smctr_setup_single_cmd_w_data(struct net_device *dev,
+ __u16 command, __u16 subcommand)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ tp->acb_head->cmd_done_status = ACB_COMMAND_NOT_DONE;
+ tp->acb_head->cmd = command;
+ tp->acb_head->subcmd = subcommand;
+ tp->acb_head->data_offset_lo
+ = (__u16)TRC_POINTER(tp->misc_command_data);
+
+ return(smctr_issue_resume_acb_cmd(dev));
+}
+
+static char *smctr_malloc(struct net_device *dev, __u16 size)
+{
+ struct net_local *tp = netdev_priv(dev);
+ char *m;
+
+ m = (char *)(tp->ram_access + tp->sh_mem_used);
+ tp->sh_mem_used += (__u32)size;
+
+ return (m);
+}
+
+static int smctr_status_chg(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_status_chg\n", dev->name);
+
+ switch(tp->status)
+ {
+ case OPEN:
+ break;
+
+ case CLOSED:
+ break;
+
+ /* Interrupt driven open() completion. XXX */
+ case INITIALIZED:
+ tp->group_address_0 = 0;
+ tp->group_address[0] = 0;
+ tp->group_address[1] = 0;
+ tp->functional_address_0 = 0;
+ tp->functional_address[0] = 0;
+ tp->functional_address[1] = 0;
+ smctr_open_tr(dev);
+ break;
+
+ default:
+ printk(KERN_INFO "%s: status change unknown %x\n",
+ dev->name, tp->status);
+ break;
+ }
+
+ return (0);
+}
+
+static int smctr_trc_send_packet(struct net_device *dev, FCBlock *fcb,
+ __u16 queue)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int err = 0;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_trc_send_packet\n", dev->name);
+
+ fcb->info = FCB_CHAIN_END | FCB_ENABLE_TFS;
+ if(tp->num_tx_fcbs[queue] != 1)
+ fcb->back_ptr->info = FCB_INTERRUPT_ENABLE | FCB_ENABLE_TFS;
+
+ if(tp->tx_queue_status[queue] == NOT_TRANSMITING)
+ {
+ tp->tx_queue_status[queue] = TRANSMITING;
+ err = smctr_issue_resume_tx_fcb_cmd(dev, queue);
+ }
+
+ return (err);
+}
+
+static __u16 smctr_tx_complete(struct net_device *dev, __u16 queue)
+{
+ struct net_local *tp = netdev_priv(dev);
+ __u16 status, err = 0;
+ int cstatus;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_tx_complete\n", dev->name);
+
+ while((status = tp->tx_fcb_end[queue]->frame_status) != SUCCESS)
+ {
+ if(status & 0x7e00 )
+ {
+ err = HARDWARE_FAILED;
+ break;
+ }
+
+ if((err = smctr_update_tx_chain(dev, tp->tx_fcb_end[queue],
+ queue)) != SUCCESS)
+ break;
+
+ smctr_disable_16bit(dev);
+
+ if(tp->mode_bits & UMAC)
+ {
+ if(!(status & (FCB_TX_STATUS_AR1 | FCB_TX_STATUS_AR2)))
+ cstatus = NO_SUCH_DESTINATION;
+ else
+ {
+ if(!(status & (FCB_TX_STATUS_CR1 | FCB_TX_STATUS_CR2)))
+ cstatus = DEST_OUT_OF_RESOURCES;
+ else
+ {
+ if(status & FCB_TX_STATUS_E)
+ cstatus = MAX_COLLISIONS;
+ else
+ cstatus = SUCCESS;
+ }
+ }
+ }
+ else
+ cstatus = SUCCESS;
+
+ if(queue == BUG_QUEUE)
+ err = SUCCESS;
+
+ smctr_enable_16bit(dev);
+ if(err != SUCCESS)
+ break;
+ }
+
+ return (err);
+}
+
+static unsigned short smctr_tx_move_frame(struct net_device *dev,
+ struct sk_buff *skb, __u8 *pbuff, unsigned int bytes)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int ram_usable;
+ __u32 flen, len, offset = 0;
+ __u8 *frag, *page;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_tx_move_frame\n", dev->name);
+
+ ram_usable = ((unsigned int)tp->ram_usable) << 10;
+ frag = skb->data;
+ flen = skb->len;
+
+ while(flen > 0 && bytes > 0)
+ {
+ smctr_set_page(dev, pbuff);
+
+ offset = SMC_PAGE_OFFSET(pbuff);
+
+ if(offset + flen > ram_usable)
+ len = ram_usable - offset;
+ else
+ len = flen;
+
+ if(len > bytes)
+ len = bytes;
+
+ page = (char *) (offset + tp->ram_access);
+ memcpy(page, frag, len);
+
+ flen -=len;
+ bytes -= len;
+ frag += len;
+ pbuff += len;
+ }
+
+ return (0);
+}
+
+/* Update the error statistic counters for this adapter. */
+static int smctr_update_err_stats(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ struct tr_statistics *tstat = &tp->MacStat;
+
+ if(tstat->internal_errors)
+ tstat->internal_errors
+ += *(tp->misc_command_data + 0) & 0x00ff;
+
+ if(tstat->line_errors)
+ tstat->line_errors += *(tp->misc_command_data + 0) >> 8;
+
+ if(tstat->A_C_errors)
+ tstat->A_C_errors += *(tp->misc_command_data + 1) & 0x00ff;
+
+ if(tstat->burst_errors)
+ tstat->burst_errors += *(tp->misc_command_data + 1) >> 8;
+
+ if(tstat->abort_delimiters)
+ tstat->abort_delimiters += *(tp->misc_command_data + 2) >> 8;
+
+ if(tstat->recv_congest_count)
+ tstat->recv_congest_count
+ += *(tp->misc_command_data + 3) & 0x00ff;
+
+ if(tstat->lost_frames)
+ tstat->lost_frames
+ += *(tp->misc_command_data + 3) >> 8;
+
+ if(tstat->frequency_errors)
+ tstat->frequency_errors += *(tp->misc_command_data + 4) & 0x00ff;
+
+ if(tstat->frame_copied_errors)
+ tstat->frame_copied_errors
+ += *(tp->misc_command_data + 4) >> 8;
+
+ if(tstat->token_errors)
+ tstat->token_errors += *(tp->misc_command_data + 5) >> 8;
+
+ return (0);
+}
+
+static int smctr_update_rx_chain(struct net_device *dev, __u16 queue)
+{
+ struct net_local *tp = netdev_priv(dev);
+ FCBlock *fcb;
+ BDBlock *bdb;
+ __u16 size, len;
+
+ fcb = tp->rx_fcb_curr[queue];
+ len = fcb->frame_length;
+
+ fcb->frame_status = 0;
+ fcb->info = FCB_CHAIN_END;
+ fcb->back_ptr->info = FCB_WARNING;
+
+ tp->rx_fcb_curr[queue] = tp->rx_fcb_curr[queue]->next_ptr;
+
+ /* update RX BDBs */
+ size = (len >> RX_BDB_SIZE_SHIFT);
+ if(len & RX_DATA_BUFFER_SIZE_MASK)
+ size += sizeof(BDBlock);
+ size &= (~RX_BDB_SIZE_MASK);
+
+ /* check if wrap around */
+ bdb = (BDBlock *)((__u32)(tp->rx_bdb_curr[queue]) + (__u32)(size));
+ if((__u32)bdb >= (__u32)tp->rx_bdb_end[queue])
+ {
+ bdb = (BDBlock *)((__u32)(tp->rx_bdb_head[queue])
+ + (__u32)(bdb) - (__u32)(tp->rx_bdb_end[queue]));
+ }
+
+ bdb->back_ptr->info = BDB_CHAIN_END;
+ tp->rx_bdb_curr[queue]->back_ptr->info = BDB_NOT_CHAIN_END;
+ tp->rx_bdb_curr[queue] = bdb;
+
+ return (0);
+}
+
+static int smctr_update_tx_chain(struct net_device *dev, FCBlock *fcb,
+ __u16 queue)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ if(smctr_debug > 20)
+ printk(KERN_DEBUG "smctr_update_tx_chain\n");
+
+ if(tp->num_tx_fcbs_used[queue] <= 0)
+ return (HARDWARE_FAILED);
+ else
+ {
+ if(tp->tx_buff_used[queue] < fcb->memory_alloc)
+ {
+ tp->tx_buff_used[queue] = 0;
+ return (HARDWARE_FAILED);
+ }
+
+ tp->tx_buff_used[queue] -= fcb->memory_alloc;
+
+ /* if all transmit buffer are cleared
+ * need to set the tx_buff_curr[] to tx_buff_head[]
+ * otherwise, tx buffer will be segregate and cannot
+ * accommodate and buffer greater than (curr - head) and
+ * (end - curr) since we do not allow wrap around allocation.
+ */
+ if(tp->tx_buff_used[queue] == 0)
+ tp->tx_buff_curr[queue] = tp->tx_buff_head[queue];
+
+ tp->num_tx_fcbs_used[queue]--;
+ fcb->frame_status = 0;
+ tp->tx_fcb_end[queue] = fcb->next_ptr;
+ netif_wake_queue(dev);
+ return (0);
+ }
+}
+
+static int smctr_wait_cmd(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int loop_count = 0x20000;
+
+ if(smctr_debug > 10)
+ printk(KERN_DEBUG "%s: smctr_wait_cmd\n", dev->name);
+
+ while(loop_count)
+ {
+ if(tp->acb_head->cmd_done_status & ACB_COMMAND_DONE)
+ break;
+ udelay(1);
+ loop_count--;
+ }
+
+ if(loop_count == 0)
+ return(HARDWARE_FAILED);
+
+ if(tp->acb_head->cmd_done_status & 0xff)
+ return(HARDWARE_FAILED);
+
+ return (0);
+}
+
+static int smctr_wait_while_cbusy(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int timeout = 0x20000;
+ int ioaddr = dev->base_addr;
+ __u8 r;
+
+ if(tp->bic_type == BIC_585_CHIP)
+ {
+ while(timeout)
+ {
+ r = inb(ioaddr + HWR);
+ if((r & HWR_CBUSY) == 0)
+ break;
+ timeout--;
+ }
+ }
+ else
+ {
+ while(timeout)
+ {
+ r = inb(ioaddr + CSR);
+ if((r & CSR_CBUSY) == 0)
+ break;
+ timeout--;
+ }
+ }
+
+ if(timeout)
+ return (0);
+ else
+ return (HARDWARE_FAILED);
+}
+
+#ifdef MODULE
+
+static struct net_device* dev_smctr[SMCTR_MAX_ADAPTERS];
+static int io[SMCTR_MAX_ADAPTERS];
+static int irq[SMCTR_MAX_ADAPTERS];
+
+MODULE_LICENSE("GPL");
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param(ringspeed, int, 0);
+
+static struct net_device *setup_card(int n)
+{
+ struct net_device *dev = alloc_trdev(sizeof(struct net_local));
+ int err;
+
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
+
+ dev->irq = irq[n];
+ err = smctr_probe1(dev, io[n]);
+ if (err)
+ goto out;
+
+ err = register_netdev(dev);
+ if (err)
+ goto out1;
+ return dev;
+ out1:
+#ifdef CONFIG_MCA_LEGACY
+ { struct net_local *tp = netdev_priv(dev);
+ if (tp->slot_num)
+ mca_mark_as_unused(tp->slot_num);
+ }
+#endif
+ release_region(dev->base_addr, SMCTR_IO_EXTENT);
+ free_irq(dev->irq, dev);
+out:
+ free_netdev(dev);
+ return ERR_PTR(err);
+}
+
+
+int init_module(void)
+{
+ int i, found = 0;
+ struct net_device *dev;
+
+ for(i = 0; i < SMCTR_MAX_ADAPTERS; i++) {
+ dev = io[0]? setup_card(i) : smctr_probe(-1);
+ if (!IS_ERR(dev)) {
+ ++found;
+ dev_smctr[i] = dev;
+ }
+ }
+
+ return found ? 0 : -ENODEV;
+}
+
+void cleanup_module(void)
+{
+ int i;
+
+ for(i = 0; i < SMCTR_MAX_ADAPTERS; i++) {
+ struct net_device *dev = dev_smctr[i];
+
+ if (dev) {
+
+ unregister_netdev(dev);
+#ifdef CONFIG_MCA_LEGACY
+ { struct net_local *tp = netdev_priv(dev);
+ if (tp->slot_num)
+ mca_mark_as_unused(tp->slot_num);
+ }
+#endif
+ release_region(dev->base_addr, SMCTR_IO_EXTENT);
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+
+ free_netdev(dev);
+ }
+ }
+}
+#endif /* MODULE */
diff --git a/drivers/net/tokenring/smctr.h b/drivers/net/tokenring/smctr.h
new file mode 100644
index 00000000000..b306c7e4c79
--- /dev/null
+++ b/drivers/net/tokenring/smctr.h
@@ -0,0 +1,1588 @@
+/* smctr.h: SMC Token Ring driver header for Linux
+ *
+ * Authors:
+ * - Jay Schulist <jschlst@samba.org>
+ */
+
+#ifndef __LINUX_SMCTR_H
+#define __LINUX_SMCTR_H
+
+#ifdef __KERNEL__
+
+#define MAX_TX_QUEUE 10
+
+#define SMC_HEADER_SIZE 14
+
+#define SMC_PAGE_OFFSET(X) (((unsigned long)(X) - tp->ram_access) & tp->page_offset_mask)
+
+#define INIT 0x0D
+#define RQ_ATTCH 0x10
+#define RQ_STATE 0x0F
+#define RQ_ADDR 0x0E
+#define CHG_PARM 0x0C
+#define RSP 0x00
+#define TX_FORWARD 0x09
+
+#define AC_FC_DAT ((3<<13) | 1)
+#define DAT 0x07
+
+#define RPT_NEW_MON 0x25
+#define RPT_SUA_CHG 0x26
+#define RPT_ACTIVE_ERR 0x28
+#define RPT_NN_INCMP 0x27
+#define RPT_ERROR 0x29
+
+#define RQ_INIT 0x20
+#define RPT_ATTCH 0x24
+#define RPT_STATE 0x23
+#define RPT_ADDR 0x22
+
+#define POSITIVE_ACK 0x0001
+#define A_FRAME_WAS_FORWARDED 0x8888
+
+#define GROUP_ADDRESS 0x2B
+#define PHYSICAL_DROP 0x0B
+#define AUTHORIZED_ACCESS_PRIORITY 0x07
+#define AUTHORIZED_FUNCTION_CLASS 0x06
+#define FUNCTIONAL_ADDRESS 0x2C
+#define RING_STATION_STATUS 0x29
+#define TRANSMIT_STATUS_CODE 0x2A
+#define IBM_PASS_SOURCE_ADDR 0x01
+#define AC_FC_RPT_TX_FORWARD ((0<<13) | 0)
+#define AC_FC_RPT_STATE ((0<<13) | 0)
+#define AC_FC_RPT_ADDR ((0<<13) | 0)
+#define CORRELATOR 0x09
+
+#define POSITIVE_ACK 0x0001 /* */
+#define E_MAC_DATA_INCOMPLETE 0x8001 /* not used */
+#define E_VECTOR_LENGTH_ERROR 0x8002 /* */
+#define E_UNRECOGNIZED_VECTOR_ID 0x8003 /* */
+#define E_INAPPROPRIATE_SOURCE_CLASS 0x8004 /* */
+#define E_SUB_VECTOR_LENGTH_ERROR 0x8005 /* */
+#define E_TRANSMIT_FORWARD_INVALID 0x8006 /* def. by IBM */
+#define E_MISSING_SUB_VECTOR 0x8007 /* */
+#define E_SUB_VECTOR_UNKNOWN 0x8008 /* */
+#define E_MAC_HEADER_TOO_LONG 0x8009 /* */
+#define E_FUNCTION_DISABLED 0x800A /* not used */
+
+#define A_FRAME_WAS_FORWARDED 0x8888 /* used by send_TX_FORWARD */
+
+#define UPSTREAM_NEIGHBOR_ADDRESS 0x02
+#define LOCAL_RING_NUMBER 0x03
+#define ASSIGN_PHYSICAL_DROP 0x04
+#define ERROR_TIMER_VALUE 0x05
+#define AUTHORIZED_FUNCTION_CLASS 0x06
+#define AUTHORIZED_ACCESS_PRIORITY 0x07
+#define CORRELATOR 0x09
+#define PHYSICAL_DROP 0x0B
+#define RESPONSE_CODE 0x20
+#define ADDRESS_MODIFER 0x21
+#define PRODUCT_INSTANCE_ID 0x22
+#define RING_STATION_VERSION_NUMBER 0x23
+#define WRAP_DATA 0x26
+#define FRAME_FORWARD 0x27
+#define STATION_IDENTIFER 0x28
+#define RING_STATION_STATUS 0x29
+#define TRANSMIT_STATUS_CODE 0x2A
+#define GROUP_ADDRESS 0x2B
+#define FUNCTIONAL_ADDRESS 0x2C
+
+#define F_NO_SUB_VECTORS_FOUND 0x0000
+#define F_UPSTREAM_NEIGHBOR_ADDRESS 0x0001
+#define F_LOCAL_RING_NUMBER 0x0002
+#define F_ASSIGN_PHYSICAL_DROP 0x0004
+#define F_ERROR_TIMER_VALUE 0x0008
+#define F_AUTHORIZED_FUNCTION_CLASS 0x0010
+#define F_AUTHORIZED_ACCESS_PRIORITY 0x0020
+#define F_CORRELATOR 0x0040
+#define F_PHYSICAL_DROP 0x0080
+#define F_RESPONSE_CODE 0x0100
+#define F_PRODUCT_INSTANCE_ID 0x0200
+#define F_RING_STATION_VERSION_NUMBER 0x0400
+#define F_STATION_IDENTIFER 0x0800
+#define F_RING_STATION_STATUS 0x1000
+#define F_GROUP_ADDRESS 0x2000
+#define F_FUNCTIONAL_ADDRESS 0x4000
+#define F_FRAME_FORWARD 0x8000
+
+#define R_INIT 0x00
+#define R_RQ_ATTCH_STATE_ADDR 0x00
+#define R_CHG_PARM 0x00
+#define R_TX_FORWARD F_FRAME_FORWARD
+
+
+#define UPSTREAM_NEIGHBOR_ADDRESS 0x02
+#define ADDRESS_MODIFER 0x21
+#define RING_STATION_VERSION_NUMBER 0x23
+#define PRODUCT_INSTANCE_ID 0x22
+
+#define RPT_TX_FORWARD 0x2A
+
+#define AC_FC_INIT (3<<13) | 0 /* */
+#define AC_FC_RQ_INIT ((3<<13) | 0) /* */
+#define AC_FC_RQ_ATTCH (3<<13) | 0 /* DC = SC of rx frame */
+#define AC_FC_RQ_STATE (3<<13) | 0 /* DC = SC of rx frame */
+#define AC_FC_RQ_ADDR (3<<13) | 0 /* DC = SC of rx frame */
+#define AC_FC_CHG_PARM (3<<13) | 0 /* */
+#define AC_FC_RSP (0<<13) | 0 /* DC = SC of rx frame */
+#define AC_FC_RPT_ATTCH (0<<13) | 0
+
+#define S_UPSTREAM_NEIGHBOR_ADDRESS 6 + 2
+#define S_LOCAL_RING_NUMBER 2 + 2
+#define S_ASSIGN_PHYSICAL_DROP 4 + 2
+#define S_ERROR_TIMER_VALUE 2 + 2
+#define S_AUTHORIZED_FUNCTION_CLASS 2 + 2
+#define S_AUTHORIZED_ACCESS_PRIORITY 2 + 2
+#define S_CORRELATOR 2 + 2
+#define S_PHYSICAL_DROP 4 + 2
+#define S_RESPONSE_CODE 4 + 2
+#define S_ADDRESS_MODIFER 2 + 2
+#define S_PRODUCT_INSTANCE_ID 18 + 2
+#define S_RING_STATION_VERSION_NUMBER 10 + 2
+#define S_STATION_IDENTIFER 6 + 2
+#define S_RING_STATION_STATUS 6 + 2
+#define S_GROUP_ADDRESS 4 + 2
+#define S_FUNCTIONAL_ADDRESS 4 + 2
+#define S_FRAME_FORWARD 252 + 2
+#define S_TRANSMIT_STATUS_CODE 2 + 2
+
+#define ISB_IMC_RES0 0x0000 /* */
+#define ISB_IMC_MAC_TYPE_3 0x0001 /* MAC_ARC_INDICATE */
+#define ISB_IMC_MAC_ERROR_COUNTERS 0x0002 /* */
+#define ISB_IMC_RES1 0x0003 /* */
+#define ISB_IMC_MAC_TYPE_2 0x0004 /* QUE_MAC_INDICATE */
+#define ISB_IMC_TX_FRAME 0x0005 /* */
+#define ISB_IMC_END_OF_TX_QUEUE 0x0006 /* */
+#define ISB_IMC_NON_MAC_RX_RESOURCE 0x0007 /* */
+#define ISB_IMC_MAC_RX_RESOURCE 0x0008 /* */
+#define ISB_IMC_NON_MAC_RX_FRAME 0x0009 /* */
+#define ISB_IMC_MAC_RX_FRAME 0x000A /* */
+#define ISB_IMC_TRC_FIFO_STATUS 0x000B /* */
+#define ISB_IMC_COMMAND_STATUS 0x000C /* */
+#define ISB_IMC_MAC_TYPE_1 0x000D /* Self Removed */
+#define ISB_IMC_TRC_INTRNL_TST_STATUS 0x000E /* */
+#define ISB_IMC_RES2 0x000F /* */
+
+#define NON_MAC_RX_RESOURCE_BW 0x10 /* shifted right 8 bits */
+#define NON_MAC_RX_RESOURCE_FW 0x20 /* shifted right 8 bits */
+#define NON_MAC_RX_RESOURCE_BE 0x40 /* shifted right 8 bits */
+#define NON_MAC_RX_RESOURCE_FE 0x80 /* shifted right 8 bits */
+#define RAW_NON_MAC_RX_RESOURCE_BW 0x1000 /* */
+#define RAW_NON_MAC_RX_RESOURCE_FW 0x2000 /* */
+#define RAW_NON_MAC_RX_RESOURCE_BE 0x4000 /* */
+#define RAW_NON_MAC_RX_RESOURCE_FE 0x8000 /* */
+
+#define MAC_RX_RESOURCE_BW 0x10 /* shifted right 8 bits */
+#define MAC_RX_RESOURCE_FW 0x20 /* shifted right 8 bits */
+#define MAC_RX_RESOURCE_BE 0x40 /* shifted right 8 bits */
+#define MAC_RX_RESOURCE_FE 0x80 /* shifted right 8 bits */
+#define RAW_MAC_RX_RESOURCE_BW 0x1000 /* */
+#define RAW_MAC_RX_RESOURCE_FW 0x2000 /* */
+#define RAW_MAC_RX_RESOURCE_BE 0x4000 /* */
+#define RAW_MAC_RX_RESOURCE_FE 0x8000 /* */
+
+#define TRC_FIFO_STATUS_TX_UNDERRUN 0x40 /* shifted right 8 bits */
+#define TRC_FIFO_STATUS_RX_OVERRUN 0x80 /* shifted right 8 bits */
+#define RAW_TRC_FIFO_STATUS_TX_UNDERRUN 0x4000 /* */
+#define RAW_TRC_FIFO_STATUS_RX_OVERRUN 0x8000 /* */
+
+#define CSR_CLRTINT 0x08
+
+#define MSB(X) ((__u8)((__u16) X >> 8))
+#define LSB(X) ((__u8)((__u16) X & 0xff))
+
+#define AC_FC_LOBE_MEDIA_TEST ((3<<13) | 0)
+#define S_WRAP_DATA 248 + 2 /* 500 + 2 */
+#define WRAP_DATA 0x26
+#define LOBE_MEDIA_TEST 0x08
+
+/* Destination Class (dc) */
+
+#define DC_MASK 0xF0
+#define DC_RS 0x00
+#define DC_CRS 0x40
+#define DC_RPS 0x50
+#define DC_REM 0x60
+
+/* Source Classes (sc) */
+
+#define SC_MASK 0x0F
+#define SC_RS 0x00
+#define SC_CRS 0x04
+#define SC_RPS 0x05
+#define SC_REM 0x06
+
+#define PR 0x11
+#define PR_PAGE_MASK 0x0C000
+
+#define MICROCHANNEL 0x0008
+#define INTERFACE_CHIP 0x0010
+#define BOARD_16BIT 0x0040
+#define PAGED_RAM 0x0080
+#define WD8115TA (TOKEN_MEDIA | MICROCHANNEL | INTERFACE_CHIP | PAGED_RAM)
+#define WD8115T (TOKEN_MEDIA | INTERFACE_CHIP | BOARD_16BIT | PAGED_RAM)
+
+#define BRD_ID_8316 0x50
+
+#define r587_SER 0x001
+#define SER_DIN 0x80
+#define SER_DOUT 0x40
+#define SER_CLK 0x20
+#define SER_ECS 0x10
+#define SER_E806 0x08
+#define SER_PNP 0x04
+#define SER_BIO 0x02
+#define SER_16B 0x01
+
+#define r587_IDR 0x004
+#define IDR_IRQ_MASK 0x0F0
+#define IDR_DCS_MASK 0x007
+#define IDR_RWS 0x008
+
+
+#define r587_BIO 0x003
+#define BIO_ENB 0x080
+#define BIO_MASK 0x03F
+
+#define r587_PCR 0x005
+#define PCR_RAMS 0x040
+
+
+
+#define NUM_ADDR_BITS 8
+
+#define ISA_MAX_ADDRESS 0x00ffffff
+
+#define SMCTR_MAX_ADAPTERS 7
+
+#define MC_TABLE_ENTRIES 16
+
+#define MAXFRAGMENTS 32
+
+#define CHIP_REV_MASK 0x3000
+
+#define MAX_TX_QS 8
+#define NUM_TX_QS_USED 3
+
+#define MAX_RX_QS 2
+#define NUM_RX_QS_USED 2
+
+#define INTEL_DATA_FORMAT 0x4000
+#define INTEL_ADDRESS_POINTER_FORMAT 0x8000
+#define PAGE_POINTER(X) ((((unsigned long)(X) - tp->ram_access) & tp->page_offset_mask) + tp->ram_access)
+#define SWAP_WORDS(X) (((X & 0xFFFF) << 16) | (X >> 16))
+
+#define INTERFACE_CHIP 0x0010 /* Soft Config Adapter */
+#define ADVANCED_FEATURES 0x0020 /* Adv. netw. interface features */
+#define BOARD_16BIT 0x0040 /* 16 bit capability */
+#define PAGED_RAM 0x0080 /* Adapter has paged RAM */
+
+#define PAGED_ROM 0x0100 /* Adapter has paged ROM */
+
+#define RAM_SIZE_UNKNOWN 0x0000 /* Unknown RAM size */
+#define RAM_SIZE_0K 0x0001 /* 0K RAM */
+#define RAM_SIZE_8K 0x0002 /* 8k RAM */
+#define RAM_SIZE_16K 0x0003 /* 16k RAM */
+#define RAM_SIZE_32K 0x0004 /* 32k RAM */
+#define RAM_SIZE_64K 0x0005 /* 64k RAM */
+#define RAM_SIZE_RESERVED_6 0x0006 /* Reserved RAM size */
+#define RAM_SIZE_RESERVED_7 0x0007 /* Reserved RAM size */
+#define RAM_SIZE_MASK 0x0007 /* Isolates RAM Size */
+
+#define TOKEN_MEDIA 0x0005
+
+#define BID_REG_0 0x00
+#define BID_REG_1 0x01
+#define BID_REG_2 0x02
+#define BID_REG_3 0x03
+#define BID_REG_4 0x04
+#define BID_REG_5 0x05
+#define BID_REG_6 0x06
+#define BID_REG_7 0x07
+#define BID_LAR_0 0x08
+#define BID_LAR_1 0x09
+#define BID_LAR_2 0x0A
+#define BID_LAR_3 0x0B
+#define BID_LAR_4 0x0C
+#define BID_LAR_5 0x0D
+
+#define BID_BOARD_ID_BYTE 0x0E
+#define BID_CHCKSM_BYTE 0x0F
+#define BID_LAR_OFFSET 0x08
+
+#define BID_MSZ_583_BIT 0x08
+#define BID_SIXTEEN_BIT_BIT 0x01
+
+#define BID_BOARD_REV_MASK 0x1E
+
+#define BID_MEDIA_TYPE_BIT 0x01
+#define BID_SOFT_CONFIG_BIT 0x20
+#define BID_RAM_SIZE_BIT 0x40
+#define BID_BUS_TYPE_BIT 0x80
+
+#define BID_CR 0x10
+
+#define BID_TXP 0x04 /* Transmit Packet Command */
+
+#define BID_TCR_DIFF 0x0D /* Transmit Configuration Register */
+
+#define BID_TCR_VAL 0x18 /* Value to Test 8390 or 690 */
+#define BID_PS0 0x00 /* Register Page Select 0 */
+#define BID_PS1 0x40 /* Register Page Select 1 */
+#define BID_PS2 0x80 /* Register Page Select 2 */
+#define BID_PS_MASK 0x3F /* For Masking Off Page Select Bits */
+
+#define BID_EEPROM_0 0x08
+#define BID_EEPROM_1 0x09
+#define BID_EEPROM_2 0x0A
+#define BID_EEPROM_3 0x0B
+#define BID_EEPROM_4 0x0C
+#define BID_EEPROM_5 0x0D
+#define BID_EEPROM_6 0x0E
+#define BID_EEPROM_7 0x0F
+
+#define BID_OTHER_BIT 0x02
+#define BID_ICR_MASK 0x0C
+#define BID_EAR_MASK 0x0F
+#define BID_ENGR_PAGE 0x0A0
+#define BID_RLA 0x10
+#define BID_EA6 0x80
+#define BID_RECALL_DONE_MASK 0x10
+#define BID_BID_EEPROM_OVERRIDE 0xFFB0
+#define BID_EXTRA_EEPROM_OVERRIDE 0xFFD0
+#define BID_EEPROM_MEDIA_MASK 0x07
+#define BID_STARLAN_TYPE 0x00
+#define BID_ETHERNET_TYPE 0x01
+#define BID_TP_TYPE 0x02
+#define BID_EW_TYPE 0x03
+#define BID_TOKEN_RING_TYPE 0x04
+#define BID_UTP2_TYPE 0x05
+#define BID_EEPROM_IRQ_MASK 0x18
+#define BID_PRIMARY_IRQ 0x00
+#define BID_ALTERNATE_IRQ_1 0x08
+#define BID_ALTERNATE_IRQ_2 0x10
+#define BID_ALTERNATE_IRQ_3 0x18
+#define BID_EEPROM_RAM_SIZE_MASK 0xE0
+#define BID_EEPROM_RAM_SIZE_RES1 0x00
+#define BID_EEPROM_RAM_SIZE_RES2 0x20
+#define BID_EEPROM_RAM_SIZE_8K 0x40
+#define BID_EEPROM_RAM_SIZE_16K 0x60
+#define BID_EEPROM_RAM_SIZE_32K 0x80
+#define BID_EEPROM_RAM_SIZE_64K 0xA0
+#define BID_EEPROM_RAM_SIZE_RES3 0xC0
+#define BID_EEPROM_RAM_SIZE_RES4 0xE0
+#define BID_EEPROM_BUS_TYPE_MASK 0x07
+#define BID_EEPROM_BUS_TYPE_AT 0x00
+#define BID_EEPROM_BUS_TYPE_MCA 0x01
+#define BID_EEPROM_BUS_TYPE_EISA 0x02
+#define BID_EEPROM_BUS_TYPE_NEC 0x03
+#define BID_EEPROM_BUS_SIZE_MASK 0x18
+#define BID_EEPROM_BUS_SIZE_8BIT 0x00
+#define BID_EEPROM_BUS_SIZE_16BIT 0x08
+#define BID_EEPROM_BUS_SIZE_32BIT 0x10
+#define BID_EEPROM_BUS_SIZE_64BIT 0x18
+#define BID_EEPROM_BUS_MASTER 0x20
+#define BID_EEPROM_RAM_PAGING 0x40
+#define BID_EEPROM_ROM_PAGING 0x80
+#define BID_EEPROM_PAGING_MASK 0xC0
+#define BID_EEPROM_LOW_COST 0x08
+#define BID_EEPROM_IO_MAPPED 0x10
+#define BID_EEPROM_HMI 0x01
+#define BID_EEPROM_AUTO_MEDIA_DETECT 0x01
+#define BID_EEPROM_CHIP_REV_MASK 0x0C
+
+#define BID_EEPROM_LAN_ADDR 0x30
+
+#define BID_EEPROM_MEDIA_OPTION 0x54
+#define BID_EEPROM_MEDIA_UTP 0x01
+#define BID_EEPROM_4MB_RING 0x08
+#define BID_EEPROM_16MB_RING 0x10
+#define BID_EEPROM_MEDIA_STP 0x40
+
+#define BID_EEPROM_MISC_DATA 0x56
+#define BID_EEPROM_EARLY_TOKEN_RELEASE 0x02
+
+#define CNFG_ID_8003E 0x6fc0
+#define CNFG_ID_8003S 0x6fc1
+#define CNFG_ID_8003W 0x6fc2
+#define CNFG_ID_8115TRA 0x6ec6
+#define CNFG_ID_8013E 0x61C8
+#define CNFG_ID_8013W 0x61C9
+#define CNFG_ID_BISTRO03E 0xEFE5
+#define CNFG_ID_BISTRO13E 0xEFD5
+#define CNFG_ID_BISTRO13W 0xEFD4
+#define CNFG_MSR_583 0x0
+#define CNFG_ICR_583 0x1
+#define CNFG_IAR_583 0x2
+#define CNFG_BIO_583 0x3
+#define CNFG_EAR_583 0x3
+#define CNFG_IRR_583 0x4
+#define CNFG_LAAR_584 0x5
+#define CNFG_GP2 0x7
+#define CNFG_LAAR_MASK 0x1F
+#define CNFG_LAAR_ZWS 0x20
+#define CNFG_LAAR_L16E 0x40
+#define CNFG_ICR_IR2_584 0x04
+#define CNFG_ICR_MASK 0x08
+#define CNFG_ICR_MSZ 0x08
+#define CNFG_ICR_RLA 0x10
+#define CNFG_ICR_STO 0x80
+#define CNFG_IRR_IRQS 0x60
+#define CNFG_IRR_IEN 0x80
+#define CNFG_IRR_ZWS 0x01
+#define CNFG_GP2_BOOT_NIBBLE 0x0F
+#define CNFG_IRR_OUT2 0x04
+#define CNFG_IRR_OUT1 0x02
+
+#define CNFG_SIZE_8KB 8
+#define CNFG_SIZE_16KB 16
+#define CNFG_SIZE_32KB 32
+#define CNFG_SIZE_64KB 64
+#define CNFG_SIZE_128KB 128
+#define CNFG_SIZE_256KB 256
+#define ROM_DISABLE 0x0
+
+#define CNFG_SLOT_ENABLE_BIT 0x08
+
+#define CNFG_POS_CONTROL_REG 0x096
+#define CNFG_POS_REG0 0x100
+#define CNFG_POS_REG1 0x101
+#define CNFG_POS_REG2 0x102
+#define CNFG_POS_REG3 0x103
+#define CNFG_POS_REG4 0x104
+#define CNFG_POS_REG5 0x105
+
+#define CNFG_ADAPTER_TYPE_MASK 0x0e
+
+#define SLOT_16BIT 0x0008
+#define INTERFACE_5X3_CHIP 0x0000 /* 0000 = 583 or 593 chips */
+#define NIC_690_BIT 0x0010 /* NIC is 690 */
+#define ALTERNATE_IRQ_BIT 0x0020 /* Alternate IRQ is used */
+#define INTERFACE_584_CHIP 0x0040 /* 0001 = 584 chip */
+#define INTERFACE_594_CHIP 0x0080 /* 0010 = 594 chip */
+#define INTERFACE_585_CHIP 0x0100 /* 0100 = 585/790 chip */
+#define INTERFACE_CHIP_MASK 0x03C0 /* Isolates Intfc Chip Type */
+
+#define BOARD_16BIT 0x0040
+#define NODE_ADDR_CKSUM 0xEE
+#define BRD_ID_8115T 0x04
+
+#define NIC_825_BIT 0x0400 /* TRC 83C825 NIC */
+#define NIC_790_BIT 0x0800 /* NIC is 83C790 Ethernet */
+
+#define CHIP_REV_MASK 0x3000
+
+#define HWR_CBUSY 0x02
+#define HWR_CA 0x01
+
+#define MAC_QUEUE 0
+#define NON_MAC_QUEUE 1
+#define BUG_QUEUE 2 /* NO RECEIVE QUEUE, ONLY TX */
+
+#define NUM_MAC_TX_FCBS 8
+#define NUM_MAC_TX_BDBS NUM_MAC_TX_FCBS
+#define NUM_MAC_RX_FCBS 7
+#define NUM_MAC_RX_BDBS 8
+
+#define NUM_NON_MAC_TX_FCBS 6
+#define NUM_NON_MAC_TX_BDBS NUM_NON_MAC_TX_FCBS
+
+#define NUM_NON_MAC_RX_BDBS 0 /* CALCULATED DYNAMICALLY */
+
+#define NUM_BUG_TX_FCBS 8
+#define NUM_BUG_TX_BDBS NUM_BUG_TX_FCBS
+
+#define MAC_TX_BUFFER_MEMORY 1024
+#define NON_MAC_TX_BUFFER_MEMORY (20 * 1024)
+#define BUG_TX_BUFFER_MEMORY (NUM_BUG_TX_FCBS * 32)
+
+#define RX_BUFFER_MEMORY 0 /* CALCULATED DYNAMICALLY */
+#define RX_DATA_BUFFER_SIZE 256
+#define RX_BDB_SIZE_SHIFT 3 /* log2(RX_DATA_BUFFER_SIZE)-log2(sizeof(BDBlock)) */
+#define RX_BDB_SIZE_MASK (sizeof(BDBlock) - 1)
+#define RX_DATA_BUFFER_SIZE_MASK (RX_DATA_BUFFER_SIZE-1)
+
+#define NUM_OF_INTERRUPTS 0x20
+
+#define NOT_TRANSMITING 0
+#define TRANSMITING 1
+
+#define TRC_INTERRUPT_ENABLE_MASK 0x7FF6
+
+#define UCODE_VERSION 0x58
+
+#define UCODE_SIZE_OFFSET 0x0000 /* WORD */
+#define UCODE_CHECKSUM_OFFSET 0x0002 /* WORD */
+#define UCODE_VERSION_OFFSET 0x0004 /* BYTE */
+
+#define CS_RAM_SIZE 0X2000
+#define CS_RAM_CHECKSUM_OFFSET 0x1FFE /* WORD 1FFE(MSB)-1FFF(LSB)*/
+#define CS_RAM_VERSION_OFFSET 0x1FFC /* WORD 1FFC(MSB)-1FFD(LSB)*/
+
+#define MISC_DATA_SIZE 128
+#define NUM_OF_ACBS 1
+
+#define ACB_COMMAND_NOT_DONE 0x0000 /* Init, command not done */
+#define ACB_COMMAND_DONE 0x8000 /* TRC says command done */
+#define ACB_COMMAND_STATUS_MASK 0x00FF /* low byte is status */
+#define ACB_COMMAND_SUCCESSFUL 0x0000 /* means cmd was successful */
+#define ACB_NOT_CHAIN_END 0x0000 /* tell TRC more CBs in chain */
+#define ACB_CHAIN_END 0x8000 /* tell TRC last CB in chain */
+#define ACB_COMMAND_NO_INTERRUPT 0x0000 /* tell TRC no INT after CB */
+#define ACB_COMMAND_INTERRUPT 0x2000 /* tell TRC to INT after CB */
+#define ACB_SUB_CMD_NOP 0x0000
+#define ACB_CMD_HIC_NOP 0x0080
+#define ACB_CMD_MCT_NOP 0x0000
+#define ACB_CMD_MCT_TEST 0x0001
+#define ACB_CMD_HIC_TEST 0x0081
+#define ACB_CMD_INSERT 0x0002
+#define ACB_CMD_REMOVE 0x0003
+#define ACB_CMD_MCT_WRITE_VALUE 0x0004
+#define ACB_CMD_HIC_WRITE_VALUE 0x0084
+#define ACB_CMD_MCT_READ_VALUE 0x0005
+#define ACB_CMD_HIC_READ_VALUE 0x0085
+#define ACB_CMD_INIT_TX_RX 0x0086
+#define ACB_CMD_INIT_TRC_TIMERS 0x0006
+#define ACB_CMD_READ_TRC_STATUS 0x0007
+#define ACB_CMD_CHANGE_JOIN_STATE 0x0008
+#define ACB_CMD_RESERVED_9 0x0009
+#define ACB_CMD_RESERVED_A 0x000A
+#define ACB_CMD_RESERVED_B 0x000B
+#define ACB_CMD_RESERVED_C 0x000C
+#define ACB_CMD_RESERVED_D 0x000D
+#define ACB_CMD_RESERVED_E 0x000E
+#define ACB_CMD_RESERVED_F 0x000F
+
+#define TRC_MAC_REGISTERS_TEST 0x0000
+#define TRC_INTERNAL_LOOPBACK 0x0001
+#define TRC_TRI_LOOPBACK 0x0002
+#define TRC_INTERNAL_ROM_TEST 0x0003
+#define TRC_LOBE_MEDIA_TEST 0x0004
+#define TRC_ANALOG_TEST 0x0005
+#define TRC_HOST_INTERFACE_REG_TEST 0x0003
+
+#define TEST_DMA_1 0x0000
+#define TEST_DMA_2 0x0001
+#define TEST_MCT_ROM 0x0002
+#define HIC_INTERNAL_DIAG 0x0003
+
+#define ABORT_TRANSMIT_PRIORITY_0 0x0001
+#define ABORT_TRANSMIT_PRIORITY_1 0x0002
+#define ABORT_TRANSMIT_PRIORITY_2 0x0004
+#define ABORT_TRANSMIT_PRIORITY_3 0x0008
+#define ABORT_TRANSMIT_PRIORITY_4 0x0010
+#define ABORT_TRANSMIT_PRIORITY_5 0x0020
+#define ABORT_TRANSMIT_PRIORITY_6 0x0040
+#define ABORT_TRANSMIT_PRIORITY_7 0x0080
+
+#define TX_PENDING_PRIORITY_0 0x0001
+#define TX_PENDING_PRIORITY_1 0x0002
+#define TX_PENDING_PRIORITY_2 0x0004
+#define TX_PENDING_PRIORITY_3 0x0008
+#define TX_PENDING_PRIORITY_4 0x0010
+#define TX_PENDING_PRIORITY_5 0x0020
+#define TX_PENDING_PRIORITY_6 0x0040
+#define TX_PENDING_PRIORITY_7 0x0080
+
+#define FCB_FRAME_LENGTH 0x100
+#define FCB_COMMAND_DONE 0x8000 /* FCB Word 0 */
+#define FCB_NOT_CHAIN_END 0x0000 /* FCB Word 1 */
+#define FCB_CHAIN_END 0x8000
+#define FCB_NO_WARNING 0x0000
+#define FCB_WARNING 0x4000
+#define FCB_INTERRUPT_DISABLE 0x0000
+#define FCB_INTERRUPT_ENABLE 0x2000
+
+#define FCB_ENABLE_IMA 0x0008
+#define FCB_ENABLE_TES 0x0004 /* Guarantee Tx before Int */
+#define FCB_ENABLE_TFS 0x0002 /* Post Tx Frame Status */
+#define FCB_ENABLE_NTC 0x0001 /* No Tx CRC */
+
+#define FCB_TX_STATUS_CR2 0x0004
+#define FCB_TX_STATUS_AR2 0x0008
+#define FCB_TX_STATUS_CR1 0x0040
+#define FCB_TX_STATUS_AR1 0x0080
+#define FCB_TX_AC_BITS (FCB_TX_STATUS_AR1+FCB_TX_STATUS_AR2+FCB_TX_STATUS_CR1+FCB_TX_STATUS_CR2)
+#define FCB_TX_STATUS_E 0x0100
+
+#define FCB_RX_STATUS_ANY_ERROR 0x0001
+#define FCB_RX_STATUS_FCS_ERROR 0x0002
+
+#define FCB_RX_STATUS_IA_MATCHED 0x0400
+#define FCB_RX_STATUS_IGA_BSGA_MATCHED 0x0500
+#define FCB_RX_STATUS_FA_MATCHED 0x0600
+#define FCB_RX_STATUS_BA_MATCHED 0x0700
+#define FCB_RX_STATUS_DA_MATCHED 0x0400
+#define FCB_RX_STATUS_SOURCE_ROUTING 0x0800
+
+#define BDB_BUFFER_SIZE 0x100
+#define BDB_NOT_CHAIN_END 0x0000
+#define BDB_CHAIN_END 0x8000
+#define BDB_NO_WARNING 0x0000
+#define BDB_WARNING 0x4000
+
+#define ERROR_COUNTERS_CHANGED 0x0001
+#define TI_NDIS_RING_STATUS_CHANGED 0x0002
+#define UNA_CHANGED 0x0004
+#define READY_TO_SEND_RQ_INIT 0x0008
+
+#define SCGB_ADDRESS_POINTER_FORMAT INTEL_ADDRESS_POINTER_FORMAT
+#define SCGB_DATA_FORMAT INTEL_DATA_FORMAT
+#define SCGB_MULTI_WORD_CONTROL 0
+#define SCGB_BURST_LENGTH 0x000E /* DMA Burst Length */
+
+#define SCGB_CONFIG (INTEL_ADDRESS_POINTER_FORMAT+INTEL_DATA_FORMAT+SCGB_BURST_LENGTH)
+
+#define ISCP_BLOCK_SIZE 0x0A
+#define RAM_SIZE 0x10000
+#define INIT_SYS_CONFIG_PTR_OFFSET (RAM_SIZE-ISCP_BLOCK_SIZE)
+#define SCGP_BLOCK_OFFSET 0
+
+#define SCLB_NOT_VALID 0x0000 /* Initially, SCLB not valid */
+#define SCLB_VALID 0x8000 /* Host tells TRC SCLB valid */
+#define SCLB_PROCESSED 0x0000 /* TRC says SCLB processed */
+#define SCLB_RESUME_CONTROL_NOT_VALID 0x0000 /* Initially, RC not valid */
+#define SCLB_RESUME_CONTROL_VALID 0x4000 /* Host tells TRC RC valid */
+#define SCLB_IACK_CODE_NOT_VALID 0x0000 /* Initially, IACK not valid */
+#define SCLB_IACK_CODE_VALID 0x2000 /* Host tells TRC IACK valid */
+#define SCLB_CMD_NOP 0x0000
+#define SCLB_CMD_REMOVE 0x0001
+#define SCLB_CMD_SUSPEND_ACB_CHAIN 0x0002
+#define SCLB_CMD_SET_INTERRUPT_MASK 0x0003
+#define SCLB_CMD_CLEAR_INTERRUPT_MASK 0x0004
+#define SCLB_CMD_RESERVED_5 0x0005
+#define SCLB_CMD_RESERVED_6 0x0006
+#define SCLB_CMD_RESERVED_7 0x0007
+#define SCLB_CMD_RESERVED_8 0x0008
+#define SCLB_CMD_RESERVED_9 0x0009
+#define SCLB_CMD_RESERVED_A 0x000A
+#define SCLB_CMD_RESERVED_B 0x000B
+#define SCLB_CMD_RESERVED_C 0x000C
+#define SCLB_CMD_RESERVED_D 0x000D
+#define SCLB_CMD_RESERVED_E 0x000E
+#define SCLB_CMD_RESERVED_F 0x000F
+
+#define SCLB_RC_ACB 0x0001 /* Action Command Block Chain */
+#define SCLB_RC_RES0 0x0002 /* Always Zero */
+#define SCLB_RC_RES1 0x0004 /* Always Zero */
+#define SCLB_RC_RES2 0x0008 /* Always Zero */
+#define SCLB_RC_RX_MAC_FCB 0x0010 /* RX_MAC_FCB Chain */
+#define SCLB_RC_RX_MAC_BDB 0x0020 /* RX_MAC_BDB Chain */
+#define SCLB_RC_RX_NON_MAC_FCB 0x0040 /* RX_NON_MAC_FCB Chain */
+#define SCLB_RC_RX_NON_MAC_BDB 0x0080 /* RX_NON_MAC_BDB Chain */
+#define SCLB_RC_TFCB0 0x0100 /* TX Priority 0 FCB Chain */
+#define SCLB_RC_TFCB1 0x0200 /* TX Priority 1 FCB Chain */
+#define SCLB_RC_TFCB2 0x0400 /* TX Priority 2 FCB Chain */
+#define SCLB_RC_TFCB3 0x0800 /* TX Priority 3 FCB Chain */
+#define SCLB_RC_TFCB4 0x1000 /* TX Priority 4 FCB Chain */
+#define SCLB_RC_TFCB5 0x2000 /* TX Priority 5 FCB Chain */
+#define SCLB_RC_TFCB6 0x4000 /* TX Priority 6 FCB Chain */
+#define SCLB_RC_TFCB7 0x8000 /* TX Priority 7 FCB Chain */
+
+#define SCLB_IMC_RES0 0x0001 /* */
+#define SCLB_IMC_MAC_TYPE_3 0x0002 /* MAC_ARC_INDICATE */
+#define SCLB_IMC_MAC_ERROR_COUNTERS 0x0004 /* */
+#define SCLB_IMC_RES1 0x0008 /* */
+#define SCLB_IMC_MAC_TYPE_2 0x0010 /* QUE_MAC_INDICATE */
+#define SCLB_IMC_TX_FRAME 0x0020 /* */
+#define SCLB_IMC_END_OF_TX_QUEUE 0x0040 /* */
+#define SCLB_IMC_NON_MAC_RX_RESOURCE 0x0080 /* */
+#define SCLB_IMC_MAC_RX_RESOURCE 0x0100 /* */
+#define SCLB_IMC_NON_MAC_RX_FRAME 0x0200 /* */
+#define SCLB_IMC_MAC_RX_FRAME 0x0400 /* */
+#define SCLB_IMC_TRC_FIFO_STATUS 0x0800 /* */
+#define SCLB_IMC_COMMAND_STATUS 0x1000 /* */
+#define SCLB_IMC_MAC_TYPE_1 0x2000 /* Self Removed */
+#define SCLB_IMC_TRC_INTRNL_TST_STATUS 0x4000 /* */
+#define SCLB_IMC_RES2 0x8000 /* */
+
+#define DMA_TRIGGER 0x0004
+#define FREQ_16MB_BIT 0x0010
+#define THDREN 0x0020
+#define CFG0_RSV1 0x0040
+#define CFG0_RSV2 0x0080
+#define ETREN 0x0100
+#define RX_OWN_BIT 0x0200
+#define RXATMAC 0x0400
+#define PROMISCUOUS_BIT 0x0800
+#define USETPT 0x1000
+#define SAVBAD_BIT 0x2000
+#define ONEQUE 0x4000
+#define NO_AUTOREMOVE 0x8000
+
+#define RX_FCB_AREA_8316 0x00000000
+#define RX_BUFF_AREA_8316 0x00000000
+
+#define TRC_POINTER(X) ((unsigned long)(X) - tp->ram_access)
+#define RX_FCB_TRC_POINTER(X) ((unsigned long)(X) - tp->ram_access + RX_FCB_AREA_8316)
+#define RX_BUFF_TRC_POINTER(X) ((unsigned long)(X) - tp->ram_access + RX_BUFF_AREA_8316)
+
+// Offset 0: MSR - Memory Select Register
+//
+#define r587_MSR 0x000 // Register Offset
+//#define MSR_RST 0x080 // LAN Controller Reset
+#define MSR_MENB 0x040 // Shared Memory Enable
+#define MSR_RA18 0x020 // Ram Address bit 18 (583, 584, 587)
+#define MSR_RA17 0x010 // Ram Address bit 17 (583, 584, 585/790)
+#define MSR_RA16 0x008 // Ram Address bit 16 (583, 584, 585/790)
+#define MSR_RA15 0x004 // Ram Address bit 15 (583, 584, 585/790)
+#define MSR_RA14 0x002 // Ram Address bit 14 (583, 584, 585/790)
+#define MSR_RA13 0x001 // Ram Address bit 13 (583, 584, 585/790)
+
+#define MSR_MASK 0x03F // Mask for Address bits RA18-RA13 (583, 584, 587)
+
+#define MSR 0x00
+#define IRR 0x04
+#define HWR 0x04
+#define LAAR 0x05
+#define IMCCR 0x05
+#define LAR0 0x08
+#define BDID 0x0E // Adapter ID byte register offset
+#define CSR 0x10
+#define PR 0x11
+
+#define MSR_RST 0x80
+#define MSR_MEMB 0x40
+#define MSR_0WS 0x20
+
+#define FORCED_16BIT_MODE 0x0002
+
+#define INTERFRAME_SPACING_16 0x0003 /* 6 bytes */
+#define INTERFRAME_SPACING_4 0x0001 /* 2 bytes */
+#define MULTICAST_ADDRESS_BIT 0x0010
+#define NON_SRC_ROUTING_BIT 0x0020
+
+#define LOOPING_MODE_MASK 0x0007
+
+/*
+ * Decode firmware defines.
+ */
+#define SWAP_BYTES(X) ((X & 0xff) << 8) | (X >> 8)
+#define WEIGHT_OFFSET 5
+#define TREE_SIZE_OFFSET 9
+#define TREE_OFFSET 11
+
+/* The Huffman Encoding Tree is constructed of these nodes. */
+typedef struct {
+ __u8 llink; /* Short version of above node. */
+ __u8 tag;
+ __u8 info; /* This node is used on decodes. */
+ __u8 rlink;
+} DECODE_TREE_NODE;
+
+#define ROOT 0 /* Branch value. */
+#define LEAF 0 /* Tag field value. */
+#define BRANCH 1 /* Tag field value. */
+
+/*
+ * Multicast Table Structure
+ */
+typedef struct {
+ __u8 address[6];
+ __u8 instance_count;
+} McTable;
+
+/*
+ * Fragment Descriptor Definition
+ */
+typedef struct {
+ __u8 *fragment_ptr;
+ __u32 fragment_length;
+} FragmentStructure;
+
+/*
+ * Data Buffer Structure Definition
+ */
+typedef struct {
+ __u32 fragment_count;
+ FragmentStructure fragment_list[MAXFRAGMENTS];
+} DataBufferStructure;
+
+#pragma pack(1)
+typedef struct {
+ __u8 IType;
+ __u8 ISubtype;
+} Interrupt_Status_Word;
+
+#pragma pack(1)
+typedef struct BDBlockType {
+ __u16 info; /* 02 */
+ __u32 trc_next_ptr; /* 06 */
+ __u32 trc_data_block_ptr; /* 10 */
+ __u16 buffer_length; /* 12 */
+
+ __u16 *data_block_ptr; /* 16 */
+ struct BDBlockType *next_ptr; /* 20 */
+ struct BDBlockType *back_ptr; /* 24 */
+ __u8 filler[8]; /* 32 */
+} BDBlock;
+
+#pragma pack(1)
+typedef struct FCBlockType {
+ __u16 frame_status; /* 02 */
+ __u16 info; /* 04 */
+ __u32 trc_next_ptr; /* 08 */
+ __u32 trc_bdb_ptr; /* 12 */
+ __u16 frame_length; /* 14 */
+
+ BDBlock *bdb_ptr; /* 18 */
+ struct FCBlockType *next_ptr; /* 22 */
+ struct FCBlockType *back_ptr; /* 26 */
+ __u16 memory_alloc; /* 28 */
+ __u8 filler[4]; /* 32 */
+
+} FCBlock;
+
+#pragma pack(1)
+typedef struct SBlockType{
+ __u8 Internal_Error_Count;
+ __u8 Line_Error_Count;
+ __u8 AC_Error_Count;
+ __u8 Burst_Error_Count;
+ __u8 RESERVED_COUNTER_0;
+ __u8 AD_TRANS_Count;
+ __u8 RCV_Congestion_Count;
+ __u8 Lost_FR_Error_Count;
+ __u8 FREQ_Error_Count;
+ __u8 FR_Copied_Error_Count;
+ __u8 RESERVED_COUNTER_1;
+ __u8 Token_Error_Count;
+
+ __u16 TI_NDIS_Ring_Status;
+ __u16 BCN_Type;
+ __u16 Error_Code;
+ __u16 SA_of_Last_AMP_SMP[3];
+ __u16 UNA[3];
+ __u16 Ucode_Version_Number;
+ __u16 Status_CHG_Indicate;
+ __u16 RESERVED_STATUS_0;
+} SBlock;
+
+#pragma pack(1)
+typedef struct ACBlockType {
+ __u16 cmd_done_status; /* 02 */
+ __u16 cmd_info; /* 04 */
+ __u32 trc_next_ptr; /* 08 */
+ __u16 cmd; /* 10 */
+ __u16 subcmd; /* 12 */
+ __u16 data_offset_lo; /* 14 */
+ __u16 data_offset_hi; /* 16 */
+
+ struct ACBlockType *next_ptr; /* 20 */
+
+ __u8 filler[12]; /* 32 */
+} ACBlock;
+
+#define NUM_OF_INTERRUPTS 0x20
+
+#pragma pack(1)
+typedef struct {
+ Interrupt_Status_Word IStatus[NUM_OF_INTERRUPTS];
+} ISBlock;
+
+#pragma pack(1)
+typedef struct {
+ __u16 valid_command; /* 02 */
+ __u16 iack_code; /* 04 */
+ __u16 resume_control; /* 06 */
+ __u16 int_mask_control; /* 08 */
+ __u16 int_mask_state; /* 10 */
+
+ __u8 filler[6]; /* 16 */
+} SCLBlock;
+
+#pragma pack(1)
+typedef struct
+{
+ __u16 config; /* 02 */
+ __u32 trc_sclb_ptr; /* 06 */
+ __u32 trc_acb_ptr; /* 10 */
+ __u32 trc_isb_ptr; /* 14 */
+ __u16 isbsiz; /* 16 */
+
+ SCLBlock *sclb_ptr; /* 20 */
+ ACBlock *acb_ptr; /* 24 */
+ ISBlock *isb_ptr; /* 28 */
+
+ __u16 Non_Mac_Rx_Bdbs; /* 30 DEBUG */
+ __u8 filler[2]; /* 32 */
+
+} SCGBlock;
+
+#pragma pack(1)
+typedef struct
+{
+ __u32 trc_scgb_ptr;
+ SCGBlock *scgb_ptr;
+} ISCPBlock;
+#pragma pack()
+
+typedef struct net_local {
+ ISCPBlock *iscpb_ptr;
+ SCGBlock *scgb_ptr;
+ SCLBlock *sclb_ptr;
+ ISBlock *isb_ptr;
+
+ ACBlock *acb_head;
+ ACBlock *acb_curr;
+ ACBlock *acb_next;
+
+ __u8 adapter_name[12];
+
+ __u16 num_rx_bdbs [NUM_RX_QS_USED];
+ __u16 num_rx_fcbs [NUM_RX_QS_USED];
+
+ __u16 num_tx_bdbs [NUM_TX_QS_USED];
+ __u16 num_tx_fcbs [NUM_TX_QS_USED];
+
+ __u16 num_of_tx_buffs;
+
+ __u16 tx_buff_size [NUM_TX_QS_USED];
+ __u16 tx_buff_used [NUM_TX_QS_USED];
+ __u16 tx_queue_status [NUM_TX_QS_USED];
+
+ FCBlock *tx_fcb_head[NUM_TX_QS_USED];
+ FCBlock *tx_fcb_curr[NUM_TX_QS_USED];
+ FCBlock *tx_fcb_end[NUM_TX_QS_USED];
+ BDBlock *tx_bdb_head[NUM_TX_QS_USED];
+ __u16 *tx_buff_head[NUM_TX_QS_USED];
+ __u16 *tx_buff_end[NUM_TX_QS_USED];
+ __u16 *tx_buff_curr[NUM_TX_QS_USED];
+ __u16 num_tx_fcbs_used[NUM_TX_QS_USED];
+
+ FCBlock *rx_fcb_head[NUM_RX_QS_USED];
+ FCBlock *rx_fcb_curr[NUM_RX_QS_USED];
+ BDBlock *rx_bdb_head[NUM_RX_QS_USED];
+ BDBlock *rx_bdb_curr[NUM_RX_QS_USED];
+ BDBlock *rx_bdb_end[NUM_RX_QS_USED];
+ __u16 *rx_buff_head[NUM_RX_QS_USED];
+ __u16 *rx_buff_end[NUM_RX_QS_USED];
+
+ __u32 *ptr_local_ring_num;
+
+ __u32 sh_mem_used;
+
+ __u16 page_offset_mask;
+
+ __u16 authorized_function_classes;
+ __u16 authorized_access_priority;
+
+ __u16 num_acbs;
+ __u16 num_acbs_used;
+ __u16 acb_pending;
+
+ __u16 current_isb_index;
+
+ __u8 monitor_state;
+ __u8 monitor_state_ready;
+ __u16 ring_status;
+ __u8 ring_status_flags;
+ __u8 current_ring_status;
+ __u8 state;
+
+ __u8 join_state;
+
+ __u8 slot_num;
+ __u16 pos_id;
+
+ __u32 *ptr_una;
+ __u32 *ptr_bcn_type;
+ __u32 *ptr_tx_fifo_underruns;
+ __u32 *ptr_rx_fifo_underruns;
+ __u32 *ptr_rx_fifo_overruns;
+ __u32 *ptr_tx_fifo_overruns;
+ __u32 *ptr_tx_fcb_overruns;
+ __u32 *ptr_rx_fcb_overruns;
+ __u32 *ptr_tx_bdb_overruns;
+ __u32 *ptr_rx_bdb_overruns;
+
+ __u16 receive_queue_number;
+
+ __u8 rx_fifo_overrun_count;
+ __u8 tx_fifo_overrun_count;
+
+ __u16 adapter_flags;
+ __u16 adapter_flags1;
+ __u16 *misc_command_data;
+ __u16 max_packet_size;
+
+ __u16 config_word0;
+ __u16 config_word1;
+
+ __u8 trc_mask;
+
+ __u16 source_ring_number;
+ __u16 target_ring_number;
+
+ __u16 microcode_version;
+
+ __u16 bic_type;
+ __u16 nic_type;
+ __u16 board_id;
+
+ __u16 rom_size;
+ __u32 rom_base;
+ __u16 ram_size;
+ __u16 ram_usable;
+ __u32 ram_base;
+ __u32 ram_access;
+
+ __u16 extra_info;
+ __u16 mode_bits;
+ __u16 media_menu;
+ __u16 media_type;
+ __u16 adapter_bus;
+
+ __u16 status;
+ __u16 receive_mask;
+
+ __u16 group_address_0;
+ __u16 group_address[2];
+ __u16 functional_address_0;
+ __u16 functional_address[2];
+ __u16 bitwise_group_address[2];
+
+ __u8 *ptr_ucode;
+
+ __u8 cleanup;
+
+ struct sk_buff_head SendSkbQueue;
+ __u16 QueueSkb;
+
+ struct tr_statistics MacStat; /* MAC statistics structure */
+
+ spinlock_t lock;
+} NET_LOCAL;
+
+/************************************
+ * SNMP-ON-BOARD Agent Link Structure
+ ************************************/
+
+typedef struct {
+ __u8 LnkSigStr[12]; /* signature string "SmcLinkTable" */
+ __u8 LnkDrvTyp; /* 1=Redbox ODI, 2=ODI DOS, 3=ODI OS/2, 4=NDIS DOS */
+ __u8 LnkFlg; /* 0 if no agent linked, 1 if agent linked */
+ void *LnkNfo; /* routine which returns pointer to NIC info */
+ void *LnkAgtRcv; /* pointer to agent receive trap entry */
+ void *LnkAgtXmt; /* pointer to agent transmit trap
+entry */
+void *LnkGet; /* pointer to NIC receive data
+copy routine */
+ void *LnkSnd; /* pointer to NIC send routine
+*/
+ void *LnkRst; /* pointer to NIC driver reset
+routine */
+ void *LnkMib; /* pointer to MIB data base */
+ void *LnkMibAct; /* pointer to MIB action routine list */
+ __u16 LnkCntOffset; /* offset to error counters */
+ __u16 LnkCntNum; /* number of error counters */
+ __u16 LnkCntSize; /* size of error counters i.e. 32 = 32 bits */
+ void *LnkISR; /* pointer to interrupt vector */
+ __u8 LnkFrmTyp; /* 1=Ethernet, 2=Token Ring */
+ __u8 LnkDrvVer1 ; /* driver major version */
+ __u8 LnkDrvVer2 ; /* driver minor version */
+} AgentLink;
+
+/*
+ * Definitions for pcm_card_flags(bit_mapped)
+ */
+#define REG_COMPLETE 0x0001
+#define INSERTED 0x0002
+#define PCC_INSERTED 0x0004 /* 1=currently inserted, 0=cur removed */
+
+/*
+ * Adapter RAM test patterns
+ */
+#define RAM_PATTERN_1 0x55AA
+#define RAM_PATTERN_2 0x9249
+#define RAM_PATTERN_3 0xDB6D
+
+/*
+ * definitions for RAM test
+ */
+#define ROM_SIGNATURE 0xAA55
+#define MIN_ROM_SIZE 0x2000
+
+/*
+ * Return Codes
+ */
+#define SUCCESS 0x0000
+#define ADAPTER_AND_CONFIG 0x0001
+#define ADAPTER_NO_CONFIG 0x0002
+#define NOT_MY_INTERRUPT 0x0003
+#define FRAME_REJECTED 0x0004
+#define EVENTS_DISABLED 0x0005
+#define OUT_OF_RESOURCES 0x0006
+#define INVALID_PARAMETER 0x0007
+#define INVALID_FUNCTION 0x0008
+#define INITIALIZE_FAILED 0x0009
+#define CLOSE_FAILED 0x000A
+#define MAX_COLLISIONS 0x000B
+#define NO_SUCH_DESTINATION 0x000C
+#define BUFFER_TOO_SMALL_ERROR 0x000D
+#define ADAPTER_CLOSED 0x000E
+#define UCODE_NOT_PRESENT 0x000F
+#define FIFO_UNDERRUN 0x0010
+#define DEST_OUT_OF_RESOURCES 0x0011
+#define ADAPTER_NOT_INITIALIZED 0x0012
+#define PENDING 0x0013
+#define UCODE_PRESENT 0x0014
+#define NOT_INIT_BY_BRIDGE 0x0015
+
+#define OPEN_FAILED 0x0080
+#define HARDWARE_FAILED 0x0081
+#define SELF_TEST_FAILED 0x0082
+#define RAM_TEST_FAILED 0x0083
+#define RAM_CONFLICT 0x0084
+#define ROM_CONFLICT 0x0085
+#define UNKNOWN_ADAPTER 0x0086
+#define CONFIG_ERROR 0x0087
+#define CONFIG_WARNING 0x0088
+#define NO_FIXED_CNFG 0x0089
+#define EEROM_CKSUM_ERROR 0x008A
+#define ROM_SIGNATURE_ERROR 0x008B
+#define ROM_CHECKSUM_ERROR 0x008C
+#define ROM_SIZE_ERROR 0x008D
+#define UNSUPPORTED_NIC_CHIP 0x008E
+#define NIC_REG_ERROR 0x008F
+#define BIC_REG_ERROR 0x0090
+#define MICROCODE_TEST_ERROR 0x0091
+#define LOBE_MEDIA_TEST_FAILED 0x0092
+
+#define ADAPTER_FOUND_LAN_CORRUPT 0x009B
+
+#define ADAPTER_NOT_FOUND 0xFFFF
+
+#define ILLEGAL_FUNCTION INVALID_FUNCTION
+
+/* Errors */
+#define IO_BASE_INVALID 0x0001
+#define IO_BASE_RANGE 0x0002
+#define IRQ_INVALID 0x0004
+#define IRQ_RANGE 0x0008
+#define RAM_BASE_INVALID 0x0010
+#define RAM_BASE_RANGE 0x0020
+#define RAM_SIZE_RANGE 0x0040
+#define MEDIA_INVALID 0x0800
+
+/* Warnings */
+#define IRQ_MISMATCH 0x0080
+#define RAM_BASE_MISMATCH 0x0100
+#define RAM_SIZE_MISMATCH 0x0200
+#define BUS_MODE_MISMATCH 0x0400
+
+#define RX_CRC_ERROR 0x01
+#define RX_ALIGNMENT_ERROR 0x02
+#define RX_HW_FAILED 0x80
+
+/*
+ * Definitions for the field RING_STATUS_FLAGS
+ */
+#define RING_STATUS_CHANGED 0X01
+#define MONITOR_STATE_CHANGED 0X02
+#define JOIN_STATE_CHANGED 0X04
+
+/*
+ * Definitions for the field JOIN_STATE
+ */
+#define JS_BYPASS_STATE 0x00
+#define JS_LOBE_TEST_STATE 0x01
+#define JS_DETECT_MONITOR_PRESENT_STATE 0x02
+#define JS_AWAIT_NEW_MONITOR_STATE 0x03
+#define JS_DUPLICATE_ADDRESS_TEST_STATE 0x04
+#define JS_NEIGHBOR_NOTIFICATION_STATE 0x05
+#define JS_REQUEST_INITIALIZATION_STATE 0x06
+#define JS_JOIN_COMPLETE_STATE 0x07
+#define JS_BYPASS_WAIT_STATE 0x08
+
+/*
+ * Definitions for the field MONITOR_STATE
+ */
+#define MS_MONITOR_FSM_INACTIVE 0x00
+#define MS_REPEAT_BEACON_STATE 0x01
+#define MS_REPEAT_CLAIM_TOKEN_STATE 0x02
+#define MS_TRANSMIT_CLAIM_TOKEN_STATE 0x03
+#define MS_STANDBY_MONITOR_STATE 0x04
+#define MS_TRANSMIT_BEACON_STATE 0x05
+#define MS_ACTIVE_MONITOR_STATE 0x06
+#define MS_TRANSMIT_RING_PURGE_STATE 0x07
+#define MS_BEACON_TEST_STATE 0x09
+
+/*
+ * Definitions for the bit-field RING_STATUS
+ */
+#define SIGNAL_LOSS 0x8000
+#define HARD_ERROR 0x4000
+#define SOFT_ERROR 0x2000
+#define TRANSMIT_BEACON 0x1000
+#define LOBE_WIRE_FAULT 0x0800
+#define AUTO_REMOVAL_ERROR 0x0400
+#define REMOVE_RECEIVED 0x0100
+#define COUNTER_OVERFLOW 0x0080
+#define SINGLE_STATION 0x0040
+#define RING_RECOVERY 0x0020
+
+/*
+ * Definitions for the field BUS_TYPE
+ */
+#define AT_BUS 0x00
+#define MCA_BUS 0x01
+#define EISA_BUS 0x02
+#define PCI_BUS 0x03
+#define PCMCIA_BUS 0x04
+
+/*
+ * Definitions for adapter_flags
+ */
+#define RX_VALID_LOOKAHEAD 0x0001
+#define FORCED_16BIT_MODE 0x0002
+#define ADAPTER_DISABLED 0x0004
+#define TRANSMIT_CHAIN_INT 0x0008
+#define EARLY_RX_FRAME 0x0010
+#define EARLY_TX 0x0020
+#define EARLY_RX_COPY 0x0040
+#define USES_PHYSICAL_ADDR 0x0080 /* Rsvd for DEC PCI and 9232 */
+#define NEEDS_PHYSICAL_ADDR 0x0100 /* Reserved*/
+#define RX_STATUS_PENDING 0x0200
+#define ERX_DISABLED 0x0400 /* EARLY_RX_ENABLE rcv_mask */
+#define ENABLE_TX_PENDING 0x0800
+#define ENABLE_RX_PENDING 0x1000
+#define PERM_CLOSE 0x2000
+#define IO_MAPPED 0x4000 /* IOmapped bus interface 795 */
+#define ETX_DISABLED 0x8000
+
+
+/*
+ * Definitions for adapter_flags1
+ */
+#define TX_PHY_RX_VIRT 0x0001
+#define NEEDS_HOST_RAM 0x0002
+#define NEEDS_MEDIA_TYPE 0x0004
+#define EARLY_RX_DONE 0x0008
+#define PNP_BOOT_BIT 0x0010 /* activates PnP & config on power-up */
+ /* clear => regular PnP operation */
+#define PNP_ENABLE 0x0020 /* regular PnP operation clear => */
+ /* no PnP, overrides PNP_BOOT_BIT */
+#define SATURN_ENABLE 0x0040
+
+#define ADAPTER_REMOVABLE 0x0080 /* adapter is hot swappable */
+#define TX_PHY 0x0100 /* Uses physical address for tx bufs */
+#define RX_PHY 0x0200 /* Uses physical address for rx bufs */
+#define TX_VIRT 0x0400 /* Uses virtual addr for tx bufs */
+#define RX_VIRT 0x0800
+#define NEEDS_SERVICE 0x1000
+
+/*
+ * Adapter Status Codes
+ */
+#define OPEN 0x0001
+#define INITIALIZED 0x0002
+#define CLOSED 0x0003
+#define FAILED 0x0005
+#define NOT_INITIALIZED 0x0006
+#define IO_CONFLICT 0x0007
+#define CARD_REMOVED 0x0008
+#define CARD_INSERTED 0x0009
+
+/*
+ * Mode Bit Definitions
+ */
+#define INTERRUPT_STATUS_BIT 0x8000 /* PC Interrupt Line: 0 = Not Enabled */
+#define BOOT_STATUS_MASK 0x6000 /* Mask to isolate BOOT_STATUS */
+#define BOOT_INHIBIT 0x0000 /* BOOT_STATUS is 'inhibited' */
+#define BOOT_TYPE_1 0x2000 /* Unused BOOT_STATUS value */
+#define BOOT_TYPE_2 0x4000 /* Unused BOOT_STATUS value */
+#define BOOT_TYPE_3 0x6000 /* Unused BOOT_STATUS value */
+#define ZERO_WAIT_STATE_MASK 0x1800 /* Mask to isolate Wait State flags */
+#define ZERO_WAIT_STATE_8_BIT 0x1000 /* 0 = Disabled (Inserts Wait States) */
+#define ZERO_WAIT_STATE_16_BIT 0x0800 /* 0 = Disabled (Inserts Wait States) */
+#define LOOPING_MODE_MASK 0x0007
+#define LOOPBACK_MODE_0 0x0000
+#define LOOPBACK_MODE_1 0x0001
+#define LOOPBACK_MODE_2 0x0002
+#define LOOPBACK_MODE_3 0x0003
+#define LOOPBACK_MODE_4 0x0004
+#define LOOPBACK_MODE_5 0x0005
+#define LOOPBACK_MODE_6 0x0006
+#define LOOPBACK_MODE_7 0x0007
+#define AUTO_MEDIA_DETECT 0x0008
+#define MANUAL_CRC 0x0010
+#define EARLY_TOKEN_REL 0x0020 /* Early Token Release for Token Ring */
+#define UMAC 0x0040
+#define UTP2_PORT 0x0080 /* For 8216T2, 0=port A, 1=Port B. */
+#define BNC_10BT_INTERFACE 0x0600 /* BNC and UTP current media set */
+#define UTP_INTERFACE 0x0500 /* Ethernet UTP Only. */
+#define BNC_INTERFACE 0x0400
+#define AUI_INTERFACE 0x0300
+#define AUI_10BT_INTERFACE 0x0200
+#define STARLAN_10_INTERFACE 0x0100
+#define INTERFACE_TYPE_MASK 0x0700
+
+/*
+ * Media Type Bit Definitions
+ *
+ * legend: TP = Twisted Pair
+ * STP = Shielded twisted pair
+ * UTP = Unshielded twisted pair
+ */
+
+#define CNFG_MEDIA_TYPE_MASK 0x001e /* POS Register 3 Mask */
+
+#define MEDIA_S10 0x0000 /* Ethernet adapter, TP. */
+#define MEDIA_AUI_UTP 0x0001 /* Ethernet adapter, AUI/UTP media */
+#define MEDIA_BNC 0x0002 /* Ethernet adapter, BNC media. */
+#define MEDIA_AUI 0x0003 /* Ethernet Adapter, AUI media. */
+#define MEDIA_STP_16 0x0004 /* TokenRing adap, 16Mbit STP. */
+#define MEDIA_STP_4 0x0005 /* TokenRing adap, 4Mbit STP. */
+#define MEDIA_UTP_16 0x0006 /* TokenRing adap, 16Mbit UTP. */
+#define MEDIA_UTP_4 0x0007 /* TokenRing adap, 4Mbit UTP. */
+#define MEDIA_UTP 0x0008 /* Ethernet adapter, UTP media (no AUI)
+*/
+#define MEDIA_BNC_UTP 0x0010 /* Ethernet adapter, BNC/UTP media */
+#define MEDIA_UTPFD 0x0011 /* Ethernet adapter, TP full duplex */
+#define MEDIA_UTPNL 0x0012 /* Ethernet adapter, TP with link integrity test disabled */
+#define MEDIA_AUI_BNC 0x0013 /* Ethernet adapter, AUI/BNC media */
+#define MEDIA_AUI_BNC_UTP 0x0014 /* Ethernet adapter, AUI_BNC/UTP */
+#define MEDIA_UTPA 0x0015 /* Ethernet UTP-10Mbps Ports A */
+#define MEDIA_UTPB 0x0016 /* Ethernet UTP-10Mbps Ports B */
+#define MEDIA_STP_16_UTP_16 0x0017 /* Token Ring STP-16Mbps/UTP-16Mbps */
+#define MEDIA_STP_4_UTP_4 0x0018 /* Token Ring STP-4Mbps/UTP-4Mbps */
+
+#define MEDIA_STP100_UTP100 0x0020 /* Ethernet STP-100Mbps/UTP-100Mbps */
+#define MEDIA_UTP100FD 0x0021 /* Ethernet UTP-100Mbps, full duplex */
+#define MEDIA_UTP100 0x0022 /* Ethernet UTP-100Mbps */
+
+
+#define MEDIA_UNKNOWN 0xFFFF /* Unknown adapter/media type */
+
+/*
+ * Definitions for the field:
+ * media_type2
+ */
+#define MEDIA_TYPE_MII 0x0001
+#define MEDIA_TYPE_UTP 0x0002
+#define MEDIA_TYPE_BNC 0x0004
+#define MEDIA_TYPE_AUI 0x0008
+#define MEDIA_TYPE_S10 0x0010
+#define MEDIA_TYPE_AUTO_SENSE 0x1000
+#define MEDIA_TYPE_AUTO_DETECT 0x4000
+#define MEDIA_TYPE_AUTO_NEGOTIATE 0x8000
+
+/*
+ * Definitions for the field:
+ * line_speed
+ */
+#define LINE_SPEED_UNKNOWN 0x0000
+#define LINE_SPEED_4 0x0001
+#define LINE_SPEED_10 0x0002
+#define LINE_SPEED_16 0x0004
+#define LINE_SPEED_100 0x0008
+#define LINE_SPEED_T4 0x0008 /* 100BaseT4 aliased for 9332BVT */
+#define LINE_SPEED_FULL_DUPLEX 0x8000
+
+/*
+ * Definitions for the field:
+ * bic_type (Bus interface chip type)
+ */
+#define BIC_NO_CHIP 0x0000 /* Bus interface chip not implemented */
+#define BIC_583_CHIP 0x0001 /* 83C583 bus interface chip */
+#define BIC_584_CHIP 0x0002 /* 83C584 bus interface chip */
+#define BIC_585_CHIP 0x0003 /* 83C585 bus interface chip */
+#define BIC_593_CHIP 0x0004 /* 83C593 bus interface chip */
+#define BIC_594_CHIP 0x0005 /* 83C594 bus interface chip */
+#define BIC_564_CHIP 0x0006 /* PCMCIA Bus interface chip */
+#define BIC_790_CHIP 0x0007 /* 83C790 bus i-face/Ethernet NIC chip */
+#define BIC_571_CHIP 0x0008 /* 83C571 EISA bus master i-face */
+#define BIC_587_CHIP 0x0009 /* Token Ring AT bus master i-face */
+#define BIC_574_CHIP 0x0010 /* FEAST bus interface chip */
+#define BIC_8432_CHIP 0x0011 /* 8432 bus i-face/Ethernet NIC(DEC PCI) */
+#define BIC_9332_CHIP 0x0012 /* 9332 bus i-face/100Mbps Ether NIC(DEC PCI) */
+#define BIC_8432E_CHIP 0x0013 /* 8432 Enhanced bus iface/Ethernet NIC(DEC) */
+#define BIC_EPIC100_CHIP 0x0014 /* EPIC/100 10/100 Mbps Ethernet BIC/NIC */
+#define BIC_C94_CHIP 0x0015 /* 91C94 bus i-face in PCMCIA mode */
+#define BIC_X8020_CHIP 0x0016 /* Xilinx PCMCIA multi-func i-face */
+
+/*
+ * Definitions for the field:
+ * nic_type (Bus interface chip type)
+ */
+#define NIC_UNK_CHIP 0x0000 /* Unknown NIC chip */
+#define NIC_8390_CHIP 0x0001 /* DP8390 Ethernet NIC */
+#define NIC_690_CHIP 0x0002 /* 83C690 Ethernet NIC */
+#define NIC_825_CHIP 0x0003 /* 83C825 Token Ring NIC */
+/* #define NIC_???_CHIP 0x0004 */ /* Not used */
+/* #define NIC_???_CHIP 0x0005 */ /* Not used */
+/* #define NIC_???_CHIP 0x0006 */ /* Not used */
+#define NIC_790_CHIP 0x0007 /* 83C790 bus i-face/Ethernet NIC chip */
+#define NIC_C100_CHIP 0x0010 /* FEAST 100Mbps Ethernet NIC */
+#define NIC_8432_CHIP 0x0011 /* 8432 bus i-face/Ethernet NIC(DEC PCI) */
+#define NIC_9332_CHIP 0x0012 /* 9332 bus i-face/100Mbps Ether NIC(DEC PCI) */
+#define NIC_8432E_CHIP 0x0013 /* 8432 enhanced bus iface/Ethernet NIC(DEC) */
+#define NIC_EPIC100_CHIP 0x0014 /* EPIC/100 10/100 Mbps Ethernet BIC/NIC */
+#define NIC_C94_CHIP 0x0015 /* 91C94 PC Card with multi func */
+
+/*
+ * Definitions for the field:
+ * adapter_type The adapter_type field describes the adapter/bus
+ * configuration.
+ */
+#define BUS_ISA16_TYPE 0x0001 /* 16 bit adap in 16 bit (E)ISA slot */
+#define BUS_ISA8_TYPE 0x0002 /* 8/16b adap in 8 bit XT/(E)ISA slot */
+#define BUS_MCA_TYPE 0x0003 /* Micro Channel adapter */
+
+/*
+ * Receive Mask definitions
+ */
+#define ACCEPT_MULTICAST 0x0001
+#define ACCEPT_BROADCAST 0x0002
+#define PROMISCUOUS_MODE 0x0004
+#define ACCEPT_SOURCE_ROUTING 0x0008
+#define ACCEPT_ERR_PACKETS 0x0010
+#define ACCEPT_ATT_MAC_FRAMES 0x0020
+#define ACCEPT_MULTI_PROM 0x0040
+#define TRANSMIT_ONLY 0x0080
+#define ACCEPT_EXT_MAC_FRAMES 0x0100
+#define EARLY_RX_ENABLE 0x0200
+#define PKT_SIZE_NOT_NEEDED 0x0400
+#define ACCEPT_SOURCE_ROUTING_SPANNING 0x0808
+
+#define ACCEPT_ALL_MAC_FRAMES 0x0120
+
+/*
+ * config_mode defs
+ */
+#define STORE_EEROM 0x0001 /* Store config in EEROM. */
+#define STORE_REGS 0x0002 /* Store config in register set. */
+
+/*
+ * equates for lmac_flags in adapter structure (Ethernet)
+ */
+#define MEM_DISABLE 0x0001
+#define RX_STATUS_POLL 0x0002
+#define USE_RE_BIT 0x0004
+/*#define RESERVED 0x0008 */
+/*#define RESERVED 0x0010 */
+/*#define RESERVED 0x0020 */
+/*#define RESERVED 0x0040 */
+/*#define RESERVED 0x0080 */
+/*#define RESERVED 0x0100 */
+/*#define RESERVED 0x0200 */
+/*#define RESERVED 0x0400 */
+/*#define RESERVED 0x0800 */
+/*#define RESERVED 0x1000 */
+/*#define RESERVED 0x2000 */
+/*#define RESERVED 0x4000 */
+/*#define RESERVED 0x8000 */
+
+/* media_opts & media_set Fields bit defs for Ethernet ... */
+#define MED_OPT_BNC 0x01
+#define MED_OPT_UTP 0x02
+#define MED_OPT_AUI 0x04
+#define MED_OPT_10MB 0x08
+#define MED_OPT_100MB 0x10
+#define MED_OPT_S10 0x20
+
+/* media_opts & media_set Fields bit defs for Token Ring ... */
+#define MED_OPT_4MB 0x08
+#define MED_OPT_16MB 0x10
+#define MED_OPT_STP 0x40
+
+#define MAX_8023_SIZE 1500 /* Max 802.3 size of frame. */
+#define DEFAULT_ERX_VALUE 4 /* Number of 16-byte blocks for 790B early Rx. */
+#define DEFAULT_ETX_VALUE 32 /* Number of bytes for 790B early Tx. */
+#define DEFAULT_TX_RETRIES 3 /* Number of transmit retries */
+#define LPBK_FRAME_SIZE 1024 /* Default loopback frame for Rx calibration test. */
+#define MAX_LOOKAHEAD_SIZE 252 /* Max lookahead size for ethernet. */
+
+#define RW_MAC_STATE 0x1101
+#define RW_SA_OF_LAST_AMP_OR_SMP 0x2803
+#define RW_PHYSICAL_DROP_NUMBER 0x3B02
+#define RW_UPSTREAM_NEIGHBOR_ADDRESS 0x3E03
+#define RW_PRODUCT_INSTANCE_ID 0x4B09
+
+#define RW_TRC_STATUS_BLOCK 0x5412
+
+#define RW_MAC_ERROR_COUNTERS_NO_CLEAR 0x8006
+#define RW_MAC_ERROR_COUNTER_CLEAR 0x7A06
+#define RW_CONFIG_REGISTER_0 0xA001
+#define RW_CONFIG_REGISTER_1 0xA101
+#define RW_PRESCALE_TIMER_THRESHOLD 0xA201
+#define RW_TPT_THRESHOLD 0xA301
+#define RW_TQP_THRESHOLD 0xA401
+#define RW_TNT_THRESHOLD 0xA501
+#define RW_TBT_THRESHOLD 0xA601
+#define RW_TSM_THRESHOLD 0xA701
+#define RW_TAM_THRESHOLD 0xA801
+#define RW_TBR_THRESHOLD 0xA901
+#define RW_TER_THRESHOLD 0xAA01
+#define RW_TGT_THRESHOLD 0xAB01
+#define RW_THT_THRESHOLD 0xAC01
+#define RW_TRR_THRESHOLD 0xAD01
+#define RW_TVX_THRESHOLD 0xAE01
+#define RW_INDIVIDUAL_MAC_ADDRESS 0xB003
+
+#define RW_INDIVIDUAL_GROUP_ADDRESS 0xB303 /* all of group addr */
+#define RW_INDIVIDUAL_GROUP_ADDR_WORD_0 0xB301 /* 1st word of group addr */
+#define RW_INDIVIDUAL_GROUP_ADDR 0xB402 /* 2nd-3rd word of group addr */
+#define RW_FUNCTIONAL_ADDRESS 0xB603 /* all of functional addr */
+#define RW_FUNCTIONAL_ADDR_WORD_0 0xB601 /* 1st word of func addr */
+#define RW_FUNCTIONAL_ADDR 0xB702 /* 2nd-3rd word func addr */
+
+#define RW_BIT_SIGNIFICANT_GROUP_ADDR 0xB902
+#define RW_SOURCE_RING_BRIDGE_NUMBER 0xBB01
+#define RW_TARGET_RING_NUMBER 0xBC01
+
+#define RW_HIC_INTERRUPT_MASK 0xC601
+
+#define SOURCE_ROUTING_SPANNING_BITS 0x00C0 /* Spanning Tree Frames */
+#define SOURCE_ROUTING_EXPLORER_BIT 0x0040 /* Explorer and Single Route */
+
+ /* write */
+
+#define CSR_MSK_ALL 0x80 // Bic 587 Only
+#define CSR_MSKTINT 0x20
+#define CSR_MSKCBUSY 0x10
+#define CSR_CLRTINT 0x08
+#define CSR_CLRCBUSY 0x04
+#define CSR_WCSS 0x02
+#define CSR_CA 0x01
+
+ /* read */
+
+#define CSR_TINT 0x20
+#define CSR_CINT 0x10
+#define CSR_TSTAT 0x08
+#define CSR_CSTAT 0x04
+#define CSR_FAULT 0x02
+#define CSR_CBUSY 0x01
+
+#define LAAR_MEM16ENB 0x80
+#define Zws16 0x20
+
+#define IRR_IEN 0x80
+#define Zws8 0x01
+
+#define IMCCR_EIL 0x04
+
+typedef struct {
+ __u8 ac; /* Access Control */
+ __u8 fc; /* Frame Control */
+ __u8 da[6]; /* Dest Addr */
+ __u8 sa[6]; /* Source Addr */
+
+ __u16 vl; /* Vector Length */
+ __u8 dc_sc; /* Dest/Source Class */
+ __u8 vc; /* Vector Code */
+ } MAC_HEADER;
+
+#define MAX_SUB_VECTOR_INFO (RX_DATA_BUFFER_SIZE - sizeof(MAC_HEADER) - 2)
+
+typedef struct
+ {
+ __u8 svl; /* Sub-vector Length */
+ __u8 svi; /* Sub-vector Code */
+ __u8 svv[MAX_SUB_VECTOR_INFO]; /* Sub-vector Info */
+ } MAC_SUB_VECTOR;
+
+#endif /* __KERNEL__ */
+#endif /* __LINUX_SMCTR_H */
diff --git a/drivers/net/tokenring/smctr_firmware.h b/drivers/net/tokenring/smctr_firmware.h
new file mode 100644
index 00000000000..53f2cbc817c
--- /dev/null
+++ b/drivers/net/tokenring/smctr_firmware.h
@@ -0,0 +1,979 @@
+/*
+ * The firmware this driver downloads into the tokenring card is a
+ * separate program and is not GPL'd source code, even though the Linux
+ * side driver and the routine that loads this data into the card are.
+ *
+ * This firmware is licensed to you strictly for use in conjunction
+ * with the use of SMC TokenRing adapters. There is no waranty
+ * expressed or implied about its fitness for any purpose.
+ */
+
+/* smctr_firmware.h: SMC TokenRing driver firmware dump for Linux.
+ *
+ * Notes:
+ * - This is an 8K binary image. (MCT.BIN v6.3C1 03/01/95)
+ *
+ * Authors:
+ * - Jay Schulist <jschlst@samba.org>
+ */
+
+#include <linux/config.h>
+
+#if defined(CONFIG_SMCTR) || defined(CONFIG_SMCTR_MODULE)
+
+unsigned char smctr_code[] = {
+ 0x0BC, 0x01D, 0x012, 0x03B, 0x063, 0x0B4, 0x0E9, 0x000,
+ 0x000, 0x01F, 0x000, 0x001, 0x001, 0x000, 0x002, 0x005,
+ 0x001, 0x000, 0x006, 0x003, 0x001, 0x000, 0x004, 0x009,
+ 0x001, 0x000, 0x00A, 0x007, 0x001, 0x000, 0x008, 0x00B,
+ 0x001, 0x000, 0x00C, 0x000, 0x000, 0x000, 0x000, 0x00F,
+ 0x001, 0x000, 0x010, 0x00D, 0x001, 0x000, 0x00E, 0x013,
+ 0x001, 0x000, 0x014, 0x011, 0x001, 0x000, 0x012, 0x000,
+ 0x000, 0x005, 0x000, 0x015, 0x001, 0x000, 0x016, 0x019,
+ 0x001, 0x000, 0x01A, 0x017, 0x001, 0x000, 0x018, 0x000,
+ 0x000, 0x00E, 0x000, 0x000, 0x000, 0x001, 0x000, 0x000,
+ 0x000, 0x004, 0x000, 0x01B, 0x001, 0x000, 0x01C, 0x000,
+ 0x000, 0x007, 0x000, 0x000, 0x000, 0x00F, 0x000, 0x000,
+ 0x000, 0x00B, 0x000, 0x01D, 0x001, 0x000, 0x01E, 0x000,
+ 0x000, 0x008, 0x000, 0x000, 0x000, 0x002, 0x000, 0x000,
+ 0x000, 0x00C, 0x000, 0x000, 0x000, 0x006, 0x000, 0x000,
+ 0x000, 0x00D, 0x000, 0x000, 0x000, 0x003, 0x000, 0x000,
+ 0x000, 0x00A, 0x000, 0x000, 0x000, 0x009, 0x000, 0x004,
+ 0x078, 0x0C6, 0x0BC, 0x001, 0x094, 0x004, 0x093, 0x080,
+ 0x0C8, 0x040, 0x062, 0x0E9, 0x0DA, 0x01C, 0x02C, 0x015,
+ 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x058,
+ 0x00B, 0x0E9, 0x0E5, 0x0D5, 0x095, 0x0C1, 0x09D, 0x077,
+ 0x0CE, 0x0BB, 0x0A0, 0x06E, 0x01C, 0x005, 0x0F6, 0x077,
+ 0x0C6, 0x002, 0x0FA, 0x096, 0x070, 0x0E8, 0x01D, 0x0C0,
+ 0x017, 0x00E, 0x002, 0x0FA, 0x058, 0x07D, 0x0C0, 0x05F,
+ 0x072, 0x0CE, 0x0EC, 0x0A4, 0x0C3, 0x084, 0x090, 0x07A,
+ 0x030, 0x0CD, 0x08D, 0x079, 0x019, 0x0E7, 0x06C, 0x024,
+ 0x027, 0x09C, 0x008, 0x039, 0x007, 0x038, 0x0A8, 0x04A,
+ 0x04C, 0x0EA, 0x04D, 0x098, 0x09B, 0x024, 0x04C, 0x0C0,
+ 0x026, 0x0D3, 0x0E7, 0x054, 0x05A, 0x04D, 0x0F2, 0x04C,
+ 0x00C, 0x013, 0x023, 0x049, 0x090, 0x032, 0x06E, 0x0A4,
+ 0x0DF, 0x093, 0x071, 0x013, 0x077, 0x026, 0x0E1, 0x026,
+ 0x0F8, 0x026, 0x00C, 0x04C, 0x012, 0x026, 0x008, 0x009,
+ 0x082, 0x082, 0x060, 0x0A9, 0x030, 0x079, 0x036, 0x0B0,
+ 0x0B2, 0x0A8, 0x0A7, 0x072, 0x064, 0x08F, 0x09B, 0x033,
+ 0x033, 0x0F9, 0x0B8, 0x039, 0x0D5, 0x011, 0x073, 0x0AA,
+ 0x075, 0x026, 0x05D, 0x026, 0x051, 0x093, 0x02A, 0x049,
+ 0x094, 0x0C9, 0x095, 0x089, 0x0BC, 0x04D, 0x0C8, 0x09B,
+ 0x080, 0x09B, 0x0A0, 0x099, 0x006, 0x04C, 0x086, 0x026,
+ 0x058, 0x09B, 0x0A4, 0x09B, 0x099, 0x037, 0x062, 0x06C,
+ 0x067, 0x09B, 0x033, 0x030, 0x0BF, 0x036, 0x066, 0x061,
+ 0x0BF, 0x036, 0x0EC, 0x0C5, 0x0BD, 0x066, 0x082, 0x05A,
+ 0x050, 0x031, 0x0D5, 0x09D, 0x098, 0x018, 0x029, 0x03C,
+ 0x098, 0x086, 0x04C, 0x017, 0x026, 0x03E, 0x02C, 0x0B8,
+ 0x069, 0x03B, 0x049, 0x02E, 0x0B4, 0x008, 0x043, 0x01A,
+ 0x0A4, 0x0F9, 0x0B3, 0x051, 0x0F1, 0x010, 0x0F3, 0x043,
+ 0x0CD, 0x008, 0x06F, 0x063, 0x079, 0x0B3, 0x033, 0x00E,
+ 0x013, 0x098, 0x049, 0x098, 0x004, 0x0DA, 0x07C, 0x0E0,
+ 0x052, 0x079, 0x031, 0x00C, 0x098, 0x02E, 0x04D, 0x0AC,
+ 0x02C, 0x084, 0x014, 0x0EE, 0x04C, 0x0FE, 0x067, 0x05E,
+ 0x0E4, 0x09A, 0x075, 0x029, 0x0D7, 0x0A9, 0x035, 0x03A,
+ 0x094, 0x05B, 0x0D5, 0x09B, 0x058, 0x0B4, 0x0AF, 0x075,
+ 0x066, 0x0AF, 0x014, 0x0A9, 0x0EF, 0x040, 0x095, 0x025,
+ 0x008, 0x0B9, 0x0AD, 0x042, 0x0FC, 0x0D8, 0x0D9, 0x08C,
+ 0x033, 0x00E, 0x013, 0x098, 0x066, 0x01E, 0x045, 0x0AC,
+ 0x0B0, 0x00C, 0x042, 0x0D3, 0x0CC, 0x0A6, 0x012, 0x062,
+ 0x0DE, 0x0B4, 0x0B1, 0x080, 0x049, 0x07D, 0x0A2, 0x0DE,
+ 0x0B4, 0x018, 0x0C0, 0x024, 0x084, 0x0E6, 0x054, 0x0F5,
+ 0x083, 0x046, 0x001, 0x068, 0x01A, 0x063, 0x00C, 0x0C6,
+ 0x012, 0x064, 0x0FA, 0x04C, 0x035, 0x01C, 0x02C, 0x00E,
+ 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA,
+ 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AD, 0x0D7, 0x002,
+ 0x070, 0x0E0, 0x04C, 0x0F3, 0x0A1, 0x0C1, 0x0D5, 0x0C0,
+ 0x03C, 0x0B9, 0x069, 0x039, 0x060, 0x04E, 0x058, 0x077,
+ 0x002, 0x067, 0x093, 0x03C, 0x099, 0x0E4, 0x0CF, 0x038,
+ 0x01C, 0x097, 0x02E, 0x040, 0x01B, 0x090, 0x031, 0x046,
+ 0x0A3, 0x05E, 0x00E, 0x088, 0x034, 0x06A, 0x035, 0x0E0,
+ 0x0E8, 0x0AA, 0x035, 0x01A, 0x0A9, 0x0F5, 0x015, 0x046,
+ 0x0A3, 0x0EA, 0x07D, 0x04A, 0x0A3, 0x051, 0x0AA, 0x09F,
+ 0x070, 0x054, 0x0A6, 0x057, 0x02E, 0x0B4, 0x0CD, 0x0C8,
+ 0x0A3, 0x00C, 0x0C1, 0x0DA, 0x0C6, 0x0E1, 0x0CB, 0x07A,
+ 0x0D4, 0x01C, 0x068, 0x0FF, 0x0CF, 0x055, 0x0A8, 0x0C0,
+ 0x02D, 0x085, 0x011, 0x017, 0x044, 0x02A, 0x030, 0x00B,
+ 0x04A, 0x088, 0x0C2, 0x04D, 0x0B5, 0x020, 0x0D5, 0x026,
+ 0x001, 0x069, 0x051, 0x069, 0x052, 0x019, 0x052, 0x060,
+ 0x016, 0x095, 0x016, 0x082, 0x096, 0x054, 0x098, 0x005,
+ 0x0A5, 0x045, 0x0F3, 0x0DD, 0x06A, 0x0F9, 0x028, 0x018,
+ 0x0EF, 0x000, 0x030, 0x030, 0x051, 0x04E, 0x044, 0x05D,
+ 0x012, 0x0D1, 0x043, 0x0E6, 0x012, 0x06F, 0x09E, 0x0BA,
+ 0x0CC, 0x0DF, 0x025, 0x003, 0x01D, 0x0E0, 0x006, 0x006,
+ 0x00A, 0x030, 0x0CC, 0x0A9, 0x0EB, 0x02D, 0x000, 0x086,
+ 0x0A6, 0x012, 0x065, 0x04F, 0x056, 0x0D6, 0x065, 0x049,
+ 0x05F, 0x03D, 0x0E8, 0x037, 0x0C9, 0x040, 0x0C7, 0x078,
+ 0x001, 0x081, 0x082, 0x08C, 0x033, 0x018, 0x049, 0x080,
+ 0x0AE, 0x040, 0x0C5, 0x018, 0x005, 0x09C, 0x06D, 0x018,
+ 0x066, 0x00E, 0x0F3, 0x0A0, 0x0C6, 0x012, 0x062, 0x0DE,
+ 0x0F5, 0x004, 0x0B4, 0x0AC, 0x06B, 0x0C6, 0x019, 0x091,
+ 0x073, 0x005, 0x048, 0x02E, 0x072, 0x094, 0x080, 0x073,
+ 0x0A1, 0x0C8, 0x047, 0x036, 0x066, 0x064, 0x02F, 0x036,
+ 0x066, 0x064, 0x007, 0x099, 0x002, 0x091, 0x08E, 0x072,
+ 0x0D1, 0x00F, 0x09D, 0x006, 0x031, 0x073, 0x0A0, 0x0C3,
+ 0x051, 0x06A, 0x01A, 0x020, 0x0BF, 0x03A, 0x00C, 0x02C,
+ 0x073, 0x087, 0x043, 0x05E, 0x060, 0x002, 0x023, 0x0FC,
+ 0x0E0, 0x0D6, 0x035, 0x0EF, 0x09E, 0x0F5, 0x0EF, 0x092,
+ 0x081, 0x08E, 0x0F0, 0x003, 0x003, 0x005, 0x018, 0x066,
+ 0x045, 0x0CC, 0x00B, 0x048, 0x02E, 0x070, 0x00A, 0x040,
+ 0x039, 0x0D0, 0x0E4, 0x023, 0x09B, 0x033, 0x032, 0x017,
+ 0x09B, 0x033, 0x032, 0x003, 0x0CC, 0x085, 0x048, 0x0C7,
+ 0x038, 0x014, 0x0A5, 0x0CE, 0x029, 0x07E, 0x0D2, 0x080,
+ 0x0A1, 0x0A8, 0x0B4, 0x048, 0x088, 0x02F, 0x0CE, 0x083,
+ 0x00B, 0x01C, 0x0E1, 0x0D0, 0x0D7, 0x098, 0x004, 0x088,
+ 0x087, 0x0CE, 0x096, 0x031, 0x073, 0x0A5, 0x08F, 0x0F3,
+ 0x083, 0x058, 0x0D7, 0x0BE, 0x07B, 0x082, 0x0AF, 0x092,
+ 0x081, 0x08E, 0x0F0, 0x003, 0x003, 0x005, 0x018, 0x066,
+ 0x045, 0x0CC, 0x015, 0x020, 0x0B9, 0x0C8, 0x029, 0x000,
+ 0x0E7, 0x043, 0x090, 0x08E, 0x06C, 0x0CC, 0x0C8, 0x05E,
+ 0x06C, 0x0CC, 0x0C8, 0x00F, 0x032, 0x005, 0x023, 0x01C,
+ 0x0E4, 0x050, 0x0D4, 0x05A, 0x017, 0x088, 0x02F, 0x0CE,
+ 0x083, 0x010, 0x0F9, 0x0D0, 0x023, 0x017, 0x03A, 0x004,
+ 0x035, 0x0E6, 0x000, 0x022, 0x016, 0x039, 0x0C3, 0x0A3,
+ 0x0FC, 0x0E0, 0x0D6, 0x035, 0x0E0, 0x0BF, 0x0F4, 0x018,
+ 0x0F2, 0x02D, 0x04D, 0x043, 0x051, 0x06E, 0x05A, 0x022,
+ 0x01F, 0x030, 0x0D4, 0x017, 0x0E7, 0x041, 0x091, 0x073,
+ 0x005, 0x048, 0x02E, 0x077, 0x069, 0x000, 0x0E7, 0x043,
+ 0x090, 0x08E, 0x06C, 0x0CC, 0x0C8, 0x05E, 0x06C, 0x0CC,
+ 0x0C8, 0x00F, 0x032, 0x005, 0x023, 0x01C, 0x0EF, 0x04C,
+ 0x04E, 0x006, 0x004, 0x0C9, 0x09E, 0x00B, 0x0FF, 0x041,
+ 0x08F, 0x022, 0x0D4, 0x0D4, 0x035, 0x016, 0x0E5, 0x0A2,
+ 0x021, 0x0F3, 0x05A, 0x082, 0x0FC, 0x0E8, 0x032, 0x02E,
+ 0x060, 0x0A9, 0x005, 0x0CE, 0x013, 0x048, 0x007, 0x03A,
+ 0x01C, 0x084, 0x073, 0x066, 0x066, 0x042, 0x0F3, 0x066,
+ 0x066, 0x040, 0x079, 0x090, 0x029, 0x018, 0x0E7, 0x00A,
+ 0x098, 0x09C, 0x00A, 0x09E, 0x0B5, 0x012, 0x05C, 0x07C,
+ 0x0C3, 0x031, 0x08B, 0x098, 0x02A, 0x07C, 0x0D3, 0x0ED,
+ 0x038, 0x0E9, 0x0D3, 0x04E, 0x074, 0x0ED, 0x049, 0x09E,
+ 0x00B, 0x0FF, 0x041, 0x08F, 0x022, 0x0D4, 0x0D4, 0x035,
+ 0x016, 0x0E5, 0x0A2, 0x02D, 0x0EB, 0x045, 0x033, 0x08F,
+ 0x0FC, 0x0F7, 0x0A0, 0x05F, 0x025, 0x003, 0x01D, 0x0E4,
+ 0x00E, 0x006, 0x00A, 0x030, 0x0CC, 0x00C, 0x0F3, 0x0EB,
+ 0x040, 0x0DE, 0x061, 0x0A8, 0x070, 0x092, 0x00A, 0x000,
+ 0x0E1, 0x024, 0x01E, 0x000, 0x0E1, 0x024, 0x01E, 0x000,
+ 0x0E1, 0x024, 0x01E, 0x000, 0x0E1, 0x024, 0x01E, 0x000,
+ 0x0E1, 0x024, 0x01E, 0x001, 0x00F, 0x098, 0x02A, 0x00B,
+ 0x0F3, 0x0A0, 0x0C8, 0x0B9, 0x0A2, 0x0A4, 0x017, 0x03A,
+ 0x069, 0x000, 0x0E7, 0x043, 0x090, 0x08E, 0x075, 0x048,
+ 0x05E, 0x070, 0x069, 0x001, 0x0E6, 0x000, 0x052, 0x031,
+ 0x0CC, 0x018, 0x014, 0x0A5, 0x0CC, 0x009, 0x082, 0x094,
+ 0x073, 0x00C, 0x0A0, 0x091, 0x0F5, 0x025, 0x0CC, 0x007,
+ 0x006, 0x084, 0x084, 0x09F, 0x030, 0x0A2, 0x0A4, 0x07D,
+ 0x050, 0x075, 0x0A6, 0x065, 0x001, 0x04A, 0x08E, 0x0B4,
+ 0x0CC, 0x0C4, 0x035, 0x054, 0x075, 0x066, 0x0A4, 0x097,
+ 0x07A, 0x089, 0x050, 0x053, 0x013, 0x080, 0x019, 0x0E3,
+ 0x049, 0x05C, 0x06D, 0x0CE, 0x0A9, 0x040, 0x035, 0x006,
+ 0x078, 0x0D2, 0x057, 0x006, 0x0F1, 0x0B3, 0x02A, 0x08D,
+ 0x097, 0x023, 0x062, 0x092, 0x05D, 0x069, 0x099, 0x01C,
+ 0x06A, 0x036, 0x0E6, 0x0CD, 0x046, 0x012, 0x06F, 0x09E,
+ 0x0E1, 0x0AB, 0x0E4, 0x0A3, 0x00C, 0x0C0, 0x0DE, 0x0AC,
+ 0x0D4, 0x00D, 0x028, 0x01B, 0x0D0, 0x012, 0x0A5, 0x000,
+ 0x0F8, 0x04B, 0x0AD, 0x033, 0x028, 0x006, 0x0A0, 0x0DE,
+ 0x014, 0x097, 0x03A, 0x089, 0x05D, 0x0C0, 0x00D, 0x0E3,
+ 0x006, 0x090, 0x092, 0x05D, 0x069, 0x098, 0x066, 0x0B9,
+ 0x019, 0x095, 0x0E4, 0x0A8, 0x0CF, 0x09D, 0x033, 0x018,
+ 0x049, 0x0BE, 0x07B, 0x086, 0x0AF, 0x092, 0x08C, 0x033,
+ 0x024, 0x014, 0x00C, 0x0F4, 0x083, 0x024, 0x021, 0x0C2,
+ 0x070, 0x0BF, 0x0F4, 0x018, 0x0F2, 0x02D, 0x04D, 0x043,
+ 0x051, 0x06E, 0x05A, 0x022, 0x01F, 0x032, 0x0A8, 0x02F,
+ 0x0CE, 0x083, 0x022, 0x0E6, 0x005, 0x0A4, 0x017, 0x03A,
+ 0x069, 0x000, 0x0E7, 0x043, 0x090, 0x08E, 0x075, 0x048,
+ 0x05E, 0x070, 0x069, 0x001, 0x0E6, 0x042, 0x0A4, 0x063,
+ 0x098, 0x002, 0x029, 0x04B, 0x09A, 0x029, 0x078, 0x0E9,
+ 0x040, 0x053, 0x013, 0x081, 0x081, 0x032, 0x067, 0x082,
+ 0x0FF, 0x0D0, 0x063, 0x0C8, 0x0B5, 0x035, 0x00D, 0x045,
+ 0x0AE, 0x050, 0x008, 0x07C, 0x0E0, 0x0D0, 0x05F, 0x09D,
+ 0x006, 0x045, 0x0CC, 0x001, 0x0A4, 0x017, 0x03A, 0x069,
+ 0x000, 0x0E7, 0x043, 0x090, 0x08E, 0x075, 0x048, 0x05E,
+ 0x070, 0x069, 0x001, 0x0E6, 0x059, 0x0A4, 0x063, 0x098,
+ 0x01C, 0x052, 0x097, 0x03B, 0x030, 0x052, 0x08E, 0x07D,
+ 0x02A, 0x009, 0x01F, 0x051, 0x0EB, 0x0A4, 0x0A4, 0x00A,
+ 0x0B9, 0x094, 0x087, 0x0AE, 0x0C5, 0x031, 0x038, 0x002,
+ 0x0FF, 0x0D0, 0x063, 0x0C8, 0x0B5, 0x035, 0x00D, 0x045,
+ 0x0AE, 0x050, 0x008, 0x07C, 0x0EA, 0x020, 0x0BF, 0x03A,
+ 0x00C, 0x08B, 0x09A, 0x016, 0x090, 0x05C, 0x0E9, 0x0A4,
+ 0x003, 0x09D, 0x00E, 0x042, 0x039, 0x0D5, 0x021, 0x079,
+ 0x095, 0x048, 0x00F, 0x030, 0x00A, 0x091, 0x08E, 0x060,
+ 0x0EB, 0x029, 0x073, 0x000, 0x009, 0x054, 0x004, 0x0CA,
+ 0x082, 0x065, 0x052, 0x065, 0x0E4, 0x0CA, 0x022, 0x065,
+ 0x072, 0x065, 0x009, 0x032, 0x0E0, 0x099, 0x072, 0x04C,
+ 0x0C4, 0x0E0, 0x00B, 0x0FF, 0x041, 0x08F, 0x022, 0x0D4,
+ 0x0D4, 0x035, 0x016, 0x0B9, 0x040, 0x021, 0x0F3, 0x08A,
+ 0x082, 0x0FC, 0x0E8, 0x032, 0x02E, 0x060, 0x0A9, 0x005,
+ 0x0CE, 0x09A, 0x040, 0x039, 0x0D0, 0x0E4, 0x023, 0x09D,
+ 0x052, 0x017, 0x099, 0x054, 0x061, 0x099, 0x001, 0x0E6,
+ 0x040, 0x0A4, 0x063, 0x098, 0x004, 0x0B1, 0x084, 0x098,
+ 0x018, 0x0EF, 0x02D, 0x003, 0x005, 0x031, 0x038, 0x002,
+ 0x0FF, 0x0D0, 0x063, 0x0C8, 0x0B5, 0x035, 0x00D, 0x045,
+ 0x0B9, 0x068, 0x088, 0x07C, 0x0E0, 0x050, 0x05F, 0x09D,
+ 0x006, 0x045, 0x0CC, 0x081, 0x048, 0x02E, 0x071, 0x034,
+ 0x08F, 0x048, 0x001, 0x048, 0x015, 0x021, 0x005, 0x021,
+ 0x0E9, 0x00A, 0x052, 0x003, 0x0CE, 0x05A, 0x046, 0x039,
+ 0x0CF, 0x047, 0x08E, 0x060, 0x0AB, 0x01A, 0x0F3, 0x053,
+ 0x043, 0x0EB, 0x035, 0x024, 0x0B8, 0x01B, 0x030, 0x007,
+ 0x009, 0x08A, 0x074, 0x02F, 0x07E, 0x041, 0x074, 0x01E,
+ 0x01D, 0x00D, 0x087, 0x046, 0x049, 0x0D5, 0x095, 0x0D1,
+ 0x0D5, 0x0D5, 0x0BB, 0x0A9, 0x04E, 0x082, 0x09D, 0x005,
+ 0x03A, 0x00A, 0x074, 0x014, 0x0E8, 0x029, 0x0D0, 0x042,
+ 0x074, 0x05B, 0x0CE, 0x050, 0x0C4, 0x007, 0x045, 0x0BC,
+ 0x0E2, 0x00C, 0x040, 0x074, 0x05B, 0x0CE, 0x083, 0x004,
+ 0x0F9, 0x095, 0x04D, 0x013, 0x063, 0x05E, 0x06F, 0x031,
+ 0x03B, 0x0A0, 0x08B, 0x0A2, 0x0C5, 0x039, 0x08D, 0x078,
+ 0x03A, 0x022, 0x0A0, 0x000, 0x06B, 0x0C1, 0x0D1, 0x054,
+ 0x060, 0x016, 0x0D9, 0x091, 0x0A2, 0x0E7, 0x043, 0x08C,
+ 0x024, 0x0DC, 0x01C, 0x0E0, 0x051, 0x017, 0x039, 0x06B,
+ 0x03B, 0x0CC, 0x04B, 0x042, 0x02E, 0x06B, 0x050, 0x0BF,
+ 0x036, 0x036, 0x065, 0x04F, 0x07A, 0x018, 0x055, 0x025,
+ 0x078, 0x098, 0x023, 0x0E7, 0x050, 0x03E, 0x0F3, 0x081,
+ 0x04C, 0x002, 0x06D, 0x03E, 0x071, 0x053, 0x0AF, 0x078,
+ 0x0A9, 0x0D4, 0x0A6, 0x029, 0x0B1, 0x0BC, 0x0D9, 0x099,
+ 0x0B2, 0x08E, 0x062, 0x08F, 0x022, 0x02E, 0x075, 0x016,
+ 0x0B0, 0x0B2, 0x0AB, 0x023, 0x028, 0x016, 0x054, 0x052,
+ 0x031, 0x0BC, 0x0D9, 0x099, 0x0B2, 0x08E, 0x066, 0x019,
+ 0x002, 0x02E, 0x075, 0x016, 0x050, 0x02C, 0x0A9, 0x0C8,
+ 0x0C6, 0x0F5, 0x020, 0x0D3, 0x0E4, 0x07F, 0x04F, 0x09C,
+ 0x00A, 0x0D6, 0x016, 0x07F, 0x090, 0x0EE, 0x04C, 0x0EB,
+ 0x0CF, 0x0E2, 0x088, 0x0BA, 0x02F, 0x042, 0x086, 0x0AE,
+ 0x0BD, 0x0E5, 0x0A7, 0x052, 0x09F, 0x093, 0x063, 0x079,
+ 0x0EB, 0x033, 0x008, 0x0F9, 0x094, 0x052, 0x047, 0x0CD,
+ 0x099, 0x025, 0x06F, 0x03A, 0x00C, 0x013, 0x0E6, 0x055,
+ 0x034, 0x04C, 0x05A, 0x04D, 0x0B5, 0x023, 0x095, 0x0A5,
+ 0x048, 0x011, 0x05A, 0x00A, 0x043, 0x095, 0x0AC, 0x02C,
+ 0x0BA, 0x024, 0x005, 0x049, 0x0B1, 0x0BC, 0x0CA, 0x0A7,
+ 0x072, 0x06C, 0x06B, 0x0C5, 0x0BD, 0x0E8, 0x031, 0x069,
+ 0x052, 0x05D, 0x006, 0x012, 0x065, 0x03E, 0x0B1, 0x050,
+ 0x04C, 0x07D, 0x04F, 0x0AC, 0x00A, 0x030, 0x00B, 0x036,
+ 0x064, 0x011, 0x073, 0x08A, 0x083, 0x08E, 0x075, 0x012,
+ 0x09F, 0x07B, 0x0D2, 0x099, 0x058, 0x0EE, 0x082, 0x02E,
+ 0x077, 0x0A0, 0x0E3, 0x09D, 0x05D, 0x04F, 0x0BC, 0x02A,
+ 0x053, 0x029, 0x053, 0x0DE, 0x093, 0x024, 0x0BA, 0x0B3,
+ 0x036, 0x0AA, 0x04A, 0x0C6, 0x079, 0x0D4, 0x0B9, 0x0DE,
+ 0x062, 0x05A, 0x011, 0x073, 0x050, 0x050, 0x0BF, 0x037,
+ 0x036, 0x06F, 0x013, 0x023, 0x0BA, 0x00C, 0x024, 0x0CE,
+ 0x0BD, 0x0E2, 0x0A7, 0x052, 0x0B2, 0x08E, 0x06B, 0x060,
+ 0x062, 0x02E, 0x075, 0x013, 0x030, 0x0AC, 0x0A0, 0x059,
+ 0x0CA, 0x064, 0x063, 0x079, 0x0B3, 0x033, 0x065, 0x01C,
+ 0x0CC, 0x032, 0x004, 0x05C, 0x0EA, 0x02C, 0x0A0, 0x059,
+ 0x0DF, 0x023, 0x01B, 0x0D4, 0x083, 0x052, 0x047, 0x0DD,
+ 0x079, 0x096, 0x0D4, 0x09E, 0x0B3, 0x052, 0x04B, 0x0A2,
+ 0x05A, 0x01A, 0x08D, 0x05D, 0x07B, 0x082, 0x0A7, 0x052,
+ 0x0B2, 0x08E, 0x066, 0x019, 0x002, 0x02E, 0x075, 0x016,
+ 0x050, 0x02C, 0x08C, 0x032, 0x01D, 0x07B, 0x08E, 0x0A7,
+ 0x052, 0x0B1, 0x0BC, 0x0D9, 0x099, 0x098, 0x004, 0x0DA,
+ 0x07C, 0x0E2, 0x0AC, 0x0FE, 0x066, 0x019, 0x002, 0x02E,
+ 0x065, 0x050, 0x0BF, 0x033, 0x066, 0x064, 0x0FE, 0x074,
+ 0x018, 0x086, 0x04C, 0x017, 0x026, 0x0D6, 0x016, 0x052,
+ 0x039, 0x018, 0x0DE, 0x07A, 0x0CC, 0x0C2, 0x03E, 0x065,
+ 0x014, 0x091, 0x0F3, 0x066, 0x049, 0x008, 0x06E, 0x083,
+ 0x009, 0x033, 0x0AF, 0x031, 0x0ED, 0x00D, 0x09D, 0x006,
+ 0x012, 0x062, 0x02A, 0x031, 0x08D, 0x06D, 0x0E7, 0x041,
+ 0x082, 0x07C, 0x0CA, 0x0A6, 0x089, 0x087, 0x009, 0x02E,
+ 0x029, 0x0B1, 0x0AF, 0x010, 0x039, 0x0D6, 0x064, 0x097,
+ 0x030, 0x01D, 0x042, 0x075, 0x093, 0x044, 0x002, 0x08C,
+ 0x024, 0x0D2, 0x07A, 0x0B3, 0x050, 0x0F6, 0x089, 0x005,
+ 0x043, 0x05E, 0x061, 0x098, 0x0C0, 0x02C, 0x092, 0x025,
+ 0x03C, 0x08B, 0x024, 0x089, 0x049, 0x005, 0x049, 0x0E7,
+ 0x00C, 0x0B9, 0x084, 0x098, 0x0B7, 0x0AD, 0x033, 0x044,
+ 0x0AE, 0x05A, 0x051, 0x086, 0x060, 0x09F, 0x038, 0x0A9,
+ 0x0A2, 0x06C, 0x06B, 0x0C4, 0x08E, 0x0F4, 0x05E, 0x049,
+ 0x046, 0x012, 0x062, 0x0DE, 0x0B4, 0x0CD, 0x021, 0x05C,
+ 0x0B4, 0x0A3, 0x00C, 0x0C1, 0x03E, 0x072, 0x029, 0x0A2,
+ 0x06C, 0x06B, 0x0C6, 0x012, 0x062, 0x047, 0x0F0, 0x0E8,
+ 0x0C3, 0x032, 0x004, 0x035, 0x040, 0x092, 0x0A4, 0x082,
+ 0x088, 0x010, 0x092, 0x07C, 0x0CB, 0x0D4, 0x02F, 0x0A4,
+ 0x002, 0x011, 0x084, 0x098, 0x0B7, 0x0AD, 0x033, 0x044,
+ 0x0AE, 0x05A, 0x051, 0x086, 0x060, 0x09F, 0x038, 0x0A9,
+ 0x0A2, 0x06C, 0x06B, 0x0C4, 0x08E, 0x0F4, 0x05E, 0x049,
+ 0x044, 0x008, 0x049, 0x03E, 0x065, 0x0EA, 0x017, 0x0D2,
+ 0x001, 0x008, 0x0C2, 0x04C, 0x05B, 0x0D6, 0x099, 0x0A4,
+ 0x02B, 0x096, 0x094, 0x061, 0x098, 0x027, 0x0CE, 0x045,
+ 0x034, 0x04D, 0x08D, 0x078, 0x081, 0x009, 0x027, 0x0CC,
+ 0x0BD, 0x012, 0x028, 0x06C, 0x058, 0x0AF, 0x0B6, 0x0F3,
+ 0x0A0, 0x0C1, 0x03E, 0x065, 0x053, 0x044, 0x0D8, 0x0D7,
+ 0x092, 0x08E, 0x07D, 0x04B, 0x0C2, 0x0FA, 0x061, 0x026,
+ 0x006, 0x03A, 0x0B3, 0x06B, 0x003, 0x005, 0x049, 0x0E7,
+ 0x00C, 0x0B9, 0x06F, 0x05A, 0x066, 0x095, 0x05C, 0x0B4,
+ 0x0A3, 0x00C, 0x0C1, 0x03E, 0x070, 0x029, 0x0A2, 0x06E,
+ 0x0A4, 0x0DF, 0x093, 0x071, 0x013, 0x077, 0x026, 0x0E1,
+ 0x026, 0x0F8, 0x026, 0x0C6, 0x0BC, 0x094, 0x073, 0x0F9,
+ 0x02F, 0x00B, 0x0E9, 0x084, 0x098, 0x018, 0x0EA, 0x0CC,
+ 0x0EC, 0x00C, 0x015, 0x027, 0x09C, 0x032, 0x0FF, 0x03D,
+ 0x056, 0x0AF, 0x092, 0x08B, 0x07A, 0x0D3, 0x035, 0x0D5,
+ 0x0CB, 0x04A, 0x030, 0x0CC, 0x013, 0x0E7, 0x002, 0x09A,
+ 0x026, 0x0C6, 0x0BC, 0x094, 0x073, 0x041, 0x097, 0x091,
+ 0x0F4, 0x083, 0x0CE, 0x004, 0x020, 0x062, 0x08B, 0x005,
+ 0x016, 0x049, 0x08C, 0x024, 0x0C0, 0x0C7, 0x056, 0x090,
+ 0x0C0, 0x0C1, 0x052, 0x079, 0x0C3, 0x02E, 0x05B, 0x0D5,
+ 0x0A6, 0x072, 0x0D2, 0x094, 0x0FA, 0x0AD, 0x058, 0x0C8,
+ 0x0FA, 0x09F, 0x054, 0x0B3, 0x032, 0x04B, 0x0B9, 0x054,
+ 0x0A6, 0x051, 0x086, 0x06B, 0x079, 0x0D0, 0x060, 0x09F,
+ 0x032, 0x005, 0x034, 0x04D, 0x08D, 0x07A, 0x04D, 0x01E,
+ 0x07A, 0x0B3, 0x051, 0x000, 0x0A9, 0x03D, 0x059, 0x0A8,
+ 0x07B, 0x044, 0x082, 0x0A1, 0x0AF, 0x04A, 0x08D, 0x052,
+ 0x0A9, 0x052, 0x041, 0x049, 0x04F, 0x03A, 0x02E, 0x040,
+ 0x0A4, 0x099, 0x050, 0x0BE, 0x090, 0x008, 0x052, 0x079,
+ 0x0C3, 0x02E, 0x061, 0x026, 0x02D, 0x0EB, 0x04C, 0x0D0,
+ 0x015, 0x0CB, 0x04A, 0x030, 0x0CC, 0x013, 0x0E7, 0x002,
+ 0x09A, 0x026, 0x0C6, 0x0BC, 0x048, 0x0FE, 0x01D, 0x025,
+ 0x046, 0x0A9, 0x054, 0x0A9, 0x020, 0x0A4, 0x0A7, 0x09D,
+ 0x017, 0x020, 0x052, 0x04C, 0x0A8, 0x05F, 0x048, 0x004,
+ 0x023, 0x009, 0x031, 0x06F, 0x05A, 0x066, 0x080, 0x0AE,
+ 0x05A, 0x051, 0x086, 0x060, 0x09F, 0x038, 0x014, 0x0D1,
+ 0x036, 0x035, 0x0E4, 0x0A7, 0x09D, 0x017, 0x020, 0x052,
+ 0x04C, 0x0A2, 0x045, 0x00D, 0x08B, 0x015, 0x0F4, 0x091,
+ 0x0DE, 0x08B, 0x0C9, 0x028, 0x0C2, 0x04C, 0x05B, 0x0D6,
+ 0x099, 0x0A9, 0x05C, 0x0B4, 0x0A3, 0x00C, 0x0D6, 0x0F3,
+ 0x0A0, 0x0C1, 0x03E, 0x064, 0x00A, 0x068, 0x09B, 0x01A,
+ 0x0F1, 0x06D, 0x04C, 0x0AA, 0x092, 0x0E0, 0x036, 0x094,
+ 0x070, 0x09B, 0x029, 0x078, 0x013, 0x0AE, 0x0B3, 0x0AA,
+ 0x085, 0x0D4, 0x043, 0x075, 0x009, 0x03A, 0x0C9, 0x0EB,
+ 0x035, 0x024, 0x0B8, 0x01B, 0x032, 0x08E, 0x013, 0x048,
+ 0x07E, 0x04E, 0x0FD, 0x040, 0x0FD, 0x040, 0x0FD, 0x040,
+ 0x0FD, 0x040, 0x0FD, 0x040, 0x0FC, 0x013, 0x0F4, 0x021,
+ 0x0F9, 0x017, 0x045, 0x08A, 0x030, 0x00B, 0x033, 0x05F,
+ 0x083, 0x0A2, 0x02A, 0x030, 0x00B, 0x033, 0x05F, 0x083,
+ 0x0A2, 0x0A8, 0x0C0, 0x02D, 0x0B3, 0x020, 0x070, 0x092,
+ 0x013, 0x09A, 0x0DE, 0x074, 0x018, 0x027, 0x0CC, 0x0AA,
+ 0x068, 0x09B, 0x01A, 0x0F7, 0x007, 0x045, 0x051, 0x080,
+ 0x05B, 0x066, 0x047, 0x007, 0x038, 0x0A8, 0x023, 0x0E7,
+ 0x051, 0x011, 0x03F, 0x0E0, 0x0E8, 0x085, 0x046, 0x001,
+ 0x06D, 0x099, 0x006, 0x012, 0x065, 0x04F, 0x07A, 0x020,
+ 0x024, 0x0BA, 0x0B3, 0x032, 0x015, 0x025, 0x07B, 0x0AD,
+ 0x033, 0x078, 0x0AE, 0x00E, 0x073, 0x0D0, 0x047, 0x0CE,
+ 0x0A7, 0x030, 0x0CC, 0x044, 0x0FF, 0x083, 0x0A2, 0x0A8,
+ 0x0C0, 0x02C, 0x0D9, 0x091, 0x0C1, 0x0D1, 0x015, 0x018,
+ 0x005, 0x09B, 0x032, 0x008, 0x0BA, 0x02C, 0x051, 0x080,
+ 0x059, 0x0B3, 0x020, 0x070, 0x092, 0x0E2, 0x098, 0x089,
+ 0x0FD, 0x0BC, 0x0EE, 0x018, 0x090, 0x0FC, 0x08B, 0x0A2,
+ 0x0C5, 0x02B, 0x00D, 0x078, 0x03A, 0x022, 0x0A5, 0x061,
+ 0x0AF, 0x007, 0x045, 0x051, 0x080, 0x05B, 0x066, 0x044,
+ 0x09E, 0x0B3, 0x052, 0x04B, 0x083, 0x0AD, 0x0C7, 0x009,
+ 0x0BE, 0x01F, 0x09F, 0x074, 0x065, 0x05D, 0x00A, 0x017,
+ 0x07C, 0x0AB, 0x0A0, 0x0C2, 0x04C, 0x038, 0x049, 0x012,
+ 0x02E, 0x038, 0x049, 0x007, 0x0A3, 0x00C, 0x0C1, 0x03E,
+ 0x065, 0x053, 0x044, 0x0D8, 0x0D7, 0x0AD, 0x0E7, 0x000,
+ 0x032, 0x04B, 0x09B, 0x033, 0x034, 0x04A, 0x003, 0x000,
+ 0x09D, 0x025, 0x0CE, 0x083, 0x024, 0x0B8, 0x019, 0x099,
+ 0x08C, 0x002, 0x012, 0x04B, 0x0A1, 0x099, 0x0D8, 0x0C0,
+ 0x027, 0x049, 0x073, 0x0CF, 0x0F9, 0x03C, 0x0F4, 0x07C,
+ 0x0E7, 0x098, 0x004, 0x0E9, 0x02E, 0x07F, 0x039, 0x0E3,
+ 0x04F, 0x046, 0x053, 0x0C0, 0x060, 0x013, 0x0A4, 0x0B9,
+ 0x0E5, 0x03C, 0x003, 0x0DE, 0x08F, 0x09C, 0x0F3, 0x000,
+ 0x09C, 0x06F, 0x0CF, 0x03E, 0x085, 0x0F9, 0x0A3, 0x036,
+ 0x002, 0x01E, 0x060, 0x038, 0x092, 0x03E, 0x063, 0x01A,
+ 0x010, 0x09F, 0x0CF, 0x018, 0x010, 0x092, 0x0BC, 0x0D0,
+ 0x0A4, 0x00C, 0x0DC, 0x0C0, 0x00F, 0x09C, 0x097, 0x034,
+ 0x062, 0x0B6, 0x0E7, 0x0F3, 0x0F3, 0x0A5, 0x0CF, 0x018,
+ 0x042, 0x034, 0x01C, 0x0C2, 0x0CA, 0x0FA, 0x08E, 0x068,
+ 0x052, 0x006, 0x0AF, 0x03C, 0x0A3, 0x00D, 0x0BF, 0x09E,
+ 0x050, 0x0E1, 0x0D1, 0x073, 0x0CA, 0x0E0, 0x03A, 0x0FC,
+ 0x0C1, 0x009, 0x01A, 0x01E, 0x06A, 0x05C, 0x05B, 0x08E,
+ 0x063, 0x04E, 0x077, 0x073, 0x0CC, 0x061, 0x067, 0x0DD,
+ 0x0E6, 0x06C, 0x048, 0x0D1, 0x0F3, 0x01B, 0x024, 0x069,
+ 0x051, 0x008, 0x0D4, 0x042, 0x01B, 0x0F4, 0x067, 0x0D1,
+ 0x080, 0x04E, 0x02F, 0x0D0, 0x08C, 0x0D8, 0x030, 0x009,
+ 0x0C2, 0x01E, 0x080, 0x01C, 0x046, 0x001, 0x03A, 0x047,
+ 0x0D0, 0x031, 0x0A1, 0x006, 0x001, 0x03A, 0x07F, 0x046,
+ 0x030, 0x021, 0x018, 0x004, 0x0E9, 0x05E, 0x084, 0x029,
+ 0x000, 0x0C0, 0x027, 0x0CD, 0x0D0, 0x000, 0x07C, 0x098,
+ 0x004, 0x0F9, 0x02E, 0x084, 0x062, 0x08C, 0x002, 0x07D,
+ 0x0BA, 0x03E, 0x07E, 0x04C, 0x002, 0x07D, 0x02E, 0x08C,
+ 0x061, 0x008, 0x030, 0x009, 0x0F4, 0x01D, 0x001, 0x065,
+ 0x073, 0x000, 0x09F, 0x051, 0x0D0, 0x085, 0x020, 0x018,
+ 0x004, 0x0FA, 0x0BD, 0x019, 0x046, 0x018, 0x0C0, 0x027,
+ 0x0DF, 0x0D1, 0x094, 0x038, 0x04C, 0x002, 0x07D, 0x017,
+ 0x046, 0x057, 0x001, 0x030, 0x009, 0x0F5, 0x0FA, 0x001,
+ 0x009, 0x006, 0x001, 0x03E, 0x087, 0x0A1, 0x04B, 0x088,
+ 0x0C0, 0x027, 0x0DC, 0x074, 0x00D, 0x039, 0x0D3, 0x000,
+ 0x09F, 0x073, 0x0D0, 0x030, 0x0B3, 0x098, 0x004, 0x0FB,
+ 0x0BD, 0x006, 0x0C4, 0x083, 0x000, 0x09F, 0x047, 0x0D0,
+ 0x036, 0x048, 0x0CC, 0x002, 0x071, 0x0BF, 0x03F, 0x09A,
+ 0x017, 0x0E6, 0x03F, 0x008, 0x021, 0x0E6, 0x092, 0x0A4,
+ 0x08F, 0x09A, 0x010, 0x031, 0x0A7, 0x0F3, 0x010, 0x0B1,
+ 0x084, 0x0AF, 0x03A, 0x0AC, 0x0DC, 0x0F7, 0x073, 0x0F2,
+ 0x05C, 0x0C6, 0x02A, 0x0DB, 0x09E, 0x07E, 0x07E, 0x097,
+ 0x031, 0x008, 0x063, 0x0D0, 0x073, 0x07B, 0x043, 0x0A8,
+ 0x0E6, 0x03D, 0x034, 0x0EA, 0x0F3, 0x0E3, 0x015, 0x0BF,
+ 0x09F, 0x018, 0x05F, 0x045, 0x0CF, 0x0E8, 0x09F, 0x05F,
+ 0x09A, 0x05B, 0x003, 0x0D0, 0x0F3, 0x0D3, 0x0CE, 0x037,
+ 0x01C, 0x0D0, 0x00F, 0x0BB, 0x09E, 0x068, 0x078, 0x03B,
+ 0x0BC, 0x0CA, 0x031, 0x0E8, 0x0F9, 0x0A2, 0x002, 0x012,
+ 0x0A2, 0x073, 0x051, 0x008, 0x06F, 0x0D1, 0x0F3, 0x046,
+ 0x001, 0x038, 0x0BF, 0x040, 0x0FC, 0x023, 0x000, 0x09C,
+ 0x021, 0x0E8, 0x049, 0x051, 0x080, 0x04E, 0x091, 0x0F4,
+ 0x021, 0x003, 0x019, 0x080, 0x04E, 0x09F, 0x0D0, 0x021,
+ 0x063, 0x006, 0x001, 0x03A, 0x056, 0x08C, 0x002, 0x074,
+ 0x0FE, 0x075, 0x049, 0x05E, 0x063, 0x0D3, 0x04A, 0x054,
+ 0x042, 0x035, 0x013, 0x0A7, 0x0D1, 0x080, 0x04E, 0x095,
+ 0x0E8, 0x01E, 0x09A, 0x04C, 0x002, 0x07C, 0x0DD, 0x01B,
+ 0x0B9, 0x0E6, 0x001, 0x03E, 0x04B, 0x0A0, 0x062, 0x0A3,
+ 0x000, 0x09F, 0x06E, 0x08C, 0x0FC, 0x0F3, 0x000, 0x09F,
+ 0x04B, 0x0A0, 0x042, 0x018, 0x0CC, 0x002, 0x07D, 0x007,
+ 0x043, 0x0DA, 0x013, 0x000, 0x09F, 0x051, 0x0D0, 0x03D,
+ 0x034, 0x098, 0x004, 0x0FA, 0x0BD, 0x01C, 0x062, 0x08C,
+ 0x002, 0x07D, 0x0FD, 0x01C, 0x061, 0x073, 0x000, 0x09F,
+ 0x045, 0x0D1, 0x0F4, 0x04E, 0x060, 0x013, 0x0EB, 0x0F4,
+ 0x025, 0x0B0, 0x033, 0x000, 0x09F, 0x043, 0x0D1, 0x0A7,
+ 0x09C, 0x018, 0x004, 0x0FB, 0x08E, 0x084, 0x003, 0x0E9,
+ 0x080, 0x04F, 0x0B9, 0x0E8, 0x043, 0x0C1, 0x030, 0x009,
+ 0x0F7, 0x07A, 0x00A, 0x031, 0x098, 0x004, 0x0FA, 0x03E,
+ 0x084, 0x040, 0x041, 0x080, 0x04E, 0x082, 0x0E7, 0x041,
+ 0x087, 0x009, 0x023, 0x004, 0x023, 0x000, 0x09D, 0x005,
+ 0x0CE, 0x096, 0x01C, 0x024, 0x08C, 0x010, 0x08C, 0x002,
+ 0x074, 0x017, 0x03A, 0x004, 0x038, 0x049, 0x018, 0x021,
+ 0x018, 0x004, 0x0E8, 0x02E, 0x074, 0x050, 0x0E1, 0x024,
+ 0x060, 0x084, 0x060, 0x013, 0x0A0, 0x0B9, 0x0D4, 0x011,
+ 0x0C2, 0x048, 0x0C1, 0x008, 0x0C0, 0x027, 0x041, 0x073,
+ 0x0A8, 0x023, 0x084, 0x091, 0x082, 0x011, 0x080, 0x04E,
+ 0x082, 0x0E7, 0x052, 0x08E, 0x012, 0x046, 0x008, 0x046,
+ 0x001, 0x03A, 0x00B, 0x09D, 0x040, 0x01C, 0x024, 0x08C,
+ 0x010, 0x08C, 0x002, 0x074, 0x017, 0x03A, 0x009, 0x00E,
+ 0x012, 0x046, 0x008, 0x046, 0x001, 0x03A, 0x00B, 0x098,
+ 0x06A, 0x01C, 0x024, 0x0B0, 0x0E1, 0x018, 0x004, 0x0E8,
+ 0x02E, 0x06B, 0x050, 0x0E1, 0x025, 0x087, 0x008, 0x0C0,
+ 0x027, 0x041, 0x073, 0x005, 0x043, 0x084, 0x096, 0x01C,
+ 0x023, 0x000, 0x09D, 0x005, 0x0CC, 0x0AA, 0x01C, 0x024,
+ 0x0B0, 0x0E1, 0x018, 0x004, 0x0E8, 0x02E, 0x070, 0x068,
+ 0x070, 0x092, 0x0C3, 0x084, 0x060, 0x013, 0x0E5, 0x044,
+ 0x0F9, 0x040, 0x09D, 0x005, 0x0CE, 0x05A, 0x01C, 0x024,
+ 0x0B0, 0x0E1, 0x018, 0x004, 0x0F9, 0x0D1, 0x03E, 0x070,
+ 0x027, 0x0CF, 0x013, 0x0E5, 0x044, 0x02C, 0x0A0, 0x042,
+ 0x0CB, 0x089, 0x0F2, 0x021, 0x03A, 0x00B, 0x09C, 0x00A,
+ 0x01C, 0x024, 0x0B0, 0x0E1, 0x018, 0x004, 0x0F9, 0x0D1,
+ 0x00B, 0x038, 0x010, 0x0B3, 0x0C4, 0x021, 0x039, 0x036,
+ 0x05C, 0x042, 0x0C8, 0x084, 0x02B, 0x079, 0x0D0, 0x061,
+ 0x0C2, 0x074, 0x015, 0x024, 0x0BA, 0x0D3, 0x031, 0x0E5,
+ 0x059, 0x008, 0x029, 0x008, 0x0E0, 0x066, 0x063, 0x042,
+ 0x095, 0x012, 0x081, 0x000, 0x029, 0x00B, 0x0C1, 0x051,
+ 0x024, 0x0B8, 0x019, 0x099, 0x090, 0x022, 0x090, 0x0B4,
+ 0x018, 0x0A0, 0x091, 0x041, 0x001, 0x041, 0x041, 0x041,
+ 0x052, 0x083, 0x0CA, 0x040, 0x028, 0x068, 0x029, 0x008,
+ 0x0BA, 0x016, 0x010, 0x09C, 0x099, 0x00B, 0x056, 0x094,
+ 0x090, 0x052, 0x015, 0x074, 0x0C0, 0x027, 0x01A, 0x02A,
+ 0x0D2, 0x090, 0x025, 0x0D3, 0x000, 0x09D, 0x028, 0x0AB,
+ 0x04A, 0x042, 0x017, 0x04C, 0x002, 0x070, 0x0D4, 0x084,
+ 0x02E, 0x098, 0x004, 0x0E1, 0x02A, 0x042, 0x017, 0x04C,
+ 0x002, 0x070, 0x082, 0x090, 0x04B, 0x0A6, 0x001, 0x038,
+ 0x051, 0x048, 0x042, 0x0E9, 0x080, 0x04E, 0x015, 0x0A4,
+ 0x021, 0x074, 0x0C0, 0x027, 0x00F, 0x0A4, 0x012, 0x0E9,
+ 0x080, 0x04E, 0x082, 0x0AC, 0x080, 0x0AC, 0x0A0, 0x0AC,
+ 0x0A9, 0x059, 0x0E5, 0x064, 0x045, 0x065, 0x0CA, 0x0C8,
+ 0x04A, 0x0CE, 0x00A, 0x0CE, 0x04A, 0x0CE, 0x095, 0x091,
+ 0x095, 0x094, 0x095, 0x093, 0x029, 0x025, 0x0C0, 0x0CC,
+ 0x0CC, 0x088, 0x0A4, 0x097, 0x056, 0x036, 0x064, 0x072,
+ 0x090, 0x054, 0x08A, 0x09C, 0x045, 0x008, 0x0B9, 0x0B7,
+ 0x066, 0x012, 0x093, 0x009, 0x0C9, 0x0B2, 0x074, 0x08E,
+ 0x0BA, 0x060, 0x013, 0x0E5, 0x034, 0x08E, 0x0BA, 0x060,
+ 0x013, 0x0E4, 0x074, 0x08E, 0x0BA, 0x060, 0x013, 0x0E5,
+ 0x069, 0x01D, 0x074, 0x0C0, 0x027, 0x0CA, 0x029, 0x01D,
+ 0x074, 0x0C0, 0x027, 0x0CE, 0x0D2, 0x025, 0x0D3, 0x000,
+ 0x09F, 0x038, 0x0A4, 0x04B, 0x0A6, 0x001, 0x03E, 0x05E,
+ 0x091, 0x02E, 0x098, 0x004, 0x0F9, 0x015, 0x022, 0x05D,
+ 0x030, 0x009, 0x0F3, 0x0E9, 0x012, 0x0E9, 0x080, 0x04F,
+ 0x090, 0x052, 0x025, 0x0D3, 0x000, 0x09D, 0x0C5, 0x048,
+ 0x025, 0x0D3, 0x000, 0x09C, 0x045, 0x0CE, 0x0CD, 0x009,
+ 0x0C9, 0x0B2, 0x01A, 0x044, 0x0BA, 0x060, 0x013, 0x0E7,
+ 0x034, 0x089, 0x074, 0x0C0, 0x027, 0x01C, 0x027, 0x0B7,
+ 0x09C, 0x080, 0x0C2, 0x0D7, 0x076, 0x059, 0x09B, 0x093,
+ 0x00C, 0x064, 0x0C3, 0x01D, 0x01B, 0x0F4, 0x045, 0x04B,
+ 0x0C7, 0x0C6, 0x03A, 0x037, 0x0E8, 0x081, 0x04B, 0x0C7,
+ 0x0C6, 0x03A, 0x037, 0x0E8, 0x091, 0x04B, 0x0C7, 0x0C6,
+ 0x032, 0x061, 0x08E, 0x0B3, 0x0BC, 0x0C3, 0x04A, 0x022,
+ 0x0E6, 0x0B5, 0x024, 0x097, 0x071, 0x0C9, 0x087, 0x0B4,
+ 0x031, 0x0AE, 0x073, 0x0A2, 0x0CF, 0x039, 0x0D2, 0x05D,
+ 0x004, 0x044, 0x042, 0x0C0, 0x0D6, 0x0DE, 0x071, 0x006,
+ 0x016, 0x0BB, 0x0DB, 0x0CE, 0x083, 0x00C, 0x064, 0x0C3,
+ 0x01D, 0x031, 0x013, 0x004, 0x0F9, 0x095, 0x04D, 0x013,
+ 0x032, 0x093, 0x063, 0x05E, 0x066, 0x014, 0x0CC, 0x029,
+ 0x02A, 0x053, 0x030, 0x0A6, 0x061, 0x04C, 0x0C2, 0x099,
+ 0x085, 0x03A, 0x072, 0x0CC, 0x0C2, 0x099, 0x085, 0x006,
+ 0x01B, 0x0B3, 0x00A, 0x066, 0x014, 0x014, 0x024, 0x099,
+ 0x085, 0x033, 0x00A, 0x008, 0x0B1, 0x086, 0x061, 0x04C,
+ 0x0C2, 0x084, 0x021, 0x068, 0x073, 0x03B, 0x030, 0x0A6,
+ 0x061, 0x041, 0x04E, 0x0A5, 0x098, 0x053, 0x030, 0x0AC,
+ 0x059, 0x076, 0x061, 0x04C, 0x0C2, 0x0B0, 0x08D, 0x0D6,
+ 0x061, 0x04C, 0x0C2, 0x0B0, 0x02C, 0x0F6, 0x061, 0x04C,
+ 0x0C2, 0x0B1, 0x08C, 0x0A5, 0x098, 0x053, 0x030, 0x0AC,
+ 0x00F, 0x024, 0x0CC, 0x029, 0x098, 0x056, 0x00F, 0x028,
+ 0x066, 0x015, 0x092, 0x01A, 0x019, 0x085, 0x033, 0x00A,
+ 0x0CA, 0x085, 0x00C, 0x0C2, 0x099, 0x085, 0x065, 0x0C3,
+ 0x0D9, 0x085, 0x033, 0x00A, 0x0CE, 0x070, 0x086, 0x061,
+ 0x04C, 0x0C2, 0x0B3, 0x097, 0x071, 0x00C, 0x099, 0x03B,
+ 0x0CC, 0x083, 0x058, 0x00B, 0x0EA, 0x077, 0x09D, 0x006,
+ 0x04A, 0x0BE, 0x004, 0x074, 0x060, 0x0E0, 0x0D1, 0x04E,
+ 0x038, 0x04C, 0x03E, 0x0EE, 0x03E, 0x0EE, 0x03E, 0x0EE,
+ 0x03E, 0x0EE, 0x030, 0x0BB, 0x0CA, 0x0E1, 0x01F, 0x077,
+ 0x01F, 0x077, 0x01F, 0x077, 0x01F, 0x077, 0x027, 0x070,
+ 0x08F, 0x0BB, 0x080, 0x00E, 0x011, 0x0F7, 0x071, 0x0F7,
+ 0x07C, 0x06F, 0x03C, 0x0B3, 0x036, 0x002, 0x0FB, 0x08D,
+ 0x0E6, 0x055, 0x070, 0x07F, 0x02D, 0x024, 0x069, 0x055,
+ 0x04F, 0x058, 0x0A9, 0x023, 0x01F, 0x054, 0x0F7, 0x08A,
+ 0x095, 0x025, 0x02B, 0x075, 0x00C, 0x0CC, 0x0AC, 0x056,
+ 0x051, 0x0CC, 0x051, 0x0E4, 0x045, 0x0CE, 0x0A2, 0x012,
+ 0x039, 0x0C0, 0x0A0, 0x0AF, 0x056, 0x06A, 0x049, 0x07F,
+ 0x002, 0x08C, 0x009, 0x0F8, 0x00B, 0x0EB, 0x0AF, 0x056,
+ 0x076, 0x067, 0x052, 0x0B2, 0x08E, 0x069, 0x0A7, 0x011,
+ 0x073, 0x0A8, 0x0B1, 0x0BC, 0x0CA, 0x0A0, 0x0A9, 0x036,
+ 0x050, 0x02C, 0x098, 0x0E7, 0x00A, 0x0F5, 0x066, 0x0A4,
+ 0x097, 0x0E2, 0x05A, 0x030, 0x027, 0x0BA, 0x0F7, 0x083,
+ 0x04E, 0x0A5, 0x033, 0x00A, 0x066, 0x015, 0x08D, 0x0E6,
+ 0x055, 0x039, 0x0D2, 0x0A7, 0x0AC, 0x054, 0x060, 0x016,
+ 0x070, 0x01B, 0x072, 0x08E, 0x062, 0x08F, 0x022, 0x02E,
+ 0x075, 0x016, 0x002, 0x0FB, 0x08D, 0x0E6, 0x00A, 0x095,
+ 0x03D, 0x062, 0x0A3, 0x000, 0x0B7, 0x001, 0x0B5, 0x053,
+ 0x0DE, 0x02A, 0x054, 0x094, 0x0AD, 0x0D4, 0x033, 0x032,
+ 0x0B1, 0x059, 0x047, 0x031, 0x047, 0x091, 0x017, 0x03A,
+ 0x088, 0x048, 0x0E7, 0x002, 0x0B0, 0x017, 0x0DC, 0x067,
+ 0x09D, 0x04B, 0x08D, 0x0E7, 0x052, 0x0AA, 0x07B, 0x0D4,
+ 0x0AA, 0x092, 0x0BD, 0x0D6, 0x099, 0x0BC, 0x056, 0x002,
+ 0x0FB, 0x08C, 0x0F3, 0x066, 0x066, 0x0C6, 0x0F3, 0x066,
+ 0x066, 0x062, 0x099, 0x02A, 0x0F8, 0x018, 0x068, 0x070,
+ 0x0B0, 0x08A, 0x00D, 0x055, 0x055, 0x055, 0x055, 0x052,
+ 0x032, 0x0E1, 0x040, 0x05C, 0x038, 0x00B, 0x0EA, 0x09B,
+ 0x087, 0x001, 0x07D, 0x0C0, 0x05F, 0x070, 0x017, 0x0DC,
+ 0x005, 0x0F5, 0x0DC, 0x09B, 0x001, 0x07D, 0x061, 0x04D,
+ 0x080, 0x0BE, 0x0A7, 0x079, 0x082, 0x0A2, 0x01F, 0x050,
+ 0x015, 0x02A, 0x08F, 0x08B, 0x01C, 0x0E5, 0x0A5, 0x013,
+ 0x084, 0x058, 0x0E7, 0x002, 0x091, 0x054, 0x005, 0x002,
+ 0x04B, 0x0BD, 0x022, 0x01A, 0x094, 0x07F, 0x09C, 0x01A,
+ 0x0C0, 0x05F, 0x042, 0x01A, 0x021, 0x0D1, 0x080, 0x059,
+ 0x0C0, 0x06D, 0x01C, 0x02C, 0x00A, 0x083, 0x055, 0x055,
+ 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055,
+ 0x055, 0x054, 0x01C, 0x0B8, 0x05C, 0x06E, 0x017, 0x09C,
+ 0x02F, 0x038, 0x05E, 0x070, 0x0E7, 0x0B8, 0x05E, 0x070,
+ 0x0BC, 0x0E1, 0x079, 0x0C2, 0x0F3, 0x085, 0x0E7, 0x00B,
+ 0x0CE, 0x017, 0x09C, 0x029, 0x09C, 0x029, 0x09C, 0x029,
+ 0x09C, 0x023, 0x00F, 0x058, 0x014, 0x0EE, 0x035, 0x077,
+ 0x026, 0x021, 0x093, 0x005, 0x0C9, 0x0B0, 0x017, 0x0D2,
+ 0x01D, 0x018, 0x08A, 0x021, 0x093, 0x005, 0x0C9, 0x0B0,
+ 0x017, 0x0D1, 0x087, 0x0AC, 0x00A, 0x074, 0x00F, 0x0AE,
+ 0x0F5, 0x05A, 0x082, 0x0A3, 0x0E4, 0x03A, 0x031, 0x014,
+ 0x0BB, 0x0D7, 0x059, 0x099, 0x074, 0x0A2, 0x019, 0x030,
+ 0x05C, 0x09B, 0x001, 0x07D, 0x018, 0x07A, 0x0C0, 0x0A7,
+ 0x040, 0x0F8, 0x043, 0x0D4, 0x063, 0x089, 0x025, 0x0D0,
+ 0x010, 0x0D6, 0x01C, 0x06A, 0x010, 0x0F5, 0x055, 0x089,
+ 0x025, 0x0D1, 0x051, 0x066, 0x01F, 0x051, 0x0F5, 0x091,
+ 0x049, 0x02E, 0x089, 0x015, 0x098, 0x06A, 0x0A3, 0x0E0,
+ 0x08A, 0x094, 0x065, 0x064, 0x00E, 0x013, 0x017, 0x038,
+ 0x0A8, 0x086, 0x04C, 0x017, 0x026, 0x0C0, 0x05F, 0x046,
+ 0x01E, 0x0B0, 0x028, 0x063, 0x01F, 0x008, 0x07A, 0x08C,
+ 0x071, 0x024, 0x0BA, 0x002, 0x01A, 0x0D0, 0x00D, 0x042,
+ 0x01E, 0x0AA, 0x0B1, 0x024, 0x0BA, 0x02A, 0x02D, 0x031,
+ 0x0F5, 0x01F, 0x058, 0x074, 0x092, 0x0E8, 0x087, 0x05A,
+ 0x063, 0x052, 0x0DE, 0x0F4, 0x051, 0x069, 0x04A, 0x03E,
+ 0x009, 0x069, 0x046, 0x050, 0x0F0, 0x0E1, 0x031, 0x073,
+ 0x005, 0x045, 0x0BD, 0x059, 0x08D, 0x08B, 0x04A, 0x07C,
+ 0x0D3, 0x0ED, 0x038, 0x0E9, 0x0D3, 0x04E, 0x074, 0x0ED,
+ 0x044, 0x032, 0x060, 0x0B9, 0x036, 0x002, 0x0FA, 0x05B,
+ 0x0DE, 0x08A, 0x02D, 0x029, 0x0D0, 0x0E1, 0x021, 0x0F5,
+ 0x0A3, 0x092, 0x021, 0x0F2, 0x019, 0x030, 0x05C, 0x09B,
+ 0x001, 0x07D, 0x021, 0x0F5, 0x0A0, 0x0C6, 0x001, 0x067,
+ 0x001, 0x0B4, 0x045, 0x0CE, 0x0A5, 0x012, 0x039, 0x0D4,
+ 0x01C, 0x005, 0x0F4, 0x040, 0x0A1, 0x0C2, 0x0C3, 0x050,
+ 0x06A, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA,
+ 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x081, 0x0AF,
+ 0x086, 0x09F, 0x019, 0x01B, 0x0E7, 0x081, 0x0F3, 0x065,
+ 0x0F2, 0x080, 0x0BE, 0x070, 0x017, 0x0DF, 0x0DF, 0x038,
+ 0x00B, 0x0EB, 0x00D, 0x0C3, 0x080, 0x0BE, 0x0A7, 0x00F,
+ 0x095, 0x04F, 0x05A, 0x094, 0x0C0, 0x02C, 0x0D8, 0x0B1,
+ 0x0A7, 0x0CE, 0x05A, 0x011, 0x073, 0x0A8, 0x03A, 0x0C2,
+ 0x0CC, 0x0B6, 0x030, 0x017, 0x0DC, 0x06F, 0x035, 0x0A9,
+ 0x080, 0x04D, 0x0A7, 0x0CE, 0x02A, 0x018, 0x079, 0x0C5,
+ 0x049, 0x0DE, 0x061, 0x0A8, 0x022, 0x0E7, 0x050, 0x033,
+ 0x0F9, 0x098, 0x064, 0x008, 0x0B9, 0x095, 0x042, 0x0FC,
+ 0x0CC, 0x0D9, 0x095, 0x03D, 0x062, 0x0A2, 0x048, 0x0D4,
+ 0x048, 0x0E7, 0x002, 0x088, 0x0B9, 0x0C1, 0x0A0, 0x0E3,
+ 0x09D, 0x04E, 0x062, 0x0E6, 0x0CC, 0x0C6, 0x06B, 0x0CE,
+ 0x083, 0x010, 0x0C9, 0x082, 0x0E4, 0x0DA, 0x0C2, 0x0C8,
+ 0x01E, 0x0C3, 0x0B9, 0x036, 0x002, 0x0FA, 0x0A9, 0x0EB,
+ 0x04E, 0x030, 0x030, 0x0FA, 0x00D, 0x0F0, 0x0A9, 0x0EB,
+ 0x040, 0x0B9, 0x00F, 0x0AA, 0x07A, 0x0D2, 0x0C2, 0x0C8,
+ 0x0FA, 0x0A7, 0x0AD, 0x041, 0x00A, 0x047, 0x0D5, 0x03D,
+ 0x068, 0x0AC, 0x0F1, 0x0F5, 0x04F, 0x05A, 0x097, 0x054,
+ 0x07D, 0x04F, 0x0A8, 0x0AA, 0x055, 0x01F, 0x011, 0x073,
+ 0x05A, 0x0B0, 0x017, 0x0DE, 0x05D, 0x059, 0x0A9, 0x025,
+ 0x0D0, 0x055, 0x02A, 0x046, 0x0BC, 0x0B8, 0x022, 0x0AE,
+ 0x045, 0x029, 0x03E, 0x014, 0x0FA, 0x0E1, 0x099, 0x094,
+ 0x0CA, 0x04A, 0x0BE, 0x03D, 0x0D6, 0x099, 0x092, 0x05D,
+ 0x015, 0x017, 0x0C8, 0x0D7, 0x0DC, 0x015, 0x017, 0x08A,
+ 0x040, 0x01F, 0x00A, 0x09E, 0x0AC, 0x0C9, 0x065, 0x049,
+ 0x05C, 0x01D, 0x010, 0x068, 0x04A, 0x03E, 0x05B, 0x0DE,
+ 0x083, 0x016, 0x095, 0x080, 0x0BE, 0x091, 0x074, 0x058,
+ 0x0A4, 0x000, 0x07C, 0x038, 0x0E7, 0x056, 0x030, 0x017,
+ 0x0DF, 0x075, 0x0A6, 0x064, 0x097, 0x045, 0x020, 0x09D,
+ 0x003, 0x05F, 0x070, 0x054, 0x05E, 0x029, 0x01D, 0x0F0,
+ 0x0A9, 0x0EA, 0x0CC, 0x086, 0x054, 0x095, 0x0C1, 0x0D1,
+ 0x006, 0x083, 0x00F, 0x0AA, 0x07B, 0x0D0, 0x065, 0x049,
+ 0x045, 0x0BD, 0x0E9, 0x062, 0x0D2, 0x091, 0x0DF, 0x004,
+ 0x05D, 0x016, 0x029, 0x01C, 0x07D, 0x04F, 0x0AC, 0x01A,
+ 0x047, 0x01A, 0x0A9, 0x0F5, 0x067, 0x066, 0x053, 0x028,
+ 0x0B7, 0x0BD, 0x02C, 0x05A, 0x052, 0x03B, 0x0E3, 0x0DD,
+ 0x059, 0x0A9, 0x025, 0x0D1, 0x0A8, 0x0AC, 0x008, 0x06B,
+ 0x0EE, 0x008, 0x0AB, 0x0C5, 0x020, 0x02F, 0x085, 0x04F,
+ 0x056, 0x066, 0x075, 0x049, 0x05C, 0x01C, 0x018, 0x01D,
+ 0x081, 0x0C2, 0x064, 0x005, 0x0F0, 0x080, 0x0BE, 0x035,
+ 0x05C, 0x0D0, 0x017, 0x0C2, 0x055, 0x0F0, 0x095, 0x07C,
+ 0x025, 0x05F, 0x008, 0x00B, 0x0E1, 0x001, 0x07C, 0x07B,
+ 0x0AB, 0x035, 0x024, 0x0BA, 0x010, 0x055, 0x093, 0x01A,
+ 0x0FB, 0x082, 0x02A, 0x0F1, 0x048, 0x0D7, 0x0C2, 0x0A7,
+ 0x0AB, 0x031, 0x0B2, 0x0A4, 0x0AC, 0x063, 0x09D, 0x04A,
+ 0x08D, 0x07C, 0x07B, 0x0AB, 0x035, 0x024, 0x0BA, 0x010,
+ 0x054, 0x030, 0x08D, 0x07D, 0x0C1, 0x015, 0x078, 0x0AC,
+ 0x06F, 0x05A, 0x094, 0x060, 0x01A, 0x0E3, 0x079, 0x0D4,
+ 0x0AA, 0x04F, 0x085, 0x04F, 0x056, 0x066, 0x0D5, 0x049,
+ 0x058, 0x0C7, 0x03A, 0x095, 0x049, 0x0F0, 0x045, 0x0D1,
+ 0x062, 0x094, 0x086, 0x0BC, 0x01D, 0x013, 0x0D2, 0x090,
+ 0x0FF, 0x0CF, 0x07A, 0x083, 0x0F2, 0x050, 0x031, 0x0DE,
+ 0x000, 0x060, 0x060, 0x0A1, 0x017, 0x035, 0x0A8, 0x05F,
+ 0x09B, 0x01B, 0x037, 0x007, 0x044, 0x01A, 0x030, 0x00B,
+ 0x038, 0x00D, 0x0BC, 0x01C, 0x0E0, 0x0D0, 0x047, 0x0CE,
+ 0x0A0, 0x0AA, 0x07A, 0x0A1, 0x098, 0x06A, 0x092, 0x095,
+ 0x03D, 0x068, 0x031, 0x080, 0x05B, 0x080, 0x0DA, 0x0A9,
+ 0x0EF, 0x041, 0x095, 0x025, 0x016, 0x0F7, 0x0A5, 0x08B,
+ 0x04A, 0x0C6, 0x079, 0x0B3, 0x033, 0x060, 0x02F, 0x0AA,
+ 0x09E, 0x0B1, 0x051, 0x080, 0x059, 0x09E, 0x0CA, 0x0A7,
+ 0x0AC, 0x00A, 0x030, 0x00B, 0x067, 0x0B2, 0x0AD, 0x0D5,
+ 0x0DA, 0x092, 0x05D, 0x017, 0x0A3, 0x000, 0x0B3, 0x02D,
+ 0x095, 0x06E, 0x008, 0x0A9, 0x058, 0x0A1, 0x017, 0x03A,
+ 0x08B, 0x001, 0x07D, 0x054, 0x0F7, 0x08E, 0x095, 0x025,
+ 0x008, 0x01C, 0x0E0, 0x056, 0x002, 0x0FB, 0x0C1, 0x0D1,
+ 0x015, 0x018, 0x005, 0x092, 0x06B, 0x03C, 0x01D, 0x012,
+ 0x028, 0x0C0, 0x02C, 0x0A5, 0x06C, 0x011, 0x070, 0x017,
+ 0x0B2, 0x038, 0x04D, 0x080, 0x0BE, 0x0E0, 0x02F, 0x0B4,
+ 0x0EC, 0x04A, 0x0ED, 0x0B3, 0x09E, 0x002, 0x0FB, 0x080,
+ 0x0BE, 0x0E0, 0x02F, 0x0B1, 0x039, 0x093, 0x03E, 0x06D,
+ 0x0E7, 0x010, 0x060, 0x09F, 0x032, 0x0A9, 0x0A2, 0x06C,
+ 0x005, 0x0F4, 0x040, 0x0E6, 0x00A, 0x095, 0x03D, 0x06A,
+ 0x023, 0x000, 0x0B3, 0x080, 0x0DA, 0x0A7, 0x0D6, 0x02A,
+ 0x003, 0x00D, 0x070, 0x017, 0x0D2, 0x02E, 0x076, 0x029,
+ 0x04F, 0x0BC, 0x054, 0x0A6, 0x051, 0x06F, 0x07A, 0x058,
+ 0x0B4, 0x0AC, 0x005, 0x0F4, 0x08B, 0x0A2, 0x0F4, 0x00E,
+ 0x035, 0x00D, 0x049, 0x02E, 0x0B4, 0x0CC, 0x018, 0x0A5,
+ 0x0C8, 0x0F8, 0x04A, 0x097, 0x023, 0x0E1, 0x005, 0x02E,
+ 0x047, 0x0C2, 0x08A, 0x05C, 0x08F, 0x085, 0x069, 0x072,
+ 0x03E, 0x01F, 0x04A, 0x0C3, 0x055, 0x01F, 0x056, 0x043,
+ 0x032, 0x08C, 0x0A3, 0x05E, 0x060, 0x0A8, 0x045, 0x0CE,
+ 0x00D, 0x060, 0x02F, 0x0A3, 0x084, 0x09D, 0x0D8, 0x0F0,
+ 0x017, 0x0D2, 0x02E, 0x00E, 0x01B, 0x023, 0x084, 0x0D8,
+ 0x00B, 0x0EB, 0x089, 0x0F3, 0x080, 0x0BE, 0x0E0, 0x02F,
+ 0x0BB, 0x039, 0x085, 0x0DF, 0x022, 0x003, 0x0E7, 0x001,
+ 0x07D, 0x0C0, 0x05F, 0x070, 0x017, 0x0D1, 0x017, 0x038,
+ 0x014, 0x05B, 0x0D6, 0x0A2, 0x074, 0x00D, 0x04B, 0x07A,
+ 0x0B3, 0x031, 0x096, 0x094, 0x06B, 0x0CC, 0x035, 0x023,
+ 0x0D7, 0x049, 0x048, 0x015, 0x073, 0x029, 0x00F, 0x05D,
+ 0x08A, 0x0C0, 0x05F, 0x04D, 0x079, 0x084, 0x035, 0x080,
+ 0x0BE, 0x088, 0x01C, 0x0C3, 0x052, 0x09F, 0x059, 0x068,
+ 0x0C0, 0x02C, 0x0E0, 0x036, 0x0AA, 0x07B, 0x0CD, 0x04A,
+ 0x092, 0x0BE, 0x0F3, 0x081, 0x04A, 0x07D, 0x05B, 0x059,
+ 0x094, 0x0CA, 0x01C, 0x024, 0x0EE, 0x0C7, 0x080, 0x0BE,
+ 0x088, 0x01C, 0x0C3, 0x052, 0x09F, 0x059, 0x068, 0x0C0,
+ 0x02C, 0x0E0, 0x036, 0x0AA, 0x07B, 0x0CD, 0x04A, 0x092,
+ 0x0BE, 0x0F3, 0x081, 0x043, 0x084, 0x09C, 0x07B, 0x038,
+ 0x00B, 0x0EB, 0x0AF, 0x070, 0x0D4, 0x0EA, 0x053, 0x000,
+ 0x09B, 0x04F, 0x09C, 0x054, 0x030, 0x0F3, 0x08A, 0x094,
+ 0x0FA, 0x0B6, 0x0B3, 0x029, 0x094, 0x022, 0x0E6, 0x01A,
+ 0x085, 0x0F9, 0x0B0, 0x059, 0x093, 0x0F9, 0x0D2, 0x0C4,
+ 0x032, 0x060, 0x0B9, 0x036, 0x0B0, 0x0B3, 0x090, 0x0D9,
+ 0x077, 0x026, 0x01C, 0x027, 0x022, 0x0E8, 0x096, 0x0B4,
+ 0x023, 0x0EA, 0x09E, 0x0B5, 0x011, 0x080, 0x059, 0x065,
+ 0x086, 0x020, 0x073, 0x096, 0x08D, 0x079, 0x0AD, 0x058,
+ 0x00B, 0x0E9, 0x017, 0x044, 0x08A, 0x04A, 0x007, 0x0D7,
+ 0x07A, 0x082, 0x0A1, 0x090, 0x0FA, 0x0EF, 0x001, 0x054,
+ 0x0BA, 0x050, 0x0D4, 0x059, 0x01E, 0x02C, 0x0E9, 0x0F3,
+ 0x08A, 0x099, 0x085, 0x06B, 0x00B, 0x023, 0x015, 0x097,
+ 0x072, 0x061, 0x017, 0x030, 0x0D4, 0x02C, 0x073, 0x087,
+ 0x048, 0x0AA, 0x002, 0x081, 0x025, 0x0DE, 0x091, 0x00D,
+ 0x04A, 0x0C0, 0x05F, 0x07E, 0x0D2, 0x080, 0x0A5, 0x03E,
+ 0x0B2, 0x0D0, 0x0C8, 0x06B, 0x080, 0x0BE, 0x088, 0x01C,
+ 0x0EA, 0x009, 0x017, 0x044, 0x01A, 0x037, 0x01A, 0x091,
+ 0x074, 0x058, 0x0A3, 0x071, 0x0AF, 0x007, 0x044, 0x054,
+ 0x06E, 0x035, 0x0E0, 0x0E8, 0x0AA, 0x064, 0x00F, 0x090,
+ 0x0FA, 0x0D0, 0x063, 0x000, 0x0B3, 0x080, 0x0DA, 0x02C,
+ 0x073, 0x087, 0x048, 0x0AA, 0x002, 0x081, 0x025, 0x0DE,
+ 0x091, 0x00D, 0x04A, 0x0C0, 0x05F, 0x048, 0x0BA, 0x027,
+ 0x0A3, 0x000, 0x0B7, 0x001, 0x0B7, 0x04F, 0x09C, 0x0B4,
+ 0x06B, 0x0CC, 0x035, 0x016, 0x0F5, 0x066, 0x063, 0x02D,
+ 0x029, 0x01E, 0x0BA, 0x04A, 0x040, 0x0AB, 0x099, 0x048,
+ 0x07A, 0x0EC, 0x050, 0x08B, 0x09C, 0x008, 0x022, 0x0FC,
+ 0x0F9, 0x0B2, 0x055, 0x03D, 0x062, 0x0A9, 0x023, 0x051,
+ 0x023, 0x09C, 0x00A, 0x03C, 0x073, 0x00D, 0x044, 0x05C,
+ 0x0E1, 0x050, 0x071, 0x0CE, 0x0A1, 0x01F, 0x0E7, 0x015,
+ 0x06B, 0x00B, 0x025, 0x0ED, 0x00B, 0x093, 0x060, 0x02F,
+ 0x0AA, 0x09E, 0x0AC, 0x036, 0x065, 0x049, 0x05F, 0x07A,
+ 0x020, 0x050, 0x008, 0x07F, 0x0EF, 0x039, 0x014, 0x049,
+ 0x001, 0x011, 0x081, 0x004, 0x060, 0x040, 0x0CC, 0x059,
+ 0x0C0, 0x0AD, 0x023, 0x0EB, 0x041, 0x0B0, 0x081, 0x0F2,
+ 0x03A, 0x041, 0x0AA, 0x050, 0x043, 0x0E4, 0x0D4, 0x086,
+ 0x054, 0x0A0, 0x087, 0x0C1, 0x052, 0x0CA, 0x093, 0x001,
+ 0x032, 0x054, 0x09D, 0x024, 0x002, 0x000, 0x000, 0x052,
+ 0x0AF, 0x016, 0x046, 0x0A7, 0x091, 0x067, 0x008, 0x0B4,
+ 0x004, 0x051, 0x0F1, 0x065, 0x019, 0x0B4, 0x06E, 0x02D,
+ 0x0C0, 0x0AD, 0x049, 0x000, 0x092, 0x057, 0x01B, 0x074,
+ 0x045, 0x05F, 0x023, 0x051, 0x0B7, 0x044, 0x00A, 0x010,
+ 0x006, 0x0A3, 0x06E, 0x08B, 0x06B, 0x008, 0x01F, 0x019,
+ 0x0D1, 0x0E6, 0x080, 0x082, 0x080, 0x054, 0x004, 0x02A,
+ 0x045, 0x091, 0x0A9, 0x0E4, 0x059, 0x0C2, 0x02D, 0x001,
+ 0x014, 0x004, 0x050, 0x0D3, 0x0FC, 0x055, 0x084, 0x061,
+ 0x0D9, 0x080, 0x051, 0x02F, 0x0E2, 0x01F, 0x046, 0x05F,
+ 0x040, 0x0E0, 0x020, 0x015, 0x04A, 0x0BC, 0x059, 0x01A,
+ 0x09E, 0x045, 0x09C, 0x022, 0x0D0, 0x011, 0x048, 0x0CB,
+ 0x0E8, 0x014, 0x008, 0x001, 0x054, 0x015, 0x0E2, 0x0C8,
+ 0x0D4, 0x0F2, 0x02C, 0x0E1, 0x016, 0x080, 0x08A, 0x046,
+ 0x05F, 0x052, 0x07C, 0x0D9, 0x0A8, 0x0F8, 0x088, 0x0D0,
+ 0x05A, 0x03C, 0x0D2, 0x05C, 0x05B, 0x080, 0x0DA, 0x0A7,
+ 0x0D6, 0x05A, 0x008, 0x086, 0x0A4, 0x05D, 0x017, 0x0A0,
+ 0x0C3, 0x052, 0x02E, 0x088, 0x0A8, 0x022, 0x01F, 0x053,
+ 0x0EA, 0x0DA, 0x0CC, 0x0A6, 0x050, 0x0E1, 0x027, 0x076,
+ 0x03C, 0x005, 0x0F5, 0x04F, 0x0AB, 0x06B, 0x032, 0x099,
+ 0x043, 0x084, 0x09C, 0x07B, 0x038, 0x00B, 0x0E9, 0x027,
+ 0x0AC, 0x0D4, 0x092, 0x0E0, 0x00E, 0x0DA, 0x038, 0x04D,
+ 0x080, 0x0BE, 0x0E6, 0x07D, 0x050, 0x0BA, 0x051, 0x0AE,
+ 0x066, 0x0EF, 0x0BC, 0x0DC, 0x07B, 0x087, 0x01E, 0x002,
+ 0x0FA, 0x093, 0x0E6, 0x0CD, 0x047, 0x0C4, 0x043, 0x0CD,
+ 0x00F, 0x034, 0x09D, 0x0A3, 0x000, 0x0B0, 0x055, 0x001,
+ 0x0AE, 0x003, 0x084, 0x004, 0x0CE, 0x001, 0x0D0, 0x0E1,
+ 0x070, 0x002, 0x080, 0x00E, 0x089, 0x0E9, 0x022, 0x01F,
+ 0x0E0, 0x0E8, 0x096, 0x0B0, 0x011, 0x0F4, 0x0C2, 0x0CE,
+ 0x003, 0x06A, 0x044, 0x02D, 0x0C0, 0x06D, 0x048, 0x005,
+ 0x0B8, 0x00D, 0x0A3, 0x000, 0x0B7, 0x076, 0x0D5, 0x0DE,
+ 0x0B1, 0x050, 0x0DC, 0x07D, 0x077, 0x0BC, 0x054, 0x0BA,
+ 0x052, 0x07F, 0x058, 0x014, 0x034, 0x00F, 0x09A, 0x0F3,
+ 0x081, 0x058, 0x00B, 0x0EA, 0x0EF, 0x058, 0x014, 0x060,
+ 0x016, 0x0A5, 0x06C, 0x02E, 0x0F7, 0x081, 0x04B, 0x0A5,
+ 0x06F, 0x07D, 0x05D, 0x0EE, 0x0B5, 0x02E, 0x095, 0x080,
+ 0x0BE, 0x0F0, 0x073, 0x0BD, 0x004, 0x07C, 0x0EA, 0x0FE,
+ 0x0EB, 0x04C, 0x0DE, 0x029, 0x053, 0x0DD, 0x06A, 0x054,
+ 0x094, 0x0A9, 0x0EA, 0x00A, 0x08C, 0x002, 0x0D6, 0x04C,
+ 0x03C, 0x005, 0x0F4, 0x000, 0x0EA, 0x0CD, 0x056, 0x0AF,
+ 0x0C0, 0x047, 0x0D2, 0x09C, 0x08D, 0x029, 0x0CA, 0x0E0,
+ 0x02F, 0x0AE, 0x0BD, 0x075, 0x099, 0x09D, 0x04A, 0x0F9,
+ 0x0EF, 0x051, 0x07C, 0x094, 0x00C, 0x077, 0x080, 0x018,
+ 0x018, 0x029, 0x02A, 0x0F8, 0x0E0, 0x0E8, 0x0AA, 0x030,
+ 0x00B, 0x02A, 0x098, 0x07C, 0x01D, 0x011, 0x051, 0x080,
+ 0x059, 0x054, 0x0C3, 0x051, 0x0F5, 0x01B, 0x033, 0x024,
+ 0x0BB, 0x082, 0x0A5, 0x019, 0x05C, 0x01D, 0x010, 0x028,
+ 0x0C0, 0x02C, 0x09A, 0x0C7, 0x0C1, 0x0D1, 0x022, 0x08C,
+ 0x002, 0x0C9, 0x094, 0x064, 0x05C, 0x00C, 0x0D6, 0x08E,
+ 0x013, 0x060, 0x02F, 0x0B8, 0x00B, 0x0EA, 0x030, 0x0E3,
+ 0x0C0, 0x05F, 0x048, 0x0DC, 0x078, 0x00B, 0x0E8, 0x000,
+ 0x0E3, 0x0C0, 0x05F, 0x06C, 0x038, 0x0D5, 0x02E, 0x035,
+ 0x04F, 0x05A, 0x08A, 0x061, 0x0AA, 0x09F, 0x056, 0x01B,
+ 0x032, 0x099, 0x046, 0x042, 0x0C8, 0x001, 0x00C, 0x045,
+ 0x0CE, 0x0A5, 0x017, 0x0E6, 0x0C6, 0x0CE, 0x0A9, 0x0EB,
+ 0x015, 0x016, 0x046, 0x0A2, 0x047, 0x038, 0x014, 0x043,
+ 0x026, 0x022, 0x0E7, 0x03D, 0x060, 0x02F, 0x0AA, 0x09E,
+ 0x0B5, 0x012, 0x0E0, 0x07F, 0x001, 0x07D, 0x0E3, 0x0E7,
+ 0x002, 0x093, 0x0F9, 0x095, 0x044, 0x05C, 0x0E5, 0x0A0,
+ 0x0E3, 0x09D, 0x04A, 0x07F, 0x09C, 0x054, 0x0A9, 0x0EB,
+ 0x051, 0x005, 0x046, 0x0B9, 0x0FC, 0x0C0, 0x01B, 0x022,
+ 0x02E, 0x064, 0x054, 0x02F, 0x0CD, 0x046, 0x0CC, 0x0A7,
+ 0x0D5, 0x086, 0x0CC, 0x0A6, 0x050, 0x055, 0x0C6, 0x045,
+ 0x0CE, 0x05A, 0x00E, 0x039, 0x0D4, 0x0A7, 0x0F9, 0x0C5,
+ 0x04A, 0x09E, 0x0B5, 0x011, 0x080, 0x059, 0x0C0, 0x06D,
+ 0x0CF, 0x0E6, 0x000, 0x0D9, 0x011, 0x073, 0x022, 0x0A1,
+ 0x07E, 0x06A, 0x036, 0x065, 0x03E, 0x0AC, 0x036, 0x065,
+ 0x032, 0x0B0, 0x017, 0x0DD, 0x03E, 0x072, 0x0D2, 0x079,
+ 0x031, 0x00C, 0x098, 0x02E, 0x04C, 0x020, 0x073, 0x02A,
+ 0x08F, 0x0F3, 0x08A, 0x0AD, 0x0E7, 0x041, 0x082, 0x07C,
+ 0x0CA, 0x0A6, 0x089, 0x0B5, 0x085, 0x09F, 0x0B0, 0x0F0,
+ 0x017, 0x0D5, 0x01F, 0x054, 0x054, 0x025, 0x01A, 0x0A8,
+ 0x0FF, 0x02A, 0x094, 0x065, 0x011, 0x0D7, 0x049, 0x044,
+ 0x0D5, 0x0CC, 0x0A0, 0x055, 0x0D8, 0x0AE, 0x00E, 0x088,
+ 0x014, 0x060, 0x016, 0x04D, 0x063, 0x022, 0x0E0, 0x072,
+ 0x086, 0x038, 0x04D, 0x080, 0x0BE, 0x0E0, 0x02F, 0x0B8,
+ 0x00B, 0x0EE, 0x002, 0x0FB, 0x081, 0x038, 0x0F0, 0x017,
+ 0x0D7, 0x0D7, 0x01E, 0x002, 0x0FA, 0x0FA, 0x0E3, 0x0C0,
+ 0x05F, 0x04C, 0x085, 0x090, 0x002, 0x018, 0x0C8, 0x05B,
+ 0x080, 0x0DA, 0x030, 0x00B, 0x070, 0x01B, 0x04C, 0x022,
+ 0x0D3, 0x04C, 0x033, 0x003, 0x08C, 0x02E, 0x04C, 0x043,
+ 0x026, 0x0D0, 0x0F5, 0x063, 0x066, 0x0D0, 0x095, 0x0A7,
+ 0x0CE, 0x045, 0x033, 0x00A, 0x0D6, 0x016, 0x042, 0x038,
+ 0x06E, 0x0E4, 0x0CE, 0x0BD, 0x059, 0x02C, 0x0D2, 0x0AB,
+ 0x0BA, 0x094, 0x09D, 0x0E6, 0x01A, 0x0B0, 0x017, 0x0D5,
+ 0x04F, 0x05A, 0x08B, 0x009, 0x01A, 0x088, 0x0B9, 0x0C5,
+ 0x042, 0x047, 0x030, 0x0D4, 0x032, 0x016, 0x072, 0x088,
+ 0x065, 0x0BD, 0x059, 0x099, 0x025, 0x0A5, 0x060, 0x02F,
+ 0x0B8, 0x060, 0x0F3, 0x008, 0x0B7, 0x04A, 0x01A, 0x08F,
+ 0x0AB, 0x00D, 0x099, 0x046, 0x051, 0x0AF, 0x038, 0x0A8,
+ 0x08E, 0x090, 0x065, 0x013, 0x052, 0x018, 0x0A0, 0x054,
+ 0x0B1, 0x042, 0x02E, 0x061, 0x0A8, 0x048, 0x0E7, 0x02D,
+ 0x016, 0x0F7, 0x0A8, 0x005, 0x0A5, 0x060, 0x02F, 0x0A4,
+ 0x075, 0x0D2, 0x051, 0x035, 0x073, 0x028, 0x015, 0x076,
+ 0x02B, 0x083, 0x0A2, 0x005, 0x018, 0x005, 0x093, 0x058,
+ 0x0C8, 0x0B8, 0x006, 0x028, 0x063, 0x084, 0x0D8, 0x00B,
+ 0x0EE, 0x002, 0x0FB, 0x080, 0x0BE, 0x0E0, 0x02F, 0x0A0,
+ 0x043, 0x0A7, 0x001, 0x07D, 0x04C, 0x0E3, 0x0C0, 0x05F,
+ 0x070, 0x017, 0x0DC, 0x005, 0x0F4, 0x064, 0x02D, 0x0C0,
+ 0x06D, 0x018, 0x005, 0x0B8, 0x00D, 0x0A5, 0x0BD, 0x06A,
+ 0x023, 0x086, 0x0AA, 0x09E, 0x0B5, 0x011, 0x0A4, 0x06A,
+ 0x0A3, 0x0EA, 0x08A, 0x08D, 0x023, 0x0E1, 0x017, 0x038,
+ 0x034, 0x069, 0x071, 0x098, 0x045, 0x0A6, 0x098, 0x06A,
+ 0x03E, 0x0AC, 0x036, 0x065, 0x019, 0x046, 0x0BC, 0x0E2,
+ 0x0A2, 0x03A, 0x041, 0x094, 0x04D, 0x048, 0x062, 0x081,
+ 0x052, 0x0C5, 0x016, 0x0F7, 0x0A8, 0x08B, 0x04A, 0x054,
+ 0x0F5, 0x0A8, 0x08C, 0x002, 0x0DC, 0x006, 0x0D1, 0x003,
+ 0x09C, 0x0B4, 0x0A9, 0x0EE, 0x00A, 0x095, 0x025, 0x02A,
+ 0x07A, 0x0AD, 0x046, 0x001, 0x067, 0x001, 0x0B5, 0x0D7,
+ 0x0AC, 0x00A, 0x030, 0x00B, 0x06C, 0x049, 0x035, 0x0E6,
+ 0x0B5, 0x067, 0x0F3, 0x000, 0x06C, 0x088, 0x0B9, 0x091,
+ 0x050, 0x0BF, 0x031, 0x01B, 0x032, 0x0A7, 0x0B8, 0x068,
+ 0x095, 0x025, 0x07B, 0x0AD, 0x033, 0x078, 0x0A7, 0x0CD,
+ 0x03E, 0x0D3, 0x08E, 0x09D, 0x034, 0x0E7, 0x04E, 0x0D4,
+ 0x022, 0x0E7, 0x006, 0x084, 0x08E, 0x060, 0x0A8, 0x0FF,
+ 0x038, 0x0AB, 0x083, 0x09C, 0x02A, 0x008, 0x0F9, 0x0D4,
+ 0x020, 0x063, 0x0BC, 0x01A, 0x006, 0x00A, 0x0C0, 0x05F,
+ 0x046, 0x042, 0x0DC, 0x006, 0x0D1, 0x080, 0x05B, 0x080,
+ 0x0DA, 0x022, 0x0E6, 0x01A, 0x084, 0x08E, 0x072, 0x0D1,
+ 0x06F, 0x05A, 0x080, 0x087, 0x01A, 0x0AA, 0x07A, 0x0D4,
+ 0x048, 0x0C8, 0x0D5, 0x047, 0x0D5, 0x015, 0x023, 0x023,
+ 0x0E1, 0x017, 0x038, 0x034, 0x08C, 0x0BA, 0x04B, 0x07B,
+ 0x0D4, 0x002, 0x0D2, 0x08C, 0x022, 0x0DC, 0x006, 0x0D5,
+ 0x01F, 0x056, 0x01B, 0x032, 0x08C, 0x0A3, 0x05E, 0x071,
+ 0x051, 0x01D, 0x020, 0x0CA, 0x026, 0x0A4, 0x031, 0x040,
+ 0x0A9, 0x062, 0x0B0, 0x017, 0x0DF, 0x09E, 0x0F4, 0x0B7,
+ 0x0C9, 0x040, 0x0C7, 0x078, 0x001, 0x081, 0x082, 0x0B8,
+ 0x038, 0x039, 0x049, 0x01C, 0x026, 0x0C0, 0x05F, 0x070,
+ 0x017, 0x0D4, 0x0AB, 0x0E1, 0x02A, 0x0F8, 0x04A, 0x0BE,
+ 0x012, 0x0AF, 0x08F, 0x097, 0x04F, 0x0CB, 0x0A7, 0x001,
+ 0x07D, 0x0DA, 0x080, 0x0AA, 0x091, 0x064, 0x07F, 0x04A,
+ 0x081, 0x0D5, 0x022, 0x0C8, 0x0FE, 0x082, 0x080, 0x025,
+ 0x048, 0x0B2, 0x03E, 0x0BB, 0x0DC, 0x035, 0x02E, 0x094,
+ 0x007, 0x0E8, 0x08A, 0x09C, 0x003, 0x0E2, 0x04B, 0x0A5,
+ 0x077, 0x0AB, 0x0B3, 0x032, 0x0E9, 0x04B, 0x0BD, 0x059,
+ 0x086, 0x084, 0x097, 0x07A, 0x004, 0x0BA, 0x053, 0x0E1,
+ 0x032, 0x0EF, 0x050, 0x0D4, 0x0E6, 0x035, 0x053, 0x0EB,
+ 0x002, 0x09C, 0x0C7, 0x0D7, 0x07A, 0x0B3, 0x030, 0x0D2,
+ 0x05D, 0x0EA, 0x002, 0x0E9, 0x044, 0x05D, 0x016, 0x028,
+ 0x0C0, 0x02C, 0x0E0, 0x036, 0x091, 0x074, 0x045, 0x059,
+ 0x018, 0x0D5, 0x04F, 0x0AC, 0x00A, 0x0C4, 0x035, 0x030,
+ 0x08B, 0x038, 0x069, 0x02B, 0x0BD, 0x059, 0x098, 0x069,
+ 0x02E, 0x0F5, 0x012, 0x0E9, 0x058, 0x067, 0x04A, 0x0EF,
+ 0x050, 0x0D5, 0x08E, 0x03E, 0x01C, 0x0A4, 0x0B0, 0x0CE,
+ 0x093, 0x021, 0x06E, 0x01A, 0x048, 0x01F, 0x0A2, 0x02A,
+ 0x0C3, 0x00D, 0x057, 0x07A, 0x0B3, 0x00D, 0x009, 0x02E,
+ 0x0F4, 0x043, 0x05D, 0x028, 0x08B, 0x083, 0x020, 0x092,
+ 0x038, 0x04D, 0x080, 0x0BE, 0x0E0, 0x02F, 0x0AC, 0x017,
+ 0x049, 0x0B3, 0x0A5, 0x082, 0x0E9, 0x03E, 0x0E9, 0x036,
+ 0x074, 0x0E0, 0x02F, 0x0A6, 0x0CE, 0x09C, 0x005, 0x0F4,
+ 0x0C2, 0x02C, 0x08C, 0x052, 0x057, 0x07A, 0x0D4, 0x08D,
+ 0x048, 0x0FA, 0x0EF, 0x050, 0x0D5, 0x0AE, 0x035, 0x053,
+ 0x0EB, 0x002, 0x086, 0x021, 0x0AA, 0x0EF, 0x056, 0x066,
+ 0x01A, 0x04B, 0x0BD, 0x044, 0x0BA, 0x050, 0x0C4, 0x0E9,
+ 0x053, 0x0EB, 0x002, 0x086, 0x081, 0x0F5, 0x0DE, 0x0A1,
+ 0x0A8, 0x062, 0x01F, 0x05D, 0x0FE, 0x0A2, 0x05D, 0x029,
+ 0x077, 0x0A8, 0x06A, 0x061, 0x08D, 0x040, 0x0FD, 0x011,
+ 0x053, 0x00C, 0x06A, 0x0A7, 0x0D6, 0x005, 0x030, 0x0C7,
+ 0x0D7, 0x07F, 0x0A9, 0x057, 0x04A, 0x05D, 0x0EB, 0x048,
+ 0x01B, 0x00C, 0x07C, 0x08B, 0x09D, 0x08A, 0x053, 0x0EF,
+ 0x066, 0x094, 0x0CA, 0x054, 0x0F5, 0x0A0, 0x0C6, 0x001,
+ 0x06E, 0x003, 0x06A, 0x09F, 0x056, 0x076, 0x065, 0x032,
+ 0x08B, 0x07B, 0x0D2, 0x0C5, 0x0A5, 0x060, 0x02F, 0x0AA,
+ 0x07D, 0x065, 0x0A3, 0x000, 0x0B7, 0x001, 0x0B4, 0x0C8,
+ 0x05A, 0x007, 0x08F, 0x0ED, 0x001, 0x0D5, 0x027, 0x091,
+ 0x067, 0x001, 0x0B4, 0x08B, 0x09C, 0x054, 0x01C, 0x073,
+ 0x0A8, 0x084, 0x05C, 0x0C1, 0x050, 0x0BF, 0x036, 0x056,
+ 0x060, 0x0AB, 0x08C, 0x08B, 0x09C, 0x054, 0x01C, 0x073,
+ 0x0A8, 0x084, 0x05C, 0x0C1, 0x050, 0x0BF, 0x036, 0x056,
+ 0x06C, 0x005, 0x0F5, 0x053, 0x0D6, 0x0A2, 0x030, 0x00B,
+ 0x029, 0x05B, 0x019, 0x0FC, 0x0F6, 0x094, 0x045, 0x0CF,
+ 0x015, 0x00B, 0x0F3, 0x03C, 0x0B3, 0x02A, 0x07A, 0x0C5,
+ 0x046, 0x001, 0x064, 0x08A, 0x031, 0x023, 0x09C, 0x00A,
+ 0x05D, 0x0EA, 0x034, 0x033, 0x02E, 0x095, 0x0C7, 0x0CE,
+ 0x02A, 0x04F, 0x0E6, 0x050, 0x020, 0x0B9, 0x031, 0x00C,
+ 0x09B, 0x0EF, 0x039, 0x014, 0x045, 0x0CE, 0x045, 0x007,
+ 0x01C, 0x0EA, 0x046, 0x087, 0x0AB, 0x01B, 0x036, 0x084,
+ 0x0A7, 0x05E, 0x0AC, 0x096, 0x067, 0x052, 0x0B0, 0x017,
+ 0x0DC, 0x0FE, 0x07B, 0x04A, 0x022, 0x0E7, 0x08A, 0x085,
+ 0x0F9, 0x09E, 0x059, 0x097, 0x07A, 0x08D, 0x00C, 0x0CB,
+ 0x0A5, 0x027, 0x0F3, 0x0A0, 0x044, 0x032, 0x060, 0x0B9,
+ 0x037, 0x0DE, 0x072, 0x028, 0x08B, 0x09C, 0x08A, 0x00E,
+ 0x039, 0x0D4, 0x08C, 0x005, 0x0F7, 0x0E7, 0x0B8, 0x02A,
+ 0x0F9, 0x028, 0x018, 0x0EF, 0x000, 0x030, 0x030, 0x057,
+ 0x007, 0x044, 0x00A, 0x050, 0x08F, 0x0F0, 0x073, 0x091,
+ 0x041, 0x01F, 0x03A, 0x090, 0x045, 0x0C0, 0x0BB, 0x018,
+ 0x0E1, 0x036, 0x002, 0x0FB, 0x0FB, 0x09E, 0x002, 0x0FA,
+ 0x0EE, 0x0E7, 0x0F5, 0x0CF, 0x001, 0x07D, 0x010, 0x05C,
+ 0x0F0, 0x017, 0x0D1, 0x005, 0x0CF, 0x001, 0x07D, 0x053,
+ 0x0EB, 0x02D, 0x018, 0x005, 0x0B8, 0x00D, 0x0A6, 0x042,
+ 0x0DC, 0x006, 0x0D3, 0x017, 0x035, 0x0A8, 0x08B, 0x09C,
+ 0x00A, 0x00E, 0x039, 0x0D4, 0x00C, 0x0FE, 0x07B, 0x04A,
+ 0x022, 0x0E6, 0x055, 0x00B, 0x0F3, 0x031, 0x0B3, 0x060,
+ 0x02F, 0x0BC, 0x07C, 0x0E2, 0x0A4, 0x0FE, 0x065, 0x051,
+ 0x017, 0x038, 0x014, 0x01C, 0x073, 0x0A8, 0x019, 0x0FC,
+ 0x0F6, 0x094, 0x045, 0x0CC, 0x0AA, 0x017, 0x0E6, 0x063,
+ 0x066, 0x00A, 0x0B8, 0x0CC, 0x085, 0x0A1, 0x058, 0x0F6,
+ 0x0A2, 0x035, 0x048, 0x048, 0x07F, 0x04A, 0x089, 0x095,
+ 0x021, 0x021, 0x0FD, 0x005, 0x002, 0x054, 0x09E, 0x045,
+ 0x091, 0x00E, 0x03C, 0x005, 0x0F5, 0x007, 0x040, 0x055,
+ 0x048, 0x052, 0x03E, 0x086, 0x0A0, 0x075, 0x048, 0x052,
+ 0x03E, 0x0B5, 0x000, 0x04A, 0x09C, 0x000, 0x06B, 0x0C7,
+ 0x0CE, 0x045, 0x027, 0x0F3, 0x02A, 0x084, 0x037, 0x035,
+ 0x0DE, 0x0A0, 0x0AB, 0x023, 0x01A, 0x0AE, 0x0F5, 0x083,
+ 0x059, 0x018, 0x0D7, 0x043, 0x0DE, 0x02A, 0x0D0, 0x094,
+ 0x0EB, 0x0DE, 0x005, 0x03A, 0x095, 0x09F, 0x0CC, 0x0C3,
+ 0x020, 0x045, 0x0CC, 0x0AA, 0x017, 0x0E6, 0x066, 0x0CC,
+ 0x043, 0x026, 0x04F, 0x0E7, 0x041, 0x022, 0x02E, 0x070,
+ 0x068, 0x038, 0x0E7, 0x053, 0x0E0, 0x02F, 0x0AB, 0x0BC,
+ 0x012, 0x0D2, 0x0E9, 0x058, 0x00B, 0x0EA, 0x0A7, 0x0AD,
+ 0x045, 0x0A1, 0x01F, 0x0C0, 0x05F, 0x078, 0x039, 0x0C8,
+ 0x0A0, 0x08F, 0x09D, 0x048, 0x01C, 0x024, 0x0EE, 0x0C7,
+ 0x080, 0x0BE, 0x0BA, 0x0F5, 0x06D, 0x066, 0x049, 0x077,
+ 0x00D, 0x04E, 0x0A5, 0x030, 0x009, 0x0B4, 0x0F9, 0x0C5,
+ 0x043, 0x00F, 0x038, 0x0A9, 0x03F, 0x09D, 0x002, 0x0FB,
+ 0x0CE, 0x045, 0x011, 0x073, 0x091, 0x041, 0x0C7, 0x03A,
+ 0x091, 0x09F, 0x0CF, 0x069, 0x044, 0x05C, 0x0F1, 0x050,
+ 0x0BF, 0x033, 0x0CB, 0x032, 0x0A7, 0x0AC, 0x054, 0x090,
+ 0x08D, 0x044, 0x08E, 0x070, 0x029, 0x077, 0x0A8, 0x0D0,
+ 0x0CC, 0x0BA, 0x056, 0x0B0, 0x0B2, 0x09D, 0x08C, 0x086,
+ 0x04C, 0x017, 0x026, 0x077, 0x026, 0x01C, 0x027, 0x01C,
+ 0x024, 0x09E, 0x023, 0x061, 0x0BE, 0x08E, 0x012, 0x04F,
+ 0x011, 0x087, 0x01C, 0x0EA, 0x05C, 0x005, 0x0F5, 0x0D7,
+ 0x0B8, 0x06A, 0x075, 0x029, 0x077, 0x0AB, 0x00D, 0x099,
+ 0x074, 0x0A5, 0x04F, 0x072, 0x0A0, 0x0AA, 0x04A, 0x0C6,
+ 0x0F3, 0x066, 0x066, 0x0C6, 0x039, 0x082, 0x0AF, 0x075,
+ 0x0A6, 0x06F, 0x014, 0x06B, 0x0CE, 0x005, 0x070, 0x073,
+ 0x096, 0x082, 0x03E, 0x075, 0x028, 0x0E1, 0x03A, 0x0A7,
+ 0x0AD, 0x044, 0x060, 0x016, 0x052, 0x0B6, 0x01D, 0x07A,
+ 0x0B6, 0x0B3, 0x024, 0x0BB, 0x086, 0x0A7, 0x052, 0x098,
+ 0x004, 0x0DA, 0x07C, 0x0E2, 0x0A1, 0x087, 0x09C, 0x055,
+ 0x0F7, 0x09C, 0x0B5, 0x0AC, 0x02C, 0x095, 0x033, 0x0B9,
+ 0x031, 0x005, 0x0D9, 0x053, 0x0D6, 0x0A2, 0x030, 0x00B,
+ 0x029, 0x05B, 0x002, 0x02E, 0x061, 0x05A, 0x017, 0x0E6,
+ 0x09C, 0x0B3, 0x02A, 0x07A, 0x0C5, 0x040, 0x021, 0x0A8,
+ 0x091, 0x0CE, 0x005, 0x027, 0x0F3, 0x0A5, 0x088, 0x064,
+ 0x0C1, 0x072, 0x065, 0x04F, 0x058, 0x014, 0x00C, 0x08D,
+ 0x07E, 0x0F3, 0x081, 0x044, 0x05C, 0x0EF, 0x041, 0x0C7,
+ 0x03A, 0x0BE, 0x002, 0x0FA, 0x0A9, 0x0EA, 0x0CE, 0x0CC,
+ 0x0A9, 0x029, 0x053, 0x0D6, 0x0A2, 0x046, 0x047, 0x0DD,
+ 0x07A, 0x0C0, 0x0A3, 0x000, 0x086, 0x0E2, 0x09B, 0x029,
+ 0x078, 0x08B, 0x081, 0x009, 0x098, 0x070, 0x09B, 0x029,
+ 0x079, 0x05D, 0x0D9, 0x072, 0x0ED, 0x094, 0x0BC, 0x0B9,
+ 0x076, 0x013, 0x03B, 0x02A, 0x05D, 0x0B2, 0x097, 0x095,
+ 0x02E, 0x0D9, 0x04B, 0x0CA, 0x07D, 0x05B, 0x059, 0x094,
+ 0x0CA, 0x01C, 0x024, 0x0EE, 0x0C7, 0x094, 0x0BC, 0x0C0,
+ 0x026, 0x0D3, 0x0E7, 0x015, 0x00C, 0x03C, 0x0E2, 0x0AC,
+ 0x0FE, 0x07B, 0x04A, 0x022, 0x0E7, 0x08A, 0x085, 0x0F9,
+ 0x09E, 0x059, 0x097, 0x07A, 0x08D, 0x00C, 0x0CB, 0x0A5,
+ 0x027, 0x0F3, 0x0A0, 0x041, 0x072, 0x062, 0x019, 0x037,
+ 0x0DE, 0x070, 0x028, 0x08B, 0x09C, 0x08A, 0x00E, 0x039,
+ 0x0D4, 0x08D, 0x00F, 0x056, 0x036, 0x06D, 0x009, 0x04E,
+ 0x0BD, 0x059, 0x02C, 0x0CE, 0x0A5, 0x06B, 0x00B, 0x022,
+ 0x0D9, 0x09D, 0x0C9, 0x0B2, 0x097, 0x0BE, 0x0F3, 0x081,
+ 0x04A, 0x07D, 0x065, 0x0A3, 0x000, 0x093, 0x08F, 0x067,
+ 0x029, 0x078, 0x0C2, 0x04D, 0x0C1, 0x0D1, 0x006, 0x082,
+ 0x031, 0x0AF, 0x007, 0x038, 0x034, 0x011, 0x0F3, 0x0A8,
+ 0x02A, 0x09E, 0x0A8, 0x066, 0x01A, 0x0A4, 0x0A5, 0x04F,
+ 0x05A, 0x00C, 0x011, 0x08F, 0x0AA, 0x07B, 0x0D0, 0x065,
+ 0x049, 0x045, 0x0BD, 0x0E9, 0x062, 0x0D2, 0x0B1, 0x09E,
+ 0x06C, 0x0CC, 0x0C6, 0x019, 0x087, 0x009, 0x0C3, 0x08E,
+ 0x075, 0x041, 0x01F, 0x03A, 0x0A5, 0x013, 0x0D5, 0x055,
+ 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055,
+ 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055,
+ 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055,
+ 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055,
+ 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055,
+ 0x055, 0x055, 0x055, 0x05A, 0x0CC, 0x090
+ };
+
+#endif /* defined(CONFIG_SMCTR) || defined(CONFIG_SMCTR_MODULE) */
diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
new file mode 100644
index 00000000000..df43b449e42
--- /dev/null
+++ b/drivers/net/tokenring/tms380tr.c
@@ -0,0 +1,2410 @@
+/*
+ * tms380tr.c: A network driver library for Texas Instruments TMS380-based
+ * Token Ring Adapters.
+ *
+ * Originally sktr.c: Written 1997 by Christoph Goos
+ *
+ * A fine result of the Linux Systems Network Architecture Project.
+ * http://www.linux-sna.org
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * The following modules are currently available for card support:
+ * - tmspci (Generic PCI card support)
+ * - abyss (Madge PCI support)
+ * - tmsisa (SysKonnect TR4/16 ISA)
+ *
+ * Sources:
+ * - The hardware related parts of this driver are take from
+ * the SysKonnect Token Ring driver for Windows NT.
+ * - I used the IBM Token Ring driver 'ibmtr.c' as a base for this
+ * driver, as well as the 'skeleton.c' driver by Donald Becker.
+ * - Also various other drivers in the linux source tree were taken
+ * as samples for some tasks.
+ * - TI TMS380 Second-Generation Token Ring User's Guide
+ * - TI datasheets for respective chips
+ * - David Hein at Texas Instruments
+ * - Various Madge employees
+ *
+ * Maintainer(s):
+ * JS Jay Schulist jschlst@samba.org
+ * CG Christoph Goos cgoos@syskonnect.de
+ * AF Adam Fritzler mid@auk.cx
+ * MLP Mike Phillips phillim@amtrak.com
+ * JF Jochen Friedrich jochen@scram.de
+ *
+ * Modification History:
+ * 29-Aug-97 CG Created
+ * 04-Apr-98 CG Fixed problems caused by tok_timer_check
+ * 10-Apr-98 CG Fixed lockups at cable disconnection
+ * 27-May-98 JS Formated to Linux Kernel Format
+ * 31-May-98 JS Hacked in PCI support
+ * 16-Jun-98 JS Modulized for multiple cards with one driver
+ * Sep-99 AF Renamed to tms380tr (supports more than SK's)
+ * 23-Sep-99 AF Added Compaq and Thomas-Conrad PCI support
+ * Fixed a bug causing double copies on PCI
+ * Fixed for new multicast stuff (2.2/2.3)
+ * 25-Sep-99 AF Uped TPL_NUM from 3 to 9
+ * Removed extraneous 'No free TPL'
+ * 22-Dec-99 AF Added Madge PCI Mk2 support and generalized
+ * parts of the initilization procedure.
+ * 30-Dec-99 AF Turned tms380tr into a library ala 8390.
+ * Madge support is provided in the abyss module
+ * Generic PCI support is in the tmspci module.
+ * 30-Nov-00 JF Updated PCI code to support IO MMU via
+ * pci_map_static(). Alpha uses this MMU for ISA
+ * as well.
+ * 14-Jan-01 JF Fix DMA on ifdown/ifup sequences. Some
+ * cleanup.
+ * 13-Jan-02 JF Add spinlock to fix race condition.
+ * 09-Nov-02 JF Fixed printks to not SPAM the console during
+ * normal operation.
+ * 30-Dec-02 JF Removed incorrect __init from
+ * tms380tr_init_card.
+ *
+ * To do:
+ * 1. Multi/Broadcast packet handling (this may have fixed itself)
+ * 2. Write a sktrisa module that includes the old ISA support (done)
+ * 3. Allow modules to load their own microcode
+ * 4. Speed up the BUD process -- freezing the kernel for 3+sec is
+ * quite unacceptable.
+ * 5. Still a few remaining stalls when the cable is unplugged.
+ */
+
+#ifdef MODULE
+static const char version[] = "tms380tr.c: v1.10 30/12/2002 by Christoph Goos, Adam Fritzler\n";
+#endif
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/time.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/trdevice.h>
+#include <linux/firmware.h>
+#include <linux/bitops.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "tms380tr.h" /* Our Stuff */
+
+/* Use 0 for production, 1 for verification, 2 for debug, and
+ * 3 for very verbose debug.
+ */
+#ifndef TMS380TR_DEBUG
+#define TMS380TR_DEBUG 0
+#endif
+static unsigned int tms380tr_debug = TMS380TR_DEBUG;
+
+static struct device tms_device;
+
+/* Index to functions, as function prototypes.
+ * Alphabetical by function name.
+ */
+
+/* "A" */
+/* "B" */
+static int tms380tr_bringup_diags(struct net_device *dev);
+/* "C" */
+static void tms380tr_cancel_tx_queue(struct net_local* tp);
+static int tms380tr_chipset_init(struct net_device *dev);
+static void tms380tr_chk_irq(struct net_device *dev);
+static void tms380tr_chk_outstanding_cmds(struct net_device *dev);
+static void tms380tr_chk_src_addr(unsigned char *frame, unsigned char *hw_addr);
+static unsigned char tms380tr_chk_ssb(struct net_local *tp, unsigned short IrqType);
+int tms380tr_close(struct net_device *dev);
+static void tms380tr_cmd_status_irq(struct net_device *dev);
+/* "D" */
+static void tms380tr_disable_interrupts(struct net_device *dev);
+#if TMS380TR_DEBUG > 0
+static void tms380tr_dump(unsigned char *Data, int length);
+#endif
+/* "E" */
+static void tms380tr_enable_interrupts(struct net_device *dev);
+static void tms380tr_exec_cmd(struct net_device *dev, unsigned short Command);
+static void tms380tr_exec_sifcmd(struct net_device *dev, unsigned int WriteValue);
+/* "F" */
+/* "G" */
+static struct net_device_stats *tms380tr_get_stats(struct net_device *dev);
+/* "H" */
+static int tms380tr_hardware_send_packet(struct sk_buff *skb,
+ struct net_device *dev);
+/* "I" */
+static int tms380tr_init_adapter(struct net_device *dev);
+static void tms380tr_init_ipb(struct net_local *tp);
+static void tms380tr_init_net_local(struct net_device *dev);
+static void tms380tr_init_opb(struct net_device *dev);
+/* "M" */
+/* "O" */
+int tms380tr_open(struct net_device *dev);
+static void tms380tr_open_adapter(struct net_device *dev);
+/* "P" */
+/* "R" */
+static void tms380tr_rcv_status_irq(struct net_device *dev);
+static int tms380tr_read_ptr(struct net_device *dev);
+static void tms380tr_read_ram(struct net_device *dev, unsigned char *Data,
+ unsigned short Address, int Length);
+static int tms380tr_reset_adapter(struct net_device *dev);
+static void tms380tr_reset_interrupt(struct net_device *dev);
+static void tms380tr_ring_status_irq(struct net_device *dev);
+/* "S" */
+static int tms380tr_send_packet(struct sk_buff *skb, struct net_device *dev);
+static void tms380tr_set_multicast_list(struct net_device *dev);
+static int tms380tr_set_mac_address(struct net_device *dev, void *addr);
+/* "T" */
+static void tms380tr_timer_chk(unsigned long data);
+static void tms380tr_timer_end_wait(unsigned long data);
+static void tms380tr_tx_status_irq(struct net_device *dev);
+/* "U" */
+static void tms380tr_update_rcv_stats(struct net_local *tp,
+ unsigned char DataPtr[], unsigned int Length);
+/* "W" */
+void tms380tr_wait(unsigned long time);
+static void tms380tr_write_rpl_status(RPL *rpl, unsigned int Status);
+static void tms380tr_write_tpl_status(TPL *tpl, unsigned int Status);
+
+#define SIFREADB(reg) (((struct net_local *)dev->priv)->sifreadb(dev, reg))
+#define SIFWRITEB(val, reg) (((struct net_local *)dev->priv)->sifwriteb(dev, val, reg))
+#define SIFREADW(reg) (((struct net_local *)dev->priv)->sifreadw(dev, reg))
+#define SIFWRITEW(val, reg) (((struct net_local *)dev->priv)->sifwritew(dev, val, reg))
+
+
+
+#if 0 /* TMS380TR_DEBUG > 0 */
+static int madgemc_sifprobe(struct net_device *dev)
+{
+ unsigned char old, chk1, chk2;
+
+ old = SIFREADB(SIFADR); /* Get the old SIFADR value */
+
+ chk1 = 0; /* Begin with check value 0 */
+ do {
+ madgemc_setregpage(dev, 0);
+ /* Write new SIFADR value */
+ SIFWRITEB(chk1, SIFADR);
+ chk2 = SIFREADB(SIFADR);
+ if (chk2 != chk1)
+ return -1;
+
+ madgemc_setregpage(dev, 1);
+ /* Read, invert and write */
+ chk2 = SIFREADB(SIFADD);
+ if (chk2 != chk1)
+ return -1;
+
+ madgemc_setregpage(dev, 0);
+ chk2 ^= 0x0FE;
+ SIFWRITEB(chk2, SIFADR);
+
+ /* Read, invert and compare */
+ madgemc_setregpage(dev, 1);
+ chk2 = SIFREADB(SIFADD);
+ madgemc_setregpage(dev, 0);
+ chk2 ^= 0x0FE;
+
+ if(chk1 != chk2)
+ return (-1); /* No adapter */
+ chk1 -= 2;
+ } while(chk1 != 0); /* Repeat 128 times (all byte values) */
+
+ madgemc_setregpage(dev, 0); /* sanity */
+ /* Restore the SIFADR value */
+ SIFWRITEB(old, SIFADR);
+
+ return (0);
+}
+#endif
+
+/*
+ * Open/initialize the board. This is called sometime after
+ * booting when the 'ifconfig' program is run.
+ *
+ * This routine should set everything up anew at each open, even
+ * registers that "should" only need to be set once at boot, so that
+ * there is non-reboot way to recover if something goes wrong.
+ */
+int tms380tr_open(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int err;
+
+ /* init the spinlock */
+ spin_lock_init(&tp->lock);
+ init_timer(&tp->timer);
+
+ /* Reset the hardware here. Don't forget to set the station address. */
+
+#ifdef CONFIG_ISA
+ if(dev->dma > 0)
+ {
+ unsigned long flags=claim_dma_lock();
+ disable_dma(dev->dma);
+ set_dma_mode(dev->dma, DMA_MODE_CASCADE);
+ enable_dma(dev->dma);
+ release_dma_lock(flags);
+ }
+#endif
+
+ err = tms380tr_chipset_init(dev);
+ if(err)
+ {
+ printk(KERN_INFO "%s: Chipset initialization error\n",
+ dev->name);
+ return (-1);
+ }
+
+ tp->timer.expires = jiffies + 30*HZ;
+ tp->timer.function = tms380tr_timer_end_wait;
+ tp->timer.data = (unsigned long)dev;
+ add_timer(&tp->timer);
+
+ printk(KERN_DEBUG "%s: Adapter RAM size: %dK\n",
+ dev->name, tms380tr_read_ptr(dev));
+
+ tms380tr_enable_interrupts(dev);
+ tms380tr_open_adapter(dev);
+
+ netif_start_queue(dev);
+
+ /* Wait for interrupt from hardware. If interrupt does not come,
+ * there will be a timeout from the timer.
+ */
+ tp->Sleeping = 1;
+ interruptible_sleep_on(&tp->wait_for_tok_int);
+ del_timer(&tp->timer);
+
+ /* If AdapterVirtOpenFlag is 1, the adapter is now open for use */
+ if(tp->AdapterVirtOpenFlag == 0)
+ {
+ tms380tr_disable_interrupts(dev);
+ return (-1);
+ }
+
+ tp->StartTime = jiffies;
+
+ /* Start function control timer */
+ tp->timer.expires = jiffies + 2*HZ;
+ tp->timer.function = tms380tr_timer_chk;
+ tp->timer.data = (unsigned long)dev;
+ add_timer(&tp->timer);
+
+ return (0);
+}
+
+/*
+ * Timeout function while waiting for event
+ */
+static void tms380tr_timer_end_wait(unsigned long data)
+{
+ struct net_device *dev = (struct net_device*)data;
+ struct net_local *tp = netdev_priv(dev);
+
+ if(tp->Sleeping)
+ {
+ tp->Sleeping = 0;
+ wake_up_interruptible(&tp->wait_for_tok_int);
+ }
+
+ return;
+}
+
+/*
+ * Initialize the chipset
+ */
+static int tms380tr_chipset_init(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int err;
+
+ tms380tr_init_ipb(tp);
+ tms380tr_init_opb(dev);
+ tms380tr_init_net_local(dev);
+
+ if(tms380tr_debug > 3)
+ printk(KERN_DEBUG "%s: Resetting adapter...\n", dev->name);
+ err = tms380tr_reset_adapter(dev);
+ if(err < 0)
+ return (-1);
+
+ if(tms380tr_debug > 3)
+ printk(KERN_DEBUG "%s: Bringup diags...\n", dev->name);
+ err = tms380tr_bringup_diags(dev);
+ if(err < 0)
+ return (-1);
+
+ if(tms380tr_debug > 3)
+ printk(KERN_DEBUG "%s: Init adapter...\n", dev->name);
+ err = tms380tr_init_adapter(dev);
+ if(err < 0)
+ return (-1);
+
+ if(tms380tr_debug > 3)
+ printk(KERN_DEBUG "%s: Done!\n", dev->name);
+ return (0);
+}
+
+/*
+ * Initializes the net_local structure.
+ */
+static void tms380tr_init_net_local(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int i;
+ dma_addr_t dmabuf;
+
+ tp->scb.CMD = 0;
+ tp->scb.Parm[0] = 0;
+ tp->scb.Parm[1] = 0;
+
+ tp->ssb.STS = 0;
+ tp->ssb.Parm[0] = 0;
+ tp->ssb.Parm[1] = 0;
+ tp->ssb.Parm[2] = 0;
+
+ tp->CMDqueue = 0;
+
+ tp->AdapterOpenFlag = 0;
+ tp->AdapterVirtOpenFlag = 0;
+ tp->ScbInUse = 0;
+ tp->OpenCommandIssued = 0;
+ tp->ReOpenInProgress = 0;
+ tp->HaltInProgress = 0;
+ tp->TransmitHaltScheduled = 0;
+ tp->LobeWireFaultLogged = 0;
+ tp->LastOpenStatus = 0;
+ tp->MaxPacketSize = DEFAULT_PACKET_SIZE;
+
+ /* Create circular chain of transmit lists */
+ for (i = 0; i < TPL_NUM; i++)
+ {
+ tp->Tpl[i].NextTPLAddr = htonl(((char *)(&tp->Tpl[(i+1) % TPL_NUM]) - (char *)tp) + tp->dmabuffer); /* DMA buffer may be MMU driven */
+ tp->Tpl[i].Status = 0;
+ tp->Tpl[i].FrameSize = 0;
+ tp->Tpl[i].FragList[0].DataCount = 0;
+ tp->Tpl[i].FragList[0].DataAddr = 0;
+ tp->Tpl[i].NextTPLPtr = &tp->Tpl[(i+1) % TPL_NUM];
+ tp->Tpl[i].MData = NULL;
+ tp->Tpl[i].TPLIndex = i;
+ tp->Tpl[i].DMABuff = 0;
+ tp->Tpl[i].BusyFlag = 0;
+ }
+
+ tp->TplFree = tp->TplBusy = &tp->Tpl[0];
+
+ /* Create circular chain of receive lists */
+ for (i = 0; i < RPL_NUM; i++)
+ {
+ tp->Rpl[i].NextRPLAddr = htonl(((char *)(&tp->Rpl[(i+1) % RPL_NUM]) - (char *)tp) + tp->dmabuffer); /* DMA buffer may be MMU driven */
+ tp->Rpl[i].Status = (RX_VALID | RX_START_FRAME | RX_END_FRAME | RX_FRAME_IRQ);
+ tp->Rpl[i].FrameSize = 0;
+ tp->Rpl[i].FragList[0].DataCount = cpu_to_be16((unsigned short)tp->MaxPacketSize);
+
+ /* Alloc skb and point adapter to data area */
+ tp->Rpl[i].Skb = dev_alloc_skb(tp->MaxPacketSize);
+ tp->Rpl[i].DMABuff = 0;
+
+ /* skb == NULL ? then use local buffer */
+ if(tp->Rpl[i].Skb == NULL)
+ {
+ tp->Rpl[i].SkbStat = SKB_UNAVAILABLE;
+ tp->Rpl[i].FragList[0].DataAddr = htonl(((char *)tp->LocalRxBuffers[i] - (char *)tp) + tp->dmabuffer);
+ tp->Rpl[i].MData = tp->LocalRxBuffers[i];
+ }
+ else /* SKB != NULL */
+ {
+ tp->Rpl[i].Skb->dev = dev;
+ skb_put(tp->Rpl[i].Skb, tp->MaxPacketSize);
+
+ /* data unreachable for DMA ? then use local buffer */
+ dmabuf = pci_map_single(tp->pdev, tp->Rpl[i].Skb->data, tp->MaxPacketSize, PCI_DMA_FROMDEVICE);
+ if(tp->dmalimit && (dmabuf + tp->MaxPacketSize > tp->dmalimit))
+ {
+ tp->Rpl[i].SkbStat = SKB_DATA_COPY;
+ tp->Rpl[i].FragList[0].DataAddr = htonl(((char *)tp->LocalRxBuffers[i] - (char *)tp) + tp->dmabuffer);
+ tp->Rpl[i].MData = tp->LocalRxBuffers[i];
+ }
+ else /* DMA directly in skb->data */
+ {
+ tp->Rpl[i].SkbStat = SKB_DMA_DIRECT;
+ tp->Rpl[i].FragList[0].DataAddr = htonl(dmabuf);
+ tp->Rpl[i].MData = tp->Rpl[i].Skb->data;
+ tp->Rpl[i].DMABuff = dmabuf;
+ }
+ }
+
+ tp->Rpl[i].NextRPLPtr = &tp->Rpl[(i+1) % RPL_NUM];
+ tp->Rpl[i].RPLIndex = i;
+ }
+
+ tp->RplHead = &tp->Rpl[0];
+ tp->RplTail = &tp->Rpl[RPL_NUM-1];
+ tp->RplTail->Status = (RX_START_FRAME | RX_END_FRAME | RX_FRAME_IRQ);
+
+ return;
+}
+
+/*
+ * Initializes the initialisation parameter block.
+ */
+static void tms380tr_init_ipb(struct net_local *tp)
+{
+ tp->ipb.Init_Options = BURST_MODE;
+ tp->ipb.CMD_Status_IV = 0;
+ tp->ipb.TX_IV = 0;
+ tp->ipb.RX_IV = 0;
+ tp->ipb.Ring_Status_IV = 0;
+ tp->ipb.SCB_Clear_IV = 0;
+ tp->ipb.Adapter_CHK_IV = 0;
+ tp->ipb.RX_Burst_Size = BURST_SIZE;
+ tp->ipb.TX_Burst_Size = BURST_SIZE;
+ tp->ipb.DMA_Abort_Thrhld = DMA_RETRIES;
+ tp->ipb.SCB_Addr = 0;
+ tp->ipb.SSB_Addr = 0;
+
+ return;
+}
+
+/*
+ * Initializes the open parameter block.
+ */
+static void tms380tr_init_opb(struct net_device *dev)
+{
+ struct net_local *tp;
+ unsigned long Addr;
+ unsigned short RplSize = RPL_SIZE;
+ unsigned short TplSize = TPL_SIZE;
+ unsigned short BufferSize = BUFFER_SIZE;
+ int i;
+
+ tp = netdev_priv(dev);
+
+ tp->ocpl.OPENOptions = 0;
+ tp->ocpl.OPENOptions |= ENABLE_FULL_DUPLEX_SELECTION;
+ tp->ocpl.FullDuplex = 0;
+ tp->ocpl.FullDuplex |= OPEN_FULL_DUPLEX_OFF;
+
+ /*
+ * Set node address
+ *
+ * We go ahead and put it in the OPB even though on
+ * most of the generic adapters this isn't required.
+ * Its simpler this way. -- ASF
+ */
+ for (i=0;i<6;i++)
+ tp->ocpl.NodeAddr[i] = ((unsigned char *)dev->dev_addr)[i];
+
+ tp->ocpl.GroupAddr = 0;
+ tp->ocpl.FunctAddr = 0;
+ tp->ocpl.RxListSize = cpu_to_be16((unsigned short)RplSize);
+ tp->ocpl.TxListSize = cpu_to_be16((unsigned short)TplSize);
+ tp->ocpl.BufSize = cpu_to_be16((unsigned short)BufferSize);
+ tp->ocpl.Reserved = 0;
+ tp->ocpl.TXBufMin = TX_BUF_MIN;
+ tp->ocpl.TXBufMax = TX_BUF_MAX;
+
+ Addr = htonl(((char *)tp->ProductID - (char *)tp) + tp->dmabuffer);
+
+ tp->ocpl.ProdIDAddr[0] = LOWORD(Addr);
+ tp->ocpl.ProdIDAddr[1] = HIWORD(Addr);
+
+ return;
+}
+
+/*
+ * Send OPEN command to adapter
+ */
+static void tms380tr_open_adapter(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ if(tp->OpenCommandIssued)
+ return;
+
+ tp->OpenCommandIssued = 1;
+ tms380tr_exec_cmd(dev, OC_OPEN);
+
+ return;
+}
+
+/*
+ * Clear the adapter's interrupt flag. Clear system interrupt enable
+ * (SINTEN): disable adapter to system interrupts.
+ */
+static void tms380tr_disable_interrupts(struct net_device *dev)
+{
+ SIFWRITEB(0, SIFACL);
+
+ return;
+}
+
+/*
+ * Set the adapter's interrupt flag. Set system interrupt enable
+ * (SINTEN): enable adapter to system interrupts.
+ */
+static void tms380tr_enable_interrupts(struct net_device *dev)
+{
+ SIFWRITEB(ACL_SINTEN, SIFACL);
+
+ return;
+}
+
+/*
+ * Put command in command queue, try to execute it.
+ */
+static void tms380tr_exec_cmd(struct net_device *dev, unsigned short Command)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ tp->CMDqueue |= Command;
+ tms380tr_chk_outstanding_cmds(dev);
+
+ 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
+ */
+static int tms380tr_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ int err;
+
+ err = tms380tr_hardware_send_packet(skb, dev);
+ if(tp->TplFree->NextTPLPtr->BusyFlag)
+ netif_stop_queue(dev);
+ return (err);
+}
+
+/*
+ * Move frames into adapter tx queue
+ */
+static int tms380tr_hardware_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+ TPL *tpl;
+ short length;
+ unsigned char *buf;
+ unsigned long flags;
+ int i;
+ dma_addr_t dmabuf, newbuf;
+ struct net_local *tp = netdev_priv(dev);
+
+ /* Try to get a free TPL from the chain.
+ *
+ * NOTE: We *must* always leave one unused TPL in the chain,
+ * because otherwise the adapter might send frames twice.
+ */
+ spin_lock_irqsave(&tp->lock, flags);
+ if(tp->TplFree->NextTPLPtr->BusyFlag) { /* No free TPL */
+ if (tms380tr_debug > 0)
+ printk(KERN_DEBUG "%s: No free TPL\n", dev->name);
+ spin_unlock_irqrestore(&tp->lock, flags);
+ return 1;
+ }
+
+ dmabuf = 0;
+
+ /* Is buffer reachable for Busmaster-DMA? */
+
+ length = skb->len;
+ dmabuf = pci_map_single(tp->pdev, skb->data, length, PCI_DMA_TODEVICE);
+ if(tp->dmalimit && (dmabuf + length > tp->dmalimit)) {
+ /* Copy frame to local buffer */
+ pci_unmap_single(tp->pdev, dmabuf, length, PCI_DMA_TODEVICE);
+ dmabuf = 0;
+ i = tp->TplFree->TPLIndex;
+ buf = tp->LocalTxBuffers[i];
+ memcpy(buf, skb->data, length);
+ newbuf = ((char *)buf - (char *)tp) + tp->dmabuffer;
+ }
+ else {
+ /* Send direct from skb->data */
+ newbuf = dmabuf;
+ buf = skb->data;
+ }
+ /* Source address in packet? */
+ tms380tr_chk_src_addr(buf, dev->dev_addr);
+ tp->LastSendTime = jiffies;
+ tpl = tp->TplFree; /* Get the "free" TPL */
+ tpl->BusyFlag = 1; /* Mark TPL as busy */
+ tp->TplFree = tpl->NextTPLPtr;
+
+ /* Save the skb for delayed return of skb to system */
+ tpl->Skb = skb;
+ tpl->DMABuff = dmabuf;
+ tpl->FragList[0].DataCount = cpu_to_be16((unsigned short)length);
+ tpl->FragList[0].DataAddr = htonl(newbuf);
+
+ /* Write the data length in the transmit list. */
+ tpl->FrameSize = cpu_to_be16((unsigned short)length);
+ tpl->MData = buf;
+
+ /* Transmit the frame and set the status values. */
+ tms380tr_write_tpl_status(tpl, TX_VALID | TX_START_FRAME
+ | TX_END_FRAME | TX_PASS_SRC_ADDR
+ | TX_FRAME_IRQ);
+
+ /* Let adapter send the frame. */
+ tms380tr_exec_sifcmd(dev, CMD_TX_VALID);
+ spin_unlock_irqrestore(&tp->lock, flags);
+
+ return 0;
+}
+
+/*
+ * Write the given value to the 'Status' field of the specified TPL.
+ * NOTE: This function should be used whenever the status of any TPL must be
+ * modified by the driver, because the compiler may otherwise change the
+ * order of instructions such that writing the TPL status may be executed at
+ * an undesireable time. When this function is used, the status is always
+ * written when the function is called.
+ */
+static void tms380tr_write_tpl_status(TPL *tpl, unsigned int Status)
+{
+ tpl->Status = Status;
+}
+
+static void tms380tr_chk_src_addr(unsigned char *frame, unsigned char *hw_addr)
+{
+ unsigned char SRBit;
+
+ if((((unsigned long)frame[8]) & ~0x80) != 0) /* Compare 4 bytes */
+ return;
+ if((unsigned short)frame[12] != 0) /* Compare 2 bytes */
+ return;
+
+ SRBit = frame[8] & 0x80;
+ memcpy(&frame[8], hw_addr, 6);
+ frame[8] |= SRBit;
+
+ return;
+}
+
+/*
+ * The timer routine: Check if adapter still open and working, reopen if not.
+ */
+static void tms380tr_timer_chk(unsigned long data)
+{
+ struct net_device *dev = (struct net_device*)data;
+ struct net_local *tp = netdev_priv(dev);
+
+ if(tp->HaltInProgress)
+ return;
+
+ tms380tr_chk_outstanding_cmds(dev);
+ if(time_before(tp->LastSendTime + SEND_TIMEOUT, jiffies)
+ && (tp->TplFree != tp->TplBusy))
+ {
+ /* Anything to send, but stalled too long */
+ tp->LastSendTime = jiffies;
+ tms380tr_exec_cmd(dev, OC_CLOSE); /* Does reopen automatically */
+ }
+
+ tp->timer.expires = jiffies + 2*HZ;
+ add_timer(&tp->timer);
+
+ if(tp->AdapterOpenFlag || tp->ReOpenInProgress)
+ return;
+ tp->ReOpenInProgress = 1;
+ tms380tr_open_adapter(dev);
+
+ return;
+}
+
+/*
+ * The typical workload of the driver: Handle the network interface interrupts.
+ */
+irqreturn_t tms380tr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct net_local *tp;
+ unsigned short irq_type;
+ int handled = 0;
+
+ if(dev == NULL) {
+ printk(KERN_INFO "%s: irq %d for unknown device.\n", dev->name, irq);
+ return IRQ_NONE;
+ }
+
+ tp = netdev_priv(dev);
+
+ irq_type = SIFREADW(SIFSTS);
+
+ while(irq_type & STS_SYSTEM_IRQ) {
+ handled = 1;
+ irq_type &= STS_IRQ_MASK;
+
+ if(!tms380tr_chk_ssb(tp, irq_type)) {
+ printk(KERN_DEBUG "%s: DATA LATE occurred\n", dev->name);
+ break;
+ }
+
+ switch(irq_type) {
+ case STS_IRQ_RECEIVE_STATUS:
+ tms380tr_reset_interrupt(dev);
+ tms380tr_rcv_status_irq(dev);
+ break;
+
+ case STS_IRQ_TRANSMIT_STATUS:
+ /* Check if TRANSMIT.HALT command is complete */
+ if(tp->ssb.Parm[0] & COMMAND_COMPLETE) {
+ tp->TransmitCommandActive = 0;
+ tp->TransmitHaltScheduled = 0;
+
+ /* Issue a new transmit command. */
+ tms380tr_exec_cmd(dev, OC_TRANSMIT);
+ }
+
+ tms380tr_reset_interrupt(dev);
+ tms380tr_tx_status_irq(dev);
+ break;
+
+ case STS_IRQ_COMMAND_STATUS:
+ /* The SSB contains status of last command
+ * other than receive/transmit.
+ */
+ tms380tr_cmd_status_irq(dev);
+ break;
+
+ case STS_IRQ_SCB_CLEAR:
+ /* The SCB is free for another command. */
+ tp->ScbInUse = 0;
+ tms380tr_chk_outstanding_cmds(dev);
+ break;
+
+ case STS_IRQ_RING_STATUS:
+ tms380tr_ring_status_irq(dev);
+ break;
+
+ case STS_IRQ_ADAPTER_CHECK:
+ tms380tr_chk_irq(dev);
+ break;
+
+ case STS_IRQ_LLC_STATUS:
+ printk(KERN_DEBUG "tms380tr: unexpected LLC status IRQ\n");
+ break;
+
+ case STS_IRQ_TIMER:
+ printk(KERN_DEBUG "tms380tr: unexpected Timer IRQ\n");
+ break;
+
+ case STS_IRQ_RECEIVE_PENDING:
+ printk(KERN_DEBUG "tms380tr: unexpected Receive Pending IRQ\n");
+ break;
+
+ default:
+ printk(KERN_DEBUG "Unknown Token Ring IRQ (0x%04x)\n", irq_type);
+ break;
+ }
+
+ /* Reset system interrupt if not already done. */
+ if(irq_type != STS_IRQ_TRANSMIT_STATUS
+ && irq_type != STS_IRQ_RECEIVE_STATUS) {
+ tms380tr_reset_interrupt(dev);
+ }
+
+ irq_type = SIFREADW(SIFSTS);
+ }
+
+ return IRQ_RETVAL(handled);
+}
+
+/*
+ * Reset the INTERRUPT SYSTEM bit and issue SSB CLEAR command.
+ */
+static void tms380tr_reset_interrupt(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ SSB *ssb = &tp->ssb;
+
+ /*
+ * [Workaround for "Data Late"]
+ * Set all fields of the SSB to well-defined values so we can
+ * check if the adapter has written the SSB.
+ */
+
+ ssb->STS = (unsigned short) -1;
+ ssb->Parm[0] = (unsigned short) -1;
+ ssb->Parm[1] = (unsigned short) -1;
+ ssb->Parm[2] = (unsigned short) -1;
+
+ /* Free SSB by issuing SSB_CLEAR command after reading IRQ code
+ * and clear STS_SYSTEM_IRQ bit: enable adapter for further interrupts.
+ */
+ tms380tr_exec_sifcmd(dev, CMD_SSB_CLEAR | CMD_CLEAR_SYSTEM_IRQ);
+
+ return;
+}
+
+/*
+ * Check if the SSB has actually been written by the adapter.
+ */
+static unsigned char tms380tr_chk_ssb(struct net_local *tp, unsigned short IrqType)
+{
+ SSB *ssb = &tp->ssb; /* The address of the SSB. */
+
+ /* C 0 1 2 INTERRUPT CODE
+ * - - - - --------------
+ * 1 1 1 1 TRANSMIT STATUS
+ * 1 1 1 1 RECEIVE STATUS
+ * 1 ? ? 0 COMMAND STATUS
+ * 0 0 0 0 SCB CLEAR
+ * 1 1 0 0 RING STATUS
+ * 0 0 0 0 ADAPTER CHECK
+ *
+ * 0 = SSB field not affected by interrupt
+ * 1 = SSB field is affected by interrupt
+ *
+ * C = SSB ADDRESS +0: COMMAND
+ * 0 = SSB ADDRESS +2: STATUS 0
+ * 1 = SSB ADDRESS +4: STATUS 1
+ * 2 = SSB ADDRESS +6: STATUS 2
+ */
+
+ /* Check if this interrupt does use the SSB. */
+
+ if(IrqType != STS_IRQ_TRANSMIT_STATUS
+ && IrqType != STS_IRQ_RECEIVE_STATUS
+ && IrqType != STS_IRQ_COMMAND_STATUS
+ && IrqType != STS_IRQ_RING_STATUS)
+ {
+ return (1); /* SSB not involved. */
+ }
+
+ /* Note: All fields of the SSB have been set to all ones (-1) after it
+ * has last been used by the software (see DriverIsr()).
+ *
+ * Check if the affected SSB fields are still unchanged.
+ */
+
+ if(ssb->STS == (unsigned short) -1)
+ return (0); /* Command field not yet available. */
+ if(IrqType == STS_IRQ_COMMAND_STATUS)
+ return (1); /* Status fields not always affected. */
+ if(ssb->Parm[0] == (unsigned short) -1)
+ return (0); /* Status 1 field not yet available. */
+ if(IrqType == STS_IRQ_RING_STATUS)
+ return (1); /* Status 2 & 3 fields not affected. */
+
+ /* Note: At this point, the interrupt is either TRANSMIT or RECEIVE. */
+ if(ssb->Parm[1] == (unsigned short) -1)
+ return (0); /* Status 2 field not yet available. */
+ if(ssb->Parm[2] == (unsigned short) -1)
+ return (0); /* Status 3 field not yet available. */
+
+ return (1); /* All SSB fields have been written by the adapter. */
+}
+
+/*
+ * Evaluates the command results status in the SSB status field.
+ */
+static void tms380tr_cmd_status_irq(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned short ssb_cmd, ssb_parm_0;
+ unsigned short ssb_parm_1;
+ char *open_err = "Open error -";
+ char *code_err = "Open code -";
+
+ /* Copy the ssb values to local variables */
+ ssb_cmd = tp->ssb.STS;
+ ssb_parm_0 = tp->ssb.Parm[0];
+ ssb_parm_1 = tp->ssb.Parm[1];
+
+ if(ssb_cmd == OPEN)
+ {
+ tp->Sleeping = 0;
+ if(!tp->ReOpenInProgress)
+ wake_up_interruptible(&tp->wait_for_tok_int);
+
+ tp->OpenCommandIssued = 0;
+ tp->ScbInUse = 0;
+
+ if((ssb_parm_0 & 0x00FF) == GOOD_COMPLETION)
+ {
+ /* Success, the adapter is open. */
+ tp->LobeWireFaultLogged = 0;
+ tp->AdapterOpenFlag = 1;
+ tp->AdapterVirtOpenFlag = 1;
+ tp->TransmitCommandActive = 0;
+ tms380tr_exec_cmd(dev, OC_TRANSMIT);
+ tms380tr_exec_cmd(dev, OC_RECEIVE);
+
+ if(tp->ReOpenInProgress)
+ tp->ReOpenInProgress = 0;
+
+ return;
+ }
+ else /* The adapter did not open. */
+ {
+ if(ssb_parm_0 & NODE_ADDR_ERROR)
+ printk(KERN_INFO "%s: Node address error\n",
+ dev->name);
+ if(ssb_parm_0 & LIST_SIZE_ERROR)
+ printk(KERN_INFO "%s: List size error\n",
+ dev->name);
+ if(ssb_parm_0 & BUF_SIZE_ERROR)
+ printk(KERN_INFO "%s: Buffer size error\n",
+ dev->name);
+ if(ssb_parm_0 & TX_BUF_COUNT_ERROR)
+ printk(KERN_INFO "%s: Tx buffer count error\n",
+ dev->name);
+ if(ssb_parm_0 & INVALID_OPEN_OPTION)
+ printk(KERN_INFO "%s: Invalid open option\n",
+ dev->name);
+ if(ssb_parm_0 & OPEN_ERROR)
+ {
+ /* Show the open phase. */
+ switch(ssb_parm_0 & OPEN_PHASES_MASK)
+ {
+ case LOBE_MEDIA_TEST:
+ if(!tp->LobeWireFaultLogged)
+ {
+ tp->LobeWireFaultLogged = 1;
+ printk(KERN_INFO "%s: %s Lobe wire fault (check cable !).\n", dev->name, open_err);
+ }
+ tp->ReOpenInProgress = 1;
+ tp->AdapterOpenFlag = 0;
+ tp->AdapterVirtOpenFlag = 1;
+ tms380tr_open_adapter(dev);
+ return;
+
+ case PHYSICAL_INSERTION:
+ printk(KERN_INFO "%s: %s Physical insertion.\n", dev->name, open_err);
+ break;
+
+ case ADDRESS_VERIFICATION:
+ printk(KERN_INFO "%s: %s Address verification.\n", dev->name, open_err);
+ break;
+
+ case PARTICIPATION_IN_RING_POLL:
+ printk(KERN_INFO "%s: %s Participation in ring poll.\n", dev->name, open_err);
+ break;
+
+ case REQUEST_INITIALISATION:
+ printk(KERN_INFO "%s: %s Request initialisation.\n", dev->name, open_err);
+ break;
+
+ case FULLDUPLEX_CHECK:
+ printk(KERN_INFO "%s: %s Full duplex check.\n", dev->name, open_err);
+ break;
+
+ default:
+ printk(KERN_INFO "%s: %s Unknown open phase\n", dev->name, open_err);
+ break;
+ }
+
+ /* Show the open errors. */
+ switch(ssb_parm_0 & OPEN_ERROR_CODES_MASK)
+ {
+ case OPEN_FUNCTION_FAILURE:
+ printk(KERN_INFO "%s: %s OPEN_FUNCTION_FAILURE", dev->name, code_err);
+ tp->LastOpenStatus =
+ OPEN_FUNCTION_FAILURE;
+ break;
+
+ case OPEN_SIGNAL_LOSS:
+ printk(KERN_INFO "%s: %s OPEN_SIGNAL_LOSS\n", dev->name, code_err);
+ tp->LastOpenStatus =
+ OPEN_SIGNAL_LOSS;
+ break;
+
+ case OPEN_TIMEOUT:
+ printk(KERN_INFO "%s: %s OPEN_TIMEOUT\n", dev->name, code_err);
+ tp->LastOpenStatus =
+ OPEN_TIMEOUT;
+ break;
+
+ case OPEN_RING_FAILURE:
+ printk(KERN_INFO "%s: %s OPEN_RING_FAILURE\n", dev->name, code_err);
+ tp->LastOpenStatus =
+ OPEN_RING_FAILURE;
+ break;
+
+ case OPEN_RING_BEACONING:
+ printk(KERN_INFO "%s: %s OPEN_RING_BEACONING\n", dev->name, code_err);
+ tp->LastOpenStatus =
+ OPEN_RING_BEACONING;
+ break;
+
+ case OPEN_DUPLICATE_NODEADDR:
+ printk(KERN_INFO "%s: %s OPEN_DUPLICATE_NODEADDR\n", dev->name, code_err);
+ tp->LastOpenStatus =
+ OPEN_DUPLICATE_NODEADDR;
+ break;
+
+ case OPEN_REQUEST_INIT:
+ printk(KERN_INFO "%s: %s OPEN_REQUEST_INIT\n", dev->name, code_err);
+ tp->LastOpenStatus =
+ OPEN_REQUEST_INIT;
+ break;
+
+ case OPEN_REMOVE_RECEIVED:
+ printk(KERN_INFO "%s: %s OPEN_REMOVE_RECEIVED", dev->name, code_err);
+ tp->LastOpenStatus =
+ OPEN_REMOVE_RECEIVED;
+ break;
+
+ case OPEN_FULLDUPLEX_SET:
+ printk(KERN_INFO "%s: %s OPEN_FULLDUPLEX_SET\n", dev->name, code_err);
+ tp->LastOpenStatus =
+ OPEN_FULLDUPLEX_SET;
+ break;
+
+ default:
+ printk(KERN_INFO "%s: %s Unknown open err code", dev->name, code_err);
+ tp->LastOpenStatus =
+ OPEN_FUNCTION_FAILURE;
+ break;
+ }
+ }
+
+ tp->AdapterOpenFlag = 0;
+ tp->AdapterVirtOpenFlag = 0;
+
+ return;
+ }
+ }
+ else
+ {
+ if(ssb_cmd != READ_ERROR_LOG)
+ return;
+
+ /* Add values from the error log table to the MAC
+ * statistics counters and update the errorlogtable
+ * memory.
+ */
+ tp->MacStat.line_errors += tp->errorlogtable.Line_Error;
+ tp->MacStat.burst_errors += tp->errorlogtable.Burst_Error;
+ tp->MacStat.A_C_errors += tp->errorlogtable.ARI_FCI_Error;
+ tp->MacStat.lost_frames += tp->errorlogtable.Lost_Frame_Error;
+ tp->MacStat.recv_congest_count += tp->errorlogtable.Rx_Congest_Error;
+ tp->MacStat.rx_errors += tp->errorlogtable.Rx_Congest_Error;
+ tp->MacStat.frame_copied_errors += tp->errorlogtable.Frame_Copied_Error;
+ tp->MacStat.token_errors += tp->errorlogtable.Token_Error;
+ tp->MacStat.dummy1 += tp->errorlogtable.DMA_Bus_Error;
+ tp->MacStat.dummy1 += tp->errorlogtable.DMA_Parity_Error;
+ tp->MacStat.abort_delimiters += tp->errorlogtable.AbortDelimeters;
+ tp->MacStat.frequency_errors += tp->errorlogtable.Frequency_Error;
+ tp->MacStat.internal_errors += tp->errorlogtable.Internal_Error;
+ }
+
+ return;
+}
+
+/*
+ * The inverse routine to tms380tr_open().
+ */
+int tms380tr_close(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ netif_stop_queue(dev);
+
+ del_timer(&tp->timer);
+
+ /* Flush the Tx and disable Rx here. */
+
+ tp->HaltInProgress = 1;
+ tms380tr_exec_cmd(dev, OC_CLOSE);
+ tp->timer.expires = jiffies + 1*HZ;
+ tp->timer.function = tms380tr_timer_end_wait;
+ tp->timer.data = (unsigned long)dev;
+ add_timer(&tp->timer);
+
+ tms380tr_enable_interrupts(dev);
+
+ tp->Sleeping = 1;
+ interruptible_sleep_on(&tp->wait_for_tok_int);
+ tp->TransmitCommandActive = 0;
+
+ del_timer(&tp->timer);
+ tms380tr_disable_interrupts(dev);
+
+#ifdef CONFIG_ISA
+ if(dev->dma > 0)
+ {
+ unsigned long flags=claim_dma_lock();
+ disable_dma(dev->dma);
+ release_dma_lock(flags);
+ }
+#endif
+
+ SIFWRITEW(0xFF00, SIFCMD);
+#if 0
+ if(dev->dma > 0) /* what the? */
+ SIFWRITEB(0xff, POSREG);
+#endif
+ tms380tr_cancel_tx_queue(tp);
+
+ return (0);
+}
+
+/*
+ * Get the current statistics. This may be called with the card open
+ * or closed.
+ */
+static struct net_device_stats *tms380tr_get_stats(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ return ((struct net_device_stats *)&tp->MacStat);
+}
+
+/*
+ * Set or clear the multicast filter for this adapter.
+ */
+static void tms380tr_set_multicast_list(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned int OpenOptions;
+
+ OpenOptions = tp->ocpl.OPENOptions &
+ ~(PASS_ADAPTER_MAC_FRAMES
+ | PASS_ATTENTION_FRAMES
+ | PASS_BEACON_MAC_FRAMES
+ | COPY_ALL_MAC_FRAMES
+ | COPY_ALL_NON_MAC_FRAMES);
+
+ tp->ocpl.FunctAddr = 0;
+
+ if(dev->flags & IFF_PROMISC)
+ /* Enable promiscuous mode */
+ OpenOptions |= COPY_ALL_NON_MAC_FRAMES |
+ COPY_ALL_MAC_FRAMES;
+ else
+ {
+ if(dev->flags & IFF_ALLMULTI)
+ {
+ /* Disable promiscuous mode, use normal mode. */
+ tp->ocpl.FunctAddr = 0xFFFFFFFF;
+ }
+ else
+ {
+ int i;
+ struct dev_mc_list *mclist = dev->mc_list;
+ for (i=0; i< dev->mc_count; i++)
+ {
+ ((char *)(&tp->ocpl.FunctAddr))[0] |=
+ mclist->dmi_addr[2];
+ ((char *)(&tp->ocpl.FunctAddr))[1] |=
+ mclist->dmi_addr[3];
+ ((char *)(&tp->ocpl.FunctAddr))[2] |=
+ mclist->dmi_addr[4];
+ ((char *)(&tp->ocpl.FunctAddr))[3] |=
+ mclist->dmi_addr[5];
+ mclist = mclist->next;
+ }
+ }
+ tms380tr_exec_cmd(dev, OC_SET_FUNCT_ADDR);
+ }
+
+ tp->ocpl.OPENOptions = OpenOptions;
+ tms380tr_exec_cmd(dev, OC_MODIFY_OPEN_PARMS);
+ return;
+}
+
+/*
+ * Wait for some time (microseconds)
+ */
+void tms380tr_wait(unsigned long time)
+{
+#if 0
+ long tmp;
+
+ tmp = jiffies + time/(1000000/HZ);
+ do {
+ current->state = TASK_INTERRUPTIBLE;
+ tmp = schedule_timeout(tmp);
+ } while(time_after(tmp, jiffies));
+#else
+ udelay(time);
+#endif
+ return;
+}
+
+/*
+ * Write a command value to the SIFCMD register
+ */
+static void tms380tr_exec_sifcmd(struct net_device *dev, unsigned int WriteValue)
+{
+ unsigned short cmd;
+ unsigned short SifStsValue;
+ unsigned long loop_counter;
+
+ WriteValue = ((WriteValue ^ CMD_SYSTEM_IRQ) | CMD_INTERRUPT_ADAPTER);
+ cmd = (unsigned short)WriteValue;
+ loop_counter = 0,5 * 800000;
+ do {
+ SifStsValue = SIFREADW(SIFSTS);
+ } while((SifStsValue & CMD_INTERRUPT_ADAPTER) && loop_counter--);
+ SIFWRITEW(cmd, SIFCMD);
+
+ return;
+}
+
+/*
+ * Processes adapter hardware reset, halts adapter and downloads firmware,
+ * clears the halt bit.
+ */
+static int tms380tr_reset_adapter(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned short *fw_ptr;
+ unsigned short count, c, count2;
+ const struct firmware *fw_entry = NULL;
+
+ strncpy(tms_device.bus_id,dev->name, BUS_ID_SIZE);
+
+ if (request_firmware(&fw_entry, "tms380tr.bin", &tms_device) != 0) {
+ printk(KERN_ALERT "%s: firmware %s is missing, cannot start.\n",
+ dev->name, "tms380tr.bin");
+ return (-1);
+ }
+
+ fw_ptr = (unsigned short *)fw_entry->data;
+ count2 = fw_entry->size / 2;
+
+ /* Hardware adapter reset */
+ SIFWRITEW(ACL_ARESET, SIFACL);
+ tms380tr_wait(40);
+
+ c = SIFREADW(SIFACL);
+ tms380tr_wait(20);
+
+ if(dev->dma == 0) /* For PCI adapters */
+ {
+ c &= ~(ACL_NSELOUT0 | ACL_NSELOUT1); /* Clear bits */
+ if(tp->setnselout)
+ c |= (*tp->setnselout)(dev);
+ }
+
+ /* In case a command is pending - forget it */
+ tp->ScbInUse = 0;
+
+ c &= ~ACL_ARESET; /* Clear adapter reset bit */
+ c |= ACL_CPHALT; /* Halt adapter CPU, allow download */
+ c |= ACL_BOOT;
+ c |= ACL_SINTEN;
+ c &= ~ACL_PSDMAEN; /* Clear pseudo dma bit */
+ SIFWRITEW(c, SIFACL);
+ tms380tr_wait(40);
+
+ count = 0;
+ /* Download firmware via DIO interface: */
+ do {
+ if (count2 < 3) continue;
+
+ /* Download first address part */
+ SIFWRITEW(*fw_ptr, SIFADX);
+ fw_ptr++;
+ count2--;
+ /* Download second address part */
+ SIFWRITEW(*fw_ptr, SIFADD);
+ fw_ptr++;
+ count2--;
+
+ if((count = *fw_ptr) != 0) /* Load loop counter */
+ {
+ fw_ptr++; /* Download block data */
+ count2--;
+ if (count > count2) continue;
+
+ for(; count > 0; count--)
+ {
+ SIFWRITEW(*fw_ptr, SIFINC);
+ fw_ptr++;
+ count2--;
+ }
+ }
+ else /* Stop, if last block downloaded */
+ {
+ c = SIFREADW(SIFACL);
+ c &= (~ACL_CPHALT | ACL_SINTEN);
+
+ /* Clear CPHALT and start BUD */
+ SIFWRITEW(c, SIFACL);
+ if (fw_entry)
+ release_firmware(fw_entry);
+ return (1);
+ }
+ } while(count == 0);
+
+ if (fw_entry)
+ release_firmware(fw_entry);
+ printk(KERN_INFO "%s: Adapter Download Failed\n", dev->name);
+ return (-1);
+}
+
+/*
+ * Starts bring up diagnostics of token ring adapter and evaluates
+ * diagnostic results.
+ */
+static int tms380tr_bringup_diags(struct net_device *dev)
+{
+ int loop_cnt, retry_cnt;
+ unsigned short Status;
+
+ tms380tr_wait(HALF_SECOND);
+ tms380tr_exec_sifcmd(dev, EXEC_SOFT_RESET);
+ tms380tr_wait(HALF_SECOND);
+
+ retry_cnt = BUD_MAX_RETRIES; /* maximal number of retrys */
+
+ do {
+ retry_cnt--;
+ if(tms380tr_debug > 3)
+ printk(KERN_DEBUG "BUD-Status: ");
+ loop_cnt = BUD_MAX_LOOPCNT; /* maximum: three seconds*/
+ do { /* Inspect BUD results */
+ loop_cnt--;
+ tms380tr_wait(HALF_SECOND);
+ Status = SIFREADW(SIFSTS);
+ Status &= STS_MASK;
+
+ if(tms380tr_debug > 3)
+ printk(KERN_DEBUG " %04X \n", Status);
+ /* BUD successfully completed */
+ if(Status == STS_INITIALIZE)
+ return (1);
+ /* Unrecoverable hardware error, BUD not completed? */
+ } while((loop_cnt > 0) && ((Status & (STS_ERROR | STS_TEST))
+ != (STS_ERROR | STS_TEST)));
+
+ /* Error preventing completion of BUD */
+ if(retry_cnt > 0)
+ {
+ printk(KERN_INFO "%s: Adapter Software Reset.\n",
+ dev->name);
+ tms380tr_exec_sifcmd(dev, EXEC_SOFT_RESET);
+ tms380tr_wait(HALF_SECOND);
+ }
+ } while(retry_cnt > 0);
+
+ Status = SIFREADW(SIFSTS);
+
+ printk(KERN_INFO "%s: Hardware error\n", dev->name);
+ /* Hardware error occurred! */
+ Status &= 0x001f;
+ if (Status & 0x0010)
+ printk(KERN_INFO "%s: BUD Error: Timeout\n", dev->name);
+ else if ((Status & 0x000f) > 6)
+ printk(KERN_INFO "%s: BUD Error: Illegal Failure\n", dev->name);
+ else
+ printk(KERN_INFO "%s: Bring Up Diagnostics Error (%04X) occurred\n", dev->name, Status & 0x000f);
+
+ return (-1);
+}
+
+/*
+ * Copy initialisation data to adapter memory, beginning at address
+ * 1:0A00; Starting DMA test and evaluating result bits.
+ */
+static int tms380tr_init_adapter(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ const unsigned char SCB_Test[6] = {0x00, 0x00, 0xC1, 0xE2, 0xD4, 0x8B};
+ const unsigned char SSB_Test[8] = {0xFF, 0xFF, 0xD1, 0xD7,
+ 0xC5, 0xD9, 0xC3, 0xD4};
+ void *ptr = (void *)&tp->ipb;
+ unsigned short *ipb_ptr = (unsigned short *)ptr;
+ unsigned char *cb_ptr = (unsigned char *) &tp->scb;
+ unsigned char *sb_ptr = (unsigned char *) &tp->ssb;
+ unsigned short Status;
+ int i, loop_cnt, retry_cnt;
+
+ /* Normalize: byte order low/high, word order high/low! (only IPB!) */
+ tp->ipb.SCB_Addr = SWAPW(((char *)&tp->scb - (char *)tp) + tp->dmabuffer);
+ tp->ipb.SSB_Addr = SWAPW(((char *)&tp->ssb - (char *)tp) + tp->dmabuffer);
+
+ if(tms380tr_debug > 3)
+ {
+ printk(KERN_DEBUG "%s: buffer (real): %lx\n", dev->name, (long) &tp->scb);
+ printk(KERN_DEBUG "%s: buffer (virt): %lx\n", dev->name, (long) ((char *)&tp->scb - (char *)tp) + (long) tp->dmabuffer);
+ printk(KERN_DEBUG "%s: buffer (DMA) : %lx\n", dev->name, (long) tp->dmabuffer);
+ printk(KERN_DEBUG "%s: buffer (tp) : %lx\n", dev->name, (long) tp);
+ }
+ /* Maximum: three initialization retries */
+ retry_cnt = INIT_MAX_RETRIES;
+
+ do {
+ retry_cnt--;
+
+ /* Transfer initialization block */
+ SIFWRITEW(0x0001, SIFADX);
+
+ /* To address 0001:0A00 of adapter RAM */
+ SIFWRITEW(0x0A00, SIFADD);
+
+ /* Write 11 words to adapter RAM */
+ for(i = 0; i < 11; i++)
+ SIFWRITEW(ipb_ptr[i], SIFINC);
+
+ /* Execute SCB adapter command */
+ tms380tr_exec_sifcmd(dev, CMD_EXECUTE);
+
+ loop_cnt = INIT_MAX_LOOPCNT; /* Maximum: 11 seconds */
+
+ /* While remaining retries, no error and not completed */
+ do {
+ Status = 0;
+ loop_cnt--;
+ tms380tr_wait(HALF_SECOND);
+
+ /* Mask interesting status bits */
+ Status = SIFREADW(SIFSTS);
+ Status &= STS_MASK;
+ } while(((Status &(STS_INITIALIZE | STS_ERROR | STS_TEST)) != 0)
+ && ((Status & STS_ERROR) == 0) && (loop_cnt != 0));
+
+ if((Status & (STS_INITIALIZE | STS_ERROR | STS_TEST)) == 0)
+ {
+ /* Initialization completed without error */
+ i = 0;
+ do { /* Test if contents of SCB is valid */
+ if(SCB_Test[i] != *(cb_ptr + i))
+ {
+ printk(KERN_INFO "%s: DMA failed\n", dev->name);
+ /* DMA data error: wrong data in SCB */
+ return (-1);
+ }
+ i++;
+ } while(i < 6);
+
+ i = 0;
+ do { /* Test if contents of SSB is valid */
+ if(SSB_Test[i] != *(sb_ptr + i))
+ /* DMA data error: wrong data in SSB */
+ return (-1);
+ i++;
+ } while (i < 8);
+
+ return (1); /* Adapter successfully initialized */
+ }
+ else
+ {
+ if((Status & STS_ERROR) != 0)
+ {
+ /* Initialization error occurred */
+ Status = SIFREADW(SIFSTS);
+ Status &= STS_ERROR_MASK;
+ /* ShowInitialisationErrorCode(Status); */
+ printk(KERN_INFO "%s: Status error: %d\n", dev->name, Status);
+ return (-1); /* Unrecoverable error */
+ }
+ else
+ {
+ if(retry_cnt > 0)
+ {
+ /* Reset adapter and try init again */
+ tms380tr_exec_sifcmd(dev, EXEC_SOFT_RESET);
+ tms380tr_wait(HALF_SECOND);
+ }
+ }
+ }
+ } while(retry_cnt > 0);
+
+ printk(KERN_INFO "%s: Retry exceeded\n", dev->name);
+ return (-1);
+}
+
+/*
+ * Check for outstanding commands in command queue and tries to execute
+ * command immediately. Corresponding command flag in command queue is cleared.
+ */
+static void tms380tr_chk_outstanding_cmds(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned long Addr = 0;
+
+ if(tp->CMDqueue == 0)
+ return; /* No command execution */
+
+ /* If SCB in use: no command */
+ if(tp->ScbInUse == 1)
+ return;
+
+ /* Check if adapter is opened, avoiding COMMAND_REJECT
+ * interrupt by the adapter!
+ */
+ if(tp->AdapterOpenFlag == 0)
+ {
+ if(tp->CMDqueue & OC_OPEN)
+ {
+ /* Execute OPEN command */
+ tp->CMDqueue ^= OC_OPEN;
+
+ Addr = htonl(((char *)&tp->ocpl - (char *)tp) + tp->dmabuffer);
+ tp->scb.Parm[0] = LOWORD(Addr);
+ tp->scb.Parm[1] = HIWORD(Addr);
+ tp->scb.CMD = OPEN;
+ }
+ else
+ /* No OPEN command queued, but adapter closed. Note:
+ * We'll try to re-open the adapter in DriverPoll()
+ */
+ return; /* No adapter command issued */
+ }
+ else
+ {
+ /* Adapter is open; evaluate command queue: try to execute
+ * outstanding commands (depending on priority!) CLOSE
+ * command queued
+ */
+ if(tp->CMDqueue & OC_CLOSE)
+ {
+ tp->CMDqueue ^= OC_CLOSE;
+ tp->AdapterOpenFlag = 0;
+ tp->scb.Parm[0] = 0; /* Parm[0], Parm[1] are ignored */
+ tp->scb.Parm[1] = 0; /* but should be set to zero! */
+ tp->scb.CMD = CLOSE;
+ if(!tp->HaltInProgress)
+ tp->CMDqueue |= OC_OPEN; /* re-open adapter */
+ else
+ tp->CMDqueue = 0; /* no more commands */
+ }
+ else
+ {
+ if(tp->CMDqueue & OC_RECEIVE)
+ {
+ tp->CMDqueue ^= OC_RECEIVE;
+ Addr = htonl(((char *)tp->RplHead - (char *)tp) + tp->dmabuffer);
+ tp->scb.Parm[0] = LOWORD(Addr);
+ tp->scb.Parm[1] = HIWORD(Addr);
+ tp->scb.CMD = RECEIVE;
+ }
+ else
+ {
+ if(tp->CMDqueue & OC_TRANSMIT_HALT)
+ {
+ /* NOTE: TRANSMIT.HALT must be checked
+ * before TRANSMIT.
+ */
+ tp->CMDqueue ^= OC_TRANSMIT_HALT;
+ tp->scb.CMD = TRANSMIT_HALT;
+
+ /* Parm[0] and Parm[1] are ignored
+ * but should be set to zero!
+ */
+ tp->scb.Parm[0] = 0;
+ tp->scb.Parm[1] = 0;
+ }
+ else
+ {
+ if(tp->CMDqueue & OC_TRANSMIT)
+ {
+ /* NOTE: TRANSMIT must be
+ * checked after TRANSMIT.HALT
+ */
+ if(tp->TransmitCommandActive)
+ {
+ if(!tp->TransmitHaltScheduled)
+ {
+ tp->TransmitHaltScheduled = 1;
+ tms380tr_exec_cmd(dev, OC_TRANSMIT_HALT) ;
+ }
+ tp->TransmitCommandActive = 0;
+ return;
+ }
+
+ tp->CMDqueue ^= OC_TRANSMIT;
+ tms380tr_cancel_tx_queue(tp);
+ Addr = htonl(((char *)tp->TplBusy - (char *)tp) + tp->dmabuffer);
+ tp->scb.Parm[0] = LOWORD(Addr);
+ tp->scb.Parm[1] = HIWORD(Addr);
+ tp->scb.CMD = TRANSMIT;
+ tp->TransmitCommandActive = 1;
+ }
+ else
+ {
+ if(tp->CMDqueue & OC_MODIFY_OPEN_PARMS)
+ {
+ tp->CMDqueue ^= OC_MODIFY_OPEN_PARMS;
+ tp->scb.Parm[0] = tp->ocpl.OPENOptions; /* new OPEN options*/
+ tp->scb.Parm[0] |= ENABLE_FULL_DUPLEX_SELECTION;
+ tp->scb.Parm[1] = 0; /* is ignored but should be zero */
+ tp->scb.CMD = MODIFY_OPEN_PARMS;
+ }
+ else
+ {
+ if(tp->CMDqueue & OC_SET_FUNCT_ADDR)
+ {
+ tp->CMDqueue ^= OC_SET_FUNCT_ADDR;
+ tp->scb.Parm[0] = LOWORD(tp->ocpl.FunctAddr);
+ tp->scb.Parm[1] = HIWORD(tp->ocpl.FunctAddr);
+ tp->scb.CMD = SET_FUNCT_ADDR;
+ }
+ else
+ {
+ if(tp->CMDqueue & OC_SET_GROUP_ADDR)
+ {
+ tp->CMDqueue ^= OC_SET_GROUP_ADDR;
+ tp->scb.Parm[0] = LOWORD(tp->ocpl.GroupAddr);
+ tp->scb.Parm[1] = HIWORD(tp->ocpl.GroupAddr);
+ tp->scb.CMD = SET_GROUP_ADDR;
+ }
+ else
+ {
+ if(tp->CMDqueue & OC_READ_ERROR_LOG)
+ {
+ tp->CMDqueue ^= OC_READ_ERROR_LOG;
+ Addr = htonl(((char *)&tp->errorlogtable - (char *)tp) + tp->dmabuffer);
+ tp->scb.Parm[0] = LOWORD(Addr);
+ tp->scb.Parm[1] = HIWORD(Addr);
+ tp->scb.CMD = READ_ERROR_LOG;
+ }
+ else
+ {
+ printk(KERN_WARNING "CheckForOutstandingCommand: unknown Command\n");
+ tp->CMDqueue = 0;
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ tp->ScbInUse = 1; /* Set semaphore: SCB in use. */
+
+ /* Execute SCB and generate IRQ when done. */
+ tms380tr_exec_sifcmd(dev, CMD_EXECUTE | CMD_SCB_REQUEST);
+
+ return;
+}
+
+/*
+ * IRQ conditions: signal loss on the ring, transmit or receive of beacon
+ * frames (disabled if bit 1 of OPEN option is set); report error MAC
+ * frame transmit (disabled if bit 2 of OPEN option is set); open or short
+ * circuit fault on the lobe is detected; remove MAC frame received;
+ * error counter overflow (255); opened adapter is the only station in ring.
+ * After some of the IRQs the adapter is closed!
+ */
+static void tms380tr_ring_status_irq(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+
+ tp->CurrentRingStatus = be16_to_cpu((unsigned short)tp->ssb.Parm[0]);
+
+ /* First: fill up statistics */
+ if(tp->ssb.Parm[0] & SIGNAL_LOSS)
+ {
+ printk(KERN_INFO "%s: Signal Loss\n", dev->name);
+ tp->MacStat.line_errors++;
+ }
+
+ /* Adapter is closed, but initialized */
+ if(tp->ssb.Parm[0] & LOBE_WIRE_FAULT)
+ {
+ printk(KERN_INFO "%s: Lobe Wire Fault, Reopen Adapter\n",
+ dev->name);
+ tp->MacStat.line_errors++;
+ }
+
+ if(tp->ssb.Parm[0] & RING_RECOVERY)
+ printk(KERN_INFO "%s: Ring Recovery\n", dev->name);
+
+ /* Counter overflow: read error log */
+ if(tp->ssb.Parm[0] & COUNTER_OVERFLOW)
+ {
+ printk(KERN_INFO "%s: Counter Overflow\n", dev->name);
+ tms380tr_exec_cmd(dev, OC_READ_ERROR_LOG);
+ }
+
+ /* Adapter is closed, but initialized */
+ if(tp->ssb.Parm[0] & REMOVE_RECEIVED)
+ printk(KERN_INFO "%s: Remove Received, Reopen Adapter\n",
+ dev->name);
+
+ /* Adapter is closed, but initialized */
+ if(tp->ssb.Parm[0] & AUTO_REMOVAL_ERROR)
+ printk(KERN_INFO "%s: Auto Removal Error, Reopen Adapter\n",
+ dev->name);
+
+ if(tp->ssb.Parm[0] & HARD_ERROR)
+ printk(KERN_INFO "%s: Hard Error\n", dev->name);
+
+ if(tp->ssb.Parm[0] & SOFT_ERROR)
+ printk(KERN_INFO "%s: Soft Error\n", dev->name);
+
+ if(tp->ssb.Parm[0] & TRANSMIT_BEACON)
+ printk(KERN_INFO "%s: Transmit Beacon\n", dev->name);
+
+ if(tp->ssb.Parm[0] & SINGLE_STATION)
+ printk(KERN_INFO "%s: Single Station\n", dev->name);
+
+ /* Check if adapter has been closed */
+ if(tp->ssb.Parm[0] & ADAPTER_CLOSED)
+ {
+ printk(KERN_INFO "%s: Adapter closed (Reopening),"
+ "CurrentRingStat %x\n",
+ dev->name, tp->CurrentRingStatus);
+ tp->AdapterOpenFlag = 0;
+ tms380tr_open_adapter(dev);
+ }
+
+ return;
+}
+
+/*
+ * Issued if adapter has encountered an unrecoverable hardware
+ * or software error.
+ */
+static void tms380tr_chk_irq(struct net_device *dev)
+{
+ int i;
+ unsigned short AdapterCheckBlock[4];
+ struct net_local *tp = netdev_priv(dev);
+
+ tp->AdapterOpenFlag = 0; /* Adapter closed now */
+
+ /* Page number of adapter memory */
+ SIFWRITEW(0x0001, SIFADX);
+ /* Address offset */
+ SIFWRITEW(CHECKADDR, SIFADR);
+
+ /* Reading 8 byte adapter check block. */
+ for(i = 0; i < 4; i++)
+ AdapterCheckBlock[i] = SIFREADW(SIFINC);
+
+ if(tms380tr_debug > 3)
+ {
+ printk(KERN_DEBUG "%s: AdapterCheckBlock: ", dev->name);
+ for (i = 0; i < 4; i++)
+ printk("%04X", AdapterCheckBlock[i]);
+ printk("\n");
+ }
+
+ switch(AdapterCheckBlock[0])
+ {
+ case DIO_PARITY:
+ printk(KERN_INFO "%s: DIO parity error\n", dev->name);
+ break;
+
+ case DMA_READ_ABORT:
+ printk(KERN_INFO "%s DMA read operation aborted:\n",
+ dev->name);
+ switch (AdapterCheckBlock[1])
+ {
+ case 0:
+ printk(KERN_INFO "Timeout\n");
+ printk(KERN_INFO "Address: %04X %04X\n",
+ AdapterCheckBlock[2],
+ AdapterCheckBlock[3]);
+ break;
+
+ case 1:
+ printk(KERN_INFO "Parity error\n");
+ printk(KERN_INFO "Address: %04X %04X\n",
+ AdapterCheckBlock[2],
+ AdapterCheckBlock[3]);
+ break;
+
+ case 2:
+ printk(KERN_INFO "Bus error\n");
+ printk(KERN_INFO "Address: %04X %04X\n",
+ AdapterCheckBlock[2],
+ AdapterCheckBlock[3]);
+ break;
+
+ default:
+ printk(KERN_INFO "Unknown error.\n");
+ break;
+ }
+ break;
+
+ case DMA_WRITE_ABORT:
+ printk(KERN_INFO "%s: DMA write operation aborted: \n",
+ dev->name);
+ switch (AdapterCheckBlock[1])
+ {
+ case 0:
+ printk(KERN_INFO "Timeout\n");
+ printk(KERN_INFO "Address: %04X %04X\n",
+ AdapterCheckBlock[2],
+ AdapterCheckBlock[3]);
+ break;
+
+ case 1:
+ printk(KERN_INFO "Parity error\n");
+ printk(KERN_INFO "Address: %04X %04X\n",
+ AdapterCheckBlock[2],
+ AdapterCheckBlock[3]);
+ break;
+
+ case 2:
+ printk(KERN_INFO "Bus error\n");
+ printk(KERN_INFO "Address: %04X %04X\n",
+ AdapterCheckBlock[2],
+ AdapterCheckBlock[3]);
+ break;
+
+ default:
+ printk(KERN_INFO "Unknown error.\n");
+ break;
+ }
+ break;
+
+ case ILLEGAL_OP_CODE:
+ printk(KERN_INFO "%s: Illegal operation code in firmware\n",
+ dev->name);
+ /* Parm[0-3]: adapter internal register R13-R15 */
+ break;
+
+ case PARITY_ERRORS:
+ printk(KERN_INFO "%s: Adapter internal bus parity error\n",
+ dev->name);
+ /* Parm[0-3]: adapter internal register R13-R15 */
+ break;
+
+ case RAM_DATA_ERROR:
+ printk(KERN_INFO "%s: RAM data error\n", dev->name);
+ /* Parm[0-1]: MSW/LSW address of RAM location. */
+ break;
+
+ case RAM_PARITY_ERROR:
+ printk(KERN_INFO "%s: RAM parity error\n", dev->name);
+ /* Parm[0-1]: MSW/LSW address of RAM location. */
+ break;
+
+ case RING_UNDERRUN:
+ printk(KERN_INFO "%s: Internal DMA underrun detected\n",
+ dev->name);
+ break;
+
+ case INVALID_IRQ:
+ printk(KERN_INFO "%s: Unrecognized interrupt detected\n",
+ dev->name);
+ /* Parm[0-3]: adapter internal register R13-R15 */
+ break;
+
+ case INVALID_ERROR_IRQ:
+ printk(KERN_INFO "%s: Unrecognized error interrupt detected\n",
+ dev->name);
+ /* Parm[0-3]: adapter internal register R13-R15 */
+ break;
+
+ case INVALID_XOP:
+ printk(KERN_INFO "%s: Unrecognized XOP request detected\n",
+ dev->name);
+ /* Parm[0-3]: adapter internal register R13-R15 */
+ break;
+
+ default:
+ printk(KERN_INFO "%s: Unknown status", dev->name);
+ break;
+ }
+
+ if(tms380tr_chipset_init(dev) == 1)
+ {
+ /* Restart of firmware successful */
+ tp->AdapterOpenFlag = 1;
+ }
+
+ return;
+}
+
+/*
+ * Internal adapter pointer to RAM data are copied from adapter into
+ * host system.
+ */
+static int tms380tr_read_ptr(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned short adapterram;
+
+ tms380tr_read_ram(dev, (unsigned char *)&tp->intptrs.BurnedInAddrPtr,
+ ADAPTER_INT_PTRS, 16);
+ tms380tr_read_ram(dev, (unsigned char *)&adapterram,
+ cpu_to_be16((unsigned short)tp->intptrs.AdapterRAMPtr), 2);
+ return be16_to_cpu(adapterram);
+}
+
+/*
+ * Reads a number of bytes from adapter to system memory.
+ */
+static void tms380tr_read_ram(struct net_device *dev, unsigned char *Data,
+ unsigned short Address, int Length)
+{
+ int i;
+ unsigned short old_sifadx, old_sifadr, InWord;
+
+ /* Save the current values */
+ old_sifadx = SIFREADW(SIFADX);
+ old_sifadr = SIFREADW(SIFADR);
+
+ /* Page number of adapter memory */
+ SIFWRITEW(0x0001, SIFADX);
+ /* Address offset in adapter RAM */
+ SIFWRITEW(Address, SIFADR);
+
+ /* Copy len byte from adapter memory to system data area. */
+ i = 0;
+ for(;;)
+ {
+ InWord = SIFREADW(SIFINC);
+
+ *(Data + i) = HIBYTE(InWord); /* Write first byte */
+ if(++i == Length) /* All is done break */
+ break;
+
+ *(Data + i) = LOBYTE(InWord); /* Write second byte */
+ if (++i == Length) /* All is done break */
+ break;
+ }
+
+ /* Restore original values */
+ SIFWRITEW(old_sifadx, SIFADX);
+ SIFWRITEW(old_sifadr, SIFADR);
+
+ return;
+}
+
+/*
+ * Cancel all queued packets in the transmission queue.
+ */
+static void tms380tr_cancel_tx_queue(struct net_local* tp)
+{
+ TPL *tpl;
+
+ /*
+ * NOTE: There must not be an active TRANSMIT command pending, when
+ * this function is called.
+ */
+ if(tp->TransmitCommandActive)
+ return;
+
+ for(;;)
+ {
+ tpl = tp->TplBusy;
+ if(!tpl->BusyFlag)
+ break;
+ /* "Remove" TPL from busy list. */
+ tp->TplBusy = tpl->NextTPLPtr;
+ tms380tr_write_tpl_status(tpl, 0); /* Clear VALID bit */
+ tpl->BusyFlag = 0; /* "free" TPL */
+
+ printk(KERN_INFO "Cancel tx (%08lXh).\n", (unsigned long)tpl);
+ if (tpl->DMABuff)
+ pci_unmap_single(tp->pdev, tpl->DMABuff, tpl->Skb->len, PCI_DMA_TODEVICE);
+ dev_kfree_skb_any(tpl->Skb);
+ }
+
+ return;
+}
+
+/*
+ * This function is called whenever a transmit interrupt is generated by the
+ * adapter. For a command complete interrupt, it is checked if we have to
+ * issue a new transmit command or not.
+ */
+static void tms380tr_tx_status_irq(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned char HighByte, HighAc, LowAc;
+ TPL *tpl;
+
+ /* NOTE: At this point the SSB from TRANSMIT STATUS is no longer
+ * available, because the CLEAR SSB command has already been issued.
+ *
+ * Process all complete transmissions.
+ */
+
+ for(;;)
+ {
+ tpl = tp->TplBusy;
+ if(!tpl->BusyFlag || (tpl->Status
+ & (TX_VALID | TX_FRAME_COMPLETE))
+ != TX_FRAME_COMPLETE)
+ {
+ break;
+ }
+
+ /* "Remove" TPL from busy list. */
+ tp->TplBusy = tpl->NextTPLPtr ;
+
+ /* Check the transmit status field only for directed frames*/
+ if(DIRECTED_FRAME(tpl) && (tpl->Status & TX_ERROR) == 0)
+ {
+ HighByte = GET_TRANSMIT_STATUS_HIGH_BYTE(tpl->Status);
+ HighAc = GET_FRAME_STATUS_HIGH_AC(HighByte);
+ LowAc = GET_FRAME_STATUS_LOW_AC(HighByte);
+
+ if((HighAc != LowAc) || (HighAc == AC_NOT_RECOGNIZED))
+ {
+ printk(KERN_DEBUG "%s: (DA=%08lX not recognized)\n",
+ dev->name,
+ *(unsigned long *)&tpl->MData[2+2]);
+ }
+ else
+ {
+ if(tms380tr_debug > 3)
+ printk(KERN_DEBUG "%s: Directed frame tx'd\n",
+ dev->name);
+ }
+ }
+ else
+ {
+ if(!DIRECTED_FRAME(tpl))
+ {
+ if(tms380tr_debug > 3)
+ printk(KERN_DEBUG "%s: Broadcast frame tx'd\n",
+ dev->name);
+ }
+ }
+
+ tp->MacStat.tx_packets++;
+ if (tpl->DMABuff)
+ pci_unmap_single(tp->pdev, tpl->DMABuff, tpl->Skb->len, PCI_DMA_TODEVICE);
+ dev_kfree_skb_irq(tpl->Skb);
+ tpl->BusyFlag = 0; /* "free" TPL */
+ }
+
+ if(!tp->TplFree->NextTPLPtr->BusyFlag)
+ netif_wake_queue(dev);
+ return;
+}
+
+/*
+ * Called if a frame receive interrupt is generated by the adapter.
+ * Check if the frame is valid and indicate it to system.
+ */
+static void tms380tr_rcv_status_irq(struct net_device *dev)
+{
+ struct net_local *tp = netdev_priv(dev);
+ unsigned char *ReceiveDataPtr;
+ struct sk_buff *skb;
+ unsigned int Length, Length2;
+ RPL *rpl;
+ RPL *SaveHead;
+ dma_addr_t dmabuf;
+
+ /* NOTE: At this point the SSB from RECEIVE STATUS is no longer
+ * available, because the CLEAR SSB command has already been issued.
+ *
+ * Process all complete receives.
+ */
+
+ for(;;)
+ {
+ rpl = tp->RplHead;
+ if(rpl->Status & RX_VALID)
+ break; /* RPL still in use by adapter */
+
+ /* Forward RPLHead pointer to next list. */
+ SaveHead = tp->RplHead;
+ tp->RplHead = rpl->NextRPLPtr;
+
+ /* Get the frame size (Byte swap for Intel).
+ * Do this early (see workaround comment below)
+ */
+ Length = be16_to_cpu((unsigned short)rpl->FrameSize);
+
+ /* Check if the Frame_Start, Frame_End and
+ * Frame_Complete bits are set.
+ */
+ if((rpl->Status & VALID_SINGLE_BUFFER_FRAME)
+ == VALID_SINGLE_BUFFER_FRAME)
+ {
+ ReceiveDataPtr = rpl->MData;
+
+ /* Workaround for delayed write of FrameSize on ISA
+ * (FrameSize is false but valid-bit is reset)
+ * Frame size is set to zero when the RPL is freed.
+ * Length2 is there because there have also been
+ * cases where the FrameSize was partially written
+ */
+ Length2 = be16_to_cpu((unsigned short)rpl->FrameSize);
+
+ if(Length == 0 || Length != Length2)
+ {
+ tp->RplHead = SaveHead;
+ break; /* Return to tms380tr_interrupt */
+ }
+ tms380tr_update_rcv_stats(tp,ReceiveDataPtr,Length);
+
+ if(tms380tr_debug > 3)
+ printk(KERN_DEBUG "%s: Packet Length %04X (%d)\n",
+ dev->name, Length, Length);
+
+ /* Indicate the received frame to system the
+ * adapter does the Source-Routing padding for
+ * us. See: OpenOptions in tms380tr_init_opb()
+ */
+ skb = rpl->Skb;
+ if(rpl->SkbStat == SKB_UNAVAILABLE)
+ {
+ /* Try again to allocate skb */
+ skb = dev_alloc_skb(tp->MaxPacketSize);
+ if(skb == NULL)
+ {
+ /* Update Stats ?? */
+ }
+ else
+ {
+ skb->dev = dev;
+ skb_put(skb, tp->MaxPacketSize);
+ rpl->SkbStat = SKB_DATA_COPY;
+ ReceiveDataPtr = rpl->MData;
+ }
+ }
+
+ if(skb && (rpl->SkbStat == SKB_DATA_COPY
+ || rpl->SkbStat == SKB_DMA_DIRECT))
+ {
+ if(rpl->SkbStat == SKB_DATA_COPY)
+ memcpy(skb->data, ReceiveDataPtr, Length);
+
+ /* Deliver frame to system */
+ rpl->Skb = NULL;
+ skb_trim(skb,Length);
+ skb->protocol = tr_type_trans(skb,dev);
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+ }
+ }
+ else /* Invalid frame */
+ {
+ if(rpl->Skb != NULL)
+ dev_kfree_skb_irq(rpl->Skb);
+
+ /* Skip list. */
+ if(rpl->Status & RX_START_FRAME)
+ /* Frame start bit is set -> overflow. */
+ tp->MacStat.rx_errors++;
+ }
+ if (rpl->DMABuff)
+ pci_unmap_single(tp->pdev, rpl->DMABuff, tp->MaxPacketSize, PCI_DMA_TODEVICE);
+ rpl->DMABuff = 0;
+
+ /* Allocate new skb for rpl */
+ rpl->Skb = dev_alloc_skb(tp->MaxPacketSize);
+ /* skb == NULL ? then use local buffer */
+ if(rpl->Skb == NULL)
+ {
+ rpl->SkbStat = SKB_UNAVAILABLE;
+ rpl->FragList[0].DataAddr = htonl(((char *)tp->LocalRxBuffers[rpl->RPLIndex] - (char *)tp) + tp->dmabuffer);
+ rpl->MData = tp->LocalRxBuffers[rpl->RPLIndex];
+ }
+ else /* skb != NULL */
+ {
+ rpl->Skb->dev = dev;
+ skb_put(rpl->Skb, tp->MaxPacketSize);
+
+ /* Data unreachable for DMA ? then use local buffer */
+ dmabuf = pci_map_single(tp->pdev, rpl->Skb->data, tp->MaxPacketSize, PCI_DMA_FROMDEVICE);
+ if(tp->dmalimit && (dmabuf + tp->MaxPacketSize > tp->dmalimit))
+ {
+ rpl->SkbStat = SKB_DATA_COPY;
+ rpl->FragList[0].DataAddr = htonl(((char *)tp->LocalRxBuffers[rpl->RPLIndex] - (char *)tp) + tp->dmabuffer);
+ rpl->MData = tp->LocalRxBuffers[rpl->RPLIndex];
+ }
+ else
+ {
+ /* DMA directly in skb->data */
+ rpl->SkbStat = SKB_DMA_DIRECT;
+ rpl->FragList[0].DataAddr = htonl(dmabuf);
+ rpl->MData = rpl->Skb->data;
+ rpl->DMABuff = dmabuf;
+ }
+ }
+
+ rpl->FragList[0].DataCount = cpu_to_be16((unsigned short)tp->MaxPacketSize);
+ rpl->FrameSize = 0;
+
+ /* Pass the last RPL back to the adapter */
+ tp->RplTail->FrameSize = 0;
+
+ /* Reset the CSTAT field in the list. */
+ tms380tr_write_rpl_status(tp->RplTail, RX_VALID | RX_FRAME_IRQ);
+
+ /* Current RPL becomes last one in list. */
+ tp->RplTail = tp->RplTail->NextRPLPtr;
+
+ /* Inform adapter about RPL valid. */
+ tms380tr_exec_sifcmd(dev, CMD_RX_VALID);
+ }
+
+ return;
+}
+
+/*
+ * This function should be used whenever the status of any RPL must be
+ * modified by the driver, because the compiler may otherwise change the
+ * order of instructions such that writing the RPL status may be executed
+ * at an undesireable time. When this function is used, the status is
+ * always written when the function is called.
+ */
+static void tms380tr_write_rpl_status(RPL *rpl, unsigned int Status)
+{
+ rpl->Status = Status;
+
+ return;
+}
+
+/*
+ * The function updates the statistic counters in mac->MacStat.
+ * It differtiates between directed and broadcast/multicast ( ==functional)
+ * frames.
+ */
+static void tms380tr_update_rcv_stats(struct net_local *tp, unsigned char DataPtr[],
+ unsigned int Length)
+{
+ tp->MacStat.rx_packets++;
+ tp->MacStat.rx_bytes += Length;
+
+ /* Test functional bit */
+ if(DataPtr[2] & GROUP_BIT)
+ tp->MacStat.multicast++;
+
+ return;
+}
+
+static int tms380tr_set_mac_address(struct net_device *dev, void *addr)
+{
+ struct net_local *tp = netdev_priv(dev);
+ struct sockaddr *saddr = addr;
+
+ if (tp->AdapterOpenFlag || tp->AdapterVirtOpenFlag) {
+ printk(KERN_WARNING "%s: Cannot set MAC/LAA address while card is open\n", dev->name);
+ return -EIO;
+ }
+ memcpy(dev->dev_addr, saddr->sa_data, dev->addr_len);
+ return 0;
+}
+
+#if TMS380TR_DEBUG > 0
+/*
+ * Dump Packet (data)
+ */
+static void tms380tr_dump(unsigned char *Data, int length)
+{
+ int i, j;
+
+ for (i = 0, j = 0; i < length / 8; i++, j += 8)
+ {
+ printk(KERN_DEBUG "%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]);
+ }
+
+ return;
+}
+#endif
+
+void tmsdev_term(struct net_device *dev)
+{
+ struct net_local *tp;
+
+ tp = netdev_priv(dev);
+ pci_unmap_single(tp->pdev, tp->dmabuffer, sizeof(struct net_local),
+ PCI_DMA_BIDIRECTIONAL);
+}
+
+int tmsdev_init(struct net_device *dev, unsigned long dmalimit,
+ struct pci_dev *pdev)
+{
+ struct net_local *tms_local;
+
+ memset(dev->priv, 0, sizeof(struct net_local));
+ tms_local = netdev_priv(dev);
+ init_waitqueue_head(&tms_local->wait_for_tok_int);
+ tms_local->dmalimit = dmalimit;
+ tms_local->pdev = pdev;
+ tms_local->dmabuffer = pci_map_single(pdev, (void *)tms_local,
+ sizeof(struct net_local), PCI_DMA_BIDIRECTIONAL);
+ if (tms_local->dmabuffer + sizeof(struct net_local) > dmalimit)
+ {
+ printk(KERN_INFO "%s: Memory not accessible for DMA\n",
+ dev->name);
+ tmsdev_term(dev);
+ return -ENOMEM;
+ }
+
+ /* These can be overridden by the card driver if needed */
+ dev->open = tms380tr_open;
+ 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;
+
+ return 0;
+}
+
+#ifdef MODULE
+
+EXPORT_SYMBOL(tms380tr_open);
+EXPORT_SYMBOL(tms380tr_close);
+EXPORT_SYMBOL(tms380tr_interrupt);
+EXPORT_SYMBOL(tmsdev_init);
+EXPORT_SYMBOL(tmsdev_term);
+EXPORT_SYMBOL(tms380tr_wait);
+
+struct module *TMS380_module = NULL;
+
+int init_module(void)
+{
+ printk(KERN_DEBUG "%s", version);
+
+ TMS380_module = &__this_module;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ TMS380_module = NULL;
+}
+#endif
+
+MODULE_LICENSE("GPL");
+
+
+/*
+ * Local variables:
+ * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tms380tr.c"
+ * alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tms380tr.c"
+ * c-set-style "K&R"
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/drivers/net/tokenring/tms380tr.h b/drivers/net/tokenring/tms380tr.h
new file mode 100644
index 00000000000..f2c5ba0f37a
--- /dev/null
+++ b/drivers/net/tokenring/tms380tr.h
@@ -0,0 +1,1141 @@
+/*
+ * tms380tr.h: TI TMS380 Token Ring driver for Linux
+ *
+ * Authors:
+ * - Christoph Goos <cgoos@syskonnect.de>
+ * - Adam Fritzler <mid@auk.cx>
+ */
+
+#ifndef __LINUX_TMS380TR_H
+#define __LINUX_TMS380TR_H
+
+#ifdef __KERNEL__
+
+#include <linux/interrupt.h>
+
+/* module prototypes */
+int tms380tr_open(struct net_device *dev);
+int tms380tr_close(struct net_device *dev);
+irqreturn_t tms380tr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+int tmsdev_init(struct net_device *dev, unsigned long dmalimit,
+ struct pci_dev *pdev);
+void tmsdev_term(struct net_device *dev);
+void tms380tr_wait(unsigned long time);
+
+#define TMS380TR_MAX_ADAPTERS 7
+
+#define SEND_TIMEOUT 10*HZ
+
+#define TR_RCF_LONGEST_FRAME_MASK 0x0070
+#define TR_RCF_FRAME4K 0x0030
+
+/*------------------------------------------------------------------*/
+/* Bit order for adapter communication with DMA */
+/* -------------------------------------------------------------- */
+/* Bit 8 | 9| 10| 11|| 12| 13| 14| 15|| 0| 1| 2| 3|| 4| 5| 6| 7| */
+/* -------------------------------------------------------------- */
+/* The bytes in a word must be byte swapped. Also, if a double */
+/* word is used for storage, then the words, as well as the bytes, */
+/* must be swapped. */
+/* Bit order for adapter communication with DIO */
+/* -------------------------------------------------------------- */
+/* Bit 0 | 1| 2| 3|| 4| 5| 6| 7|| 8| 9| 10| 11|| 12| 13| 14| 15| */
+/* -------------------------------------------------------------- */
+/*------------------------------------------------------------------*/
+
+/* Swap words of a long. */
+#define SWAPW(x) (((x) << 16) | ((x) >> 16))
+
+/* Get the low byte of a word. */
+#define LOBYTE(w) ((unsigned char)(w))
+
+/* Get the high byte of a word. */
+#define HIBYTE(w) ((unsigned char)((unsigned short)(w) >> 8))
+
+/* Get the low word of a long. */
+#define LOWORD(l) ((unsigned short)(l))
+
+/* Get the high word of a long. */
+#define HIWORD(l) ((unsigned short)((unsigned long)(l) >> 16))
+
+
+
+/* Token ring adapter I/O addresses for normal mode. */
+
+/*
+ * The SIF registers. Common to all adapters.
+ */
+/* Basic SIF (SRSX = 0) */
+#define SIFDAT 0x00 /* SIF/DMA data. */
+#define SIFINC 0x02 /* IO Word data with auto increment. */
+#define SIFINH 0x03 /* IO Byte data with auto increment. */
+#define SIFADR 0x04 /* SIF/DMA Address. */
+#define SIFCMD 0x06 /* SIF Command. */
+#define SIFSTS 0x06 /* SIF Status. */
+
+/* "Extended" SIF (SRSX = 1) */
+#define SIFACL 0x08 /* SIF Adapter Control Register. */
+#define SIFADD 0x0a /* SIF/DMA Address. -- 0x0a */
+#define SIFADX 0x0c /* 0x0c */
+#define DMALEN 0x0e /* SIF DMA length. -- 0x0e */
+
+/*
+ * POS Registers. Only for ISA Adapters.
+ */
+#define POSREG 0x10 /* Adapter Program Option Select (POS)
+ * Register: base IO address + 16 byte.
+ */
+#define POSREG_2 24L /* only for TR4/16+ adapter
+ * base IO address + 24 byte. -- 0x18
+ */
+
+/* SIFCMD command codes (high-low) */
+#define CMD_INTERRUPT_ADAPTER 0x8000 /* Cause internal adapter interrupt */
+#define CMD_ADAPTER_RESET 0x4000 /* Hardware reset of adapter */
+#define CMD_SSB_CLEAR 0x2000 /* Acknowledge to adapter to
+ * system interrupts.
+ */
+#define CMD_EXECUTE 0x1000 /* Execute SCB command */
+#define CMD_SCB_REQUEST 0x0800 /* Request adapter to interrupt
+ * system when SCB is available for
+ * another command.
+ */
+#define CMD_RX_CONTINUE 0x0400 /* Continue receive after odd pointer
+ * stop. (odd pointer receive method)
+ */
+#define CMD_RX_VALID 0x0200 /* Now actual RPL is valid. */
+#define CMD_TX_VALID 0x0100 /* Now actual TPL is valid. (valid
+ * bit receive/transmit method)
+ */
+#define CMD_SYSTEM_IRQ 0x0080 /* Adapter-to-attached-system
+ * interrupt is reset.
+ */
+#define CMD_CLEAR_SYSTEM_IRQ 0x0080 /* Clear SYSTEM_INTERRUPT bit.
+ * (write: 1=ignore, 0=reset)
+ */
+#define EXEC_SOFT_RESET 0xFF00 /* adapter soft reset. (restart
+ * adapter after hardware reset)
+ */
+
+
+/* ACL commands (high-low) */
+#define ACL_SWHLDA 0x0800 /* Software hold acknowledge. */
+#define ACL_SWDDIR 0x0400 /* Data transfer direction. */
+#define ACL_SWHRQ 0x0200 /* Pseudo DMA operation. */
+#define ACL_PSDMAEN 0x0100 /* Enable pseudo system DMA. */
+#define ACL_ARESET 0x0080 /* Adapter hardware reset command.
+ * (held in reset condition as
+ * long as bit is set)
+ */
+#define ACL_CPHALT 0x0040 /* Communication processor halt.
+ * (can only be set while ACL_ARESET
+ * bit is set; prevents adapter
+ * processor from executing code while
+ * downloading firmware)
+ */
+#define ACL_BOOT 0x0020
+#define ACL_SINTEN 0x0008 /* System interrupt enable/disable
+ * (1/0): can be written if ACL_ARESET
+ * is zero.
+ */
+#define ACL_PEN 0x0004
+
+#define ACL_NSELOUT0 0x0002
+#define ACL_NSELOUT1 0x0001 /* NSELOUTx have a card-specific
+ * meaning for setting ring speed.
+ */
+
+#define PS_DMA_MASK (ACL_SWHRQ | ACL_PSDMAEN)
+
+
+/* SIFSTS register return codes (high-low) */
+#define STS_SYSTEM_IRQ 0x0080 /* Adapter-to-attached-system
+ * interrupt is valid.
+ */
+#define STS_INITIALIZE 0x0040 /* INITIALIZE status. (ready to
+ * initialize)
+ */
+#define STS_TEST 0x0020 /* TEST status. (BUD not completed) */
+#define STS_ERROR 0x0010 /* ERROR status. (unrecoverable
+ * HW error occurred)
+ */
+#define STS_MASK 0x00F0 /* Mask interesting status bits. */
+#define STS_ERROR_MASK 0x000F /* Get Error Code by masking the
+ * interrupt code bits.
+ */
+#define ADAPTER_INT_PTRS 0x0A00 /* Address offset of adapter internal
+ * pointers 01:0a00 (high-low) have to
+ * be read after init and before open.
+ */
+
+
+/* Interrupt Codes (only MAC IRQs) */
+#define STS_IRQ_ADAPTER_CHECK 0x0000 /* unrecoverable hardware or
+ * software error.
+ */
+#define STS_IRQ_RING_STATUS 0x0004 /* SSB is updated with ring status. */
+#define STS_IRQ_LLC_STATUS 0x0005 /* Not used in MAC-only microcode */
+#define STS_IRQ_SCB_CLEAR 0x0006 /* SCB clear, following an
+ * SCB_REQUEST IRQ.
+ */
+#define STS_IRQ_TIMER 0x0007 /* Not normally used in MAC ucode */
+#define STS_IRQ_COMMAND_STATUS 0x0008 /* SSB is updated with command
+ * status.
+ */
+#define STS_IRQ_RECEIVE_STATUS 0x000A /* SSB is updated with receive
+ * status.
+ */
+#define STS_IRQ_TRANSMIT_STATUS 0x000C /* SSB is updated with transmit
+ * status
+ */
+#define STS_IRQ_RECEIVE_PENDING 0x000E /* Not used in MAC-only microcode */
+#define STS_IRQ_MASK 0x000F /* = STS_ERROR_MASK. */
+
+
+/* TRANSMIT_STATUS completion code: (SSB.Parm[0]) */
+#define COMMAND_COMPLETE 0x0080 /* TRANSMIT command completed
+ * (avoid this!) issue another transmit
+ * to send additional frames.
+ */
+#define FRAME_COMPLETE 0x0040 /* Frame has been transmitted;
+ * INTERRUPT_FRAME bit was set in the
+ * CSTAT request; indication of possibly
+ * more than one frame transmissions!
+ * SSB.Parm[0-1]: 32 bit pointer to
+ * TPL of last frame.
+ */
+#define LIST_ERROR 0x0020 /* Error in one of the TPLs that
+ * compose the frame; TRANSMIT
+ * terminated; Parm[1-2]: 32bit pointer
+ * to TPL which starts the error
+ * frame; error details in bits 8-13.
+ * (14?)
+ */
+#define FRAME_SIZE_ERROR 0x8000 /* FRAME_SIZE does not equal the sum of
+ * the valid DATA_COUNT fields;
+ * FRAME_SIZE less than header plus
+ * information field. (15 bytes +
+ * routing field) Or if FRAME_SIZE
+ * was specified as zero in one list.
+ */
+#define TX_THRESHOLD 0x4000 /* FRAME_SIZE greater than (BUFFER_SIZE
+ * - 9) * TX_BUF_MAX.
+ */
+#define ODD_ADDRESS 0x2000 /* Odd forward pointer value is
+ * read on a list without END_FRAME
+ * indication.
+ */
+#define FRAME_ERROR 0x1000 /* START_FRAME bit (not) anticipated,
+ * but (not) set.
+ */
+#define ACCESS_PRIORITY_ERROR 0x0800 /* Access priority requested has not
+ * been allowed.
+ */
+#define UNENABLED_MAC_FRAME 0x0400 /* MAC frame has source class of zero
+ * or MAC frame PCF ATTN field is
+ * greater than one.
+ */
+#define ILLEGAL_FRAME_FORMAT 0x0200 /* Bit 0 or FC field was set to one. */
+
+
+/*
+ * Since we need to support some functions even if the adapter is in a
+ * CLOSED state, we have a (pseudo-) command queue which holds commands
+ * that are outstandig to be executed.
+ *
+ * Each time a command completes, an interrupt occurs and the next
+ * command is executed. The command queue is actually a simple word with
+ * a bit for each outstandig command. Therefore the commands will not be
+ * executed in the order they have been queued.
+ *
+ * The following defines the command code bits and the command queue:
+ */
+#define OC_OPEN 0x0001 /* OPEN command */
+#define OC_TRANSMIT 0x0002 /* TRANSMIT command */
+#define OC_TRANSMIT_HALT 0x0004 /* TRANSMIT_HALT command */
+#define OC_RECEIVE 0x0008 /* RECEIVE command */
+#define OC_CLOSE 0x0010 /* CLOSE command */
+#define OC_SET_GROUP_ADDR 0x0020 /* SET_GROUP_ADDR command */
+#define OC_SET_FUNCT_ADDR 0x0040 /* SET_FUNCT_ADDR command */
+#define OC_READ_ERROR_LOG 0x0080 /* READ_ERROR_LOG command */
+#define OC_READ_ADAPTER 0x0100 /* READ_ADAPTER command */
+#define OC_MODIFY_OPEN_PARMS 0x0400 /* MODIFY_OPEN_PARMS command */
+#define OC_RESTORE_OPEN_PARMS 0x0800 /* RESTORE_OPEN_PARMS command */
+#define OC_SET_FIRST_16_GROUP 0x1000 /* SET_FIRST_16_GROUP command */
+#define OC_SET_BRIDGE_PARMS 0x2000 /* SET_BRIDGE_PARMS command */
+#define OC_CONFIG_BRIDGE_PARMS 0x4000 /* CONFIG_BRIDGE_PARMS command */
+
+#define OPEN 0x0300 /* C: open command. S: completion. */
+#define TRANSMIT 0x0400 /* C: transmit command. S: completion
+ * status. (reject: COMMAND_REJECT if
+ * adapter not opened, TRANSMIT already
+ * issued or address passed in the SCB
+ * not word aligned)
+ */
+#define TRANSMIT_HALT 0x0500 /* C: interrupt TX TPL chain; if no
+ * TRANSMIT command issued, the command
+ * is ignored (completion with TRANSMIT
+ * status (0x0400)!)
+ */
+#define RECEIVE 0x0600 /* C: receive command. S: completion
+ * status. (reject: COMMAND_REJECT if
+ * adapter not opened, RECEIVE already
+ * issued or address passed in the SCB
+ * not word aligned)
+ */
+#define CLOSE 0x0700 /* C: close adapter. S: completion.
+ * (COMMAND_REJECT if adapter not open)
+ */
+#define SET_GROUP_ADDR 0x0800 /* C: alter adapter group address after
+ * OPEN. S: completion. (COMMAND_REJECT
+ * if adapter not open)
+ */
+#define SET_FUNCT_ADDR 0x0900 /* C: alter adapter functional address
+ * after OPEN. S: completion.
+ * (COMMAND_REJECT if adapter not open)
+ */
+#define READ_ERROR_LOG 0x0A00 /* C: read adapter error counters.
+ * S: completion. (command ignored
+ * if adapter not open!)
+ */
+#define READ_ADAPTER 0x0B00 /* C: read data from adapter memory.
+ * (important: after init and before
+ * open!) S: completion. (ADAPTER_CHECK
+ * interrupt if undefined storage area
+ * read)
+ */
+#define MODIFY_OPEN_PARMS 0x0D00 /* C: modify some adapter operational
+ * parameters. (bit correspondend to
+ * WRAP_INTERFACE is ignored)
+ * S: completion. (reject:
+ * COMMAND_REJECT)
+ */
+#define RESTORE_OPEN_PARMS 0x0E00 /* C: modify some adapter operational
+ * parameters. (bit correspondend
+ * to WRAP_INTERFACE is ignored)
+ * S: completion. (reject:
+ * COMMAND_REJECT)
+ */
+#define SET_FIRST_16_GROUP 0x0F00 /* C: alter the first two bytes in
+ * adapter group address.
+ * S: completion. (reject:
+ * COMMAND_REJECT)
+ */
+#define SET_BRIDGE_PARMS 0x1000 /* C: values and conditions for the
+ * adapter hardware to use when frames
+ * are copied for forwarding.
+ * S: completion. (reject:
+ * COMMAND_REJECT)
+ */
+#define CONFIG_BRIDGE_PARMS 0x1100 /* C: ..
+ * S: completion. (reject:
+ * COMMAND_REJECT)
+ */
+
+#define SPEED_4 4
+#define SPEED_16 16 /* Default transmission speed */
+
+
+/* Initialization Parameter Block (IPB); word alignment necessary! */
+#define BURST_SIZE 0x0018 /* Default burst size */
+#define BURST_MODE 0x9F00 /* Burst mode enable */
+#define DMA_RETRIES 0x0505 /* Magic DMA retry number... */
+
+#define CYCLE_TIME 3 /* Default AT-bus cycle time: 500 ns
+ * (later adapter version: fix cycle time!)
+ */
+#define LINE_SPEED_BIT 0x80
+
+/* Macro definition for the wait function. */
+#define ONE_SECOND_TICKS 1000000
+#define HALF_SECOND (ONE_SECOND_TICKS / 2)
+#define ONE_SECOND (ONE_SECOND_TICKS)
+#define TWO_SECONDS (ONE_SECOND_TICKS * 2)
+#define THREE_SECONDS (ONE_SECOND_TICKS * 3)
+#define FOUR_SECONDS (ONE_SECOND_TICKS * 4)
+#define FIVE_SECONDS (ONE_SECOND_TICKS * 5)
+
+#define BUFFER_SIZE 2048 /* Buffers on Adapter */
+
+#pragma pack(1)
+typedef struct {
+ unsigned short Init_Options; /* Initialize with burst mode;
+ * LLC disabled. (MAC only)
+ */
+
+ /* Interrupt vectors the adapter places on attached system bus. */
+ u_int8_t CMD_Status_IV; /* Interrupt vector: command status. */
+ u_int8_t TX_IV; /* Interrupt vector: transmit. */
+ u_int8_t RX_IV; /* Interrupt vector: receive. */
+ u_int8_t Ring_Status_IV; /* Interrupt vector: ring status. */
+ u_int8_t SCB_Clear_IV; /* Interrupt vector: SCB clear. */
+ u_int8_t Adapter_CHK_IV; /* Interrupt vector: adapter check. */
+
+ u_int16_t RX_Burst_Size; /* Max. number of transfer cycles. */
+ u_int16_t TX_Burst_Size; /* During DMA burst; even value! */
+ u_int16_t DMA_Abort_Thrhld; /* Number of DMA retries. */
+
+ u_int32_t SCB_Addr; /* SCB address: even, word aligned, high-low */
+ u_int32_t SSB_Addr; /* SSB address: even, word aligned, high-low */
+} IPB, *IPB_Ptr;
+#pragma pack()
+
+/*
+ * OPEN Command Parameter List (OCPL) (can be reused, if the adapter has to
+ * be reopened)
+ */
+#define BUFFER_SIZE 2048 /* Buffers on Adapter. */
+#define TPL_SIZE 8+6*TX_FRAG_NUM /* Depending on fragments per TPL. */
+#define RPL_SIZE 14 /* (with TI firmware v2.26 handling
+ * up to nine fragments possible)
+ */
+#define TX_BUF_MIN 20 /* ??? (Stephan: calculation with */
+#define TX_BUF_MAX 40 /* BUFFER_SIZE and MAX_FRAME_SIZE) ???
+ */
+#define DISABLE_EARLY_TOKEN_RELEASE 0x1000
+
+/* OPEN Options (high-low) */
+#define WRAP_INTERFACE 0x0080 /* Inserting omitted for test
+ * purposes; transmit data appears
+ * as receive data. (useful for
+ * testing; change: CLOSE necessary)
+ */
+#define DISABLE_HARD_ERROR 0x0040 /* On HARD_ERROR & TRANSMIT_BEACON
+ * no RING.STATUS interrupt.
+ */
+#define DISABLE_SOFT_ERROR 0x0020 /* On SOFT_ERROR, no RING.STATUS
+ * interrupt.
+ */
+#define PASS_ADAPTER_MAC_FRAMES 0x0010 /* Passing unsupported MAC frames
+ * to system.
+ */
+#define PASS_ATTENTION_FRAMES 0x0008 /* All changed attention MAC frames are
+ * passed to the system.
+ */
+#define PAD_ROUTING_FIELD 0x0004 /* Routing field is padded to 18
+ * bytes.
+ */
+#define FRAME_HOLD 0x0002 /*Adapter waits for entire frame before
+ * initiating DMA transfer; otherwise:
+ * DMA transfer initiation if internal
+ * buffer filled.
+ */
+#define CONTENDER 0x0001 /* Adapter participates in the monitor
+ * contention process.
+ */
+#define PASS_BEACON_MAC_FRAMES 0x8000 /* Adapter passes beacon MAC frames
+ * to the system.
+ */
+#define EARLY_TOKEN_RELEASE 0x1000 /* Only valid in 16 Mbps operation;
+ * 0 = ETR. (no effect in 4 Mbps
+ * operation)
+ */
+#define COPY_ALL_MAC_FRAMES 0x0400 /* All MAC frames are copied to
+ * the system. (after OPEN: duplicate
+ * address test (DAT) MAC frame is
+ * first received frame copied to the
+ * system)
+ */
+#define COPY_ALL_NON_MAC_FRAMES 0x0200 /* All non MAC frames are copied to
+ * the system.
+ */
+#define PASS_FIRST_BUF_ONLY 0x0100 /* Passes only first internal buffer
+ * of each received frame; FrameSize
+ * of RPLs must contain internal
+ * BUFFER_SIZE bits for promiscous mode.
+ */
+#define ENABLE_FULL_DUPLEX_SELECTION 0x2000
+ /* Enable the use of full-duplex
+ * settings with bits in byte 22 in
+ * ocpl. (new feature in firmware
+ * version 3.09)
+ */
+
+/* Full-duplex settings */
+#define OPEN_FULL_DUPLEX_OFF 0x0000
+#define OPEN_FULL_DUPLEX_ON 0x00c0
+#define OPEN_FULL_DUPLEX_AUTO 0x0080
+
+#define PROD_ID_SIZE 18 /* Length of product ID. */
+
+#define TX_FRAG_NUM 3 /* Number of fragments used in one TPL. */
+#define TX_MORE_FRAGMENTS 0x8000 /* Bit set in DataCount to indicate more
+ * fragments following.
+ */
+
+/* XXX is there some better way to do this? */
+#define ISA_MAX_ADDRESS 0x00ffffff
+#define PCI_MAX_ADDRESS 0xffffffff
+
+#pragma pack(1)
+typedef struct {
+ u_int16_t OPENOptions;
+ u_int8_t NodeAddr[6]; /* Adapter node address; use ROM
+ * address
+ */
+ u_int32_t GroupAddr; /* Multicast: high order
+ * bytes = 0xC000
+ */
+ u_int32_t FunctAddr; /* High order bytes = 0xC000 */
+ u_int16_t RxListSize; /* RPL size: 0 (=26), 14, 20 or
+ * 26 bytes read by the adapter.
+ * (Depending on the number of
+ * fragments/list)
+ */
+ u_int16_t TxListSize; /* TPL size */
+ u_int16_t BufSize; /* Is automatically rounded up to the
+ * nearest nK boundary.
+ */
+ u_int16_t FullDuplex;
+ u_int16_t Reserved;
+ u_int8_t TXBufMin; /* Number of adapter buffers reserved
+ * for transmission a minimum of 2
+ * buffers must be allocated.
+ */
+ u_int8_t TXBufMax; /* Maximum number of adapter buffers
+ * for transmit; a minimum of 2 buffers
+ * must be available for receive.
+ * Default: 6
+ */
+ u_int16_t ProdIDAddr[2];/* Pointer to product ID. */
+} OPB, *OPB_Ptr;
+#pragma pack()
+
+/*
+ * SCB: adapter commands enabled by the host system started by writing
+ * CMD_INTERRUPT_ADAPTER | CMD_EXECUTE (|SCB_REQUEST) to the SIFCMD IO
+ * register. (special case: | CMD_SYSTEM_IRQ for initialization)
+ */
+#pragma pack(1)
+typedef struct {
+ u_int16_t CMD; /* Command code */
+ u_int16_t Parm[2]; /* Pointer to Command Parameter Block */
+} SCB; /* System Command Block (32 bit physical address; big endian)*/
+#pragma pack()
+
+/*
+ * SSB: adapter command return status can be evaluated after COMMAND_STATUS
+ * adapter to system interrupt after reading SSB, the availability of the SSB
+ * has to be told the adapter by writing CMD_INTERRUPT_ADAPTER | CMD_SSB_CLEAR
+ * in the SIFCMD IO register.
+ */
+#pragma pack(1)
+typedef struct {
+ u_int16_t STS; /* Status code */
+ u_int16_t Parm[3]; /* Parameter or pointer to Status Parameter
+ * Block.
+ */
+} SSB; /* System Status Block (big endian - physical address) */
+#pragma pack()
+
+typedef struct {
+ unsigned short BurnedInAddrPtr; /* Pointer to adapter burned in
+ * address. (BIA)
+ */
+ unsigned short SoftwareLevelPtr;/* Pointer to software level data. */
+ unsigned short AdapterAddrPtr; /* Pointer to adapter addresses. */
+ unsigned short AdapterParmsPtr; /* Pointer to adapter parameters. */
+ unsigned short MACBufferPtr; /* Pointer to MAC buffer. (internal) */
+ unsigned short LLCCountersPtr; /* Pointer to LLC counters. */
+ unsigned short SpeedFlagPtr; /* Pointer to data rate flag.
+ * (4/16 Mbps)
+ */
+ unsigned short AdapterRAMPtr; /* Pointer to adapter RAM found. (KB) */
+} INTPTRS; /* Adapter internal pointers */
+
+#pragma pack(1)
+typedef struct {
+ u_int8_t Line_Error; /* Line error: code violation in
+ * frame or in a token, or FCS error.
+ */
+ u_int8_t Internal_Error; /* IBM specific. (Reserved_1) */
+ u_int8_t Burst_Error;
+ u_int8_t ARI_FCI_Error; /* ARI/FCI bit zero in AMP or
+ * SMP MAC frame.
+ */
+ u_int8_t AbortDelimeters; /* IBM specific. (Reserved_2) */
+ u_int8_t Reserved_3;
+ u_int8_t Lost_Frame_Error; /* Receive of end of transmitted
+ * frame failed.
+ */
+ u_int8_t Rx_Congest_Error; /* Adapter in repeat mode has not
+ * enough buffer space to copy incoming
+ * frame.
+ */
+ u_int8_t Frame_Copied_Error; /* ARI bit not zero in frame
+ * addressed to adapter.
+ */
+ u_int8_t Frequency_Error; /* IBM specific. (Reserved_4) */
+ u_int8_t Token_Error; /* (active only in monitor station) */
+ u_int8_t Reserved_5;
+ u_int8_t DMA_Bus_Error; /* DMA bus errors not exceeding the
+ * abort thresholds.
+ */
+ u_int8_t DMA_Parity_Error; /* DMA parity errors not exceeding
+ * the abort thresholds.
+ */
+} ERRORTAB; /* Adapter error counters */
+#pragma pack()
+
+
+/*--------------------- Send and Receive definitions -------------------*/
+#pragma pack(1)
+typedef struct {
+ u_int16_t DataCount; /* Value 0, even and odd values are
+ * permitted; value is unaltered most
+ * significant bit set: following
+ * fragments last fragment: most
+ * significant bit is not evaluated.
+ * (???)
+ */
+ u_int32_t DataAddr; /* Pointer to frame data fragment;
+ * even or odd.
+ */
+} Fragment;
+#pragma pack()
+
+#define MAX_FRAG_NUMBERS 9 /* Maximal number of fragments possible to use
+ * in one RPL/TPL. (depending on TI firmware
+ * version)
+ */
+
+/*
+ * AC (1), FC (1), Dst (6), Src (6), RIF (18), Data (4472) = 4504
+ * The packet size can be one of the follows: 548, 1502, 2084, 4504, 8176,
+ * 11439, 17832. Refer to TMS380 Second Generation Token Ring User's Guide
+ * Page 2-27.
+ */
+#define HEADER_SIZE (1 + 1 + 6 + 6)
+#define SRC_SIZE 18
+#define MIN_DATA_SIZE 516
+#define DEFAULT_DATA_SIZE 4472
+#define MAX_DATA_SIZE 17800
+
+#define DEFAULT_PACKET_SIZE (HEADER_SIZE + SRC_SIZE + DEFAULT_DATA_SIZE)
+#define MIN_PACKET_SIZE (HEADER_SIZE + SRC_SIZE + MIN_DATA_SIZE)
+#define MAX_PACKET_SIZE (HEADER_SIZE + SRC_SIZE + MAX_DATA_SIZE)
+
+/*
+ * Macros to deal with the frame status field.
+ */
+#define AC_NOT_RECOGNIZED 0x00
+#define GROUP_BIT 0x80
+#define GET_TRANSMIT_STATUS_HIGH_BYTE(Ts) ((unsigned char)((Ts) >> 8))
+#define GET_FRAME_STATUS_HIGH_AC(Fs) ((unsigned char)(((Fs) & 0xC0) >> 6))
+#define GET_FRAME_STATUS_LOW_AC(Fs) ((unsigned char)(((Fs) & 0x0C) >> 2))
+#define DIRECTED_FRAME(Context) (!((Context)->MData[2] & GROUP_BIT))
+
+
+/*--------------------- Send Functions ---------------------------------*/
+/* define TX_CSTAT _REQUEST (R) and _COMPLETE (C) values (high-low) */
+
+#define TX_VALID 0x0080 /* R: set via TRANSMIT.VALID interrupt.
+ * C: always reset to zero!
+ */
+#define TX_FRAME_COMPLETE 0x0040 /* R: must be reset to zero.
+ * C: set to one.
+ */
+#define TX_START_FRAME 0x0020 /* R: start of a frame: 1
+ * C: unchanged.
+ */
+#define TX_END_FRAME 0x0010 /* R: end of a frame: 1
+ * C: unchanged.
+ */
+#define TX_FRAME_IRQ 0x0008 /* R: request interrupt generation
+ * after transmission.
+ * C: unchanged.
+ */
+#define TX_ERROR 0x0004 /* R: reserved.
+ * C: set to one if Error occurred.
+ */
+#define TX_INTERFRAME_WAIT 0x0004
+#define TX_PASS_CRC 0x0002 /* R: set if CRC value is already
+ * calculated. (valid only in
+ * FRAME_START TPL)
+ * C: unchanged.
+ */
+#define TX_PASS_SRC_ADDR 0x0001 /* R: adapter uses explicit frame
+ * source address and does not overwrite
+ * with the adapter node address.
+ * (valid only in FRAME_START TPL)
+ *
+ * C: unchanged.
+ */
+#define TX_STRIP_FS 0xFF00 /* R: reserved.
+ * C: if no Transmission Error,
+ * field contains copy of FS byte after
+ * stripping of frame.
+ */
+
+/*
+ * Structure of Transmit Parameter Lists (TPLs) (only one frame every TPL,
+ * but possibly multiple TPLs for one frame) the length of the TPLs has to be
+ * initialized in the OPL. (OPEN parameter list)
+ */
+#define TPL_NUM 3 /* Number of Transmit Parameter Lists.
+ * !! MUST BE >= 3 !!
+ */
+
+#pragma pack(1)
+typedef struct s_TPL TPL;
+
+struct s_TPL { /* Transmit Parameter List (align on even word boundaries) */
+ u_int32_t NextTPLAddr; /* Pointer to next TPL in chain; if
+ * pointer is odd: this is the last
+ * TPL. Pointing to itself can cause
+ * problems!
+ */
+ volatile u_int16_t Status; /* Initialized by the adapter:
+ * CSTAT_REQUEST important: update least
+ * significant bit first! Set by the
+ * adapter: CSTAT_COMPLETE status.
+ */
+ u_int16_t FrameSize; /* Number of bytes to be transmitted
+ * as a frame including AC/FC,
+ * Destination, Source, Routing field
+ * not including CRC, FS, End Delimiter
+ * (valid only if START_FRAME bit in
+ * CSTAT nonzero) must not be zero in
+ * any list; maximum value: (BUFFER_SIZE
+ * - 8) * TX_BUF_MAX sum of DataCount
+ * values in FragmentList must equal
+ * Frame_Size value in START_FRAME TPL!
+ * frame data fragment list.
+ */
+
+ /* TPL/RPL size in OPEN parameter list depending on maximal
+ * numbers of fragments used in one parameter list.
+ */
+ Fragment FragList[TX_FRAG_NUM]; /* Maximum: nine frame fragments in one
+ * TPL actual version of firmware: 9
+ * fragments possible.
+ */
+#pragma pack()
+
+ /* Special proprietary data and precalculations */
+
+ TPL *NextTPLPtr; /* Pointer to next TPL in chain. */
+ unsigned char *MData;
+ struct sk_buff *Skb;
+ unsigned char TPLIndex;
+ volatile unsigned char BusyFlag;/* Flag: TPL busy? */
+ dma_addr_t DMABuff; /* DMA IO bus address from pci_map */
+};
+
+/* ---------------------Receive Functions-------------------------------*
+ * define RECEIVE_CSTAT_REQUEST (R) and RECEIVE_CSTAT_COMPLETE (C) values.
+ * (high-low)
+ */
+#define RX_VALID 0x0080 /* R: set; tell adapter with
+ * RECEIVE.VALID interrupt.
+ * C: reset to zero.
+ */
+#define RX_FRAME_COMPLETE 0x0040 /* R: must be reset to zero,
+ * C: set to one.
+ */
+#define RX_START_FRAME 0x0020 /* R: must be reset to zero.
+ * C: set to one on the list.
+ */
+#define RX_END_FRAME 0x0010 /* R: must be reset to zero.
+ * C: set to one on the list
+ * that ends the frame.
+ */
+#define RX_FRAME_IRQ 0x0008 /* R: request interrupt generation
+ * after receive.
+ * C: unchanged.
+ */
+#define RX_INTERFRAME_WAIT 0x0004 /* R: after receiving a frame:
+ * interrupt and wait for a
+ * RECEIVE.CONTINUE.
+ * C: unchanged.
+ */
+#define RX_PASS_CRC 0x0002 /* R: if set, the adapter includes
+ * the CRC in data passed. (last four
+ * bytes; valid only if FRAME_START is
+ * set)
+ * C: set, if CRC is included in
+ * received data.
+ */
+#define RX_PASS_SRC_ADDR 0x0001 /* R: adapter uses explicit frame
+ * source address and does not
+ * overwrite with the adapter node
+ * address. (valid only if FRAME_START
+ * is set)
+ * C: unchanged.
+ */
+#define RX_RECEIVE_FS 0xFC00 /* R: reserved; must be reset to zero.
+ * C: on lists with START_FRAME, field
+ * contains frame status field from
+ * received frame; otherwise cleared.
+ */
+#define RX_ADDR_MATCH 0x0300 /* R: reserved; must be reset to zero.
+ * C: address match code mask.
+ */
+#define RX_STATUS_MASK 0x00FF /* Mask for receive status bits. */
+
+#define RX_INTERN_ADDR_MATCH 0x0100 /* C: internally address match. */
+#define RX_EXTERN_ADDR_MATCH 0x0200 /* C: externally matched via
+ * XMATCH/XFAIL interface.
+ */
+#define RX_INTEXT_ADDR_MATCH 0x0300 /* C: internally and externally
+ * matched.
+ */
+#define RX_READY (RX_VALID | RX_FRAME_IRQ) /* Ready for receive. */
+
+/* Constants for Command Status Interrupt.
+ * COMMAND_REJECT status field bit functions (SSB.Parm[0])
+ */
+#define ILLEGAL_COMMAND 0x0080 /* Set if an unknown command
+ * is issued to the adapter
+ */
+#define ADDRESS_ERROR 0x0040 /* Set if any address field in
+ * the SCB is odd. (not word aligned)
+ */
+#define ADAPTER_OPEN 0x0020 /* Command issued illegal with
+ * open adapter.
+ */
+#define ADAPTER_CLOSE 0x0010 /* Command issued illegal with
+ * closed adapter.
+ */
+#define SAME_COMMAND 0x0008 /* Command issued with same command
+ * already executing.
+ */
+
+/* OPEN_COMPLETION values (SSB.Parm[0], MSB) */
+#define NODE_ADDR_ERROR 0x0040 /* Wrong address or BIA read
+ * zero address.
+ */
+#define LIST_SIZE_ERROR 0x0020 /* If List_Size value not in 0,
+ * 14, 20, 26.
+ */
+#define BUF_SIZE_ERROR 0x0010 /* Not enough available memory for
+ * two buffers.
+ */
+#define TX_BUF_COUNT_ERROR 0x0004 /* Remaining receive buffers less than
+ * two.
+ */
+#define OPEN_ERROR 0x0002 /* Error during ring insertion; more
+ * information in bits 8-15.
+ */
+
+/* Standard return codes */
+#define GOOD_COMPLETION 0x0080 /* =OPEN_SUCCESSFULL */
+#define INVALID_OPEN_OPTION 0x0001 /* OPEN options are not supported by
+ * the adapter.
+ */
+
+/* OPEN phases; details of OPEN_ERROR (SSB.Parm[0], LSB) */
+#define OPEN_PHASES_MASK 0xF000 /* Check only the bits 8-11. */
+#define LOBE_MEDIA_TEST 0x1000
+#define PHYSICAL_INSERTION 0x2000
+#define ADDRESS_VERIFICATION 0x3000
+#define PARTICIPATION_IN_RING_POLL 0x4000
+#define REQUEST_INITIALISATION 0x5000
+#define FULLDUPLEX_CHECK 0x6000
+
+/* OPEN error codes; details of OPEN_ERROR (SSB.Parm[0], LSB) */
+#define OPEN_ERROR_CODES_MASK 0x0F00 /* Check only the bits 12-15. */
+#define OPEN_FUNCTION_FAILURE 0x0100 /* Unable to transmit to itself or
+ * frames received before insertion.
+ */
+#define OPEN_SIGNAL_LOSS 0x0200 /* Signal loss condition detected at
+ * receiver.
+ */
+#define OPEN_TIMEOUT 0x0500 /* Insertion timer expired before
+ * logical insertion.
+ */
+#define OPEN_RING_FAILURE 0x0600 /* Unable to receive own ring purge
+ * MAC frames.
+ */
+#define OPEN_RING_BEACONING 0x0700 /* Beacon MAC frame received after
+ * ring insertion.
+ */
+#define OPEN_DUPLICATE_NODEADDR 0x0800 /* Other station in ring found
+ * with the same address.
+ */
+#define OPEN_REQUEST_INIT 0x0900 /* RPS present but does not respond. */
+#define OPEN_REMOVE_RECEIVED 0x0A00 /* Adapter received a remove adapter
+ * MAC frame.
+ */
+#define OPEN_FULLDUPLEX_SET 0x0D00 /* Got this with full duplex on when
+ * trying to connect to a normal ring.
+ */
+
+/* SET_BRIDGE_PARMS return codes: */
+#define BRIDGE_INVALID_MAX_LEN 0x4000 /* MAX_ROUTING_FIELD_LENGTH odd,
+ * less than 6 or > 30.
+ */
+#define BRIDGE_INVALID_SRC_RING 0x2000 /* SOURCE_RING number zero, too large
+ * or = TARGET_RING.
+ */
+#define BRIDGE_INVALID_TRG_RING 0x1000 /* TARGET_RING number zero, too large
+ * or = SOURCE_RING.
+ */
+#define BRIDGE_INVALID_BRDGE_NO 0x0800 /* BRIDGE_NUMBER too large. */
+#define BRIDGE_INVALID_OPTIONS 0x0400 /* Invalid bridge options. */
+#define BRIDGE_DIAGS_FAILED 0x0200 /* Diagnostics of TMS380SRA failed. */
+#define BRIDGE_NO_SRA 0x0100 /* The TMS380SRA does not exist in HW
+ * configuration.
+ */
+
+/*
+ * Bring Up Diagnostics error codes.
+ */
+#define BUD_INITIAL_ERROR 0x0
+#define BUD_CHECKSUM_ERROR 0x1
+#define BUD_ADAPTER_RAM_ERROR 0x2
+#define BUD_INSTRUCTION_ERROR 0x3
+#define BUD_CONTEXT_ERROR 0x4
+#define BUD_PROTOCOL_ERROR 0x5
+#define BUD_INTERFACE_ERROR 0x6
+
+/* BUD constants */
+#define BUD_MAX_RETRIES 3
+#define BUD_MAX_LOOPCNT 6
+#define BUD_TIMEOUT 3000
+
+/* Initialization constants */
+#define INIT_MAX_RETRIES 3 /* Maximum three retries. */
+#define INIT_MAX_LOOPCNT 22 /* Maximum loop counts. */
+
+/* RING STATUS field values (high/low) */
+#define SIGNAL_LOSS 0x0080 /* Loss of signal on the ring
+ * detected.
+ */
+#define HARD_ERROR 0x0040 /* Transmitting or receiving beacon
+ * frames.
+ */
+#define SOFT_ERROR 0x0020 /* Report error MAC frame
+ * transmitted.
+ */
+#define TRANSMIT_BEACON 0x0010 /* Transmitting beacon frames on the
+ * ring.
+ */
+#define LOBE_WIRE_FAULT 0x0008 /* Open or short circuit in the
+ * cable to concentrator; adapter
+ * closed.
+ */
+#define AUTO_REMOVAL_ERROR 0x0004 /* Lobe wrap test failed, deinserted;
+ * adapter closed.
+ */
+#define REMOVE_RECEIVED 0x0001 /* Received a remove ring station MAC
+ * MAC frame request; adapter closed.
+ */
+#define COUNTER_OVERFLOW 0x8000 /* Overflow of one of the adapters
+ * error counters; READ.ERROR.LOG.
+ */
+#define SINGLE_STATION 0x4000 /* Adapter is the only station on the
+ * ring.
+ */
+#define RING_RECOVERY 0x2000 /* Claim token MAC frames on the ring;
+ * reset after ring purge frame.
+ */
+
+#define ADAPTER_CLOSED (LOBE_WIRE_FAULT | AUTO_REMOVAL_ERROR |\
+ REMOVE_RECEIVED)
+
+/* Adapter_check_block.Status field bit assignments: */
+#define DIO_PARITY 0x8000 /* Adapter detects bad parity
+ * through direct I/O access.
+ */
+#define DMA_READ_ABORT 0x4000 /* Aborting DMA read operation
+ * from system Parm[0]: 0=timeout,
+ * 1=parity error, 2=bus error;
+ * Parm[1]: 32 bit pointer to host
+ * system address at failure.
+ */
+#define DMA_WRITE_ABORT 0x2000 /* Aborting DMA write operation
+ * to system. (parameters analogous to
+ * DMA_READ_ABORT)
+ */
+#define ILLEGAL_OP_CODE 0x1000 /* Illegal operation code in the
+ * the adapters firmware Parm[0]-2:
+ * communications processor registers
+ * R13-R15.
+ */
+#define PARITY_ERRORS 0x0800 /* Adapter detects internal bus
+ * parity error.
+ */
+#define RAM_DATA_ERROR 0x0080 /* Valid only during RAM testing;
+ * RAM data error Parm[0-1]: 32 bit
+ * pointer to RAM location.
+ */
+#define RAM_PARITY_ERROR 0x0040 /* Valid only during RAM testing;
+ * RAM parity error Parm[0-1]: 32 bit
+ * pointer to RAM location.
+ */
+#define RING_UNDERRUN 0x0020 /* Internal DMA underrun when
+ * transmitting onto ring.
+ */
+#define INVALID_IRQ 0x0008 /* Unrecognized interrupt generated
+ * internal to adapter Parm[0-2]:
+ * adapter register R13-R15.
+ */
+#define INVALID_ERROR_IRQ 0x0004 /* Unrecognized error interrupt
+ * generated Parm[0-2]: adapter register
+ * R13-R15.
+ */
+#define INVALID_XOP 0x0002 /* Unrecognized XOP request in
+ * communication processor Parm[0-2]:
+ * adapter register R13-R15.
+ */
+#define CHECKADDR 0x05E0 /* Adapter check status information
+ * address offset.
+ */
+#define ROM_PAGE_0 0x0000 /* Adapter ROM page 0. */
+
+/*
+ * RECEIVE.STATUS interrupt result SSB values: (high-low)
+ * (RECEIVE_COMPLETE field bit definitions in SSB.Parm[0])
+ */
+#define RX_COMPLETE 0x0080 /* SSB.Parm[0]; SSB.Parm[1]: 32
+ * bit pointer to last RPL.
+ */
+#define RX_SUSPENDED 0x0040 /* SSB.Parm[0]; SSB.Parm[1]: 32
+ * bit pointer to RPL with odd
+ * forward pointer.
+ */
+
+/* Valid receive CSTAT: */
+#define RX_FRAME_CONTROL_BITS (RX_VALID | RX_START_FRAME | RX_END_FRAME | \
+ RX_FRAME_COMPLETE)
+#define VALID_SINGLE_BUFFER_FRAME (RX_START_FRAME | RX_END_FRAME | \
+ RX_FRAME_COMPLETE)
+
+typedef enum SKB_STAT SKB_STAT;
+enum SKB_STAT {
+ SKB_UNAVAILABLE,
+ SKB_DMA_DIRECT,
+ SKB_DATA_COPY
+};
+
+/* Receive Parameter List (RPL) The length of the RPLs has to be initialized
+ * in the OPL. (OPEN parameter list)
+ */
+#define RPL_NUM 3
+
+#define RX_FRAG_NUM 1 /* Maximal number of used fragments in one RPL.
+ * (up to firmware v2.24: 3, now: up to 9)
+ */
+
+#pragma pack(1)
+typedef struct s_RPL RPL;
+struct s_RPL { /* Receive Parameter List */
+ u_int32_t NextRPLAddr; /* Pointer to next RPL in chain
+ * (normalized = physical 32 bit
+ * address) if pointer is odd: this
+ * is last RPL. Pointing to itself can
+ * cause problems!
+ */
+ volatile u_int16_t Status; /* Set by creation of Receive Parameter
+ * List RECEIVE_CSTAT_COMPLETE set by
+ * adapter in lists that start or end
+ * a frame.
+ */
+ volatile u_int16_t FrameSize; /* Number of bytes received as a
+ * frame including AC/FC, Destination,
+ * Source, Routing field not including
+ * CRC, FS (Frame Status), End Delimiter
+ * (valid only if START_FRAME bit in
+ * CSTAT nonzero) must not be zero in
+ * any list; maximum value: (BUFFER_SIZE
+ * - 8) * TX_BUF_MAX sum of DataCount
+ * values in FragmentList must equal
+ * Frame_Size value in START_FRAME TPL!
+ * frame data fragment list
+ */
+
+ /* TPL/RPL size in OPEN parameter list depending on maximal numbers
+ * of fragments used in one parameter list.
+ */
+ Fragment FragList[RX_FRAG_NUM]; /* Maximum: nine frame fragments in
+ * one TPL. Actual version of firmware:
+ * 9 fragments possible.
+ */
+#pragma pack()
+
+ /* Special proprietary data and precalculations. */
+ RPL *NextRPLPtr; /* Logical pointer to next RPL in chain. */
+ unsigned char *MData;
+ struct sk_buff *Skb;
+ SKB_STAT SkbStat;
+ int RPLIndex;
+ dma_addr_t DMABuff; /* DMA IO bus address from pci_map */
+};
+
+/* Information that need to be kept for each board. */
+typedef struct net_local {
+#pragma pack(1)
+ IPB ipb; /* Initialization Parameter Block. */
+ SCB scb; /* System Command Block: system to adapter
+ * communication.
+ */
+ SSB ssb; /* System Status Block: adapter to system
+ * communication.
+ */
+ OPB ocpl; /* Open Options Parameter Block. */
+
+ ERRORTAB errorlogtable; /* Adapter statistic error counters.
+ * (read from adapter memory)
+ */
+ unsigned char ProductID[PROD_ID_SIZE + 1]; /* Product ID */
+#pragma pack()
+
+ TPL Tpl[TPL_NUM];
+ TPL *TplFree;
+ TPL *TplBusy;
+ unsigned char LocalTxBuffers[TPL_NUM][DEFAULT_PACKET_SIZE];
+
+ RPL Rpl[RPL_NUM];
+ RPL *RplHead;
+ RPL *RplTail;
+ unsigned char LocalRxBuffers[RPL_NUM][DEFAULT_PACKET_SIZE];
+
+ struct pci_dev *pdev;
+ int DataRate;
+ unsigned char ScbInUse;
+ unsigned short CMDqueue;
+
+ unsigned long AdapterOpenFlag:1;
+ unsigned long AdapterVirtOpenFlag:1;
+ unsigned long OpenCommandIssued:1;
+ unsigned long TransmitCommandActive:1;
+ unsigned long TransmitHaltScheduled:1;
+ unsigned long HaltInProgress:1;
+ unsigned long LobeWireFaultLogged:1;
+ unsigned long ReOpenInProgress:1;
+ unsigned long Sleeping:1;
+
+ unsigned long LastOpenStatus;
+ unsigned short CurrentRingStatus;
+ unsigned long MaxPacketSize;
+
+ unsigned long StartTime;
+ unsigned long LastSendTime;
+
+ struct tr_statistics MacStat; /* MAC statistics structure */
+
+ unsigned long dmalimit; /* the max DMA address (ie, ISA) */
+ dma_addr_t dmabuffer; /* the DMA bus address corresponding to
+ priv. Might be different from virt_to_bus()
+ for architectures with IO MMU (Alpha) */
+
+ struct timer_list timer;
+
+ wait_queue_head_t wait_for_tok_int;
+
+ INTPTRS intptrs; /* Internal adapter pointer. Must be read
+ * before OPEN command.
+ */
+ unsigned short (*setnselout)(struct net_device *);
+ unsigned short (*sifreadb)(struct net_device *, unsigned short);
+ void (*sifwriteb)(struct net_device *, unsigned short, unsigned short);
+ unsigned short (*sifreadw)(struct net_device *, unsigned short);
+ void (*sifwritew)(struct net_device *, unsigned short, unsigned short);
+
+ spinlock_t lock; /* SMP protection */
+ void *tmspriv;
+} NET_LOCAL;
+
+#endif /* __KERNEL__ */
+#endif /* __LINUX_TMS380TR_H */
diff --git a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c
new file mode 100644
index 00000000000..37ddb5c2bec
--- /dev/null
+++ b/drivers/net/tokenring/tmspci.c
@@ -0,0 +1,267 @@
+/*
+ * tmspci.c: A generic network driver for TMS380-based PCI token ring cards.
+ *
+ * Written 1999 by Adam Fritzler
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * This driver module supports the following cards:
+ * - SysKonnect TR4/16(+) PCI (SK-4590)
+ * - SysKonnect TR4/16 PCI (SK-4591)
+ * - Compaq TR 4/16 PCI
+ * - Thomas-Conrad TC4048 4/16 PCI
+ * - 3Com 3C339 Token Link Velocity
+ *
+ * Maintainer(s):
+ * AF Adam Fritzler mid@auk.cx
+ *
+ * Modification History:
+ * 30-Dec-99 AF Split off from the tms380tr driver.
+ * 22-Jan-00 AF Updated to use indirect read/writes
+ * 23-Nov-00 JG New PCI API, cleanups
+ *
+ * TODO:
+ * 1. See if we can use MMIO instead of port accesses
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/trdevice.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "tms380tr.h"
+
+static char version[] __devinitdata =
+"tmspci.c: v1.02 23/11/2000 by Adam Fritzler\n";
+
+#define TMS_PCI_IO_EXTENT 32
+
+struct card_info {
+ unsigned char nselout[2]; /* NSELOUT vals for 4mb([0]) and 16mb([1]) */
+ char *name;
+};
+
+static struct card_info card_info_table[] = {
+ { {0x03, 0x01}, "Compaq 4/16 TR PCI"},
+ { {0x03, 0x01}, "SK NET TR 4/16 PCI"},
+ { {0x03, 0x01}, "Thomas-Conrad TC4048 PCI 4/16"},
+ { {0x03, 0x01}, "3Com Token Link Velocity"},
+};
+
+static struct pci_device_id tmspci_pci_tbl[] = {
+ { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TOKENRING, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_TR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
+ { PCI_VENDOR_ID_TCONRAD, PCI_DEVICE_ID_TCONRAD_TOKENRING, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
+ { PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C339, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, tmspci_pci_tbl);
+
+MODULE_LICENSE("GPL");
+
+static void tms_pci_read_eeprom(struct net_device *dev);
+static unsigned short tms_pci_setnselout_pins(struct net_device *dev);
+
+static unsigned short tms_pci_sifreadb(struct net_device *dev, unsigned short reg)
+{
+ return inb(dev->base_addr + reg);
+}
+
+static unsigned short tms_pci_sifreadw(struct net_device *dev, unsigned short reg)
+{
+ return inw(dev->base_addr + reg);
+}
+
+static void tms_pci_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg)
+{
+ outb(val, dev->base_addr + reg);
+}
+
+static void tms_pci_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg)
+{
+ outw(val, dev->base_addr + reg);
+}
+
+static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ static int versionprinted;
+ struct net_device *dev;
+ struct net_local *tp;
+ int i, ret;
+ unsigned int pci_irq_line;
+ unsigned long pci_ioaddr;
+ struct card_info *cardinfo = &card_info_table[ent->driver_data];
+
+ if (versionprinted++ == 0)
+ printk("%s", version);
+
+ if (pci_enable_device(pdev))
+ return -EIO;
+
+ /* Remove I/O space marker in bit 0. */
+ pci_irq_line = pdev->irq;
+ pci_ioaddr = pci_resource_start (pdev, 0);
+
+ /* At this point we have found a valid card. */
+ dev = alloc_trdev(sizeof(struct net_local));
+ if (!dev)
+ return -ENOMEM;
+ SET_MODULE_OWNER(dev);
+
+ if (!request_region(pci_ioaddr, TMS_PCI_IO_EXTENT, dev->name)) {
+ ret = -EBUSY;
+ goto err_out_trdev;
+ }
+
+ ret = request_irq(pdev->irq, tms380tr_interrupt, SA_SHIRQ,
+ dev->name, dev);
+ if (ret)
+ goto err_out_region;
+
+ dev->base_addr = pci_ioaddr;
+ dev->irq = pci_irq_line;
+ dev->dma = 0;
+
+ printk("%s: %s\n", dev->name, cardinfo->name);
+ printk("%s: IO: %#4lx IRQ: %d\n",
+ dev->name, dev->base_addr, dev->irq);
+
+ tms_pci_read_eeprom(dev);
+
+ printk("%s: Ring Station Address: ", dev->name);
+ printk("%2.2x", dev->dev_addr[0]);
+ for (i = 1; i < 6; i++)
+ printk(":%2.2x", dev->dev_addr[i]);
+ printk("\n");
+
+ ret = tmsdev_init(dev, PCI_MAX_ADDRESS, pdev);
+ if (ret) {
+ printk("%s: unable to get memory for dev->priv.\n", dev->name);
+ goto err_out_irq;
+ }
+
+ tp = dev->priv;
+ tp->setnselout = tms_pci_setnselout_pins;
+
+ tp->sifreadb = tms_pci_sifreadb;
+ tp->sifreadw = tms_pci_sifreadw;
+ tp->sifwriteb = tms_pci_sifwriteb;
+ tp->sifwritew = tms_pci_sifwritew;
+
+ memcpy(tp->ProductID, cardinfo->name, PROD_ID_SIZE + 1);
+
+ tp->tmspriv = cardinfo;
+
+ dev->open = tms380tr_open;
+ dev->stop = tms380tr_close;
+ pci_set_drvdata(pdev, dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ ret = register_netdev(dev);
+ if (ret)
+ goto err_out_tmsdev;
+
+ return 0;
+
+err_out_tmsdev:
+ pci_set_drvdata(pdev, NULL);
+ tmsdev_term(dev);
+err_out_irq:
+ free_irq(pdev->irq, dev);
+err_out_region:
+ release_region(pci_ioaddr, TMS_PCI_IO_EXTENT);
+err_out_trdev:
+ free_netdev(dev);
+ return ret;
+}
+
+/*
+ * Reads MAC address from adapter RAM, which should've read it from
+ * the onboard ROM.
+ *
+ * Calling this on a board that does not support it can be a very
+ * dangerous thing. The Madge board, for instance, will lock your
+ * machine hard when this is called. Luckily, its supported in a
+ * separate driver. --ASF
+ */
+static void tms_pci_read_eeprom(struct net_device *dev)
+{
+ int i;
+
+ /* Address: 0000:0000 */
+ tms_pci_sifwritew(dev, 0, SIFADX);
+ tms_pci_sifwritew(dev, 0, SIFADR);
+
+ /* Read six byte MAC address data */
+ dev->addr_len = 6;
+ for(i = 0; i < 6; i++)
+ dev->dev_addr[i] = tms_pci_sifreadw(dev, SIFINC) >> 8;
+}
+
+static unsigned short tms_pci_setnselout_pins(struct net_device *dev)
+{
+ unsigned short val = 0;
+ struct net_local *tp = dev->priv;
+ struct card_info *cardinfo = tp->tmspriv;
+
+ if(tp->DataRate == SPEED_4)
+ val |= cardinfo->nselout[0]; /* Set 4Mbps */
+ else
+ val |= cardinfo->nselout[1]; /* Set 16Mbps */
+ return val;
+}
+
+static void __devexit tms_pci_detach (struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ if (!dev)
+ BUG();
+ unregister_netdev(dev);
+ release_region(dev->base_addr, TMS_PCI_IO_EXTENT);
+ free_irq(dev->irq, dev);
+ tmsdev_term(dev);
+ free_netdev(dev);
+ pci_set_drvdata(pdev, NULL);
+}
+
+static struct pci_driver tms_pci_driver = {
+ .name = "tmspci",
+ .id_table = tmspci_pci_tbl,
+ .probe = tms_pci_attach,
+ .remove = __devexit_p(tms_pci_detach),
+};
+
+static int __init tms_pci_init (void)
+{
+ return pci_register_driver(&tms_pci_driver);
+}
+
+static void __exit tms_pci_rmmod (void)
+{
+ pci_unregister_driver (&tms_pci_driver);
+}
+
+module_init(tms_pci_init);
+module_exit(tms_pci_rmmod);
+
+
+/*
+ * Local variables:
+ * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tmspci.c"
+ * alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tmspci.c"
+ * c-set-style "K&R"
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */