Support generic MP (RFC 1717)
CONFIG_ISDN_MPP
With synchronous PPP enabled, it is possible to increase throughput
- by bundling several ISDN-connections, using this protocol. See
- Documentation/isdn/README.syncppp for more information.
+ by bundling several ISDN-connections, using this protocol.
+ See Documentation/isdn/README.syncppp for more information.
Use VJ-compression with synchronous PPP
CONFIG_ISDN_PPP_VJ
Support for german chargeinfo
CONFIG_DE_AOC
-If you have german AOC, you can enable this to get the charginfo.
+ If you have german AOC, you can enable this to get the charginfo.
Disable sending complete
CONFIG_HISAX_NO_SENDCOMPLETE
-If you have trouble with some ugly exchanges or you live in Australia
-select this option.
+ If you have trouble with some ugly exchanges or you live in
+ Australia select this option.
Disable sending low layer compatibility
CONFIG_HISAX_NO_LLC
-If you have trouble with some ugly exchanges try to select this
-option.
+ If you have trouble with some ugly exchanges try to select this
+ option.
HiSax Support for german 1TR6
CONFIG_HISAX_1TR6
-Enable this if you have a old german 1TR6 line.
-Note: Many older local switches are using 1TR6 on internal S0.
+ Enable this if you have a old german 1TR6 line.
+ Note: Many older local switches are using 1TR6 on internal S0.
HiSax Support for Teles 16.0/8.0
CONFIG_HISAX_16_0
This enables HiSax support for the Teles ISDN-cards S0-16.0,
S0-8 and many compatibles.
- See Documentation/isdn/README.HiSax on how to configure it
- using the different cards, a different D-channel protocol, or
- non-standard IRQ/port/shmem settings.
+ See Documentation/isdn/README.HiSax on how to configure it using the
+ different cards, a different D-channel protocol, or non-standard
+ IRQ/port/shmem settings.
HiSax Support for Teles 16.3 or PNP or PCMCIA
CONFIG_HISAX_16_3
This enables HiSax support for the Teles ISDN-cards S0-16.3
the Teles/Creatix PnP and the Teles PCMCIA.
- See Documentation/isdn/README.HiSax on how to configure it
- using the different cards, a different D-channel protocol, or
- non-standard IRQ/port settings.
+ See Documentation/isdn/README.HiSax on how to configure it using the
+ different cards, a different D-channel protocol, or non-standard
+ IRQ/port settings.
HiSax Support for Teles 16.3c
CONFIG_HISAX_TELES3C
HiSax Support for Teles S0Box
CONFIG_HISAX_S0BOX
- This enables HiSax support for the Teles/Creatix parallel port S0BOX.
- See Documentation/isdn/README.HiSax on how to configure it.
+ This enables HiSax support for the Teles/Creatix parallel port
+ S0BOX. See Documentation/isdn/README.HiSax on how to configure it.
HiSax Support for AVM A1 (Fritz)
CONFIG_HISAX_AVM_A1
This enables HiSax support for the AVM A1 (aka "Fritz!").
- See Documentation/isdn/README.HiSax on how to configure it
- using the different cards, a different D-channel protocol, or
- non-standard IRQ/port settings.
+ See Documentation/isdn/README.HiSax on how to configure it using the
+ different cards, a different D-channel protocol, or non-standard
+ IRQ/port settings.
HiSax Support for AVM PCI (Fritz!PCI)
CONFIG_HISAX_FRITZPCI
HiSax Support for Elsa ISA cards
CONFIG_HISAX_ELSA
This enables HiSax support for all Elsa cards.
- See Documentation/isdn/README.HiSax on how to configure it
- using the different cards, a different D-channel protocol, or
- non-standard IRQ/port settings.
+ See Documentation/isdn/README.HiSax on how to configure it using the
+ different cards, a different D-channel protocol, or non-standard
+ IRQ/port settings.
+
HiSax Support for ITK ix1-micro Revision 2
CONFIG_HISAX_IX1MICROR2
HiSax Support for Eicon.Diehl Diva cards
CONFIG_HISAX_DIEHLDIVA
- This enables HiSax support for all none Pro versions of Eicon.Diehl's
- Diva series passiv cards.
+ This enables HiSax support for all none Pro versions of
+ Eicon.Diehl's Diva series passiv cards.
See Documentation/isdn/README.HiSax on how to configure it.
HiSax Support for ASUSCOM cards
CONFIG_HISAX_ASUSCOM
- This enables HiSax support for all AsusCom passiv cards.
+ This enables HiSax support for all passiv AsusCom and AsusComs OEM cards,
+ e.g PCBIT-DP, Dynalink and much more.
See Documentation/isdn/README.HiSax on how to configure it.
HiSax Support for TELEINT cards
CONFIG_HISAX_TELEINT
- This enables HiSax support for TeleInts semi-activ card and for other
- HFC-2BS0 based cards
+ This enables HiSax support for TeleInts semi-activ card and for
+ other HFC-2BS0 based cards.
See Documentation/isdn/README.HiSax on how to configure it.
-HiSax Support for Sedlbauer speed card/win/star/PC104/fax
+HiSax Support for Sedlbauer cards
CONFIG_HISAX_SEDLBAUER
- This enables HiSax support for all Sedlbauer passiv cards.
+ This enables HiSax support for all Sedlbauer passiv cards such as
+ Sedlbauer Speed Card (Speed Win, Teledat 100), Speed Star
+ and Speed Star2 (PCMCIA), ISDN-Controller PC/104, Speed PCI and
+ Speed Fax+.
+
See Documentation/isdn/README.HiSax on how to configure it.
HiSax Support for USR Sportster internal TA
CONFIG_HISAX_SPORTSTER
- This enables HiSax support for the USR (3Com) Sportster internal TA passiv card.
+ This enables HiSax support for the USR (3Com) Sportster internal TA
+ passiv card.
See Documentation/isdn/README.HiSax on how to configure it.
HiSax Support for MIC card
HiSax Support for NETjet card
CONFIG_HISAX_NETJET
- This enables HiSax support for the NetJet PCI and maybe for other
+ This enables HiSax support for the NetJet PCI and maybe for other
Tiger300 based passiv cards.
See Documentation/isdn/README.HiSax on how to configure it.
This enables support for the PCBIT ISDN-cards. This card is
manufactured in Portugal by Octal. For running this card, additional
firmware is necessary, which has to be downloaded into the card
- using a utility which is distributed separately. See
- Documentation/isdn/README and Documentation/isdn/README.pcbit for
- more information.
+ using a utility which is distributed separately.
+ See Documentation/isdn/README and Documentation/isdn/README.pcbit
+ for more information.
Spellcaster support (EXPERIMENTAL)
CONFIG_ISDN_DRV_SC
Eicon.Diehl Diva Piccola
ASUSCOM NETWORK INC. ISDNLink 128K PC adapter (order code I-IN100-ST-D)
Dynalink IS64PH (OEM version of ASUSCOM NETWORK INC. ISDNLink 128K adapter)
+PCBIT-DP (OEM version of ASUSCOM NETWORK INC. ISDNLink)
HFC-2BS0 based cards (TeleInt SA1)
-Sedlbauer Speed Card (Speed Win, Teledat 100)
-Sedlbauer Speed Star (PCMCIA)
+Sedlbauer Speed Card (Speed Win, Teledat 100, PCI, Fax+)
+Sedlbauer Speed Star/Speed Star2 (PCMCIA)
Sedlbauer ISDN-Controller PC/104
USR Sportster internal TA (compatible Stollmann tina-pp V3)
ith Kommunikationstechnik GmbH MIC 16 ISA card
11 Eicon.Diehl Diva ISA PnP irq, io
11 Eicon.Diehl Diva PCI no parameter
12 ASUS COM ISDNLink irq, io (from isapnp setup)
- 13 HFC-2BS0 based cards irq, io
+ 13 HFC-2BS0 based cards irq, io
14 Teles 16.3c PnP irq, io
- 15 Sedlbauer Speed Card irq, io
- 16 USR Sportster internal irq, io
- 17 MIC card irq, io
+ 15 Sedlbauer Speed Card irq, io
+ 16 USR Sportster internal irq, io
+ 17 MIC card irq, io
18 ELSA Quickstep 1000PCI no parameter
19 Compaq ISDN S0 ISA card irq, io0, io1, io (from isapnp setup io=IO2)
20 NETjet PCI card no parameter
25 Teles S0Box irq, io (of the used lpt port)
26 AVM A1 PCMCIA (Fritz!) irq, io (set with card manager)
27 AVM PCI (Fritz!PCI) no parameter
+ 28 Sedlbauer Speed Fax+ irq, io (from isapnp setup)
At the moment IRQ sharing is only possible with PCI cards. Please make sure
Note: the ID string must start with an alphabetical character!
Card types:
-
- type
+
+type
1 Teles 16.0 pa=irq pb=membase pc=iobase
2 Teles 8.0 pa=irq pb=membase
3 Teles 16.3 pa=irq pb=iobase
12 ASUS COM ISDNLink ONLY WORKS AS A MODULE !
13 HFC-2BS0 based cards pa=irq pb=io
14 Teles 16.3c PnP ONLY WORKS AS A MODULE !
- 15 Sedlbauer Speed Card pa=irq pb=io (Speed Win only as module !)
+ 15 Sedlbauer Speed Card pa=irq pb=io (Speed Win only as module !)
16 USR Sportster internal pa=irq pb=io
17 MIC card pa=irq pb=io
18 ELSA Quickstep 1000PCI no parameter
25 Teles S0Box irq, io (of the used lpt port)
26 AVM A1 PCMCIA (Fritz!) irq, io (set with card manager)
27 AVM PCI (Fritz!PCI) no parameter
+ 28 Sedlbauer Speed Fax+ ONLY WORKS AS A MODULE !
+
Running the driver
------------------
Firma Traverse Technologie Australia
Firma Medusa GmbH (www.medusa.de).
Firma Quant-X Austria for sponsoring a DEC Alpha board+CPU
+ Firma Cologne Chip Designs GmbH
My girl friend and partner in life Ute for her patience with me.
L: linux-kernel@vger.rutgers.edu
S: Maintained
-ISDN SUBSYSTEM
+ISDN SUBSYSTEM [GENERAL]
P: Fritz Elfert
-M: fritz@wuemaus.franken.de
+M: fritz@isdn4linux.de
L: isdn4linux@hub-wue.franken.de
+W: http://www.isdn4linux.de
+S: Maintained
+
+ISDN SUBSYSTEM HISAX
+P: Karsten Keil
+M: keil@isdn4linux.de
+L: isdn4linux@hub-wue.franken.de
+W: http://www.isdn4linux.de
S: Maintained
MODULE SUPPORT [GENERAL], KERNELD
# define CDU535_MESSAGE_NAME "Sony CDU-535"
#endif
+#define CDU535_BLOCK_SIZE 2048
+
#ifndef MAX_SPINUP_RETRY
# define MAX_SPINUP_RETRY 3 /* 1 is sufficient for most drives... */
#endif
* it returns one of the standard error returns.
***************************************************************************/
-static int sonycd535_block_size = 2048;
-
static int
seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2],
Byte **buff, int buf_size)
Byte *data_buff;
int sector_count = 0;
- if (buf_size < sonycd535_block_size * n_blocks)
+ if (buf_size < CDU535_BLOCK_SIZE * n_blocks)
return NO_ROOM;
set_drive_mode(SONY535_CDROM_DRIVE_MODE, status);
if ((read_status & SONY535_DATA_NOT_READY_BIT) == 0) {
/* data is ready, read it */
data_buff = buff[sector_count++];
- for (i = 0; i < sonycd535_block_size; i++)
+ for (i = 0; i < CDU535_BLOCK_SIZE; i++)
*data_buff++ = inb(data_reg); /* unrolling this loop does not seem to help */
break; /* exit the timeout loop */
}
/* read all the data, now read the status */
if ((i = read_exec_status(status)) != 0)
return i;
- return sonycd535_block_size * sector_count;
+ return CDU535_BLOCK_SIZE * sector_count;
} /* seek_and_read_N_blocks() */
/****************************************************************************
* The OS calls this to perform a read or write operation to the drive.
* Write obviously fail. Reads to a read ahead of sony_buffer_size
* bytes to help speed operations. This especially helps since the OS
- * uses 1024 byte blocks and the drive uses 2048 byte blocks. Since most
+ * may use 1024 byte blocks and the drive uses 2048 byte blocks. Since most
* data access on a CD is done sequentially, this saves a lot of operations.
*/
static void
* seek_and_read_N_blocks for the various cases.
*/
int readStatus = seek_and_read_N_blocks(params, read_size,
- status, sony_buffer, (read_size * 2048));
+ status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
if (0 <= readStatus) /* Good data; common case, placed first */
break;
if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
NULL /* revalidate */
};
+static int sonycd535_block_size = CDU535_BLOCK_SIZE;
+
/*
* Initialize the driver.
*/
if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) == 0) {
/* set the drive mode successful, we are set! */
sony_buffer_size = SONY535_BUFFER_SIZE;
- sony_buffer_sectors = sony_buffer_size / 2048;
+ sony_buffer_sectors = sony_buffer_size / CDU535_BLOCK_SIZE;
printk(KERN_INFO CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s",
drive_config.vendor_id,
return -ENOMEM;
}
for (i = 0; i < sony_buffer_sectors; i++) {
- sony_buffer[i] = (Byte *)kmalloc(2048, GFP_KERNEL);
+ sony_buffer[i] =
+ (Byte *)kmalloc(CDU535_BLOCK_SIZE, GFP_KERNEL);
if (sony_buffer[i] == NULL) {
while (--i>=0)
kfree(sony_buffer[i]);
release_region(sony535_cd_base_io, 4);
for (i = 0; i < sony_buffer_sectors; i++)
- kfree_s(sony_buffer[i], 2048);
+ kfree_s(sony_buffer[i], CDU535_BLOCK_SIZE);
kfree_s(sony_buffer, 4 * sony_buffer_sectors);
kfree_s(last_sony_subcode, sizeof *last_sony_subcode);
kfree_s(sony_toc, sizeof *sony_toc);
bool 'HiSax Support for Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA
bool 'HiSax Support for ASUSCOM cards' CONFIG_HISAX_ASUSCOM
bool 'HiSax Support for TELEINT cards' CONFIG_HISAX_TELEINT
- bool 'HiSax Support for Sedlbauer speed card/win/star/PC104/fax' CONFIG_HISAX_SEDLBAUER
+ bool 'HiSax Support for Sedlbauer cards' CONFIG_HISAX_SEDLBAUER
bool 'HiSax Support for USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
bool 'HiSax Support for MIC card' CONFIG_HISAX_MIC
bool 'HiSax Support for NETjet card' CONFIG_HISAX_NETJET
ISAC_OBJ :=
ARCOFI_OBJ :=
HSCX_OBJ :=
+ISAR_OBJ :=
HFC_OBJ :=
HFC_2BDS0 :=
O_OBJS += sedlbauer.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
+ ISAR_OBJ := isar.o
endif
ifeq ($(CONFIG_HISAX_SPORTSTER),y)
HSCX_OBJ := hscx.o
endif
-O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(ARCOFI_OBJ)
+O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(ISAR_OBJ) $(ARCOFI_OBJ)
O_OBJS += $(HFC_OBJ) $(HFC_2BDS0)
OX_OBJS += config.o
-/* $Id: avm_pci.c,v 1.1.2.3 1998/09/27 23:52:57 keil Exp $
+/* $Id: avm_pci.c,v 1.1.2.5 1998/10/13 18:38:50 keil Exp $
* avm_pci.c low level stuff for AVM Fritz!PCI isdn cards
* Thanks to AVM, Berlin for informations
*
*
* $Log: avm_pci.c,v $
+ * Revision 1.1.2.5 1998/10/13 18:38:50 keil
+ * Fix PCI detection
+ *
+ * Revision 1.1.2.4 1998/10/04 23:03:41 keil
+ * PCI has 255 device entries
+ *
* Revision 1.1.2.3 1998/09/27 23:52:57 keil
* Fix error handling
*
#include <linux/interrupt.h>
extern const char *CardType[];
-static const char *avm_pci_rev = "$Revision: 1.1.2.3 $";
+static const char *avm_pci_rev = "$Revision: 1.1.2.5 $";
#define PCI_VENDOR_AVM 0x1244
#define PCI_FRITZPCI_ID 0xa00
return(0);
}
cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
+ break;
}
- if (pci_index == 8) {
+ if (pci_index == 255) {
printk(KERN_WARNING "FritzPCI: No PCI card found\n");
return(0);
}
-/* $Id: config.c,v 1.15.2.16 1998/09/27 13:05:48 keil Exp $
+/* $Id: config.c,v 1.15.2.18 1998/10/13 10:27:26 keil Exp $
* Author Karsten Keil (keil@temic-ech.spacenet.de)
* based on the teles driver from Jan den Ouden
*
*
* $Log: config.c,v $
+ * Revision 1.15.2.18 1998/10/13 10:27:26 keil
+ * New cards, minor fixes
+ *
+ * Revision 1.15.2.17 1998/10/11 19:31:31 niemann
+ * Fixed problems with CONFIG_MODVERSIONS for sedlbauer cards
+ *
* Revision 1.15.2.16 1998/09/27 13:05:48 keil
* Apply most changes from 2.1.X (HiSax 3.1)
*
#include <linux/config.h>
#include "hisax.h"
#include <linux/module.h>
+
/*
* This structure array contains one entry per card. An entry looks
* like this:
* 25 Teles S0Box p0=irq p1=iobase (from isapnp setup)
* 26 AVM A1 PCMCIA (Fritz) p0=irq p1=iobase
* 27 AVM PCI (Fritz!PCI) no parameter
- * 28 reserved
+ * 28 Sedlbauer Speed Fax+ p0=irq p1=iobase (from isapnp setup)
*
* protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1
*
#ifdef CONFIG_HISAX_ELSA
#define DEFAULT_CARD ISDN_CTYPE_ELSA
#define DEFAULT_CFG {0,0,0,0}
-#ifdef MODULE
int elsa_init_pcmcia(void*, int, int*, int);
+#ifdef MODULE
static struct symbol_table hisax_syms_elsa = {
#include <linux/symtab_begin.h>
X(elsa_init_pcmcia),
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_A1_PCMCIA
#define DEFAULT_CFG {11,0x170,0,0}
-#ifdef MODULE
int avm_a1_init_pcmcia(void*, int, int*, int);
void HiSax_closecard(int cardnr);
+#ifdef MODULE
static struct symbol_table hisax_syms_avm_a1= {
#include <linux/symtab_begin.h>
X(avm_a1_init_pcmcia),
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_SEDLBAUER
#define DEFAULT_CFG {11,0x270,0,0}
-#ifdef MODULE
int sedl_init_pcmcia(void*, int, int*, int);
static struct symbol_table hisax_syms_sedl= {
#include <linux/symtab_begin.h>
X(sedl_init_pcmcia),
#include <linux/symtab_end.h>
};
-void register_sedl_symbols(void) {
- register_symtab(&hisax_syms_sedl);
-}
-#endif
#endif
#ifdef CONFIG_HISAX_SPORTSTER
#ifdef CONFIG_HISAX_SEDLBAUER
if (type[0] == ISDN_CTYPE_SEDLBAUER_PCMCIA) {
/* we have to export and return in this case */
+ register_symtab(&hisax_syms_sedl);
return 0;
}
#endif
return (0);
}
#endif
+#endif
+
#ifdef CONFIG_HISAX_SEDLBAUER
int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
{
+#ifdef MODULE
int i;
int nzproto = 0;
TeiNew();
HiSax_inithardware(busy_flag);
printk(KERN_NOTICE "HiSax: module installed\n");
+#endif
return (0);
}
#endif
+#ifdef MODULE
#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
{
-/* $Id: hisax.h,v 1.13.2.15 1998/09/30 22:28:04 keil Exp $
+/* $Id: hisax.h,v 1.13.2.17 1998/10/11 19:33:48 niemann Exp $
* Basic declarations, defines and prototypes
*
* $Log: hisax.h,v $
+ * Revision 1.13.2.17 1998/10/11 19:33:48 niemann
+ * Added new IPAC based cards.
+ * Code cleanup and simplified (sedlbauer.c)
+ *
+ * Revision 1.13.2.16 1998/10/04 23:04:54 keil
+ * ISAR works now
+ *
* Revision 1.13.2.15 1998/09/30 22:28:04 keil
* more work for isar support
*
u_char *rcvbuf; /* B-Channel receive Buffer */
};
+struct isar_reg {
+ unsigned int Flags;
+ volatile u_char bstat;
+ volatile u_char iis;
+ volatile u_char cmsb;
+ volatile u_char clsb;
+ volatile u_char par[8];
+};
+
struct isar_hw {
int dpath;
int rcvidx;
int txcnt;
+ int mml;
u_char *rcvbuf; /* B-Channel receive Buffer */
+ struct isar_reg *reg;
};
struct hdlc_hw {
unsigned int adr;
unsigned int isac;
unsigned int hscx;
- unsigned int isar;
unsigned int reset_on;
unsigned int reset_off;
- volatile u_char bstat;
- volatile u_char iis;
- volatile u_char cmsb;
- volatile u_char clsb;
- volatile u_char par[8];
+ struct isar_reg isar;
+ unsigned int chip;
+ unsigned int bus;
};
struct spt_hw {
--- /dev/null
+/* $Id: isar.c,v 1.1.2.3 1998/10/04 23:04:58 keil Exp $
+
+ * isar.c ISAR (Siemens PSB 7110) specific routines
+ *
+ * Author Karsten Keil (keil@isdn4linux.de)
+ *
+ *
+ * $Log: isar.c,v $
+ * Revision 1.1.2.3 1998/10/04 23:04:58 keil
+ * ISAR works now
+ *
+ * Revision 1.1.2.2 1998/09/30 22:28:07 keil
+ * more work for isar support
+ *
+ * Revision 1.1.2.1 1998/09/27 13:01:43 keil
+ * Start support for ISAR based cards
+ *
+ * Revision 1.1 1998/08/13 23:33:47 keil
+ * First version, only init
+ *
+ *
+ */
+
+#define __NO_VERSION__
+#include "hisax.h"
+#include "isar.h"
+#include "isdnl1.h"
+#include <linux/interrupt.h>
+
+#define DBG_LOADFIRM 0
+#define DUMP_MBOXFRAME 2
+
+#define MIN(a,b) ((a<b)?a:b)
+
+void isar_setup(struct IsdnCardState *cs);
+
+static inline int
+waitforHIA(struct IsdnCardState *cs, int timeout)
+{
+
+ while ((cs->BC_Read_Reg(cs, 0, ISAR_HIA) & 1) && timeout) {
+ udelay(1);
+ timeout--;
+ }
+ if (!timeout)
+ printk(KERN_WARNING "HiSax: ISAR waitforHIA timeout\n");
+ return(timeout);
+}
+
+
+int
+sendmsg(struct IsdnCardState *cs, u_char his, u_char creg, u_char len,
+ u_char *msg)
+{
+ long flags;
+ int i;
+
+ if (!waitforHIA(cs, 4000))
+ return(0);
+#if DUMP_MBOXFRAME
+ if (cs->debug & L1_DEB_HSCX) {
+ char tmp[32];
+
+ sprintf(tmp, "sendmsg(%02x,%02x,%d)", his, creg, len);
+ debugl1(cs, tmp);
+ }
+#endif
+ save_flags(flags);
+ cli();
+ cs->BC_Write_Reg(cs, 0, ISAR_CTRL_H, creg);
+ cs->BC_Write_Reg(cs, 0, ISAR_CTRL_L, len);
+ cs->BC_Write_Reg(cs, 0, ISAR_WADR, 0);
+ if (msg && len) {
+ cs->BC_Write_Reg(cs, 1, ISAR_MBOX, msg[0]);
+ for (i=1; i<len; i++)
+ cs->BC_Write_Reg(cs, 2, ISAR_MBOX, msg[i]);
+#if DUMP_MBOXFRAME>1
+ if (cs->debug & L1_DEB_HSCX_FIFO) {
+ char tmp[256], *t;
+
+ i = len;
+ while (i>0) {
+ t = tmp;
+ t += sprintf(t, "sendmbox cnt %d", len);
+ QuickHex(t, &msg[len-i], (i>64) ? 64:i);
+ debugl1(cs, tmp);
+ i -= 64;
+ }
+ }
+#endif
+ }
+ cs->BC_Write_Reg(cs, 1, ISAR_HIS, his);
+ restore_flags(flags);
+ waitforHIA(cs, 10000);
+ return(1);
+}
+
+/* Call only with IRQ disabled !!! */
+inline void
+rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u_char *msg)
+{
+ int i;
+
+ cs->BC_Write_Reg(cs, 1, ISAR_RADR, 0);
+ if (msg && ireg->clsb) {
+ msg[0] = cs->BC_Read_Reg(cs, 1, ISAR_MBOX);
+ for (i=1; i < ireg->clsb; i++)
+ msg[i] = cs->BC_Read_Reg(cs, 2, ISAR_MBOX);
+#if DUMP_MBOXFRAME>1
+ if (cs->debug & L1_DEB_HSCX_FIFO) {
+ char tmp[256], *t;
+
+ i = ireg->clsb;
+ while (i>0) {
+ t = tmp;
+ t += sprintf(t, "rcv_mbox cnt %d", ireg->clsb);
+ QuickHex(t, &msg[ireg->clsb-i], (i>64) ? 64:i);
+ debugl1(cs, tmp);
+ i -= 64;
+ }
+ }
+#endif
+ }
+ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+}
+
+/* Call only with IRQ disabled !!! */
+inline void
+get_irq_infos(struct IsdnCardState *cs, struct isar_reg *ireg)
+{
+ ireg->iis = cs->BC_Read_Reg(cs, 1, ISAR_IIS);
+ ireg->cmsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_H);
+ ireg->clsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_L);
+#if DUMP_MBOXFRAME
+ if (cs->debug & L1_DEB_HSCX) {
+ char tmp[32];
+
+ sprintf(tmp, "rcv_mbox(%02x,%02x,%d)", ireg->iis, ireg->cmsb,
+ ireg->clsb);
+ debugl1(cs, tmp);
+ }
+#endif
+}
+
+int
+waitrecmsg(struct IsdnCardState *cs, u_char *len,
+ u_char *msg, int maxdelay)
+{
+ int timeout = 0;
+ long flags;
+ struct isar_reg *ir = cs->bcs[0].hw.isar.reg;
+
+
+ while((!(cs->BC_Read_Reg(cs, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) &&
+ (timeout++ < maxdelay))
+ udelay(1);
+ if (timeout >= maxdelay) {
+ printk(KERN_WARNING"isar recmsg IRQSTA timeout\n");
+ return(0);
+ }
+ save_flags(flags);
+ cli();
+ get_irq_infos(cs, ir);
+ rcv_mbox(cs, ir, msg);
+ *len = ir->clsb;
+ restore_flags(flags);
+ return(1);
+}
+
+int
+ISARVersion(struct IsdnCardState *cs, char *s)
+{
+ int ver;
+ u_char msg[] = ISAR_MSG_HWVER;
+ u_char tmp[64];
+ u_char len;
+ int debug;
+
+ cs->cardmsg(cs, CARD_RESET, NULL);
+ /* disable ISAR IRQ */
+ cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0);
+ debug = cs->debug;
+ cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO);
+ if (!sendmsg(cs, ISAR_HIS_VNR, 0, 3, msg))
+ return(-1);
+ if (!waitrecmsg(cs, &len, tmp, 100000))
+ return(-2);
+ cs->debug = debug;
+ if (cs->bcs[0].hw.isar.reg->iis == ISAR_IIS_VNR) {
+ if (len == 1) {
+ ver = tmp[0] & 0xf;
+ printk(KERN_INFO "%s ISAR version %d\n", s, ver);
+ return(ver);
+ }
+ return(-3);
+ }
+ return(-4);
+}
+
+int
+isar_load_firmware(struct IsdnCardState *cs, u_char *buf)
+{
+ int ret, size, cnt, debug;
+ u_char len, nom, noc;
+ u_short sadr, left, *sp;
+ u_char *p = buf;
+ u_char *msg, *tmpmsg, *mp, tmp[64];
+ long flags;
+ struct isar_reg *ireg = cs->bcs[0].hw.isar.reg;
+
+ struct {u_short sadr;
+ u_short len;
+ u_short d_key;
+ } blk_head;
+
+#define BLK_HEAD_SIZE 6
+ if (1 != (ret = ISARVersion(cs, "Testing"))) {
+ printk(KERN_ERR"isar_load_firmware wrong isar version %d\n", ret);
+ return(1);
+ }
+ debug = cs->debug;
+#if DBG_LOADFIRM<2
+ cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO);
+#endif
+ printk(KERN_DEBUG"isar_load_firmware buf %#lx\n", (u_long)buf);
+ if ((ret = verify_area(VERIFY_READ, (void *) p, sizeof(int)))) {
+ printk(KERN_ERR"isar_load_firmware verify_area ret %d\n", ret);
+ return ret;
+ }
+ if ((ret = copy_from_user(&size, p, sizeof(int)))) {
+ printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret);
+ return ret;
+ }
+ p += sizeof(int);
+ printk(KERN_DEBUG"isar_load_firmware size: %d\n", size);
+ if ((ret = verify_area(VERIFY_READ, (void *) p, size))) {
+ printk(KERN_ERR"isar_load_firmware verify_area ret %d\n", ret);
+ return ret;
+ }
+ cnt = 0;
+ /* disable ISAR IRQ */
+ cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0);
+ if (!(msg = kmalloc(256, GFP_KERNEL))) {
+ printk(KERN_ERR"isar_load_firmware no buffer\n");
+ return (1);
+ }
+ if (!(tmpmsg = kmalloc(256, GFP_KERNEL))) {
+ printk(KERN_ERR"isar_load_firmware no tmp buffer\n");
+ kfree(msg);
+ return (1);
+ }
+ while (cnt < size) {
+ if ((ret = copy_from_user(&blk_head, p, BLK_HEAD_SIZE))) {
+ printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret);
+ goto reterror;
+ }
+ cnt += BLK_HEAD_SIZE;
+ p += BLK_HEAD_SIZE;
+ printk(KERN_DEBUG"isar firmware block (%#x,%5d,%#x)\n",
+ blk_head.sadr, blk_head.len, blk_head.d_key & 0xff);
+ sadr = blk_head.sadr;
+ left = blk_head.len;
+ if (!sendmsg(cs, ISAR_HIS_DKEY, blk_head.d_key & 0xff, 0, NULL)) {
+ printk(KERN_ERR"isar sendmsg dkey failed\n");
+ ret = 1;goto reterror;
+ }
+ if (!waitrecmsg(cs, &len, tmp, 100000)) {
+ printk(KERN_ERR"isar waitrecmsg dkey failed\n");
+ ret = 1;goto reterror;
+ }
+ if ((ireg->iis != ISAR_IIS_DKEY) || ireg->cmsb || len) {
+ printk(KERN_ERR"isar wrong dkey response (%x,%x,%x)\n",
+ ireg->iis, ireg->cmsb, len);
+ ret = 1;goto reterror;
+ }
+ while (left>0) {
+ noc = MIN(126, left);
+ nom = 2*noc;
+ mp = msg;
+ *mp++ = sadr / 256;
+ *mp++ = sadr % 256;
+ left -= noc;
+ *mp++ = noc;
+ if ((ret = copy_from_user(tmpmsg, p, nom))) {
+ printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret);
+ goto reterror;
+ }
+ p += nom;
+ cnt += nom;
+ nom += 3;
+ sp = (u_short *)tmpmsg;
+#if DBG_LOADFIRM
+ printk(KERN_DEBUG"isar: load %3d words at %04x\n",
+ noc, sadr);
+#endif
+ sadr += noc;
+ while(noc) {
+ *mp++ = *sp / 256;
+ *mp++ = *sp % 256;
+ sp++;
+ noc--;
+ }
+ if (!sendmsg(cs, ISAR_HIS_FIRM, 0, nom, msg)) {
+ printk(KERN_ERR"isar sendmsg prog failed\n");
+ ret = 1;goto reterror;
+ }
+ if (!waitrecmsg(cs, &len, tmp, 100000)) {
+ printk(KERN_ERR"isar waitrecmsg prog failed\n");
+ ret = 1;goto reterror;
+ }
+ if ((ireg->iis != ISAR_IIS_FIRM) || ireg->cmsb || len) {
+ printk(KERN_ERR"isar wrong prog response (%x,%x,%x)\n",
+ ireg->iis, ireg->cmsb, len);
+ ret = 1;goto reterror;
+ }
+ }
+ printk(KERN_DEBUG"isar firmware block %5d words loaded\n",
+ blk_head.len);
+ }
+ msg[0] = 0xff;
+ msg[1] = 0xfe;
+ ireg->bstat = 0;
+ if (!sendmsg(cs, ISAR_HIS_STDSP, 0, 2, msg)) {
+ printk(KERN_ERR"isar sendmsg start dsp failed\n");
+ ret = 1;goto reterror;
+ }
+ if (!waitrecmsg(cs, &len, tmp, 100000)) {
+ printk(KERN_ERR"isar waitrecmsg start dsp failed\n");
+ ret = 1;goto reterror;
+ }
+ if ((ireg->iis != ISAR_IIS_STDSP) || ireg->cmsb || len) {
+ printk(KERN_ERR"isar wrong start dsp response (%x,%x,%x)\n",
+ ireg->iis, ireg->cmsb, len);
+ ret = 1;goto reterror;
+ } else
+ printk(KERN_DEBUG"isar start dsp success\n");
+ /* NORMAL mode entered */
+ /* Enable IRQs of ISAR */
+ cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, ISAR_IRQSTA);
+ save_flags(flags);
+ sti();
+ cnt = 1000; /* max 1s */
+ while ((!ireg->bstat) && cnt) {
+ udelay(1000);
+ cnt--;
+ }
+ if (!cnt) {
+ printk(KERN_ERR"isar no general status event received\n");
+ ret = 1;goto reterrflg;
+ } else {
+ printk(KERN_DEBUG"isar general status event %x\n",
+ ireg->bstat);
+ }
+ ireg->iis = 0;
+ if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) {
+ printk(KERN_ERR"isar sendmsg self tst failed\n");
+ ret = 1;goto reterrflg;
+ }
+ cnt = 1000; /* max 10 ms */
+ while ((ireg->iis != ISAR_IIS_DIAG) && cnt) {
+ udelay(10);
+ cnt--;
+ }
+ if (!cnt) {
+ printk(KERN_ERR"isar no self tst response\n");
+ ret = 1;goto reterrflg;
+ } else if ((ireg->cmsb == ISAR_CTRL_STST) && (ireg->clsb == 1)
+ && (ireg->par[0] == 0)) {
+ printk(KERN_DEBUG"isar selftest OK\n");
+ } else {
+ printk(KERN_DEBUG"isar selftest not OK %x/%x/%x\n",
+ ireg->cmsb, ireg->clsb, ireg->par[0]);
+ ret = 1;goto reterror;
+ }
+ ireg->iis = 0;
+ if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) {
+ printk(KERN_ERR"isar RQST SVN failed\n");
+ ret = 1;goto reterror;
+ }
+ cnt = 10000; /* max 100 ms */
+ while ((ireg->iis != ISAR_IIS_DIAG) && cnt) {
+ udelay(10);
+ cnt--;
+ }
+ if (!cnt) {
+ printk(KERN_ERR"isar no SVN response\n");
+ ret = 1;goto reterrflg;
+ } else {
+ if ((ireg->cmsb == ISAR_CTRL_SWVER) && (ireg->clsb == 1))
+ printk(KERN_DEBUG"isar software version %#x\n",
+ ireg->par[0]);
+ else {
+ printk(KERN_ERR"isar wrong swver response (%x,%x) cnt(%d)\n",
+ ireg->cmsb, ireg->clsb, cnt);
+ ret = 1;goto reterrflg;
+ }
+ }
+ cs->debug = debug;
+ isar_setup(cs);
+ ret = 0;
+reterrflg:
+ restore_flags(flags);
+reterror:
+ cs->debug = debug;
+ if (ret)
+ /* disable ISAR IRQ */
+ cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0);
+ kfree(msg);
+ kfree(tmpmsg);
+ return(ret);
+}
+
+void
+isar_sched_event(struct BCState *bcs, int event)
+{
+ bcs->event |= 1 << event;
+ queue_task(&bcs->tqueue, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+}
+
+static inline void
+isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs)
+{
+ u_char *ptr;
+ struct sk_buff *skb;
+ struct isar_reg *ireg = bcs->hw.isar.reg;
+ char tmp[64];
+
+ if (!ireg->clsb) {
+ debugl1(cs, "isar zero len frame");
+ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ return;
+ }
+ switch (bcs->mode) {
+ case L1_MODE_NULL:
+ sprintf(tmp, "isar mode 0 spurious IIS_RDATA %x/%x/%x",
+ ireg->iis, ireg->cmsb, ireg->clsb);
+ printk(KERN_WARNING"%s\n",tmp);
+ debugl1(cs, tmp);
+ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ break;
+ case L1_MODE_TRANS:
+ if ((skb = dev_alloc_skb(ireg->clsb))) {
+ SET_SKB_FREE(skb);
+ rcv_mbox(cs, ireg, (u_char *)skb_put(skb, ireg->clsb));
+ skb_queue_tail(&bcs->rqueue, skb);
+ isar_sched_event(bcs, B_RCVBUFREADY);
+ } else {
+ printk(KERN_WARNING "HiSax: skb out of memory\n");
+ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ }
+ break;
+ case L1_MODE_HDLC:
+ if ((bcs->hw.isar.rcvidx + ireg->clsb) > HSCX_BUFMAX) {
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "isar_rcv_frame: incoming packet too large");
+ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ bcs->hw.isar.rcvidx = 0;
+ } else if (ireg->cmsb & HDLC_ERROR) {
+ if (cs->debug & L1_DEB_WARN) {
+ sprintf(tmp, "isar frame error %x len %d",
+ ireg->cmsb, ireg->clsb);
+ debugl1(cs, tmp);
+ }
+ bcs->hw.isar.rcvidx = 0;
+ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ } else {
+ if (ireg->cmsb & HDLC_FSD)
+ bcs->hw.isar.rcvidx = 0;
+ ptr = bcs->hw.isar.rcvbuf + bcs->hw.isar.rcvidx;
+ bcs->hw.isar.rcvidx += ireg->clsb;
+ rcv_mbox(cs, ireg, ptr);
+ if (ireg->cmsb & HDLC_FED) {
+ if (bcs->hw.isar.rcvidx < 3) { /* last 2 bytes are the FCS */
+ printk(KERN_WARNING "ISAR: HDLC frame too short(%d)\n",
+ bcs->hw.isar.rcvidx);
+ } else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx-2)))
+ printk(KERN_WARNING "ISAR: receive out of memory\n");
+ else {
+ SET_SKB_FREE(skb);
+ memcpy(skb_put(skb, bcs->hw.isar.rcvidx-2),
+ bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx-2);
+ skb_queue_tail(&bcs->rqueue, skb);
+ isar_sched_event(bcs, B_RCVBUFREADY);
+ }
+ }
+ }
+ break;
+ default:
+ printk(KERN_ERR"isar_rcv_frame mode (%x)error\n", bcs->mode);
+ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ break;
+ }
+}
+
+void
+isar_fill_fifo(struct BCState *bcs)
+{
+ struct IsdnCardState *cs = bcs->cs;
+ char tmp[64];
+ int count;
+ u_char msb;
+ u_char *ptr;
+ long flags;
+
+ if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+ debugl1(cs, "isar_fill_fifo");
+ if (!bcs->tx_skb)
+ return;
+ if (bcs->tx_skb->len <= 0)
+ return;
+ if (!(bcs->hw.isar.reg->bstat &
+ (bcs->hw.isar.dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2)))
+ return;
+ if (bcs->tx_skb->len > bcs->hw.isar.mml) {
+ msb = 0;
+ count = bcs->hw.isar.mml;
+ } else {
+ count = bcs->tx_skb->len;
+ msb = HDLC_FED;
+ }
+ if (!bcs->hw.isar.txcnt)
+ msb |= HDLC_FST;
+ save_flags(flags);
+ cli();
+ ptr = bcs->tx_skb->data;
+ skb_pull(bcs->tx_skb, count);
+ bcs->tx_cnt -= count;
+ bcs->hw.isar.txcnt += count;
+ switch (bcs->mode) {
+ case L1_MODE_NULL:
+ printk(KERN_ERR"isar_fill_fifo wrong mode 0\n");
+ break;
+ case L1_MODE_TRANS:
+ if (!sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
+ 0, count, ptr)) {
+ if (cs->debug) {
+ sprintf(tmp, "isar bin data send dp%d failed",
+ bcs->hw.isar.dpath);
+ debugl1(cs, tmp);
+ }
+ }
+ break;
+ case L1_MODE_HDLC:
+ if (!sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
+ msb, count, ptr)) {
+ if (cs->debug) {
+ sprintf(tmp, "isar hdlc data send dp%d failed",
+ bcs->hw.isar.dpath);
+ debugl1(cs, tmp);
+ }
+ }
+ break;
+ default:
+ printk(KERN_ERR"isar_fill_fifo mode (%x)error\n", bcs->mode);
+ break;
+ }
+ restore_flags(flags);
+}
+
+inline
+struct BCState *sel_bcs_isar(struct IsdnCardState *cs, u_char dpath)
+{
+ if ((!dpath) || (dpath == 3))
+ return(NULL);
+ if (cs->bcs[0].hw.isar.dpath == dpath)
+ return(&cs->bcs[0]);
+ if (cs->bcs[1].hw.isar.dpath == dpath)
+ return(&cs->bcs[1]);
+ return(NULL);
+}
+
+inline void
+send_frames(struct BCState *bcs)
+{
+ if (bcs->tx_skb) {
+ if (bcs->tx_skb->len) {
+ isar_fill_fifo(bcs);
+ return;
+ } else {
+ if (bcs->st->lli.l1writewakeup &&
+ (PACKET_NOACK != bcs->tx_skb->pkt_type))
+ bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.isar.txcnt);
+ dev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+ bcs->hw.isar.txcnt = 0;
+ bcs->tx_skb = NULL;
+ }
+ }
+ if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+ bcs->hw.isar.txcnt = 0;
+ test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+ isar_fill_fifo(bcs);
+ } else {
+ test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+ isar_sched_event(bcs, B_XMTBUFREADY);
+ }
+}
+
+inline void
+check_send(struct IsdnCardState *cs, u_char rdm)
+{
+ struct BCState *bcs;
+
+ if (rdm & BSTAT_RDM1) {
+ if ((bcs = sel_bcs_isar(cs, 1))) {
+ if (bcs->mode) {
+ send_frames(bcs);
+ }
+ }
+ }
+ if (rdm & BSTAT_RDM2) {
+ if ((bcs = sel_bcs_isar(cs, 2))) {
+ if (bcs->mode) {
+ send_frames(bcs);
+ }
+ }
+ }
+
+}
+
+void
+isar_int_main(struct IsdnCardState *cs)
+{
+ long flags;
+ char tmp[64];
+ struct isar_reg *ireg = cs->bcs[0].hw.isar.reg;
+ struct BCState *bcs;
+
+ save_flags(flags);
+ cli();
+ get_irq_infos(cs, ireg);
+ switch (ireg->iis & ISAR_IIS_MSCMSD) {
+ case ISAR_IIS_RDATA:
+ if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) {
+ isar_rcv_frame(cs, bcs);
+ } else {
+ sprintf(tmp, "isar spurious IIS_RDATA %x/%x/%x",
+ ireg->iis, ireg->cmsb, ireg->clsb);
+ printk(KERN_WARNING"%s\n",tmp);
+ debugl1(cs, tmp);
+ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ }
+ break;
+ case ISAR_IIS_GSTEV:
+ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ ireg->bstat |= ireg->cmsb;
+ check_send(cs, ireg->cmsb);
+ break;
+ case ISAR_IIS_BSTEV:
+ cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+ if (cs->debug & L1_DEB_WARN) {
+ sprintf(tmp, "Buffer STEV dpath%d msb(%x)",
+ ireg->iis>>6, ireg->cmsb);
+ debugl1(cs, tmp);
+ }
+
+ break;
+ case ISAR_IIS_DIAG:
+ case ISAR_IIS_PSTRSP:
+ case ISAR_IIS_PSTEV:
+ case ISAR_IIS_BSTRSP:
+ case ISAR_IIS_IOM2RSP:
+ rcv_mbox(cs, ireg, (u_char *)ireg->par);
+ if ((cs->debug & (L1_DEB_HSCX | L1_DEB_HSCX_FIFO))
+ == L1_DEB_HSCX) {
+ u_char *tp=tmp;
+
+ tp += sprintf(tmp, "msg iis(%x) msb(%x)",
+ ireg->iis, ireg->cmsb);
+ QuickHex(tp, (u_char *)ireg->par, ireg->clsb);
+ debugl1(cs, tmp);
+ }
+ break;
+ default:
+ rcv_mbox(cs, ireg, tmp);
+ if (cs->debug & L1_DEB_WARN) {
+ sprintf(tmp, "unhandled msg iis(%x) ctrl(%x/%x)",
+ ireg->iis, ireg->cmsb, ireg->clsb);
+ debugl1(cs, tmp);
+ }
+ break;
+ }
+ restore_flags(flags);
+}
+
+void
+setup_pump(struct BCState *bcs) {
+ struct IsdnCardState *cs = bcs->cs;
+ u_char dps = SET_DPS(bcs->hw.isar.dpath);
+ char tmp[40];
+
+ switch (bcs->mode) {
+ case L1_MODE_NULL:
+ case L1_MODE_TRANS:
+ case L1_MODE_HDLC:
+ if (!sendmsg(cs, dps | ISAR_HIS_PUMPCFG, PMOD_BYPASS, 0, NULL)) {
+ if (cs->debug) {
+ sprintf(tmp, "isar pump bypass cfg dp%d failed",
+ bcs->hw.isar.dpath);
+ debugl1(cs, tmp);
+ }
+ }
+ break;
+ }
+ if (!sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL)) {
+ if (cs->debug) {
+ sprintf(tmp, "isar pump status req dp%d failed",
+ bcs->hw.isar.dpath);
+ debugl1(cs, tmp);
+ }
+ }
+}
+
+void
+setup_sart(struct BCState *bcs) {
+ struct IsdnCardState *cs = bcs->cs;
+ u_char dps = SET_DPS(bcs->hw.isar.dpath);
+ char tmp[40];
+
+ switch (bcs->mode) {
+ case L1_MODE_NULL:
+ if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_DISABLE, 0, NULL)) {
+ if (cs->debug) {
+ sprintf(tmp, "isar sart disable dp%d failed",
+ bcs->hw.isar.dpath);
+ debugl1(cs, tmp);
+ }
+ }
+ break;
+ case L1_MODE_TRANS:
+ tmp[0] = 0;
+ tmp[1] = 0;
+ if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_BINARY, 2, tmp)) {
+ if (cs->debug) {
+ sprintf(tmp, "isar sart binary dp%d failed",
+ bcs->hw.isar.dpath);
+ debugl1(cs, tmp);
+ }
+ }
+ break;
+ case L1_MODE_HDLC:
+ tmp[0] = 0;
+ if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1, tmp)) {
+ if (cs->debug) {
+ sprintf(tmp, "isar sart binary dp%d failed",
+ bcs->hw.isar.dpath);
+ debugl1(cs, tmp);
+ }
+ }
+ break;
+ }
+ if (!sendmsg(cs, dps | ISAR_HIS_BSTREQ, 0, 0, NULL)) {
+ if (cs->debug) {
+ sprintf(tmp, "isar buf stat req dp%d failed",
+ bcs->hw.isar.dpath);
+ debugl1(cs, tmp);
+ }
+ }
+}
+
+void
+setup_iom2(struct BCState *bcs) {
+ struct IsdnCardState *cs = bcs->cs;
+ u_char dps = SET_DPS(bcs->hw.isar.dpath);
+ char tmp[40];
+ u_char cmsb = 0, msg[5] = {0x10,0,0,0,0};
+
+ switch (bcs->mode) {
+ case L1_MODE_NULL:
+ /* dummy slot */
+ msg[1] = msg[3] = bcs->hw.isar.dpath + 2;
+ break;
+ case L1_MODE_TRANS:
+ case L1_MODE_HDLC:
+ cmsb = 0x80;
+ if (bcs->channel)
+ msg[1] = msg[3] = 1;
+ break;
+ }
+ if (!sendmsg(cs, dps | ISAR_HIS_IOM2CFG, cmsb, 5, msg)) {
+ if (cs->debug) {
+ sprintf(tmp, "isar iom2 dp%d failed", bcs->hw.isar.dpath);
+ debugl1(cs, tmp);
+ }
+ }
+ if (!sendmsg(cs, dps | ISAR_HIS_IOM2REQ, 0, 0, NULL)) {
+ if (cs->debug) {
+ sprintf(tmp, "isar IOM2 cfg req dp%d failed",
+ bcs->hw.isar.dpath);
+ debugl1(cs, tmp);
+ }
+ }
+}
+
+int
+modeisar(struct BCState *bcs, int mode, int bc)
+{
+ struct IsdnCardState *cs = bcs->cs;
+ char tmp[40];
+
+ /* Here we are selecting the best datapath for requested mode */
+ if(bcs->mode == L1_MODE_NULL) { /* New Setup */
+ bcs->channel = bc;
+ switch (mode) {
+ case L1_MODE_NULL: /* init */
+ break;
+ case L1_MODE_TRANS:
+ case L1_MODE_HDLC:
+ /* best is datapath 2 */
+ if (!test_and_set_bit(ISAR_DP2_USE,
+ &bcs->hw.isar.reg->Flags))
+ bcs->hw.isar.dpath = 2;
+ else if (!test_and_set_bit(ISAR_DP1_USE,
+ &bcs->hw.isar.reg->Flags))
+ bcs->hw.isar.dpath = 1;
+ else {
+ printk(KERN_ERR"isar modeisar both pathes in use\n");
+ return(1);
+ }
+ break;
+ }
+ }
+ if (cs->debug & L1_DEB_HSCX) {
+ sprintf(tmp, "isar dp%d mode %d->%d ichan %d",
+ bcs->hw.isar.dpath, bcs->mode, mode, bc);
+ debugl1(cs, tmp);
+ }
+ bcs->mode = mode;
+ setup_pump(bcs);
+ setup_sart(bcs);
+ setup_iom2(bcs);
+ if (bcs->mode == L1_MODE_NULL) {
+ /* Clear resources */
+ if (bcs->hw.isar.dpath == 1)
+ test_and_clear_bit(ISAR_DP1_USE, &bcs->hw.isar.reg->Flags);
+ else if (bcs->hw.isar.dpath == 2)
+ test_and_clear_bit(ISAR_DP2_USE, &bcs->hw.isar.reg->Flags);
+ bcs->hw.isar.dpath = 0;
+ }
+ return(0);
+}
+
+void
+isar_setup(struct IsdnCardState *cs)
+{
+ u_char msg;
+ char tmp[40];
+ int i;
+
+ /* Dpath 1, 2 */
+ msg = 61;
+ for (i=0; i<2; i++) {
+ /* Buffer Config */
+ if (!sendmsg(cs, (i ? ISAR_HIS_DPS2 : ISAR_HIS_DPS1) |
+ ISAR_HIS_P12CFG, 4, 1, &msg)) {
+ if (cs->debug) {
+ sprintf(tmp, "isar P%dCFG failed", i+1);
+ debugl1(cs, tmp);
+ }
+ }
+ cs->bcs[i].hw.isar.mml = msg;
+ cs->bcs[i].mode = 0;
+ cs->bcs[i].hw.isar.dpath = i + 1;
+ modeisar(&cs->bcs[i], 0, 0);
+ }
+}
+
+void
+isar_l2l1(struct PStack *st, int pr, void *arg)
+{
+ struct sk_buff *skb = arg;
+ long flags;
+
+ switch (pr) {
+ case (PH_DATA | REQUEST):
+ save_flags(flags);
+ cli();
+ if (st->l1.bcs->tx_skb) {
+ skb_queue_tail(&st->l1.bcs->squeue, skb);
+ restore_flags(flags);
+ } else {
+ st->l1.bcs->tx_skb = skb;
+ test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ if (st->l1.bcs->cs->debug & L1_DEB_HSCX)
+ debugl1(st->l1.bcs->cs, "DRQ set BC_FLG_BUSY");
+ st->l1.bcs->hw.isar.txcnt = 0;
+ restore_flags(flags);
+ st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+ }
+ break;
+ case (PH_PULL | INDICATION):
+ if (st->l1.bcs->tx_skb) {
+ printk(KERN_WARNING "isar_l2l1: this shouldn't happen\n");
+ break;
+ }
+ test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ if (st->l1.bcs->cs->debug & L1_DEB_HSCX)
+ debugl1(st->l1.bcs->cs, "PUI set BC_FLG_BUSY");
+ st->l1.bcs->tx_skb = skb;
+ st->l1.bcs->hw.isar.txcnt = 0;
+ st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+ break;
+ case (PH_PULL | REQUEST):
+ if (!st->l1.bcs->tx_skb) {
+ test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+ st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+ } else
+ test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+ break;
+ case (PH_ACTIVATE | REQUEST):
+ test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+ modeisar(st->l1.bcs, st->l1.mode, st->l1.bc);
+ l1_msg_b(st, pr, arg);
+ break;
+ case (PH_DEACTIVATE | REQUEST):
+ l1_msg_b(st, pr, arg);
+ break;
+ case (PH_DEACTIVATE | CONFIRM):
+ test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+ test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ if (st->l1.bcs->cs->debug & L1_DEB_HSCX)
+ debugl1(st->l1.bcs->cs, "PDAC clear BC_FLG_BUSY");
+ modeisar(st->l1.bcs, 0, st->l1.bc);
+ st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+ break;
+ }
+}
+
+void
+close_isarstate(struct BCState *bcs)
+{
+ modeisar(bcs, 0, bcs->channel);
+ if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
+ if (bcs->hw.isar.rcvbuf) {
+ kfree(bcs->hw.isar.rcvbuf);
+ bcs->hw.isar.rcvbuf = NULL;
+ }
+ discard_queue(&bcs->rqueue);
+ discard_queue(&bcs->squeue);
+ if (bcs->tx_skb) {
+ dev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+ bcs->tx_skb = NULL;
+ test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+ if (bcs->cs->debug & L1_DEB_HSCX)
+ debugl1(bcs->cs, "closeisar clear BC_FLG_BUSY");
+ }
+ }
+}
+
+int
+open_isarstate(struct IsdnCardState *cs, struct BCState *bcs)
+{
+ if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
+ if (!(bcs->hw.isar.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
+ printk(KERN_WARNING
+ "HiSax: No memory for isar.rcvbuf\n");
+ return (1);
+ }
+ skb_queue_head_init(&bcs->rqueue);
+ skb_queue_head_init(&bcs->squeue);
+ }
+ bcs->tx_skb = NULL;
+ test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "openisar clear BC_FLG_BUSY");
+ bcs->event = 0;
+ bcs->hw.isar.rcvidx = 0;
+ bcs->tx_cnt = 0;
+ return (0);
+}
+
+int
+setstack_isar(struct PStack *st, struct BCState *bcs)
+{
+ bcs->channel = st->l1.bc;
+ if (open_isarstate(st->l1.hardware, bcs))
+ return (-1);
+ st->l1.bcs = bcs;
+ st->l2.l2l1 = isar_l2l1;
+ setstack_manager(st);
+ bcs->st = st;
+ setstack_l1_B(st);
+ return (0);
+}
+
+HISAX_INITFUNC(void
+initisar(struct IsdnCardState *cs))
+{
+ cs->bcs[0].BC_SetStack = setstack_isar;
+ cs->bcs[1].BC_SetStack = setstack_isar;
+ cs->bcs[0].BC_Close = close_isarstate;
+ cs->bcs[1].BC_Close = close_isarstate;
+}
--- /dev/null
+/* $Id: isar.h,v 1.1.2.3 1998/10/04 23:05:01 keil Exp $
+ * isar.h ISAR (Siemens PSB 7110) specific defines
+ *
+ * Author Karsten Keil (keil@isdn4linux.de)
+ *
+ *
+ * $Log: isar.h,v $
+ * Revision 1.1.2.3 1998/10/04 23:05:01 keil
+ * ISAR works now
+ *
+ * Revision 1.1.2.2 1998/09/30 22:28:09 keil
+ * more work for isar support
+ *
+ * Revision 1.1.2.1 1998/09/27 13:01:44 keil
+ * Start support for ISAR based cards
+ *
+ * Revision 1.1 1998/08/13 23:33:48 keil
+ * First version, only init
+ *
+ *
+ */
+
+#define ISAR_IRQMSK 0x04
+#define ISAR_IRQSTA 0x04
+#define ISAR_IRQBIT 0x75
+#define ISAR_CTRL_H 0x61
+#define ISAR_CTRL_L 0x60
+#define ISAR_IIS 0x58
+#define ISAR_IIA 0x58
+#define ISAR_HIS 0x50
+#define ISAR_HIA 0x50
+#define ISAR_MBOX 0x4c
+#define ISAR_WADR 0x4a
+#define ISAR_RADR 0x48
+
+#define ISAR_HIS_VNR 0x14
+#define ISAR_HIS_DKEY 0x02
+#define ISAR_HIS_FIRM 0x1e
+#define ISAR_HIS_STDSP 0x08
+#define ISAR_HIS_DIAG 0x05
+#define ISAR_HIS_P0CFG 0x3c
+#define ISAR_HIS_P12CFG 0x24
+#define ISAR_HIS_SARTCFG 0x25
+#define ISAR_HIS_PUMPCFG 0x26
+#define ISAR_HIS_IOM2CFG 0x27
+#define ISAR_HIS_IOM2REQ 0x07
+#define ISAR_HIS_BSTREQ 0x0c
+#define ISAR_HIS_PSTREQ 0x0e
+#define ISAR_HIS_SDATA 0x20
+#define ISAR_HIS_DPS1 0x40
+#define ISAR_HIS_DPS2 0x80
+#define SET_DPS(x) ((x<<6) & 0xc0)
+
+#define ISAR_IIS_MSCMSD 0x3f
+#define ISAR_IIS_VNR 0x15
+#define ISAR_IIS_DKEY 0x03
+#define ISAR_IIS_FIRM 0x1f
+#define ISAR_IIS_STDSP 0x09
+#define ISAR_IIS_DIAG 0x25
+#define ISAR_IIS_GSTEV 0x0
+#define ISAR_IIS_BSTEV 0x28
+#define ISAR_IIS_BSTRSP 0x2c
+#define ISAR_IIS_PSTRSP 0x2e
+#define ISAR_IIS_PSTEV 0x2a
+#define ISAR_IIS_IOM2RSP 0x27
+
+#define ISAR_IIS_RDATA 0x20
+#define ISAR_CTRL_SWVER 0x10
+#define ISAR_CTRL_STST 0x40
+
+#define ISAR_MSG_HWVER {0x20, 0, 1}
+
+#define ISAR_DP1_USE 1
+#define ISAR_DP2_USE 2
+
+#define PMOD_BYPASS 7
+
+#define SMODE_DISABLE 0
+#define SMODE_HDLC 3
+#define SMODE_BINARY 4
+
+#define HDLC_FED 0x40
+#define HDLC_FSD 0x20
+#define HDLC_FST 0x20
+#define HDLC_ERROR 0x1c
+
+#define BSTAT_RDM0 0x1
+#define BSTAT_RDM1 0x2
+#define BSTAT_RDM2 0x4
+#define BSTAT_RDM3 0x8
+
+
+extern int ISARVersion(struct IsdnCardState *cs, char *s);
+extern int isar_load_firmware(struct IsdnCardState *cs, u_char *buf);
+extern void isar_int_main(struct IsdnCardState *cs);
+extern void initisar(struct IsdnCardState *cs);
+extern void isar_fill_fifo(struct BCState *bcs);
-/* $Id: sedlbauer.c,v 1.1.2.8 1998/09/30 22:28:10 keil Exp $
+/* $Id: sedlbauer.c,v 1.1.2.12 1998/10/13 18:38:53 keil Exp $
* sedlbauer.c low level stuff for Sedlbauer cards
- * includes support for the Sedlbauer Speed Star
+ * includes support for the Sedlbauer speed star (speed star II)
* and support for the Sedlbauer ISDN-Controller PC/104
+ * with beginning support for the Sedlbauer speed pci
* derived from the original file asuscom.c from Karsten Keil
*
* Copyright (C) 1997,1998 Marcus Niemann (for the modifications to
* Edgar Toernig
*
* $Log: sedlbauer.c,v $
+ * Revision 1.1.2.12 1998/10/13 18:38:53 keil
+ * Fix PCI detection
+ *
+ * Revision 1.1.2.11 1998/10/13 10:27:30 keil
+ * New cards, minor fixes
+ *
+ * Revision 1.1.2.10 1998/10/11 19:33:52 niemann
+ * Added new IPAC based cards.
+ * Code cleanup and simplified (sedlbauer.c)
+ *
+ * Revision 1.1.2.9 1998/10/04 23:05:03 keil
+ * ISAR works now
+ *
* Revision 1.1.2.8 1998/09/30 22:28:10 keil
* more work for isar support
*
*
*/
+/* Supported cards:
+ * Card: Chip: Configuration: Comment:
+ * ---------------------------------------------------------------------
+ * Speed Card ISAC_HSCX DIP-SWITCH
+ * Speed Win ISAC_HSCX ISAPNP
+ * Speed Fax+ ISAC_ISAR ISAPNP #HDLC works#
+ * Speed Star ISAC_HSCX CARDMGR
+ * Speed Win2 IPAC ISAPNP
+ * ISDN PC/104 IPAC DIP-SWITCH
+ * Speed Star2 IPAC CARDMGR
+ * Speed PCI IPAC PNP #not ready#
+*/
+
+#undef SEDLBAUER_PCI
+
#define __NO_VERSION__
+#include <linux/config.h>
#include "hisax.h"
#include "isac.h"
#include "ipac.h"
#include "hscx.h"
+#include "isar.h"
#include "isdnl1.h"
+#include <linux/pci.h>
+#include <linux/bios32.h>
extern const char *CardType[];
-const char *Sedlbauer_revision = "$Revision: 1.1.2.8 $";
+const char *Sedlbauer_revision = "$Revision: 1.1.2.12 $";
const char *Sedlbauer_Types[] =
-{"None", "Speed Card", "Speed Win", "Speed Star", "Speed Fax+", "ISDN PC/104"};
+ {"None", "speed card/win", "speed star", "speed fax+",
+ "speed win II / ISDN PC/104", "speed star II", "speed pci"};
+
+#ifdef SEDLBAUER_PCI
+#define PCI_VENDOR_SEDLBAUER 0x0000
+#define PCI_SPEEDPCI_ID 0x00
+#endif
-#define SEDL_SPEED_CARD 1
-#define SEDL_SPEED_WIN 2
-#define SEDL_SPEED_STAR 3
-#define SEDL_SPEED_FAX 4
-#define SEDL_SPEED_PC104 5
+#define SEDL_SPEED_CARD_WIN 1
+#define SEDL_SPEED_STAR 2
+#define SEDL_SPEED_FAX 3
+#define SEDL_SPEED_WIN2_PC104 4
+#define SEDL_SPEED_STAR2 5
+#define SEDL_SPEED_PCI 6
+
+#define SEDL_CHIP_TEST 0
+#define SEDL_CHIP_ISAC_HSCX 1
+#define SEDL_CHIP_ISAC_ISAR 2
+#define SEDL_CHIP_IPAC 3
+
+#define SEDL_BUS_ISA 1
+#define SEDL_BUS_PCI 2
+#define SEDL_BUS_PCMCIA 3
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
-#define SEDL_RESET_ON 0
-#define SEDL_RESET_OFF 1
-#define SEDL_ISAC 2
-#define SEDL_HSCX 3
-#define SEDL_ADR 4
+#define SEDL_HSCX_ISA_RESET_ON 0
+#define SEDL_HSCX_ISA_RESET_OFF 1
+#define SEDL_HSCX_ISA_ISAC 2
+#define SEDL_HSCX_ISA_HSCX 3
+#define SEDL_HSCX_ISA_ADR 4
-#define SEDL_PCMCIA_RESET 0
-#define SEDL_PCMCIA_ISAC 1
-#define SEDL_PCMCIA_HSCX 2
-#define SEDL_PCMCIA_ADR 4
+#define SEDL_HSCX_PCMCIA_RESET 0
+#define SEDL_HSCX_PCMCIA_ISAC 1
+#define SEDL_HSCX_PCMCIA_HSCX 2
+#define SEDL_HSCX_PCMCIA_ADR 4
-#define SEDL_PC104_ADR 0
-#define SEDL_PC104_IPAC 2
+#define SEDL_ISAR_ISA_ISAC 4
+#define SEDL_ISAR_ISA_ISAR 6
+#define SEDL_ISAR_ISA_ADR 8
+#define SEDL_ISAR_ISA_ISAR_RESET_ON 10
+#define SEDL_ISAR_ISA_ISAR_RESET_OFF 12
+
+#define SEDL_IPAC_ANY_ADR 0
+#define SEDL_IPAC_ANY_IPAC 2
+
+#define SEDL_IPAC_PCI_BASE 0
+#define SEDL_IPAC_PCI_ADR 0xc0
+#define SEDL_IPAC_PCI_IPAC 0xc8
#define SEDL_RESET 0x3 /* same as DOS driver */
cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0), value);
}
+/* ISAR access routines
+ * mode = 0 access with IRQ on
+ * mode = 1 access with IRQ off
+ * mode = 2 access with IRQ off and using last offset
+ */
+
+static u_char
+ReadISAR(struct IsdnCardState *cs, int mode, u_char offset)
+{
+ if (mode == 0)
+ return (readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset));
+ else if (mode == 1)
+ byteout(cs->hw.sedl.adr, offset);
+ return(bytein(cs->hw.sedl.hscx));
+}
+
+static void
+WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value)
+{
+ if (mode == 0)
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset, value);
+ else {
+ if (mode == 1)
+ byteout(cs->hw.sedl.adr, offset);
+ byteout(cs->hw.sedl.hscx, value);
+ }
+}
+
/*
* fast interrupt HSCX stuff goes here
*/
return;
}
- if ((cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) && (*cs->busy_flag == 1)) {
+ if ((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && (*cs->busy_flag == 1)) {
/* The card tends to generate interrupts while being removed
causing us to just crash the kernel. bad. */
printk(KERN_WARNING "Sedlbauer: card not available!\n");
writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xC0);
}
+static void
+sedlbauer_interrupt_isar(int intno, void *dev_id, struct pt_regs *regs)
+{
+ struct IsdnCardState *cs = dev_id;
+ u_char val;
+ int cnt = 20;
+
+ if (!cs) {
+ printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n");
+ return;
+ }
+
+ val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT);
+ Start_ISAR:
+ if (val & ISAR_IRQSTA)
+ isar_int_main(cs);
+ val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
+ Start_ISAC:
+ if (val)
+ isac_interrupt(cs, val);
+ val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT);
+ if ((val & ISAR_IRQSTA) && --cnt) {
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "ISAR IntStat after IntRoutine");
+ goto Start_ISAR;
+ }
+ val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
+ if (val && --cnt) {
+ if (cs->debug & L1_DEB_ISAC)
+ debugl1(cs, "ISAC IntStat after IntRoutine");
+ goto Start_ISAC;
+ }
+ if (!cnt)
+ printk(KERN_WARNING "Sedlbauer IRQ LOOP\n");
+
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, 0);
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF);
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0);
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, ISAR_IRQMSK);
+}
+
void
release_io_sedlbauer(struct IsdnCardState *cs)
{
- int bytecnt = 8;
+ int bytecnt = (cs->subtyp == SEDL_SPEED_FAX) ? 16 : 8;
+ if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
+ bytecnt = 256;
+ }
if (cs->hw.sedl.cfg_reg)
release_region(cs->hw.sedl.cfg_reg, bytecnt);
}
{
long flags;
- printk(KERN_INFO "Sedlbauer %s: resetting card\n",
- Sedlbauer_Types[cs->subtyp]);
- if (cs->subtyp != SEDL_SPEED_STAR) {
- if (cs->subtyp == SEDL_SPEED_PC104)
+ printk(KERN_INFO "Sedlbauer: resetting card\n");
+
+ if (!((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) &&
+ (cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX))) {
+ if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x20);
- else
- byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */
- save_flags(flags);
- sti();
- current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + 1;
- schedule();
- if (cs->subtyp == SEDL_SPEED_PC104)
+ save_flags(flags);
+ sti();
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + 1;
+ schedule();
writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x0);
- else
- byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */
- current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + 1;
- schedule();
- if (cs->subtyp == SEDL_SPEED_PC104) {
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + 1;
+ schedule();
writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_CONF, 0x0);
writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ACFG, 0xff);
writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_AOE, 0x0);
writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xc0);
writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_PCFG, 0x12);
+ restore_flags(flags);
+ } else {
+ byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */
+ save_flags(flags);
+ sti();
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + 1;
+ schedule();
+ byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + 1;
+ schedule();
+ restore_flags(flags);
}
-
- restore_flags(flags);
}
}
release_io_sedlbauer(cs);
return(0);
case CARD_SETIRQ:
- if (cs->subtyp == SEDL_SPEED_PC104) {
+ if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+ return(request_irq(cs->irq, &sedlbauer_interrupt_isar,
+ I4L_IRQ_FLAG, "HiSax", cs));
+ } else if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
return(request_irq(cs->irq, &sedlbauer_interrupt_ipac,
I4L_IRQ_FLAG, "HiSax", cs));
} else {
I4L_IRQ_FLAG, "HiSax", cs));
}
case CARD_INIT:
- inithscxisac(cs, 3);
+ if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+ clear_pending_isac_ints(cs);
+ writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
+ ISAR_IRQBIT, 0);
+ initisac(cs);
+ initisar(cs);
+ /* Reenable all IRQ */
+ cs->writeisac(cs, ISAC_MASK, 0);
+ /* RESET Receiver and Transmitter */
+ cs->writeisac(cs, ISAC_CMDR, 0x41);
+ } else {
+ inithscxisac(cs, 3);
+ }
return(0);
case CARD_TEST:
return(0);
+ case CARD_LOAD_FIRM:
+ if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+ if (isar_load_firmware(cs, arg))
+ return(1);
+ else
+ ll_run(cs);
+ }
+ return(0);
}
return(0);
}
+
+#ifdef SEDLBAUER_PCI
+static int pci_index __initdata = 0;
+#endif
+
__initfunc(int
setup_sedlbauer(struct IsdnCard *card))
{
- int bytecnt, val;
+ int bytecnt, ver, val;
struct IsdnCardState *cs = card->cs;
char tmp[64];
strcpy(tmp, Sedlbauer_revision);
printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp));
+
if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
- cs->subtyp = SEDL_SPEED_CARD;
+ cs->subtyp = SEDL_SPEED_CARD_WIN;
+ cs->hw.sedl.bus = SEDL_BUS_ISA;
+ cs->hw.sedl.chip = SEDL_CHIP_TEST;
} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {
cs->subtyp = SEDL_SPEED_STAR;
+ cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
+ cs->hw.sedl.chip = SEDL_CHIP_TEST;
+ } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {
+ cs->subtyp = SEDL_SPEED_FAX;
+ cs->hw.sedl.bus = SEDL_BUS_ISA;
+ cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
} else
return (0);
bytecnt = 8;
- cs->hw.sedl.cfg_reg = card->para[1];
- cs->irq = card->para[0];
- if (cs->subtyp == SEDL_SPEED_STAR) {
- cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_ADR;
- cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_ISAC;
- cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_HSCX;
- cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_RESET;
- cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_RESET;
+ if (card->para[1]) {
+ cs->hw.sedl.cfg_reg = card->para[1];
+ cs->irq = card->para[0];
+ if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+ bytecnt = 16;
+ }
} else {
- cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ADR;
- cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAC;
- cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX;
- cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_RESET_ON;
- cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_RESET_OFF;
- }
-
- /* In case of the sedlbauer pcmcia card, this region is in use,
+/* Probe for Sedlbauer speed pci */
+#if SEDLBAUER_PCI
+#if CONFIG_PCI
+ for (; pci_index < 255; pci_index++) {
+ unsigned char pci_bus, pci_device_fn;
+ unsigned int ioaddr;
+ unsigned char irq;
+
+ if (pcibios_find_device (PCI_VENDOR_SEDLBAUER,
+ PCI_SPEEDPCI_ID, pci_index,
+ &pci_bus, &pci_device_fn) != 0) {
+ continue;
+ }
+ pcibios_read_config_byte(pci_bus, pci_device_fn,
+ PCI_INTERRUPT_LINE, &irq);
+ pcibios_read_config_dword(pci_bus, pci_device_fn,
+ PCI_BASE_ADDRESS_1, &ioaddr);
+ cs->irq = irq;
+ cs->hw.sedl.cfg_reg = ioaddr & PCI_BASE_ADDRESS_IO_MASK;
+ if (!cs->hw.sedl.cfg_reg) {
+ printk(KERN_WARNING "Sedlbauer: No IO-Adr for PCI card found\n");
+ return(0);
+ }
+ cs->hw.sedl.bus = SEDL_BUS_PCI;
+ cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+ cs->hw.sedl.subtyp = SEDL_SPEED_PCI;
+ bytecnt = 256;
+ byteout(cs->hw.sedl.cfg_reg, 0xff);
+ byteout(cs->hw.sedl.cfg_reg, 0x00);
+ byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
+ byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
+ break;
+ }
+ if (pci_index == 255) {
+ printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
+ return(0);
+ }
+#else
+ printk(KERN_WARNING "Sedlbauer: NO_PCI_BIOS\n");
+ return (0);
+#endif /* CONFIG_PCI */
+#endif /* SEDLBAUER_PCI */
+ }
+
+ /* In case of the sedlbauer pcmcia card, this region is in use,
reserved for us by the card manager. So we do not check it
here, it would fail. */
- if ((cs->typ != ISDN_CTYPE_SEDLBAUER_PCMCIA) &&
+ if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA &&
check_region((cs->hw.sedl.cfg_reg), bytecnt)) {
printk(KERN_WARNING
"HiSax: %s config port %x-%x already in use\n",
cs->BC_Write_Reg = &WriteHSCX;
cs->BC_Send_Data = &hscx_fill_fifo;
cs->cardmsg = &Sedl_card_msg;
-
- val = readreg(cs->hw.sedl.cfg_reg + SEDL_PC104_ADR,
- cs->hw.sedl.cfg_reg + SEDL_PC104_IPAC, IPAC_ID);
- if (val == 1) {
- cs->subtyp = SEDL_SPEED_PC104;
- cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_PC104_ADR;
- cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_PC104_IPAC;
- cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_PC104_IPAC;
+
+/*
+ * testing ISA and PCMCIA Cards for IPAC, default is ISAC
+ * do not test for PCI card, because ports are different
+ * and PCI card uses only IPAC (for the moment)
+ */
+ if (cs->hw.sedl.bus != SEDL_BUS_PCI) {
+ val = readreg(cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR,
+ cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID);
+ if (val == 1) {
+ /* IPAC */
+ cs->subtyp = SEDL_SPEED_WIN2_PC104;
+ if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
+ cs->subtyp = SEDL_SPEED_STAR2;
+ }
+ cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+ } else {
+ /* ISAC_HSCX oder ISAC_ISAR */
+ if (cs->hw.sedl.chip == SEDL_CHIP_TEST) {
+ cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
+ }
+ }
+ }
+
+/*
+ * hw.sedl.chip is now properly set
+ */
+ printk(KERN_INFO "Sedlbauer: %s detected\n",
+ Sedlbauer_Types[cs->subtyp]);
+
+
+ if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
+ /* IPAC */
+ if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
+ cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
+ cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
+ cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
+ } else {
+ cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
+ cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
+ cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
+ }
test_and_set_bit(HW_IPAC, &cs->HW_Flags);
cs->readisac = &ReadISAC_IPAC;
cs->writeisac = &WriteISAC_IPAC;
cs->readisacfifo = &ReadISACfifo_IPAC;
cs->writeisacfifo = &WriteISACfifo_IPAC;
- printk(KERN_INFO "Sedlbauer %s: IPAC version %x\n",
- Sedlbauer_Types[cs->subtyp], val);
+
+ val = readreg(cs->hw.sedl.adr,cs->hw.sedl.isac, IPAC_ID);
+ printk(KERN_INFO "Sedlbauer: IPAC version %x\n", val);
reset_sedlbauer(cs);
} else {
+ /* ISAC_HSCX oder ISAC_ISAR */
cs->readisac = &ReadISAC;
cs->writeisac = &WriteISAC;
cs->readisacfifo = &ReadISACfifo;
cs->writeisacfifo = &WriteISACfifo;
- ISACVersion(cs, "Sedlbauer:");
- if (HscxVersion(cs, "Sedlbauer:")) {
- printk(KERN_WARNING
- "Sedlbauer %s: wrong HSCX versions check IO address\n",
- Sedlbauer_Types[cs->subtyp]);
- release_io_sedlbauer(cs);
- return (0);
+ if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+ cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ADR;
+ cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAC;
+ cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR;
+ cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_ON;
+ cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_OFF;
+ cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
+ cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
+ test_and_set_bit(HW_ISAR, &cs->HW_Flags);
+
+ ISACVersion(cs, "Sedlbauer:");
+
+ cs->BC_Read_Reg = &ReadISAR;
+ cs->BC_Write_Reg = &WriteISAR;
+ cs->BC_Send_Data = &isar_fill_fifo;
+ ver = ISARVersion(cs, "Sedlbauer:");
+ if (ver < 0) {
+ printk(KERN_WARNING
+ "Sedlbauer: wrong ISAR version (ret = %d)\n", ver);
+ release_io_sedlbauer(cs);
+ return (0);
+ }
+ } else {
+ if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
+ cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
+ cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
+ cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
+ cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
+ cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
+ } else {
+ cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
+ cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
+ cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
+ cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
+ cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
+ }
+ ISACVersion(cs, "Sedlbauer:");
+
+ if (HscxVersion(cs, "Sedlbauer:")) {
+ printk(KERN_WARNING
+ "Sedlbauer: wrong HSCX versions check IO address\n");
+ release_io_sedlbauer(cs);
+ return (0);
+ }
+ reset_sedlbauer(cs);
}
- reset_sedlbauer(cs);
}
return (1);
}
-/* epic100.c: A SMC 83c170 EPIC/100 fast ethernet driver for Linux. */
+/* epic100.c: A SMC 83c170 EPIC/100 Fast Ethernet driver for Linux. */
/*
Written 1997-1998 by Donald Becker.
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
- All other rights reserved.
+ All other rights reserved.
This driver is for the SMC83c170/175 "EPIC" series, as used on the
SMC EtherPower II 9432 PCI adapter, and several CardBus cards.
*/
static const char *version =
-"epic100.c:v0.99B 4/7/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html\n";
+"epic100.c:v1.03 8/7/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html\n";
/* A few user-configurable values. */
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
/* Bytes transferred to chip before transmission starts. */
-#define TX_FIFO_THRESH 128 /* Rounded down to 4 byte units. */
+#define TX_FIFO_THRESH 256 /* Rounded down to 4 byte units. */
#define RX_FIFO_THRESH 1 /* 0-3, 0==32, 64,96, or 3==128 bytes */
+#include <linux/config.h>
+#include <linux/version.h> /* Evil, but neccessary */
#ifdef MODULE
#ifdef MODVERSIONS
#include <linux/modversions.h>
#endif
#include <linux/module.h>
-#include <linux/version.h>
#else
#define MOD_INC_USE_COUNT
#define MOD_DEC_USE_COUNT
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
+#if LINUX_VERSION_CODE >= 0x20155
+#define PCI_SUPPORT_VER2
+#else
#include <linux/bios32.h>
+#endif
#include <linux/delay.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-#define RUN_AT(x) (jiffies + (x))
+/* Kernel compatibility defines, common to David Hind's PCMCIA package.
+ This is only in the support-all-kernels source code. */
-#if LINUX_VERSION_CODE < 0x20138
-#define test_and_set_bit(val, addr) set_bit(val, addr)
+#if ! defined (LINUX_VERSION_CODE) || LINUX_VERSION_CODE < 0x20000
+#warning This driver version is only for kernel versions 2.0.0 and later.
#endif
+
+#define RUN_AT(x) (jiffies + (x))
+
#if defined(MODULE) && (LINUX_VERSION_CODE >= 0x20115)
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_DESCRIPTION("SMC 83c170 EPIC series Ethernet driver");
MODULE_PARM(rx_copybreak, "i");
MODULE_PARM(max_interrupt_work, "i");
#endif
+#if LINUX_VERSION_CODE < 0x20123
+#define test_and_set_bit(val, addr) set_bit(val, addr)
+#endif
+#if LINUX_VERSION_CODE <= 0x20139
+#define net_device_stats enet_statistics
+#define NETSTATS_VER2
+#endif
+#if LINUX_VERSION_CODE < 0x20159
+#define DEV_FREE_SKB(skb) dev_kfree_skb(skb, FREE_WRITE);
+#else /* Grrr, unneeded incompatible change. */
+#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
+#endif
/* The I/O extent. */
#define EPIC_TOTAL_SIZE 0x100
I. Board Compatibility
This device driver is designed for the SMC "EPCI/100", the SMC
-single-chip ethernet controllers for PCI. This chip is used on
+single-chip Ethernet controllers for PCI. This chip is used on
the SMC EtherPower II boards.
*/
-#ifndef PCI_VENDOR_ID_SMC
-#define PCI_VENDOR_ID_SMC 0x10B8
-#endif
-#ifndef PCI_DEVICE_ID_SMC_EPIC100
-#define PCI_DEVICE_ID_SMC_EPIC100 0x0005
-#endif
-
/* The rest of these values should never change. */
+
+static struct device *epic_probe1(int pci_bus, int pci_devfn,
+ struct device *dev, int card_idx);
+
+enum pci_flags_bit {
+ PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
+ PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
+};
+struct chip_info {
+ const char *name;
+ u16 vendor_id, device_id, device_id_mask, pci_flags;
+ int io_size, min_latency;
+ struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev,
+ int chip_idx);
+} chip_tbl[] = {
+ {"SMSC EPIC/100", 0x10B8, 0x0005, 0x7fff,
+ PCI_USES_IO|PCI_USES_MASTER|PCI_ADDR0, EPIC_TOTAL_SIZE, 32, epic_probe1},
+ {0,},
+};
+
/* Offsets to registers, using the (ugh) SMC names. */
enum epic_registers {
COMMAND=0, INTSTAT=4, INTMASK=8, GENCTL=0x0C, NVCTL=0x10, EECTL=0x14,
+ PCIBurstCnt=0x18,
TEST1=0x1C, CRCCNT=0x20, ALICNT=0x24, MPCNT=0x28, /* Rx error counters. */
MIICtrl=0x30, MIIData=0x34, MIICfg=0x38,
LAN0=64, /* MAC address. */
/* Interrupt register bits, using my own meaningful names. */
enum IntrStatus {
- TxIdle=0x40000, RxIdle=0x20000,
- CntFull=0x0200, TxUnderrun=0x0100,
+ TxIdle=0x40000, RxIdle=0x20000, IntrSummary=0x010000,
+ PCIBusErr170=0x7000, PCIBusErr175=0x1000, PhyEvent175=0x8000,
+ RxStarted=0x0800, RxEarlyWarn=0x0400, CntFull=0x0200, TxUnderrun=0x0100,
TxEmpty=0x0080, TxDone=0x0020, RxError=0x0010,
RxOverflow=0x0008, RxFull=0x0004, RxHeader=0x0002, RxDone=0x0001,
};
u32 bufaddr;
u16 buflength;
u16 control;
- u32 next;
+ u32 next;
};
struct epic_rx_desc {
u16 rxlength;
u32 bufaddr;
u32 buflength;
- u32 next;
+ u32 next;
};
struct epic_private {
u8 pci_bus, pci_dev_fn; /* PCI bus location. */
u16 chip_id;
- struct enet_statistics stats;
+ struct net_device_stats stats;
struct timer_list timer; /* Media selection timer. */
unsigned char mc_filter[8];
signed char phys[4]; /* MII device addresses. */
unsigned int tx_full:1; /* The Tx queue is full. */
- unsigned int full_duplex:1; /* Full-duplex operation requested. */
+ unsigned int full_duplex:1; /* Current duplex setting. */
+ unsigned int force_fd:1; /* Full-duplex operation requested. */
unsigned int default_port:4; /* Last dev->if_port value. */
unsigned int media2:4; /* Secondary monitored media port. */
unsigned int medialock:1; /* Don't sense media type. */
static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static struct device *epic100_probe1(int pci_bus, int pci_devfn,
- struct device *dev, int card_idx);
static int epic_open(struct device *dev);
-static int read_eeprom(int ioaddr, int location);
-static int mii_read(int ioaddr, int phy_id, int location);
+static int read_eeprom(long ioaddr, int location);
+static int mdio_read(long ioaddr, int phy_id, int location);
+static void mdio_write(long ioaddr, int phy_id, int location, int value);
+static void epic_restart(struct device *dev);
static void epic_timer(unsigned long data);
static void epic_tx_timeout(struct device *dev);
static void epic_init_ring(struct device *dev);
static int epic_start_xmit(struct sk_buff *skb, struct device *dev);
static int epic_rx(struct device *dev);
static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd);
static int epic_close(struct device *dev);
-static struct enet_statistics *epic_get_stats(struct device *dev);
+static struct net_device_stats *epic_get_stats(struct device *dev);
static void set_rx_mode(struct device *dev);
\f
/* A list of all installed EPIC devices, for removing the driver module. */
static struct device *root_epic_dev = NULL;
+#ifndef CARDBUS
int epic100_probe(struct device *dev)
{
- static int cards_found = 0;
- static int pci_index = 0; /* Static, for multiple probe calls. */
+ int cards_found = 0;
+ int chip_idx;
+ u16 pci_command, new_command;
+ unsigned char pci_bus, pci_device_fn;
+
+#ifdef PCI_SUPPORT_VER2
+ struct pci_dev *pcidev = NULL;
+ while ((pcidev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pcidev))
+ != NULL) {
+ long pci_ioaddr = pcidev->base_address[0] & ~3;
+ int vendor = pcidev->vendor;
+ int device = pcidev->device;
+
+ for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++)
+ if (vendor == chip_tbl[chip_idx].vendor_id
+ && (device & chip_tbl[chip_idx].device_id_mask) ==
+ chip_tbl[chip_idx].device_id)
+ break;
+ if (chip_tbl[chip_idx].vendor_id == 0 /* Compiled out! */
+ || check_region(pci_ioaddr, chip_tbl[chip_idx].io_size))
+ continue;
+ pci_bus = pcidev->bus->number;
+ pci_device_fn = pcidev->devfn;
+#else
+ int pci_index;
+
+ if ( ! pcibios_present())
+ return -ENODEV;
- /* Ideally we would detect all network cards in slot order. That would
- be best done a central PCI probe dispatch, which wouldn't work
- well with the current structure. So instead we detect just the
- Epic cards in slot order. */
+ for (pci_index = 0; pci_index < 0xff; pci_index++) {
+ u16 vendor, device;
+ u32 pci_ioaddr;
- if (pcibios_present()) {
- unsigned char pci_bus, pci_device_fn;
+ if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
+ pci_index, &pci_bus, &pci_device_fn)
+ != PCIBIOS_SUCCESSFUL)
+ break;
+ pcibios_read_config_word(pci_bus, pci_device_fn,
+ PCI_VENDOR_ID, &vendor);
+ pcibios_read_config_word(pci_bus, pci_device_fn,
+ PCI_DEVICE_ID, &device);
+
+ for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++)
+ if (vendor == chip_tbl[chip_idx].vendor_id
+ && (device & chip_tbl[chip_idx].device_id_mask) ==
+ chip_tbl[chip_idx].device_id)
+ break;
+ if (chip_tbl[chip_idx].vendor_id == 0) /* Compiled out! */
+ continue;
- for (;pci_index < 0xff; pci_index++) {
- u8 pci_latency;
- u16 pci_command, new_command, vendor, device;
- u32 pci_ioaddr;
+ pcibios_read_config_dword(pci_bus, pci_device_fn,
+ PCI_BASE_ADDRESS_0, &pci_ioaddr);
+ /* Remove I/O space marker in bit 0. */
+ pci_ioaddr &= ~3;
- if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
-#ifdef REVERSE_PROBE_ORDER
- 0xff - pci_index,
-#else
- pci_index,
+ if (check_region(pci_ioaddr, chip_tbl[chip_idx].io_size))
+ continue;
#endif
- &pci_bus, &pci_device_fn)
- != PCIBIOS_SUCCESSFUL)
- break;
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_VENDOR_ID, &vendor);
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_DEVICE_ID, &device);
- if (vendor != PCI_VENDOR_ID_SMC)
- continue;
- if (device != PCI_DEVICE_ID_SMC_EPIC100) {
- printk("Unknown SMC PCI ethernet chip type %4.4x detected:"
- " not configured.\n", device);
- continue;
- }
- /* Activate the card: fix for brain-damaged Win98 BIOSes. */
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, &pci_command);
- new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
- if (pci_command != new_command) {
- printk(KERN_INFO " The PCI BIOS has not enabled Ethernet"
- " device %4.4x-%4.4x."
- " Updating PCI command %4.4x->%4.4x.\n",
- vendor, device, pci_command, new_command);
- pcibios_write_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, new_command);
- }
+ /* EPIC-specific code: Soft-reset the chip ere setting as master. */
+ outl(0x0001, pci_ioaddr + GENCTL);
+
+ /* Activate the card: fix for brain-damaged Win98 BIOSes. */
+ pcibios_read_config_word(pci_bus, pci_device_fn,
+ PCI_COMMAND, &pci_command);
+ new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
+ if (pci_command != new_command) {
+ printk(KERN_INFO " The PCI BIOS has not enabled Ethernet"
+ " device %4.4x-%4.4x."
+ " Updating PCI command %4.4x->%4.4x.\n",
+ vendor, device, pci_command, new_command);
+ pcibios_write_config_word(pci_bus, pci_device_fn,
+ PCI_COMMAND, new_command);
+ }
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_0, &pci_ioaddr);
- /* Remove I/O space marker in bit 0. */
- pci_ioaddr &= ~3;
-
- if (check_region(pci_ioaddr, EPIC_TOTAL_SIZE))
- continue;
-
- dev = epic100_probe1(pci_bus, pci_device_fn, dev, cards_found);
-
- if (dev) {
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, &pci_latency);
- if (pci_latency < 32) {
- printk(" PCI latency timer (CFLT) value of %d is "
- "unreasonably low, setting to 32.\n", pci_latency);
- pcibios_write_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, 32);
- } else if (epic_debug > 1)
- printk(" PCI latency timer (CFLT) is %#x.\n",
- pci_latency);
- dev = 0;
- cards_found++;
+ dev = chip_tbl[chip_idx].probe1(pci_bus, pci_device_fn,
+ dev, cards_found);
+
+ /* Check the latency timer. */
+ if (dev) {
+ u8 pci_latency;
+ pcibios_read_config_byte(pci_bus, pci_device_fn,
+ PCI_LATENCY_TIMER, &pci_latency);
+ if (pci_latency < chip_tbl[chip_idx].min_latency) {
+ printk(KERN_INFO " PCI latency timer (CFLT) value of %d is "
+ "unreasonably low, setting to %d.\n", pci_latency,
+ chip_tbl[chip_idx].min_latency);
+ pcibios_write_config_byte(pci_bus, pci_device_fn,
+ PCI_LATENCY_TIMER,
+ chip_tbl[chip_idx].min_latency);
}
+ dev = 0;
+ cards_found++;
}
}
return cards_found ? 0 : -ENODEV;
}
+#endif /* not CARDBUS */
-static struct device *epic100_probe1(int bus, int devfn, struct device *dev,
+static struct device *epic_probe1(int bus, int devfn, struct device *dev,
int card_idx)
{
static int did_version = 0; /* Already printed version info. */
- struct epic_private *tp;
+ struct epic_private *ep;
int i, option = 0, duplex = 0;
- u8 irq;
u16 chip_id;
u32 ioaddr;
if (epic_debug > 0 && did_version++ == 0)
- printk(version);
+ printk(KERN_INFO "%s", version);
if (dev && dev->mem_start) {
option = dev->mem_start;
dev = init_etherdev(dev, 0);
- pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &ioaddr);
- pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
- pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &chip_id);
- ioaddr &= ~3;
+ { /* Grrrr, badly consider interface change. */
+#if defined(PCI_SUPPORT_VER2)
+ struct pci_dev *pdev = pci_find_slot(bus, devfn);
+ ioaddr = pdev->base_address[0] & ~3;
+ dev->irq = pdev->irq;
+ chip_id = pdev->device;
+#else
+ u8 irq;
+ u32 ioaddr0;
+ pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &ioaddr0);
+ pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
+ pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &chip_id);
+ ioaddr = ioaddr0 & ~3;
+ dev->irq = irq;
+#endif
+ }
- printk("%s: SMC EPIC/100 at %#3x, IRQ %d, ", dev->name, ioaddr, irq);
+ dev->base_addr = ioaddr;
+ printk(KERN_INFO "%s: SMC EPIC/100 (chip ID %4.4x) at %#3x, IRQ %d, ",
+ dev->name, chip_id, ioaddr, dev->irq);
/* Bring the chip out of low-power mode. */
- outl(0x0200, ioaddr + GENCTL);
+ outl(0x4200, ioaddr + GENCTL);
/* Magic?! If we don't set this bit the MII interface won't work. */
outl(0x0008, ioaddr + TEST1);
+ /* Turn on the MII transceiver. */
+ outl(0x12, ioaddr + MIICfg);
+ if (chip_id == 6)
+ outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+ outl(0x0200, ioaddr + GENCTL);
+
/* This could also be read from the EEPROM. */
for (i = 0; i < 3; i++)
((u16 *)dev->dev_addr)[i] = inw(ioaddr + LAN0 + i*4);
printk("%2.2x.\n", dev->dev_addr[i]);
if (epic_debug > 1) {
- printk("%s: EEPROM contents\n", dev->name);
- for (i = 0; i < 64; i++)
- printk(" %4.4x%s", read_eeprom(ioaddr, i), i % 16 == 15 ? "\n" : "");
+ printk(KERN_DEBUG "%s: EEPROM contents\n", dev->name);
+ for (i = 0; i < 64; i++)
+ printk(" %4.4x%s", read_eeprom(ioaddr, i),
+ i % 16 == 15 ? "\n" : "");
}
/* We do a request_region() to register /proc/ioports info. */
request_region(ioaddr, EPIC_TOTAL_SIZE, "SMC EPIC/100");
- dev->base_addr = ioaddr;
- dev->irq = irq;
-
/* The data structures must be quadword aligned. */
- tp = kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA);
- memset(tp, 0, sizeof(*tp));
- dev->priv = tp;
+ ep = kmalloc(sizeof(*ep), GFP_KERNEL | GFP_DMA);
+ memset(ep, 0, sizeof(*ep));
+ dev->priv = ep;
- tp->next_module = root_epic_dev;
+ ep->next_module = root_epic_dev;
root_epic_dev = dev;
- tp->chip_id = chip_id;
+ ep->pci_bus = bus;
+ ep->pci_dev_fn = devfn;
+ ep->chip_id = chip_id;
/* Find the connected MII xcvrs.
Doing this in open() would allow detecting external xcvrs later, but
takes too much time. */
{
int phy, phy_idx;
- for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
+ for (phy = 1, phy_idx = 0; phy < 32 && phy_idx < sizeof(ep->phys);
phy++) {
- int mii_status = mii_read(ioaddr, phy, 0);
+ int mii_status = mdio_read(ioaddr, phy, 1);
if (mii_status != 0xffff && mii_status != 0x0000) {
- tp->phys[phy_idx++] = phy;
- printk("%s: MII transceiver found at address %d.\n",
- dev->name, phy);
+ ep->phys[phy_idx++] = phy;
+ printk(KERN_INFO "%s: MII transceiver #%d control "
+ "%4.4x status %4.4x.\n"
+ KERN_INFO "%s: Autonegotiation advertising %4.4x "
+ "link partner %4.4x.\n",
+ dev->name, phy, mdio_read(ioaddr, phy, 0), mii_status,
+ dev->name, mdio_read(ioaddr, phy, 4),
+ mdio_read(ioaddr, phy, 5));
}
}
if (phy_idx == 0) {
- printk("%s: ***WARNING***: No MII transceiver found!\n",
+ printk(KERN_WARNING "%s: ***WARNING***: No MII transceiver found!\n",
dev->name);
/* Use the known PHY address of the EPII. */
- tp->phys[0] = 3;
+ ep->phys[0] = 3;
}
}
- /* Leave the chip in low-power mode. */
+ /* Turn off the MII xcvr (175 only!), leave the chip in low-power mode. */
+ if (ep->chip_id == 6)
+ outl(inl(ioaddr + NVCTL) & ~0x483C, ioaddr + NVCTL);
outl(0x0008, ioaddr + GENCTL);
/* The lower four bits are the media type. */
- tp->full_duplex = duplex;
- tp->default_port = option;
- if (tp->default_port)
- tp->medialock = 1;
+ ep->force_fd = duplex;
+ ep->default_port = option;
+ if (ep->default_port)
+ ep->medialock = 1;
/* The Epic-specific entries in the device structure. */
dev->open = &epic_open;
dev->stop = &epic_close;
dev->get_stats = &epic_get_stats;
dev->set_multicast_list = &set_rx_mode;
+ dev->do_ioctl = &mii_ioctl;
return dev;
}
/* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD (5 << 6)
-#define EE_READ_CMD (6 << 6)
+#define EE_READ64_CMD (6 << 6)
+#define EE_READ256_CMD (6 << 8)
#define EE_ERASE_CMD (7 << 6)
-static int read_eeprom(int ioaddr, int location)
+static int read_eeprom(long ioaddr, int location)
{
int i;
int retval = 0;
- int ee_addr = ioaddr + EECTL;
- int read_cmd = location | EE_READ_CMD;
-
+ long ee_addr = ioaddr + EECTL;
+ int read_cmd = location |
+ (inl(ee_addr) & 0x40) ? EE_READ64_CMD : EE_READ256_CMD;
+
+ printk("EEctrl is %x.\n", inl(ee_addr));
outl(EE_ENB & ~EE_CS, ee_addr);
outl(EE_ENB, ee_addr);
-
+
/* Shift the read command bits out. */
- for (i = 10; i >= 0; i--) {
- short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+ for (i = 12; i >= 0; i--) {
+ short dataval = (read_cmd & (1 << i)) ? EE_WRITE_1 : EE_WRITE_0;
outl(EE_ENB | dataval, ee_addr);
eeprom_delay(100);
outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
eeprom_delay(150);
- outl(EE_ENB | dataval, ee_addr); /* Finish EEPROM a clock tick. */
- eeprom_delay(250);
}
outl(EE_ENB, ee_addr);
-
+
for (i = 16; i > 0; i--) {
outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
eeprom_delay(100);
#define MII_READOP 1
#define MII_WRITEOP 2
-static int mii_read(int ioaddr, int phy_id, int location)
+static int mdio_read(long ioaddr, int phy_id, int location)
{
int i;
/* Typical operation takes < 50 ticks. */
for (i = 4000; i > 0; i--)
if ((inl(ioaddr + MIICtrl) & MII_READOP) == 0)
+ return inw(ioaddr + MIIData);
+ return 0xffff;
+}
+
+static void mdio_write(long ioaddr, int phy_id, int location, int value)
+{
+ int i;
+
+ outw(value, ioaddr + MIIData);
+ outl((phy_id << 9) | (location << 4) | MII_WRITEOP, ioaddr + MIICtrl);
+ for (i = 10000; i > 0; i--) {
+ if ((inl(ioaddr + MIICtrl) & MII_WRITEOP) == 0)
break;
- return inw(ioaddr + MIIData);
+ }
+ return;
}
\f
static int
epic_open(struct device *dev)
{
- struct epic_private *tp = (struct epic_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
+ long ioaddr = dev->base_addr;
int i;
int mii_reg5;
- int full_duplex = 0;
+ ep->full_duplex = ep->force_fd;
/* Soft reset the chip. */
- outl(0x0001, ioaddr + GENCTL);
+ outl(0x4001, ioaddr + GENCTL);
if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, "SMC EPIC/100", dev))
return -EAGAIN;
epic_init_ring(dev);
- /* This next line by Ken Yamaguchi.. ?? */
- outl(0x8, ioaddr + 0x1c);
+ outl(0x4000, ioaddr + GENCTL);
+ /* This next magic! line by Ken Yamaguchi.. ?? */
+ outl(0x0008, ioaddr + TEST1);
/* Pull the chip out of low-power mode, enable interrupts, and set for
- PCI read multiple. */
+ PCI read multiple. The MIIcfg setting and strange write order are
+ required by the details of which bits are reset and the transceiver
+ wiring on the Ositech CardBus card.
+ */
+ outl(0x12, ioaddr + MIICfg);
+ if (ep->chip_id == 6)
+ outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+
+#if defined(__powerpc__) || defined(__sparc__) /* Big endian */
+ outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+#else
outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+#endif
for (i = 0; i < 3; i++)
outl(((u16*)dev->dev_addr)[i], ioaddr + LAN0 + i*4);
outl(TX_FIFO_THRESH, ioaddr + TxThresh);
- full_duplex = tp->full_duplex;
- mii_reg5 = mii_read(ioaddr, tp->phys[0], 5);
- if (mii_reg5 != 0xffff && (mii_reg5 & 0x0100)) {
- full_duplex = 1;
+ mii_reg5 = mdio_read(ioaddr, ep->phys[0], 5);
+ if (mii_reg5 != 0xffff) {
+ if ((mii_reg5 & 0x0100) || (mii_reg5 & 0x01C0) == 0x0040)
+ ep->full_duplex = 1;
+ else if (! (mii_reg5 & 0x4000))
+ mdio_write(ioaddr, ep->phys[0], 0, 0x1200);
if (epic_debug > 1)
- printk("%s: Setting %s-duplex based on MII xcvr %d"
+ printk(KERN_INFO "%s: Setting %s-duplex based on MII xcvr %d"
" register read of %4.4x.\n", dev->name,
- full_duplex ? "full" : "half", tp->phys[0],
- mii_read(ioaddr, tp->phys[0], 5));
+ ep->full_duplex ? "full" : "half", ep->phys[0], mii_reg5);
}
- outl(full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
- outl(virt_to_bus(tp->rx_ring), ioaddr + PRxCDAR);
- outl(virt_to_bus(tp->tx_ring), ioaddr + PTxCDAR);
+ outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+ outl(virt_to_bus(ep->rx_ring), ioaddr + PRxCDAR);
+ outl(virt_to_bus(ep->tx_ring), ioaddr + PTxCDAR);
/* Start the chip's Rx process. */
set_rx_mode(dev);
dev->start = 1;
/* Enable interrupts by setting the interrupt mask. */
- outl(CntFull | TxUnderrun | TxDone
+ outl((ep->chip_id == 6 ? PCIBusErr175 : PCIBusErr170)
+ | CntFull | TxUnderrun | TxDone
| RxError | RxOverflow | RxFull | RxHeader | RxDone,
ioaddr + INTMASK);
if (epic_debug > 1)
- printk("%s: epic_open() ioaddr %4.4x IRQ %d status %4.4x %s-duplex.\n",
+ printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x "
+ "%s-duplex.\n",
dev->name, ioaddr, dev->irq, inl(ioaddr + GENCTL),
- full_duplex ? "full" : "half");
+ ep->full_duplex ? "full" : "half");
/* Set the timer to switch to check for link beat and perhaps switch
to an alternate media type. */
- init_timer(&tp->timer);
- tp->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */
- tp->timer.data = (unsigned long)dev;
- tp->timer.function = &epic_timer; /* timer handler */
- add_timer(&tp->timer);
+ init_timer(&ep->timer);
+ ep->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */
+ ep->timer.data = (unsigned long)dev;
+ ep->timer.function = &epic_timer; /* timer handler */
+ add_timer(&ep->timer);
return 0;
}
+/* Reset the chip to recover from a PCI transaction error.
+ This may occur at interrupt time. */
+static void epic_pause(struct device *dev)
+{
+ long ioaddr = dev->base_addr;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
+
+ /* Disable interrupts by clearing the interrupt mask. */
+ outl(0x00000000, ioaddr + INTMASK);
+ /* Stop the chip's Tx and Rx DMA processes. */
+ outw(0x0061, ioaddr + COMMAND);
+
+ /* Update the error counts. */
+ if (inw(ioaddr + COMMAND) != 0xffff) {
+ ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+ ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+ ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+ }
+
+ /* Remove the packets on the Rx queue. */
+ epic_rx(dev);
+}
+
+static void epic_restart(struct device *dev)
+{
+ long ioaddr = dev->base_addr;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
+ int i;
+
+ printk(KERN_DEBUG "%s: Restarting the EPIC chip, Rx %d/%d Tx %d/%d.\n",
+ dev->name, ep->cur_rx, ep->dirty_rx, ep->dirty_tx, ep->cur_tx);
+ /* Soft reset the chip. */
+ outl(0x0001, ioaddr + GENCTL);
+
+ udelay(1);
+ /* Duplicate code from epic_open(). */
+ outl(0x0008, ioaddr + TEST1);
+
+#if defined(__powerpc__) /* Big endian */
+ outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+#else
+ outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+#endif
+ outl(0x12, ioaddr + MIICfg);
+ if (ep->chip_id == 6)
+ outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+
+ for (i = 0; i < 3; i++)
+ outl(((u16*)dev->dev_addr)[i], ioaddr + LAN0 + i*4);
+
+ outl(TX_FIFO_THRESH, ioaddr + TxThresh);
+ outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+ outl(virt_to_bus(&ep->rx_ring[ep->cur_rx%RX_RING_SIZE]), ioaddr + PRxCDAR);
+ outl(virt_to_bus(&ep->tx_ring[ep->dirty_tx%TX_RING_SIZE]),
+ ioaddr + PTxCDAR);
+
+ /* Start the chip's Rx process. */
+ set_rx_mode(dev);
+ outl(0x000A, ioaddr + COMMAND);
+
+ /* Enable interrupts by setting the interrupt mask. */
+ outl((ep->chip_id == 6 ? PCIBusErr175 : PCIBusErr170)
+ | CntFull | TxUnderrun | TxDone
+ | RxError | RxOverflow | RxFull | RxHeader | RxDone,
+ ioaddr + INTMASK);
+ printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x"
+ " interrupt %4.4x.\n",
+ dev->name, inl(ioaddr + COMMAND), inl(ioaddr + GENCTL),
+ inl(ioaddr + INTSTAT));
+ return;
+}
+
static void epic_timer(unsigned long data)
{
struct device *dev = (struct device *)data;
- struct epic_private *tp = (struct epic_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
+ long ioaddr = dev->base_addr;
int next_tick = 0;
+ int mii_reg5 = mdio_read(ioaddr, ep->phys[0], 5);
if (epic_debug > 3) {
- printk("%s: Media selection tick, Tx status %8.8x.\n",
+ printk(KERN_DEBUG "%s: Media selection tick, Tx status %8.8x.\n",
dev->name, inl(ioaddr + TxSTAT));
- printk("%s: Other registers are IntMask %4.4x IntStatus %4.4x RxStatus"
- " %4.4x.\n",
+ printk(KERN_DEBUG "%s: Other registers are IntMask %4.4x "
+ "IntStatus %4.4x RxStatus %4.4x.\n",
dev->name, inl(ioaddr + INTMASK), inl(ioaddr + INTSTAT),
inl(ioaddr + RxSTAT));
}
+ if (! ep->force_fd && mii_reg5 != 0xffff) {
+ int duplex = (mii_reg5&0x0100) || (mii_reg5 & 0x01C0) == 0x0040;
+ if (ep->full_duplex != duplex) {
+ ep->full_duplex = duplex;
+ printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link"
+ " partner capability of %4.4x.\n", dev->name,
+ ep->full_duplex ? "full" : "half", ep->phys[0], mii_reg5);
+ outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+ }
+ next_tick = 60*HZ;
+ }
if (next_tick) {
- tp->timer.expires = RUN_AT(next_tick);
- add_timer(&tp->timer);
+ ep->timer.expires = RUN_AT(next_tick);
+ add_timer(&ep->timer);
}
}
static void epic_tx_timeout(struct device *dev)
{
- struct epic_private *tp = (struct epic_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
+ long ioaddr = dev->base_addr;
if (epic_debug > 0) {
- printk("%s: Transmit timeout using MII device, Tx status %4.4x.\n",
+ printk(KERN_WARNING "%s: Transmit timeout using MII device, "
+ "Tx status %4.4x.\n",
dev->name, inw(ioaddr + TxSTAT));
if (epic_debug > 1) {
- printk("%s: Tx indices: dirty_tx %d, cur_tx %d.\n",
- dev->name, tp->dirty_tx, tp->cur_tx);
+ printk(KERN_DEBUG "%s: Tx indices: dirty_tx %d, cur_tx %d.\n",
+ dev->name, ep->dirty_tx, ep->cur_tx);
}
}
+ if (inw(ioaddr + TxSTAT) & 0x10) { /* Tx FIFO underflow. */
+ ep->stats.tx_fifo_errors++;
+ /* Restart the transmit process. */
+ outl(0x0080, ioaddr + COMMAND);
+ }
+
/* Perhaps stop and restart the chip's Tx processes . */
/* Trigger a transmit demand. */
outl(0x0004, dev->base_addr + COMMAND);
dev->trans_start = jiffies;
- tp->stats.tx_errors++;
+ ep->stats.tx_errors++;
return;
}
static void
epic_init_ring(struct device *dev)
{
- struct epic_private *tp = (struct epic_private *)dev->priv;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
int i;
- tp->tx_full = 0;
- tp->cur_rx = tp->cur_tx = 0;
- tp->dirty_rx = tp->dirty_tx = 0;
+ ep->tx_full = 0;
+ ep->cur_rx = ep->cur_tx = 0;
+ ep->dirty_rx = ep->dirty_tx = 0;
for (i = 0; i < RX_RING_SIZE; i++) {
- tp->rx_ring[i].status = 0x8000; /* Owned by Epic chip */
- tp->rx_ring[i].buflength = PKT_BUF_SZ;
+ ep->rx_ring[i].status = 0x8000; /* Owned by Epic chip */
+ ep->rx_ring[i].buflength = PKT_BUF_SZ;
{
/* Note the receive buffer must be longword aligned.
dev_alloc_skb() provides 16 byte alignment. But do *not*
use skb_reserve() to align the IP header! */
struct sk_buff *skb;
skb = dev_alloc_skb(PKT_BUF_SZ);
- tp->rx_skbuff[i] = skb;
+ ep->rx_skbuff[i] = skb;
if (skb == NULL)
break; /* Bad news! */
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- tp->rx_ring[i].bufaddr = virt_to_bus(skb->tail);
+ ep->rx_ring[i].bufaddr = virt_to_bus(skb->tail);
}
- tp->rx_ring[i].next = virt_to_bus(&tp->rx_ring[i+1]);
+ ep->rx_ring[i].next = virt_to_bus(&ep->rx_ring[i+1]);
}
/* Mark the last entry as wrapping the ring. */
- tp->rx_ring[i-1].next = virt_to_bus(&tp->rx_ring[0]);
+ ep->rx_ring[i-1].next = virt_to_bus(&ep->rx_ring[0]);
/* The Tx buffer descriptor is filled in as needed, but we
do need to clear the ownership bit. */
for (i = 0; i < TX_RING_SIZE; i++) {
- tp->tx_skbuff[i] = 0;
- tp->tx_ring[i].status = 0x0000;
- tp->tx_ring[i].next = virt_to_bus(&tp->tx_ring[i+1]);
+ ep->tx_skbuff[i] = 0;
+ ep->tx_ring[i].status = 0x0000;
+ ep->tx_ring[i].next = virt_to_bus(&ep->tx_ring[i+1]);
}
- tp->tx_ring[i-1].next = virt_to_bus(&tp->tx_ring[0]);
+ ep->tx_ring[i-1].next = virt_to_bus(&ep->tx_ring[0]);
}
static int
epic_start_xmit(struct sk_buff *skb, struct device *dev)
{
- struct epic_private *tp = (struct epic_private *)dev->priv;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
int entry;
u32 flag;
with the "ownership" bits last. */
/* Calculate the next Tx descriptor entry. */
- entry = tp->cur_tx % TX_RING_SIZE;
+ entry = ep->cur_tx % TX_RING_SIZE;
- tp->tx_skbuff[entry] = skb;
- tp->tx_ring[entry].txlength = (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN);
- tp->tx_ring[entry].bufaddr = virt_to_bus(skb->data);
- tp->tx_ring[entry].buflength = skb->len;
+ ep->tx_skbuff[entry] = skb;
+ ep->tx_ring[entry].txlength = (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN);
+ ep->tx_ring[entry].bufaddr = virt_to_bus(skb->data);
+ ep->tx_ring[entry].buflength = skb->len;
- if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
+ if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
flag = 0x10; /* No interrupt */
clear_bit(0, (void*)&dev->tbusy);
- } else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) {
+ } else if (ep->cur_tx - ep->dirty_tx == TX_RING_SIZE/2) {
flag = 0x14; /* Tx-done intr. */
clear_bit(0, (void*)&dev->tbusy);
- } else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) {
+ } else if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE - 2) {
flag = 0x10; /* No Tx-done intr. */
clear_bit(0, (void*)&dev->tbusy);
} else {
/* Leave room for two additional entries. */
flag = 0x14; /* Tx-done intr. */
- tp->tx_full = 1;
+ ep->tx_full = 1;
}
- tp->tx_ring[entry].control = flag;
- tp->tx_ring[entry].status = 0x8000; /* Pass ownership to the chip. */
- tp->cur_tx++;
+ ep->tx_ring[entry].control = flag;
+ ep->tx_ring[entry].status = 0x8000; /* Pass ownership to the chip. */
+ ep->cur_tx++;
/* Trigger an immediate transmit demand. */
outl(0x0004, dev->base_addr + COMMAND);
dev->trans_start = jiffies;
if (epic_debug > 4)
- printk("%s: Queued Tx packet size %d to slot %d, "
+ printk(KERN_DEBUG "%s: Queued Tx packet size %d to slot %d, "
"flag %2.2x Tx status %8.8x.\n",
dev->name, (int)skb->len, entry, flag,
inl(dev->base_addr + TxSTAT));
static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
{
struct device *dev = (struct device *)dev_instance;
- struct epic_private *lp;
+ struct epic_private *ep;
int status, ioaddr, boguscnt = max_interrupt_work;
ioaddr = dev->base_addr;
- lp = (struct epic_private *)dev->priv;
+ ep = (struct epic_private *)dev->priv;
+
+#if defined(__i386__)
+ /* A lock to prevent simultaneous entry bug on Intel SMP machines. */
+ if (test_and_set_bit(0, (void*)&dev->interrupt)) {
+ printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
+ dev->name);
+ dev->interrupt = 0; /* Avoid halting machine. */
+ return;
+ }
+#else
if (dev->interrupt) {
- printk("%s: Re-entering the interrupt handler.\n", dev->name);
+ printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
return;
}
dev->interrupt = 1;
+#endif
do {
status = inl(ioaddr + INTSTAT);
printk("%s: interrupt interrupt=%#8.8x new intstat=%#8.8x.\n",
dev->name, status, inl(ioaddr + INTSTAT));
- if ((status & (RxDone | TxEmpty | TxDone)) == 0)
+ if ((status & IntrSummary) == 0)
break;
- if (status & RxDone) /* Rx interrupt */
+ if (status & (RxDone | RxStarted | RxEarlyWarn))
epic_rx(dev);
if (status & (TxEmpty | TxDone)) {
int dirty_tx;
- for (dirty_tx = lp->dirty_tx; dirty_tx < lp->cur_tx; dirty_tx++) {
+ for (dirty_tx = ep->dirty_tx; dirty_tx < ep->cur_tx; dirty_tx++) {
int entry = dirty_tx % TX_RING_SIZE;
- int txstatus = lp->tx_ring[entry].status;
+ int txstatus = ep->tx_ring[entry].status;
if (txstatus < 0)
break; /* It still hasn't been Txed */
printk("%s: Transmit error, Tx status %8.8x.\n",
dev->name, txstatus);
#endif
- lp->stats.tx_errors++;
- if (txstatus & 0x1050) lp->stats.tx_aborted_errors++;
- if (txstatus & 0x0008) lp->stats.tx_carrier_errors++;
- if (txstatus & 0x0040) lp->stats.tx_window_errors++;
- if (txstatus & 0x0010) lp->stats.tx_fifo_errors++;
+ ep->stats.tx_errors++;
+ if (txstatus & 0x1050) ep->stats.tx_aborted_errors++;
+ if (txstatus & 0x0008) ep->stats.tx_carrier_errors++;
+ if (txstatus & 0x0040) ep->stats.tx_window_errors++;
+ if (txstatus & 0x0010) ep->stats.tx_fifo_errors++;
#ifdef ETHER_STATS
- if (txstatus & 0x1000) lp->stats.collisions16++;
+ if (txstatus & 0x1000) ep->stats.collisions16++;
#endif
} else {
#ifdef ETHER_STATS
- if ((txstatus & 0x0002) != 0) lp->stats.tx_deferred++;
+ if ((txstatus & 0x0002) != 0) ep->stats.tx_deferred++;
#endif
- lp->stats.collisions += (txstatus >> 8) & 15;
- lp->stats.tx_packets++;
+ ep->stats.collisions += (txstatus >> 8) & 15;
+ ep->stats.tx_packets++;
}
/* Free the original skb. */
- dev_kfree_skb(lp->tx_skbuff[entry], FREE_WRITE);
- lp->tx_skbuff[entry] = 0;
+ DEV_FREE_SKB(ep->tx_skbuff[entry]);
+ ep->tx_skbuff[entry] = 0;
}
#ifndef final_version
- if (lp->cur_tx - dirty_tx > TX_RING_SIZE) {
+ if (ep->cur_tx - dirty_tx > TX_RING_SIZE) {
printk("%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
- dev->name, dirty_tx, lp->cur_tx, lp->tx_full);
+ dev->name, dirty_tx, ep->cur_tx, ep->tx_full);
dirty_tx += TX_RING_SIZE;
}
#endif
- if (lp->tx_full && dev->tbusy
- && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
+ if (ep->tx_full && dev->tbusy
+ && dirty_tx > ep->cur_tx - TX_RING_SIZE + 2) {
/* The ring is no longer full, clear tbusy. */
- lp->tx_full = 0;
+ ep->tx_full = 0;
clear_bit(0, (void*)&dev->tbusy);
mark_bh(NET_BH);
}
- lp->dirty_tx = dirty_tx;
+ ep->dirty_tx = dirty_tx;
}
/* Check uncommon events all at once. */
- if (status & (CntFull | TxUnderrun | RxOverflow)) {
+ if (status & (CntFull | TxUnderrun | RxOverflow |
+ PCIBusErr170 | PCIBusErr175)) {
+ if (status == 0xffffffff) /* Chip failed or removed (CardBus). */
+ break;
/* Always update the error counts to avoid overhead later. */
- lp->stats.rx_missed_errors += inb(ioaddr + MPCNT);
- lp->stats.rx_frame_errors += inb(ioaddr + ALICNT);
- lp->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+ ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+ ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+ ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
if (status & TxUnderrun) { /* Tx FIFO underflow. */
- lp->stats.tx_fifo_errors++;
- /* Restart the transmit process. */
- outl(0x0080, ioaddr + COMMAND);
+ ep->stats.tx_fifo_errors++;
+ outl(1536, ioaddr + TxThresh);
+ /* Restart the transmit process. */
+ outl(0x0080, ioaddr + COMMAND);
}
if (status & RxOverflow) { /* Missed a Rx frame. */
- lp->stats.rx_errors++;
+ ep->stats.rx_errors++;
+ }
+ if (status & PCIBusErr170) {
+ printk(KERN_ERR "%s: PCI Bus Error! EPIC status %4.4x.\n",
+ dev->name, status);
+ epic_pause(dev);
+ epic_restart(dev);
}
/* Clear all error sources. */
outl(status & 0x7f18, ioaddr + INTSTAT);
}
if (--boguscnt < 0) {
- printk("%s: Too much work at interrupt, IntrStatus=0x%8.8x.\n",
+ printk(KERN_ERR "%s: Too much work at interrupt, "
+ "IntrStatus=0x%8.8x.\n",
dev->name, status);
/* Clear all interrupt sources. */
outl(0x0001ffff, ioaddr + INTSTAT);
} while (1);
if (epic_debug > 3)
- printk("%s: exiting interrupt, intr_status=%#4.4x.\n",
+ printk(KERN_DEBUG "%s: exiting interrupt, intr_status=%#4.4x.\n",
dev->name, inl(ioaddr + INTSTAT));
+#if defined(__i386__)
+ clear_bit(0, (void*)&dev->interrupt);
+#else
dev->interrupt = 0;
+#endif
return;
}
-static int
-epic_rx(struct device *dev)
+static int epic_rx(struct device *dev)
{
- struct epic_private *lp = (struct epic_private *)dev->priv;
- int entry = lp->cur_rx % RX_RING_SIZE;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
+ int entry = ep->cur_rx % RX_RING_SIZE;
+ int work_done = 0;
if (epic_debug > 4)
- printk(" In epic_rx(), entry %d %8.8x.\n", entry,
- lp->rx_ring[entry].status);
+ printk(KERN_DEBUG " In epic_rx(), entry %d %8.8x.\n", entry,
+ ep->rx_ring[entry].status);
/* If we own the next entry, it's a new packet. Send it up. */
- while (lp->rx_ring[entry].status >= 0) {
- int status = lp->rx_ring[entry].status;
+ while (ep->rx_ring[entry].status >= 0 && ep->rx_skbuff[entry]) {
+ int status = ep->rx_ring[entry].status;
if (epic_debug > 4)
- printk(" epic_rx() status was %8.8x.\n", status);
- if (status & 0x2000) {
- printk("%s: Oversized Ethernet frame spanned multiple buffers,"
- " status %4.4x!\n", dev->name, status);
- lp->stats.rx_length_errors++;
- } else if (status & 0x0006) {
- /* Rx Frame errors are counted in hardware. */
- lp->stats.rx_errors++;
+ printk(KERN_DEBUG " epic_rx() status was %8.8x.\n", status);
+ if (status & 0x2006) {
+ if (status & 0x2000) {
+ printk(KERN_WARNING "%s: Oversized Ethernet frame spanned "
+ "multiple buffers, status %4.4x!\n", dev->name, status);
+ ep->stats.rx_length_errors++;
+ } else if (status & 0x0006)
+ /* Rx Frame errors are counted in hardware. */
+ ep->stats.rx_errors++;
} else {
/* Malloc up new buffer, compatible with net-2e. */
/* Omit the four octet CRC from the length. */
- short pkt_len = lp->rx_ring[entry].rxlength - 4;
+ short pkt_len = ep->rx_ring[entry].rxlength - 4;
struct sk_buff *skb;
- int rx_in_place = 0;
-
- /* Check if the packet is long enough to just accept without
- copying to a properly sized skbuff. */
- if (pkt_len > rx_copybreak) {
- struct sk_buff *newskb;
- char *temp;
-
- /* Pass up the skb already on the Rx ring. */
- skb = lp->rx_skbuff[entry];
- temp = skb_put(skb, pkt_len);
- if (bus_to_virt(lp->rx_ring[entry].bufaddr) != temp)
- printk("%s: Warning -- the skbuff addresses do not match"
- " in epic_rx: %p vs. %p / %p.\n", dev->name,
- bus_to_virt(lp->rx_ring[entry].bufaddr),
- skb->head, temp);
- /* Get a fresh skbuff to replace the filled one. */
- newskb = dev_alloc_skb(PKT_BUF_SZ);
- if (newskb) {
- rx_in_place = 1;
- lp->rx_skbuff[entry] = newskb;
- newskb->dev = dev;
- /* Align IP on 16 byte boundaries */
- skb_reserve(newskb, 2);
- lp->rx_ring[entry].bufaddr = virt_to_bus(newskb->tail);
- } else /* No memory, drop the packet. */
- skb = 0;
- } else
- skb = dev_alloc_skb(pkt_len + 2);
- if (skb == NULL) {
- int i;
- printk("%s: Memory squeeze, deferring packet.\n", dev->name);
- /* Check that at least two ring entries are free.
- If not, free one and mark stats->rx_dropped++. */
- for (i = 0; i < RX_RING_SIZE; i++)
- if (lp->rx_ring[(entry+i) % RX_RING_SIZE].status < 0)
- break;
-
- if (i > RX_RING_SIZE -2) {
- lp->stats.rx_dropped++;
- lp->rx_ring[entry].status = 0x8000;
- lp->cur_rx++;
- }
- break;
- }
- skb->dev = dev;
- if (! rx_in_place) {
- skb_reserve(skb, 2); /* 16 byte align the data fields */
+
+ /* Check if the packet is long enough to accept without copying
+ to a minimally-sized skbuff. */
+ if (pkt_len < rx_copybreak
+ && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+ skb->dev = dev;
+ skb_reserve(skb, 2); /* 16 byte align the IP header */
+#if 1 /* USE_IP_COPYSUM */
+ eth_copy_and_sum(skb, bus_to_virt(ep->rx_ring[entry].bufaddr),
+ pkt_len, 0);
+ skb_put(skb, pkt_len);
+#else
memcpy(skb_put(skb, pkt_len),
- bus_to_virt(lp->rx_ring[entry].bufaddr), pkt_len);
+ bus_to_virt(ep->rx_ring[entry].bufaddr), pkt_len);
+#endif
+ } else {
+ skb_put(skb = ep->rx_skbuff[entry], pkt_len);
+ ep->rx_skbuff[entry] = NULL;
}
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- lp->stats.rx_packets++;
+ ep->stats.rx_packets++;
}
-
- lp->rx_ring[entry].status = 0x8000;
- entry = (++lp->cur_rx) % RX_RING_SIZE;
+ work_done++;
+ entry = (++ep->cur_rx) % RX_RING_SIZE;
}
- return 0;
+ /* Refill the Rx ring buffers. */
+ for (; ep->cur_rx - ep->dirty_rx > 0; ep->dirty_rx++) {
+ entry = ep->dirty_rx % RX_RING_SIZE;
+ if (ep->rx_skbuff[entry] == NULL) {
+ struct sk_buff *skb;
+ skb = ep->rx_skbuff[entry] = dev_alloc_skb(PKT_BUF_SZ);
+ if (skb == NULL)
+ break;
+ skb->dev = dev; /* Mark as being used by this device. */
+ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
+ ep->rx_ring[entry].bufaddr = virt_to_bus(skb->tail);
+ work_done++;
+ }
+ ep->rx_ring[entry].status = 0x8000;
+ }
+ return work_done;
}
-static int
-epic_close(struct device *dev)
+static int epic_close(struct device *dev)
{
- int ioaddr = dev->base_addr;
- struct epic_private *tp = (struct epic_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
int i;
dev->start = 0;
dev->tbusy = 1;
if (epic_debug > 1)
- printk("%s: Shutting down ethercard, status was %2.2x.\n",
+ printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
dev->name, inl(ioaddr + INTSTAT));
/* Disable interrupts by clearing the interrupt mask. */
outw(0x0061, ioaddr + COMMAND);
/* Update the error counts. */
- tp->stats.rx_missed_errors += inb(ioaddr + MPCNT);
- tp->stats.rx_frame_errors += inb(ioaddr + ALICNT);
- tp->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+ ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+ ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+ ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
- del_timer(&tp->timer);
+ del_timer(&ep->timer);
free_irq(dev->irq, dev);
/* Free all the skbuffs in the Rx queue. */
for (i = 0; i < RX_RING_SIZE; i++) {
- struct sk_buff *skb = tp->rx_skbuff[i];
- tp->rx_skbuff[i] = 0;
- tp->rx_ring[i].status = 0; /* Not owned by Epic chip. */
- tp->rx_ring[i].buflength = 0;
- tp->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */
+ struct sk_buff *skb = ep->rx_skbuff[i];
+ ep->rx_skbuff[i] = 0;
+ ep->rx_ring[i].status = 0; /* Not owned by Epic chip. */
+ ep->rx_ring[i].buflength = 0;
+ ep->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */
if (skb) {
#if LINUX_VERSION_CODE < 0x20100
skb->free = 1;
#endif
- dev_kfree_skb(skb, FREE_WRITE);
+ DEV_FREE_SKB(skb);
}
}
for (i = 0; i < TX_RING_SIZE; i++) {
- if (tp->tx_skbuff[i])
- dev_kfree_skb(tp->tx_skbuff[i], FREE_WRITE);
- tp->tx_skbuff[i] = 0;
+ if (ep->tx_skbuff[i])
+ DEV_FREE_SKB(ep->tx_skbuff[i]);
+ ep->tx_skbuff[i] = 0;
}
/* Green! Leave the chip in low-power mode. */
outl(0x0008, ioaddr + GENCTL);
-
+
MOD_DEC_USE_COUNT;
return 0;
}
-static struct enet_statistics *
-epic_get_stats(struct device *dev)
+static struct net_device_stats *epic_get_stats(struct device *dev)
{
- struct epic_private *tp = (struct epic_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
+ long ioaddr = dev->base_addr;
if (dev->start) {
/* Update the error counts. */
- tp->stats.rx_missed_errors += inb(ioaddr + MPCNT);
- tp->stats.rx_frame_errors += inb(ioaddr + ALICNT);
- tp->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+ ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+ ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+ ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
}
- return &tp->stats;
+ return &ep->stats;
}
/* Set or clear the multicast filter for this adaptor.
Note that we only use exclusion around actually queueing the
- new frame, not around filling tp->setup_frame. This is non-deterministic
+ new frame, not around filling ep->setup_frame. This is non-deterministic
when re-entered but still correct. */
/* The little-endian AUTODIN II ethernet CRC calculation.
static void set_rx_mode(struct device *dev)
{
- int ioaddr = dev->base_addr;
- struct epic_private *tp = (struct epic_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
unsigned char mc_filter[8]; /* Multicast hash filter */
int i;
if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
outl(0x002C, ioaddr + RxCtrl);
/* Unconditionally log net taps. */
- printk("%s: Promiscuous mode enabled.\n", dev->name);
+ printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
memset(mc_filter, 0xff, sizeof(mc_filter));
} else if ((dev->mc_count > 0) || (dev->flags & IFF_ALLMULTI)) {
/* There is apparently a chip bug, so the multicast filter
mc_filter);
}
/* ToDo: perhaps we need to stop the Tx and Rx process here? */
- if (memcmp(mc_filter, tp->mc_filter, sizeof(mc_filter))) {
+ if (memcmp(mc_filter, ep->mc_filter, sizeof(mc_filter))) {
for (i = 0; i < 4; i++)
outw(((u16 *)mc_filter)[i], ioaddr + MC0 + i*4);
- memcpy(tp->mc_filter, mc_filter, sizeof(mc_filter));
+ memcpy(ep->mc_filter, mc_filter, sizeof(mc_filter));
}
return;
}
+static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+{
+ long ioaddr = dev->base_addr;
+ u16 *data = (u16 *)&rq->ifr_data;
+
+ switch(cmd) {
+ case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
+ data[0] = ((struct epic_private *)dev->priv)->phys[0] & 0x1f;
+ /* Fall Through */
+ case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
+ if (! dev->start) {
+ outl(0x0200, ioaddr + GENCTL);
+ outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+ }
+ data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
+ if (! dev->start) {
+#ifdef notdef
+ outl(0x0008, ioaddr + GENCTL);
+ outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
+#endif
+ }
+ return 0;
+ case SIOCDEVPRIVATE+2: /* Write the specified MII register */
+ if (!suser())
+ return -EPERM;
+ if (! dev->start) {
+ outl(0x0200, ioaddr + GENCTL);
+ outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+ }
+ mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+ if (! dev->start) {
+#ifdef notdef
+ outl(0x0008, ioaddr + GENCTL);
+ outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
+#endif
+ }
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
\f
#ifdef CARDBUS
pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
io &= ~3;
- dev = epic100_probe1(bus, devfn, NULL, -1);
+ dev = epic_probe1(bus, devfn, NULL, -1);
if (dev) {
dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
strcpy(node->dev_name, dev->name);
return NULL;
}
+static void epic_suspend(dev_node_t *node)
+{
+ struct device **devp, **next;
+ printk(KERN_INFO "epic_suspend(%s)\n", node->dev_name);
+ for (devp = &root_epic_dev; *devp; devp = next) {
+ next = &((struct epic_private *)(*devp)->priv)->next_module;
+ if (strcmp((*devp)->name, node->dev_name) == 0) break;
+ }
+ if (*devp) {
+ long ioaddr = (*devp)->base_addr;
+ epic_pause(*devp);
+ /* Put the chip into low-power mode. */
+ outl(0x0008, ioaddr + GENCTL);
+ }
+}
+static void epic_resume(dev_node_t *node)
+{
+ struct device **devp, **next;
+ printk(KERN_INFO "epic_resume(%s)\n", node->dev_name);
+ for (devp = &root_epic_dev; *devp; devp = next) {
+ next = &((struct epic_private *)(*devp)->priv)->next_module;
+ if (strcmp((*devp)->name, node->dev_name) == 0) break;
+ }
+ if (*devp) {
+ epic_restart(*devp);
+ }
+}
static void epic_detach(dev_node_t *node)
{
struct device **devp, **next;
}
struct driver_operations epic_ops = {
- "epic_cb", epic_attach, NULL, NULL, epic_detach
+ "epic_cb", epic_attach, epic_suspend, epic_resume, epic_detach
};
#endif /* Cardbus support */
\f
/*
* Local variables:
- * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c"
- * alt-compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c"
- * alt-compile-command: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic.c -o epic_cb.c -I/usr/src/pcmcia-cs-3.0.0/include/"
+ * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ * cardbus-compile-command: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c -o epic_cb.o -I/usr/src/pcmcia-cs-3.0.5/include/"
* c-indent-level: 4
* c-basic-offset: 4
* tab-width: 4
/* eth16i.c An ICL EtherTeam 16i and 32 EISA ethernet driver for Linux
-
- Written 1994-95 by Mika Kuoppala
-
- Copyright (C) 1994, 1995 by Mika Kuoppala
- Based on skeleton.c and at1700.c by Donald Becker
+
+ Written 1994-1998 by Mika Kuoppala
+
+ Copyright (C) 1994-1998 by Mika Kuoppala
+ Based on skeleton.c and heavily on at1700.c by Donald Becker
This software may be used and distributed according to the terms
of the GNU Public Licence, incorporated herein by reference.
- The author may be reached as miku@elt.icl.fi
+ The author may be reached as miku@iki.fi
This driver supports following cards :
- ICL EtherTeam 16i
- - ICL EtherTeam 32 EISA
+ - ICL EtherTeam 32 EISA
+ (Uses true 32 bit transfers rather than 16i compability mode)
+
+ Example Module usage:
+ insmod eth16i.o ioaddr=0x2a0 mediatype=bnc
+ mediatype can be one of the following: bnc,tp,dix,auto,eprom
+
+ 'auto' will try to autoprobe mediatype.
+ 'eprom' will use whatever type defined in eprom.
+
+ I have benchmarked driver with PII/300Mhz as a ftp client
+ and 486/33Mhz as a ftp server. Top speed was 1128.37 kilobytes/sec.
+
Sources:
- skeleton.c a sample network driver core for linux,
written by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
written by Markku Viima
- The Fujitsu MB86965 databook.
- Valuable assistance from:
- Markku Viima (ICL)
- Ari Valve (ICL)
-
+ Author thanks following persons due to their valueble assistance:
+ Markku Viima (ICL)
+ Ari Valve (ICL)
+ Donald Becker
+ Kurt Huwig <kurt@huwig.de>
+
Revision history:
Version Date Description
- 0.01 15.12-94 Initial version (card detection)
+ 0.01 15.12-94 Initial version (card detection)
0.02 23.01-95 Interrupt is now hooked correctly
0.03 01.02-95 Rewrote initialization part
0.04 07.02-95 Base skeleton done...
- Made a few changes to signature checking
- to make it a bit reliable.
- - fixed bug in tx_buf mapping
- - fixed bug in initialization (DLC_EN
- wasn't enabled when initialization
- was done.)
- 0.05 08.02-95 If there were more than one packet to send,
- transmit was jammed due to invalid
- register write...now fixed
+ Made a few changes to signature checking
+ to make it a bit reliable.
+ - fixed bug in tx_buf mapping
+ - fixed bug in initialization (DLC_EN
+ wasn't enabled when initialization
+ was done.)
+ 0.05 08.02-95 If there were more than one packet to send,
+ transmit was jammed due to invalid
+ register write...now fixed
0.06 19.02-95 Rewrote interrupt handling
0.07 13.04-95 Wrote EEPROM read routines
Card configuration now set according to
- data read from EEPROM
+ data read from EEPROM
0.08 23.06-95 Wrote part that tries to probe used interface
port if AUTO is selected
- 0.09 01.09-95 Added module support
-
- 0.10 04.09-95 Fixed receive packet allocation to work
- with kernels > 1.3.x
+ 0.09 01.09-95 Added module support
+ 0.10 04.09-95 Fixed receive packet allocation to work
+ with kernels > 1.3.x
+
0.20 20.09-95 Added support for EtherTeam32 EISA
0.21 17.10-95 Removed the unnecessary extern
init_etherdev() declaration. Some
other cleanups.
+
+ 0.22 22.02-96 Receive buffer was not flushed
+ correctly when faulty packet was
+ received. Now fixed.
+
+ 0.23 26.02-96 Made resetting the adapter
+ more reliable.
+
+ 0.24 27.02-96 Rewrote faulty packet handling in eth16i_rx
+
+ 0.25 22.05-96 kfree() was missing from cleanup_module.
+
+ 0.26 11.06-96 Sometimes card was not found by
+ check_signature(). Now made more reliable.
+
+ 0.27 23.06-96 Oops. 16 consecutive collisions halted
+ adapter. Now will try to retransmit
+ MAX_COL_16 times before finally giving up.
+
+ 0.28 28.10-97 Added dev_id parameter (NULL) for free_irq
- 0.21a 15.08-97 Made signature check less restrictive to
- detect card that have been used for booting
- with a bootprom.
+ 0.29 29.10-97 Multiple card support for module users
+
+ 0.30 30.10-97 Fixed irq allocation bug.
+ (request_irq moved from probe to open)
+
+ 0.30a 21.08-98 Card detection made more relaxed. Driver
+ had problems with some TCP/IP-PROM boots
+ to find the card. Suggested by
Kurt Huwig <kurt@huwig.de>
+
+ 0.31 28.08-98 Media interface port can now be selected
+ with module parameters or kernel
+ boot parameters.
+
+ 0.32 31.08-98 IRQ was never freed if open/close
+ pair wasn't called. Now fixed.
+
+ 0.33 10.09-98 When eth16i_open() was called after
+ eth16i_close() chip never recovered.
+ Now more shallow reset is made on
+ close.
+
Bugs:
- In some cases the interface autoprobing code doesn't find
+ In some cases the media interface autoprobing code doesn't find
the correct interface type. In this case you can
manually choose the interface type in DOS with E16IC.EXE which is
configuration software for EtherTeam16i and EtherTeam32 cards.
-
+ This is also true for IRQ setting. You cannot use module
+ parameter to configure IRQ of the card (yet).
+
To do:
- Real multicast support
+ - Rewrite the media interface autoprobing code. Its _horrible_ !
+ - Possibly merge all the MB86965 specific code to external
+ module for use by eth16.c and Donald's at1700.c
+ - IRQ configuration with module parameter. I will do
+ this when i will get enough info about setting
+ irq without configuration utility.
*/
static char *version =
- "eth16i.c: v0.21a 15-08-97 Mika Kuoppala (miku@elt.icl.fi)/Kurt Huwig (kurt@huwig.de)\n";
+ "eth16i.c: v0.33 10-09-98 Mika Kuoppala (miku@iki.fi)\n";
#include <linux/module.h>
#include <asm/io.h>
#include <asm/dma.h>
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#if LINUX_VERSION_CODE >= 0x20123
+#include <linux/init.h>
+#else
+#define __init
+#define __initdata
+#define __initfunc(x) x
+#endif
+
+#if LINUX_VERSION_CODE < 0x20138
+#define test_and_set_bit(val,addr) set_bit(val,addr)
+#endif
+
+#if LINUX_VERSION_CODE < 0x020100
+typedef struct enet_statistics eth16i_stats_type;
+#else
+typedef struct net_device_stats eth16i_stats_type;
+#endif
+
/* Few macros */
-#define BIT(a) ( (1 << (a)) )
+#define BIT(a) ( (1 << (a)) )
#define BITSET(ioaddr, bnum) ((outb(((inb(ioaddr)) | (bnum)), ioaddr)))
#define BITCLR(ioaddr, bnum) ((outb(((inb(ioaddr)) & (~(bnum))), ioaddr)))
/* This is the I/O address space for Etherteam 16i adapter. */
-#define ETH16I_IO_EXTENT 32
+#define ETH16I_IO_EXTENT 32
/* Ticks before deciding that transmit has timed out */
-#define TIMEOUT_TICKS 30
+#define TX_TIMEOUT (400*HZ/1000)
/* Maximum loop count when receiving packets */
-#define MAX_RX_LOOP 40
+#define MAX_RX_LOOP 20
/* Some interrupt masks */
-#define ETH16I_INTR_ON 0x8f82
+#define ETH16I_INTR_ON 0xef8a /* Higher is receive mask */
#define ETH16I_INTR_OFF 0x0000
/* Buffers header status byte meanings */
#define NET_BUSY BIT(6)
#define TX_PKT_RCD BIT(5)
#define CR_LOST BIT(4)
+#define TX_JABBER_ERR BIT(3)
#define COLLISION BIT(2)
#define COLLISIONS_16 BIT(1)
#define BUFFER_WIDTH_8 BIT(4) /* 1 = 8bit, 0 = 16bit */
#define TBS1 BIT(3)
#define TBS0 BIT(2)
-#define _BS1 BIT(1) /* 00=8kb, 01=16kb */
-#define _BS0 BIT(0) /* 10=32kb, 11=64kb */
+#define SRAM_BS1 BIT(1) /* 00=8kb, 01=16kb */
+#define SRAM_BS0 BIT(0) /* 10=32kb, 11=64kb */
#ifndef ETH16I_TX_BUF_SIZE /* 0 = 2kb, 1 = 4kb */
-#define ETH16I_TX_BUF_SIZE 2 /* 2 = 8kb, 3 = 16kb */
+#define ETH16I_TX_BUF_SIZE 3 /* 2 = 8kb, 3 = 16kb */
#endif
-#define TX_BUF_1x2048 0
-#define TX_BUF_2x2048 1
-#define TX_BUF_2x4098 2
-#define TX_BUF_2x8192 3
+#define TX_BUF_1x2048 0
+#define TX_BUF_2x2048 1
+#define TX_BUF_2x4098 2
+#define TX_BUF_2x8192 3
/* Configuration Register 1 (DLCR7) */
#define CONFIG_REG_1 7
#define HASH_TABLE_RB 1
/* Buffer memory ports */
-#define BUFFER_MEM_PORT_LB 8
-#define DATAPORT BUFFER_MEM_PORT_LB
-#define BUFFER_MEM_PORT_HB 9
+#define BUFFER_MEM_PORT_LB 8
+#define DATAPORT BUFFER_MEM_PORT_LB
+#define BUFFER_MEM_PORT_HB 9
/* 16 Collision control register (BMPR11) */
#define COL_16_REG 11
#define HALT_ON_16 0x00
#define RETRANS_AND_HALT_ON_16 0x02
+/* Maximum number of attempts to send after 16 concecutive collisions */
+#define MAX_COL_16 10
+
/* DMA Burst and Transceiver Mode Register (BMPR13) */
#define TRANSCEIVER_MODE_REG 13
#define TRANSCEIVER_MODE_RB 2
/* Filter Self Receive Register (BMPR14) */
#define FILTER_SELF_RX_REG 14
-#define SKIP_RECEIVE_PACKET BIT(2)
+#define SKIP_RX_PACKET BIT(2)
#define FILTER_SELF_RECEIVE BIT(0)
-#define RX_BUF_SKIP_PACKET SKIP_RECEIVE_PACKET | FILTER_SELF_RECEIVE
/* EEPROM Control Register (BMPR 16) */
#define EEPROM_CTRL_REG 16
#define EEPROM_READ 0x80
/* NMC93CSx6 EEPROM Addresses */
-#define E_NODEID_0 0x02
-#define E_NODEID_1 0x03
-#define E_NODEID_2 0x04
-#define E_PORT_SELECT 0x14
- #define E_PORT_BNC 0
- #define E_PORT_DIX 1
- #define E_PORT_TP 2
- #define E_PORT_AUTO 3
-#define E_PRODUCT_CFG 0x30
+#define E_NODEID_0 0x02
+#define E_NODEID_1 0x03
+#define E_NODEID_2 0x04
+#define E_PORT_SELECT 0x14
+ #define E_PORT_BNC 0x00
+ #define E_PORT_DIX 0x01
+ #define E_PORT_TP 0x02
+ #define E_PORT_AUTO 0x03
+ #define E_PORT_FROM_EPROM 0x04
+#define E_PRODUCT_CFG 0x30
/* Macro to slow down io between EEPROM clock transitions */
-#define eeprom_slow_io() do { int _i = 40; while(--_i > 0) { __SLOW_DOWN_IO; }}while(0)
+#define eeprom_slow_io() do { int _i = 40; while(--_i > 0) { inb(0x80); }}while(0)
/* Jumperless Configuration Register (BMPR19) */
#define JUMPERLESS_CONFIG 19
0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0 };
/* This is the Interrupt lookup table for Eth16i card */
-static unsigned int eth16i_irqmap[] = { 9, 10, 5, 15 };
+static unsigned int eth16i_irqmap[] = { 9, 10, 5, 15, 0 };
+#define NUM_OF_ISA_IRQS 4
/* This is the Interrupt lookup table for Eth32i card */
-static unsigned int eth32i_irqmap[] = { 3, 5, 7, 9, 10, 11, 12, 15 };
+static unsigned int eth32i_irqmap[] = { 3, 5, 7, 9, 10, 11, 12, 15, 0 };
#define EISA_IRQ_REG 0xc89
+#define NUM_OF_EISA_IRQS 8
static unsigned int eth16i_tx_buf_map[] = { 2048, 2048, 4096, 8192 };
-unsigned int boot = 1;
+static unsigned int boot = 1;
/* Use 0 for production, 1 for verification, >2 for debug */
#ifndef ETH16I_DEBUG
static unsigned int eth16i_debug = ETH16I_DEBUG;
/* Information for each board */
+
struct eth16i_local {
- struct enet_statistics stats;
- unsigned int tx_started:1;
- unsigned char tx_queue; /* Number of packets in transmit buffer */
- unsigned short tx_queue_len;
- unsigned int tx_buf_size;
- unsigned long open_time;
+ eth16i_stats_type stats;
+ unsigned char tx_started;
+ unsigned char tx_buf_busy;
+ unsigned short tx_queue; /* Number of packets in transmit buffer */
+ unsigned short tx_queue_len;
+ unsigned int tx_buf_size;
+ unsigned long open_time;
+ unsigned long tx_buffered_packets;
+ unsigned long col_16;
};
/* Function prototypes */
-extern int eth16i_probe(struct device *dev);
-
-static int eth16i_probe1(struct device *dev, short ioaddr);
-static int eth16i_check_signature(short ioaddr);
-static int eth16i_probe_port(short ioaddr);
-static void eth16i_set_port(short ioaddr, int porttype);
-static int eth16i_send_probe_packet(short ioaddr, unsigned char *b, int l);
-static int eth16i_receive_probe_packet(short ioaddr);
-static int eth16i_get_irq(short ioaddr);
-static int eth16i_read_eeprom(int ioaddr, int offset);
-static int eth16i_read_eeprom_word(int ioaddr);
-static void eth16i_eeprom_cmd(int ioaddr, unsigned char command);
-static int eth16i_open(struct device *dev);
-static int eth16i_close(struct device *dev);
-static int eth16i_tx(struct sk_buff *skb, struct device *dev);
-static void eth16i_rx(struct device *dev);
-static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void eth16i_multicast(struct device *dev);
-static void eth16i_select_regbank(unsigned char regbank, short ioaddr);
-static void eth16i_initialize(struct device *dev);
+extern int eth16i_probe(struct device *dev);
+
+static int eth16i_probe1(struct device *dev, int ioaddr);
+static int eth16i_check_signature(int ioaddr);
+static int eth16i_probe_port(int ioaddr);
+static void eth16i_set_port(int ioaddr, int porttype);
+static int eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l);
+static int eth16i_receive_probe_packet(int ioaddr);
+static int eth16i_get_irq(int ioaddr);
+static int eth16i_read_eeprom(int ioaddr, int offset);
+static int eth16i_read_eeprom_word(int ioaddr);
+static void eth16i_eeprom_cmd(int ioaddr, unsigned char command);
+static int eth16i_open(struct device *dev);
+static int eth16i_close(struct device *dev);
+static int eth16i_tx(struct sk_buff *skb, struct device *dev);
+static void eth16i_rx(struct device *dev);
+static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void eth16i_reset(struct device *dev);
+static void eth16i_skip_packet(struct device *dev);
+static void eth16i_multicast(struct device *dev);
+static void eth16i_select_regbank(unsigned char regbank, int ioaddr);
+static void eth16i_initialize(struct device *dev);
+
+#if 0
+static int eth16i_set_irq(struct device *dev);
+#endif
+
+#ifdef MODULE
+static ushort eth16i_parse_mediatype(const char* s);
+#endif
+
static struct enet_statistics *eth16i_get_stats(struct device *dev);
static char *cardname = "ICL EtherTeam 16i/32";
#ifdef HAVE_DEVLIST
+
/* Support for alternate probe manager */
/struct netdev_entry eth16i_drv =
- {"eth16i", eth16i_probe1, ETH16I_IO_EXTENT, eth16i_probe_list};
+ {"eth16i", eth16i_probe1, ETH16I_IO_EXTENT, eth16i_probe_list};
#else /* Not HAVE_DEVLIST */
-int eth16i_probe(struct device *dev)
+
+__initfunc(int eth16i_probe(struct device *dev))
{
- int i;
- int ioaddr;
- int base_addr = dev ? dev->base_addr : 0;
-
- if(eth16i_debug > 4)
- printk("Probing started for %s\n", cardname);
-
- if(base_addr > 0x1ff) /* Check only single location */
- return eth16i_probe1(dev, base_addr);
- else if(base_addr != 0) /* Don't probe at all */
- return ENXIO;
-
- /* Seek card from the ISA io address space */
- for(i = 0; (ioaddr = eth16i_portlist[i]) ; i++) {
- if(check_region(ioaddr, ETH16I_IO_EXTENT))
- continue;
- if(eth16i_probe1(dev, ioaddr) == 0)
- return 0;
- }
-
- /* Seek card from the EISA io address space */
- for(i = 0; (ioaddr = eth32i_portlist[i]) ; i++) {
- if(check_region(ioaddr, ETH16I_IO_EXTENT))
- continue;
- if(eth16i_probe1(dev, ioaddr) == 0)
- return 0;
- }
+ int i;
+ int ioaddr;
+ int base_addr = dev ? dev->base_addr : 0;
+
+ if(eth16i_debug > 4)
+ printk(KERN_DEBUG "Probing started for %s\n", cardname);
+
+ if(base_addr > 0x1ff) /* Check only single location */
+ return eth16i_probe1(dev, base_addr);
+ else if(base_addr != 0) /* Don't probe at all */
+ return ENXIO;
+
+ /* Seek card from the ISA io address space */
+ for(i = 0; (ioaddr = eth16i_portlist[i]) ; i++) {
+ if(check_region(ioaddr, ETH16I_IO_EXTENT))
+ continue;
+ if(eth16i_probe1(dev, ioaddr) == 0)
+ return 0;
+ }
- return ENODEV;
+ /* Seek card from the EISA io address space */
+ for(i = 0; (ioaddr = eth32i_portlist[i]) ; i++) {
+ if(check_region(ioaddr, ETH16I_IO_EXTENT))
+ continue;
+ if(eth16i_probe1(dev, ioaddr) == 0)
+ return 0;
+ }
+
+ return ENODEV;
}
#endif /* Not HAVE_DEVLIST */
-static int eth16i_probe1(struct device *dev, short ioaddr)
+__initfunc(static int eth16i_probe1(struct device *dev, int ioaddr))
{
- static unsigned version_printed = 0;
- unsigned int irq = 0;
- boot = 1; /* To inform initialization that we are in boot probe */
-
- /*
- The MB86985 chip has on register which holds information in which
- io address the chip lies. First read this register and compare
- it to our current io address and if match then this could
- be our chip.
- */
-
- if(ioaddr < 0x1000) {
- if(eth16i_portlist[(inb(ioaddr + JUMPERLESS_CONFIG) & 0x07)] != ioaddr)
- return -ENODEV;
- }
+ static unsigned version_printed = 0;
+ boot = 1; /* To inform initilization that we are in boot probe */
- /* Now we will go a bit deeper and try to find the chip's signature */
+ /*
+ The MB86985 chip has on register which holds information in which
+ io address the chip lies. First read this register and compare
+ it to our current io address and if match then this could
+ be our chip.
+ */
- if(eth16i_check_signature(ioaddr) != 0) /* Can we find the signature here */
- return -ENODEV;
-
- /*
- Now it seems that we have found a ethernet chip in this particular
- ioaddr. The MB86985 chip has this feature, that when you read a
- certain register it will increase its io base address to next
- configurable slot. Now when we have found the chip, first thing is
- to make sure that the chip's ioaddr will hold still here.
- */
-
- eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
- outb(0x00, ioaddr + TRANSCEIVER_MODE_REG);
-
- outb(0x00, ioaddr + RESET); /* Will reset some parts of chip */
- BITSET(ioaddr + CONFIG_REG_0, BIT(7)); /* This will disable the data link */
-
- if(dev == NULL)
- dev = init_etherdev(0, sizeof(struct eth16i_local));
+ if(ioaddr < 0x1000) {
+
+ if(eth16i_portlist[(inb(ioaddr + JUMPERLESS_CONFIG) & 0x07)]
+ != ioaddr)
+ return -ENODEV;
+ }
- if( (eth16i_debug & version_printed++) == 0)
- printk(version);
+ /* Now we will go a bit deeper and try to find the chip's signature */
- dev->base_addr = ioaddr;
-
- irq = eth16i_get_irq(ioaddr);
- dev->irq = irq;
+ if(eth16i_check_signature(ioaddr) != 0)
+ return -ENODEV;
- /* Try to obtain interrupt vector */
- if(request_irq(dev->irq, ð16i_interrupt, 0, "eth16i", NULL)) {
- printk("%s: %s at %#3x, but is unusable due
- conflict on IRQ %d.\n", dev->name, cardname, ioaddr, irq);
- return EAGAIN;
- }
+ /*
+ Now it seems that we have found a ethernet chip in this particular
+ ioaddr. The MB86985 chip has this feature, that when you read a
+ certain register it will increase it's io base address to next
+ configurable slot. Now when we have found the chip, first thing is
+ to make sure that the chip's ioaddr will hold still here.
+ */
- printk("%s: %s at %#3x, IRQ %d, ",
- dev->name, cardname, ioaddr, dev->irq);
+ eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
+ outb(0x00, ioaddr + TRANSCEIVER_MODE_REG);
- /* Let's grab the region */
- request_region(ioaddr, ETH16I_IO_EXTENT, "eth16i");
+ outb(0x00, ioaddr + RESET); /* Reset some parts of chip */
+ BITSET(ioaddr + CONFIG_REG_0, BIT(7)); /* Disable the data link */
- /* Now we will have to lock the chip's io address */
- eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
- outb(0x38, ioaddr + TRANSCEIVER_MODE_REG);
+ if(dev == NULL)
+ dev = init_etherdev(0, 0);
- eth16i_initialize(dev); /* Initialize rest of the chip's registers */
-
- /* Now let's same some energy by shutting down the chip ;) */
- BITCLR(ioaddr + CONFIG_REG_1, POWERUP);
-
- /* Initialize the device structure */
- if(dev->priv == NULL)
- dev->priv = kmalloc(sizeof(struct eth16i_local), GFP_KERNEL);
- memset(dev->priv, 0, sizeof(struct eth16i_local));
+ if( (eth16i_debug & version_printed++) == 0)
+ printk(KERN_INFO "%s", version);
+
+ dev->base_addr = ioaddr;
+
+#if 0
+ if(dev->irq) {
+ if(eth16i_set_irq(dev)) {
+ dev->irq = eth16i_get_irq(ioaddr);
+ }
+
+ }
+ else {
+#endif
+
+ dev->irq = eth16i_get_irq(ioaddr);
+
+ /* Try to obtain interrupt vector */
+
+ if (request_irq(dev->irq, (void *)ð16i_interrupt, 0, "eth16i", dev)) {
+ printk(KERN_WARNING "%s: %s at %#3x, but is unusable due conflicting IRQ %d.\n",
+ dev->name, cardname, ioaddr, dev->irq);
+ return -EAGAIN;
+ }
+
+#if 0
+ irq2dev_map[dev->irq] = dev;
+#endif
+
+ printk(KERN_INFO "%s: %s at %#3x, IRQ %d, ",
+ dev->name, cardname, ioaddr, dev->irq);
+
+ /* Let's grab the region */
+ request_region(ioaddr, ETH16I_IO_EXTENT, "eth16i");
+
+ /* Now we will have to lock the chip's io address */
+ eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
+ outb(0x38, ioaddr + TRANSCEIVER_MODE_REG);
+
+ eth16i_initialize(dev); /* Initialize rest of the chip's registers */
+
+ /* Now let's same some energy by shutting down the chip ;) */
+ BITCLR(ioaddr + CONFIG_REG_1, POWERUP);
- dev->open = eth16i_open;
- dev->stop = eth16i_close;
- dev->hard_start_xmit = eth16i_tx;
- dev->get_stats = eth16i_get_stats;
- dev->set_multicast_list = eth16i_multicast;
+ /* Initialize the device structure */
+ if(dev->priv == NULL) {
+ dev->priv = kmalloc(sizeof(struct eth16i_local), GFP_KERNEL);
+ if(dev->priv == NULL)
+ return -ENOMEM;
+ }
+
+ memset(dev->priv, 0, sizeof(struct eth16i_local));
+
+ dev->open = eth16i_open;
+ dev->stop = eth16i_close;
+ dev->hard_start_xmit = eth16i_tx;
+ dev->get_stats = eth16i_get_stats;
+ dev->set_multicast_list = ð16i_multicast;
- /* Fill in the fields of the device structure with ethernet values. */
- ether_setup(dev);
+ /* Fill in the fields of the device structure with ethernet values. */
+ ether_setup(dev);
- boot = 0;
+ boot = 0;
- return 0;
+ return 0;
}
static void eth16i_initialize(struct device *dev)
{
- short ioaddr = dev->base_addr;
- int i, node_w = 0;
- unsigned char node_byte = 0;
-
- /* Setup station address */
- eth16i_select_regbank(NODE_ID_RB, ioaddr);
- for(i = 0 ; i < 3 ; i++) {
- unsigned short node_val = eth16i_read_eeprom(ioaddr, E_NODEID_0 + i);
- ((unsigned short *)dev->dev_addr)[i] = ntohs(node_val);
- }
-
- for(i = 0; i < 6; i++) {
- outb( ((unsigned char *)dev->dev_addr)[i], ioaddr + NODE_ID_0 + i);
- if(boot) {
- printk("%02x", inb(ioaddr + NODE_ID_0 + i));
- if(i != 5)
- printk(":");
- }
- }
-
- /* Now we will set multicast addresses to accept none */
- eth16i_select_regbank(HASH_TABLE_RB, ioaddr);
- for(i = 0; i < 8; i++)
- outb(0x00, ioaddr + HASH_TABLE_0 + i);
-
- /*
- Now let's disable the transmitter and receiver, set the buffer ram
- cycle time, bus width and buffer data path width. Also we shall
- set transmit buffer size and total buffer size.
- */
-
- eth16i_select_regbank(2, ioaddr);
-
- node_byte = 0;
- node_w = eth16i_read_eeprom(ioaddr, E_PRODUCT_CFG);
-
- if( (node_w & 0xFF00) == 0x0800)
- node_byte |= BUFFER_WIDTH_8;
-
- node_byte |= _BS1;
-
- if( (node_w & 0x00FF) == 64)
- node_byte |= _BS0;
-
- node_byte |= DLC_EN | SRAM_CYCLE_TIME_100NS | (ETH16I_TX_BUF_SIZE << 2);
+ int ioaddr = dev->base_addr;
+ int i, node_w = 0;
+ unsigned char node_byte = 0;
+
+ /* Setup station address */
+ eth16i_select_regbank(NODE_ID_RB, ioaddr);
+ for(i = 0 ; i < 3 ; i++) {
+ unsigned short node_val = eth16i_read_eeprom(ioaddr, E_NODEID_0 + i);
+ ((unsigned short *)dev->dev_addr)[i] = ntohs(node_val);
+ }
- outb(node_byte, ioaddr + CONFIG_REG_0);
+ for(i = 0; i < 6; i++) {
+ outb( ((unsigned char *)dev->dev_addr)[i], ioaddr + NODE_ID_0 + i);
+ if(boot) {
+ printk("%02x", inb(ioaddr + NODE_ID_0 + i));
+ if(i != 5)
+ printk(":");
+ }
+ }
- /* We shall halt the transmitting, if 16 collisions are detected */
- outb(RETRANS_AND_HALT_ON_16, ioaddr + COL_16_REG);
+ /* Now we will set multicast addresses to accept none */
+ eth16i_select_regbank(HASH_TABLE_RB, ioaddr);
+ for(i = 0; i < 8; i++)
+ outb(0x00, ioaddr + HASH_TABLE_0 + i);
- if(boot) /* Now set port type */
- {
- char *porttype[] = {"BNC", "DIX", "TP", "AUTO"};
-
- ushort ptype = eth16i_read_eeprom(ioaddr, E_PORT_SELECT);
- dev->if_port = (ptype & 0x00FF);
-
- printk(" %s interface.\n", porttype[dev->if_port]);
+ /*
+ Now let's disable the transmitter and receiver, set the buffer ram
+ cycle time, bus width and buffer data path width. Also we shall
+ set transmit buffer size and total buffer size.
+ */
- if(ptype == E_PORT_AUTO)
- ptype = eth16i_probe_port(ioaddr);
-
- eth16i_set_port(ioaddr, ptype);
- }
+ eth16i_select_regbank(2, ioaddr);
+
+ node_byte = 0;
+ node_w = eth16i_read_eeprom(ioaddr, E_PRODUCT_CFG);
+
+ if( (node_w & 0xFF00) == 0x0800)
+ node_byte |= BUFFER_WIDTH_8;
+
+ node_byte |= SRAM_BS1;
+
+ if( (node_w & 0x00FF) == 64)
+ node_byte |= SRAM_BS0;
+
+ node_byte |= DLC_EN | SRAM_CYCLE_TIME_100NS | (ETH16I_TX_BUF_SIZE << 2);
+
+ outb(node_byte, ioaddr + CONFIG_REG_0);
+
+ /* We shall halt the transmitting, if 16 collisions are detected */
+ outb(HALT_ON_16, ioaddr + COL_16_REG);
+
+#ifdef MODULE
+ /* if_port already set by init_module() */
+#else
+ dev->if_port = (dev->mem_start < E_PORT_FROM_EPROM) ?
+ dev->mem_start : E_PORT_FROM_EPROM;
+#endif
+
+ /* Set interface port type */
+ if(boot) {
+ char *porttype[] = {"BNC", "DIX", "TP", "AUTO", "FROM_EPROM" };
+
+ switch(dev->if_port)
+ {
+
+ case E_PORT_FROM_EPROM:
+ dev->if_port = eth16i_read_eeprom(ioaddr, E_PORT_SELECT);
+ break;
+
+ case E_PORT_AUTO:
+ dev->if_port = eth16i_probe_port(ioaddr);
+ break;
+
+ case E_PORT_BNC:
+ case E_PORT_TP:
+ case E_PORT_DIX:
+ break;
+ }
+
+ printk(" %s interface.\n", porttype[dev->if_port]);
+
+ eth16i_set_port(ioaddr, dev->if_port);
+ }
- /* Set Receive Mode to normal operation */
- outb(MODE_2, ioaddr + RECEIVE_MODE_REG);
+ /* Set Receive Mode to normal operation */
+ outb(MODE_2, ioaddr + RECEIVE_MODE_REG);
}
-static int eth16i_probe_port(short ioaddr)
+static int eth16i_probe_port(int ioaddr)
{
- int i;
- int retcode;
- unsigned char dummy_packet[64] = { 0 };
+ int i;
+ int retcode;
+ unsigned char dummy_packet[64] = { 0 };
- /* Powerup the chip */
- outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
+ /* Powerup the chip */
+ outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
- BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
+ BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
- eth16i_select_regbank(NODE_ID_RB, ioaddr);
+ eth16i_select_regbank(NODE_ID_RB, ioaddr);
- for(i = 0; i < 6; i++) {
- dummy_packet[i] = inb(ioaddr + NODE_ID_0 + i);
- dummy_packet[i+6] = inb(ioaddr + NODE_ID_0 + i);
- }
+ for(i = 0; i < 6; i++) {
+ dummy_packet[i] = inb(ioaddr + NODE_ID_0 + i);
+ dummy_packet[i+6] = inb(ioaddr + NODE_ID_0 + i);
+ }
- dummy_packet[12] = 0x00;
- dummy_packet[13] = 0x04;
+ dummy_packet[12] = 0x00;
+ dummy_packet[13] = 0x04;
+
+ eth16i_select_regbank(2, ioaddr);
+
+ for(i = 0; i < 3; i++) {
+ BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
+ BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
+ eth16i_set_port(ioaddr, i);
+
+ if(eth16i_debug > 1)
+ printk(KERN_DEBUG "Set port number %d\n", i);
+
+ retcode = eth16i_send_probe_packet(ioaddr, dummy_packet, 64);
+ if(retcode == 0) {
+ retcode = eth16i_receive_probe_packet(ioaddr);
+ if(retcode != -1) {
+ if(eth16i_debug > 1)
+ printk(KERN_DEBUG "Eth16i interface port found at %d\n", i);
+ return i;
+ }
+ }
+ else {
+ if(eth16i_debug > 1)
+ printk(KERN_DEBUG "TRANSMIT_DONE timeout when probing interface port\n");
+ }
+ }
- eth16i_select_regbank(2, ioaddr);
+ if( eth16i_debug > 1)
+ printk(KERN_DEBUG "Using default port\n");
- for(i = 0; i < 3; i++) {
- BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
- BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
- eth16i_set_port(ioaddr, i);
-
- if(eth16i_debug > 1)
- printk("Set port number %d\n", i);
-
- retcode = eth16i_send_probe_packet(ioaddr, dummy_packet, 64);
- if(retcode == 0) {
- retcode = eth16i_receive_probe_packet(ioaddr);
- if(retcode != -1) {
- if(eth16i_debug > 1)
- printk("Eth16i interface port found at %d\n", i);
- return i;
- }
- }
- else {
- if(eth16i_debug > 1)
- printk("TRANSMIT_DONE timeout\n");
- }
- }
-
- if( eth16i_debug > 1)
- printk("Using default port\n");
-
- return E_PORT_BNC;
+ return E_PORT_BNC;
}
-static void eth16i_set_port(short ioaddr, int porttype)
+static void eth16i_set_port(int ioaddr, int porttype)
{
- unsigned short temp = 0;
+ unsigned short temp = 0;
- eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
- outb(LOOPBACK_CONTROL, ioaddr + TRANSMIT_MODE_REG);
+ eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
+ outb(LOOPBACK_CONTROL, ioaddr + TRANSMIT_MODE_REG);
- temp |= DIS_AUTO_PORT_SEL;
+ temp |= DIS_AUTO_PORT_SEL;
- switch(porttype) {
+ switch(porttype) {
- case E_PORT_BNC :
- temp |= AUI_SELECT;
- break;
+ case E_PORT_BNC :
+ temp |= AUI_SELECT;
+ break;
- case E_PORT_TP :
- break;
-
- case E_PORT_DIX :
- temp |= AUI_SELECT;
- BITSET(ioaddr + TRANSMIT_MODE_REG, CONTROL_OUTPUT);
- break;
- }
- outb(temp, ioaddr + TRANSCEIVER_MODE_REG);
-
- if(eth16i_debug > 1) {
- printk("TRANSMIT_MODE_REG = %x\n", inb(ioaddr + TRANSMIT_MODE_REG));
- printk("TRANSCEIVER_MODE_REG = %x\n", inb(ioaddr+TRANSCEIVER_MODE_REG));
- }
+ case E_PORT_TP :
+ break;
+
+ case E_PORT_DIX :
+ temp |= AUI_SELECT;
+ BITSET(ioaddr + TRANSMIT_MODE_REG, CONTROL_OUTPUT);
+ break;
+ }
+
+ outb(temp, ioaddr + TRANSCEIVER_MODE_REG);
+
+ if(eth16i_debug > 1) {
+ printk(KERN_DEBUG "TRANSMIT_MODE_REG = %x\n", inb(ioaddr + TRANSMIT_MODE_REG));
+ printk(KERN_DEBUG "TRANSCEIVER_MODE_REG = %x\n",
+ inb(ioaddr+TRANSCEIVER_MODE_REG));
+ }
}
-static int eth16i_send_probe_packet(short ioaddr, unsigned char *b, int l)
+static int eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l)
{
- int starttime;
+ int starttime;
- outb(0xff, ioaddr + TX_STATUS_REG);
+ outb(0xff, ioaddr + TX_STATUS_REG);
- outw(l, ioaddr + DATAPORT);
- outsw(ioaddr + DATAPORT, (unsigned short *)b, (l + 1) >> 1);
-
- starttime = jiffies;
- outb(TX_START | 1, ioaddr + TRANSMIT_START_REG);
-
- while( (inb(ioaddr + TX_STATUS_REG) & 0x80) == 0) {
- if( (jiffies - starttime) > TIMEOUT_TICKS) {
- break;
- }
- }
-
- return(0);
+ outw(l, ioaddr + DATAPORT);
+ outsw(ioaddr + DATAPORT, (unsigned short *)b, (l + 1) >> 1);
+
+ starttime = jiffies;
+ outb(TX_START | 1, ioaddr + TRANSMIT_START_REG);
+
+ while( (inb(ioaddr + TX_STATUS_REG) & 0x80) == 0) {
+ if( (jiffies - starttime) > TX_TIMEOUT) {
+ return -1;
+ }
+ }
+
+ return 0;
}
-static int eth16i_receive_probe_packet(short ioaddr)
+static int eth16i_receive_probe_packet(int ioaddr)
{
- int starttime;
-
- starttime = jiffies;
-
- while((inb(ioaddr + TX_STATUS_REG) & 0x20) == 0) {
- if( (jiffies - starttime) > TIMEOUT_TICKS) {
-
- if(eth16i_debug > 1)
- printk("Timeout occurred waiting transmit packet received\n");
- starttime = jiffies;
- while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0) {
- if( (jiffies - starttime) > TIMEOUT_TICKS) {
- if(eth16i_debug > 1)
- printk("Timeout occurred waiting receive packet\n");
- return -1;
- }
- }
-
- if(eth16i_debug > 1)
- printk("RECEIVE_PACKET\n");
- return(0); /* Found receive packet */
- }
- }
-
- if(eth16i_debug > 1) {
- printk("TRANSMIT_PACKET_RECEIVED %x\n", inb(ioaddr + TX_STATUS_REG));
- printk("RX_STATUS_REG = %x\n", inb(ioaddr + RX_STATUS_REG));
- }
-
- return(0); /* Return success */
+ int starttime;
+
+ starttime = jiffies;
+
+ while((inb(ioaddr + TX_STATUS_REG) & 0x20) == 0) {
+ if( (jiffies - starttime) > TX_TIMEOUT) {
+
+ if(eth16i_debug > 1)
+ printk(KERN_DEBUG "Timeout occured waiting transmit packet received\n");
+ starttime = jiffies;
+ while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0) {
+ if( (jiffies - starttime) > TX_TIMEOUT) {
+ if(eth16i_debug > 1)
+ printk(KERN_DEBUG "Timeout occured waiting receive packet\n");
+ return -1;
+ }
+ }
+
+ if(eth16i_debug > 1)
+ printk(KERN_DEBUG "RECEIVE_PACKET\n");
+ return(0); /* Found receive packet */
+ }
+ }
+
+ if(eth16i_debug > 1) {
+ printk(KERN_DEBUG "TRANSMIT_PACKET_RECEIVED %x\n", inb(ioaddr + TX_STATUS_REG));
+ printk(KERN_DEBUG "RX_STATUS_REG = %x\n", inb(ioaddr + RX_STATUS_REG));
+ }
+
+ return(0); /* Return success */
}
-static int eth16i_get_irq(short ioaddr)
+#if 0
+static int eth16i_set_irq(struct device* dev)
{
- unsigned char cbyte;
-
- if( ioaddr < 0x1000) {
- cbyte = inb(ioaddr + JUMPERLESS_CONFIG);
- return( eth16i_irqmap[ ((cbyte & 0xC0) >> 6) ] );
- } else { /* Oh..the card is EISA so method getting IRQ different */
- unsigned short index = 0;
- cbyte = inb(ioaddr + EISA_IRQ_REG);
- while( (cbyte & 0x01) == 0) {
- cbyte = cbyte >> 1;
- index++;
- }
- return( eth32i_irqmap[ index ] );
- }
+ const int ioaddr = dev->base_addr;
+ const int irq = dev->irq;
+ int i = 0;
+
+ if(ioaddr < 0x1000) {
+ while(eth16i_irqmap[i] && eth16i_irqmap[i] != irq)
+ i++;
+
+ if(i < NUM_OF_ISA_IRQS) {
+ u8 cbyte = inb(ioaddr + JUMPERLESS_CONFIG);
+ cbyte = (cbyte & 0x3F) | (i << 6);
+ outb(cbyte, ioaddr + JUMPERLESS_CONFIG);
+ return 0;
+ }
+ }
+ else {
+ printk(KERN_NOTICE "%s: EISA Interrupt cannot be set. Use EISA Configuration utility.\n", dev->name);
+ }
+
+ return -1;
+
}
+#endif
-static int eth16i_check_signature(short ioaddr)
+static int eth16i_get_irq(int ioaddr)
{
- int i;
- unsigned char creg[4] = { 0 };
-
- for(i = 0; i < 4 ; i++) {
+ unsigned char cbyte;
+
+ if( ioaddr < 0x1000) {
+ cbyte = inb(ioaddr + JUMPERLESS_CONFIG);
+ return( eth16i_irqmap[ ((cbyte & 0xC0) >> 6) ] );
+ } else { /* Oh..the card is EISA so method getting IRQ different */
+ unsigned short index = 0;
+ cbyte = inb(ioaddr + EISA_IRQ_REG);
+ while( (cbyte & 0x01) == 0) {
+ cbyte = cbyte >> 1;
+ index++;
+ }
+ return( eth32i_irqmap[ index ] );
+ }
+}
- creg[i] = inb(ioaddr + TRANSMIT_MODE_REG + i);
-
- if(eth16i_debug > 1)
- printk("eth16i: read signature byte %x at %x\n", creg[i],
- ioaddr + TRANSMIT_MODE_REG + i);
- }
+static int eth16i_check_signature(int ioaddr)
+{
+ int i;
+ unsigned char creg[4] = { 0 };
- creg[0] &= 0x0F; /* Mask collision cnr */
- creg[2] &= 0x7F; /* Mask DCLEN bit */
+ for(i = 0; i < 4 ; i++) {
-#if 0
-/*
- This was removed because the card was sometimes left to state
- from which it couldn't be find anymore. If there is need
- to more strict chech still this have to be fixed.
-*/
- if( !( (creg[0] == 0x06) && (creg[1] == 0x41)) ) {
- if(creg[1] != 0x42)
- return -1;
- }
-#endif
+ creg[i] = inb(ioaddr + TRANSMIT_MODE_REG + i);
- if( !( (creg[2] == 0x36) && (creg[3] == 0xE0)) ) {
- creg[2] &= 0x40;
- creg[3] &= 0x03;
+ if(eth16i_debug > 1)
+ printk("eth16i: read signature byte %x at %x\n",
+ creg[i],
+ ioaddr + TRANSMIT_MODE_REG + i);
+ }
- if( !( (creg[2] == 0x40) && (creg[3] == 0x00)) )
- return -1;
- }
+ creg[0] &= 0x0F; /* Mask collision cnr */
+ creg[2] &= 0x7F; /* Mask DCLEN bit */
- if(eth16i_read_eeprom(ioaddr, E_NODEID_0) != 0)
- return -1;
- if((eth16i_read_eeprom(ioaddr, E_NODEID_1) & 0xFF00) != 0x4B00)
- return -1;
+#ifdef 0
+ /*
+ This was removed because the card was sometimes left to state
+ from which it couldn't be find anymore. If there is need
+ to more strict check still this have to be fixed.
+ */
+ if( ! ((creg[0] == 0x06) && (creg[1] == 0x41)) ) {
+ if(creg[1] != 0x42)
+ return -1;
+ }
+#endif
+
+ if( !((creg[2] == 0x36) && (creg[3] == 0xE0)) ) {
+ creg[2] &= 0x40;
+ creg[3] &= 0x03;
+
+ if( !((creg[2] == 0x40) && (creg[3] == 0x00)) )
+ return -1;
+ }
+
+ if(eth16i_read_eeprom(ioaddr, E_NODEID_0) != 0)
+ return -1;
+
+ if((eth16i_read_eeprom(ioaddr, E_NODEID_1) & 0xFF00) != 0x4B00)
+ return -1;
- return 0;
+ return 0;
}
static int eth16i_read_eeprom(int ioaddr, int offset)
{
- int data = 0;
+ int data = 0;
- eth16i_eeprom_cmd(ioaddr, EEPROM_READ | offset);
- outb(CS_1, ioaddr + EEPROM_CTRL_REG);
- data = eth16i_read_eeprom_word(ioaddr);
- outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
+ eth16i_eeprom_cmd(ioaddr, EEPROM_READ | offset);
+ outb(CS_1, ioaddr + EEPROM_CTRL_REG);
+ data = eth16i_read_eeprom_word(ioaddr);
+ outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
- return(data);
+ return(data);
}
static int eth16i_read_eeprom_word(int ioaddr)
{
- int i;
- int data = 0;
-
- for(i = 16; i > 0; i--) {
- outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
- eeprom_slow_io();
- outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
- eeprom_slow_io();
- data = (data << 1) | ((inb(ioaddr + EEPROM_DATA_REG) & DI_1) ? 1 : 0);
- eeprom_slow_io();
- }
-
- return(data);
+ int i;
+ int data = 0;
+
+ for(i = 16; i > 0; i--) {
+ outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
+ eeprom_slow_io();
+ outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
+ eeprom_slow_io();
+ data = (data << 1) |
+ ((inb(ioaddr + EEPROM_DATA_REG) & DI_1) ? 1 : 0);
+
+ eeprom_slow_io();
+ }
+
+ return(data);
}
static void eth16i_eeprom_cmd(int ioaddr, unsigned char command)
{
- int i;
-
- outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
- outb(DI_0, ioaddr + EEPROM_DATA_REG);
- outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
- outb(DI_1, ioaddr + EEPROM_DATA_REG);
- outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
-
- for(i = 7; i >= 0; i--) {
- short cmd = ( (command & (1 << i)) ? DI_1 : DI_0 );
- outb(cmd, ioaddr + EEPROM_DATA_REG);
- outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
- eeprom_slow_io();
- outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
- eeprom_slow_io();
- }
+ int i;
+
+ outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
+ outb(DI_0, ioaddr + EEPROM_DATA_REG);
+ outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
+ outb(DI_1, ioaddr + EEPROM_DATA_REG);
+ outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
+
+ for(i = 7; i >= 0; i--) {
+ short cmd = ( (command & (1 << i)) ? DI_1 : DI_0 );
+ outb(cmd, ioaddr + EEPROM_DATA_REG);
+ outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
+ eeprom_slow_io();
+ outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
+ eeprom_slow_io();
+ }
}
static int eth16i_open(struct device *dev)
{
- struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
- int ioaddr = dev->base_addr;
-
- irq2dev_map[dev->irq] = dev;
+ struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+
+ /* Powerup the chip */
+ outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
- /* Powerup the chip */
- outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
-
- /* Initialize the chip */
- eth16i_initialize(dev);
-
- /* Set the transmit buffer size */
- lp->tx_buf_size = eth16i_tx_buf_map[ETH16I_TX_BUF_SIZE & 0x03];
-
- if(eth16i_debug > 3)
- printk("%s: transmit buffer size %d\n", dev->name, lp->tx_buf_size);
+ /* Initialize the chip */
+ eth16i_initialize(dev);
- /* Now enable Transmitter and Receiver sections */
- BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
-
- /* Now switch to register bank 2, for run time operation */
- eth16i_select_regbank(2, ioaddr);
+ /* Set the transmit buffer size */
+ lp->tx_buf_size = eth16i_tx_buf_map[ETH16I_TX_BUF_SIZE & 0x03];
- lp->open_time = jiffies;
- lp->tx_started = 0;
- lp->tx_queue = 0;
- lp->tx_queue_len = 0;
+ if(eth16i_debug > 0)
+ printk(KERN_DEBUG "%s: transmit buffer size %d\n",
+ dev->name, lp->tx_buf_size);
- /* Turn on interrupts*/
- outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+ /* Now enable Transmitter and Receiver sections */
+ BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ /* Now switch to register bank 2, for run time operation */
+ eth16i_select_regbank(2, ioaddr);
-#ifdef MODULE
- MOD_INC_USE_COUNT;
-#endif
+ lp->open_time = jiffies;
+ lp->tx_started = 0;
+ lp->tx_queue = 0;
+ lp->tx_queue_len = 0;
+
+ /* Turn on interrupts*/
+ outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+
+ MOD_INC_USE_COUNT;
- return 0;
+ return 0;
}
static int eth16i_close(struct device *dev)
{
- struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
- int ioaddr = dev->base_addr;
+ struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+ int ioaddr = dev->base_addr;
- lp->open_time = 0;
+ eth16i_reset(dev);
- dev->tbusy = 1;
- dev->start = 0;
+ /* Turn off interrupts*/
+ outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
- /* Disable transmit and receive */
- BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
+ dev->start = 0;
+ dev->tbusy = 1;
- /* Reset the chip */
- outb(0xff, ioaddr + RESET);
+ lp->open_time = 0;
- /* Save some energy by switching off power */
- BITCLR(ioaddr + CONFIG_REG_1, POWERUP);
+ /* Disable transmit and receive */
+ BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
-#ifdef MODULE
- MOD_DEC_USE_COUNT;
-#endif
+ /* Reset the chip */
+ /* outb(0xff, ioaddr + RESET); */
+ /* outw(0xffff, ioaddr + TX_STATUS_REG); */
+
+ outb(0x00, ioaddr + CONFIG_REG_1);
+
+ MOD_DEC_USE_COUNT;
- return 0;
+ return 0;
}
static int eth16i_tx(struct sk_buff *skb, struct device *dev)
{
- struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
- int ioaddr = dev->base_addr;
-
- if(dev->tbusy) {
- /*
- If we get here, some higher level has decided that we are broken.
- There should really be a "kick me" function call instead.
- */
-
- int tickssofar = jiffies - dev->trans_start;
- if(tickssofar < TIMEOUT_TICKS) /* Let's not rush with our timeout, */
- return 1; /* wait a couple of ticks first */
+ struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+ int status = 0;
- printk("%s: transmit timed out with status %04x, %s ?\n", dev->name,
- inw(ioaddr + TX_STATUS_REG),
- (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ?
- "IRQ conflict" : "network cable problem");
+ if(dev->tbusy) {
+
+ /*
+ If we get here, some higher level has decided that
+ we are broken. There should really be a "kick me"
+ function call instead.
+ */
- /* Let's dump all registers */
- if(eth16i_debug > 0) {
- printk("%s: timeout regs: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
- dev->name, inb(ioaddr + 0), inb(ioaddr + 1), inb(ioaddr + 2),
- inb(ioaddr + 3), inb(ioaddr + 4), inb(ioaddr + 5),
- inb(ioaddr + 6), inb(ioaddr + 7));
+ int tickssofar = jiffies - dev->trans_start;
+ if(tickssofar < TX_TIMEOUT)
+ return 1;
+ outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
- printk("lp->tx_queue = %d\n", lp->tx_queue);
- printk("lp->tx_queue_len = %d\n", lp->tx_queue_len);
- printk("lp->tx_started = %d\n", lp->tx_started);
+ printk(KERN_WARNING "%s: transmit timed out with status %04x, %s ?\n",
+ dev->name,
+ inw(ioaddr + TX_STATUS_REG),
+ (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ?
+ "IRQ conflict" : "network cable problem");
- }
+ dev->trans_start = jiffies;
- lp->stats.tx_errors++;
+ /* Let's dump all registers */
+ if(eth16i_debug > 0) {
+ printk(KERN_DEBUG "%s: timeout: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
+ dev->name, inb(ioaddr + 0),
+ inb(ioaddr + 1), inb(ioaddr + 2),
+ inb(ioaddr + 3), inb(ioaddr + 4),
+ inb(ioaddr + 5),
+ inb(ioaddr + 6), inb(ioaddr + 7));
- /* Now let's try to restart the adaptor */
-
- BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
- outw(0xffff, ioaddr + RESET);
- eth16i_initialize(dev);
- outw(0xffff, ioaddr + TX_STATUS_REG);
- BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
-
- lp->tx_started = 0;
- lp->tx_queue = 0;
- lp->tx_queue_len = 0;
-
- outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-
- dev->tbusy = 0;
- dev->trans_start = jiffies;
- }
-
- /*
- If some higher layer thinks we've missed an tx-done interrupt
- we are passed NULL. Caution: dev_tint() handles the cli()/sti()
- itself
- */
- if(skb == NULL) {
- dev_tint(dev);
- return 0;
- }
-
- /* Block a timer based transmitter from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-
- /* Turn off TX interrupts */
- outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
-
- if(set_bit(0, (void *)&dev->tbusy) != 0)
- printk("%s: Transmitter access conflict.\n", dev->name);
- else {
- short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- unsigned char *buf = skb->data;
-
- outw(length, ioaddr + DATAPORT);
-
- if( ioaddr < 0x1000 )
- outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
- else {
- unsigned char frag = length % 4;
+ printk(KERN_DEBUG "%s: transmit start reg: %02x. collision reg %02x\n",
+ dev->name, inb(ioaddr + TRANSMIT_START_REG),
+ inb(ioaddr + COL_16_REG));
- outsl(ioaddr + DATAPORT, buf, length >> 2);
-
- if( frag != 0 ) {
- outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC)), 1);
- if( frag == 3 )
- outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC) + 2), 1);
- }
- }
-
- lp->tx_queue++;
- lp->tx_queue_len += length + 2;
-
- if(lp->tx_started == 0) {
- /* If the transmitter is idle..always trigger a transmit */
- outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
- lp->tx_queue = 0;
- lp->tx_queue_len = 0;
- dev->trans_start = jiffies;
- lp->tx_started = 1;
- dev->tbusy = 0;
- }
- else if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
- /* There is still more room for one more packet in tx buffer */
- dev->tbusy = 0;
- }
-
- outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-
- /* Turn TX interrupts back on */
- /* outb(TX_INTR_DONE | TX_INTR_16_COL, ioaddr + TX_INTR_REG); */
- }
- dev_kfree_skb(skb, FREE_WRITE);
-
- return 0;
-}
+ printk(KERN_DEBUG "lp->tx_queue = %d\n", lp->tx_queue);
+ printk(KERN_DEBUG "lp->tx_queue_len = %d\n", lp->tx_queue_len);
+ printk(KERN_DEBUG "lp->tx_started = %d\n", lp->tx_started);
-static void eth16i_rx(struct device *dev)
-{
- struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
- int ioaddr = dev->base_addr;
- int boguscount = MAX_RX_LOOP;
+ }
- /* Loop until all packets have been read */
- while( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) {
-
- /* Read status byte from receive buffer */
- ushort status = inw(ioaddr + DATAPORT);
+ lp->stats.tx_errors++;
- if(eth16i_debug > 4)
- printk("%s: Receiving packet mode %02x status %04x.\n",
- dev->name, inb(ioaddr + RECEIVE_MODE_REG), status);
-
- if( !(status & PKT_GOOD) ) {
- /* Hmm..something went wrong. Let's check what error occurred */
- lp->stats.rx_errors++;
- if( status & PKT_SHORT ) lp->stats.rx_length_errors++;
- if( status & PKT_ALIGN_ERR ) lp->stats.rx_frame_errors++;
- if( status & PKT_CRC_ERR ) lp->stats.rx_crc_errors++;
- if( status & PKT_RX_BUF_OVERFLOW) lp->stats.rx_over_errors++;
- }
- else { /* Ok so now we should have a good packet */
- struct sk_buff *skb;
-
- /* Get the size of the packet from receive buffer */
- ushort pkt_len = inw(ioaddr + DATAPORT);
-
- if(pkt_len > ETH_FRAME_LEN) {
- printk("%s: %s claimed a very large packet, size of %d bytes.\n",
- dev->name, cardname, pkt_len);
- outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG);
- lp->stats.rx_dropped++;
- break;
- }
+ eth16i_reset(dev);
+
+ dev->trans_start = jiffies;
+
+ outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
- skb = dev_alloc_skb(pkt_len + 3);
- if( skb == NULL ) {
- printk("%s: Couldn't allocate memory for packet (len %d)\n",
- dev->name, pkt_len);
- outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG);
- lp->stats.rx_dropped++;
- break;
}
-
- skb->dev = dev;
- skb_reserve(skb,2);
+
/*
- Now let's get the packet out of buffer.
- size is (pkt_len + 1) >> 1, cause we are now reading words
- and it have to be even aligned.
- */
-
- if( ioaddr < 0x1000)
- insw(ioaddr + DATAPORT, skb_put(skb, pkt_len), (pkt_len + 1) >> 1);
- else {
- unsigned char *buf = skb_put(skb, pkt_len);
- unsigned char frag = pkt_len % 4;
-
- insl(ioaddr + DATAPORT, buf, pkt_len >> 2);
+ If some higher layer thinks we've missed an tx-done interrupt
+ we are passed NULL. Caution: dev_tint() handles the cli()/sti()
+ itself
+ */
- if(frag != 0) {
- unsigned short rest[2];
- rest[0] = inw( ioaddr + DATAPORT );
- if(frag == 3)
- rest[1] = inw( ioaddr + DATAPORT );
-
- memcpy(buf + (pkt_len & 0xfffc), (char *)rest, frag);
- }
+ if(skb == NULL) {
+#if LINUX_VERSION_CODE < 0x020100
+ dev_tint(dev);
+#endif
+ if(eth16i_debug > 0)
+ printk(KERN_WARNING "%s: Missed tx-done interrupt.\n", dev->name);
+ return 0;
}
+
+ /* Block a timer based transmitter from overlapping.
+ This could better be done with atomic_swap(1, dev->tbusy),
+ but set_bit() works as well. */
+
+ set_bit(0, (void *)&lp->tx_buf_busy);
- skb->protocol=eth_type_trans(skb, dev);
- netif_rx(skb);
- lp->stats.rx_packets++;
-
- if( eth16i_debug > 5 ) {
- int i;
- printk("%s: Received packet of length %d.\n", dev->name, pkt_len);
- for(i = 0; i < 14; i++)
- printk(" %02x", skb->data[i]);
- printk(".\n");
+ /* Turn off TX interrupts */
+ outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
+
+ if(test_and_set_bit(0, (void *)&dev->tbusy) != 0) {
+ printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
+ status = -1;
}
-
- } /* else */
+ else {
+ ushort length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+ unsigned char *buf = skb->data;
+
+ if( (length + 2) > (lp->tx_buf_size - lp->tx_queue_len)) {
+ if(eth16i_debug > 0)
+ printk(KERN_WARNING "%s: Transmit buffer full.\n", dev->name);
+ }
+ else {
+ outw(length, ioaddr + DATAPORT);
+
+ if( ioaddr < 0x1000 )
+ outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
+ else {
+ unsigned char frag = length % 4;
+
+ outsl(ioaddr + DATAPORT, buf, length >> 2);
+
+ if( frag != 0 ) {
+ outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC)), 1);
+ if( frag == 3 )
+ outsw(ioaddr + DATAPORT,
+ (buf + (length & 0xFFFC) + 2), 1);
+ }
+ }
+
+ lp->tx_buffered_packets++;
+ lp->tx_queue++;
+ lp->tx_queue_len += length + 2;
+
+ }
+
+ lp->tx_buf_busy = 0;
+
+ if(lp->tx_started == 0) {
+ /* If the transmitter is idle..always trigger a transmit */
+ outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
+ lp->tx_queue = 0;
+ lp->tx_queue_len = 0;
+ dev->trans_start = jiffies;
+ lp->tx_started = 1;
+ dev->tbusy = 0;
+ }
+ else if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
+ /* There is still more room for one more packet in tx buffer */
+ dev->tbusy = 0;
+ }
+
+ outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+
+ /* Turn TX interrupts back on */
+ /* outb(TX_INTR_DONE | TX_INTR_16_COL, ioaddr + TX_INTR_REG); */
+ status = 0;
+ }
+
+#if LINUX_VERSION_CODE >= 0x020100
+ dev_kfree_skb(skb);
+#else
+ dev_kfree_skb(skb, FREE_WRITE);
+#endif
- if(--boguscount <= 0)
- break;
+ return status;
+}
- } /* while */
+static void eth16i_rx(struct device *dev)
+{
+ struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+ int boguscount = MAX_RX_LOOP;
+
+ /* Loop until all packets have been read */
+ while( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) {
+
+ /* Read status byte from receive buffer */
+ ushort status = inw(ioaddr + DATAPORT);
+
+ /* Get the size of the packet from receive buffer */
+ ushort pkt_len = inw(ioaddr + DATAPORT);
+
+ if(eth16i_debug > 4)
+ printk(KERN_DEBUG "%s: Receiving packet mode %02x status %04x.\n",
+ dev->name,
+ inb(ioaddr + RECEIVE_MODE_REG), status);
+
+ if( !(status & PKT_GOOD) ) {
+ lp->stats.rx_errors++;
+
+ if( (pkt_len < ETH_ZLEN) || (pkt_len > ETH_FRAME_LEN) ) {
+ lp->stats.rx_length_errors++;
+ eth16i_reset(dev);
+ return;
+ }
+ else {
+ eth16i_skip_packet(dev);
+ lp->stats.rx_dropped++;
+ }
+ }
+ else { /* Ok so now we should have a good packet */
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(pkt_len + 3);
+ if( skb == NULL ) {
+ printk(KERN_WARNING "%s: Could'n allocate memory for packet (len %d)\n",
+ dev->name, pkt_len);
+ eth16i_skip_packet(dev);
+ lp->stats.rx_dropped++;
+ break;
+ }
+
+ skb->dev = dev;
+ skb_reserve(skb,2);
+
+ /*
+ Now let's get the packet out of buffer.
+ size is (pkt_len + 1) >> 1, cause we are now reading words
+ and it have to be even aligned.
+ */
+
+ if(ioaddr < 0x1000)
+ insw(ioaddr + DATAPORT, skb_put(skb, pkt_len),
+ (pkt_len + 1) >> 1);
+ else {
+ unsigned char *buf = skb_put(skb, pkt_len);
+ unsigned char frag = pkt_len % 4;
+
+ insl(ioaddr + DATAPORT, buf, pkt_len >> 2);
+
+ if(frag != 0) {
+ unsigned short rest[2];
+ rest[0] = inw( ioaddr + DATAPORT );
+ if(frag == 3)
+ rest[1] = inw( ioaddr + DATAPORT );
+
+ memcpy(buf + (pkt_len & 0xfffc), (char *)rest, frag);
+ }
+ }
+
+ skb->protocol=eth_type_trans(skb, dev);
+ netif_rx(skb);
+ lp->stats.rx_packets++;
+
+ if( eth16i_debug > 5 ) {
+ int i;
+ printk(KERN_DEBUG "%s: Received packet of length %d.\n",
+ dev->name, pkt_len);
+ for(i = 0; i < 14; i++)
+ printk(KERN_DEBUG " %02x", skb->data[i]);
+ printk(KERN_DEBUG ".\n");
+ }
+
+ } /* else */
+
+ if(--boguscount <= 0)
+ break;
+
+ } /* while */
#if 0
- {
- int i;
-
- for(i = 0; i < 20; i++) {
- if( (inb(ioaddr+RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == RX_BUFFER_EMPTY)
- break;
- inw(ioaddr + DATAPORT);
- outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG);
- }
-
- if(eth16i_debug > 1)
- printk("%s: Flushed receive buffer.\n", dev->name);
- }
+ {
+ int i;
+
+ for(i = 0; i < 20; i++) {
+ if( (inb(ioaddr+RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) ==
+ RX_BUFFER_EMPTY)
+ break;
+ inw(ioaddr + DATAPORT);
+ outb(SKIP_RX_PACKET, ioaddr + FILTER_SELF_RX_REG);
+ }
+
+ if(eth16i_debug > 1)
+ printk(KERN_DEBUG "%s: Flushed receive buffer.\n", dev->name);
+ }
#endif
- return;
+ return;
}
static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- struct device *dev = (struct device *)(irq2dev_map[irq]);
- struct eth16i_local *lp;
- int ioaddr = 0,
- status;
+ struct device *dev = dev_id;
+ struct eth16i_local *lp;
+ int ioaddr = 0,
+ status;
+
+ if(dev == NULL) {
+ printk(KERN_WARNING "eth16i_interrupt(): irq %d for unknown device. \n", irq);
+ return;
+ }
- if(dev == NULL) {
- printk("eth16i_interrupt(): irq %d for unknown device. \n", irq);
- return;
- }
+ /* Turn off all interrupts from adapter */
+ outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
- /* Turn off all interrupts from adapter */
- outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
+ set_bit(0, (void *)&dev->tbusy); /* Set the device busy so that */
+ /* eth16i_tx wont be called */
- dev->interrupt = 1;
+ if(dev->interrupt)
+ printk(KERN_WARNING "%s: Re-entering the interrupt handler.\n", dev->name);
+ dev->interrupt = 1;
- ioaddr = dev->base_addr;
- lp = (struct eth16i_local *)dev->priv;
- status = inw(ioaddr + TX_STATUS_REG); /* Get the status */
- outw(status, ioaddr + TX_STATUS_REG); /* Clear status bits */
-
- if(eth16i_debug > 3)
- printk("%s: Interrupt with status %04x.\n", dev->name, status);
+ ioaddr = dev->base_addr;
+ lp = (struct eth16i_local *)dev->priv;
+ status = inw(ioaddr + TX_STATUS_REG); /* Get the status */
+ outw(status, ioaddr + TX_STATUS_REG); /* Clear status bits */
- if( status & 0x00ff ) { /* Let's check the transmit status reg */
-
- if(status & TX_DONE) { /* The transmit has been done */
- lp->stats.tx_packets++;
+ if(eth16i_debug > 3)
+ printk(KERN_DEBUG "%s: Interrupt with status %04x.\n", dev->name, status);
- if(lp->tx_queue) { /* Is there still packets ? */
- /* There was packet(s) so start transmitting and write also
- how many packets there is to be sent */
- outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
- lp->tx_queue = 0;
- lp->tx_queue_len = 0;
- dev->trans_start = jiffies;
- dev->tbusy = 0;
- mark_bh(NET_BH);
- }
- else {
- lp->tx_started = 0;
- dev->tbusy = 0;
- mark_bh(NET_BH);
- }
- }
- }
-
- if( ( status & 0xff00 ) ||
- ( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) ) {
- eth16i_rx(dev); /* We have packet in receive buffer */
- }
+ if( status & 0x7f00 ) {
- dev->interrupt = 0;
-
- /* Turn interrupts back on */
- outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+ lp->stats.rx_errors++;
+
+ if(status & (BUS_RD_ERR << 8) )
+ printk(KERN_WARNING "%s: Bus read error.\n",dev->name);
+ if(status & (SHORT_PKT_ERR << 8) ) lp->stats.rx_length_errors++;
+ if(status & (ALIGN_ERR << 8) ) lp->stats.rx_frame_errors++;
+ if(status & (CRC_ERR << 8) ) lp->stats.rx_crc_errors++;
+ if(status & (RX_BUF_OVERFLOW << 8) ) lp->stats.rx_over_errors++;
+ }
+ if( status & 0x001a) {
+
+ lp->stats.tx_errors++;
+
+ if(status & CR_LOST) lp->stats.tx_carrier_errors++;
+ if(status & TX_JABBER_ERR) lp->stats.tx_window_errors++;
+
+#if 0
+ if(status & COLLISION) {
+ lp->stats.collisions +=
+ ((inb(ioaddr+TRANSMIT_MODE_REG) & 0xF0) >> 4);
+ }
+#endif
+ if(status & COLLISIONS_16) {
+ if(lp->col_16 < MAX_COL_16) {
+ lp->col_16++;
+ lp->stats.collisions++;
+ /* Resume transmitting, skip failed packet */
+ outb(0x02, ioaddr + COL_16_REG);
+ }
+ else {
+ printk(KERN_WARNING "%s: bailing out due to many consecutive 16-in-a-row collisions. Network cable problem?\n", dev->name);
+ }
+ }
+ }
+
+ if( status & 0x00ff ) { /* Let's check the transmit status reg */
+
+ if(status & TX_DONE) { /* The transmit has been done */
+ lp->stats.tx_packets = lp->tx_buffered_packets;
+ lp->col_16 = 0;
+
+ if(lp->tx_queue) { /* Is there still packets ? */
+ /* There was packet(s) so start transmitting and write also
+ how many packets there is to be sended */
+ outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
+ lp->tx_queue = 0;
+ lp->tx_queue_len = 0;
+ lp->tx_started = 1;
+ dev->trans_start = jiffies;
+ mark_bh(NET_BH);
+ }
+ else {
+ lp->tx_started = 0;
+ mark_bh(NET_BH);
+ }
+ }
+ }
+
+ if( ( status & 0x8000 ) ||
+ ( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) ) {
+ eth16i_rx(dev); /* We have packet in receive buffer */
+ }
+
+ dev->interrupt = 0;
+
+ /* Turn interrupts back on */
+ outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+
+ if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
+ /* There is still more room for one more packet in tx buffer */
+ dev->tbusy = 0;
+ }
+
+ return;
+}
+
+static void eth16i_skip_packet(struct device *dev)
+{
+ int ioaddr = dev->base_addr;
+
+ inw(ioaddr + DATAPORT);
+ inw(ioaddr + DATAPORT);
+ inw(ioaddr + DATAPORT);
+
+ outb(SKIP_RX_PACKET, ioaddr + FILTER_SELF_RX_REG);
+ while( inb( ioaddr + FILTER_SELF_RX_REG ) != 0);
+}
+
+static void eth16i_reset(struct device *dev)
+{
+ struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+
+ if(eth16i_debug > 1)
+ printk(KERN_DEBUG "%s: Resetting device.\n", dev->name);
+
+ BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
+ outw(0xffff, ioaddr + TX_STATUS_REG);
+ eth16i_select_regbank(2, ioaddr);
- return;
+ lp->tx_started = 0;
+ lp->tx_buf_busy = 0;
+ lp->tx_queue = 0;
+ lp->tx_queue_len = 0;
+
+ dev->interrupt = 0;
+ dev->start = 1;
+ dev->tbusy = 0;
+ BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
}
static void eth16i_multicast(struct device *dev)
{
- short ioaddr = dev->base_addr;
+ int ioaddr = dev->base_addr;
- if(dev->mc_count || dev->flags&(IFF_ALLMULTI|IFF_PROMISC))
- {
- dev->flags|=IFF_PROMISC; /* Must do this */
- outb(3, ioaddr + RECEIVE_MODE_REG);
- } else {
- outb(2, ioaddr + RECEIVE_MODE_REG);
- }
+ if(dev->mc_count || dev->flags&(IFF_ALLMULTI|IFF_PROMISC))
+ {
+ dev->flags|=IFF_PROMISC; /* Must do this */
+ outb(3, ioaddr + RECEIVE_MODE_REG);
+ } else {
+ outb(2, ioaddr + RECEIVE_MODE_REG);
+ }
}
static struct enet_statistics *eth16i_get_stats(struct device *dev)
{
- struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+ struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
- return &lp->stats;
+ return &lp->stats;
}
-static void eth16i_select_regbank(unsigned char banknbr, short ioaddr)
+static void eth16i_select_regbank(unsigned char banknbr, int ioaddr)
{
- unsigned char data;
+ unsigned char data;
- data = inb(ioaddr + CONFIG_REG_1);
- outb( ((data & 0xF3) | ( (banknbr & 0x03) << 2)), ioaddr + CONFIG_REG_1);
+ data = inb(ioaddr + CONFIG_REG_1);
+ outb( ((data & 0xF3) | ( (banknbr & 0x03) << 2)), ioaddr + CONFIG_REG_1);
}
#ifdef MODULE
-static char devicename[9] = { 0, };
-static struct device dev_eth16i = {
- devicename,
- 0, 0, 0, 0,
- 0, 0,
- 0, 0, 0, NULL, eth16i_probe };
-int io = 0x2a0;
-int irq = 0;
+static ushort eth16i_parse_mediatype(const char* s)
+{
+ if(!s)
+ return E_PORT_FROM_EPROM;
+
+ if (!strncmp(s, "bnc", 3))
+ return E_PORT_BNC;
+ else if (!strncmp(s, "tp", 2))
+ return E_PORT_TP;
+ else if (!strncmp(s, "dix", 3))
+ return E_PORT_DIX;
+ else if (!strncmp(s, "auto", 4))
+ return E_PORT_AUTO;
+ else
+ return E_PORT_FROM_EPROM;
+}
+
+#define MAX_ETH16I_CARDS 4 /* Max number of Eth16i cards per module */
+#define NAMELEN 8 /* number of chars for storing dev->name */
+
+static char namelist[NAMELEN * MAX_ETH16I_CARDS] = { 0, };
+static struct device dev_eth16i[MAX_ETH16I_CARDS] = {
+ {
+ NULL,
+ 0, 0, 0, 0,
+ 0, 0,
+ 0, 0, 0, NULL, NULL
+ },
+};
+
+static int ioaddr[MAX_ETH16I_CARDS] = { 0, };
+#if 0
+static int irq[MAX_ETH16I_CARDS] = { 0, };
+#endif
+static char* mediatype[MAX_ETH16I_CARDS] = { 0, };
+static int debug = -1;
+
+#if (LINUX_VERSION_CODE >= 0x20115)
+MODULE_AUTHOR("Mika Kuoppala <miku@iki.fi>");
+MODULE_DESCRIPTION("ICL EtherTeam 16i/32 driver");
+
+MODULE_PARM(ioaddr, "1-" __MODULE_STRING(MAX_ETH16I_CARDS) "i");
+MODULE_PARM_DESC(ioaddr, "eth16i io base address");
+
+#if 0
+MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ETH16I_CARDS) "i");
+MODULE_PARM_DESC(irq, "eth16i interrupt request number");
+#endif
+
+MODULE_PARM(mediatype, "1-" __MODULE_STRING(MAX_ETH16I_CARDS) "s");
+MODULE_PARM_DESC(mediatype, "eth16i interfaceport mediatype");
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "eth16i debug level (0-4)");
+#endif
int init_module(void)
{
- if(io == 0)
- printk("eth16i: You should not use auto-probing with insmod!\n");
+ int this_dev, found = 0;
+
+ for(this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++)
+ {
+ struct device *dev = &dev_eth16i[this_dev];
- dev_eth16i.base_addr = io;
- dev_eth16i.irq = irq;
- if( register_netdev( &dev_eth16i ) != 0 ) {
- printk("eth16i: register_netdev() returned non-zero.\n");
- return -EIO;
- }
+ dev->name = namelist + (NAMELEN*this_dev);
+ dev->irq = 0; /* irq[this_dev]; */
+ dev->base_addr = ioaddr[this_dev];
+ dev->init = eth16i_probe;
+
+ if(debug != -1)
+ eth16i_debug = debug;
+
+ if(eth16i_debug > 1)
+ printk(KERN_NOTICE "eth16i(%d): interface type %s\n", this_dev, mediatype[this_dev] ? mediatype[this_dev] : "none" );
+
+ dev->if_port = eth16i_parse_mediatype(mediatype[this_dev]);
+
+ if(ioaddr[this_dev] == 0)
+ {
+ if(this_dev != 0) break; /* Only autoprobe 1st one */
+ printk(KERN_NOTICE "eth16i.c: Presently autoprobing (not recommended) for a single card.\n");
+ }
+
+ if(register_netdev(dev) != 0)
+ {
+ printk(KERN_WARNING "eth16i.c No Eth16i card found (i/o = 0x%x).\n",
+ ioaddr[this_dev]);
+
+ if(found != 0) return 0;
+ return -ENXIO;
+ }
+
+ found++;
+ }
return 0;
}
-
+
void cleanup_module(void)
{
- unregister_netdev( &dev_eth16i );
- free_irq( dev_eth16i.irq, NULL );
- irq2dev_map[ dev_eth16i.irq ] = NULL;
- release_region( dev_eth16i.base_addr, ETH16I_IO_EXTENT );
+ int this_dev;
+
+ for(this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++)
+ {
+ struct device* dev = &dev_eth16i[this_dev];
+
+ if(dev->priv != NULL)
+ {
+ unregister_netdev(dev);
+ kfree(dev->priv);
+ dev->priv = NULL;
+
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr, ETH16I_IO_EXTENT);
+
+ }
+ }
}
-
#endif /* MODULE */
-
+/*
+ * Local variables:
+ * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c eth16i.c"
+ * alt-compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict -prototypes -O6 -c eth16i.c"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * c-indent-level: 8
+ * End:
+ */
+
+/* End of file eth16i.c */
dev->base_addr = ioaddr;
request_region(ioaddr, LANCE_TOTAL_SIZE, chip_table[lance_version].name);
-#ifdef CONFIG_LANCE32
- /* look if it's a PCI or VLB chip */
- if (lance_version == PCNET_PCI || lance_version == PCNET_VLB || lance_version == PCNET_PCI_II) {
- extern int lance32_probe1 (struct device *dev, const char *chipname, int pci_irq_line);
-
- return lance32_probe1 (dev, chipname, pci_irq_line);
- }
-#endif
/* Make certain the data structures used by the LANCE are aligned and DMAble. */
lp = (struct lance_private *)(((unsigned long)kmalloc(sizeof(*lp)+7,
* This driver is for AMD PCnet-PCI based ethercards
*/
-static const char *version = "pcnet32.c:v0.99B 4/4/98 DJBecker/TSBogend.\n";
+static const char *version = "\npcnet32.c:v0.99B 4/4/98 DJBecker/TSBogend.\n";
/* A few user-configurable values. */
PCI_COMMAND, new_command);
}
-#ifdef __powerpc__
- /* This is bogus! -djb */
- irq_line = 15;
-#endif
-
if (pcnet32_probe1(dev, pci_ioaddr, irq_line) != 0) {
/* Should never happen. */
printk(KERN_ERR "pcnet32.c: Probe of PCI card at %#x failed.\n",
inw(ioaddr+PCNET32_ADDR);
dev->irq = irq_line;
-#ifdef __powerpc__
- /* This is sooo bogus! -djb */
- irq_line = 15;
-#endif
outw(0x0002, ioaddr+PCNET32_ADDR);
/* only touch autoselect bit */
/* Log misc errors. */
if (csr0 & 0x4000) lp->stats.tx_errors++; /* Tx babble. */
- if (csr0 & 0x1000) lp->stats.rx_errors++; /* Missed a Rx frame. */
+ if (csr0 & 0x1000) {
+ /*
+ * this happens when our receive ring is full. This
+ * shouldn't be a problem as we will see normal rx
+ * interrupts for the frames in the receive ring. But
+ * there are some PCI chipsets (I can reproduce this
+ * on SP3G with Intel saturn chipset) which have some-
+ * times problems and will fill up the receive ring
+ * with error descriptors. In this situation we don't
+ * get a rx interrupt, but a missed frame interrupt
+ * sooner or later. So we try to clean up our receive
+ * ring here.
+ */
+ pcnet32_rx(dev);
+ lp->stats.rx_errors++; /* Missed a Rx frame. */
+ }
if (csr0 & 0x0800) {
printk("%s: Bus master arbitration failure, status %4.4x.\n",
dev->name, csr0);
+++ /dev/null
-/*
- * THIS FILE IS GENERATED AUTOMATICALLY BY ./gentbl, DO NOT EDIT!
- */
-
-
-/*
- * small cosine table in U8 format
- */
-#define OFFSCOSTABBITS 6
-#define OFFSCOSTABSIZE (1<<OFFSCOSTABBITS)
-
-static unsigned char offscostab[OFFSCOSTABSIZE] = {
- 255, 254, 252, 249, 245, 240, 233, 226,
- 217, 208, 198, 187, 176, 164, 152, 140,
- 128, 115, 103, 91, 79, 68, 57, 47,
- 38, 29, 22, 15, 10, 6, 3, 1,
- 1, 1, 3, 6, 10, 15, 22, 29,
- 38, 47, 57, 68, 79, 91, 103, 115,
- 127, 140, 152, 164, 176, 187, 198, 208,
- 217, 226, 233, 240, 245, 249, 252, 254
-};
-
-#define OFFSCOS(x) offscostab[((x)>>10)&0x3f]
-
-
-/*
- * more accurate cosine table
- */
-
-static const short costab[64] = {
- 32767, 32609, 32137, 31356, 30272, 28897, 27244, 25329,
- 23169, 20787, 18204, 15446, 12539, 9511, 6392, 3211,
- 0, -3211, -6392, -9511, -12539, -15446, -18204, -20787,
- -23169, -25329, -27244, -28897, -30272, -31356, -32137, -32609,
- -32767, -32609, -32137, -31356, -30272, -28897, -27244, -25329,
- -23169, -20787, -18204, -15446, -12539, -9511, -6392, -3211,
- 0, 3211, 6392, 9511, 12539, 15446, 18204, 20787,
- 23169, 25329, 27244, 28897, 30272, 31356, 32137, 32609
-};
-
-#define COS(x) costab[((x)>>10)&0x3f]
-#define SIN(x) COS((x)+0xc000)
-
-
-/*
- * afsk1200 specific tables
- */
-#define AFSK12_SAMPLE_RATE 9600
-#define AFSK12_TX_FREQ_LO 1200
-#define AFSK12_TX_FREQ_HI 2200
-#define AFSK12_CORRLEN 8
-
-static const int afsk12_tx_lo_i[] = {
- 127, 89, 0, -89, -127, -89, 0, 89
-};
-#define SUM_AFSK12_TX_LO_I 0
-
-static const int afsk12_tx_lo_q[] = {
- 0, 89, 127, 89, 0, -89, -127, -89
-};
-#define SUM_AFSK12_TX_LO_Q 0
-
-static const int afsk12_tx_hi_i[] = {
- 127, 16, -122, -48, 109, 77, -89, -100
-};
-#define SUM_AFSK12_TX_HI_I -30
-
-static const int afsk12_tx_hi_q[] = {
- 0, 125, 32, -117, -63, 100, 89, -77
-};
-#define SUM_AFSK12_TX_HI_Q 89
-
+++ /dev/null
-/*
- * THIS FILE IS GENERATED AUTOMATICALLY BY ./gentbl, DO NOT EDIT!
- */
-
-
-/*
- * small cosine table in U8 format
- */
-#define OFFSCOSTABBITS 6
-#define OFFSCOSTABSIZE (1<<OFFSCOSTABBITS)
-
-static unsigned char offscostab[OFFSCOSTABSIZE] = {
- 255, 254, 252, 249, 245, 240, 233, 226,
- 217, 208, 198, 187, 176, 164, 152, 140,
- 128, 115, 103, 91, 79, 68, 57, 47,
- 38, 29, 22, 15, 10, 6, 3, 1,
- 1, 1, 3, 6, 10, 15, 22, 29,
- 38, 47, 57, 68, 79, 91, 103, 115,
- 127, 140, 152, 164, 176, 187, 198, 208,
- 217, 226, 233, 240, 245, 249, 252, 254
-};
-
-#define OFFSCOS(x) offscostab[((x)>>10)&0x3f]
-
-
-/*
- * more accurate cosine table
- */
-
-static const short costab[64] = {
- 32767, 32609, 32137, 31356, 30272, 28897, 27244, 25329,
- 23169, 20787, 18204, 15446, 12539, 9511, 6392, 3211,
- 0, -3211, -6392, -9511, -12539, -15446, -18204, -20787,
- -23169, -25329, -27244, -28897, -30272, -31356, -32137, -32609,
- -32767, -32609, -32137, -31356, -30272, -28897, -27244, -25329,
- -23169, -20787, -18204, -15446, -12539, -9511, -6392, -3211,
- 0, 3211, 6392, 9511, 12539, 15446, 18204, 20787,
- 23169, 25329, 27244, 28897, 30272, 31356, 32137, 32609
-};
-
-#define COS(x) costab[((x)>>10)&0x3f]
-#define SIN(x) COS((x)+0xc000)
-
-
-/*
- * afsk2400 specific tables (tcm3105 clk 7372800.000000Hz)
- */
-#define AFSK24_TX_FREQ_LO 1995
-#define AFSK24_TX_FREQ_HI 3658
-#define AFSK24_BITPLL_INC 9830
-#define AFSK24_SAMPLERATE 16000
-
-static const int afsk24_tx_lo_i[] = {
- 10, 11, 0, -43, -89, -80, -1, 87, 112, 64, 0, -24, -16, -7
-};
-#define SUM_AFSK24_TX_LO_I 24
-
-static const int afsk24_tx_lo_q[] = {
- 0, 11, 35, 43, 0, -78, -125, -89, -1, 62, 61, 25, 0, -7
-};
-#define SUM_AFSK24_TX_LO_Q -63
-
-static const int afsk24_tx_hi_i[] = {
- 10, 2, -34, -24, 76, 69, -86, -101, 53, 83, -14, -35, 0, 10
-};
-#define SUM_AFSK24_TX_HI_I 9
-
-static const int afsk24_tx_hi_q[] = {
- 0, 16, 9, -56, -45, 88, 90, -74, -98, 31, 59, -3, -16, -1
-};
-#define SUM_AFSK24_TX_HI_Q 0
-
+++ /dev/null
-/*
- * THIS FILE IS GENERATED AUTOMATICALLY BY ./gentbl, DO NOT EDIT!
- */
-
-
-/*
- * small cosine table in U8 format
- */
-#define OFFSCOSTABBITS 6
-#define OFFSCOSTABSIZE (1<<OFFSCOSTABBITS)
-
-static unsigned char offscostab[OFFSCOSTABSIZE] = {
- 255, 254, 252, 249, 245, 240, 233, 226,
- 217, 208, 198, 187, 176, 164, 152, 140,
- 128, 115, 103, 91, 79, 68, 57, 47,
- 38, 29, 22, 15, 10, 6, 3, 1,
- 1, 1, 3, 6, 10, 15, 22, 29,
- 38, 47, 57, 68, 79, 91, 103, 115,
- 127, 140, 152, 164, 176, 187, 198, 208,
- 217, 226, 233, 240, 245, 249, 252, 254
-};
-
-#define OFFSCOS(x) offscostab[((x)>>10)&0x3f]
-
-
-/*
- * more accurate cosine table
- */
-
-static const short costab[64] = {
- 32767, 32609, 32137, 31356, 30272, 28897, 27244, 25329,
- 23169, 20787, 18204, 15446, 12539, 9511, 6392, 3211,
- 0, -3211, -6392, -9511, -12539, -15446, -18204, -20787,
- -23169, -25329, -27244, -28897, -30272, -31356, -32137, -32609,
- -32767, -32609, -32137, -31356, -30272, -28897, -27244, -25329,
- -23169, -20787, -18204, -15446, -12539, -9511, -6392, -3211,
- 0, 3211, 6392, 9511, 12539, 15446, 18204, 20787,
- 23169, 25329, 27244, 28897, 30272, 31356, 32137, 32609
-};
-
-#define COS(x) costab[((x)>>10)&0x3f]
-#define SIN(x) COS((x)+0xc000)
-
-
-/*
- * afsk2400 specific tables (tcm3105 clk 8000000.000000Hz)
- */
-#define AFSK24_TX_FREQ_LO 2165
-#define AFSK24_TX_FREQ_HI 3970
-#define AFSK24_BITPLL_INC 9830
-#define AFSK24_SAMPLERATE 16000
-
-static const int afsk24_tx_lo_i[] = {
- 10, 11, -4, -51, -86, -49, 47, 118, 97, 17, -37, -35, -11, 0
-};
-#define SUM_AFSK24_TX_LO_I 27
-
-static const int afsk24_tx_lo_q[] = {
- 0, 12, 35, 34, -22, -100, -115, -40, 55, 87, 48, 2, -11, -10
-};
-#define SUM_AFSK24_TX_LO_Q -25
-
-static const int afsk24_tx_hi_i[] = {
- 10, 0, -35, -2, 89, 6, -124, -10, 111, 9, -61, -4, 16, 1
-};
-#define SUM_AFSK24_TX_HI_I 6
-
-static const int afsk24_tx_hi_q[] = {
- 0, 16, 0, -61, -4, 112, 8, -124, -10, 88, 7, -35, -2, 10
-};
-#define SUM_AFSK24_TX_HI_Q 5
-
+++ /dev/null
-/*
- * THIS FILE IS GENERATED AUTOMATICALLY BY ./gentbl, DO NOT EDIT!
- */
-
-
-/*
- * small cosine table in U8 format
- */
-#define OFFSCOSTABBITS 6
-#define OFFSCOSTABSIZE (1<<OFFSCOSTABBITS)
-
-static unsigned char offscostab[OFFSCOSTABSIZE] = {
- 255, 254, 252, 249, 245, 240, 233, 226,
- 217, 208, 198, 187, 176, 164, 152, 140,
- 128, 115, 103, 91, 79, 68, 57, 47,
- 38, 29, 22, 15, 10, 6, 3, 1,
- 1, 1, 3, 6, 10, 15, 22, 29,
- 38, 47, 57, 68, 79, 91, 103, 115,
- 127, 140, 152, 164, 176, 187, 198, 208,
- 217, 226, 233, 240, 245, 249, 252, 254
-};
-
-#define OFFSCOS(x) offscostab[((x)>>10)&0x3f]
-
-
-/*
- * more accurate cosine table
- */
-
-static const short costab[64] = {
- 32767, 32609, 32137, 31356, 30272, 28897, 27244, 25329,
- 23169, 20787, 18204, 15446, 12539, 9511, 6392, 3211,
- 0, -3211, -6392, -9511, -12539, -15446, -18204, -20787,
- -23169, -25329, -27244, -28897, -30272, -31356, -32137, -32609,
- -32767, -32609, -32137, -31356, -30272, -28897, -27244, -25329,
- -23169, -20787, -18204, -15446, -12539, -9511, -6392, -3211,
- 0, 3211, 6392, 9511, 12539, 15446, 18204, 20787,
- 23169, 25329, 27244, 28897, 30272, 31356, 32137, 32609
-};
-
-#define COS(x) costab[((x)>>10)&0x3f]
-#define SIN(x) COS((x)+0xc000)
-
-
-/*
- * afsk2666 specific tables
- */
-#define AFSK26_DEMCORRLEN 12
-#define AFSK26_SAMPLERATE 16000
-
-static const unsigned int afsk26_carfreq[2] = { 0x2000, 0x3555 };
-
-
-static const struct {
- int i[12];
- int q[12];
-} afsk26_dem_tables[2][2] = {
- {
- {{ 1, 7, -18, -73, -100, -47, 47, 100, 73, 18, -7, -1 }, { 0, 17, 43, 30, -41, -115, -115, -41, 30, 43, 17, 0 }},
-#define AFSK26_DEM_SUM_I_0_0 0
-#define AFSK26_DEM_SUM_Q_0_0 -132
- {{ 1, -7, -46, -10, 100, 76, -75, -100, 10, 46, 7, -1 }, { 1, 17, -6, -79, -41, 99, 99, -41, -79, -6, 17, 1 }}
-#define AFSK26_DEM_SUM_I_0_1 1
-#define AFSK26_DEM_SUM_Q_0_1 -18
- },
- {
- {{ 8, 22, 0, -67, -118, -89, 0, 67, 63, 22, 0, 0 }, { 0, 22, 63, 67, 0, -89, -118, -67, 0, 22, 8, 0 }},
-#define AFSK26_DEM_SUM_I_1_0 -92
-#define AFSK26_DEM_SUM_Q_1_0 -92
- {{ 8, 8, -54, -67, 59, 122, 0, -91, -31, 22, 7, 0 }, { 0, 30, 31, -67, -102, 32, 118, 24, -54, -22, 4, 0 }}
-#define AFSK26_DEM_SUM_I_1_1 -17
-#define AFSK26_DEM_SUM_Q_1_1 -6
- }
-};
-
+++ /dev/null
-/*
- * THIS FILE IS GENERATED AUTOMATICALLY BY ./gentbl, DO NOT EDIT!
- */
-
-
-/*
- * fsk9600 specific tables
- */
-static unsigned char fsk96_txfilt_4[] = {
- 37, 37, 35, 36, 39, 40, 38, 38,
- 53, 53, 51, 52, 55, 56, 54, 54,
- 210, 210, 208, 209, 212, 213, 211, 211,
- 226, 226, 224, 225, 228, 229, 227, 227,
- 23, 23, 22, 22, 26, 26, 24, 24,
- 39, 39, 38, 38, 42, 42, 40, 40,
- 196, 196, 195, 195, 199, 199, 197, 197,
- 212, 212, 211, 211, 215, 215, 213, 213,
- 43, 43, 42, 42, 46, 46, 44, 44,
- 59, 59, 58, 58, 62, 62, 60, 60,
- 216, 216, 215, 215, 219, 219, 217, 217,
- 232, 232, 231, 231, 235, 235, 233, 233,
- 29, 29, 28, 28, 32, 32, 30, 30,
- 45, 45, 44, 44, 48, 48, 46, 46,
- 202, 202, 201, 201, 205, 205, 203, 203,
- 218, 218, 217, 217, 221, 221, 219, 219,
- 36, 36, 34, 34, 38, 38, 37, 37,
- 52, 52, 50, 50, 54, 54, 53, 53,
- 209, 209, 207, 207, 211, 211, 210, 210,
- 225, 225, 223, 223, 227, 227, 226, 226,
- 22, 22, 20, 20, 24, 24, 23, 23,
- 38, 38, 36, 36, 40, 40, 39, 39,
- 195, 195, 193, 193, 197, 197, 196, 196,
- 211, 211, 209, 209, 213, 213, 212, 212,
- 42, 42, 40, 40, 44, 44, 43, 43,
- 58, 58, 56, 56, 60, 60, 59, 59,
- 215, 215, 213, 213, 217, 217, 216, 216,
- 231, 231, 229, 229, 233, 233, 232, 232,
- 28, 28, 26, 27, 30, 31, 29, 29,
- 44, 44, 42, 43, 46, 47, 45, 45,
- 201, 201, 199, 200, 203, 204, 202, 202,
- 217, 217, 215, 216, 219, 220, 218, 218,
- 37, 37, 37, 37, 29, 29, 29, 30,
- 108, 108, 108, 108, 100, 100, 100, 100,
- 169, 169, 169, 170, 161, 161, 162, 162,
- 240, 240, 240, 240, 232, 232, 232, 232,
- 19, 19, 19, 20, 11, 11, 12, 12,
- 90, 90, 90, 90, 82, 82, 82, 82,
- 151, 151, 152, 152, 143, 143, 144, 144,
- 222, 222, 222, 222, 214, 214, 215, 215,
- 41, 41, 41, 41, 33, 33, 33, 34,
- 112, 112, 112, 112, 104, 104, 104, 104,
- 173, 173, 173, 174, 165, 165, 166, 166,
- 244, 244, 244, 244, 236, 236, 236, 236,
- 23, 23, 23, 24, 15, 15, 16, 16,
- 94, 94, 94, 94, 86, 86, 86, 86,
- 155, 155, 156, 156, 147, 147, 148, 148,
- 226, 226, 226, 226, 218, 218, 219, 219,
- 36, 36, 37, 37, 29, 29, 29, 29,
- 107, 107, 108, 108, 99, 99, 100, 100,
- 169, 169, 169, 169, 161, 161, 161, 161,
- 239, 239, 240, 240, 231, 232, 232, 232,
- 19, 19, 19, 19, 11, 11, 11, 11,
- 89, 89, 90, 90, 81, 82, 82, 82,
- 151, 151, 151, 151, 143, 143, 143, 143,
- 221, 222, 222, 222, 214, 214, 214, 214,
- 40, 40, 41, 41, 33, 33, 33, 33,
- 111, 111, 112, 112, 103, 103, 104, 104,
- 173, 173, 173, 173, 165, 165, 165, 165,
- 243, 243, 244, 244, 235, 236, 236, 236,
- 23, 23, 23, 23, 15, 15, 15, 15,
- 93, 93, 94, 94, 85, 86, 86, 86,
- 155, 155, 155, 155, 147, 147, 147, 147,
- 225, 226, 226, 226, 218, 218, 218, 218,
- 37, 36, 41, 40, 19, 19, 23, 23,
- 169, 169, 173, 173, 151, 151, 155, 155,
- 108, 107, 112, 111, 90, 89, 94, 93,
- 240, 239, 244, 243, 222, 221, 226, 225,
- 29, 29, 33, 33, 11, 11, 15, 15,
- 161, 161, 165, 165, 143, 143, 147, 147,
- 100, 99, 104, 103, 82, 81, 86, 85,
- 232, 231, 236, 235, 214, 214, 218, 218,
- 37, 37, 41, 41, 19, 19, 23, 23,
- 169, 169, 173, 173, 152, 151, 156, 155,
- 108, 108, 112, 112, 90, 90, 94, 94,
- 240, 240, 244, 244, 222, 222, 226, 226,
- 29, 29, 33, 33, 12, 11, 16, 15,
- 162, 161, 166, 165, 144, 143, 148, 147,
- 100, 100, 104, 104, 82, 82, 86, 86,
- 232, 232, 236, 236, 215, 214, 219, 218,
- 37, 36, 41, 40, 19, 19, 23, 23,
- 169, 169, 173, 173, 151, 151, 155, 155,
- 108, 107, 112, 111, 90, 89, 94, 93,
- 240, 239, 244, 243, 222, 222, 226, 226,
- 29, 29, 33, 33, 11, 11, 15, 15,
- 161, 161, 165, 165, 143, 143, 147, 147,
- 100, 99, 104, 103, 82, 82, 86, 86,
- 232, 232, 236, 236, 214, 214, 218, 218,
- 37, 37, 41, 41, 20, 19, 24, 23,
- 170, 169, 174, 173, 152, 151, 156, 155,
- 108, 108, 112, 112, 90, 90, 94, 94,
- 240, 240, 244, 244, 222, 222, 226, 226,
- 30, 29, 34, 33, 12, 11, 16, 15,
- 162, 161, 166, 165, 144, 143, 148, 147,
- 100, 100, 104, 104, 82, 82, 86, 86,
- 232, 232, 236, 236, 215, 214, 219, 218,
- 37, 36, 43, 42, 23, 22, 29, 28,
- 210, 209, 216, 215, 196, 195, 202, 201,
- 53, 52, 59, 58, 39, 38, 45, 44,
- 226, 225, 232, 231, 212, 211, 218, 217,
- 39, 38, 46, 44, 26, 24, 32, 30,
- 212, 211, 219, 217, 199, 197, 205, 203,
- 55, 54, 62, 60, 42, 40, 48, 46,
- 228, 227, 235, 233, 215, 213, 221, 219,
- 35, 34, 42, 40, 22, 20, 28, 26,
- 208, 207, 215, 213, 195, 193, 201, 199,
- 51, 50, 58, 56, 38, 36, 44, 42,
- 224, 223, 231, 229, 211, 209, 217, 215,
- 38, 37, 44, 43, 24, 23, 30, 29,
- 211, 210, 217, 216, 197, 196, 203, 202,
- 54, 53, 60, 59, 40, 39, 46, 45,
- 227, 226, 233, 232, 213, 212, 219, 218,
- 37, 36, 43, 42, 23, 22, 29, 28,
- 210, 209, 216, 215, 196, 195, 202, 201,
- 53, 52, 59, 58, 39, 38, 45, 44,
- 226, 225, 232, 231, 212, 211, 218, 217,
- 40, 38, 46, 44, 26, 24, 32, 31,
- 213, 211, 219, 217, 199, 197, 205, 204,
- 56, 54, 62, 60, 42, 40, 48, 47,
- 229, 227, 235, 233, 215, 213, 221, 220,
- 36, 34, 42, 40, 22, 20, 28, 27,
- 209, 207, 215, 213, 195, 193, 201, 200,
- 52, 50, 58, 56, 38, 36, 44, 43,
- 225, 223, 231, 229, 211, 209, 217, 216,
- 38, 37, 44, 43, 24, 23, 30, 29,
- 211, 210, 217, 216, 197, 196, 203, 202,
- 54, 53, 60, 59, 40, 39, 46, 45,
- 227, 226, 233, 232, 213, 212, 219, 218
-};
-
-static unsigned char fsk96_txfilt_5[] = {
- 39, 40, 38, 38, 42, 43, 41, 41,
- 51, 51, 50, 50, 54, 54, 53, 53,
- 209, 209, 207, 208, 212, 212, 210, 211,
- 221, 221, 219, 219, 224, 224, 222, 222,
- 28, 28, 27, 27, 31, 31, 30, 30,
- 40, 40, 38, 39, 43, 43, 41, 42,
- 198, 198, 196, 196, 201, 201, 199, 199,
- 209, 210, 208, 208, 212, 213, 211, 211,
- 45, 45, 44, 44, 48, 48, 47, 47,
- 57, 57, 56, 56, 60, 60, 59, 59,
- 215, 215, 213, 213, 218, 218, 216, 216,
- 227, 227, 225, 225, 230, 230, 228, 228,
- 34, 34, 32, 33, 37, 37, 35, 36,
- 46, 46, 44, 44, 49, 49, 47, 47,
- 203, 204, 202, 202, 206, 207, 205, 205,
- 215, 215, 214, 214, 218, 218, 217, 217,
- 38, 38, 37, 37, 41, 41, 40, 40,
- 50, 50, 48, 49, 53, 53, 51, 52,
- 208, 208, 206, 206, 211, 211, 209, 209,
- 219, 220, 218, 218, 222, 223, 221, 221,
- 27, 27, 25, 25, 30, 30, 28, 28,
- 39, 39, 37, 37, 42, 42, 40, 40,
- 196, 196, 195, 195, 199, 199, 198, 198,
- 208, 208, 207, 207, 211, 211, 210, 210,
- 44, 44, 42, 43, 47, 47, 45, 46,
- 56, 56, 54, 54, 59, 59, 57, 57,
- 213, 214, 212, 212, 216, 217, 215, 215,
- 225, 225, 224, 224, 228, 228, 227, 227,
- 33, 33, 31, 31, 36, 36, 34, 34,
- 44, 45, 43, 43, 47, 48, 46, 46,
- 202, 202, 201, 201, 205, 205, 204, 204,
- 214, 214, 212, 213, 217, 217, 215, 216,
- 39, 40, 39, 39, 35, 35, 35, 35,
- 91, 91, 90, 90, 86, 87, 86, 86,
- 183, 183, 182, 182, 178, 179, 178, 178,
- 234, 234, 234, 234, 230, 230, 229, 230,
- 21, 22, 21, 21, 17, 17, 17, 17,
- 73, 73, 72, 72, 68, 69, 68, 68,
- 165, 165, 164, 164, 161, 161, 160, 160,
- 216, 216, 216, 216, 212, 212, 211, 212,
- 44, 44, 44, 44, 40, 40, 40, 40,
- 95, 96, 95, 95, 91, 91, 91, 91,
- 187, 188, 187, 187, 183, 183, 183, 183,
- 239, 239, 238, 239, 235, 235, 234, 234,
- 26, 26, 26, 26, 22, 22, 22, 22,
- 77, 78, 77, 77, 73, 73, 73, 73,
- 170, 170, 169, 169, 165, 165, 165, 165,
- 221, 221, 220, 221, 217, 217, 216, 216,
- 39, 39, 38, 38, 34, 35, 34, 34,
- 90, 90, 90, 90, 86, 86, 85, 85,
- 182, 182, 182, 182, 178, 178, 177, 178,
- 233, 233, 233, 233, 229, 229, 229, 229,
- 21, 21, 20, 20, 16, 17, 16, 16,
- 72, 72, 72, 72, 68, 68, 67, 68,
- 164, 164, 164, 164, 160, 160, 159, 160,
- 215, 215, 215, 215, 211, 211, 211, 211,
- 43, 44, 43, 43, 39, 39, 39, 39,
- 95, 95, 94, 94, 91, 91, 90, 90,
- 187, 187, 186, 187, 183, 183, 182, 182,
- 238, 238, 238, 238, 234, 234, 233, 234,
- 25, 26, 25, 25, 21, 21, 21, 21,
- 77, 77, 76, 77, 73, 73, 72, 72,
- 169, 169, 168, 169, 165, 165, 164, 164,
- 220, 220, 220, 220, 216, 216, 215, 216,
- 39, 39, 41, 41, 26, 26, 28, 28,
- 139, 139, 141, 141, 126, 125, 128, 128,
- 139, 139, 141, 141, 126, 125, 128, 127,
- 238, 238, 240, 240, 225, 225, 227, 227,
- 26, 26, 28, 28, 13, 13, 15, 15,
- 126, 125, 128, 128, 112, 112, 115, 114,
- 126, 125, 128, 127, 112, 112, 115, 114,
- 225, 225, 227, 227, 212, 212, 214, 214,
- 41, 41, 44, 43, 28, 28, 30, 30,
- 141, 141, 143, 143, 128, 128, 130, 130,
- 141, 141, 143, 143, 128, 127, 130, 130,
- 240, 240, 242, 242, 227, 227, 229, 229,
- 28, 28, 30, 30, 15, 15, 17, 17,
- 128, 128, 130, 130, 115, 114, 117, 116,
- 128, 127, 130, 130, 115, 114, 117, 116,
- 227, 227, 229, 229, 214, 214, 216, 216,
- 39, 39, 41, 41, 26, 26, 28, 28,
- 139, 138, 141, 140, 125, 125, 128, 127,
- 139, 138, 141, 140, 125, 125, 127, 127,
- 238, 238, 240, 240, 225, 225, 227, 227,
- 26, 26, 28, 28, 13, 13, 15, 15,
- 125, 125, 128, 127, 112, 112, 114, 114,
- 125, 125, 127, 127, 112, 112, 114, 114,
- 225, 225, 227, 227, 212, 211, 214, 214,
- 41, 41, 43, 43, 28, 28, 30, 30,
- 141, 140, 143, 143, 128, 127, 130, 129,
- 141, 140, 143, 143, 127, 127, 130, 129,
- 240, 240, 242, 242, 227, 227, 229, 229,
- 28, 28, 30, 30, 15, 15, 17, 17,
- 128, 127, 130, 129, 114, 114, 116, 116,
- 127, 127, 130, 129, 114, 114, 116, 116,
- 227, 227, 229, 229, 214, 214, 216, 216,
- 39, 39, 44, 43, 21, 21, 26, 25,
- 183, 182, 187, 187, 165, 164, 170, 169,
- 91, 90, 95, 95, 73, 72, 77, 77,
- 234, 233, 239, 238, 216, 215, 221, 220,
- 35, 34, 40, 39, 17, 16, 22, 21,
- 178, 178, 183, 183, 161, 160, 165, 165,
- 86, 86, 91, 91, 68, 68, 73, 73,
- 230, 229, 235, 234, 212, 211, 217, 216,
- 39, 38, 44, 43, 21, 20, 26, 25,
- 182, 182, 187, 186, 164, 164, 169, 168,
- 90, 90, 95, 94, 72, 72, 77, 76,
- 234, 233, 238, 238, 216, 215, 220, 220,
- 35, 34, 40, 39, 17, 16, 22, 21,
- 178, 177, 183, 182, 160, 159, 165, 164,
- 86, 85, 91, 90, 68, 67, 73, 72,
- 229, 229, 234, 233, 211, 211, 216, 215,
- 40, 39, 44, 44, 22, 21, 26, 26,
- 183, 182, 188, 187, 165, 164, 170, 169,
- 91, 90, 96, 95, 73, 72, 78, 77,
- 234, 233, 239, 238, 216, 215, 221, 220,
- 35, 35, 40, 39, 17, 17, 22, 21,
- 179, 178, 183, 183, 161, 160, 165, 165,
- 87, 86, 91, 91, 69, 68, 73, 73,
- 230, 229, 235, 234, 212, 211, 217, 216,
- 39, 38, 44, 43, 21, 20, 26, 25,
- 182, 182, 187, 187, 164, 164, 169, 169,
- 90, 90, 95, 94, 72, 72, 77, 77,
- 234, 233, 239, 238, 216, 215, 221, 220,
- 35, 34, 40, 39, 17, 16, 22, 21,
- 178, 178, 183, 182, 160, 160, 165, 164,
- 86, 85, 91, 90, 68, 68, 73, 72,
- 230, 229, 234, 234, 212, 211, 216, 216,
- 39, 38, 45, 44, 28, 27, 34, 33,
- 209, 208, 215, 213, 198, 196, 203, 202,
- 51, 50, 57, 56, 40, 39, 46, 44,
- 221, 219, 227, 225, 209, 208, 215, 214,
- 42, 41, 48, 47, 31, 30, 37, 36,
- 212, 211, 218, 216, 201, 199, 206, 205,
- 54, 53, 60, 59, 43, 42, 49, 47,
- 224, 222, 230, 228, 212, 211, 218, 217,
- 38, 37, 44, 42, 27, 25, 32, 31,
- 207, 206, 213, 212, 196, 195, 202, 201,
- 50, 48, 56, 54, 38, 37, 44, 43,
- 219, 218, 225, 224, 208, 207, 214, 212,
- 41, 40, 47, 45, 30, 28, 35, 34,
- 210, 209, 216, 215, 199, 198, 205, 204,
- 53, 51, 59, 57, 41, 40, 47, 46,
- 222, 221, 228, 227, 211, 210, 217, 215,
- 40, 38, 45, 44, 28, 27, 34, 33,
- 209, 208, 215, 214, 198, 196, 204, 202,
- 51, 50, 57, 56, 40, 39, 46, 45,
- 221, 220, 227, 225, 210, 208, 215, 214,
- 43, 41, 48, 47, 31, 30, 37, 36,
- 212, 211, 218, 217, 201, 199, 207, 205,
- 54, 53, 60, 59, 43, 42, 49, 48,
- 224, 223, 230, 228, 213, 211, 218, 217,
- 38, 37, 44, 43, 27, 25, 33, 31,
- 208, 206, 213, 212, 196, 195, 202, 201,
- 50, 49, 56, 54, 39, 37, 44, 43,
- 219, 218, 225, 224, 208, 207, 214, 213,
- 41, 40, 47, 46, 30, 28, 36, 34,
- 211, 209, 216, 215, 199, 198, 205, 204,
- 53, 52, 59, 57, 42, 40, 47, 46,
- 222, 221, 228, 227, 211, 210, 217, 216
-};
-
+++ /dev/null
-/*
- * THIS FILE IS GENERATED AUTOMATICALLY BY ./gentbl, DO NOT EDIT!
- */
-
-
-/*
- * hapn4800 specific tables
- */
-
-static unsigned char hapn48_txfilt_8[] = {
- 128, 127, 92, 91, 151, 150, 115, 114,
- 141, 140, 105, 104, 164, 163, 128, 128,
- 127, 128, 63, 63, 193, 194, 129, 129,
- 126, 126, 61, 62, 192, 192, 127, 128,
- 128, 129, 37, 38, 224, 226, 134, 135,
- 120, 121, 29, 31, 217, 218, 126, 127,
- 128, 132, 19, 24, 239, 243, 130, 135,
- 120, 125, 12, 16, 231, 236, 123, 127,
- 128, 135, 16, 24, 236, 243, 125, 132,
- 123, 130, 12, 19, 231, 239, 120, 127,
- 128, 135, 31, 38, 218, 226, 121, 129,
- 126, 134, 29, 37, 217, 224, 120, 127,
- 127, 129, 62, 63, 192, 194, 126, 128,
- 127, 129, 61, 63, 192, 193, 126, 128,
- 128, 114, 104, 91, 163, 150, 140, 127,
- 128, 115, 105, 92, 164, 151, 141, 127
-};
-
-static unsigned char hapn48_txfilt_10[] = {
- 128, 127, 94, 94, 146, 146, 113, 112,
- 143, 142, 109, 109, 161, 161, 128, 128,
- 128, 127, 72, 72, 182, 182, 126, 126,
- 129, 129, 73, 73, 183, 183, 128, 127,
- 127, 128, 49, 50, 211, 212, 133, 133,
- 122, 122, 43, 44, 205, 206, 127, 128,
- 127, 130, 30, 33, 231, 233, 133, 136,
- 119, 122, 22, 24, 222, 225, 125, 128,
- 127, 133, 18, 23, 240, 245, 130, 135,
- 120, 125, 10, 15, 232, 237, 122, 128,
- 128, 135, 15, 23, 237, 245, 125, 133,
- 122, 130, 10, 18, 232, 240, 120, 128,
- 127, 136, 24, 33, 225, 233, 122, 130,
- 125, 133, 22, 30, 222, 231, 119, 128,
- 128, 133, 44, 50, 206, 212, 122, 128,
- 127, 133, 43, 49, 205, 211, 122, 127,
- 127, 126, 73, 72, 183, 182, 129, 127,
- 128, 126, 73, 72, 183, 182, 129, 128,
- 128, 112, 109, 94, 161, 146, 142, 127,
- 128, 113, 109, 94, 161, 146, 143, 127
-};
-
-static unsigned char hapn48_txfilt_pm8[] = {
- 12, 6, 242, 237, 18, 12, 248, 243,
- 12, 7, 243, 237, 18, 13, 249, 243,
- 12, 18, 243, 248, 7, 12, 237, 243,
- 12, 18, 243, 248, 7, 12, 237, 243,
- 12, 39, 225, 252, 3, 30, 216, 243,
- 12, 39, 225, 252, 3, 30, 216, 243,
- 11, 70, 193, 252, 3, 62, 185, 244,
- 11, 70, 193, 252, 3, 62, 185, 244,
- 11, 109, 152, 250, 5, 103, 146, 244,
- 11, 109, 152, 250, 5, 103, 146, 244,
- 9, 150, 107, 248, 7, 148, 105, 246,
- 9, 150, 107, 248, 7, 148, 105, 246,
- 8, 189, 66, 248, 7, 189, 66, 247,
- 8, 189, 66, 248, 7, 189, 66, 247,
- 7, 221, 34, 248, 7, 221, 34, 248,
- 7, 221, 34, 248, 7, 221, 34, 248
-};
-
-static unsigned char hapn48_txfilt_pm10[] = {
- 12, 12, 8, 8, 243, 243, 238, 238,
- 17, 17, 12, 12, 247, 247, 243, 243,
- 8, 8, 12, 13, 238, 239, 243, 243,
- 12, 12, 16, 17, 242, 243, 247, 247,
- 8, 8, 28, 28, 227, 227, 247, 247,
- 8, 8, 28, 28, 227, 227, 247, 247,
- 9, 8, 50, 50, 207, 206, 248, 248,
- 7, 7, 49, 48, 205, 205, 247, 246,
- 10, 9, 79, 78, 179, 178, 249, 248,
- 7, 6, 77, 76, 177, 176, 246, 245,
- 11, 8, 113, 110, 147, 144, 249, 246,
- 9, 6, 111, 108, 145, 142, 247, 244,
- 12, 7, 148, 143, 114, 109, 250, 245,
- 10, 5, 146, 141, 112, 107, 248, 243,
- 12, 5, 181, 174, 82, 74, 251, 244,
- 11, 4, 181, 173, 81, 74, 250, 243,
- 12, 3, 210, 201, 54, 45, 252, 243,
- 12, 3, 210, 201, 54, 45, 252, 243,
- 12, 4, 231, 223, 32, 24, 251, 243,
- 12, 4, 231, 223, 32, 24, 251, 243
-};
-
+++ /dev/null
-/*
- * THIS FILE IS GENERATED AUTOMATICALLY BY ./gentbl, DO NOT EDIT!
- */
-
-
-/*
- * psk4800 specific tables
- */
-#define PSK48_TXF_OVERSAMPLING 5
-#define PSK48_TXF_NUMSAMPLES 16
-
-#define PSK48_SAMPLERATE 8000
-#define PSK48_CAR_FREQ 2000
-#define PSK48_PSK_LEN 5
-#define PSK48_RXF_LEN 64
-#define PSK48_PHASEINC (0x10000*PSK48_CAR_FREQ/PSK48_SAMPLERATE)
-#define PSK48_SPHASEINC (0x10000/(2*PSK48_PSK_LEN))
-
-static const short psk48_tx_table[PSK48_TXF_OVERSAMPLING*PSK48_TXF_NUMSAMPLES*8*2] = {
- -12, -8, 0, 8, 12, 8, 0, -8,
- 0, -8, -12, -8, 0, 8, 12, 8,
- -20, -14, 0, 14, 20, 14, 0, -14,
- 0, -14, -20, -14, 0, 14, 20, 14,
- -45, -32, 0, 32, 45, 32, 0, -32,
- 0, -32, -45, -32, 0, 32, 45, 32,
- -92, -65, 0, 65, 92, 65, 0, -65,
- 0, -65, -92, -65, 0, 65, 92, 65,
- -172, -122, 0, 122, 172, 122, 0, -122,
- 0, -122, -172, -122, 0, 122, 172, 122,
- -307, -217, 0, 217, 307, 217, 0, -217,
- 0, -217, -307, -217, 0, 217, 307, 217,
- -564, -399, 0, 399, 564, 399, 0, -399,
- 0, -399, -564, -399, 0, 399, 564, 399,
- -1322, -935, 0, 935, 1322, 935, 0, -935,
- 0, -935, -1322, -935, 0, 935, 1322, 935,
- 12256, 8666, 0, -8666, -12256, -8666, 0, 8666,
- 0, 8666, 12256, 8666, 0, -8666, -12256, -8666,
- 1066, 754, 0, -754, -1066, -754, 0, 754,
- 0, 754, 1066, 754, 0, -754, -1066, -754,
- 495, 350, 0, -350, -495, -350, 0, 350,
- 0, 350, 495, 350, 0, -350, -495, -350,
- 273, 193, 0, -193, -273, -193, 0, 193,
- 0, 193, 273, 193, 0, -193, -273, -193,
- 153, 108, 0, -108, -153, -108, 0, 108,
- 0, 108, 153, 108, 0, -108, -153, -108,
- 81, 57, 0, -57, -81, -57, 0, 57,
- 0, 57, 81, 57, 0, -57, -81, -57,
- 38, 27, 0, -27, -38, -27, 0, 27,
- 0, 27, 38, 27, 0, -27, -38, -27,
- 17, 12, 0, -12, -17, -12, 0, 12,
- 0, 12, 17, 12, 0, -12, -17, -12,
- -20, -14, 0, 14, 20, 14, 0, -14,
- 0, -14, -20, -14, 0, 14, 20, 14,
- -38, -27, 0, 27, 38, 27, 0, -27,
- 0, -27, -38, -27, 0, 27, 38, 27,
- -85, -60, 0, 60, 85, 60, 0, -60,
- 0, -60, -85, -60, 0, 60, 85, 60,
- -170, -120, 0, 120, 170, 120, 0, -120,
- 0, -120, -170, -120, 0, 120, 170, 120,
- -314, -222, 0, 222, 314, 222, 0, -222,
- 0, -222, -314, -222, 0, 222, 314, 222,
- -557, -394, 0, 394, 557, 394, 0, -394,
- 0, -394, -557, -394, 0, 394, 557, 394,
- -1048, -741, 0, 741, 1048, 741, 0, -741,
- 0, -741, -1048, -741, 0, 741, 1048, 741,
- -2783, -1968, 0, 1968, 2783, 1968, 0, -1968,
- 0, -1968, -2783, -1968, 0, 1968, 2783, 1968,
- 6591, 4660, 0, -4660, -6591, -4660, 0, 4660,
- 0, 4660, 6591, 4660, 0, -4660, -6591, -4660,
- 1434, 1014, 0, -1014, -1434, -1014, 0, 1014,
- 0, 1014, 1434, 1014, 0, -1014, -1434, -1014,
- 707, 500, 0, -500, -707, -500, 0, 500,
- 0, 500, 707, 500, 0, -500, -707, -500,
- 395, 279, 0, -279, -395, -279, 0, 279,
- 0, 279, 395, 279, 0, -279, -395, -279,
- 219, 155, 0, -155, -219, -155, 0, 155,
- 0, 155, 219, 155, 0, -155, -219, -155,
- 114, 80, 0, -80, -114, -80, 0, 80,
- 0, 80, 114, 80, 0, -80, -114, -80,
- 53, 37, 0, -37, -53, -37, 0, 37,
- 0, 37, 53, 37, 0, -37, -53, -37,
- 25, 17, 0, -17, -25, -17, 0, 17,
- 0, 17, 25, 17, 0, -17, -25, -17,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 25, 17, 0, -17, -25, -17, 0, 17,
- 0, 17, 25, 17, 0, -17, -25, -17,
- 53, 37, 0, -37, -53, -37, 0, 37,
- 0, 37, 53, 37, 0, -37, -53, -37,
- 114, 80, 0, -80, -114, -80, 0, 80,
- 0, 80, 114, 80, 0, -80, -114, -80,
- 219, 155, 0, -155, -219, -155, 0, 155,
- 0, 155, 219, 155, 0, -155, -219, -155,
- 395, 279, 0, -279, -395, -279, 0, 279,
- 0, 279, 395, 279, 0, -279, -395, -279,
- 707, 500, 0, -500, -707, -500, 0, 500,
- 0, 500, 707, 500, 0, -500, -707, -500,
- 1434, 1014, 0, -1014, -1434, -1014, 0, 1014,
- 0, 1014, 1434, 1014, 0, -1014, -1434, -1014,
- 6591, 4660, 0, -4660, -6591, -4660, 0, 4660,
- 0, 4660, 6591, 4660, 0, -4660, -6591, -4660,
- -2783, -1968, 0, 1968, 2783, 1968, 0, -1968,
- 0, -1968, -2783, -1968, 0, 1968, 2783, 1968,
- -1048, -741, 0, 741, 1048, 741, 0, -741,
- 0, -741, -1048, -741, 0, 741, 1048, 741,
- -557, -394, 0, 394, 557, 394, 0, -394,
- 0, -394, -557, -394, 0, 394, 557, 394,
- -314, -222, 0, 222, 314, 222, 0, -222,
- 0, -222, -314, -222, 0, 222, 314, 222,
- -170, -120, 0, 120, 170, 120, 0, -120,
- 0, -120, -170, -120, 0, 120, 170, 120,
- -85, -60, 0, 60, 85, 60, 0, -60,
- 0, -60, -85, -60, 0, 60, 85, 60,
- -38, -27, 0, 27, 38, 27, 0, -27,
- 0, -27, -38, -27, 0, 27, 38, 27,
- -20, -14, 0, 14, 20, 14, 0, -14,
- 0, -14, -20, -14, 0, 14, 20, 14,
- 17, 12, 0, -12, -17, -12, 0, 12,
- 0, 12, 17, 12, 0, -12, -17, -12,
- 38, 27, 0, -27, -38, -27, 0, 27,
- 0, 27, 38, 27, 0, -27, -38, -27,
- 81, 57, 0, -57, -81, -57, 0, 57,
- 0, 57, 81, 57, 0, -57, -81, -57,
- 153, 108, 0, -108, -153, -108, 0, 108,
- 0, 108, 153, 108, 0, -108, -153, -108,
- 273, 193, 0, -193, -273, -193, 0, 193,
- 0, 193, 273, 193, 0, -193, -273, -193,
- 495, 350, 0, -350, -495, -350, 0, 350,
- 0, 350, 495, 350, 0, -350, -495, -350,
- 1066, 754, 0, -754, -1066, -754, 0, 754,
- 0, 754, 1066, 754, 0, -754, -1066, -754,
- 12256, 8666, 0, -8666, -12256, -8666, 0, 8666,
- 0, 8666, 12256, 8666, 0, -8666, -12256, -8666,
- -1322, -935, 0, 935, 1322, 935, 0, -935,
- 0, -935, -1322, -935, 0, 935, 1322, 935,
- -564, -399, 0, 399, 564, 399, 0, -399,
- 0, -399, -564, -399, 0, 399, 564, 399,
- -307, -217, 0, 217, 307, 217, 0, -217,
- 0, -217, -307, -217, 0, 217, 307, 217,
- -172, -122, 0, 122, 172, 122, 0, -122,
- 0, -122, -172, -122, 0, 122, 172, 122,
- -92, -65, 0, 65, 92, 65, 0, -65,
- 0, -65, -92, -65, 0, 65, 92, 65,
- -45, -32, 0, 32, 45, 32, 0, -32,
- 0, -32, -45, -32, 0, 32, 45, 32,
- -20, -14, 0, 14, 20, 14, 0, -14,
- 0, -14, -20, -14, 0, 14, 20, 14,
- -12, -8, 0, 8, 12, 8, 0, -8,
- 0, -8, -12, -8, 0, 8, 12, 8
-};
-
-static const short psk48_rx_coeff[PSK48_RXF_LEN] = {
- -7, 11, 28, 35, 24, -6, -48, -79,
- -76, -22, 68, 157, 186, 114, -53, -250,
- -370, -315, -58, 318, 636, 694, 371, -281,
- -1014, -1444, -1200, -86, 1793, 4033, 6035, 7215,
- 7215, 6035, 4033, 1793, -86, -1200, -1444, -1014,
- -281, 371, 694, 636, 318, -58, -315, -370,
- -250, -53, 114, 186, 157, 68, -22, -76,
- -79, -48, -6, 24, 35, 28, 11, -7
-};
-
-
-/*
- * more accurate cosine table
- */
-
-static const short costab[256] = {
- 32767, 32757, 32727, 32678, 32609, 32520, 32412, 32284,
- 32137, 31970, 31785, 31580, 31356, 31113, 30851, 30571,
- 30272, 29955, 29621, 29268, 28897, 28510, 28105, 27683,
- 27244, 26789, 26318, 25831, 25329, 24811, 24278, 23731,
- 23169, 22594, 22004, 21402, 20787, 20159, 19519, 18867,
- 18204, 17530, 16845, 16150, 15446, 14732, 14009, 13278,
- 12539, 11792, 11038, 10278, 9511, 8739, 7961, 7179,
- 6392, 5601, 4807, 4011, 3211, 2410, 1607, 804,
- 0, -804, -1607, -2410, -3211, -4011, -4807, -5601,
- -6392, -7179, -7961, -8739, -9511, -10278, -11038, -11792,
- -12539, -13278, -14009, -14732, -15446, -16150, -16845, -17530,
- -18204, -18867, -19519, -20159, -20787, -21402, -22004, -22594,
- -23169, -23731, -24278, -24811, -25329, -25831, -26318, -26789,
- -27244, -27683, -28105, -28510, -28897, -29268, -29621, -29955,
- -30272, -30571, -30851, -31113, -31356, -31580, -31785, -31970,
- -32137, -32284, -32412, -32520, -32609, -32678, -32727, -32757,
- -32767, -32757, -32727, -32678, -32609, -32520, -32412, -32284,
- -32137, -31970, -31785, -31580, -31356, -31113, -30851, -30571,
- -30272, -29955, -29621, -29268, -28897, -28510, -28105, -27683,
- -27244, -26789, -26318, -25831, -25329, -24811, -24278, -23731,
- -23169, -22594, -22004, -21402, -20787, -20159, -19519, -18867,
- -18204, -17530, -16845, -16150, -15446, -14732, -14009, -13278,
- -12539, -11792, -11038, -10278, -9511, -8739, -7961, -7179,
- -6392, -5601, -4807, -4011, -3211, -2410, -1607, -804,
- 0, 804, 1607, 2410, 3211, 4011, 4807, 5601,
- 6392, 7179, 7961, 8739, 9511, 10278, 11038, 11792,
- 12539, 13278, 14009, 14732, 15446, 16150, 16845, 17530,
- 18204, 18867, 19519, 20159, 20787, 21402, 22004, 22594,
- 23169, 23731, 24278, 24811, 25329, 25831, 26318, 26789,
- 27244, 27683, 28105, 28510, 28897, 29268, 29621, 29955,
- 30272, 30571, 30851, 31113, 31356, 31580, 31785, 31970,
- 32137, 32284, 32412, 32520, 32609, 32678, 32727, 32757
-};
-
-#define COS(x) costab[((x)>>8)&0xff]
-#define SIN(x) COS((x)+0xc000)
-
-
-/*
- * arctan table (indexed by i/q; should really be indexed by i/(i+q)
- */
-#define ATAN_TABLEN 1024
-
-static const unsigned short atan_tab[ATAN_TABLEN+2] = {
- 0, 10, 20, 30, 40, 50, 61, 71,
- 81, 91, 101, 112, 122, 132, 142, 152,
- 162, 173, 183, 193, 203, 213, 224, 234,
- 244, 254, 264, 274, 285, 295, 305, 315,
- 325, 336, 346, 356, 366, 376, 386, 397,
- 407, 417, 427, 437, 447, 458, 468, 478,
- 488, 498, 508, 519, 529, 539, 549, 559,
- 569, 579, 590, 600, 610, 620, 630, 640,
- 651, 661, 671, 681, 691, 701, 711, 722,
- 732, 742, 752, 762, 772, 782, 792, 803,
- 813, 823, 833, 843, 853, 863, 873, 884,
- 894, 904, 914, 924, 934, 944, 954, 964,
- 974, 985, 995, 1005, 1015, 1025, 1035, 1045,
- 1055, 1065, 1075, 1085, 1096, 1106, 1116, 1126,
- 1136, 1146, 1156, 1166, 1176, 1186, 1196, 1206,
- 1216, 1226, 1236, 1246, 1256, 1266, 1277, 1287,
- 1297, 1307, 1317, 1327, 1337, 1347, 1357, 1367,
- 1377, 1387, 1397, 1407, 1417, 1427, 1437, 1447,
- 1457, 1467, 1477, 1487, 1497, 1507, 1517, 1527,
- 1537, 1547, 1556, 1566, 1576, 1586, 1596, 1606,
- 1616, 1626, 1636, 1646, 1656, 1666, 1676, 1686,
- 1696, 1706, 1715, 1725, 1735, 1745, 1755, 1765,
- 1775, 1785, 1795, 1805, 1814, 1824, 1834, 1844,
- 1854, 1864, 1874, 1884, 1893, 1903, 1913, 1923,
- 1933, 1943, 1952, 1962, 1972, 1982, 1992, 2002,
- 2011, 2021, 2031, 2041, 2051, 2060, 2070, 2080,
- 2090, 2100, 2109, 2119, 2129, 2139, 2148, 2158,
- 2168, 2178, 2187, 2197, 2207, 2217, 2226, 2236,
- 2246, 2255, 2265, 2275, 2285, 2294, 2304, 2314,
- 2323, 2333, 2343, 2352, 2362, 2372, 2381, 2391,
- 2401, 2410, 2420, 2430, 2439, 2449, 2459, 2468,
- 2478, 2488, 2497, 2507, 2516, 2526, 2536, 2545,
- 2555, 2564, 2574, 2583, 2593, 2603, 2612, 2622,
- 2631, 2641, 2650, 2660, 2669, 2679, 2688, 2698,
- 2708, 2717, 2727, 2736, 2746, 2755, 2765, 2774,
- 2784, 2793, 2802, 2812, 2821, 2831, 2840, 2850,
- 2859, 2869, 2878, 2887, 2897, 2906, 2916, 2925,
- 2935, 2944, 2953, 2963, 2972, 2981, 2991, 3000,
- 3010, 3019, 3028, 3038, 3047, 3056, 3066, 3075,
- 3084, 3094, 3103, 3112, 3122, 3131, 3140, 3149,
- 3159, 3168, 3177, 3187, 3196, 3205, 3214, 3224,
- 3233, 3242, 3251, 3260, 3270, 3279, 3288, 3297,
- 3307, 3316, 3325, 3334, 3343, 3352, 3362, 3371,
- 3380, 3389, 3398, 3407, 3416, 3426, 3435, 3444,
- 3453, 3462, 3471, 3480, 3489, 3498, 3508, 3517,
- 3526, 3535, 3544, 3553, 3562, 3571, 3580, 3589,
- 3598, 3607, 3616, 3625, 3634, 3643, 3652, 3661,
- 3670, 3679, 3688, 3697, 3706, 3715, 3724, 3733,
- 3742, 3751, 3759, 3768, 3777, 3786, 3795, 3804,
- 3813, 3822, 3831, 3839, 3848, 3857, 3866, 3875,
- 3884, 3893, 3901, 3910, 3919, 3928, 3937, 3945,
- 3954, 3963, 3972, 3981, 3989, 3998, 4007, 4016,
- 4024, 4033, 4042, 4051, 4059, 4068, 4077, 4085,
- 4094, 4103, 4112, 4120, 4129, 4138, 4146, 4155,
- 4164, 4172, 4181, 4189, 4198, 4207, 4215, 4224,
- 4233, 4241, 4250, 4258, 4267, 4275, 4284, 4293,
- 4301, 4310, 4318, 4327, 4335, 4344, 4352, 4361,
- 4369, 4378, 4386, 4395, 4403, 4412, 4420, 4429,
- 4437, 4446, 4454, 4462, 4471, 4479, 4488, 4496,
- 4505, 4513, 4521, 4530, 4538, 4546, 4555, 4563,
- 4572, 4580, 4588, 4597, 4605, 4613, 4622, 4630,
- 4638, 4646, 4655, 4663, 4671, 4680, 4688, 4696,
- 4704, 4713, 4721, 4729, 4737, 4745, 4754, 4762,
- 4770, 4778, 4787, 4795, 4803, 4811, 4819, 4827,
- 4836, 4844, 4852, 4860, 4868, 4876, 4884, 4892,
- 4901, 4909, 4917, 4925, 4933, 4941, 4949, 4957,
- 4965, 4973, 4981, 4989, 4997, 5005, 5013, 5021,
- 5029, 5037, 5045, 5053, 5061, 5069, 5077, 5085,
- 5093, 5101, 5109, 5117, 5125, 5133, 5141, 5148,
- 5156, 5164, 5172, 5180, 5188, 5196, 5204, 5211,
- 5219, 5227, 5235, 5243, 5251, 5258, 5266, 5274,
- 5282, 5290, 5297, 5305, 5313, 5321, 5328, 5336,
- 5344, 5352, 5359, 5367, 5375, 5383, 5390, 5398,
- 5406, 5413, 5421, 5429, 5436, 5444, 5452, 5459,
- 5467, 5475, 5482, 5490, 5497, 5505, 5513, 5520,
- 5528, 5535, 5543, 5550, 5558, 5566, 5573, 5581,
- 5588, 5596, 5603, 5611, 5618, 5626, 5633, 5641,
- 5648, 5656, 5663, 5671, 5678, 5686, 5693, 5700,
- 5708, 5715, 5723, 5730, 5738, 5745, 5752, 5760,
- 5767, 5774, 5782, 5789, 5797, 5804, 5811, 5819,
- 5826, 5833, 5841, 5848, 5855, 5862, 5870, 5877,
- 5884, 5892, 5899, 5906, 5913, 5921, 5928, 5935,
- 5942, 5949, 5957, 5964, 5971, 5978, 5985, 5993,
- 6000, 6007, 6014, 6021, 6028, 6036, 6043, 6050,
- 6057, 6064, 6071, 6078, 6085, 6093, 6100, 6107,
- 6114, 6121, 6128, 6135, 6142, 6149, 6156, 6163,
- 6170, 6177, 6184, 6191, 6198, 6205, 6212, 6219,
- 6226, 6233, 6240, 6247, 6254, 6261, 6268, 6275,
- 6282, 6288, 6295, 6302, 6309, 6316, 6323, 6330,
- 6337, 6344, 6350, 6357, 6364, 6371, 6378, 6385,
- 6391, 6398, 6405, 6412, 6419, 6425, 6432, 6439,
- 6446, 6453, 6459, 6466, 6473, 6480, 6486, 6493,
- 6500, 6506, 6513, 6520, 6527, 6533, 6540, 6547,
- 6553, 6560, 6567, 6573, 6580, 6586, 6593, 6600,
- 6606, 6613, 6620, 6626, 6633, 6639, 6646, 6653,
- 6659, 6666, 6672, 6679, 6685, 6692, 6698, 6705,
- 6711, 6718, 6724, 6731, 6737, 6744, 6750, 6757,
- 6763, 6770, 6776, 6783, 6789, 6796, 6802, 6809,
- 6815, 6821, 6828, 6834, 6841, 6847, 6853, 6860,
- 6866, 6873, 6879, 6885, 6892, 6898, 6904, 6911,
- 6917, 6923, 6930, 6936, 6942, 6949, 6955, 6961,
- 6967, 6974, 6980, 6986, 6992, 6999, 7005, 7011,
- 7017, 7024, 7030, 7036, 7042, 7048, 7055, 7061,
- 7067, 7073, 7079, 7086, 7092, 7098, 7104, 7110,
- 7116, 7122, 7129, 7135, 7141, 7147, 7153, 7159,
- 7165, 7171, 7177, 7183, 7190, 7196, 7202, 7208,
- 7214, 7220, 7226, 7232, 7238, 7244, 7250, 7256,
- 7262, 7268, 7274, 7280, 7286, 7292, 7298, 7304,
- 7310, 7316, 7322, 7328, 7333, 7339, 7345, 7351,
- 7357, 7363, 7369, 7375, 7381, 7387, 7392, 7398,
- 7404, 7410, 7416, 7422, 7428, 7433, 7439, 7445,
- 7451, 7457, 7462, 7468, 7474, 7480, 7486, 7491,
- 7497, 7503, 7509, 7514, 7520, 7526, 7532, 7537,
- 7543, 7549, 7555, 7560, 7566, 7572, 7577, 7583,
- 7589, 7594, 7600, 7606, 7611, 7617, 7623, 7628,
- 7634, 7640, 7645, 7651, 7657, 7662, 7668, 7673,
- 7679, 7685, 7690, 7696, 7701, 7707, 7712, 7718,
- 7724, 7729, 7735, 7740, 7746, 7751, 7757, 7762,
- 7768, 7773, 7779, 7784, 7790, 7795, 7801, 7806,
- 7812, 7817, 7823, 7828, 7833, 7839, 7844, 7850,
- 7855, 7861, 7866, 7871, 7877, 7882, 7888, 7893,
- 7898, 7904, 7909, 7914, 7920, 7925, 7931, 7936,
- 7941, 7947, 7952, 7957, 7963, 7968, 7973, 7978,
- 7984, 7989, 7994, 8000, 8005, 8010, 8015, 8021,
- 8026, 8031, 8036, 8042, 8047, 8052, 8057, 8063,
- 8068, 8073, 8078, 8083, 8089, 8094, 8099, 8104,
- 8109, 8115, 8120, 8125, 8130, 8135, 8140, 8145,
- 8151, 8156, 8161, 8166, 8171, 8176, 8181, 8186,
- 8192, 8192
-};
-
}
#ifndef MODULE
-static int via_rhine_probe(struct device *dev)
+int via_rhine_probe(struct device *dev)
{
- printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
return pci_etherdev_probe(dev, pci_tbl);
}
#endif
struct device *dev, long ioaddr, int irq,
int chip_id, int card_idx)
{
+ static int did_version = 0; /* Already printed version info */
struct netdev_private *np;
int i, option = card_idx < MAX_UNITS ? options[card_idx] : 0;
+ if (debug > 0 && did_version++ == 0)
+ printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
+
dev = init_etherdev(dev, 0);
printk(KERN_INFO "%s: %s at 0x%lx, ",
DEVICE( OPTIBASE, OPTIBASE_VPLEX, "VideoPlex"),
DEVICE( OPTIBASE, OPTIBASE_VPLEXCC,"VideoPlex CC"),
DEVICE( OPTIBASE, OPTIBASE_VQUEST,"VideoQuest"),
+ DEVICE( ASIX, ASIX_88140, "88140"),
DEVICE( SATSAGEM, SATSAGEM_PCR2101,"PCR2101 DVB receiver"),
DEVICE( SATSAGEM, SATSAGEM_TELSATTURBO,"Telsat Turbo DVB"),
DEVICE( ENSONIQ, ENSONIQ_AUDIOPCI,"AudioPCI"),
case PCI_VENDOR_ID_ADAPTEC2: return "Adaptec";
case PCI_VENDOR_ID_ATRONICS: return "Atronics";
case PCI_VENDOR_ID_ARK: return "ARK Logic";
+ case PCI_VENDOR_ID_ASIX: return "ASIX";
default: return "Unknown vendor";
}
}
#include "hosts.h"
#include "aic7xxx.h"
-#include "aic7xxx/bsd_q.h"
#include "aic7xxx/sequencer.h"
#include "aic7xxx/scsi_message.h"
#include "aic7xxx_reg.h"
0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
-#define AIC7XXX_C_VERSION "5.1.0"
+#define AIC7XXX_C_VERSION "5.1.2"
#define NUMBER(arr) (sizeof(arr) / sizeof(arr[0]))
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
(((aic_inb(p, SEQADDR1) << 8) & 0x100) | aic_inb(p, SEQADDR0)));
if (aic7xxx_panic_on_abort)
aic7xxx_panic_abort(p, NULL);
+#ifdef CONFIG_PCI
if (errno & PCIERRSTAT)
aic7xxx_pci_intr(p);
+#endif
if (errno & (SQPARERR | ILLOPCODE | ILLSADDR))
{
sti();
+++ /dev/null
-/*
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * 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 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)queue.h 8.5 (Berkeley) 8/20/94
- * $Id: queue.h,v 1.21 1998/05/12 03:55:25 gibbs Exp $
- */
-
-#ifndef _SYS_QUEUE_H_
-#define _SYS_QUEUE_H_
-
-/*
- * This file defines five types of data structures: singly-linked lists,
- * slingly-linked tail queues, lists, tail queues, and circular queues.
- *
- * A singly-linked list is headed by a single forward pointer. The elements
- * are singly linked for minimum space and pointer manipulation overhead at
- * the expense of O(n) removal for arbitrary elements. New elements can be
- * added to the list after an existing element or at the head of the list.
- * Elements being removed from the head of the list should use the explicit
- * macro for this purpose for optimum efficiency. A singly-linked list may
- * only be traversed in the forward direction. Singly-linked lists are ideal
- * for applications with large datasets and few or no removals or for
- * implementing a LIFO queue.
- *
- * A singly-linked tail queue is headed by a pair of pointers, one to the
- * head of the list and the other to the tail of the list. The elements are
- * singly linked for minimum space and pointer manipulation overhead at the
- * expense of O(n) removal for arbitrary elements. New elements can be added
- * to the list after an existing element, at the head of the list, or at the
- * end of the list. Elements being removed from the head of the tail queue
- * should use the explicit macro for this purpose for optimum efficiency.
- * A singly-linked tail queue may only be traversed in the forward direction.
- * Singly-linked tail queues are ideal for applications with large datasets
- * and few or no removals or for implementing a FIFO queue.
- *
- * A list is headed by a single forward pointer (or an array of forward
- * pointers for a hash table header). The elements are doubly linked
- * so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before
- * or after an existing element or at the head of the list. A list
- * may only be traversed in the forward direction.
- *
- * A tail queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or
- * after an existing element, at the head of the list, or at the end of
- * the list. A tail queue may only be traversed in the forward direction.
- *
- * A circle queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or after
- * an existing element, at the head of the list, or at the end of the list.
- * A circle queue may be traversed in either direction, but has a more
- * complex end of list detection.
- *
- * For details on the use of these macros, see the queue(3) manual page.
- *
- *
- * SLIST LIST STAILQ TAILQ CIRCLEQ
- * _HEAD + + + + +
- * _ENTRY + + + + +
- * _INIT + + + + +
- * _EMPTY + + + + +
- * _FIRST + + - + +
- * _NEXT + + - + +
- * _PREV - - - + +
- * _LAST - - - + +
- * _FOREACH + + - + -
- * _INSERT_HEAD + + + + +
- * _INSERT_BEFORE - + - + +
- * _INSERT_AFTER + + + + +
- * _INSERT_TAIL - - + + +
- * _REMOVE_HEAD + - + - -
- * _REMOVE + + + + +
- *
- */
-
-/*
- * Singly-linked List definitions.
- */
-#define SLIST_HEAD(name, type) \
-struct name { \
- struct type *slh_first; /* first element */ \
-}
-
-#define SLIST_ENTRY(type) \
-struct { \
- struct type *sle_next; /* next element */ \
-}
-
-/*
- * Singly-linked List functions.
- */
-#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
-
-#define SLIST_FIRST(head) ((head)->slh_first)
-
-#define SLIST_FOREACH(var, head, field) \
- for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
-
-#define SLIST_INIT(head) { \
- (head)->slh_first = NULL; \
-}
-
-#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
- (elm)->field.sle_next = (slistelm)->field.sle_next; \
- (slistelm)->field.sle_next = (elm); \
-} while (0)
-
-#define SLIST_INSERT_HEAD(head, elm, field) do { \
- (elm)->field.sle_next = (head)->slh_first; \
- (head)->slh_first = (elm); \
-} while (0)
-
-#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
-
-#define SLIST_REMOVE_HEAD(head, field) do { \
- (head)->slh_first = (head)->slh_first->field.sle_next; \
-} while (0)
-
-#define SLIST_REMOVE(head, elm, type, field) do { \
- if ((head)->slh_first == (elm)) { \
- SLIST_REMOVE_HEAD((head), field); \
- } \
- else { \
- struct type *curelm = (head)->slh_first; \
- while( curelm->field.sle_next != (elm) ) \
- curelm = curelm->field.sle_next; \
- curelm->field.sle_next = \
- curelm->field.sle_next->field.sle_next; \
- } \
-} while (0)
-
-/*
- * Singly-linked Tail queue definitions.
- */
-#define STAILQ_HEAD(name, type) \
-struct name { \
- struct type *stqh_first;/* first element */ \
- struct type **stqh_last;/* addr of last next element */ \
-}
-
-#define STAILQ_ENTRY(type) \
-struct { \
- struct type *stqe_next; /* next element */ \
-}
-
-/*
- * Singly-linked Tail queue functions.
- */
-#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
-
-#define STAILQ_INIT(head) do { \
- (head)->stqh_first = NULL; \
- (head)->stqh_last = &(head)->stqh_first; \
-} while (0)
-
-#define STAILQ_FIRST(head) ((head)->stqh_first)
-#define STAILQ_LAST(head) (*(head)->stqh_last)
-
-#define STAILQ_INSERT_HEAD(head, elm, field) do { \
- if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
- (head)->stqh_last = &(elm)->field.stqe_next; \
- (head)->stqh_first = (elm); \
-} while (0)
-
-#define STAILQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.stqe_next = NULL; \
- *(head)->stqh_last = (elm); \
- (head)->stqh_last = &(elm)->field.stqe_next; \
-} while (0)
-
-#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
- if (((elm)->field.stqe_next = (tqelm)->field.stqe_next) == NULL)\
- (head)->stqh_last = &(elm)->field.stqe_next; \
- (tqelm)->field.stqe_next = (elm); \
-} while (0)
-
-#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
-
-#define STAILQ_REMOVE_HEAD(head, field) do { \
- if (((head)->stqh_first = \
- (head)->stqh_first->field.stqe_next) == NULL) \
- (head)->stqh_last = &(head)->stqh_first; \
-} while (0)
-
-#define STAILQ_REMOVE(head, elm, type, field) do { \
- if ((head)->stqh_first == (elm)) { \
- STAILQ_REMOVE_HEAD(head, field); \
- } \
- else { \
- struct type *curelm = (head)->stqh_first; \
- while( curelm->field.stqe_next != (elm) ) \
- curelm = curelm->field.stqe_next; \
- if((curelm->field.stqe_next = \
- curelm->field.stqe_next->field.stqe_next) == NULL) \
- (head)->stqh_last = &(curelm)->field.stqe_next; \
- } \
-} while (0)
-
-/*
- * List definitions.
- */
-
-#define LIST_ENTRY(type) \
-struct { \
- struct type *le_next; /* next element */ \
- struct type **le_prev; /* address of previous next element */ \
-}
-
-/*
- * List functions.
- */
-
-#define LIST_EMPTY(head) ((head)->lh_first == NULL)
-
-#define LIST_FIRST(head) ((head)->lh_first)
-
-#define LIST_FOREACH(var, head, field) \
- for((var) = (head)->lh_first; (var); (var) = (var)->field.le_next)
-
-#define LIST_INIT(head) do { \
- (head)->lh_first = NULL; \
-} while (0)
-
-#define LIST_INSERT_AFTER(listelm, elm, field) do { \
- if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
- (listelm)->field.le_next->field.le_prev = \
- &(elm)->field.le_next; \
- (listelm)->field.le_next = (elm); \
- (elm)->field.le_prev = &(listelm)->field.le_next; \
-} while (0)
-
-#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
- (elm)->field.le_prev = (listelm)->field.le_prev; \
- (elm)->field.le_next = (listelm); \
- *(listelm)->field.le_prev = (elm); \
- (listelm)->field.le_prev = &(elm)->field.le_next; \
-} while (0)
-
-#define LIST_INSERT_HEAD(head, elm, field) do { \
- if (((elm)->field.le_next = (head)->lh_first) != NULL) \
- (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
- (head)->lh_first = (elm); \
- (elm)->field.le_prev = &(head)->lh_first; \
-} while (0)
-
-#define LIST_NEXT(elm, field) ((elm)->field.le_next)
-
-#define LIST_REMOVE(elm, field) do { \
- if ((elm)->field.le_next != NULL) \
- (elm)->field.le_next->field.le_prev = \
- (elm)->field.le_prev; \
- *(elm)->field.le_prev = (elm)->field.le_next; \
-} while (0)
-
-/*
- * Tail queue definitions.
- */
-#define TAILQ_HEAD(name, type) \
-struct name { \
- struct type *tqh_first; /* first element */ \
- struct type **tqh_last; /* addr of last next element */ \
-}
-
-#define TAILQ_HEAD_INITIALIZER(head) \
- { NULL, &(head).tqh_first }
-
-#define TAILQ_ENTRY(type) \
-struct { \
- struct type *tqe_next; /* next element */ \
- struct type **tqe_prev; /* address of previous next element */ \
-}
-
-/*
- * Tail queue functions.
- */
-#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
-
-#define TAILQ_FOREACH(var, head, field) \
- for (var = TAILQ_FIRST(head); var; var = TAILQ_NEXT(var, field))
-
-#define TAILQ_FIRST(head) ((head)->tqh_first)
-
-#define TAILQ_LAST(head, headname) \
- (*(((struct headname *)((head)->tqh_last))->tqh_last))
-
-#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
-
-#define TAILQ_PREV(elm, headname, field) \
- (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
-
-#define TAILQ_INIT(head) do { \
- (head)->tqh_first = NULL; \
- (head)->tqh_last = &(head)->tqh_first; \
-} while (0)
-
-#define TAILQ_INSERT_HEAD(head, elm, field) do { \
- if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
- (head)->tqh_first->field.tqe_prev = \
- &(elm)->field.tqe_next; \
- else \
- (head)->tqh_last = &(elm)->field.tqe_next; \
- (head)->tqh_first = (elm); \
- (elm)->field.tqe_prev = &(head)->tqh_first; \
-} while (0)
-
-#define TAILQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.tqe_next = NULL; \
- (elm)->field.tqe_prev = (head)->tqh_last; \
- *(head)->tqh_last = (elm); \
- (head)->tqh_last = &(elm)->field.tqe_next; \
-} while (0)
-
-#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
- if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
- (elm)->field.tqe_next->field.tqe_prev = \
- &(elm)->field.tqe_next; \
- else \
- (head)->tqh_last = &(elm)->field.tqe_next; \
- (listelm)->field.tqe_next = (elm); \
- (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
-} while (0)
-
-#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
- (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
- (elm)->field.tqe_next = (listelm); \
- *(listelm)->field.tqe_prev = (elm); \
- (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
-} while (0)
-
-#define TAILQ_REMOVE(head, elm, field) do { \
- if (((elm)->field.tqe_next) != NULL) \
- (elm)->field.tqe_next->field.tqe_prev = \
- (elm)->field.tqe_prev; \
- else \
- (head)->tqh_last = (elm)->field.tqe_prev; \
- *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
-} while (0)
-
-/*
- * Circular queue definitions.
- */
-#define CIRCLEQ_HEAD(name, type) \
-struct name { \
- struct type *cqh_first; /* first element */ \
- struct type *cqh_last; /* last element */ \
-}
-
-#define CIRCLEQ_ENTRY(type) \
-struct { \
- struct type *cqe_next; /* next element */ \
- struct type *cqe_prev; /* previous element */ \
-}
-
-/*
- * Circular queue functions.
- */
-#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
-
-#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
-
-#define CIRCLEQ_FOREACH(var, head, field) \
- for((var) = (head)->cqh_first; \
- (var) != (void *)(head); \
- (var) = (var)->field.cqe_next)
-
-#define CIRCLEQ_INIT(head) do { \
- (head)->cqh_first = (void *)(head); \
- (head)->cqh_last = (void *)(head); \
-} while (0)
-
-#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
- (elm)->field.cqe_next = (listelm)->field.cqe_next; \
- (elm)->field.cqe_prev = (listelm); \
- if ((listelm)->field.cqe_next == (void *)(head)) \
- (head)->cqh_last = (elm); \
- else \
- (listelm)->field.cqe_next->field.cqe_prev = (elm); \
- (listelm)->field.cqe_next = (elm); \
-} while (0)
-
-#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
- (elm)->field.cqe_next = (listelm); \
- (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
- if ((listelm)->field.cqe_prev == (void *)(head)) \
- (head)->cqh_first = (elm); \
- else \
- (listelm)->field.cqe_prev->field.cqe_next = (elm); \
- (listelm)->field.cqe_prev = (elm); \
-} while (0)
-
-#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
- (elm)->field.cqe_next = (head)->cqh_first; \
- (elm)->field.cqe_prev = (void *)(head); \
- if ((head)->cqh_last == (void *)(head)) \
- (head)->cqh_last = (elm); \
- else \
- (head)->cqh_first->field.cqe_prev = (elm); \
- (head)->cqh_first = (elm); \
-} while (0)
-
-#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.cqe_next = (void *)(head); \
- (elm)->field.cqe_prev = (head)->cqh_last; \
- if ((head)->cqh_first == (void *)(head)) \
- (head)->cqh_first = (elm); \
- else \
- (head)->cqh_last->field.cqe_next = (elm); \
- (head)->cqh_last = (elm); \
-} while (0)
-
-#define CIRCLEQ_LAST(head) ((head)->cqh_last)
-
-#define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next)
-
-#define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev)
-
-#define CIRCLEQ_REMOVE(head, elm, field) do { \
- if ((elm)->field.cqe_next == (void *)(head)) \
- (head)->cqh_last = (elm)->field.cqe_prev; \
- else \
- (elm)->field.cqe_next->field.cqe_prev = \
- (elm)->field.cqe_prev; \
- if ((elm)->field.cqe_prev == (void *)(head)) \
- (head)->cqh_first = (elm)->field.cqe_next; \
- else \
- (elm)->field.cqe_prev->field.cqe_next = \
- (elm)->field.cqe_next; \
-} while (0)
-
-#ifdef KERNEL
-
-/*
- * XXX insque() and remque() are an old way of handling certain queues.
- * They bogusly assumes that all queue heads look alike.
- */
-
-struct quehead {
- struct quehead *qh_link;
- struct quehead *qh_rlink;
-};
-
-#ifdef __GNUC__
-
-static __inline void
-insque(void *a, void *b)
-{
- struct quehead *element = a, *head = b;
-
- element->qh_link = head->qh_link;
- element->qh_rlink = head;
- head->qh_link = element;
- element->qh_link->qh_rlink = element;
-}
-
-static __inline void
-remque(void *a)
-{
- struct quehead *element = a;
-
- element->qh_link->qh_rlink = element->qh_rlink;
- element->qh_rlink->qh_link = element->qh_link;
- element->qh_rlink = 0;
-}
-
-#else /* !__GNUC__ */
-
-void insque __P((void *a, void *b));
-void remque __P((void *a));
-
-#endif /* __GNUC__ */
-
-#endif /* KERNEL */
-
-#endif /* !_SYS_QUEUE_H_ */
union ins_formats format;
unsigned int srcline;
struct symbol *patch_label;
- STAILQ_ENTRY(instruction) links;
+ struct {
+ struct instruction *stqe_next;
+ } links;
};
#define AIC_OP_OR 0x0
*
* Copyright 1998 American Megatrends 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.
+ *
* Version : 0.92
*
* Description: Linux device driver for AMI MegaRAID controller
-bool 'ProAudioSpectrum 16 support' CONFIG_PAS
-bool 'Sound Blaster (SB, SBPro, SB16, clones) support' CONFIG_SB
-bool 'Generic OPL2/OPL3 FM synthesizer support' CONFIG_ADLIB
-bool 'Gravis Ultrasound support' CONFIG_GUS
-bool 'MPU-401 support (NOT for SB16)' CONFIG_MPU401
-bool '6850 UART Midi support' CONFIG_UART6850
-bool 'PSS (ECHO-ADI2111) support' CONFIG_PSS
-bool '16 bit sampling option of GUS (_NOT_ GUS MAX)' CONFIG_GUS16
-bool 'GUS MAX support' CONFIG_GUSMAX
-bool 'Microsoft Sound System support' CONFIG_MSS
-bool 'Ensoniq SoundScape support' CONFIG_SSCAPE
-bool 'MediaTrix AudioTrix Pro support' CONFIG_TRIX
-bool 'Support for MAD16 and/or Mozart based cards' CONFIG_MAD16
-bool 'Support for Crystal CS4232 based (PnP) cards' CONFIG_CS4232
-bool 'Support for Turtle Beach Wave Front (Maui, Tropez) synthesizers' CONFIG_MAUI
-bool '/dev/dsp and /dev/audio support' CONFIG_AUDIO
-bool 'MIDI interface support' CONFIG_MIDI
-bool 'FM synthesizer (YM3812/OPL-3) support' CONFIG_YM3812
-
-if [ "$CONFIG_SB" = "y" ]; then
-hex 'I/O base for SB Check from manual of the card' SBC_BASE 220
-fi
-
-if [ "$CONFIG_SB" = "y" ]; then
-int 'Sound Blaster IRQ Check from manual of the card' SBC_IRQ 7
-fi
-
-if [ "$CONFIG_SB" = "y" ]; then
-int 'Sound Blaster DMA 0, 1 or 3' SBC_DMA 1
-fi
-
-if [ "$CONFIG_SB" = "y" ]; then
-int 'Sound Blaster 16 bit DMA (_REQUIRED_for SB16, Jazz16, SMW) 5, 6 or 7 (use 1 for 8 bit cards)' SB_DMA2 5
-fi
-
-if [ "$CONFIG_SB" = "y" ]; then
-hex 'MPU401 I/O base of SB16, Jazz16 and ES1688 Check from manual of the card' SB_MPU_BASE 0
-fi
-
-if [ "$CONFIG_SB" = "y" ]; then
-int 'SB MPU401 IRQ (Jazz16, SM Wave and ES1688) Use -1 with SB16' SB_MPU_IRQ -1
-fi
-
-if [ "$CONFIG_PAS" = "y" ]; then
-int 'PAS16 IRQ 3, 4, 5, 7, 9, 10, 11, 12, 14 or 15' PAS_IRQ 10
-fi
-
-if [ "$CONFIG_PAS" = "y" ]; then
-int 'PAS16 DMA 0, 1, 3, 5, 6 or 7' PAS_DMA 3
-fi
-
-if [ "$CONFIG_GUS" = "y" ]; then
-hex 'I/O base for GUS 210, 220, 230, 240, 250 or 260' GUS_BASE 220
-fi
-
-if [ "$CONFIG_GUS" = "y" ]; then
-int 'GUS IRQ 3, 5, 7, 9, 11, 12 or 15' GUS_IRQ 15
-fi
-
-if [ "$CONFIG_GUS" = "y" ]; then
-int 'GUS DMA 1, 3, 5, 6 or 7' GUS_DMA 6
-fi
-
-if [ "$CONFIG_GUS" = "y" ]; then
-int 'Second DMA channel for GUS 1, 3, 5, 6 or 7' GUS_DMA2 -1
-fi
-
-if [ "$CONFIG_GUS16" = "y" ]; then
-hex 'I/O base for the 16 bit daughtercard of GUS 530, 604, E80 or F40' GUS16_BASE 530
-fi
-
-if [ "$CONFIG_GUS16" = "y" ]; then
-int 'GUS 16 bit daughtercard IRQ 3, 4, 5, 7, or 9' GUS16_IRQ 7
-fi
-
-if [ "$CONFIG_GUS16" = "y" ]; then
-int 'GUS DMA 0, 1 or 3' GUS16_DMA 3
-fi
-
-if [ "$CONFIG_MPU401" = "y" ]; then
-hex 'I/O base for MPU401 Check from manual of the card' MPU_BASE 330
-fi
-
-if [ "$CONFIG_MPU401" = "y" ]; then
-int 'MPU401 IRQ Check from manual of the card' MPU_IRQ 9
-fi
-
-if [ "$CONFIG_MAUI" = "y" ]; then
-hex 'I/O base for Maui 210, 230, 260, 290, 300, 320, 338 or 330' MAUI_BASE 330
-fi
-
-if [ "$CONFIG_MAUI" = "y" ]; then
-int 'Maui IRQ 5, 9, 12 or 15' MAUI_IRQ 9
-fi
-
-if [ "$CONFIG_UART6850" = "y" ]; then
-hex 'I/O base for UART 6850 MIDI port (Unknown)' U6850_BASE 0
-fi
-
-if [ "$CONFIG_UART6850" = "y" ]; then
-int 'UART6850 IRQ (Unknown)' U6850_IRQ -1
-fi
-
-if [ "$CONFIG_PSS" = "y" ]; then
-hex 'PSS I/O base 220 or 240' PSS_BASE 220
-fi
-
-if [ "$CONFIG_PSS" = "y" ]; then
-hex 'PSS audio I/O base 530, 604, E80 or F40' PSS_MSS_BASE 530
-fi
-
-if [ "$CONFIG_PSS" = "y" ]; then
-int 'PSS audio IRQ 7, 9, 10 or 11' PSS_MSS_IRQ 11
-fi
-
-if [ "$CONFIG_PSS" = "y" ]; then
-int 'PSS audio DMA 0, 1 or 3' PSS_MSS_DMA 3
-fi
-
-if [ "$CONFIG_PSS" = "y" ]; then
-hex 'PSS MIDI I/O base ' PSS_MPU_BASE 330
-fi
-
-if [ "$CONFIG_PSS" = "y" ]; then
-int 'PSS MIDI IRQ 3, 4, 5, 7 or 9' PSS_MPU_IRQ 9
-fi
-
-if [ "$CONFIG_MSS" = "y" ]; then
-hex 'MSS/WSS I/O base 530, 604, E80 or F40' MSS_BASE 530
-fi
-
-if [ "$CONFIG_MSS" = "y" ]; then
-int 'MSS/WSS IRQ 7, 9, 10 or 11' MSS_IRQ 11
-fi
-
-if [ "$CONFIG_MSS" = "y" ]; then
-int 'MSS/WSS DMA 0, 1 or 3' MSS_DMA 3
-fi
-
-if [ "$CONFIG_SSCAPE" = "y" ]; then
-hex 'SoundScape MIDI I/O base 320, 330, 340 or 350' SSCAPE_BASE 330
-fi
-
-if [ "$CONFIG_SSCAPE" = "y" ]; then
-int 'SoundScape MIDI IRQ ' SSCAPE_IRQ 9
-fi
-
-if [ "$CONFIG_SSCAPE" = "y" ]; then
-int 'SoundScape initialization DMA 0, 1 or 3' SSCAPE_DMA 3
-fi
-
-if [ "$CONFIG_SSCAPE" = "y" ]; then
-hex 'SoundScape audio I/O base 534, 608, E84 or F44' SSCAPE_MSS_BASE 534
-fi
-
-if [ "$CONFIG_SSCAPE" = "y" ]; then
-int 'SoundScape audio IRQ 7, 9, 10 or 11' SSCAPE_MSS_IRQ 11
-fi
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-hex 'AudioTrix audio I/O base 530, 604, E80 or F40' TRIX_BASE 530
-fi
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-int 'AudioTrix audio IRQ 7, 9, 10 or 11' TRIX_IRQ 11
-fi
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-int 'AudioTrix audio DMA 0, 1 or 3' TRIX_DMA 0
-fi
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-int 'AudioTrix second (duplex) DMA 0, 1 or 3' TRIX_DMA2 3
-fi
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-hex 'AudioTrix MIDI I/O base 330, 370, 3B0 or 3F0' TRIX_MPU_BASE 330
-fi
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-int 'AudioTrix MIDI IRQ 3, 4, 5, 7 or 9' TRIX_MPU_IRQ 9
-fi
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-hex 'AudioTrix SB I/O base 220, 210, 230, 240, 250, 260 or 270' TRIX_SB_BASE 220
-fi
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-int 'AudioTrix SB IRQ 3, 4, 5 or 7' TRIX_SB_IRQ 7
-fi
-
-if [ "$CONFIG_TRIX" = "y" ]; then
-int 'AudioTrix SB DMA 1 or 3' TRIX_SB_DMA 1
-fi
-
-if [ "$CONFIG_CS4232" = "y" ]; then
-hex 'CS4232 audio I/O base 530, 604, E80 or F40' CS4232_BASE 530
-fi
-
-if [ "$CONFIG_CS4232" = "y" ]; then
-int 'CS4232 audio IRQ 5, 7, 9, 11, 12 or 15' CS4232_IRQ 11
-fi
-
-if [ "$CONFIG_CS4232" = "y" ]; then
-int 'CS4232 audio DMA 0, 1 or 3' CS4232_DMA 0
-fi
-
-if [ "$CONFIG_CS4232" = "y" ]; then
-int 'CS4232 second (duplex) DMA 0, 1 or 3' CS4232_DMA2 3
-fi
-
-if [ "$CONFIG_CS4232" = "y" ]; then
-hex 'CS4232 MIDI I/O base 330, 370, 3B0 or 3F0' CS4232_MPU_BASE 330
-fi
-
-if [ "$CONFIG_CS4232" = "y" ]; then
-int 'CS4232 MIDI IRQ 5, 7, 9, 11, 12 or 15' CS4232_MPU_IRQ 9
-fi
-
-if [ "$CONFIG_MAD16" = "y" ]; then
-hex 'MAD16 audio I/O base 530, 604, E80 or F40' MAD16_BASE 530
-fi
-
-if [ "$CONFIG_MAD16" = "y" ]; then
-int 'MAD16 audio IRQ 7, 9, 10 or 11' MAD16_IRQ 11
-fi
-
-if [ "$CONFIG_MAD16" = "y" ]; then
-int 'MAD16 audio DMA 0, 1 or 3' MAD16_DMA 3
-fi
-
-if [ "$CONFIG_MAD16" = "y" ]; then
-int 'MAD16 second (duplex) DMA 0, 1 or 3' MAD16_DMA2 0
-fi
-
-if [ "$CONFIG_MAD16" = "y" ]; then
-hex 'MAD16 MIDI I/O base 300, 310, 320 or 330 (0 disables)' MAD16_MPU_BASE 330
-fi
-
-if [ "$CONFIG_MAD16" = "y" ]; then
-int 'MAD16 MIDI IRQ 5, 7, 9 or 10' MAD16_MPU_IRQ 9
-fi
-
-if [ "$CONFIG_AUDIO" = "y" ]; then
-int 'Audio DMA buffer size 4096, 16384, 32768 or 65536' DSP_BUFFSIZE 65536
-fi
#
-$MAKE -C drivers/sound kernelconfig || exit 1
+# Sound driver configuration
+#
+#--------
+# There is another config script which is compatible with rest of
+# the kernel. It can be activated by running 'make mkscript' in this
+# directory. Please note that this is an _experimental_ feature which
+# doesn't work with all cards (PSS, SM Wave, AudioTrix Pro, Maui).
+#--------
+#
+$MAKE -C drivers/sound config || exit 1
+
bool 'Additional low level drivers' CONFIG_LOWLEVEL_SOUND
if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then
#define PCI_DEVICE_ID_OPTIBASE_VPLEXCC 0x2120
#define PCI_DEVICE_ID_OPTIBASE_VQUEST 0x2130
+#define PCI_VENDOR_ID_ASIX 0x125b
+#define PCI_DEVICE_ID_ASIX_88140 0x1400
+
#define PCI_VENDOR_ID_SATSAGEM 0x1267
#define PCI_DEVICE_ID_SATSAGEM_PCR2101 0x5352
#define PCI_DEVICE_ID_SATSAGEM_TELSATTURBO 0x5a4b