patch-2.4.19 linux-2.4.19/drivers/net/wan/8253x/8253xini.c
Next file: linux-2.4.19/drivers/net/wan/8253x/8253xint.c
Previous file: linux-2.4.19/drivers/net/wan/8253x/8253xdbg.c
Back to the patch index
Back to the overall index
- Lines: 3044
- Date:
Fri Aug 2 17:39:44 2002
- Orig file:
linux-2.4.18/drivers/net/wan/8253x/8253xini.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -urN linux-2.4.18/drivers/net/wan/8253x/8253xini.c linux-2.4.19/drivers/net/wan/8253x/8253xini.c
@@ -0,0 +1,3043 @@
+/* -*- linux-c -*- */
+/*
+ * Copyright (C) 2001 By Joachim Martillo, Telford Tools, Inc.
+ *
+ * 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.
+ *
+ **/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/stddef.h>
+#include <linux/string.h>
+#include <linux/sockios.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <asm/pgtable.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+#include <linux/version.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include "Reg9050.h"
+#include "8253xctl.h"
+#include "ring.h"
+#include "8253x.h"
+#include "crc32dcl.h"
+#include "8253xmcs.h"
+#include "sp502.h"
+
+/* card names */
+
+char *aura_functionality[] =
+{
+ "NR",
+ "AO",
+ "NA",
+ "UN"
+};
+
+char *board_type[] =
+{
+ "unknown",
+ "1020P",
+ "1520P",
+ "2020P",
+ "2520P",
+ "4020P",
+ "4520P",
+ "8020P",
+ "8520P",
+ "SUNSE",
+ "WANMS",
+ "1020C",
+ "1520C",
+ "2020C",
+ "2520C",
+ "4020C",
+ "4520C",
+ "8020C",
+ "8520C",
+};
+
+unsigned int sab8253x_rebootflag = 0;
+
+AURAXX20PARAMS AuraXX20DriverParams; /* loaded at startup */
+ /* from variables below */
+SAB_BOARD *AuraBoardRoot = NULL; /* The order of this list is not important */
+SAB_CHIP *AuraChipRoot = NULL; /* chips grouped by board chip0 before chip1 */
+SAB_PORT *AuraPortRoot = NULL; /* ports grouped by board and by chip, chip0, chip1, etc */
+AURA_CIM *AuraCimRoot = NULL; /* only used for deallocating the cim structures, etc */
+/* CIM stands for Communications Interface Module -- the G.Link logic provided by the Altera parts. */
+
+/* Arrays of lists of boards of each type on a given interrupt */
+SAB_BOARD *AuraBoardESCC2IrqRoot[NUMINTS];
+SAB_BOARD *AuraBoardESCC8IrqRoot[NUMINTS];
+SAB_BOARD *AuraBoardMCSIrqRoot[NUMINTS];
+
+unsigned int NumSab8253xPorts = 0;
+
+unsigned BD1020Pcounter = 0; /* keep count of each board */
+unsigned BD1520Pcounter = 0; /* may change to just keeping count */
+unsigned BD2020Pcounter = 0; /* of the total number of boards */
+unsigned BD2520Pcounter = 0;
+unsigned BD4020Pcounter = 0;
+unsigned BD4520Pcounter = 0;
+unsigned BD8020Pcounter = 0;
+unsigned BD8520Pcounter = 0;
+
+unsigned BD1020CPcounter = 0; /* keep count of each board */
+unsigned BD1520CPcounter = 0; /* may change to just keeping count */
+unsigned BD2020CPcounter = 0; /* of the total number of boards */
+unsigned BD2520CPcounter = 0;
+unsigned BD4020CPcounter = 0;
+unsigned BD4520CPcounter = 0;
+unsigned BD8020CPcounter = 0;
+unsigned BD8520CPcounter = 0;
+
+unsigned BDMCScounter = 0;
+
+
+static int auraXX20n_debug = 0; /* turns on lots of */
+ /* debugging messages*/
+static char* auraXX20n_name = 0;/* set net dev name on command line */
+static char *sab8253xc_name = "sab8253xc";
+static int sab8253xc_major = 0;
+int sab8253xn_listsize = 32; /* recommend descriptor list size */
+int sab8253xn_rbufsize = RXSIZE; /* recommend rbuf list size */
+int sab8253xt_listsize = 256; /* recommend descriptor list size */
+int sab8253xt_rbufsize = 32; /* recommend rbuf list size for tty */
+int sab8253xs_listsize = 64; /* recommend descriptor list size */
+int sab8253xs_rbufsize = RXSIZE; /* recommend rbuf list size */
+int sab8253xc_listsize = 64; /* recommend descriptor list size */
+int sab8253xc_rbufsize = RXSIZE; /* recommend rbuf list size for tty */
+int xx20_minorstart = 128;
+int sab8253x_vendor_id = PCI_VENDOR_ID_AURORATECH;
+int sab8253x_cpci_device_id = PCI_DEVICE_ID_AURORATECH_CPCI;
+int sab8253x_wmcs_device_id = PCI_DEVICE_ID_AURORATECH_WANMS;
+int sab8253x_mpac_device_id = PCI_DEVICE_ID_AURORATECH_MULTI;
+int sab8253x_default_sp502_mode = SP502_RS232_MODE;
+
+MODULE_PARM(sab8253x_vendor_id, "i");
+MODULE_PARM(sab8253x_cpci_device_id, "i");
+MODULE_PARM(sab8253x_wmcs_device_id, "i");
+MODULE_PARM(sab8253x_mpac_device_id, "i");
+MODULE_PARM(sab8253x_default_sp502_mode, "i");
+
+MODULE_PARM(xx20_minorstart, "i");
+MODULE_PARM(sab8253xc_major, "i");
+MODULE_PARM(auraXX20n_debug, "i");
+MODULE_PARM(auraXX20n_name, "s"); /* this and the following for sync */
+MODULE_PARM(sab8253xn_listsize, "i"); /* network driver */
+MODULE_PARM(sab8253xn_rbufsize, "i"); /* network driver */
+MODULE_PARM(sab8253xt_listsize, "i"); /* tty driver */
+MODULE_PARM(sab8253xt_rbufsize, "i"); /* tty driver */
+MODULE_PARM(sab8253xc_listsize, "i"); /* network driver */
+MODULE_PARM(sab8253xc_rbufsize, "i"); /* network driver */
+MODULE_PARM(sab8253xs_listsize, "i"); /* tty driver */
+MODULE_PARM(sab8253xs_rbufsize, "i"); /* tty driver */
+MODULE_PARM(sab8253xc_name, "s");
+
+struct pci_dev *XX20lastpdev = NULL; /* just used for finding all PCI devices */
+static SAB_BOARD *find_ati_multiport_card(void); /* actually implemented */
+static SAB_BOARD *find_ati_cpci_card(void); /* to be done */
+static SAB_BOARD *find_ati_wanms_card(void); /* to be done */
+
+#if (!defined(MODULE)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0))
+ /* unpleasantness for 2.2 kernels
+ * and probe illogic */
+
+ /* The LRP project is still working on
+ 2.2.* kernels but I suspect
+ that initially we will see more
+ purchases for complete Linux
+ machines using 2.4.*, LRP
+ machines tend to be underpowered
+ and have a paucity of PCI slots
+ */
+
+unsigned int do_probe = 1;
+#endif
+
+ /* One could argue that these could be in */
+ /* the 8253xnet.c file but they are fairly */
+ /* intimately involved with initialization.*/
+struct net_device *Sab8253xRoot = NULL;
+
+struct net_device auraXX20n_prototype = /* used for the network device */
+{
+ "8253x0",
+ 0, 0, 0, 0,
+ 0x000,
+ -1, /* bad irq */
+ 0, 0, 0,
+ NULL,
+ sab8253xn_init /* network driver initialization */
+};
+
+struct file_operations sab8253xc_fops =
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0))
+ NULL,
+#endif
+ NULL, /* llseek */
+ sab8253xc_read, /* read */
+ sab8253xc_write, /* write */
+ NULL, /* readdir */
+ sab8253xc_poll, /* poll */
+ sab8253xc_ioctl, /* ioctl */
+ NULL, /* mmap */
+ sab8253xc_open, /* open */
+ NULL, /* flush */
+ sab8253xc_release, /* release */
+ NULL, /* fsync */
+ sab8253xc_fasync, /* fasync */
+ NULL, /* check_media_change */
+ NULL, /* revalidate */
+ NULL /* lock */
+};
+
+
+/* A few function defined in this file */
+/* These functions are basically functionality */
+/* independent -- they are used with asynchronous ttys */
+/* synchronous ttys, the network device and the */
+/* raw character device */
+
+ /* used for reading and writing ports
+ readw and writew require some reprogramming
+ of the PLX9050
+ */
+static unsigned char aura_readb(struct sab_port *port, unsigned char *reg);
+static unsigned char wmsaura_readb(struct sab_port *port, unsigned char *reg);
+static unsigned short aura_readw(struct sab_port *port, unsigned short *reg);
+static unsigned short wmsaura_readw(struct sab_port *port, unsigned short *reg);
+static void aura_writeb(struct sab_port *port, unsigned char *reg,unsigned char val);
+static void wmsaura_writeb(struct sab_port *port, unsigned char *reg,unsigned char val);
+static void aura_writew(struct sab_port *port, unsigned short *reg,unsigned short val);
+static void wmsaura_writew(struct sab_port *port, unsigned short *reg,unsigned short val);
+
+static void aura_readfifo(struct sab_port *port, unsigned char *buf, unsigned int nbytes);
+static void aura_writefifo(struct sab_port *port);
+
+static void wmsaura_readfifo(struct sab_port *port, unsigned char *buf, unsigned int nbytes);
+static void wmsaura_writefifo(struct sab_port *port);
+
+/* function definitions */
+
+/* [124]X20 type cards */
+static void DisableESCC2Interrupts(SAB_CHIP *chipptr) /* in processing ports may have to disable ints */
+{
+ struct sab82532_async_wr_regs *regs;
+
+ regs = chipptr->c_regs;
+ writeb(0xff,®s->pim); /* All interrupts off */
+ /* Note that regs/->c_regs
+ is set to base reg
+ address, thus taking
+ address or regs->pim
+ gets the address of
+ the PIM register/int mask */
+}
+
+static SAB_CHIP* CreateESCC2(SAB_BOARD *bptr, unsigned int offset)
+{
+ SAB_CHIP *cptr;
+ struct sab82532_async_wr_regs *regs;
+
+ printk(KERN_ALERT
+ "auraXX20n: creating ESCC2 structure on board %p at offset %x.\n",
+ bptr, offset);
+
+ cptr = (SAB_CHIP*) kmalloc(sizeof(SAB_CHIP), GFP_KERNEL);
+ if(cptr == NULL)
+ {
+ printk(KERN_ALERT
+ "auraXX20n: Failed to create ESCC2 structure on board %p at offset %x.\n",
+ bptr, offset);
+ return NULL;
+ }
+ memset(cptr, 0, sizeof(SAB_CHIP));
+ cptr->chip_type = ESCC2;
+ cptr->c_board = bptr;
+ cptr->c_cim = NULL;
+ cptr->c_chipno = (offset ? 1 : 0); /* first or second chip on board */
+ cptr->c_revision =
+ (readb(((char *)bptr->virtbaseaddress2) + offset + SAB85232_REG_VSTR) &
+ SAB82532_VSTR_VN_MASK);
+ cptr->c_nports = 2;
+ cptr->c_portbase = NULL;
+ cptr->next = AuraChipRoot; /* chips are added to chiplist in reverse order */
+ AuraChipRoot = cptr;
+ cptr->next_by_board = bptr->board_chipbase; /* likewise for the local board chiplist */
+ bptr->board_chipbase = cptr;
+ printk(KERN_ALERT "auraXX20n: chip %d on board %p is revision %d.\n",
+ cptr->c_chipno, bptr, cptr->c_revision);
+
+ /* lets set up the generic parallel
+ * port register which is used to
+ * control signaling and other stuff*/
+ /*
+ * SAB82532 (Aurora) 1 8-bit parallel port
+ * To summarize the use of the parallel port:
+ * RS-232
+ * A B I/O descr
+ * P0 P4 output TxClk ctrl
+ * P1 P5 output DTR
+ * P2 P6 input DSR
+ * P3 P7 output 485 control
+ *
+ */
+ /*
+ * Configuring the parallel port
+ */
+
+ regs = (struct sab82532_async_wr_regs *)(((char *)bptr->virtbaseaddress2) + offset);
+
+ DEBUGPRINT((KERN_ALERT "Writing 0x44 to 0x%p + 0x%x for chip %d\n",
+ regs, SAB82532_REG_PCR, cptr->c_chipno));
+
+ writeb(0x44,®s->pcr); /* 2 input bits */
+ writeb(0xff,®s->pim);/* All interrupts off */
+ writeb(0x33,®s->pvr); /* Txclk and DTR low */
+
+ cptr->c_regs = (void*) regs;
+ cptr->int_disable = DisableESCC2Interrupts;
+ return cptr;
+}
+
+static void CreateESCC2Port(SAB_CHIP *cptr, unsigned int portno, unsigned int function)
+{
+ SAB_BOARD *bptr;
+ SAB_PORT *pptr;
+ extern void sab8253x_setup_ttyport(struct sab_port *p_port) ;
+
+ ++NumSab8253xPorts;
+ bptr = cptr->c_board;
+ pptr = (SAB_PORT*) kmalloc(sizeof(SAB_PORT), GFP_KERNEL);
+ if(pptr == NULL)
+ {
+ printk(KERN_ALERT
+ "auraXX20n: Failed to create ESCC2 port structure on chip %p on board %p.\n",
+ cptr, bptr);
+ return;
+ }
+ memset(pptr, 0, sizeof(SAB_PORT));
+ DEBUGPRINT
+ ((KERN_ALERT "Setting up port %d, chipno %d for %s type board number %d.\n",
+ portno, cptr->c_chipno, board_type[bptr->b_type],bptr->board_number));
+ pptr->portno = portno;
+ pptr->chip=cptr;
+ pptr->board=bptr;
+ pptr->open_type=OPEN_NOT;
+ pptr->is_console=0;
+ pptr->regs=
+ (union sab82532_regs *)
+ (((unsigned int)cptr->c_regs) +
+ (portno * SAB82532_REG_SIZE));
+ pptr->type = cptr->c_revision;
+ pptr->function = function;
+
+ /* Simpify reading */
+#define PVR pptr->regs->async_write.pvr
+#define PCR pptr->regs->async_write.pcr
+#define PIM pptr->regs->async_write.pim
+#define ISR0 pptr->regs->async_read.isr0
+#define IMR0 pptr->regs->async_write.imr0
+#define IMR1 pptr->regs->async_write.imr1
+#define PIS pptr->regs->async_read.pis
+#define VSTR pptr->regs->async_read.vstr
+#define STAR pptr->regs->async_read.star
+#define MODE pptr->regs->async_read.mode
+
+ pptr->irq = bptr->b_irq;
+ if(portno == 0)
+ { /* Port A .... */
+ pptr->dsr.reg=(unsigned char *)&(PVR);
+ pptr->dsr.mask=0x04;
+ pptr->dsr.irq=PIS_IDX;
+ pptr->dsr.irqmask=0x04;
+
+ pptr->dtr.reg=(unsigned char *)&(PVR);
+ pptr->dtr.mask=0x02;
+
+ pptr->txclkdir.reg=(unsigned char *)&(PVR);
+ pptr->txclkdir.mask=0x01;
+ }
+ else
+ { /* Port B */
+ pptr->dsr.reg=(unsigned char *)&(PVR);
+ pptr->dsr.mask=0x40;
+ pptr->dsr.irq=PIS_IDX;
+ pptr->dsr.irqmask=0x40;
+
+ pptr->dtr.reg=(unsigned char *)&(PVR);
+ pptr->dtr.mask=0x20;
+
+ pptr->txclkdir.reg=(unsigned char *)&(PVR);
+ pptr->txclkdir.mask=0x10;
+ }
+ pptr->dsr.inverted=1;
+ pptr->dsr.cnst = 0;
+ pptr->dtr.inverted=1;
+ pptr->dtr.cnst = 0;
+ pptr->txclkdir.inverted=1;
+
+ pptr ->dcd.reg =(unsigned char *) &(VSTR);
+
+ DEBUGPRINT((KERN_ALERT "cd register set to 0x%p\n", pptr ->dcd.reg));
+
+ pptr->dcd.mask = SAB82532_VSTR_CD;
+ pptr->dcd.inverted = 1;
+ pptr->dcd.irq=ISR0_IDX;
+ pptr->dcd.irqmask=SAB82532_ISR0_CDSC;
+ pptr->dcd.cnst = 0;
+
+ pptr->cts.reg = (unsigned char *)&(STAR);
+ pptr->cts.mask = SAB82532_STAR_CTS;
+ pptr->cts.inverted = 0;
+ pptr->cts.irq=ISR1_IDX;
+ pptr->cts.irqmask=SAB82532_ISR1_CSC;
+ pptr->cts.cnst = 0;
+
+ pptr->rts.reg = (unsigned char *)&(MODE);
+ pptr->rts.mask = SAB82532_MODE_FRTS;
+ pptr->rts.inverted = 1;
+ pptr->rts.cnst = SAB82532_MODE_RTS;
+
+
+ /* Set the read and write function */
+ pptr->readbyte=aura_readb;
+ pptr->readword=aura_readw;
+ pptr->writebyte=aura_writeb;
+ pptr->writeword=aura_writew;
+ pptr->readfifo=aura_readfifo;
+ pptr->writefifo=aura_writefifo;
+
+ sab8253x_setup_ttyport(pptr); /* asynchronous */
+ /* ttys are default, basic */
+ /* initialization, everything */
+ /* else works as a modification */
+ /* thereof */
+
+ pptr->next = AuraPortRoot;
+ AuraPortRoot = pptr;
+ pptr->next_by_chip = cptr->c_portbase;
+ cptr->c_portbase = pptr;
+ pptr->next_by_board = bptr->board_portbase;
+ bptr->board_portbase = pptr;
+}
+
+/* 8x20 type functions */
+
+static void DisableESCC8Interrupts(SAB_CHIP *chipptr)
+{
+ unsigned int regbase; /* a lot more to do for ESCC8 */
+
+ regbase = (unsigned int) chipptr->c_regs;
+ writeb(0xff,((unsigned char *)regbase) + SAB82538_REG_PIM_A); /* All interrupts off */
+ writeb(0xff,((unsigned char *)regbase) + SAB82538_REG_PIM_B); /* All interrupts off */
+ writeb(0xff,((unsigned char *)regbase) + SAB82538_REG_PIM_C); /* All interrupts off */
+ writeb(0xff,((unsigned char *)regbase) + SAB82538_REG_PIM_D); /* All interrupts off */
+}
+
+static SAB_CHIP* CreateESCC8(SAB_BOARD *bptr, unsigned int offset)
+{
+ SAB_CHIP *cptr;
+ unsigned int regbase;
+
+ printk(KERN_ALERT
+ "auraXX20n: creating ESCC8 structure on board %p at offset %x.\n",
+ bptr, offset);
+
+ cptr = (SAB_CHIP*) kmalloc(sizeof(SAB_CHIP), GFP_KERNEL);
+ if(cptr == NULL)
+ {
+ printk(KERN_ALERT
+ "auraXX20n: Failed to create ESCC8 structure on board %p at offset %x.\n",
+ bptr, offset);
+ return NULL;
+ }
+ memset(cptr, 0, sizeof(SAB_CHIP));
+ cptr->chip_type = ESCC8;
+ cptr->c_board = bptr;
+ cptr->c_cim = NULL;
+ cptr->c_chipno = (offset ? 1 : 0); /* no card actually has 2 ESCC8s on it */
+ cptr->c_revision =
+ (readb(((char *)bptr->virtbaseaddress2) + offset + SAB85232_REG_VSTR) &
+ SAB82532_VSTR_VN_MASK);
+ cptr->c_nports = 8;
+ cptr->c_portbase = NULL; /* used for the list of ports associated
+ with this chip
+ */
+ cptr->next = AuraChipRoot;
+ AuraChipRoot = cptr;
+ cptr->next_by_board = bptr->board_chipbase;
+ bptr->board_chipbase = cptr;
+ printk(KERN_ALERT "auraXX20n: chip %d on board %p is revision %d.\n",
+ cptr->c_chipno, bptr, cptr->c_revision);
+
+ /* lets set up the generic parallel
+ * port register which is used to
+ * control signaling and other stuff*/
+
+ /* SAB82538 4 8-bits parallel ports
+ * To summarize the use of the parallel port:
+ * RS-232
+ * Parallel port A -- TxClkdir control (output) ports 0 - 7
+ * Parallel port B -- DTR (output) ports 0 - 7
+ * Parallel port C -- DSR (input) ports 0 - 7
+ * Parallel port D -- driver power down (output) drivers 0 - 3
+ *
+ * Note port D is not used on recent boards
+ */
+
+ regbase = (unsigned int)(((char *)bptr->virtbaseaddress2) + offset);
+
+ DEBUGPRINT((KERN_ALERT "Setting up parallel port A (0x%x), 0x%x, 0x%x, 0x%x\n", regbase,
+ SAB82538_REG_PCR_A, SAB82538_REG_PIM_A, SAB82538_REG_PVR_A));
+
+ /* Configuring Parallel Port A (Clkdir)*/
+ writeb(0x0,((unsigned char *)regbase) + SAB82538_REG_PCR_A); /* All output bits */
+ writeb(0xff,((unsigned char *)regbase) + SAB82538_REG_PIM_A); /* All interrupts off */
+ writeb(0xff,((unsigned char *)regbase) + SAB82538_REG_PVR_A); /* All low */
+
+ DEBUGPRINT((KERN_ALERT "Setting up parallel port B (0x%x), 0x%x, 0x%x, 0x%x\n", regbase,
+ SAB82538_REG_PCR_B,SAB82538_REG_PIM_B,SAB82538_REG_PVR_B));
+
+ writeb(0x0,((unsigned char *)regbase) + SAB82538_REG_PCR_B); /* All output bits */
+ writeb(0xff,((unsigned char *)regbase) + SAB82538_REG_PIM_B); /* All interrupts off */
+ writeb(0xff,((unsigned char *)regbase) + SAB82538_REG_PVR_B); /* All low */
+
+ DEBUGPRINT((KERN_ALERT "Setting up parallel port C (0x%x), 0x%x, 0x%x, 0x%x\n", regbase,
+ SAB82538_REG_PCR_C, SAB82538_REG_PIM_C, SAB82538_REG_PVR_C));
+
+ writeb(0xff,((unsigned char *)regbase) + SAB82538_REG_PCR_C); /* All intput bits */
+ writeb(0xff,((unsigned char *)regbase) + SAB82538_REG_PIM_C); /* All interrupts off */
+ /* don't set port value register on input register */
+
+ /* Configuring Parallel Port D */
+
+ DEBUGPRINT((KERN_ALERT "Setting up parallel port D (0x%x), 0x%x, 0x%x, 0x%x\n", regbase,
+ SAB82538_REG_PCR_D, SAB82538_REG_PIM_D, SAB82538_REG_PVR_D));
+ writeb(0x0f,((unsigned char *)regbase) + SAB82538_REG_PCR_D); /* 4 input bits */
+ writeb(0xff,((unsigned char *)regbase) + SAB82538_REG_PIM_D); /* All interrupts off */
+ /* don't set port value register on input register */
+
+ /* The priority rotation thing */
+
+ DEBUGPRINT((KERN_ALERT "Setting IVA (0x%x + 0x%x = 0x%x\n", regbase,
+ SAB82532_REG_IVA, regbase + SAB82532_REG_IVA));
+
+ writeb(SAB82538_IVA_ROT, ((unsigned char *)regbase) + SAB82532_REG_IVA);
+
+ cptr->c_regs = (void*) regbase;
+ cptr->int_disable = DisableESCC8Interrupts;
+ return cptr;
+}
+
+static void DisableESCC8InterruptsFromCIM(SAB_CHIP *chipptr)
+{
+ unsigned int regbase; /* a lot more to do for ESCC8 */
+
+ regbase = (unsigned int) chipptr->c_regs;
+ writeb(0xff,((unsigned char *)regbase) + (CIMCMD_WRREGB | SAB82538_REG_PIM_A)); /* All interrupts off */
+ writeb(0xff,((unsigned char *)regbase) + (CIMCMD_WRREGB | SAB82538_REG_PIM_B)); /* All interrupts off */
+ writeb(0xff,((unsigned char *)regbase) + (CIMCMD_WRREGB | SAB82538_REG_PIM_C)); /* All interrupts off */
+ writeb(0xff,((unsigned char *)regbase) + (CIMCMD_WRREGB | SAB82538_REG_PIM_D)); /* All interrupts off */
+}
+
+static void CreateESCC8Port(SAB_CHIP *cptr, unsigned int portno, unsigned int function)
+{
+ SAB_BOARD *bptr;
+ SAB_PORT *pptr;
+ extern void sab8253x_setup_ttyport(struct sab_port *p_port) ;
+
+ ++NumSab8253xPorts;
+ bptr = cptr->c_board;
+ pptr = (SAB_PORT*) kmalloc(sizeof(SAB_PORT), GFP_KERNEL);
+ if(pptr == NULL)
+ {
+ printk(KERN_ALERT
+ "auraXX20n: Failed to create ESCC2 port structure on chip %p on board %p.\n",
+ cptr, bptr);
+ return;
+ }
+ memset(pptr, 0, sizeof(SAB_PORT));
+ DEBUGPRINT
+ ((KERN_ALERT "Setting up port %d, chipno %d for %s type board number %d.\n",
+ portno, cptr->c_chipno, board_type[bptr->b_type],bptr->board_number));
+ pptr->portno = portno;
+ pptr->chip=cptr;
+ pptr->board=bptr;
+ pptr->open_type=OPEN_NOT;
+ pptr->is_console=0;
+ pptr->regs=
+ (union sab82532_regs *)
+ (((unsigned int)cptr->c_regs) +
+ (portno * SAB82538_REG_SIZE));
+ pptr->type = cptr->c_revision;
+ pptr->function = function;
+
+ pptr->irq = bptr->b_irq;
+
+ pptr->dsr.reg = ((unsigned char *)cptr->c_regs) + SAB82538_REG_PVR_C;
+ pptr->dsr.mask = 0x1 << portno;
+ pptr->dsr.inverted = 1;
+ pptr->dsr.irq=PIS_IDX; /* need to check this constant */
+ pptr->dsr.irqmask=0x1 << portno;
+ pptr->dsr.cnst = 0;
+
+ pptr->txclkdir.reg = ((unsigned char *)cptr->c_regs) + SAB82538_REG_PVR_A;
+ pptr->txclkdir.mask = 0x1 << portno;
+ /* NOTE: Early 8 ports boards had different tx clkdir sense */
+ pptr->txclkdir.inverted = 1;
+
+ pptr->dtr.reg = ((unsigned char *)cptr->c_regs) + SAB82538_REG_PVR_B;
+ pptr->dtr.mask = 0x1 << portno;
+ pptr->dtr.inverted = 1;
+ pptr->dtr.cnst = 0;
+
+ pptr ->dcd.reg = (unsigned char *)&(VSTR);
+
+ DEBUGPRINT((KERN_ALERT "cd register set to 0x%p\n", pptr ->dcd.reg));
+
+ pptr->dcd.mask = SAB82532_VSTR_CD;
+ pptr->dcd.inverted = 1;
+ pptr->dcd.irq=ISR0_IDX;
+ pptr->dcd.irqmask=SAB82532_ISR0_CDSC;
+ pptr->dcd.cnst = 0;
+
+ pptr->cts.reg = (unsigned char *)&(STAR);
+ pptr->cts.mask = SAB82532_STAR_CTS;
+ pptr->cts.inverted = 0;
+ pptr->cts.irq=ISR1_IDX;
+ pptr->cts.irqmask=SAB82532_ISR1_CSC;
+ pptr->cts.cnst = 0;
+
+ pptr->rts.reg = (unsigned char *)&(MODE);
+ pptr->rts.mask = SAB82532_MODE_FRTS;
+ pptr->rts.inverted = 1;
+ pptr->rts.cnst = SAB82532_MODE_RTS;
+
+
+ /* Set the read and write function */
+ pptr->readbyte=aura_readb;
+ pptr->readword=aura_readw;
+ pptr->writebyte=aura_writeb;
+ pptr->writeword=aura_writew;
+ pptr->readfifo=aura_readfifo;
+ pptr->writefifo=aura_writefifo;
+
+ sab8253x_setup_ttyport(pptr); /* asynchronous */
+ /* ttys are default, basic */
+ /* initialization, everything */
+ /* else works as a modification */
+ /* thereof */
+
+ pptr->next = AuraPortRoot;
+ AuraPortRoot = pptr;
+ pptr->next_by_chip = cptr->c_portbase;
+ cptr->c_portbase = pptr;
+ pptr->next_by_board = bptr->board_portbase;
+ bptr->board_portbase = pptr;
+}
+
+/* Multichannel server functions */
+
+static SAB_CHIP* CreateESCC8fromCIM(SAB_BOARD *bptr, AURA_CIM *cim, unsigned int chipno)
+{
+ SAB_CHIP *cptr;
+ unsigned int regbase;
+
+ printk(KERN_ALERT
+ "auraXX20n: creating ESCC8 %d structure on board %p from cim %p.\n",
+ chipno, bptr, cim);
+
+ cptr = (SAB_CHIP*) kmalloc(sizeof(SAB_CHIP), GFP_KERNEL);
+ if(cptr == NULL)
+ {
+ printk(KERN_ALERT
+ "auraXX20n: Failed to create ESCC8 structure %d on board %p at from cim %p.\n",
+ chipno, bptr, cim);
+ return NULL;
+ }
+
+ memset(cptr, 0, sizeof(SAB_CHIP));
+ cptr->chip_type = ESCC8;
+ cptr->c_board = bptr;
+ cptr->c_cim = cim;
+ cptr->c_chipno = chipno;
+ cptr->c_revision =
+ (readb((unsigned char *) (bptr->CIMCMD_REG +
+ (CIMCMD_RDREGB | (((chipno*8) << 6) | SAB85232_REG_VSTR))))
+ & SAB82532_VSTR_VN_MASK);
+ cptr->c_nports = 8;
+ cptr->c_portbase = NULL; /* used for the list of ports associated
+ with this chip
+ */
+ cptr->next = AuraChipRoot;
+ AuraChipRoot = cptr;
+ cptr->next_by_board = bptr->board_chipbase;
+ bptr->board_chipbase = cptr;
+
+ cptr->next_by_cim = cim->ci_chipbase;
+ cim->ci_chipbase = cptr;
+
+ printk(KERN_ALERT "auraXX20n: chip %d on board %p is revision %d.\n",
+ cptr->c_chipno, bptr, cptr->c_revision);
+
+ /* lets set up the generic parallel
+ * port register which is used to
+ * control signaling and other stuff*/
+
+ /* SAB82538 4 8-bits parallel ports
+ * To summarize the use of the parallel port:
+ * RS-232
+ * Parallel port A -- TxClkdir control (output) ports 0 - 7
+ * Parallel port B -- DTR (output) ports 0 - 7
+ * Parallel port C -- DSR (input) ports 0 - 7
+ * Parallel port D -- driver power down (output) drivers 0 - 3
+ *
+ * Note port D is not used on recent boards
+ */
+
+ regbase = (unsigned int)
+ (bptr->CIMCMD_REG + (0 | (((chipno*8) << 6) | 0))); /* need to add in RDB/WRB cmd bits
+ * and reg offset (> 32) */
+
+ DEBUGPRINT((KERN_ALERT "Setting up parallel port A (0x%x), 0x%x, 0x%x, 0x%x\n", regbase,
+ SAB82538_REG_PCR_A, SAB82538_REG_PIM_A, SAB82538_REG_PVR_A));
+
+ /* Configuring Parallel Port A (Clkdir)*/
+ writeb(0x00,((unsigned char *)regbase) + (CIMCMD_WRREGB | SAB82538_REG_PCR_A)); /* All output bits */
+ writeb(0xff,((unsigned char *)regbase) + (CIMCMD_WRREGB | SAB82538_REG_PIM_A)); /* All interrupts off */
+ writeb(0xff,((unsigned char *)regbase) + (CIMCMD_WRREGB | SAB82538_REG_PVR_A)); /* All low */
+
+ DEBUGPRINT((KERN_ALERT "Setting up parallel port B (0x%x), 0x%x, 0x%x, 0x%x\n", regbase,
+ SAB82538_REG_PCR_B,SAB82538_REG_PIM_B,SAB82538_REG_PVR_B));
+
+ writeb(0x00,((unsigned char *)regbase) + (CIMCMD_WRREGB | SAB82538_REG_PCR_B)); /* All output bits */
+ writeb(0xff,((unsigned char *)regbase) + (CIMCMD_WRREGB | SAB82538_REG_PIM_B)); /* All interrupts off */
+ writeb(0xff,((unsigned char *)regbase) + (CIMCMD_WRREGB | SAB82538_REG_PVR_B)); /* All low */
+
+ DEBUGPRINT((KERN_ALERT "Setting up parallel port C (0x%x), 0x%x, 0x%x, 0x%x\n", regbase,
+ SAB82538_REG_PCR_C, SAB82538_REG_PIM_C, SAB82538_REG_PVR_C));
+
+ writeb(0xff,((unsigned char *)regbase) + (CIMCMD_WRREGB | SAB82538_REG_PCR_C)); /* All intput bits */
+ writeb(0xff,((unsigned char *)regbase) + (CIMCMD_WRREGB | SAB82538_REG_PIM_C)); /* All interrupts off */
+ /* don't set port value register on input register */
+
+ /* Configuring Parallel Port D */
+
+ DEBUGPRINT((KERN_ALERT "Setting up parallel port D (0x%x), 0x%x, 0x%x, 0x%x\n", regbase,
+ SAB82538_REG_PCR_D, SAB82538_REG_PIM_D, SAB82538_REG_PVR_D));
+ writeb(0x0f,((unsigned char *)regbase) + (CIMCMD_WRREGB | SAB82538_REG_PCR_D)); /* 4 input bits */
+ writeb(0xff,((unsigned char *)regbase) + (CIMCMD_WRREGB | SAB82538_REG_PIM_D)); /* All interrupts off */
+ /* don't set port value register on input register */
+
+ /* The priority rotation thing */
+
+ DEBUGPRINT((KERN_ALERT "Setting IVA (0x%x + 0x%x = 0x%x\n", regbase,
+ SAB82532_REG_IVA, regbase + SAB82532_REG_IVA));
+
+ writeb(SAB82538_IVA_ROT, ((unsigned char *)regbase) + (CIMCMD_WRREGB | SAB82532_REG_IVA));
+ writeb(0, ((unsigned char *)regbase) + (CIMCMD_WRREGB | SAB82532_REG_IPC));
+
+ cptr->c_regs = (void*) regbase;
+ cptr->int_disable = DisableESCC8InterruptsFromCIM;
+ return cptr;
+}
+
+static void CreateESCC8PortWithCIM(SAB_CHIP *cptr, unsigned int portno,
+ AURA_CIM *cim, unsigned flag)
+{
+ SAB_BOARD *bptr;
+ SAB_PORT *pptr;
+ extern void sab8253x_setup_ttyport(struct sab_port *p_port) ;
+
+ ++NumSab8253xPorts;
+ bptr = cptr->c_board;
+ pptr = (SAB_PORT*) kmalloc(sizeof(SAB_PORT), GFP_KERNEL);
+ if(pptr == NULL)
+ {
+ printk(KERN_ALERT
+ "auraXX20n: Failed to create ESCC2 port structure on chip %p on board %p.\n",
+ cptr, bptr);
+ return;
+ }
+ memset(pptr, 0, sizeof(SAB_PORT));
+ DEBUGPRINT
+ ((KERN_ALERT "Setting up port %d, chipno %d for %s type board number %d.\n",
+ portno, cptr->c_chipno, board_type[bptr->b_type],bptr->board_number));
+ pptr->portno = portno;
+ pptr->chip=cptr;
+ pptr->board=bptr;
+ pptr->open_type=OPEN_NOT;
+ pptr->is_console=0;
+ pptr->regs=
+ (union sab82532_regs *)
+ (((unsigned int)cptr->c_regs) +
+ (portno << 6)); /* addressing is different when there is a cim */
+ pptr->type = cptr->c_revision;
+ pptr->function = (((cim->ci_flags & CIM_SYNC) || flag) ? FUNCTION_NR :
+ FUNCTION_AO);
+
+ pptr->irq = bptr->b_irq;
+
+ pptr->dsr.reg = ((unsigned char *)cptr->c_regs) + SAB82538_REG_PVR_C;
+ pptr->dsr.mask = 0x1 << portno;
+ pptr->dsr.inverted = 1;
+ pptr->dsr.irq=PIS_IDX; /* need to check this constant */
+ pptr->dsr.irqmask=0x1 << portno;
+ pptr->dsr.cnst = 0;
+
+ pptr->txclkdir.reg = ((unsigned char *)cptr->c_regs) + SAB82538_REG_PVR_A;
+ pptr->txclkdir.mask = 0x1 << portno;
+ /* NOTE: Early 8 ports boards had different tx clkdir sense */
+ pptr->txclkdir.inverted = 1;
+
+ pptr->dtr.reg = ((unsigned char *)cptr->c_regs) + SAB82538_REG_PVR_B;
+ pptr->dtr.mask = 0x1 << portno;
+ pptr->dtr.inverted = 1;
+ pptr->dtr.cnst = 0;
+
+ pptr->dcd.reg = ((unsigned char *)pptr->regs) + SAB85232_REG_VSTR;
+
+ DEBUGPRINT((KERN_ALERT "cd register set to 0x%p\n", pptr->dcd.reg));
+
+ pptr->dcd.mask = SAB82532_VSTR_CD;
+ pptr->dcd.inverted = 1;
+ pptr->dcd.irq=ISR0_IDX;
+ pptr->dcd.irqmask=SAB82532_ISR0_CDSC;
+ pptr->dcd.cnst = 0;
+
+ pptr->cts.reg = (unsigned char *)&(STAR);
+ pptr->cts.mask = SAB82532_STAR_CTS;
+ pptr->cts.inverted = 0;
+ pptr->cts.irq=ISR1_IDX;
+ pptr->cts.irqmask=SAB82532_ISR1_CSC;
+ pptr->cts.cnst = 0;
+
+ pptr->rts.reg = (unsigned char *)&(MODE);
+ pptr->rts.mask = SAB82532_MODE_FRTS;
+ pptr->rts.inverted = 1;
+ pptr->rts.cnst = SAB82532_MODE_RTS;
+
+
+ /* Set the read and write function */
+ pptr->readbyte=wmsaura_readb;
+ pptr->readword=wmsaura_readw;
+ pptr->writebyte=wmsaura_writeb;
+ pptr->writeword=wmsaura_writew;
+ pptr->readfifo=wmsaura_readfifo;
+ pptr->writefifo=wmsaura_writefifo;
+
+ sab8253x_setup_ttyport(pptr); /* asynchronous */
+ /* ttys are default, basic */
+ /* initialization, everything */
+ /* else works as a modification */
+ /* thereof */
+
+ pptr->next = AuraPortRoot;
+ AuraPortRoot = pptr;
+
+ pptr->next_by_chip = cptr->c_portbase;
+ cptr->c_portbase = pptr;
+
+ pptr->next_by_board = bptr->board_portbase;
+ bptr->board_portbase = pptr;
+
+ pptr->next_by_cim = cim->ci_portbase;
+ cim->ci_portbase = pptr;
+}
+
+static void CreateCIMs(SAB_BOARD *bptr)
+{
+ unsigned int cimnum;
+ unsigned char *wrcsr;
+ unsigned char *rdcsr;
+ unsigned char tmp;
+ AURA_CIM *cim;
+ unsigned short intrmask;
+
+ for(intrmask = 0, cimnum = 0; cimnum < MAX_NCIMS; ++cimnum)
+ {
+ intrmask >>= 2;
+
+ /*
+ * The hardware is mapped. Try writing to CIM CSR.
+ */
+ wrcsr = bptr->CIMCMD_REG +
+ (CIMCMD_WRCIMCSR | (cimnum << CIMCMD_CIMSHIFT));
+ rdcsr = bptr->CIMCMD_REG +
+ (CIMCMD_RDCIMCSR | (cimnum << CIMCMD_CIMSHIFT));
+
+ /* Try to write an 0xff */
+ writeb((unsigned char) 0xff, (unsigned char *) wrcsr);
+ /* and read it back */
+ tmp = (unsigned char) readb((unsigned char *) rdcsr);
+ DEBUGPRINT((KERN_ALERT
+ "aura wan mcs: wrcsr %p rdcsr %p cim %d 0xff readback: 0x%x.\n",
+ (void*) wrcsr, (void*) rdcsr, cimnum, tmp));
+
+ /* make sure it's really all ones. */
+ if ((tmp & CIMCMD_CIMCSR_TESTMASK) != CIMCMD_CIMCSR_TESTMASK)
+ {
+ printk(KERN_ALERT
+ "aura wan mcs: not found -- wrcsr %p rdcsr %p cim %d 0xff readback: 0x%x.\n",
+ (void*) wrcsr, (void*) rdcsr, cimnum, tmp);
+ continue;
+ }
+
+ /* Try to write a zero */
+ writeb((unsigned char) 0, (unsigned char*) wrcsr);
+ /* and read it back */
+ tmp = (unsigned char) readb((unsigned char *) rdcsr);
+ DEBUGPRINT((KERN_ALERT
+ "aura wan mcs: wrcsr %p rdcsr %p cim %d 0x0 readback: 0x%x.\n",
+ (void*) wrcsr, (void*) rdcsr, cimnum, tmp));
+
+ /* make sure it's really zero. */
+ if ((tmp & CIMCMD_CIMCSR_TESTMASK) != 0)
+ {
+ printk(KERN_ALERT
+ "aura wan mcs: not found -- wrcsr %p rdcsr %p cim %d 0x0 readback: 0x%x.\n",
+ (void*) wrcsr, (void*) rdcsr, cimnum, tmp);
+ continue;
+ }
+ cim = (AURA_CIM*) kmalloc(sizeof(AURA_CIM), GFP_KERNEL);
+ if(cim == NULL)
+ {
+ printk(KERN_ALERT
+ "aura wan mcs: unable to allocate memory, board %p, cim %d.\n",
+ bptr, cimnum);
+ continue;
+ }
+ cim->ci_num = cimnum;
+ cim->ci_board = bptr;
+ cim->ci_chipbase = NULL;
+ cim->ci_portbase = NULL;
+ cim->ci_nports = CIM_NPORTS;
+ cim->ci_port0lbl = cimnum * CIM_NPORTS;
+ if (mcs_ciminit(bptr, cim) == FALSE)
+ {
+ kfree(cim);
+ continue;
+ }
+ intrmask |= 0xc0; /* turn on the high two bits
+ * a little obscure, borrowed
+ * from solaris driver 0th cim
+ * gets lowest two bits*/
+ cim->next = AuraCimRoot;
+ AuraCimRoot = cim;
+ cim->next_by_mcs = bptr->b_cimbase;
+ bptr->b_cimbase = cim;
+ printk(KERN_ALERT
+ "aura wan mcs: Created cim %d type %d on board %p.\n",
+ cim->ci_num, cim->ci_type, bptr);
+ }
+ bptr->b_intrmask = intrmask;
+}
+
+/* put the chips on the boards */
+
+static void SetupAllChips(SAB_BOARD *bptr)
+{ /* note that port ordering */
+ /* is important in chip setup */
+ /* the open routine walks the */
+ /* port list for sync and async */
+ /* ttys */
+ SAB_CHIP *chip;
+ AURA_CIM *cim;
+ unsigned int chipno;
+
+ switch(bptr->b_type)
+ {
+ case BD_1020P:
+ case BD_1020CP:
+ /* setup 1 ESCC2 */
+ chip = CreateESCC2(bptr, 0);
+ if(chip != NULL)
+ {
+ CreateESCC2Port(chip, 1, FUNCTION_NA);
+ CreateESCC2Port(chip, 0, FUNCTION_AO);
+ }
+
+ break;
+ case BD_1520P:
+ case BD_1520CP:
+ /* setup 1 ESCC2 */
+ chip = CreateESCC2(bptr, 0);
+ if(chip != NULL)
+ {
+ CreateESCC2Port(chip, 1, FUNCTION_NA);
+ CreateESCC2Port(chip, 0, FUNCTION_NR);
+ }
+ break;
+ case BD_2020P:
+ case BD_2020CP:
+ /* setup 1 ESCC2 */
+ chip = CreateESCC2(bptr, 0);
+ if(chip != NULL)
+ {
+ CreateESCC2Port(chip, 1, FUNCTION_AO);
+ CreateESCC2Port(chip, 0, FUNCTION_AO);
+ }
+ break;
+ case BD_2520P:
+ case BD_2520CP:
+ /* setup 1 ESCC2 */
+ chip = CreateESCC2(bptr, 0);
+ if(chip != NULL)
+ {
+ CreateESCC2Port(chip, 1, FUNCTION_NR);
+ CreateESCC2Port(chip, 0, FUNCTION_NR);
+ }
+ break;
+ case BD_4020P:
+ case BD_4020CP: /* do chips in reverCse
+ order so that they
+ are on lists in forward
+ order
+ */
+ /* setup 2 ESCC2 */
+ chip = CreateESCC2(bptr, AURORA_4X20_CHIP_OFFSET);
+ if(chip != NULL)
+ {
+ CreateESCC2Port(chip, 1, FUNCTION_AO);
+ CreateESCC2Port(chip, 0, FUNCTION_AO);
+ }
+ chip = CreateESCC2(bptr, 0);
+ if(chip != NULL)
+ {
+ CreateESCC2Port(chip, 1, FUNCTION_AO);
+ CreateESCC2Port(chip, 0, FUNCTION_AO);
+ }
+ break;
+ case BD_4520P:
+ case BD_4520CP:
+ /* setup 2 ESCC2 */
+ chip = CreateESCC2(bptr, AURORA_4X20_CHIP_OFFSET);
+ if(chip != NULL)
+ {
+ CreateESCC2Port(chip, 1, FUNCTION_NR);
+ CreateESCC2Port(chip, 0, FUNCTION_NR);
+ }
+ chip = CreateESCC2(bptr, 0);
+ if(chip != NULL)
+ {
+ CreateESCC2Port(chip, 1, FUNCTION_NR);
+ CreateESCC2Port(chip, 0, FUNCTION_NR);
+ }
+ break;
+ case BD_8020P:
+ case BD_8020CP:
+ /* setup 1 ESCC8 */
+ chip = CreateESCC8(bptr, 0);
+ if(chip != NULL)
+ {
+ CreateESCC8Port(chip, 7, FUNCTION_AO);
+ CreateESCC8Port(chip, 6, FUNCTION_AO);
+ CreateESCC8Port(chip, 5, FUNCTION_AO);
+ CreateESCC8Port(chip, 4, FUNCTION_AO);
+ CreateESCC8Port(chip, 3, FUNCTION_AO);
+ CreateESCC8Port(chip, 2, FUNCTION_AO);
+ CreateESCC8Port(chip, 1, FUNCTION_AO);
+ CreateESCC8Port(chip, 0, FUNCTION_AO);
+ }
+ break;
+ case BD_8520P:
+ case BD_8520CP:
+ /* setup 1 ESCC8 */
+ chip = CreateESCC8(bptr, 0);
+ if(chip != NULL)
+ {
+ CreateESCC8Port(chip, 7, FUNCTION_NR);
+ CreateESCC8Port(chip, 6, FUNCTION_NR);
+ CreateESCC8Port(chip, 5, FUNCTION_NR);
+ CreateESCC8Port(chip, 4, FUNCTION_NR);
+ CreateESCC8Port(chip, 3, FUNCTION_NR);
+ CreateESCC8Port(chip, 2, FUNCTION_NR);
+ CreateESCC8Port(chip, 1, FUNCTION_NR);
+ CreateESCC8Port(chip, 0, FUNCTION_NR);
+ }
+ break;
+
+ case BD_WANMCS:
+ CreateCIMs(bptr);
+ for(chipno = 7, cim = bptr->b_cimbase;
+ cim != NULL; cim = cim->next_by_mcs)
+ {
+ chip = CreateESCC8fromCIM(bptr, cim, chipno--);
+ if(chip != NULL)
+ {
+ CreateESCC8PortWithCIM(chip, 7, cim, 0);
+ CreateESCC8PortWithCIM(chip, 6, cim, 0);
+ CreateESCC8PortWithCIM(chip, 5, cim, 0);
+ CreateESCC8PortWithCIM(chip, 4, cim, 0);
+ CreateESCC8PortWithCIM(chip, 3, cim, 0);
+ CreateESCC8PortWithCIM(chip, 2, cim, 0);
+ CreateESCC8PortWithCIM(chip, 1, cim, 0);
+ CreateESCC8PortWithCIM(chip, 0, cim, 0);
+ }
+ chip = CreateESCC8fromCIM(bptr, cim, chipno--);
+ if(chip != NULL)
+ {
+ CreateESCC8PortWithCIM(chip, 7, cim, 0);
+ CreateESCC8PortWithCIM(chip, 6, cim, 0);
+ CreateESCC8PortWithCIM(chip, 5, cim, 0);
+ CreateESCC8PortWithCIM(chip, 4, cim, 0);
+ CreateESCC8PortWithCIM(chip, 3, cim, 0);
+ CreateESCC8PortWithCIM(chip, 2, cim, 0);
+ CreateESCC8PortWithCIM(chip, 1, cim, 0);
+ CreateESCC8PortWithCIM(chip, 0, cim, 1);
+ }
+ }
+ break;
+
+ default:
+ printk(KERN_ALERT "auraXX20n: unable to set up chip for board %p.\n", bptr);
+ break;
+ }
+}
+
+/* finding the cards by PCI device type */
+
+static SAB_BOARD* find_ati_cpci_card(void)
+{
+ struct pci_dev *pdev;
+ unsigned char bus;
+ unsigned char devfn;
+ unsigned char pci_latency;
+ unsigned short pci_command;
+ SAB_BOARD *bptr;
+ unsigned control;
+ unsigned does_sync;
+ unsigned use_1port;
+
+ printk(KERN_ALERT "auraXX20n: finding ati cpci cards.\n");
+
+ bptr = (SAB_BOARD*)kmalloc(sizeof(SAB_BOARD), GFP_KERNEL);
+ if(bptr == NULL)
+ {
+ printk(KERN_ALERT "auraXX20n: could not allocate board memory!\n");
+ return 0;
+ }
+ memset(bptr, 0, sizeof(SAB_BOARD));
+
+ if(!pcibios_present())
+ {
+ printk(KERN_ALERT "auraXX20n: system does not support PCI bus.\n");
+ kfree(bptr);
+ return 0;
+ }
+ DEBUGPRINT((KERN_ALERT "auraXX20n: System supports PCI bus.\n"));
+
+ CPCIRESTART:
+ if(pdev = pci_find_device(sab8253x_vendor_id, sab8253x_cpci_device_id, XX20lastpdev),
+ pdev == NULL)
+ {
+ printk(KERN_ALERT "auraXX20n: could not find cpci card.\n");
+ kfree(bptr);
+ return 0;
+ }
+
+ DEBUGPRINT((KERN_ALERT "auraXX20n: found multiport CPCI serial card.\n"));
+
+ XX20lastpdev = pdev;
+ DEBUGPRINT((KERN_ALERT "auraXX20n: found ATI PLX 9050, %p.\n", pdev));
+ bptr->b_dev = *pdev;
+
+ /* the Solaris and model linux drivers
+ * comment that there are problems with
+ * getting the length via PCI operations
+ * seems to work for 2.4
+ */
+ bptr->length0 = (unsigned int) pci_resource_len(pdev, 0);
+ bptr->length1 = (unsigned int) pci_resource_len(pdev, 1);
+ bptr->length2 = (unsigned int) pci_resource_len(pdev, 2);
+ bptr->b_irq = pdev->irq;
+
+
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: base address 0 is %p, len is %x.\n",
+ (void*) pci_base_address(pdev, 0), bptr->length0));
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: base address 1 is %p, len is %x.\n",
+ (void*) pci_base_address(pdev, 1), bptr->length1));
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: base address 2 is %p, len is %x.\n",
+ (void*) pci_base_address(pdev, 2),
+ bptr->length2));
+
+ DEBUGPRINT((KERN_ALERT "auraXX20n: interrupt is %i.\n", pdev->irq));
+ bus = pdev->bus->number;
+ devfn = pdev->devfn;
+ DEBUGPRINT((KERN_ALERT "auraXX20n: bus is %x, slot is %x.\n", bus, PCI_SLOT(devfn)));
+ pcibios_read_config_word(bus, devfn, PCI_COMMAND, &pci_command);
+#if 0
+ /* The Aurora card does not act as a PCI master
+ * ugh!!
+ */
+ new_command = pci_command | PCI_COMMAND_MASTER;
+ if(pci_command != new_command)
+ {
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: the PCI BIOS has not enabled this device!"
+ " Updating PCI command %4.4x->%4.4x.\n",
+ pci_command,
+ new_command));
+ pcibios_write_config_word(bus, devfn, PCI_COMMAND,
+ new_command);
+ }
+ else
+ {
+ DEBUGPRINT
+ ((KERN_ALERT
+ "auraXX20n: the PCI BIOS has enabled this device as master!\n"));
+ }
+#endif
+ if((pci_command & PCI_COMMAND_MASTER) != PCI_COMMAND_MASTER)
+ {
+ DEBUGPRINT((KERN_ALERT "auraXX20n: Aurora card is not a bus master.\n"));
+ }
+
+ pcibios_read_config_byte(bus, devfn, PCI_LATENCY_TIMER,
+ &pci_latency);
+ if (pci_latency < 32)
+ {
+ DEBUGPRINT
+ ((KERN_ALERT
+ "auraXX20n: PCI latency timer (CFLT) is low at %i.\n", pci_latency));
+ /* may need to change the latency */
+#if 0
+ pcibios_write_config_byte(bus, devfn, PCI_LATENCY_TIMER, 32);
+#endif
+ }
+ else
+ {
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: PCI latency timer (CFLT) is %#x.\n",
+ pci_latency));
+ }
+ bptr->virtbaseaddress0 = ioremap_nocache(pci_base_address(pdev, 0),
+ bptr->length0);
+ if(bptr->virtbaseaddress0 == NULL)
+ {
+ printk(KERN_ALERT
+ "auraXX20n: unable to remap physical address %p.\n",
+ (void*) pci_base_address(pdev, 0));
+
+ goto CPCIRESTART;
+ }
+
+ bptr->b_bridge = (PLX9050*) bptr->virtbaseaddress0; /* MAKE SURE INTS ARE OFF */
+ writel(PLX_INT_OFF, &(bptr->b_bridge->intr));
+
+ printk
+ (KERN_ALERT
+ "auraXX20n: remapped physical address %p to virtual address %p.\n",
+ (void*) pci_base_address(pdev, 0), (void*) bptr->virtbaseaddress0);
+
+ dump_ati_adapter_registers((unsigned int*) bptr->virtbaseaddress0, bptr->length0);
+
+ if(*(unsigned int*)bptr->virtbaseaddress0 == -1) /* XP7 problem? */
+ {
+ printk(KERN_ALERT
+ "auraXX20n: unable to access PLX 9050 registers at %p.\n",
+ (void*)bptr->virtbaseaddress0);
+ printk(KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)bptr->virtbaseaddress0);
+ iounmap((void*)bptr->virtbaseaddress0);
+ bptr->virtbaseaddress0 = 0;
+
+ goto CPCIRESTART;
+ }
+
+ bptr->virtbaseaddress2 = ioremap_nocache(pci_base_address(pdev, 2),
+ bptr->length2);
+ if(bptr->virtbaseaddress2 == NULL)
+ {
+ printk(KERN_ALERT
+ "auraXX20n: unable to remap physical address %p.\n",
+ (void*) pci_base_address(pdev, 2));
+ printk(KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)bptr->virtbaseaddress0);
+ iounmap((void*)bptr->virtbaseaddress0);
+ bptr->virtbaseaddress0 = 0;
+
+ goto CPCIRESTART;
+ }
+
+ DEBUGPRINT
+ ((KERN_ALERT
+ "auraXX20n: remapped physical address %p to virtual address %p.\n",
+ (void*) pci_base_address(pdev, 2), (void*) bptr->virtbaseaddress2));
+
+ /* we get clockrate from serial eeprom */
+ if (!plx9050_eprom_read(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
+ (unsigned short*) bptr->b_eprom,
+ (unsigned char) 0, EPROM9050_SIZE))
+ {
+ printk(KERN_ALERT "auraXX20n: Could not read serial eprom.\n");
+ iounmap((void*)bptr->virtbaseaddress0);
+ bptr->virtbaseaddress0 = 0;
+ iounmap((void*)bptr->virtbaseaddress2);
+ bptr->virtbaseaddress2 = 0;
+
+ goto CPCIRESTART;
+ }
+
+ printk(KERN_ALERT "auraXX20n: dumping serial eprom.\n");
+ dump_ati_adapter_registers((unsigned int*) bptr->b_eprom, 2 * EPROM9050_SIZE);
+
+ if(*(unsigned int*)bptr->b_eprom != PCIMEMVALIDCPCI) /* bridge problem? */
+ {
+ printk(KERN_ALERT "auraXX20n: unable to access valid serial eprom data.\n");
+ iounmap((void*)bptr->virtbaseaddress0);
+ bptr->virtbaseaddress0 = 0;
+ iounmap((void*)bptr->virtbaseaddress2);
+ bptr->virtbaseaddress2 = 0;
+
+ goto CPCIRESTART;
+ }
+
+ if(((unsigned short*) bptr->b_eprom)[EPROMPREFETCHOFFSET] & PREFETCHBIT)
+ {
+ ++sab8253x_rebootflag;
+ printk(KERN_ALERT "8253x: eeprom programmed for prefetchable memory resources; must reprogram!!\n");
+ plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
+ NM93_WENCMD, NM93_WENADDR, 0);
+ plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
+ NM93_WRITECMD,
+ 9,
+ (((unsigned short*) bptr->b_eprom)[EPROMPREFETCHOFFSET] & (~PREFETCHBIT)));
+ plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
+ NM93_WDSCMD, NM93_WDSADDR, 0);
+ }
+ /* get SYNC and ONEPORT values */
+
+ control = readl(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl);
+ /* note we use the actual address
+ * of the control register in
+ * memory
+ */
+
+ if(control & AURORA_MULTI_SYNCBIT)
+ {
+ does_sync = 0;
+ }
+ else
+ {
+ does_sync = 1;
+ }
+
+ if(control & AURORA_MULTI_1PORTBIT)
+ {
+ use_1port = 1;
+ }
+ else
+ {
+ use_1port = 0;
+ }
+
+
+ /* Figure out the board */
+ switch(bptr->length2)
+ {
+ case AURORA_4X20_SIZE:
+ if(does_sync)
+ {
+ bptr->b_type = BD_4520CP;
+ bptr->b_nchips = 2;
+ bptr->b_nports = 4;
+ bptr->b_flags = BD_SYNC;
+ bptr->b_cimbase = NULL;
+ bptr->board_number = BD4520CPcounter; /* keep track of boardnumber for naming devices */
+ ++BD4520CPcounter;
+ printk(KERN_ALERT "auraXX20n: Found Saturn 4520CP.\n");
+ }
+ else
+ {
+ bptr->b_type = BD_4020CP;
+ bptr->b_nchips = 2;
+ bptr->b_nports = 4;
+ bptr->b_flags = 0x0;
+ bptr->b_cimbase = NULL;
+ bptr->board_number = BD4020CPcounter;
+ ++BD4020CPcounter;
+ printk(KERN_ALERT "auraXX20n: Found Apollo 4020CP.\n");
+ }
+ break;
+ case AURORA_8X20_SIZE:
+ if(does_sync)
+ {
+ bptr->b_type = BD_8520CP;
+ bptr->b_nchips = 1;
+ bptr->b_nports = 8;
+ bptr->b_flags = BD_SYNC;
+ bptr->b_cimbase = NULL;
+ bptr->board_number = BD8520CPcounter;
+ ++BD8520CPcounter;
+ printk(KERN_ALERT "auraXX20n: Found Saturn 8520CP.\n");
+ }
+ else
+ {
+ bptr->b_type = BD_8020CP;
+ bptr->b_nchips = 1;
+ bptr->b_nports = 8;
+ bptr->b_flags = 0x0;
+ bptr->b_cimbase = NULL;
+ bptr->board_number = BD8020CPcounter;
+ ++BD8020CPcounter;
+ printk(KERN_ALERT "auraXX20n: Found Apollo 8020CP.\n");
+ }
+ break;
+ case AURORA_2X20_SIZE:
+ if(does_sync)
+ {
+ if(use_1port)
+ {
+ bptr->b_type = BD_1520CP;
+ printk(KERN_ALERT "auraXX20n: Found Saturn 1520CP.\n");
+ bptr->b_nchips = 1;
+ bptr->b_nports = 1;
+ bptr->b_flags = BD_SYNC;
+ bptr->b_cimbase = NULL;
+ bptr->board_number = BD1520CPcounter;
+ ++BD1520CPcounter;
+ printk(KERN_ALERT "auraXX20n: Found Saturn 1520CP.\n");
+ }
+ else
+ {
+ bptr->b_type = BD_2520CP;
+ bptr->b_nchips = 1;
+ bptr->b_nports = 2;
+ bptr->b_flags = BD_SYNC;
+ bptr->b_cimbase = NULL;
+ bptr->board_number = BD2520CPcounter;
+ ++BD2520CPcounter;
+ printk(KERN_ALERT "auraXX20n: Found Saturn 2520CP.\n");
+ }
+ }
+ else
+ {
+ if(use_1port)
+ {
+ bptr->b_type = BD_1020CP;
+ bptr->b_nchips = 1;
+ bptr->b_nports = 1;
+ bptr->b_flags = 0x0;
+ bptr->b_cimbase = NULL;
+ bptr->board_number = BD1020CPcounter;
+ ++BD1020CPcounter;
+ printk(KERN_ALERT "auraXX20n: Found Apollo 1020CP.\n");
+ }
+ else
+ {
+ bptr->b_type = BD_2020CP;
+ bptr->b_nchips = 1;
+ bptr->b_nports = 2;
+ bptr->b_flags = 0x0;
+ bptr->b_cimbase = NULL;
+ bptr->board_number = BD2020CPcounter;
+ ++BD2020CPcounter;
+ printk(KERN_ALERT "auraXX20n: Found Apollo 2020CP.\n");
+ }
+ }
+ break;
+ default:
+ printk(KERN_ALERT "Error: Board could not be identified\n");
+ iounmap((void*)bptr->virtbaseaddress0);
+ bptr->virtbaseaddress0 = 0;
+ iounmap((void*)bptr->virtbaseaddress2);
+ bptr->virtbaseaddress2 = 0;
+
+ goto CPCIRESTART;
+ }
+
+ /* Let's get the clockrate right -- ugh!*/
+
+ bptr->b_clkspeed = bptr->b_eprom[AURORA_MULTI_EPROM_CLKLSW/2];
+
+ if(bptr->b_clkspeed == -1) /* misprogrammed -- ugh. */
+ {
+ switch(bptr->b_type)
+ {
+ case BD_8520CP:
+ case BD_8020CP:
+ bptr->b_clkspeed = AURORA_MULTI_CLKSPEED/4;
+ break;
+ default:
+ bptr->b_clkspeed = AURORA_MULTI_CLKSPEED;
+ break;
+
+ }
+ printk(KERN_ALERT "auraXX20n: UNKNOWN CLOCKSPEED -- ASSUMING %ld.\n", bptr->b_clkspeed);
+
+ plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
+ NM93_WENCMD, NM93_WENADDR, 0);
+ plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
+ NM93_WRITECMD,
+ 54, (unsigned short) bptr->b_clkspeed);
+ plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
+ NM93_WRITECMD,
+ 55, (unsigned short) (bptr->b_clkspeed >> 16));
+ plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
+ NM93_WDSCMD, NM93_WDSADDR, 0);
+ }
+
+ return bptr;
+}
+
+static SAB_BOARD* find_ati_wanms_card(void) /* wan multichanner server == mcs [ multichannel server] */
+{
+ struct pci_dev *pdev;
+ unsigned char bus;
+ unsigned char devfn;
+ unsigned char pci_latency;
+ unsigned short pci_command;
+ SAB_BOARD *bptr;
+ int resetresult;
+
+ printk(KERN_ALERT "auraXX20n: finding ati mcs cards.\n");
+
+ bptr = (SAB_BOARD*)kmalloc(sizeof(SAB_BOARD), GFP_KERNEL);
+ if(bptr == NULL)
+ {
+ printk(KERN_ALERT "auraXX20n: could not allocate board memory!\n");
+ return 0;
+ }
+ memset(bptr, 0, sizeof(SAB_BOARD));
+
+ if(!pcibios_present())
+ {
+ printk(KERN_ALERT "auraXX20n: system does not support PCI bus.\n");
+ kfree(bptr);
+ return 0;
+ }
+ DEBUGPRINT((KERN_ALERT "auraXX20n: System supports PCI bus.\n"));
+
+ MCSRESTART:
+ if(pdev = pci_find_device(sab8253x_vendor_id, sab8253x_wmcs_device_id, XX20lastpdev),
+ pdev == NULL)
+ {
+ printk(KERN_ALERT "auraXX20n: could not find mcs card.\n");
+ kfree(bptr);
+ return 0;
+ }
+
+ DEBUGPRINT((KERN_ALERT "auraXX20n: found mcs card.\n"));
+
+ XX20lastpdev = pdev;
+ DEBUGPRINT((KERN_ALERT "auraXX20n: found ATI S5920, %p.\n", pdev));
+ bptr->b_dev = *pdev;
+
+ /* the Solaris and model linux drivers
+ * comment that there are problems with
+ * getting the length via PCI operations
+ * seems to work for 2.4
+ */
+ bptr->length0 = (unsigned int) pci_resource_len(pdev, 0); /* AMCC 5920 operation registers
+ includes access to serial eprom */
+ bptr->length1 = (unsigned int) pci_resource_len(pdev, 1); /* commands to remote cards */
+ bptr->length2 = (unsigned int) pci_resource_len(pdev, 2); /* command to host card */
+ bptr->length3 = (unsigned int) pci_resource_len(pdev, 3); /* RFIFO cache */
+ bptr->b_irq = pdev->irq;
+
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: base address 0 is %p, len is %x.\n",
+ (void*) pci_base_address(pdev, 0), bptr->length0));
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: base address 1 is %p, len is %x.\n",
+ (void*) pci_base_address(pdev, 1), bptr->length1));
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: base address 2 is %p, len is %x.\n",
+ (void*) pci_base_address(pdev, 2),
+ bptr->length2));
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: base address 3 is %p, len is %x.\n",
+ (void*) pci_base_address(pdev, 3),
+ bptr->length3));
+
+ DEBUGPRINT((KERN_ALERT "auraXX20n: interrupt is %i.\n", pdev->irq));
+ bus = pdev->bus->number;
+ devfn = pdev->devfn;
+ DEBUGPRINT((KERN_ALERT "auraXX20n: bus is %x, slot is %x.\n", bus, PCI_SLOT(devfn)));
+ pcibios_read_config_word(bus, devfn, PCI_COMMAND, &pci_command);
+
+#if 0
+ /* The Aurora card does not act as a PCI master
+ * ugh!!
+ */
+ new_command = pci_command | PCI_COMMAND_MASTER;
+ if(pci_command != new_command)
+ {
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: the PCI BIOS has not enabled this device!"
+ " Updating PCI command %4.4x->%4.4x.\n",
+ pci_command,
+ new_command));
+ pcibios_write_config_word(bus, devfn, PCI_COMMAND,
+ new_command);
+ }
+ else
+ {
+ DEBUGPRINT
+ ((KERN_ALERT
+ "auraXX20n: the PCI BIOS has enabled this device as master!\n"));
+ }
+#endif
+
+ if((pci_command & PCI_COMMAND_MASTER) != PCI_COMMAND_MASTER)
+ {
+ DEBUGPRINT((KERN_ALERT "auraXX20n: Aurora card is not a bus master.\n"));
+ }
+
+ pcibios_read_config_byte(bus, devfn, PCI_LATENCY_TIMER,
+ &pci_latency);
+ if (pci_latency < 32)
+ {
+ DEBUGPRINT
+ ((KERN_ALERT
+ "auraXX20n: PCI latency timer (CFLT) is low at %i.\n", pci_latency));
+ /* may need to change the latency */
+#if 0
+ pcibios_write_config_byte(bus, devfn, PCI_LATENCY_TIMER, 32);
+#endif
+ }
+ else
+ {
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: PCI latency timer (CFLT) is %#x.\n",
+ pci_latency));
+ }
+
+ bptr->virtbaseaddress0 = ioremap_nocache(pci_base_address(pdev, 0),
+ bptr->length0);
+ if(bptr->virtbaseaddress0 == NULL)
+ {
+ printk(KERN_ALERT
+ "auraXX20n: unable to remap physical address %p.\n",
+ (void*) pci_base_address(pdev, 0));
+ goto MCSRESTART;
+ }
+
+ bptr->b_bridge = (void*) bptr->virtbaseaddress0; /* b_bridge is not supposed
+ to be used by the AMCC based
+ products -- it is set just
+ in case */
+
+ printk(KERN_ALERT
+ "auraXX20n: remapped physical address %p to virtual address %p.\n",
+ (void*) pci_base_address(pdev, 0), (void*) bptr->virtbaseaddress0);
+
+ /* unfortunate name -- works for any bridge */
+ dump_ati_adapter_registers((unsigned int*) bptr->virtbaseaddress0, bptr->length0);
+
+ if(*(unsigned int*)bptr->virtbaseaddress0 == -1) /* XP7 problem? */
+ {
+ printk(KERN_ALERT
+ "auraXX20n: unable to access AMCC registers at %p.\n",
+ (void*)bptr->virtbaseaddress0);
+ printk(KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)bptr->virtbaseaddress0);
+ iounmap((void*)bptr->virtbaseaddress0);
+ bptr->virtbaseaddress0 = 0;
+ goto MCSRESTART; /* try the next one if any */
+ }
+
+ writel(AMCC_INT_OFF, (unsigned int*)(bptr->AMCC_REG + AMCC_INTCSR));
+
+ bptr->virtbaseaddress1 = ioremap_nocache(pci_base_address(pdev, 1),
+ bptr->length1);
+ if(bptr->virtbaseaddress1 == NULL)
+ {
+ printk(KERN_ALERT
+ "auraXX20n: unable to remap physical address %p.\n",
+ (void*) pci_base_address(pdev, 1));
+ printk(KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)bptr->virtbaseaddress0);
+ iounmap((void*)bptr->virtbaseaddress0);
+ bptr->virtbaseaddress0 = 0;
+ goto MCSRESTART;
+ }
+
+ DEBUGPRINT
+ ((KERN_ALERT
+ "auraXX20n: remapped physical address %p to virtual address %p.\n",
+ (void*) pci_base_address(pdev, 1), (void*) bptr->virtbaseaddress1));
+
+ /* next address space */
+ bptr->virtbaseaddress2 = ioremap_nocache(pci_base_address(pdev, 2),
+ bptr->length2);
+ if(bptr->virtbaseaddress2 == NULL)
+ {
+ printk(KERN_ALERT
+ "auraXX20n: unable to remap physical address %p.\n",
+ (void*) pci_base_address(pdev, 2));
+
+ printk(KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)bptr->virtbaseaddress0);
+ iounmap((void*)bptr->virtbaseaddress0);
+ bptr->virtbaseaddress0 = 0;
+
+ printk(KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)bptr->virtbaseaddress1);
+ iounmap((void*)bptr->virtbaseaddress1);
+ bptr->virtbaseaddress1 = 0;
+ goto MCSRESTART;
+ }
+
+ DEBUGPRINT
+ ((KERN_ALERT
+ "auraXX20n: remapped physical address %p to virtual address %p.\n",
+ (void*) pci_base_address(pdev, 2), (void*) bptr->virtbaseaddress2));
+
+ bptr->virtbaseaddress3 = ioremap_nocache(pci_base_address(pdev, 3),
+ bptr->length3);
+ if(bptr->virtbaseaddress3 == NULL)
+ {
+ printk(KERN_ALERT
+ "auraXX20n: unable to remap physical address %p.\n",
+ (void*) pci_base_address(pdev, 3));
+ printk(KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)bptr->virtbaseaddress0);
+ iounmap((void*)bptr->virtbaseaddress0);
+ bptr->virtbaseaddress0 = 0;
+
+ printk(KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)bptr->virtbaseaddress1);
+ iounmap((void*)bptr->virtbaseaddress1);
+ bptr->virtbaseaddress1 = 0;
+
+ printk(KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)bptr->virtbaseaddress2);
+ iounmap((void*)bptr->virtbaseaddress2);
+ bptr->virtbaseaddress2 = 0;
+
+ goto MCSRESTART;
+ }
+
+ DEBUGPRINT
+ ((KERN_ALERT
+ "auraXX20n: remapped physical address %p to virtual address %p.\n",
+ (void*) pci_base_address(pdev, 3), (void*) bptr->virtbaseaddress3));
+
+ bptr->b_type = BD_WANMCS;
+
+ resetresult = wanmcs_reset(bptr);
+ writel(AMCC_INT_OFF, (unsigned int*)(bptr->AMCC_REG + AMCC_INTCSR));
+
+ if(resetresult == FALSE)
+ {
+ printk(KERN_ALERT "auraXX20n: unable to reset wan mcs %p.\n", bptr);
+
+ printk(KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)bptr->virtbaseaddress0);
+ iounmap((void*)bptr->virtbaseaddress0);
+ bptr->virtbaseaddress0 = 0;
+
+ printk(KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)bptr->virtbaseaddress1);
+ iounmap((void*)bptr->virtbaseaddress1);
+ bptr->virtbaseaddress1 = 0;
+
+ printk(KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)bptr->virtbaseaddress2);
+ iounmap((void*)bptr->virtbaseaddress2);
+ bptr->virtbaseaddress2 = 0;
+
+
+ printk(KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)bptr->virtbaseaddress3);
+ iounmap((void*)bptr->virtbaseaddress3);
+ bptr->virtbaseaddress3 = 0;
+
+ goto MCSRESTART;
+ }
+
+ /* we get clockrate from serial eeprom */
+ if (amcc_read_nvram((unsigned char*) bptr->b_eprom,
+ AMCC_NVRAM_SIZE, bptr->AMCC_REG) == FALSE)
+ {
+ printk(KERN_ALERT "auraXX20n: Could not read serial eprom.\n");
+ iounmap((void*)bptr->virtbaseaddress0);
+ bptr->virtbaseaddress0 = 0;
+ iounmap((void*)bptr->virtbaseaddress1);
+ bptr->virtbaseaddress1 = 0;
+ iounmap((void*)bptr->virtbaseaddress2);
+ bptr->virtbaseaddress2 = 0;
+ iounmap((void*)bptr->virtbaseaddress3);
+ bptr->virtbaseaddress3 = 0;
+ goto MCSRESTART;
+ }
+ printk(KERN_ALERT "auraXX20n: dumping serial eprom.\n");
+ dump_ati_adapter_registers((unsigned int*) bptr->b_eprom, 2 * AMCC_NVRAM_SIZE);
+ if(bptr->b_eprom[AMCC_NVR_VENDEVID] != PCIMEMVALIDWMCS)
+ {
+ printk(KERN_ALERT "auraXX20: bad serial eprom, board %p.\n", bptr);
+ iounmap((void*)bptr->virtbaseaddress0);
+ bptr->virtbaseaddress0 = 0;
+ iounmap((void*)bptr->virtbaseaddress1);
+ bptr->virtbaseaddress1 = 0;
+ iounmap((void*)bptr->virtbaseaddress2);
+ bptr->virtbaseaddress2 = 0;
+ iounmap((void*)bptr->virtbaseaddress3);
+ bptr->virtbaseaddress3 = 0;
+ goto MCSRESTART;
+ }
+ return bptr;
+}
+
+/* initialize the auraXX20 */
+static SAB_BOARD* find_ati_multiport_card(void)
+{
+ struct pci_dev *pdev;
+ unsigned char bus;
+ unsigned char devfn;
+ unsigned char pci_latency;
+ unsigned short pci_command;
+ SAB_BOARD *bptr;
+ unsigned control;
+ unsigned does_sync;
+ unsigned use_1port;
+
+ printk(KERN_ALERT "auraXX20n: finding ati cards.\n");
+
+ bptr = (SAB_BOARD*)kmalloc(sizeof(SAB_BOARD), GFP_KERNEL);
+ if(bptr == NULL)
+ {
+ printk(KERN_ALERT "auraXX20n: could not allocate board memory!\n");
+ return 0;
+ }
+ memset(bptr, 0, sizeof(SAB_BOARD));
+
+ if(!pcibios_present())
+ {
+ printk(KERN_ALERT "auraXX20n: system does not support PCI bus.\n");
+ kfree(bptr);
+ return 0;
+ }
+ DEBUGPRINT((KERN_ALERT "auraXX20n: System supports PCI bus.\n"));
+
+ MULTIPORTRESTART:
+ if(pdev = pci_find_device(sab8253x_vendor_id, sab8253x_mpac_device_id, XX20lastpdev),
+ pdev == NULL)
+ {
+ printk(KERN_ALERT "auraXX20n: could not find multiport card.\n");
+ kfree(bptr);
+ return 0;
+ }
+
+ DEBUGPRINT((KERN_ALERT "auraXX20n: found multiport PCI serial card.\n"));
+
+ XX20lastpdev = pdev;
+ DEBUGPRINT((KERN_ALERT "auraXX20n: found ATI PLX 9050, %p.\n", pdev));
+ bptr->b_dev = *pdev;
+
+ /* the Solaris and model linux drivers
+ * comment that there are problems with
+ * getting the length via PCI operations
+ * seems to work for 2.4
+ */
+ bptr->length0 = (unsigned int) pci_resource_len(pdev, 0);
+ bptr->length1 = (unsigned int) pci_resource_len(pdev, 1);
+ bptr->length2 = (unsigned int) pci_resource_len(pdev, 2);
+ bptr->b_irq = pdev->irq;
+
+
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: base address 0 is %p, len is %x.\n",
+ (void*) pci_base_address(pdev, 0), bptr->length0));
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: base address 1 is %p, len is %x.\n",
+ (void*) pci_base_address(pdev, 1), bptr->length1));
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: base address 2 is %p, len is %x.\n",
+ (void*) pci_base_address(pdev, 2),
+ bptr->length2));
+
+ DEBUGPRINT((KERN_ALERT "auraXX20n: interrupt is %i.\n", pdev->irq));
+ bus = pdev->bus->number;
+ devfn = pdev->devfn;
+ DEBUGPRINT((KERN_ALERT "auraXX20n: bus is %x, slot is %x.\n", bus, PCI_SLOT(devfn)));
+ pcibios_read_config_word(bus, devfn, PCI_COMMAND, &pci_command);
+#if 0
+ /* The Aurora card does not act as a PCI master
+ * ugh!!
+ */
+ new_command = pci_command | PCI_COMMAND_MASTER;
+ if(pci_command != new_command)
+ {
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: the PCI BIOS has not enabled this device!"
+ " Updating PCI command %4.4x->%4.4x.\n",
+ pci_command,
+ new_command));
+ pcibios_write_config_word(bus, devfn, PCI_COMMAND,
+ new_command);
+ }
+ else
+ {
+ DEBUGPRINT
+ ((KERN_ALERT
+ "auraXX20n: the PCI BIOS has enabled this device as master!\n"));
+ }
+#endif
+ if((pci_command & PCI_COMMAND_MASTER) != PCI_COMMAND_MASTER)
+ {
+ DEBUGPRINT((KERN_ALERT "auraXX20n: Aurora card is not a bus master.\n"));
+ }
+
+ pcibios_read_config_byte(bus, devfn, PCI_LATENCY_TIMER,
+ &pci_latency);
+ if (pci_latency < 32)
+ {
+ DEBUGPRINT
+ ((KERN_ALERT
+ "auraXX20n: PCI latency timer (CFLT) is low at %i.\n", pci_latency));
+ /* may need to change the latency */
+#if 0
+ pcibios_write_config_byte(bus, devfn, PCI_LATENCY_TIMER, 32);
+#endif
+ }
+ else
+ {
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: PCI latency timer (CFLT) is %#x.\n",
+ pci_latency));
+ }
+ bptr->virtbaseaddress0 = ioremap_nocache(pci_base_address(pdev, 0),
+ bptr->length0);
+ if(bptr->virtbaseaddress0 == NULL)
+ {
+ printk(KERN_ALERT
+ "auraXX20n: unable to remap physical address %p.\n",
+ (void*) pci_base_address(pdev, 0));
+
+ goto MULTIPORTRESTART;
+ }
+
+ bptr->b_bridge = (PLX9050*) bptr->virtbaseaddress0; /* MAKE SURE INTS ARE OFF */
+ writel(PLX_INT_OFF, &(bptr->b_bridge->intr));
+
+ printk(KERN_ALERT
+ "auraXX20n: remapped physical address %p to virtual address %p.\n",
+ (void*) pci_base_address(pdev, 0), (void*) bptr->virtbaseaddress0);
+
+ dump_ati_adapter_registers((unsigned int*) bptr->virtbaseaddress0, bptr->length0);
+
+ if(*(unsigned int*)bptr->virtbaseaddress0 == -1) /* XP7 problem? */
+ {
+ printk(KERN_ALERT
+ "auraXX20n: unable to access PLX 9050 registers at %p.\n",
+ (void*)bptr->virtbaseaddress0);
+ printk(KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)bptr->virtbaseaddress0);
+ iounmap((void*)bptr->virtbaseaddress0);
+ bptr->virtbaseaddress0 = 0;
+
+ goto MULTIPORTRESTART;
+ }
+
+ bptr->virtbaseaddress2 = ioremap_nocache(pci_base_address(pdev, 2),
+ bptr->length2);
+ if(bptr->virtbaseaddress2 == NULL)
+ {
+ printk(KERN_ALERT
+ "auraXX20n: unable to remap physical address %p.\n",
+ (void*) pci_base_address(pdev, 2));
+ printk(KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)bptr->virtbaseaddress0);
+ iounmap((void*)bptr->virtbaseaddress0);
+ bptr->virtbaseaddress0 = 0;
+
+ goto MULTIPORTRESTART;
+ }
+
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: remapped physical address %p to virtual address %p.\n",
+ (void*) pci_base_address(pdev, 2), (void*) bptr->virtbaseaddress2));
+
+ if (!plx9050_eprom_read(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
+ (unsigned short*) bptr->b_eprom,
+ (unsigned char) 0, EPROM9050_SIZE))
+ {
+ printk(KERN_ALERT "auraXX20n: Could not read serial eprom.\n");
+ iounmap((void*)bptr->virtbaseaddress0);
+ bptr->virtbaseaddress0 = 0;
+ iounmap((void*)bptr->virtbaseaddress2);
+ bptr->virtbaseaddress2 = 0;
+
+ goto MULTIPORTRESTART;
+ }
+
+ printk(KERN_ALERT "auraXX20n: dumping serial eprom.\n");
+ dump_ati_adapter_registers((unsigned int*) bptr->b_eprom, 2 * EPROM9050_SIZE);
+
+ if(*(unsigned int*)bptr->b_eprom != PCIMEMVALIDMULTI) /* bridge problem? */
+ {
+ printk(KERN_ALERT "auraXX20n: unable to access valid serial eprom data.\n");
+ iounmap((void*)bptr->virtbaseaddress0);
+ bptr->virtbaseaddress0 = 0;
+ iounmap((void*)bptr->virtbaseaddress2);
+ bptr->virtbaseaddress2 = 0;
+
+ goto MULTIPORTRESTART;
+ }
+
+ if(((unsigned short*) bptr->b_eprom)[EPROMPREFETCHOFFSET] & PREFETCHBIT)
+ {
+ ++sab8253x_rebootflag;
+ printk(KERN_ALERT "8253x: eeprom programmed for prefetchable memory resources; must reprogram!!\n");
+ plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
+ NM93_WENCMD, NM93_WENADDR, 0);
+ plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
+ NM93_WRITECMD,
+ 9,
+ (((unsigned short*) bptr->b_eprom)[EPROMPREFETCHOFFSET] & (~PREFETCHBIT)));
+ plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
+ NM93_WDSCMD, NM93_WDSADDR, 0);
+ }
+
+ /* get SYNC and ONEPORT values */
+
+ control = readl(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl);
+ /* note we use the actual address
+ * of the control register in
+ * memory
+ */
+
+ if(control & AURORA_MULTI_SYNCBIT)
+ {
+ does_sync = 0;
+ }
+ else
+ {
+ does_sync = 1;
+ }
+
+ if(control & AURORA_MULTI_1PORTBIT)
+ {
+ use_1port = 1;
+ }
+ else
+ {
+ use_1port = 0;
+ }
+
+
+ /* Figure out the board */
+ switch(bptr->length2)
+ {
+ case AURORA_4X20_SIZE:
+ if(does_sync)
+ {
+ bptr->b_type = BD_4520P;
+ bptr->b_nchips = 2;
+ bptr->b_nports = 4;
+ bptr->b_flags = BD_SYNC;
+ bptr->b_cimbase = NULL;
+ bptr->board_number = BD4520Pcounter; /* keep track of boardnumber for naming devices */
+ ++BD4520Pcounter;
+ printk(KERN_ALERT "auraXX20n: Found Saturn 4520P.\n");
+ }
+ else
+ {
+ bptr->b_type = BD_4020P;
+ bptr->b_nchips = 2;
+ bptr->b_nports = 4;
+ bptr->b_flags = 0x0;
+ bptr->b_cimbase = NULL;
+ bptr->board_number = BD4020Pcounter;
+ ++BD4020Pcounter;
+ printk(KERN_ALERT "auraXX20n: Found Apollo 4020P.\n");
+ }
+ break;
+ case AURORA_8X20_SIZE:
+ if(does_sync)
+ {
+ bptr->b_type = BD_8520P;
+ bptr->b_nchips = 1;
+ bptr->b_nports = 8;
+ bptr->b_flags = BD_SYNC;
+ bptr->b_cimbase = NULL;
+ bptr->board_number = BD8520Pcounter;
+ ++BD8520Pcounter;
+ printk(KERN_ALERT "auraXX20n: Found Saturn 8520P.\n");
+ }
+ else
+ {
+ bptr->b_type = BD_8020P;
+ bptr->b_nchips = 1;
+ bptr->b_nports = 8;
+ bptr->b_flags = 0x0;
+ bptr->b_cimbase = NULL;
+ bptr->board_number = BD8020Pcounter;
+ ++BD8020Pcounter;
+ printk(KERN_ALERT "auraXX20n: Found Apollo 8020P.\n");
+ }
+ break;
+ case AURORA_2X20_SIZE:
+ if(does_sync)
+ {
+ if(use_1port)
+ {
+ bptr->b_type = BD_1520P;
+ printk(KERN_ALERT "auraXX20n: Found Saturn 1520P.\n");
+ bptr->b_nchips = 1;
+ bptr->b_nports = 1;
+ bptr->b_flags = BD_SYNC;
+ bptr->b_cimbase = NULL;
+ bptr->board_number = BD1520Pcounter;
+ ++BD1520Pcounter;
+ printk(KERN_ALERT "auraXX20n: Found Saturn 1520P.\n");
+ }
+ else
+ {
+ bptr->b_type = BD_2520P;
+ bptr->b_nchips = 1;
+ bptr->b_nports = 2;
+ bptr->b_flags = BD_SYNC;
+ bptr->b_cimbase = NULL;
+ bptr->board_number = BD2520Pcounter;
+ ++BD2520Pcounter;
+ printk(KERN_ALERT "auraXX20n: Found Saturn 2520P.\n");
+ }
+ }
+ else
+ {
+ if(use_1port)
+ {
+ bptr->b_type = BD_1020P;
+ bptr->b_nchips = 1;
+ bptr->b_nports = 1;
+ bptr->b_flags = 0x0;
+ bptr->b_cimbase = NULL;
+ bptr->board_number = BD1020Pcounter;
+ ++BD1020Pcounter;
+ printk(KERN_ALERT "auraXX20n: Found Apollo 1020P.\n");
+ }
+ else
+ {
+ bptr->b_type = BD_2020P;
+ bptr->b_nchips = 1;
+ bptr->b_nports = 2;
+ bptr->b_flags = 0x0;
+ bptr->b_cimbase = NULL;
+ bptr->board_number = BD2020Pcounter;
+ ++BD2020Pcounter;
+ printk(KERN_ALERT "auraXX20n: Found Apollo 2020P.\n");
+ }
+ }
+ break;
+ default:
+ printk(KERN_ALERT "Error: Board could not be identified\n");
+ iounmap((void*)bptr->virtbaseaddress0);
+ bptr->virtbaseaddress0 = 0;
+ iounmap((void*)bptr->virtbaseaddress2);
+ bptr->virtbaseaddress2 = 0;
+
+ goto MULTIPORTRESTART;
+ }
+ /* Let's get the clockrate right -- ugh!*/
+
+ bptr->b_clkspeed = bptr->b_eprom[AURORA_MULTI_EPROM_CLKLSW/2];
+
+ if(bptr->b_clkspeed == -1) /* misprogrammed -- ugh. */
+ {
+ switch(bptr->b_type)
+ {
+ case BD_8520P:
+ case BD_8020P:
+ bptr->b_clkspeed = AURORA_MULTI_CLKSPEED/4;
+ break;
+ default:
+ bptr->b_clkspeed = AURORA_MULTI_CLKSPEED;
+ break;
+
+ }
+ printk(KERN_ALERT "auraXX20n: UNKNOWN CLOCKSPEED -- ASSUMING %ld.\n", bptr->b_clkspeed);
+
+ plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
+ NM93_WENCMD, NM93_WENADDR, 0);
+ plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
+ NM93_WRITECMD,
+ 54, (unsigned short) bptr->b_clkspeed);
+ plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
+ NM93_WRITECMD,
+ 55, (bptr->b_clkspeed >> 16));
+ plx9050_eprom_cmd(&((PLX9050*)(bptr->virtbaseaddress0))->ctrl,
+ NM93_WDSCMD, NM93_WDSADDR, 0);
+ }
+
+ return bptr;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+#ifdef MODULE
+int init_module(void) /* all OS */
+#else
+int auraXX20_probe(struct net_device *devp) /* passed default device structure */
+#endif
+#else
+static int __init auraXX20_probe(void) /* legacy device initialization 2.4.* */
+#endif
+{
+ SAB_BOARD *boardptr;
+ SAB_PORT *portptr;
+ struct net_device *dev;
+ unsigned int result;
+ unsigned int namelength;
+ unsigned int portno;
+ int intr_val;
+
+ int mp_probe_count = 0; /* multiport count */
+ int cp_probe_count = 0; /* compact pci count */
+ int wm_probe_count = 0; /* wan multiserver count */
+
+ printk(KERN_ALERT "aurora interea miseris mortalibus almam extulerat lucem\n");
+ printk(KERN_ALERT " referens opera atque labores\n");
+
+ memset(AuraBoardESCC8IrqRoot, 0, sizeof(AuraBoardESCC8IrqRoot));
+ memset(AuraBoardESCC2IrqRoot, 0, sizeof(AuraBoardESCC2IrqRoot));
+ memset(AuraBoardMCSIrqRoot, 0, sizeof(AuraBoardMCSIrqRoot));
+
+#if !defined(MODULE) && (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0))
+ if(do_probe == 0)
+ return -1; /* only allow to be called one 2.2.* */
+ do_probe = 0;
+#endif
+
+ fn_init_crc_table(); /* used in faking ethernet packets for */
+ /* the network driver -- crcs are currently */
+ /* not being checked by this software */
+ /* but is good to have them in case a frame */
+ /* passes through a WAN LAN bridge */
+
+ sab8253x_setup_ttydriver(); /* add synchronous tty and synchronous network
+ driver initialization */
+
+ AuraBoardRoot = NULL; /* basic lists */
+ AuraChipRoot = NULL;
+ AuraPortRoot = NULL;
+ NumSab8253xPorts = 0;
+
+ AuraXX20DriverParams.debug = auraXX20n_debug;
+ AuraXX20DriverParams.listsize = sab8253xn_listsize;
+
+ if(auraXX20n_name != 0)
+ {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+ auraXX20n_prototype.name = auraXX20n_name;
+#else
+ strcpy(auraXX20n_prototype.name, auraXX20n_name);
+#endif
+ }
+
+ /* find all multiport cards */
+ XX20lastpdev = NULL;
+ while(1)
+ {
+ boardptr = find_ati_multiport_card();
+ if(boardptr == NULL)
+ {
+ printk(KERN_ALERT
+ "auraXX20n: found %d AURAXX20 multiport device%s.\n",
+ mp_probe_count, ((mp_probe_count == 1) ? "" : "s"));
+ break;
+ }
+ boardptr->nextboard = AuraBoardRoot;
+ AuraBoardRoot = boardptr;
+ printk(KERN_ALERT "auraXX20n: found AURAXX20 multiport device #%d.\n",
+ mp_probe_count);
+ ++mp_probe_count;
+ }
+
+ /* find all cpci cards */
+ XX20lastpdev = NULL;
+ while(1)
+ {
+ boardptr = find_ati_cpci_card();
+ if(boardptr == NULL)
+ {
+ printk(KERN_ALERT
+ "auraXX20n: found %d AURAXX20 CPCI device%s.\n",
+ cp_probe_count, ((cp_probe_count == 1) ? "" : "s"));
+ break;
+ }
+ boardptr->nextboard = AuraBoardRoot;
+ AuraBoardRoot = boardptr;
+ printk(KERN_ALERT "auraXX20n: found AURAXX20 CPCI device #%d.\n",
+ cp_probe_count);
+ ++cp_probe_count;
+ }
+ /* find all WAN MS cards */
+ XX20lastpdev = NULL;
+ while(1)
+ {
+ boardptr = find_ati_wanms_card();
+ if(boardptr == NULL)
+ {
+ printk(KERN_ALERT
+ "auraXX20n: found %d AURAXX20 WANMS device%s.\n",
+ wm_probe_count, ((wm_probe_count == 1) ? "" : "s"));
+ break;
+ }
+ boardptr->nextboard = AuraBoardRoot;
+ AuraBoardRoot = boardptr;
+ printk(KERN_ALERT "auraXX20n: found AURAXX20 WANMS device #%d.\n",
+ wm_probe_count);
+ ++wm_probe_count;
+ }
+
+ /* Now do the chips! */
+
+ for(boardptr = AuraBoardRoot; boardptr != NULL; boardptr = boardptr->nextboard)
+ {
+ SetupAllChips(boardptr); /* sets up the ports on the chips */
+ }
+
+ /* set up global driver structures
+ * for async tty, call out device
+ * for sync tty and for network device
+ */
+
+ /* NOW TURN ON THE PLX INTS */
+ /* note all port ints (only receive right now)
+ * are off */
+
+ /* interrupts cannot be turned on by port
+ this seems to be the only sensible place
+ to do it*/
+
+ /* only at this point is the number of
+ * ttys to be created known. */
+
+ if(finish_sab8253x_setup_ttydriver() == -1) /* only as many termios are allocated */
+ /* as needed */
+ {
+ return 0;
+ }
+ for(portno = 0, portptr = AuraPortRoot; portptr != NULL; ++portno, portptr = portptr->next)
+ {
+ portptr->line = portno; /* set up the line number == minor dev associated with port */
+ portptr->sigmode = sab8253x_default_sp502_mode;
+ /* if we have SP502s let getty work with RS232 by default */
+ /* unless overridden in module setup. */
+ }
+ /* Now lets set up the network devices */
+ for(portno = 0, portptr = AuraPortRoot; portptr != NULL; ++portno, portptr = portptr->next)
+ {
+
+ dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
+ if(!dev)
+ {
+ break;
+ }
+ memset(dev, 0, sizeof(struct net_device));
+ *dev = auraXX20n_prototype;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+ dev->name = kmalloc(IFNAMSIZ+1, GFP_KERNEL);
+ if(!dev->name)
+ {
+ kfree(dev);
+ break;
+ }
+#endif
+ namelength = MIN(strlen(auraXX20n_prototype.name), IFNAMSIZ);
+ strcpy(dev->name, auraXX20n_prototype.name);
+ sprintf(&dev->name[namelength-1], "%3.3d", portno);
+
+#if 1
+ current_sab_port = portptr;
+#else
+ dev->priv = portptr;
+#endif
+ result = register_netdev(dev);
+ if(result)
+ { /* if we run into some internal kernel limit */
+ break;
+ }
+ printk(KERN_ALERT "sab8253xn: found sab8253x network device #%d.\n",
+ portno);
+ }
+ printk(KERN_ALERT
+ "sab8253xn: found %d sab8253x network device%s.\n",
+ portno, ((portno == 1) ? "" : "s"));
+
+ /* Now lets set up the character device */
+
+ if(sab8253xc_name)
+ {
+ result = register_chrdev(sab8253xc_major, sab8253xc_name, &sab8253xc_fops);
+ if(result < 0)
+ {
+ sab8253xc_major = result;
+ printk(KERN_ALERT "Could not install sab8253xc device.\n");
+ }
+ else if(result > 0)
+ {
+ sab8253xc_major = result;
+ }
+ }
+
+ for(boardptr = AuraBoardRoot; boardptr != NULL; boardptr = boardptr->nextboard)
+ { /* let's set up port interrupt lists */
+ intr_val = boardptr->b_irq;
+ if((intr_val < 0) || (intr_val >= NUMINTS))
+ {
+ printk(KERN_ALERT "sab8253xn: bad interrupt %i board %p.\n", intr_val, boardptr);
+ continue;
+ }
+ switch(boardptr->b_type)
+ {
+ case BD_WANMCS:
+ boardptr->next_on_interrupt = AuraBoardMCSIrqRoot[intr_val];
+ AuraBoardMCSIrqRoot[intr_val] = boardptr;
+ break;
+ case BD_8520P:
+ case BD_8520CP:
+ boardptr->next_on_interrupt = AuraBoardESCC8IrqRoot[intr_val];
+ AuraBoardESCC8IrqRoot[intr_val] = boardptr;
+ break;
+ default:
+ boardptr->next_on_interrupt = AuraBoardESCC2IrqRoot[intr_val];
+ AuraBoardESCC2IrqRoot[intr_val] = boardptr;
+ break;
+ }
+ }
+
+ for(intr_val = 0; intr_val < NUMINTS; ++intr_val) /* trying to install as few int handlers as possible */
+ { /* one for each group of boards on a given irq */
+ if((AuraBoardESCC2IrqRoot[intr_val] != NULL) || (AuraBoardESCC8IrqRoot[intr_val] != NULL) ||
+ (AuraBoardMCSIrqRoot[intr_val] != NULL))
+ {
+ if (request_irq(intr_val, sab8253x_interrupt, SA_SHIRQ,
+ "sab8253x", &AuraBoardESCC2IrqRoot[intr_val]) == 0)
+ /* interrupts on perboard basis
+ * cycle through chips and then
+ * ports */
+ /* NOTE PLX INTS ARE OFF -- so turn them on */
+ {
+ for(boardptr = AuraBoardESCC2IrqRoot[intr_val]; boardptr != NULL;
+ boardptr = boardptr->next_on_interrupt)
+ {
+ writel(PLX_INT_ON, &(boardptr->b_bridge->intr));
+ }
+ for(boardptr = AuraBoardESCC8IrqRoot[intr_val]; boardptr != NULL;
+ boardptr = boardptr->next_on_interrupt)
+ {
+ writel(PLX_INT_ON, &(boardptr->b_bridge->intr));
+ }
+ for(boardptr = AuraBoardMCSIrqRoot[intr_val]; boardptr != NULL;
+ boardptr = boardptr->next_on_interrupt)
+ {
+ /* write to the MIC csr to reset the PCI interrupt */
+ writeb(0, (unsigned char*)(boardptr->MICCMD_REG + MICCMD_MICCSR));
+
+ /* now, write to the CIM interrupt ena to re-enable interrupt generation */
+ writeb(0, (unsigned char*)(boardptr->CIMCMD_REG + CIMCMD_WRINTENA));
+
+ /* now, activate PCI interrupts */
+ writel(AMCC_AOINTPINENA, (unsigned int*)(boardptr->AMCC_REG + AMCC_INTCSR));
+ }
+ }
+ else
+ {
+ printk(KERN_ALERT "Unable to get interrupt, board set up not complete %i.\n", intr_val);
+ }
+ }
+ }
+
+ /* all done! a lot of work */
+
+#if !defined(MODULE) && (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0))
+ return -1; /* otherwise 2.2 probe uses up
+ * a default device structure*/
+#else
+ return 0;
+#endif
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+#ifdef MODULE
+/* cleanup module/free up virtual memory */
+/* space*/
+void cleanup_module(void)
+#endif
+#else
+void auraXX20_cleanup(void)
+#endif
+{
+ SAB_BOARD *boardptr;
+ SAB_CHIP *chipptr;
+ SAB_PORT *portptr;
+ AURA_CIM *cimptr;
+ int intr_val;
+ extern void sab8253x_cleanup_ttydriver(void);
+
+ printk(KERN_ALERT "auraXX20n: unloading AURAXX20 driver.\n");
+
+ sab8253x_cleanup_ttydriver(); /* clean up tty */
+
+ /* unallocate and turn off ints */
+ for(intr_val = 0; intr_val < NUMINTS; ++intr_val)
+ {
+ if((AuraBoardESCC2IrqRoot[intr_val] != NULL) || (AuraBoardESCC8IrqRoot[intr_val] != NULL) ||
+ (AuraBoardMCSIrqRoot[intr_val] != NULL))
+ {
+ for(boardptr = AuraBoardESCC2IrqRoot[intr_val]; boardptr != NULL;
+ boardptr = boardptr->next_on_interrupt)
+ {
+ writel(PLX_INT_OFF, &(boardptr->b_bridge->intr));
+ }
+ for(boardptr = AuraBoardESCC8IrqRoot[intr_val]; boardptr != NULL;
+ boardptr = boardptr->next_on_interrupt)
+ {
+ writel(PLX_INT_OFF, &(boardptr->b_bridge->intr));
+ }
+ for(boardptr = AuraBoardMCSIrqRoot[intr_val]; boardptr != NULL;
+ boardptr = boardptr->next_on_interrupt)
+ {
+ writel(AMCC_INT_OFF, (unsigned int*)(boardptr->AMCC_REG + AMCC_INTCSR));
+ (void) wanmcs_reset(boardptr);
+ writel(AMCC_INT_OFF, (unsigned int*)(boardptr->AMCC_REG + AMCC_INTCSR));
+ }
+
+ free_irq(intr_val, &AuraBoardESCC2IrqRoot[intr_val]); /* free up board int
+ * note that if two boards
+ * share an int, two int
+ * handlers were registered
+ *
+ */
+ }
+ }
+
+ /* disable chips and free board memory*/
+ while(AuraBoardRoot)
+ {
+ boardptr = AuraBoardRoot;
+ for(chipptr = boardptr->board_chipbase; chipptr != NULL; chipptr = chipptr->next_by_board)
+ {
+ (*chipptr->int_disable)(chipptr); /* make sure no ints can come int */
+ }
+ AuraBoardRoot = boardptr->nextboard;
+ if(boardptr->b_type == BD_WANMCS)
+ {
+ if(boardptr->virtbaseaddress0 != 0)
+ {
+ DEBUGPRINT((KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)boardptr->virtbaseaddress0));
+ iounmap((void*)boardptr->virtbaseaddress0);
+ boardptr->virtbaseaddress0 = 0;
+ }
+
+ if(boardptr->virtbaseaddress1 != 0)
+ {
+ DEBUGPRINT((KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)boardptr->virtbaseaddress1));
+ iounmap((void*)boardptr->virtbaseaddress1);
+ boardptr->virtbaseaddress1 = 0;
+ }
+
+ if(boardptr->virtbaseaddress2 != 0)
+ {
+ DEBUGPRINT((KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)boardptr->virtbaseaddress2));
+ iounmap((void*)boardptr->virtbaseaddress2);
+ boardptr->virtbaseaddress2 = 0;
+ }
+
+ if(boardptr->virtbaseaddress3 != 0)
+ {
+ DEBUGPRINT((KERN_ALERT "auraXX20n: unmapping virtual address %p.\n",
+ (void*)boardptr->virtbaseaddress3));
+ iounmap((void*)boardptr->virtbaseaddress3);
+ boardptr->virtbaseaddress3 = 0;
+ }
+
+ }
+ else /* everything but wan multichannel servers */
+ {
+ if(boardptr->virtbaseaddress0)
+ {
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: unmapping virtual address %p.\n",
+ (void*)boardptr->virtbaseaddress0));
+ iounmap((void*)boardptr->virtbaseaddress0);
+ boardptr->virtbaseaddress0 = 0;
+ }
+ if(boardptr->virtbaseaddress2)
+ {
+ DEBUGPRINT((KERN_ALERT
+ "auraXX20n: unmapping virtual address %p.\n",
+ (void*)boardptr->virtbaseaddress2));
+ iounmap((void*)boardptr->virtbaseaddress2);
+ boardptr->virtbaseaddress2 = 0;
+ }
+ }
+ kfree(boardptr);
+ }
+
+ while(AuraCimRoot)
+ {
+ cimptr = AuraCimRoot;
+ AuraCimRoot = cimptr->next;
+ kfree(cimptr);
+ }
+
+
+ while(AuraChipRoot) /* free chip memory */
+ {
+ chipptr = AuraChipRoot;
+ AuraChipRoot = chipptr->next;
+ kfree(chipptr);
+ }
+
+ if(sab8253xc_name && (sab8253xc_major > 0)) /* unregister the chr device */
+ {
+ unregister_chrdev(sab8253xc_major, sab8253xc_name);
+ }
+
+ while(Sab8253xRoot) /* free up network stuff */
+ {
+ SAB_PORT *priv;
+ priv = (SAB_PORT *)Sab8253xRoot->priv;
+ unregister_netdev(Sab8253xRoot);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+ kfree(Sab8253xRoot.name);
+#endif
+ kfree(Sab8253xRoot);
+ Sab8253xRoot = priv->next_dev;
+ }
+
+ while(AuraPortRoot) /* free up port memory */
+ {
+ portptr = AuraPortRoot;
+ AuraPortRoot = portptr->next;
+ if(portptr->dcontrol2.receive)
+ {
+ kfree(portptr->dcontrol2.receive);
+ }
+ if(portptr->dcontrol2.transmit)
+ {
+ kfree(portptr->dcontrol2.transmit);
+ }
+ kfree(portptr);
+ }
+}
+
+/*
+ * Hardware dependent read and write functions.
+ * We have functions to write/read a byte, write/read
+ * a word and read and write the FIFO
+ */
+
+
+/***************************************************************************
+ * aura_readb: Function to read a byte on a 4X20P, 8X20P or Sun serial
+ *
+ *
+ * Parameters :
+ * port: The port being accessed
+ * reg: The address of the register
+ *
+ * Return value : The value of the register.
+ *
+ * Prerequisite : The port must have been opened
+ *
+ * Remark :
+ *
+ * Author : fw
+ *
+ * Revision : Oct 10 2000, creation
+ ***************************************************************************/
+
+static unsigned char aura_readb(struct sab_port *port, unsigned char *reg)
+{
+ return readb(reg);
+}
+
+/***************************************************************************
+ * aura_writeb: Function to write a byte on a 4X20P, 8X20P or Sun serial
+ *
+ *
+ * Parameters :
+ * port: The port being accessed
+ * reg: The address of the register
+ * val: The value to put into the register
+ *
+ * Return value : None
+ *
+ * Prerequisite : The port must have been opened
+ *
+ * Remark :
+ *
+ * Author : fw
+ *
+ * Revision : Oct 10 2000, creation
+ ***************************************************************************/
+
+static void aura_writeb(struct sab_port *port, unsigned char *reg,unsigned char val)
+{
+ writeb(val,reg);
+}
+
+/***************************************************************************
+ * aura_readw: Function to read a word on a 4X20P, 8X20P or Sun serial
+ *
+ *
+ * Parameters :
+ * port: The port being accessed
+ * reg: The address of the hw memory to access
+ *
+ * Return value : The value of the memory area.
+ *
+ * Prerequisite : The port must have been opened
+ *
+ * Remark :
+ *
+ * Author : fw
+ *
+ * Revision : Oct 10 2000, creation
+ ***************************************************************************/
+static unsigned short aura_readw(struct sab_port *port, unsigned short *reg)
+{
+ return readw(reg);
+}
+
+/***************************************************************************
+ * aura_writew: Function to write a word on a 4X20P, 8X20P or Sun serial
+ *
+ *
+ * Parameters :
+ * port: The port being accessed
+ * reg: The address of the hw memory to access
+ * val: The value to put into the register
+ *
+ * Return value : The value of the memory area.
+ *
+ * Prerequisite : The port must have been opened
+ *
+ * Remark :
+ *
+ * Author : fw
+ *
+ * Revision : Oct 10 2000, creation
+ ***************************************************************************/
+
+static void aura_writew(struct sab_port *port, unsigned short *reg,unsigned short val)
+{
+ writew(val,reg);
+}
+
+/***************************************************************************
+ * aura_readfifo: Function to read the FIFO on a 4X20P, 8X20P or Sun serial
+ *
+ *
+ * Parameters :
+ * port: The port being accessed
+ * buf: The address of a buffer where we should put
+ * what we read
+ * nbytes: How many chars to read.
+ *
+ * Return value : none
+ *
+ * Prerequisite : The port must have been opened
+ *
+ * Remark :
+ *
+ * Author : fw
+ *
+ * Revision : Oct 13 2000, creation
+ ***************************************************************************/
+static void aura_readfifo(struct sab_port *port, unsigned char *buf, unsigned int nbytes)
+{
+ int i;
+ unsigned short *wptr = (unsigned short*) buf;
+ int nwords = ((nbytes+1)/2);
+ for(i = 0; i < nwords; i ++)
+ {
+ wptr[i] = readw(((unsigned short *)port->regs));
+ }
+}
+
+/***************************************************************************
+ * aura_writefifo: Function to write the FIFO on a 4X20P, 8X20P or Sun serial
+ *
+ *
+ * Parameters :
+ * port: The port being accessed
+ *
+ * Return value : none
+ *
+ * Prerequisite : The port must have been opened
+ *
+ * Remark :
+ *
+ * Author : fw
+ *
+ * Revision : Oct 13 2000, creation
+ ***************************************************************************/
+static void aura_writefifo(struct sab_port *port)
+{
+ int i,max,maxw;
+ unsigned short *wptr;
+ unsigned char buffer[32];
+
+ if(port->xmit_cnt <= 0)
+ {
+ return;
+ }
+ max= (port->xmit_fifo_size < port->xmit_cnt) ? port->xmit_fifo_size : port->xmit_cnt;
+
+ for (i = 0; i < max; i++)
+ {
+ buffer[i] = port->xmit_buf[port->xmit_tail++];
+ port->xmit_tail &= (SAB8253X_XMIT_SIZE - 1);
+ port->icount.tx++;
+ port->xmit_cnt--;
+ }
+
+ maxw = max/2;
+ wptr = (unsigned short*) buffer;
+
+ for(i = 0; i < maxw; ++i)
+ {
+ writew(wptr[i], (unsigned short *)port->regs);
+ }
+
+ if(max & 1)
+ {
+ writeb(buffer[max-1], (unsigned char*)port->regs);
+ }
+}
+
+/***************************************************************************
+ * wmsaura_readb: Function to read a byte on a LMS, WMS
+ *
+ *
+ * Parameters :
+ * port: The port being accessed
+ * reg: The address of the register
+ *
+ * Return value : The value of the register.
+ *
+ * Prerequisite : The port must have been opened
+ *
+ * Remark : TO BE IMPLEMENTED
+ *
+ * Author : fw
+ *
+ * Revision : Oct 10 2000, creation
+ ***************************************************************************/
+
+static unsigned char wmsaura_readb(struct sab_port *port, unsigned char *reg)
+{
+ return readb((unsigned char*) (((unsigned int) reg) + CIMCMD_RDREGB));
+}
+
+/***************************************************************************
+ * wmsaura_writeb: Function to write a byte on a LMS, WMS
+ *
+ *
+ * Parameters :
+ * port: The port being accessed
+ * reg: The address of the register
+ * val: The value to put into the register
+ *
+ * Return value : None
+ *
+ * Prerequisite : The port must have been opened
+ *
+ * Remark : TO BE IMPLEMENTED
+ *
+ * Author : fw
+ *
+ * Revision : Oct 10 2000, creation
+ ***************************************************************************/
+
+static void wmsaura_writeb(struct sab_port *port, unsigned char *reg,unsigned char val)
+{
+ writeb(val, (unsigned char*) (((unsigned int) reg) + CIMCMD_WRREGB));
+}
+
+/***************************************************************************
+ * wmsaura_readw: Function to read a word on a LMS, WMS
+ *
+ *
+ * Parameters :
+ * port: The port being accessed
+ * reg: The address of the hw memory to access
+ *
+ * Return value : The value of the memory area.
+ *
+ * Prerequisite : The port must have been opened
+ *
+ * Remark : TO BE IMPLEMENTED
+ *
+ * Author : fw
+ *
+ * Revision : Oct 10 2000, creation
+ ***************************************************************************/
+static unsigned short wmsaura_readw(struct sab_port *port, unsigned short *reg)
+{
+ unsigned short readval;
+ unsigned int address;
+ address = (unsigned int) reg;
+
+ readval = readb((unsigned char*) (address + CIMCMD_RDREGB));
+ ++address;
+ return (readval | (readb((unsigned char*) (address + CIMCMD_RDREGB)) << 8));
+}
+
+/***************************************************************************
+ * wmsaura_writew: Function to write a word on a LMS, WMS
+ *
+ *
+ * Parameters :
+ * port: The port being accessed
+ * reg: The address of the hw memory to access
+ * val: The value to put into the register
+ *
+ * Return value : The value of the memory area.
+ *
+ * Prerequisite : The port must have been opened
+ *
+ * Remark : TO BE IMPLEMENTED
+ *
+ * Author : fw
+ *
+ * Revision : Oct 10 2000, creation
+ ***************************************************************************/
+
+static void wmsaura_writew(struct sab_port *port, unsigned short *reg, unsigned short val)
+{
+ unsigned char vallow;
+ unsigned char valhigh;
+ unsigned int address;
+
+ address = (unsigned int) reg;
+
+ vallow = (unsigned char) val;
+ valhigh = (unsigned char) (val >> 8);
+
+ writeb(vallow, (unsigned char*) (address + CIMCMD_WRREGB));
+ ++address;
+ writeb(valhigh, (unsigned char*) (address + CIMCMD_WRREGB));
+}
+
+static void wmsaura_readfifo(struct sab_port *port, unsigned char *buf, unsigned int nbytes)
+{
+#ifdef FIFO_DIRECT
+ unsigned short fifo[32/2]; /* this array is word aligned
+ * buf may not be word aligned*/
+ unsigned int nwords;
+ int i;
+ int wcount;
+ unsigned int address;
+
+ if (nbytes == 0)
+ {
+ return;
+ }
+
+ wcount = ((nbytes + 1) >> 1);
+ /* Read the thing into the local FIFO and copy it out. */
+ address = (unsigned int) port->regs;
+
+ for(i = 0; i < wcount; ++i)
+ {
+ fifo[i] = readw((unsigned short*)(address + CIMCMD_RDFIFOW));
+ }
+
+ memcpy((unsigned char*) buf, (unsigned char*) &(fifo[0]), (unsigned int) nbytes);
+
+#else /* FIFO_DIRECT */
+ unsigned short fifo[32/2];
+ int i;
+ int wcount;
+ SAB_BOARD *bptr;
+ unsigned int channel;
+
+ if (nbytes == 0)
+ {
+ return;
+ }
+
+ bptr = port->board;
+ wcount = ((nbytes + 1) >> 1);
+ channel = (((unsigned char*) port->regs) - bptr->CIMCMD_REG); /* should be properly shifted */
+
+ /*
+ * Trigger a cache read by writing the nwords - 1 to the
+ * magic place.
+ */
+
+ writeb((unsigned char) wcount, bptr->MICCMD_REG + (MICCMD_CACHETRIG + channel));
+
+ /*
+ * Now, read out the contents.
+ */
+
+ channel >>= 1;
+
+ for(i = 0; i < wcount; ++i)
+ {
+ fifo[i] = readw((unsigned short*)(bptr->FIFOCACHE_REG + (channel + (i << 1))));
+ }
+
+ memcpy((unsigned char*) buf, (unsigned char*) &(fifo[0]), (unsigned int) nbytes);
+#endif /* !FIFO_DIRECT */
+}
+
+static void wmsaura_writefifo(struct sab_port *port)
+{
+ unsigned short fifo[32/2];
+ unsigned char* fifob = (unsigned char*) fifo;
+ int i,max;
+ int wcount;
+ unsigned int address;
+
+ if(port->xmit_cnt <= 0)
+ {
+ return;
+ }
+ max = (port->xmit_fifo_size < port->xmit_cnt) ? port->xmit_fifo_size:port->xmit_cnt;
+ for (i = 0; i < max; i++)
+ {
+ fifob[i] = port->xmit_buf[port->xmit_tail++];
+ port->xmit_tail &= (SAB8253X_XMIT_SIZE - 1);
+ port->icount.tx++;
+ port->xmit_cnt--;
+ }
+
+ wcount = (max >> 1);
+ /* Copy from the linear local FIFO into the hardware fifo. */
+ address = (unsigned int) port->regs;
+
+ for(i = 0; i < wcount; ++i)
+ {
+ writew(fifo[i], (unsigned short*)(address + CIMCMD_WRFIFOW));
+ }
+ if(max & 1) /* odd byte */
+ {
+ --max;
+ writeb(fifob[max], (unsigned short*)(address + CIMCMD_WRFIFOB));
+ }
+}
+
+module_init(auraXX20_probe);
+module_exit(auraXX20_cleanup);
+MODULE_DESCRIPTION("Aurora Multiport Multiprotocol Serial Driver");
+MODULE_AUTHOR("Joachim Martillo <martillo@telfordtools.com>");
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)