diff -ur --new-file old/atm/.kernel new/atm/.kernel --- old/atm/.kernel Wed Aug 21 11:22:21 1996 +++ new/atm/.kernel Sat Nov 16 00:24:00 1996 @@ -1,2 +1,2 @@ # this file is used to control automated generation of differences -2.0.14 +2.0.25 diff -ur --new-file old/atm/CHANGES new/atm/CHANGES --- old/atm/CHANGES Wed Nov 13 23:23:02 1996 +++ new/atm/CHANGES Sat Nov 16 00:08:57 1996 @@ -1,3 +1,37 @@ +Version 0.22 to 0.23 (16-NOV-1996) +==================== + +Bug fixes +--------- + + - fixed stupid typos in atm/lib/atmres.h and an unnecessary dependency on + libresolv.a in atm/lib/Makefile (reported by Gerald Hanusch) + - fixed warning about implicit declaration of function bigphysarea_init in + init/main.c + - I think I fixed the SSCOP VR(MR) problems that were first reported by + Edouard Lamboray in '95, then by Heinz Schuerch, and that finally led to a + total SSCOP breakdown (in 0.22) reported by Gerald Hanusch + +New features +------------ + + - integrated the IDT 77201 (NICStAR) driver by Matt Welsh and Stuart Daniel + . Note that this driver currently only supports + native ATM. + - new throughput and latency benchmark test/window (by Matt Welsh) + +Other changes +------------- + + - upgrade to kernel version 2.0.25 + - changed drivers/atm/eni.c:do_tx:dma to static in order to reduce kernel + stack use (by 480 bytes). Note that this hack may crash systems with more + than one ENI adapter. + - qlib now also complains if changing a field without a fixed list of values + - made a few changes to the native ATM data delivery path to handle some + strangeness required by the IDT driver + + Version 0.21 to 0.22 (13-NOV-1996) ==================== diff -ur --new-file old/atm/README new/atm/README --- old/atm/README Tue Nov 12 17:39:16 1996 +++ new/atm/README Fri Nov 15 20:26:30 1996 @@ -1,4 +1,4 @@ -ATM on Linux, release 0.22 (pre-alpha) by Werner Almesberger, EPFL LRC +ATM on Linux, release 0.23 (pre-alpha) by Werner Almesberger, EPFL LRC ====================================== werner.almesberger@lrc.di.epfl.ch This is experimental software. There are known major bugs and certainly @@ -12,6 +12,7 @@ The following network devices are supported: ATM over TCP pseudo device for "dry runs" Efficient Networks ENI155p-MF/U5 155 Mbps ATM adapter + IDT 77201 (NICStAR) (native ATM only) Rolf Fiedler's TNETA1570 board / UniNET1570 Zeitnet ZN1221/ZN1225 155 Mbps ATM adapter diff -ur --new-file old/atm/USAGE new/atm/USAGE --- old/atm/USAGE Wed Nov 13 23:19:59 1996 +++ new/atm/USAGE Sat Nov 16 00:09:36 1996 @@ -1,4 +1,4 @@ -Usage instructions - ATM on Linux, release 0.22 (pre-alpha) +Usage instructions - ATM on Linux, release 0.23 (pre-alpha) ------------------------------------------------------------- For updates of ATM on Linux, please check the Web page at @@ -18,8 +18,8 @@ - the package itself ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.22.tar.gz - - the Linux kernel, version 2.0.14, e.g. from - ftp://ftp.cs.helsinki.fi/pub/Software/Linux/Kernel/v2.0/linux-2.0.14.tar.gz + - the Linux kernel, version 2.0.25, e.g. from + ftp://ftp.cs.helsinki.fi/pub/Software/Linux/Kernel/v2.0/linux-2.0.25.tar.gz - Perl, version 4 or 5 - if you want memory debugging: MPR version 1.1, e.g. from ftp://sunsite.unc.edu/pub/Linux/devel/lang/c/mpr-1.1.tar.gz @@ -37,7 +37,7 @@ and the kernel source: -tar xfz linux-2.0.14.tar.gz +tar xfz linux-2.0.25.tar.gz Finally, you can extract the ATM-related patches: @@ -54,7 +54,7 @@ atm/ilmid/ ILMI address registration demon: ilmid atm/maint/ ATM maintenance programs: atmaddr, atmdiag, atmdump, atmtcp, sonetdiag, and zntune - atm/test/ Test programs: aping, aread, awrite, br, bw, ttcp + atm/test/ Test programs: aping, aread, awrite, br, bw, ttcp, window atm/ip/ IP over ATM: clip, atmarp atm/arpd/ ATMARP demon: atmarpd atm/led/ LAN Emulation demon: led @@ -89,6 +89,7 @@ Enable usec resolution timestamps (CONFIG_ATM_ZATM_EXACT_TS) Rolfs TI TNETA1570 (CONFIG_ATM_TNETA1570) Enable extended debugging (CONFIG_ATM_TNETA1570_DEBUG) +IDT 77201 (NICStAR) (CONFIG_ATM_NICSTAR) The "MMU hacks" add single-copy support for raw AAL5 on adapters whose driver supports this (currently only the ENI155p). Extended debugging @@ -97,6 +98,9 @@ The TNETA1570 driver is for a board developed by Rolf Fiedler at TU Chemnitz, see also ftp://ftp.infotech.tu-chemnitz.de/pub/linux-atm . + +The IDT 77201 driver currently only supports native ATM, i.e. IP over ATM +or LANE are not possible (and should not be tried). Support for a simple type of serial consoles is automatically added by the ATM patch. If you're using LILO, you can enable it by putting a line like diff -ur --new-file old/atm/VERSION new/atm/VERSION --- old/atm/VERSION Wed Nov 13 23:24:57 1996 +++ new/atm/VERSION Fri Nov 15 23:20:55 1996 @@ -1 +1 @@ -0.22 +0.23 diff -ur --new-file old/atm/atm.patch new/atm/atm.patch --- old/atm/atm.patch Wed Nov 13 23:42:36 1996 +++ new/atm/atm.patch Sat Nov 16 00:36:06 1996 @@ -1,5 +1,5 @@ ---- ref/Makefile Sat Aug 17 20:19:04 1996 -+++ work/Makefile Wed Aug 21 10:55:30 1996 +--- ref/Makefile Wed Oct 30 11:46:07 1996 ++++ work/Makefile Fri Nov 15 19:06:16 1996 @@ -126,6 +126,10 @@ DRIVERS := $(DRIVERS) drivers/net/net.a @@ -19,9 +19,9 @@ \ ls *.o > .allmods; \ echo $$MODULES | tr ' ' '\n' | sort | comm -23 .allmods - > .misc; \ ---- ref/Documentation/Configure.help Wed Aug 7 08:45:41 1996 -+++ work/Documentation/Configure.help Fri Oct 4 14:14:30 1996 -@@ -670,6 +670,14 @@ +--- ref/Documentation/Configure.help Sat Oct 5 10:13:56 1996 ++++ work/Documentation/Configure.help Fri Nov 15 20:52:20 1996 +@@ -674,6 +674,14 @@ say "386" or "486" here even if running on a Pentium or PPro machine. If you don't know what to do, say "386". @@ -36,7 +36,7 @@ Compile the kernel into the ELF object format CONFIG_ELF_KERNEL ELF (Executable and Linkable Format) is a format for libraries and -@@ -1181,6 +1189,111 @@ +@@ -1194,6 +1202,118 @@ with major number 36 and minor number 0 using mknod ("man mknod"), you can read some network related routing information from that file. Everything you write to that file will be discarded. @@ -145,11 +145,18 @@ + using printks, but still has some impact on performance. Note that + extended debugging may create certain race conditions itself. Enable + this ONLY if you suspect problems with the driver. ++ ++IDT 77201 (NICStAR) ++CONFIG_ATM_NICSTAR ++ Driver for the IDT 77201 (NICStAR) ATM adapter. Written by Matt Welsh ++ and Stuart Daniel . Note that this driver ++ currently only works with native ATM (i.e. not with IP over ATM or ++ LANE). SCSI support? CONFIG_SCSI ---- ref/kernel/ksyms.c Thu Jul 18 13:28:48 1996 -+++ work/kernel/ksyms.c Fri Oct 4 14:14:32 1996 +--- ref/kernel/ksyms.c Wed Oct 30 02:42:42 1996 ++++ work/kernel/ksyms.c Fri Nov 15 19:06:20 1996 @@ -63,6 +63,12 @@ #ifdef __SMP__ #include @@ -162,7 +169,7 @@ +#endif extern char *get_options(char *str, int *ints); - extern void set_device_ro(int dev,int flag); + extern void set_device_ro(kdev_t dev,int flag); @@ -77,6 +83,10 @@ extern void hard_reset_now(void); @@ -174,7 +181,7 @@ struct symbol_table symbol_table = { #include #ifdef MODVERSIONS -@@ -138,6 +148,13 @@ +@@ -136,6 +146,13 @@ X(high_memory), X(update_vm_cache), @@ -188,7 +195,7 @@ /* filesystem internal functions */ X(getname), X(putname), -@@ -351,7 +368,16 @@ +@@ -350,7 +367,16 @@ #ifdef CONFIG_BLK_DEV_MD X(disk_name), /* for md.c */ #endif @@ -207,7 +214,7 @@ X(get_write_access), X(put_write_access), --- ref/arch/i386/config.in Mon May 13 06:17:23 1996 -+++ work/arch/i386/config.in Fri Oct 4 14:14:31 1996 ++++ work/arch/i386/config.in Fri Nov 15 19:06:21 1996 @@ -43,6 +43,8 @@ 486 CONFIG_M486 \ Pentium CONFIG_M586 \ @@ -229,7 +236,7 @@ mainmenu_option next_comment --- ref/arch/sparc/config.in Thu Apr 25 12:22:05 1996 -+++ work/arch/sparc/config.in Wed Aug 21 10:55:35 1996 ++++ work/arch/sparc/config.in Fri Nov 15 19:06:21 1996 @@ -100,6 +100,12 @@ endmenu fi @@ -244,7 +251,7 @@ mainmenu_option next_comment --- ref/drivers/Makefile Mon Apr 22 09:59:39 1996 -+++ work/drivers/Makefile Wed Aug 21 10:55:35 1996 ++++ work/drivers/Makefile Fri Nov 15 19:06:21 1996 @@ -9,7 +9,7 @@ SUB_DIRS := block char net #streams @@ -266,9 +273,9 @@ endif ifeq ($(CONFIG_AP1000),y) ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/Config.in Thu Sep 26 18:58:10 1996 -@@ -0,0 +1,22 @@ +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/Config.in Fri Nov 15 20:40:08 1996 +@@ -0,0 +1,23 @@ +# +# ATM device configuration +# @@ -290,9 +297,10 @@ + if [ "$CONFIG_ATM_TNETA1570" = "y" ]; then + bool ' Enable extended debugging' CONFIG_ATM_TNETA1570_DEBUG n + fi ++ tristate 'IDT 77201 (NICStAR)' CONFIG_ATM_NICSTAR y +fi --- ref/net/Config.in Mon Jul 8 09:21:46 1996 -+++ work/net/Config.in Wed Aug 21 10:55:36 1996 ++++ work/net/Config.in Fri Nov 15 19:06:22 1996 @@ -27,4 +27,17 @@ if [ "$CONFIG_NETLINK" = "y" ]; then bool 'Routing messages' CONFIG_RTNETLINK @@ -311,9 +319,9 @@ + bool ' LANE support' CONFIG_ATM_LANE y +fi endmenu ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/Makefile Thu Aug 29 13:50:20 1996 -@@ -0,0 +1,47 @@ +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/Makefile Fri Nov 15 20:39:35 1996 +@@ -0,0 +1,55 @@ +# File: drivers/atm/Makefile +# +# Makefile for the Linux network (ATM) device drivers. @@ -350,6 +358,14 @@ +L_OBJS += fore200.o +endif + ++ifeq ($(CONFIG_ATM_NICSTAR),y) ++L_OBJS += nicstar.o ++else ++ ifeq ($(CONFIG_ATM_NICSTAR),m) ++ M_OBJS += nicstar.o ++ endif ++endif ++ +ifeq ($(CONFIG_ATM_TCP),y) +L_OBJS += atmtcp.o +else @@ -361,9 +377,9 @@ +EXTRA_CFLAGS=-g + +include $(TOPDIR)/Rules.make ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/atmdev_init.c Wed Aug 21 10:55:36 1996 -@@ -0,0 +1,47 @@ +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/atmdev_init.c Fri Nov 15 20:39:03 1996 +@@ -0,0 +1,53 @@ +/* drivers/atm/atmdev_init.c - ATM device driver initialization */ + +/* Written 1995,1996 by Werner Almesberger, EPFL LRC */ @@ -384,6 +400,9 @@ +#ifdef CONFIG_ATM_FORE200 +extern int fore200_detect(void); +#endif ++#ifdef CONFIG_ATM_NICSTAR ++extern int nicstar_detect(void); ++#endif +#ifdef CONFIG_ATM_TCP +extern int atmtcp_init(void); +#endif @@ -406,14 +425,17 @@ +#ifdef CONFIG_ATM_FORE200 + devs += fore200_detect(); +#endif ++#ifdef CONFIG_ATM_NICSTAR ++ devs += nicstar_detect(); ++#endif +#ifdef CONFIG_ATM_TCP + devs += atmtcp_init(); +#endif + return devs; +} ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/atmtcp.c Fri Oct 4 14:02:24 1996 -@@ -0,0 +1,317 @@ +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/atmtcp.c Fri Nov 15 22:00:47 1996 +@@ -0,0 +1,316 @@ +/* drivers/atm/atmtcp.c - ATM over TCP "device" driver */ + +/* Written 1995,1996 by Werner Almesberger, EPFL LRC */ @@ -626,7 +648,6 @@ + skb->atm.timestamp = xtime; + skb->len = ntohs(hdr.length); + skb->free = 1; -+ skb->atm.iovcnt = 0; + pos = skb->data; + for (left = ntohs(hdr.length); left; left -= size) { + size = do_recv(PRIV(dev)->sock,pos,left,0); @@ -731,9 +752,9 @@ +} + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/eni.c Fri Nov 8 16:38:53 1996 -@@ -0,0 +1,1960 @@ +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/eni.c Fri Nov 15 19:06:23 1996 +@@ -0,0 +1,1966 @@ +/* drivers/atm/eni.c - Efficient Networks ENI155P device driver */ + +/* Written 1995,1996 by Werner Almesberger, EPFL LRC */ @@ -1369,14 +1390,14 @@ + + eni_dev = ENI_DEV(dev); + while ((curr = eni_dev->fast)) { -+ EVENT("poll_tx.fast\n",0,0); ++ EVENT("poll_rx.fast\n",0,0); + if (rx_vcc(curr)) return; + eni_dev->fast = ENI_VCC(curr)->next; + ENI_VCC(curr)->next = ENI_VCC_NOS; + ENI_VCC(curr)->servicing--; + } + while ((curr = eni_dev->slow)) { -+ EVENT("poll_tx.slow\n",0,0); ++ EVENT("poll_rx.slow\n",0,0); + if (rx_vcc(curr)) return; + eni_dev->slow = ENI_VCC(curr)->next; + ENI_VCC(curr)->next = ENI_VCC_NOS; @@ -1657,12 +1678,18 @@ + +static enum enq_res do_tx(struct sk_buff *skb) +{ ++ /* @@@ ++ * This static var may break with multiple adapters if multiple ++ * instances of do_tx (for different cards) are active concurrently. ++ * Moving it to eni_dev may cause a performance drop, so I'm avoiding ++ * that for now. ++ */ ++ static unsigned long dma[TX_DMA_BUF*2]; + struct atm_vcc *vcc; + struct eni_dev *eni_dev; + struct eni_vcc *eni_vcc; + struct eni_tx *tx; + unsigned long dma_rd,dma_wr; -+ unsigned long dma[TX_DMA_BUF*2]; + unsigned long size; /* in words */ + int aal5,dma_size,i,j; + @@ -2694,8 +2721,8 @@ +} + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/eni.h Wed Nov 13 11:38:13 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/eni.h Fri Nov 15 21:04:21 1996 @@ -0,0 +1,113 @@ +/* drivers/atm/eni.h - Efficient Networks ENI155P device driver declarations */ + @@ -2810,8 +2837,8 @@ +#endif /* __KERNEL__ */ + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/midway.h Wed Aug 21 10:55:38 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/midway.h Fri Nov 15 19:06:24 1996 @@ -0,0 +1,265 @@ +/* drivers/atm/midway.h - Efficient Networks Midway (SAR) description */ + @@ -3078,8 +3105,8 @@ +#define MID_DT_HWORD 0x2 + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/suni.c Thu Sep 26 22:48:49 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/suni.c Fri Nov 15 19:06:24 1996 @@ -0,0 +1,298 @@ +/* drivers/atm/suni.c - PMC SUNI (PHY) driver */ + @@ -3379,8 +3406,8 @@ +} + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/suni.h Wed Nov 13 11:38:13 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/suni.h Fri Nov 15 21:04:20 1996 @@ -0,0 +1,219 @@ +/* drivers/atm/suni.h - PMC SUNI (PHY) declarations */ + @@ -3601,8 +3628,8 @@ +#endif + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/tonga.h Wed Aug 21 10:55:39 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/tonga.h Fri Nov 15 19:06:24 1996 @@ -0,0 +1,20 @@ +/* drivers/atm/tonga.h - Efficient Networks Tonga (PCI bridge) declarations */ + @@ -3624,8 +3651,8 @@ +#define SEPROM_ESI_BASE 64 /* start of ESI in serial EEPROM */ + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/uPD98401.h Wed Aug 21 10:55:39 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/uPD98401.h Fri Nov 15 19:06:25 1996 @@ -0,0 +1,292 @@ +/* drivers/atm/uPD98401.h - NEC uPD98401 (SAR) declarations */ + @@ -3919,8 +3946,8 @@ +#define uPD98401_RXLT_ENBL 0x8000 /* Enable */ + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/uPD98402.h Wed Aug 21 10:55:39 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/uPD98402.h Fri Nov 15 19:06:25 1996 @@ -0,0 +1,106 @@ +/* drivers/atm/uPD98402.h - NEC uPD98402 (PHY) declarations */ + @@ -4028,8 +4055,8 @@ +int uPD98402_init(struct atm_dev *dev); + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/uPD98402.c Thu Aug 29 15:19:33 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/uPD98402.c Fri Nov 15 19:06:25 1996 @@ -0,0 +1,228 @@ +/* drivers/atm/uPD98402.c - NEC uPD98402 (PHY) declarations */ + @@ -4259,8 +4286,8 @@ +} + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/zatm.c Sun Oct 13 19:47:54 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/zatm.c Fri Nov 15 19:06:26 1996 @@ -0,0 +1,1844 @@ +/* drivers/atm/zatm.c - ZeitNet ZN122x device driver */ + @@ -6106,8 +6133,8 @@ +} + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/zatm.h Wed Nov 13 11:38:42 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/zatm.h Fri Nov 15 21:04:48 1996 @@ -0,0 +1,172 @@ +/* drivers/atm/zatm.h - ZeitNet ZN122x device driver declarations */ + @@ -6281,8 +6308,8 @@ + +#endif __KERNEL__ +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/zeprom.h Wed Aug 21 10:55:41 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/zeprom.h Fri Nov 15 19:06:27 1996 @@ -0,0 +1,34 @@ +/* drivers/atm/zeprom.h - ZeitNet ZN122x EEPROM (NM93C46) declarations */ + @@ -6318,8 +6345,8 @@ +/* No other commands are needed. */ + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/tneta1570.h Wed Nov 13 11:39:04 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/tneta1570.h Fri Nov 15 21:05:09 1996 @@ -0,0 +1,390 @@ +/* drivers/atm/tneta1570.h - TI TNETA1570 (SAR) declarations */ + @@ -6711,8 +6738,8 @@ + +#endif __KERNEL__ +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/tneta1570.c Wed Oct 9 12:26:38 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/tneta1570.c Fri Nov 15 19:06:28 1996 @@ -0,0 +1,1625 @@ +/* drivers/atm/tneta1570.c - ti tneta1570 atm driver + * @@ -8339,8 +8366,8 @@ +/* not yet */ +} +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/drivers/atm/fore200.c Wed Aug 21 10:55:43 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/fore200.c Fri Nov 15 19:06:28 1996 @@ -0,0 +1,26 @@ +/* drivers/atm/fore200.c - This is just a test, not a real driver */ + @@ -8368,8 +8395,2214 @@ + } + return 0; +} ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atm.h Thu Nov 7 16:06:56 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/nicstar.h Fri Nov 15 20:23:35 1996 +@@ -0,0 +1,265 @@ ++/* nicstar.h, M. Welsh (matt.welsh@cl.cam.ac.uk) ++ * Definitions for IDT77201. ++ * ++ * Copyright (c) 1996 University of Cambridge Computer Laboratory ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * M. Welsh, 6 July 1996 ++ * ++ */ ++ ++#ifndef _LINUX_NICSTAR_H ++#define _LINUX_NICSTAR_H ++ ++#include ++#include ++ ++/* User definitions *********************************************************/ ++ ++#define NICSTAR_DEV_MAJOR 35 ++ ++/* Kernel definitions ******************************************************/ ++ ++#ifdef __KERNEL__ ++ ++#define NICSTAR_MAX_DEVS 5 ++#define NICSTAR_IO_SIZE (4*1024) ++ ++#define SM_BUFSZ 52 ++#define NUM_SM_BUFS 170 ++#define LG_BUFSZ 2048 ++#define RAWCELLSZ 64 ++#define NUM_LG_BUFS 32 ++#define MAX_SDU_BUFS 32 /* Max number of buffers in an AAL5 SDU */ ++#define NUM_RX_SKB 32 /* Number of SKB's to allocate for receive */ ++#define NUM_SCQ_TRAIL 32 /* Number of outstanding SCQ entries */ ++#define TST_SIZE 200 /* Size of the Transmit Schedule Table ++ This determines resolution for CBR, ++ and thus lower bound on available BW */ ++#define IDT_25_PCR (25600000/270*260/8/53) ++ /* Link rate: 25600000 bps ++ SONET overhead: /270*260 (9 section, 1 path) ++ bits per cell: /8/53 ++ max cell rate: 58141.16 cells/sec */ ++ ++/* TST entry values */ ++#define TSTE_NULL 0x0 /* force NULL cell xmit */ ++#define TSTE_CBR 0x20000000 /* transmit CBR cell */ ++#define TSTE_VBR 0x40000000 /* transmit VBR cell */ ++#define TSTE_JUMP 0x60000000 /* Jump to SRAM addr */ ++ ++ ++enum nicstar_regs { ++ DR0 = 0x00, ++ DR1 = 0x04, ++ DR2 = 0x08, ++ DR3 = 0x0c, ++ CMD = 0x10, ++ CFG = 0x14, ++ STAT = 0x18, ++ RSQB = 0x1c, ++ RSQT = 0x20, ++ RSQH = 0x24, ++ CDC = 0x28, ++ VPEC = 0x2c, ++ ICC = 0x30, ++ RAWCT = 0x34, ++ TMR = 0x38, ++ TSTB = 0x3c, ++ TSQB = 0x40, ++ TSQT = 0x44, ++ TSQH = 0x48, ++ GP = 0x4c, ++ VPM = 0x50 ++}; ++ ++/* misc configuration options (experimental) */ ++#define NICSTAR_FASTXMIT 1 ++#define NICSTAR_CBR 1 /* Constant bit rate support */ ++#undef NICSTAR_RCQ /* Raw cell queue support */ ++#define NICSTAR_PARANOID 1 /* adds some extra checks */ ++#undef TEST_LOOPBACK /* enables PHY-level loopback */ ++#undef ATM_013 ++ ++ ++/* SRAM locations */ ++#define NICSTAR_VBR_SCD0 (0x1e7f4) ++#define NICSTAR_VBR_SCD1 (0x1e7e8) ++#define NICSTAR_VBR_SCD2 (0x1e7dc) ++#define NICSTAR_TST_REGION (0x1c000) /* For 32k SRAM */ ++#define NICSTAR_SCD_REGION (0x1d000) /* Arbitrary value */ ++ ++typedef struct nicstar_rcte { ++ u32 status; ++ u32 buf_handle; ++ u32 dma_addr; ++ u32 crc; ++} nicstar_rcte; ++#define RX_CTABLE_SIZE (16 * 1024) /* 16k words */ ++ ++typedef struct nicstar_fbd { ++ u32 buf_handle; ++ u32 dma_addr; ++} nicstar_fbd; ++ ++#define RSQE_GFC_MASK 0x00004000 ++#define RSQE_CLP_MASK 0x00000400 ++ ++typedef struct nicstar_rsqe { ++ u32 vpi_vci; ++ u32 buf_handle; ++ u32 crc; ++ u32 status; ++} nicstar_rsqe; ++#define RX_STATQ_ENTRIES (512) ++ ++typedef struct nicstar_tbd { ++ u32 status; ++ u32 buf_addr; ++ u32 ctl_len; ++ u32 cell_hdr; ++} nicstar_tbd; ++ ++#define TBD_SIZE (16) ++#ifdef NICSTAR_FASTXMIT ++/* following apply to NIC_TBD_DESC */ ++#define TBD_ENDPDU 0x40000000 /* 1 => last buffer of ++ AAL5 CS_PDU */ ++#define TBD_AAL0 0x00000000 /* 000 = AAL0 */ ++#define TBD_AAL34 0x04000000 /* 001 = AAL3/4 */ ++#define TBD_AAL5 0x08000000 /* 010 = AAL5 */ ++ ++#endif ++ /* for CBR, set M and N to all 0 */ ++#define TBD_UBR_M 0x00800000 /* M value timer count, VBR */ ++#define TBD_UBR_N 0x00010000 /* N value timer count, VBR */ ++ ++#define SCQ_SIZE (8192) /* Number of bytes actually allocated */ ++#define SCQ_ENTRIES (SCQ_SIZE / TBD_SIZE) /* Variable-rate SCQ */ /* XXX 511 */ ++#define CBRSCQ_SIZE (1024) /* space to reserve for each */ ++#define CBRSCQ_ENTRIES (CBRSCQ_SIZE / TBD_SIZE) /* # entries in a CBR SCQ */ ++#ifdef NICSTAR_CBR ++#define SCQFULL_MAGIC (0xf0000000) ++#define CBRSCQFULL_MAGIC (0xc0000000) ++#define CBRSCQFULL_MAGIC_CLOSE (0xe0000000) ++#else ++#define SCQFULL_MAGIC (0xfeed0000) ++#endif ++#define SCQFULL_TIMEOUT (3 * HZ) ++ ++typedef struct nicstar_scd { ++ u32 base_addr; ++ u32 tail_addr; ++ u32 crc; ++ u32 rsvd; ++ struct nicstar_tbd cache_a; ++ struct nicstar_tbd cache_b; ++} nicstar_scd; ++ ++typedef struct nicstar_tsi { ++ u32 status; ++ u32 timestamp; ++} nicstar_tsi; ++#define TX_STATQ_ENTRIES (1024) ++ ++typedef struct nicstar_scq_shadow { ++#ifndef NICSTAR_FASTXMIT ++ unsigned char cell[48]; ++#endif ++ struct sk_buff *skb; ++} nicstar_scq_shadow; ++ ++typedef struct nicstar_scq { ++ struct nicstar_tbd *orig; ++ struct nicstar_tbd *base; ++ struct nicstar_tbd *next; ++ struct nicstar_tbd *last; ++ struct nicstar_tbd *tail; ++ struct wait_queue *scqfull_waitq; ++ u32 id; ++ u32 scd; /* SRAM address of paired SCD */ ++ int closing; ++ nicstar_scq_shadow scq_shadow[SCQ_ENTRIES]; ++ volatile int full; ++} nicstar_scq; ++ ++typedef struct nicstar_vcimap { ++ int tx:1; ++ int rx:1; ++ struct atm_vcc *tx_vcc; ++ struct atm_vcc *rx_vcc; ++ struct sk_buff *rx_skb; ++ /* Pointer to SCQ for channel if CBR */ ++#ifdef NICSTAR_CBR ++ nicstar_scq *scq; ++#endif ++} nicstar_vcimap; ++ ++#define NUM_VCI (4096) /* Size of Rx conn table, indexed by VCI only */ ++#define NUM_VCI_BITS (12) /* Num sig bits */ ++ ++typedef struct nicstar_buf_list { ++ caddr_t buf_addr; ++ struct nicstar_buf_list *next; ++} nicstar_buf_list; ++ ++ ++#if NICSTAR_RCQ ++typedef struct nicstar_rcq { /* Raw cell queue */ ++ u32 rcq_head; /* pointer to current head of queue */ ++ u32 rcq_base; /* pointer to current buffer */ ++} nicstar_rcq; ++#endif ++ ++typedef struct nicstar_dev { ++ ++ int index; /* Device index */ ++ unsigned long iobase, membase; /* I/O and memory addresses */ ++ unsigned char modid, revid; /* PCI module and revision ID */ ++ unsigned char pci_bus, pci_devfn; /* PCI params */ ++ int irq; /* IRQ line */ ++ int inuse; ++ int rev_C3; /* True if chip is rev. C3 */ ++ ++ nicstar_rsqe *rx_statq, *rx_statq_last; ++ volatile nicstar_rsqe *rx_statq_next; ++ caddr_t rx_statq_orig; ++ nicstar_tsi *tx_statq, *tx_statq_next, *tx_statq_last; ++ caddr_t tx_statq_orig; ++ ++ u32 *host_tst; ++ int available_slots; /* VBR slots in TST */ ++ int max_pcr; /* Maximum PCR for the PHY */ ++ ++#if NICSTAR_RCQ ++ nicstar_rcq rcq; ++#endif ++ ++ caddr_t sm_bufs, lg_bufs; ++ struct sk_buff_head rx_skb_queue; ++ ++ nicstar_scq *scq; ++ caddr_t scq_orig; ++ ++ struct atm_dev *dev; ++ nicstar_vcimap vci_map[NUM_VCI]; ++ unsigned char tmp_cell[48]; ++ ++} nicstar_dev, *nicstar_devp; ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* _LINUX_NICSTAR_H_ */ +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/drivers/atm/nicstar.c Fri Nov 15 22:01:13 1996 +@@ -0,0 +1,1923 @@ ++/* nicstar.c, M. Welsh (matt.welsh@cl.cam.ac.uk) ++ * ++ * Linux driver for the IDT77201 NICStAR PCI ATM controller. ++ * PHY component is expected to be 155 Mbps S/UNI-Lite or IDT 77155; ++ * see init_nicstar() for PHY initialization to change this. This driver ++ * expects the Linux ATM stack to support scatter-gather lists ++ * (skb->atm.iovcnt != 0) for Rx skb's passed to vcc->push. ++ * ++ * Copyright (c) 1996 University of Cambridge Computer Laboratory ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * M. Welsh, 6 July 1996 ++ * ++ */ ++ ++static char _modversion[] = "@(#) nicstar.c, $Id: nicstar.c,v 1.28 1996/11/12 23:17:53 swdaniel Exp $"; ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#include ++char kernel_version[] = UTS_RELEASE; ++ ++#include "nicstar.h" ++ ++#undef NICSTAR_DEBUG /* Define for verbose debugging output */ ++ ++#ifdef NICSTAR_DEBUG ++#define PRINTK(args...) printk(args) ++#else ++#define PRINTK(args...) ++#endif ++ ++#define SLEEP_ON(x) interruptible_sleep_on(x) ++#define WAKE_UP(x) wake_up_interruptible(x) ++ ++#define TRUE 1 ++#define FALSE 0 ++#define MIN(a,b) ((a)<(b)?(a):(b)) ++#define MAX(a,b) ((a)>(b)?(a):(b)) ++ ++#define CMD_BUSY(node) (readl((node)->membase + STAT) & 0x0200) ++ ++/* For timing */ ++unsigned long get_usec(void) { ++ struct timeval t; ++ do_gettimeofday(&t); ++ return (unsigned long)((1e6 * t.tv_sec) + t.tv_usec); ++} ++ ++/* Global definitions ******************************************************/ ++static struct nicstar_dev *nicstar_devs[NICSTAR_MAX_DEVS]; ++static int num_found = 0; ++#if 0 ++static int nicstar_rx_count = 0; ++static u32 nicstar_timer = 0; ++#endif ++ ++/* Global/static function declarations *************************************/ ++static int init_nicstar(struct nicstar_dev *node); ++static void nicstar_interrupt(int irq, void *dev_id, struct pt_regs *regs); ++static void process_tx_statq(nicstar_devp node); ++static void process_rx_statq(nicstar_devp node); ++#ifdef NICSTAR_RCQ ++static void process_rx_rawcellq(nicstar_devp node); ++static void dequeue_rawcell(u32 *cell); ++#endif ++static void push_rxbufs(nicstar_devp node, int lg, ++ u32 handle1, u32 addr1, u32 handle2, u32 addr2); ++static void open_rx_connection(nicstar_devp node,int index, ++ u32 status); ++static void close_rx_connection(nicstar_devp node, int index); ++static void push_scq_entry(nicstar_devp node, struct nicstar_scq *scq, ++ nicstar_tbd *entry, int xmit_now); ++int init_module(void); ++void cleanup_module(void); ++static int get_ci(nicstar_devp node, struct atm_vcc *vcc, ++ short *vpi, int *vci); ++static void dequeue_rx(nicstar_devp node); ++static void nicstar_free_rx_skb(struct atm_vcc *vcc, struct sk_buff *skb); ++static void drain_scq(nicstar_devp node, struct nicstar_scq *scq, int index); ++static void free_rx_buf(nicstar_devp node, int lg, u32 buf_addr); ++#if NICSTAR_CBR ++static void alloc_tx(nicstar_devp node, struct atm_vcc *vcc); ++static void close_cbr (nicstar_devp node, struct atm_vcc *vcc); ++static void close_cbr_final (nicstar_devp node, struct atm_vcc *vcc); ++#endif ++static int create_scq (struct nicstar_scq **scq, int size); ++ ++/* Module entry points *****************************************************/ ++ ++static int nicstar_open(struct atm_vcc *vcc, short vpi, int vci) { ++ nicstar_devp node; ++ int error; ++ ++ node = vcc->dev->dev_data; ++ ++ /* XXX AAL5 and AAL0 only supported */ ++ if ((vcc->aal != ATM_AAL5) && (vcc->aal != ATM_AAL0)) ++ return -EINVAL; ++ ++ error = get_ci(node, vcc, &vpi, &vci); ++ if (error) return error; ++ vcc->vpi = vpi; ++ vcc->vci = vci; ++ vcc->dev_data = &(node->vci_map[vci]); ++ vcc->flags |= ATM_VF_ADDR; ++ ++#if NICSTAR_CBR ++#ifndef ATM_013 ++ if (vcc->qos.txtp.traffic_class == ATM_CBR) { ++#else ++ if (vcc->txtp.class == ATM_CBR) { ++#endif ++ printk("Opening CBR connection on vpci %d.%d\n",vpi,vci); ++ alloc_tx(node,vcc); ++ } ++#endif ++ ++ if (!(vcc->flags & ATM_VF_PARTIAL)) { ++ ++#ifndef ATM_013 ++ if (vcc->qos.rxtp.traffic_class != ATM_NONE) { ++#else ++ if (vcc->rxtp.class != ATM_NONE) { ++#endif ++ u32 status = 0x8000; ++ switch (vcc->aal) { ++ case ATM_AAL0 : break; ++ case ATM_AAL34 : status |= 0x10000; break; ++ case ATM_AAL5 : status |= 0x20000; break; ++ default : ++ printk ("nicstar%d: invalid AAL %d on open",node->index,vcc->aal); ++ return -EINVAL; ++ } ++ open_rx_connection(node, vci, status); ++ } ++ ++ vcc->flags |= ATM_VF_PARTIAL; ++ ++ } ++ ++ vcc->flags |= ATM_VF_READY; ++ ++ return 0; ++ ++} ++ ++static void nicstar_close(struct atm_vcc *vcc) { ++ nicstar_devp node; ++ nicstar_vcimap *mapval; ++ ++ node = vcc->dev->dev_data; ++ mapval = vcc->dev_data; ++ ++ vcc->flags &= ~ATM_VF_READY; ++ ++#ifndef ATM_013 ++ if (vcc->qos.rxtp.traffic_class != ATM_NONE) { ++#else ++ if (vcc->rxtp.class != ATM_NONE) { ++#endif ++ close_rx_connection(node, vcc->vci); ++ vcc->flags &= ~ATM_VF_PARTIAL; ++ mapval->rx = 0; ++ } ++ ++#ifndef ATM_013 ++ if (vcc->qos.txtp.traffic_class != ATM_NONE) { ++#else ++ if (vcc->txtp.class != ATM_NONE) { ++#endif ++ mapval->tx = 0; ++#ifndef ATM_013 ++ if (vcc->qos.txtp.traffic_class == ATM_CBR) { ++#else ++ if (vcc->txtp.class == ATM_CBR) { ++#endif ++#if NICSTAR_CBR ++ close_cbr(node,vcc); ++#endif ++ } ++ } ++ ++ vcc->flags &= ~ATM_VF_ADDR; ++} ++ ++static int nicstar_ioctl(struct atm_dev *dev, unsigned int cmd, ++ unsigned long arg) { ++ if (!dev->phy->ioctl) return -EINVAL; ++ return dev->phy->ioctl(dev,cmd,arg); ++} ++ ++static int nicstar_getsockopt(struct atm_vcc *vcc, ++ int level, ++ int optname, ++ char *optval, ++ int *optlen) { ++ return -EINVAL; ++} ++ ++static int nicstar_setsockopt(struct atm_vcc *vcc, int level, ++ int optname, char *optval, int optlen) { ++ struct atm_cirange ci; ++ int error; ++ ++ if (level != SOL_ATM) return -EINVAL; ++ switch (optname) { ++ case SO_CIRANGE: ++ if (!suser()) return -EPERM; ++ if (optlen != sizeof(struct atm_cirange)) ++ return -EINVAL; ++ error = verify_area(VERIFY_READ,optval,sizeof(struct atm_cirange)); ++ if (error) return error; ++ memcpy_fromfs(&ci,optval,sizeof(struct atm_cirange)); ++ if ((ci.vpi_bits == 0 || ci.vpi_bits == ATM_CI_MAX) && ++ (ci.vci_bits == NUM_VCI_BITS || ci.vci_bits == ATM_CI_MAX)) return 0; ++ return -EINVAL; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++} ++ ++/* XXX It is possible here that when pushing multiple TBD's, the ++ * next TSI will be placed between them, causing an incomplete PDU xmit. ++ * Probably fix by not allowing a TSI to be pushed onto the SCQ when ++ * force_xmit == 0. ++ */ ++static int nicstar_send(struct atm_vcc *vcc, struct sk_buff *skb) { ++ nicstar_devp node; ++ int pad, sindex, vci; ++ nicstar_tbd tbd1; ++ nicstar_scq *scq; ++ u32 rate; ++#ifdef NICSTAR_FASTXMIT ++ int len, len_buf; ++#else ++ nicstar_tbd tbd2, tbd3; ++#endif ++ ++ node = vcc->dev->dev_data; ++ ++ if (!((nicstar_vcimap *)vcc->dev_data)->tx) { ++ printk("nicstar%d: Tx on a non-Tx VC?\n", ++ ((nicstar_devp)vcc->dev->dev_data)->index); ++ vcc->stats->tx_err++; ++ dev_kfree_skb(skb,FREE_WRITE); ++ return -EINVAL; ++ } ++#ifndef NICSTAR_CBR ++#ifndef ATM_013 ++ if (vcc->qos.txtp.traffic_class == ATM_CBR) { ++#else ++ if (vcc->txtp.class == ATM_CBR) { ++#endif /* ATM_013*/ ++ printk("nicstar: Sorry - CBR support in progress.\n"); ++ dev_kfree_skb(skb,FREE_WRITE); ++ return -EINVAL; ++ } ++#endif /* NICSTAR_CBR */ ++ ++ /* Verify AAL is supported */ ++ if ((vcc->aal != ATM_AAL5) && (vcc->aal != ATM_AAL0)) { ++ printk("nicstar%d: Only AAL5 and AAL0 supported, sorry.\n", ++ ((nicstar_devp)vcc->dev->dev_data)->index); ++ vcc->stats->tx_err++; ++ dev_kfree_skb(skb,FREE_WRITE); ++ return -EINVAL; ++ } ++ ++ /* Verify that we have a linear buffer to transmit */ ++ if (skb->atm.iovcnt) { ++ printk("nicstar%d: S/G not supported, sorry.\n", ++ ((nicstar_devp)vcc->dev->dev_data)->index); ++ vcc->stats->tx_err++; ++ dev_kfree_skb(skb,FREE_WRITE); ++ return -EINVAL; ++ } ++ ++ skb->atm.vcc = vcc; ++ ++ vci = vcc->vci; ++#ifndef ATM_013 ++ if (vcc->qos.txtp.traffic_class == ATM_CBR) { ++#else ++ if (vcc->txtp.class == ATM_CBR) { ++#endif ++#ifdef NICSTAR_CBR ++ scq = (node->vci_map[vci]).scq; ++ rate = 0; ++#endif ++ } ++ else { ++ scq = node->scq; ++ rate = TBD_UBR_M | TBD_UBR_N; ++ } ++ sindex = scq->next - scq->base; ++ ++ ++ /* AAL-dependent transmits */ ++ if (vcc->aal == ATM_AAL0) { ++ /* size is always 48 bytes */ ++ len = ATM_CELL_PAYLOAD & ~3; ++ /* create tbd */ ++ tbd1.status = TBD_AAL0 | TBD_ENDPDU | rate | len; ++ tbd1.buf_addr = (u32)(skb->data + 4); ++ tbd1.ctl_len = 0x0; ++ tbd1.cell_hdr = (u32)(*((u32 *)skb->data)); ++ push_scq_entry(node,scq,&tbd1,1); ++ } ++ else if (vcc->aal == ATM_AAL5) { /* Transmit AAL 5 */ ++#ifdef NICSTAR_FASTXMIT ++ /* Speed up and simplify transmission by "cheating". ++ Basic problem is that rev C3 only supports mod 48 ++ buffer sizes; Matt's original uses shadow cells ++ to provide this. We cheat, instead, and simply ++ lie about the length of the buffer. This may ++ have security implications and problems from ++ going over the end of a buffer. ++ ++ For rev D or better, there is a better way; these ++ chips support mod 4 buffer sizes. Thus, we simply ++ pad the entire PDU length to mod 48 by adding a ++ pointer to the zero'd tmp_cell buffer. (SWD) */ ++ len = (((skb->len + 8 + 47) / 48) * 48); ++ pad = len - skb->len; ++ PRINTK ("new len %d skb len %ld skb end %x skb tail %x\n",len,skb->len,(u32)skb->end,(u32)skb->tail); ++ if (!(node->rev_C3)) { /* SAR supports mod 4 buffer sizes */ ++ len_buf = (((skb->len + 3) / 4) * 4); ++ if (pad == 0) { ++ tbd1.status = TBD_AAL5 | TBD_ENDPDU | rate | skb->len; ++ } ++ else { ++ tbd1.status = TBD_AAL5 | rate | len_buf; ++ } ++ } ++ else { ++ tbd1.status = TBD_AAL5 | TBD_ENDPDU | rate | len; ++ if (skb->end - pad < skb->tail) { ++ PRINTK ("nicstar%d: Whoops. overpadding a buffer!\n",node->index); ++ } ++ } ++ ++ tbd1.buf_addr = (u32)skb->data; ++ tbd1.ctl_len = skb->len; ++ tbd1.cell_hdr = (vcc->vci << 4); ++ scq->scq_shadow[sindex].skb = skb; ++ ++ if (!(node->rev_C3) && (pad != 0)) { ++ push_scq_entry(node, scq, &tbd1, 0); ++ tbd1.status = TBD_AAL5 | TBD_ENDPDU | rate | (len - len_buf); ++ tbd1.buf_addr = (u32)node->tmp_cell; ++ tbd1.ctl_len = skb->len; ++ tbd1.cell_hdr = (vcc->vci << 4); ++ push_scq_entry(node, scq, &tbd1, 1); ++ } ++ else { ++ push_scq_entry(node, scq, &tbd1, 1); ++ } ++ ++#else ++ if (skb->len > 48) { ++ /* YYY If we transmit a buffer where pad == 48, an extra cell ++ is transmitted under this scheme if skb->len > 48 (SWD) */ ++ ++ pad = 48 - ((skb->len + 8) % 48); ++ if (pad <= 40) { ++ memcpy(node->scq->scq_shadow[sindex].cell, ++ skb->data + (skb->len) - (40 - pad), ++ 40 - pad); ++ ++ /* Need to do this unless we want to send garbage at ++ * end of last cell ... only bad for security */ ++ memset(node->scq->scq_shadow[sindex].cell + (40 - pad), 0, pad); ++ ++ tbd1.status = 0x08810000 | (((skb->len - (40 - pad))/sizeof(u32)) << 2); ++ tbd1.buf_addr = (u32)skb->data; ++ tbd1.ctl_len = skb->len; ++ tbd1.cell_hdr = (vcc->vci << 4); ++ ++ node->scq->scq_shadow[sindex].skb = skb; ++ push_scq_entry(node, node->scq, &tbd1, 0); ++ ++ tbd2.status = 0x48810030; ++ tbd2.buf_addr = (u32)(node->scq->scq_shadow[sindex].cell); ++ tbd2.ctl_len = skb->len; ++ tbd2.cell_hdr = (vcc->vci << 4); ++ ++ push_scq_entry(node, node->scq, &tbd2, 1); ++ ++ } else { ++ /* Pad > 40 */ ++ pad = pad - 40; /* Pad of second-to-last cell */ ++ memcpy(node->scq->scq_shadow[sindex].cell, ++ skb->data + (skb->len) - (48 - pad), 48 - pad); ++ memset(node->scq->scq_shadow[sindex].cell + (48 - pad), 0, pad); ++ ++ tbd1.status = 0x08810000 | (((skb->len - (48 - pad))/sizeof(u32)) << 2); ++ tbd1.buf_addr = (u32)skb->data; ++ tbd1.ctl_len = skb->len; ++ tbd1.cell_hdr = (vcc->vci << 4); ++ ++ node->scq->scq_shadow[sindex].skb = skb; ++ push_scq_entry(node, node->scq, &tbd1, 0); ++ ++ tbd2.status = 0x08810030; ++ tbd2.buf_addr = (u32)(node->scq->scq_shadow[sindex].cell); ++ tbd2.ctl_len = skb->len; ++ tbd2.cell_hdr = (vcc->vci << 4); ++ ++ push_scq_entry(node, node->scq, &tbd2, 0); ++ ++ tbd3.status = 0x48810030; ++ tbd3.buf_addr = (u32)(node->tmp_cell); ++ tbd3.ctl_len = skb->len; ++ tbd3.cell_hdr = (vcc->vci << 4); ++ ++ push_scq_entry(node, node->scq, &tbd3, 1); ++ } ++ ++ } else if (skb->len <= 40) { ++ ++ pad = 48 - (skb->len + 8); ++ memcpy(node->scq->scq_shadow[sindex].cell, ++ skb->data, skb->len); ++ memset(node->scq->scq_shadow[sindex].cell + skb->len, 0, pad); ++ tbd1.status = 0x48810030; ++ tbd1.buf_addr = (u32)(node->scq->scq_shadow[sindex].cell); ++ tbd1.ctl_len = skb->len; ++ tbd1.cell_hdr = (vcc->vci << 4); ++ ++ node->scq->scq_shadow[sindex].skb = skb; ++ push_scq_entry(node, node->scq, &tbd1, 1); ++ ++ } else { ++ ++ /* 41 .. 48 inclusive */ ++ pad = 48 - (skb->len); ++ memcpy(node->scq->scq_shadow[sindex].cell, ++ skb->data, skb->len); ++ memset(node->scq->scq_shadow[sindex].cell + skb->len, 0, pad); ++ ++ tbd1.status = 0x08810030; ++ tbd1.buf_addr = (u32)(node->scq->scq_shadow[sindex].cell); ++ tbd1.ctl_len = skb->len; ++ tbd1.cell_hdr = (vcc->vci << 4); ++ ++ node->scq->scq_shadow[sindex].skb = skb; ++ push_scq_entry(node, node->scq, &tbd1, 0); ++ ++ tbd2.status = 0x48810030; ++ tbd2.buf_addr = (u32)(node->tmp_cell); ++ tbd2.ctl_len = skb->len; ++ tbd2.cell_hdr = (vcc->vci << 4); ++ ++ push_scq_entry(node, node->scq, &tbd2, 1); ++ ++ } ++#endif /* NICSTAR_FASTXMIT */ ++ } ++ ++ vcc->stats->tx++; ++ return 0; ++ ++} ++ ++static struct atmdev_ops atm_ops = { ++ nicstar_open, /* open */ ++ nicstar_close, /* close */ ++ nicstar_ioctl, /* ioctl */ ++ nicstar_getsockopt, /* getsockopt */ ++ nicstar_setsockopt, /* setsockopt */ ++ nicstar_send, /* send */ ++ NULL, /* sg_send */ ++ NULL, /* poll */ ++ NULL, /* send_oam */ ++ NULL, /* phy_put */ ++ NULL, /* phy_get */ ++ NULL, /* feedback */ ++#ifndef ATM_013 ++ NULL, /* change_qos */ ++#endif ++ nicstar_free_rx_skb, /* free_rx_skb */ ++}; ++ ++static int do_detect(void) { ++ ++ int error; ++ static unsigned char pci_bus, pci_devfn; ++ int pci_index; ++ struct nicstar_dev *node; ++ unsigned short pci_command; ++ unsigned char pci_latency; ++ unsigned char irq; ++ int i; ++ u32 gp; ++ ++ PRINTK("nicstar: init_module called\n"); ++ ++ if (!pcibios_present()) { ++ printk("nicstar: Fatal error: No PCI BIOS present\n"); ++ return -EIO; ++ } ++ ++ for (i = 0; i < NICSTAR_MAX_DEVS; i++) ++ nicstar_devs[i] = NULL; ++ ++ PRINTK("nicstar: Searching for IDT77201 NICStAR: vendor 0x%x, device 0x%x\n", ++ PCI_VENDOR_ID_IDT, ++ PCI_DEVICE_ID_IDT_IDT77201); ++ ++ for (pci_index = 0; pci_index < 8; pci_index++) { ++ ++ if ((error = pcibios_find_device(PCI_VENDOR_ID_IDT, ++ PCI_DEVICE_ID_IDT_IDT77201, ++ pci_index, &pci_bus, &pci_devfn)) ++ != PCIBIOS_SUCCESSFUL) ++ break; ++ ++ /* Allocate a device structure */ ++ node = kmalloc(sizeof(struct nicstar_dev),GFP_KERNEL); ++ if (node == NULL) { ++ printk("nicstar: Can't allocate device struct for device %d!\n",pci_index); ++ return -EIO; ++ } ++ nicstar_devs[num_found] = node; ++ node->index = num_found; ++ node->pci_bus = pci_bus; ++ node->pci_devfn = pci_devfn; ++ ++ error = pcibios_read_config_byte(pci_bus,pci_devfn,PCI_REVISION_ID, ++ &(node->revid)); ++ if (error) { ++ printk("nicstar: Can't read REVID from device %d\n",pci_index); ++ return -EIO; ++ } ++ ++ error = pcibios_read_config_dword(pci_bus,pci_devfn,PCI_BASE_ADDRESS_0, ++ (unsigned int *)&(node->iobase)); ++ if (error) { ++ printk("nicstar: Can't read iobase from device %d.\n",pci_index); ++ return -EIO; ++ } ++ ++ error = pcibios_read_config_dword(pci_bus,pci_devfn,PCI_BASE_ADDRESS_1, ++ (unsigned int *)&(node->membase)); ++ if (error) { ++ printk("nicstar: Can't read membase from device %d.\n",pci_index); ++ return -EIO; ++ } ++ ++ if (pcibios_read_config_byte(pci_bus,pci_devfn,PCI_INTERRUPT_LINE, ++ (unsigned char *)&irq)) { ++ printk("nicstar: Can't read INTLN from device %d.\n",pci_index); ++ return -EIO; ++ } ++ node->irq = irq; ++ ++ node->iobase &= PCI_BASE_ADDRESS_IO_MASK; ++ node->membase &= PCI_BASE_ADDRESS_MEM_MASK; ++ ++ node->membase = (unsigned long)vremap((unsigned int)node->membase,NICSTAR_IO_SIZE); ++ if ((unsigned long *)node->membase == NULL) { ++ printk("nicstar: Can't remap membase for board %d.\n",node->index); ++ return -EIO; ++ } ++ ++ printk("nicstar: Found device index %d, bus %d, function %d.\n", ++ pci_index,pci_bus,pci_devfn); ++ printk("nicstar: Revision 0x%x, using IRQ %d.\n",node->revid,node->irq); ++ printk("nicstar: iobase: 0x%lx, membase: 0x%lx\n",node->iobase,node->membase); ++ ++ /* Enable memory space and busmastering */ ++ if (pcibios_read_config_word(pci_bus,pci_devfn,PCI_COMMAND,&pci_command)) { ++ printk("nicstar: Can't read PCI_COMMAND from device %d.\n",pci_index); ++ return -EIO; ++ } ++ ++ pci_command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_SPECIAL | PCI_COMMAND_MASTER); ++ error = pcibios_write_config_word(pci_bus,pci_devfn,PCI_COMMAND, ++ pci_command); ++ ++ if (error) { ++ printk("nicstar: Can't enable board memory for device %d.\n",pci_index); ++ return -EIO; ++ } ++ ++ /* Check latency timer */ ++ if (pcibios_read_config_byte(pci_bus,pci_devfn,PCI_LATENCY_TIMER,&pci_latency)) { ++ printk("nicstar: Can't read latency timer from device %d.\n",pci_index); ++ return -EIO; ++ } ++ if (pci_latency < 32) { ++ printk("nicstar: Setting latency timer from %d to 32 clocks.\n",pci_latency); ++ pcibios_write_config_byte(pci_bus,pci_devfn,PCI_LATENCY_TIMER,32); ++ } ++ ++ num_found++; ++ ++ /* Check for SAR, revision C3; on this revision, bit 15/GP is ++ not writable, only readable. */ ++ gp = readl(node->membase + GP); ++ writel(gp | 0x8000,node->membase + GP); ++ node->rev_C3 = (readl(node->membase + GP) & 0x8000) ? 0 : 1; ++ if (node->rev_C3) { ++ printk("nicstar%d: Revision C3 77201 detected\n",node->index); ++ } ++ else { ++ printk("nicstar%d: Revision D or later 77201 detected\n",node->index); ++ } ++ writel(gp,node->membase + GP); /* restore original contents */ ++ ++ /* Initialize random things */ ++ node->inuse = 0; ++ ++ /* Get IRQ */ ++ if (request_irq(node->irq, &nicstar_interrupt, SA_INTERRUPT, "nicstar", node)) { ++ printk("nicstar: Can't allocate IRQ %d.\n",node->irq); ++ return -EIO; ++ } ++ ++ if (init_nicstar(node)) { ++ printk("nicstar: Error initializing device %d.\n",pci_index); ++ free_irq(node->irq, node); ++ return -EIO; ++ } ++ ++ /* Register device */ ++ node->dev = atm_dev_register("nicstar", &atm_ops, 0); ++ if (node->dev == NULL) { ++ printk("nicstar: Can't register device %d.\n",node->index); ++ free_irq(node->irq, node); ++ return -EIO; ++ } ++ node->dev->esi[0] = '\0'; ++ node->dev->esi[1] = '\34'; ++ node->dev->esi[2] = '\100'; ++ node->dev->esi[3] = '\0'; ++ node->dev->esi[4] = '\17'; ++ node->dev->esi[5] = '\110'; ++ node->dev->dev_data = node; ++ ++ node->dev->ci_range.vpi_bits = 0; ++ node->dev->ci_range.vci_bits = NUM_VCI_BITS; ++ ++ } ++ ++ if (num_found == 0) return -EIO; ++ ++ printk("nicstar: %d devices found.\n",num_found); ++ return num_found; ++ ++} ++ ++ ++#ifndef MODULE ++ ++ ++int nicstar_detect(void) ++{ ++ int devs; ++ ++ devs = do_detect(); ++ return devs < 0 ? 0 : devs; ++} ++ ++ ++#else ++ ++ ++int init_module(void) { ++ int devs; ++ ++ printk("nicstar: Installing %s of %s %s.\n",__FILE__,__DATE__,__TIME__); ++ devs = do_detect(void); ++ if (!devs) { ++ printk(KERN_ERR "nicstar: no adapter found\n"); ++ return -ENXIO; ++ } ++ return 0; ++} ++ ++ ++void cleanup_module(void) { ++ int i, error; ++ nicstar_devp node; ++ unsigned short pci_command; ++ ++ PRINTK("nicstar: cleanup_module called\n"); ++ ++ if (MOD_IN_USE) ++ PRINTK("nicstar: Device busy, remove delayed.\n"); ++ ++ /* Free up the device resources */ ++ for (i = 0; i < NICSTAR_MAX_DEVS; i++) { ++ if (nicstar_devs[i] != NULL) { ++ node = nicstar_devs[i]; ++ /* Turn everything off */ ++ writel(0x00000000, (node->membase)+CFG); ++ ++ /* Disable PCI busmastering */ ++ if (pcibios_read_config_word(node->pci_bus,node->pci_devfn,PCI_COMMAND,&pci_command)) { ++ printk("nicstar: Can't read PCI_COMMAND from device %d.\n",node->index); ++ continue; ++ } ++ pci_command &= ~PCI_COMMAND_MASTER; ++ error = pcibios_write_config_word(node->pci_bus,node->pci_devfn, ++ PCI_COMMAND, pci_command); ++ if (error) { ++ printk("nicstar: Can't disable busmastering for device %d.\n",node->index); ++ continue; ++ } ++ ++ drain_scq(node,node->scq,node->scq->next - node->scq->base); ++ kfree(node->rx_statq_orig); ++ kfree(node->tx_statq_orig); ++ kfree(node->sm_bufs); ++ kfree(node->lg_bufs); ++ kfree(node->scq->orig); ++ kfree(node->scq); ++ free_irq(node->irq, node); ++ ++ { ++ struct sk_buff *skb; ++ while ((skb = skb_dequeue(&node->rx_skb_queue))) ++ dev_kfree_skb(skb, FREE_READ); ++ } ++ ++ atm_dev_deregister(node->dev); ++ ++ kfree(nicstar_devs[i]); ++ } ++ } ++ ++ printk("nicstar: Module cleanup succeeded.\n"); ++ ++} ++ ++ ++#endif ++ ++ ++/* NICStAR functions *******************************************************/ ++ ++static inline u32 read_sram(nicstar_devp node, u32 addr) { ++ u32 data; ++ unsigned long flags; ++ ++ save_flags(flags); cli(); ++ while (CMD_BUSY(node)) ; ++ writel(((0x50000000) | ((addr & 0x1ffff) << 2)), node->membase + CMD); ++ while (CMD_BUSY(node)) ; ++ data = readl(node->membase + DR0); ++ restore_flags(flags); ++ return data; ++} ++ ++static inline void write_sram(nicstar_devp node, int count, u32 addr, ++ u32 d0, u32 d1, u32 d2, u32 d3) { ++ unsigned long flags; ++ ++ save_flags(flags); cli(); ++ while (CMD_BUSY(node)); ++ switch (count) { ++ case 4: ++ writel(d3, node->membase + DR3); ++ case 3: ++ writel(d2, node->membase + DR2); ++ case 2: ++ writel(d1, node->membase + DR1); ++ case 1: ++ writel(d0, node->membase + DR0); ++ break; ++ default: ++ restore_flags(flags); ++ return; ++ } ++ ++ writel((0x40000000) | ((addr & 0x1ffff) << 2) | (count-1), node->membase+CMD); ++ restore_flags(flags); ++ return; ++} ++ ++static int init_nicstar(struct nicstar_dev *node) { ++ u32 i, d; ++ unsigned short pci_command; ++ int error; ++ u32 tmp; ++ ++ d = readl(node->membase + STAT); ++ /* Clear timer if overflow */ ++ if (d & 0x00000800) { ++ writel(0x00000800, node->membase+STAT); ++ } ++ ++ /* S/W reset */ ++ writel(0x80000000, node->membase+CFG); ++ SLOW_DOWN_IO; SLOW_DOWN_IO; SLOW_DOWN_IO; ++ writel(0x00000000, node->membase+CFG); ++ ++ /* Turn everything off, but use 4k recv status queue */ ++ writel(0x00400000, node->membase+CFG); ++ d = readl(node->membase + CFG); ++ ++ /* Determine PHY type/speed by reading PHY reg 0 (from IDT) */ ++ /* YYY This tested only for 77105 (SWD) */ ++ writel(0x80000200,node->membase + CMD); /* read PHY reg 0 command */ ++ while (CMD_BUSY(node)) ; ++ tmp = readl(node->membase + DR0); ++ if (tmp == 0x9) { ++ node->max_pcr = IDT_25_PCR; ++ printk ("nicstar%d: PHY device appears to be 25Mbps\n",node->index); ++ } ++ else if (tmp == 0x30) { ++ node->max_pcr = ATM_OC3_PCR; ++ printk ("nicstar%d: PHY device appears to be 155Mbps\n",node->index); ++ } ++ ++#ifdef TEST_LOOPBACK ++ /* PHY reset */ ++ d = readl(node->membase+GP); ++ writel(d & 0xfffffff7, node->membase+GP); /* Out of reset */ ++ { int j; for (j = 0; j < 100000; j++) ; } ++ writel(d | 0x00000008, node->membase+GP); /* Reset */ ++ { int j; for (j = 0; j < 100000; j++) ; } ++ writel(d & 0xfffffff7, node->membase+GP); /* Out of reset */ ++ ++ /* PHY loopback */ ++ while(CMD_BUSY(node)) ; ++ printk ("nicstar%d: Setting PHY Loopback\n",node->index); ++ writel(0x00000022, node->membase + DR0); ++ if (node->max_pcr == IDT_25_PCR) { /* loopback for 77105 */ ++ writel(0x90000202, node->membase + CMD); ++ } ++ else { /* assume 77155 */ ++ writel(0x90000205, node->membase + CMD); ++ } ++ ++#else ++ ++ /* PHY reset */ ++ d = readl(node->membase+GP); ++ writel(d & 0xfffffff7, node->membase+GP); /* Out of reset */ ++ { int j; for (j = 0; j < 100000; j++) ; } ++ writel(d | 0x00000008, node->membase+GP); /* Reset */ ++ { int j; for (j = 0; j < 100000; j++) ; } ++ writel(d & 0xfffffff7, node->membase+GP); /* Out of reset */ ++ ++ while (CMD_BUSY(node)) ; ++ writel(0x80000100, node->membase+CMD); /* Sync UTOPIA with SAR clock */ ++ { int j; for (j = 0; j < 100000; j++) ; } ++ ++ /* Normal mode */ ++ while(CMD_BUSY(node)) ; ++ writel(0x00000020, node->membase + DR0); ++ if (node->max_pcr == IDT_25_PCR) { /* 77105 */ ++ writel(0x90000202, node->membase + CMD); ++ } ++ else { /* assume 77155 */ ++ writel(0x90000205, node->membase + CMD); ++ } ++ ++#endif /* PHY_LOOPBACK */ ++ ++ /* Re-enable memory space and busmastering --- in case the PCI reset ++ * turned us off ... ++ */ ++ if (pcibios_read_config_word(node->pci_bus,node->pci_devfn,PCI_COMMAND,&pci_command)) { ++ printk("nicstar: Can't read PCI_COMMAND from device %d.\n",node->index); ++ return -EIO; ++ } ++ pci_command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_SPECIAL | PCI_COMMAND_MASTER); ++ error = pcibios_write_config_word(node->pci_bus,node->pci_devfn,PCI_COMMAND, ++ pci_command); ++ if (error) { ++ printk("nicstar: Can't enable board memory for device %d.\n",node->index); ++ return -EIO; ++ } ++ ++ /* Set up the recv connection table */ ++ for (i = 0; i < RX_CTABLE_SIZE; i+=4) { ++#if NICSTAR_RCQ ++ write_sram(node, 4, i, 0x00008000, 0x00000000, 0x00000000, 0xffffffff); ++#else ++ write_sram(node, 4, i, 0x00000000, 0x00000000, 0x00000000, 0xffffffff); ++#endif ++ } ++ ++ writel(0x0, node->membase + VPM); ++ ++ /* Clear VCI map and SCQ shadow */ ++ memset(node->vci_map, 0, sizeof(node->vci_map)); ++ memset(node->tmp_cell, 0, sizeof(node->tmp_cell)); ++ ++ /* Allocate Rx status queue */ ++ /* XXX What about 64-bit pointers? */ ++ node->rx_statq_orig = kmalloc(2*8192, GFP_KERNEL); ++ if (!node->rx_statq_orig) { ++ printk("nicstar%d: Can't allocate Rx status queue.\n",node->index); ++ return -ENOMEM; ++ } ++ node->rx_statq = (nicstar_rsqe *)(((u32)node->rx_statq_orig + (8192 - 1)) & ~(8192 - 1)); ++ ++ printk("nicstar%d: Rx status queue at 0x%x (0x%x).\n",node->index, (u32)node->rx_statq, (u32)node->rx_statq_orig); ++ ++ for (i = 0; i < RX_STATQ_ENTRIES; i++) { ++ node->rx_statq[i].vpi_vci = 0x0; ++ node->rx_statq[i].buf_handle = 0x0; ++ node->rx_statq[i].crc = 0x0; ++ node->rx_statq[i].status = 0x0; ++ } ++ ++ node->rx_statq_next = node->rx_statq; ++ node->rx_statq_last = node->rx_statq + (RX_STATQ_ENTRIES - 1); ++ writel((u32)node->rx_statq, node->membase + RSQB); ++ writel((u32)0x0, node->membase + RSQH); ++ ++ /* Allocate Tx status queue */ ++ /* XXX What about 64-bit pointers? */ ++ node->tx_statq_orig = (caddr_t)kmalloc(2*8192, GFP_KERNEL); ++ if (!node->tx_statq_orig) { ++ printk("nicstar%d: Can't allocate Tx status queue.\n",node->index); ++ return -ENOMEM; ++ } ++ node->tx_statq = (nicstar_tsi *)(((u32)node->tx_statq_orig + (8192 - 1)) & ~(8192 - 1)); ++ ++ printk("nicstar%d: Tx status queue at 0x%x (0x%x).\n",node->index, (u32)node->tx_statq, (u32)node->tx_statq_orig); ++ ++ for (i = 0; i < TX_STATQ_ENTRIES; i++) { ++ node->tx_statq[i].timestamp = 0x80000000; ++ } ++ node->tx_statq_next = node->tx_statq; ++ node->tx_statq_last = node->tx_statq + (TX_STATQ_ENTRIES - 1); ++ ++ writel((u32)node->tx_statq, node->membase + TSQB); ++ writel((u32)0x0, node->membase + TSQH); ++ ++ /* Allocate buffer queues */ ++ ++ node->sm_bufs = (caddr_t)kmalloc(SM_BUFSZ * NUM_SM_BUFS, GFP_KERNEL); ++ if (!node->sm_bufs) { ++ printk("nicstar%d: Can't allocate %d %d-byte small buffers!\n", ++ node->index, NUM_SM_BUFS, SM_BUFSZ); ++ return -ENOMEM; ++ } ++ ++ node->lg_bufs = (caddr_t)kmalloc(LG_BUFSZ * NUM_LG_BUFS, GFP_KERNEL); ++ if (!node->lg_bufs) { ++ printk("nicstar%d: Can't allocate %d %d-byte large buffers!\n", ++ node->index, NUM_LG_BUFS, LG_BUFSZ); ++ return -ENOMEM; ++ } ++ ++ printk("nicstar%d: Small buffers at 0x%x, Large buffers at 0x%x.\n", ++ node->index, (u32)node->sm_bufs, (u32)node->lg_bufs); ++ ++#if NICSTAR_RCQ ++ node->rcq.rcq_head = (u32) node->lg_bufs; ++ node->rcq.rcq_base = (u32) node->lg_bufs; ++ /* Manual says we should check head vs tail here; but tail reg ++ isn't updated until after we turn on RX path. Moved check to ++ end of init_module... */ ++#endif ++ ++ for (i = 0; i < NUM_SM_BUFS; i+=2) { ++ push_rxbufs(node, 0, ++ (u32)(node->sm_bufs + (i*SM_BUFSZ) + 4), ++ (u32)(node->sm_bufs + (i*SM_BUFSZ) + 4), ++ (u32)(node->sm_bufs + ((i+1)*SM_BUFSZ) + 4), ++ (u32)(node->sm_bufs + ((i+1)*SM_BUFSZ) + 4)); ++ } ++ ++ for (i = 0; i < NUM_LG_BUFS; i+=2) { ++ push_rxbufs(node, 1, ++ (u32)(node->lg_bufs + (i*LG_BUFSZ)), ++ (u32)(node->lg_bufs + (i*LG_BUFSZ)), ++ (u32)(node->lg_bufs + ((i+1)*LG_BUFSZ)), ++ (u32)(node->lg_bufs + ((i+1)*LG_BUFSZ))); ++ } ++ ++ skb_queue_head_init(&node->rx_skb_queue); ++ for (i = 0; i < NUM_RX_SKB; i++) { ++ struct sk_buff *skb; ++ skb = alloc_skb(MAX_SDU_BUFS * sizeof(struct iovec), GFP_KERNEL); ++ if (!skb) { ++ printk("nicstar%d: Can't allocate Rx skb!\n",node->index); ++ return -ENOMEM; ++ } ++ skb_queue_tail(&node->rx_skb_queue,skb); ++ } ++ ++ ++ /* Allocate seg chan queue */ ++ /* XXX What about 64-bit pointers? */ ++ i = create_scq(&(node->scq),SCQ_SIZE); ++ node->scq->id = SCQFULL_MAGIC; ++ if (i != 0) { return i; } ++ ++ printk("nicstar%d: SCQ at 0x%x.\n",node->index,(u32)node->scq->base); ++ ++ write_sram(node, 4, NICSTAR_VBR_SCD0, ++ (u32)node->scq->base, /* SCQ base */ ++ (u32)0x0, /* tail */ ++ (u32)0xffffffff, /* AAL5 CRC */ ++ (u32)0x0); /* rsvd */ ++ node->scq->scd = NICSTAR_VBR_SCD0; ++ ++ /* Install TST */ ++ ++ /* Create host transmit schedule table */ ++ if ((((u32) node->tx_statq - (u32) node->tx_statq_orig) - (4 * TST_SIZE)) < 1) { ++ printk ("Need to move host TST to later %d\n",4*TST_SIZE); ++ node->host_tst = (u32 *) ((u32) node->tx_statq_orig - 8 - (4 * TST_SIZE)); ++ printk ("New host_tst %x\n",(u32)node->host_tst); ++ } ++ else { ++ node->host_tst = (u32 *) node->tx_statq_orig; ++ } ++ ++ node->available_slots = TST_SIZE; ++ ++ memset((caddr_t) node->host_tst, 0, 4 * TST_SIZE); ++ ++#ifdef NICSTAR_CBR ++ for (i = NICSTAR_TST_REGION; i < NICSTAR_TST_REGION + TST_SIZE; i += 4) { ++ write_sram(node, 4, i, ++ (u32) TSTE_VBR, /* Tx VBR SCD */ ++ (u32) TSTE_VBR, /* Tx VBR SCD */ ++ (u32) TSTE_VBR, /* Tx VBR SCD */ ++ (u32) TSTE_VBR ); /* Tx VBR SCD */ ++ } ++ ++ write_sram(node, 1, NICSTAR_TST_REGION + TST_SIZE, ++ (u32)0x60000000 | NICSTAR_TST_REGION, /* Jump to start */ ++ 0x0, 0x0, 0x0); ++ ++#else ++ write_sram(node, 2, NICSTAR_TST_REGION + TST_SIZE, ++ (u32)0x40000000, /* Tx VBR SCD */ ++ /* (u32)0x20000000 | NICSTAR_SCD_REGION, *//* Tx SCD */ ++ (u32)0x60000000 | NICSTAR_TST_REGION, /* Jump to start */ ++ 0x0, 0x0); ++#endif ++ ++ writel((u32)(NICSTAR_TST_REGION << 2), node->membase + TSTB); ++ ++#if NICSTAR_RCQ ++ /* Turn on everything */ ++ writel(0x21801c38 | 0x200 | 0x800, node->membase+CFG); ++ /* | 0x800 turns on raw cell interrupts */ ++ /* | 0x200 for raw cell receive */ ++ /* | 0x8000 to receive cells that don't map via RCT (not there/closed) */ ++#else ++ writel(0x21801c38, node->membase+CFG); /* Turn on everything */ ++#endif ++ ++ while(CMD_BUSY(node)); ++#if NICSTAR_RCQ ++ printk("nicstar%d: Checking raw cell queue pointer...\n",node->index); ++ if (node->rcq.rcq_head != readl(node->membase + RAWCT)) { ++ printk("nicstar%d: Raw cell head %x tail %x don't match\n", ++ node->index,(u32)node->rcq.rcq_head, readl(node->membase + RAWCT)); ++ } ++#endif ++ return 0; ++} ++ ++static void nicstar_interrupt(int irq, void *dev_id, struct pt_regs *regs) { ++ nicstar_devp node = (nicstar_devp)dev_id; ++ u32 stat, wr_stat; ++ ++ PRINTK("nicstar: interrupt on %d.\n",irq); ++ ++ wr_stat = 0x0; ++ stat = readl(node->membase + STAT); ++ PRINTK("nicstar%d: Interrupt: STAT 0x%x.\n",node->index, stat); ++ ++ if (stat & 0x8000) { ++ wr_stat |= 0x8000; ++ PRINTK("nicstar%d: TSI written to Tx status queue.\n",node->index); ++ process_tx_statq(node); ++ } ++ if (stat & 0x4000) { ++ wr_stat |= 0x4000; ++ printk("nicstar%d: Incomplete CS-PDU transmitted.\n",node->index); ++ } ++ ++ if (stat & 0x800) { ++ wr_stat |= 0x800; ++ PRINTK("nicstar%d: Timer overflow.\n",node->index); ++ } ++ if (stat & 0x100) { ++ printk("nicstar%d: Small buffer queue full (this is OK).\n",node->index); ++ } ++ if (stat & 0x80) { ++ printk("nicstar%d: Large buffer queue full (this is OK).\n",node->index); ++ } ++ if (stat & 0x40) { ++ printk("nicstar%d: Rx status queue full.\n",node->index); ++ wr_stat |= 0x40; ++ process_rx_statq(node); ++ } ++ if (stat & 0x20) { ++ /* wr_stat |= 0x20; */ ++ writel(0x20, node->membase + STAT); /* XXX mdw ack immediately */ ++ PRINTK("nicstar%d: End of PDU received.\n", node->index); ++ process_rx_statq(node); ++ } ++ if (stat & 0x10) { ++ wr_stat |= 0x10; ++ printk("nicstar%d: Raw cell received.\n",node->index); ++#ifdef NICSTAR_RCQ ++ process_rx_rawcellq(node); ++#endif ++ } ++ if (stat & 0x8) { ++ printk("nicstar%d: Small buffer queue empty, disabling interrupt.\n",node->index); ++ writel((readl(node->membase + CFG) & ~0x01000000), node->membase + CFG); ++ wr_stat |= 0x8; ++ } ++ if (stat & 0x4) { ++ printk("nicstar%d: Large buffer queue empty, disabling interrupt.\n",node->index); ++ writel((readl(node->membase + CFG) & ~0x01000000), node->membase + CFG); ++ wr_stat |= 0x4; ++ } ++ if (stat & 0x2) { ++ printk("nicstar%d: Rx status queue almost full.\n",node->index); ++ wr_stat |= 0x2; ++ /* XXX Turn off interrupt */ ++ writel((readl(node->membase + CFG) & ~0x00000400), node->membase + CFG); ++ process_rx_statq(node); ++ } ++ ++ if (wr_stat != 0x0) { ++ writel(wr_stat, node->membase + STAT); ++ } ++ ++ return; ++} ++ ++ ++static void process_tx_statq(nicstar_devp node) { ++ ++ volatile nicstar_tsi *next; ++ nicstar_scq *scq; ++ u32 id; ++ ++ /* Spin until something arrives. If we get a timer-rollover and a ++ * TSI simultaneously this could be dangerous; disabling timer ++ * interrupt will prevent that. ++ */ ++ next = node->tx_statq_next; ++ while (next->timestamp & 0x80000000) ; ++ ++ while (!(node->tx_statq_next->timestamp & 0x80000000)) { ++ PRINTK("nicstar%d: Tx statq entry 0x%x 0x%x\n", ++ node->index, ++ node->tx_statq_next->status, ++ node->tx_statq_next->timestamp); ++ ++ PRINTK ("Processing entry at %x with val %x\n",(u32) node->tx_statq_next, node->tx_statq_next->status); ++ ++#if 0 /* original method */ ++ if ((node->tx_statq_next->status & 0xffff0000) == SCQFULL_MAGIC) { ++ drain_scq(node, node->scq, node->tx_statq_next->status & 0xffff); ++ /* SCQ drained, wake 'er up */ ++ node->scq->full = 0; ++ wake_up_interruptible(&node->scq->scqfull_waitq); ++ } ++#else ++ id = (node->tx_statq_next->status & 0xf0000000) >> 16; ++ switch (id) { ++ case (SCQFULL_MAGIC >> 16): ++ scq = node->scq; ++ break; ++#if NICSTAR_CBR ++ case (CBRSCQFULL_MAGIC_CLOSE >> 16): ++ scq = node->vci_map[(node->tx_statq_next->status & 0x0fff0000)>>16].scq; ++ scq->closing = 1; ++ break; ++ case (CBRSCQFULL_MAGIC >> 16): ++ scq = node->vci_map[(node->tx_statq_next->status & 0x0fff0000)>>16].scq; ++ break; ++#endif ++ default: ++ scq = node->scq; ++ } ++ PRINTK ("Draining SCQ %d at %x\n",id,(u32)scq); ++ drain_scq(node, scq, node->tx_statq_next->status & 0xffff); ++ /* SCQ drained, wake 'er up */ ++ scq->full = 0; ++ wake_up_interruptible(&scq->scqfull_waitq); ++#endif ++ ++ node->tx_statq_next->timestamp |= 0x80000000; ++ ++ if (node->tx_statq_next == node->tx_statq_last) ++ node->tx_statq_next = node->tx_statq; ++ else ++ node->tx_statq_next++; ++ } ++ ++ writel((u32)node->tx_statq_next - (u32)node->tx_statq, ++ node->membase + TSQH); ++ ++ return; ++} ++ ++#if NICSTAR_RCQ ++static void process_rx_rawcellq (nicstar_devp node) { ++ u32 tail; ++ u32 timer; ++ u32 last; ++ int count; ++ ++ tail = readl(node->membase + RAWCT); ++ timer = readl(node->membase + TMR); ++ count = 0; ++ while (node->rcq.rcq_head != tail - RAWCELLSZ) { ++ if (count > 3) { ++ printk ("nicstar OOOPS. Count > 3\n"); ++ return; ++ } ++ /* service head */ ++ PRINTK ("nicstar: dequeueing 0x%x to 0x%x\n",(u32)node->rcq.rcq_head, ++ readl(node->membase + RAWCT)); ++ dequeue_rawcell((u32 *) node->rcq.rcq_head); ++ node->rcq.rcq_head += RAWCELLSZ; ++ last = node->rcq.rcq_base + LG_BUFSZ - RAWCELLSZ; ++ PRINTK ("Last %x tail %x rawct %x\n",(u32)last,(u32)tail,readl(node->membase + RAWCT)); ++ if (node->rcq.rcq_head == (node->rcq.rcq_base + LG_BUFSZ - RAWCELLSZ)) { ++ node->rcq.rcq_head = *((u32 *) node->rcq.rcq_head); ++ free_rx_buf(node, 1, node->rcq.rcq_base); ++ node->rcq.rcq_base = node->rcq.rcq_head; ++ if (node->rcq.rcq_base == tail) return; /* watch out for jumps */ ++ } ++ count++; ++ } ++ /* YYY Might be able to avoid this by polling the cell header; ++ requires initializing the header to a known value. Also ++ assumes that we can find such a known value */ ++ while (((readl(node->membase+TMR)) - timer) < 30); ++ /* service one cell */ ++ dequeue_rawcell((u32 *) node->rcq.rcq_head); ++ node->rcq.rcq_head += RAWCELLSZ; ++ if (node->rcq.rcq_head == (node->rcq.rcq_base + LG_BUFSZ - RAWCELLSZ)) { ++ node->rcq.rcq_head = *((u32 *) node->rcq.rcq_head); ++ free_rx_buf(node, 1, node->rcq.rcq_base); ++ node->rcq.rcq_base = node->rcq.rcq_head; ++ } ++} ++ ++static void dequeue_rawcell (u32 *cell) { ++ u32 header; ++ u32 *payload; ++ int i; ++ ++ header = *cell; ++ payload = cell + 4; ++ printk("nicstar: *Raw cell %x arrival hdr=%x pay=%x*\n", ++ (u32)cell,header,(u32)payload); ++ printk("nicstar: Header contents VCI=%d Last=%d\n", ++ header >> 4, (header & 0x2) >> 1); ++ if (header & 0x2) { ++ printk("nicstar: PDU length %d\n", ++ ((payload[10] & 0xff000000) >> 24) + ++ (256 * ((payload[10] & 0x00ff0000) >> 16))); ++ } ++ for (i = 0; i < 12; i++) { ++ printk (" %d 0x%x\n",i,(u32)payload[i]); ++ } ++} ++#endif /* NICSTAR_RCQ */ ++ ++static void process_rx_statq(nicstar_devp node) { ++ u32 prev; ++ ++ /* XXX Problem here: The 77201 can interrupt us (and set EPDU ++ * bits in STAT) before the Rx statq entry arrives in memory. ++ * The interrupt could be raised for multiple incoming PDUs, ++ * and we could miss seeing those entries that are slow to ++ * arrive in memory at the end of this loop. We'll see the PDU ++ * on the next Rx EPDU interrupt, of course. ++ */ ++ while (node->rx_statq_next->status & 0x80000000) { ++ PRINTK("nicstar%d: Rx statq entry 0x%x 0x%x 0x%x 0x%x\n", ++ node->index, ++ node->rx_statq_next->vpi_vci, ++ node->rx_statq_next->buf_handle, ++ node->rx_statq_next->crc, ++ node->rx_statq_next->status); ++ ++ dequeue_rx(node); ++ node->rx_statq_next->status = 0x0; ++ ++ if (node->rx_statq_next == node->rx_statq_last) ++ node->rx_statq_next = node->rx_statq; ++ else ++ node->rx_statq_next++; ++ ++ } ++ ++ /* Update the RSQH to point to the last entry actually processed. */ ++ if (node->rx_statq_next == node->rx_statq) { ++ prev = (u32)node->rx_statq_last; ++ } else { ++ prev = (u32)(node->rx_statq_next - 1); ++ } ++ writel((u32)prev - (u32)node->rx_statq, ++ node->membase + RSQH); ++ ++ PRINTK("RSQ: 0x%x, next 0x%x, diff 0x%x, tail 0x%x\n", ++ (u32)node->rx_statq, ++ (u32)node->rx_statq_next, ++ (u32)node->rx_statq_next - (u32)node->rx_statq, ++ readl(node->membase + RSQT)); ++ ++ PRINTK("nicstar%d: Status reads 0x%x.\n", node->index, ++ readl(node->membase + STAT)); ++ ++ return; ++} ++ ++static void push_rxbufs(nicstar_devp node, int lg, ++ u32 handle1, u32 addr1, u32 handle2, u32 addr2) { ++ ++ unsigned long flags; ++ int bc; ++ ++ ++ if (lg) { ++ bc = (readl(node->membase + STAT) & 0x00ff0000) >> 16; ++ } else { ++ bc = (readl(node->membase + STAT) & 0xff000000) >> 24; ++ } ++ if (bc >= 254) return; ++ ++ save_flags(flags); cli(); ++ while (CMD_BUSY(node)) ; ++ ++ writel(handle1, node->membase + DR0); ++ writel(addr1, node->membase + DR1); ++ writel(handle2, node->membase + DR2); ++ writel(addr2, node->membase + DR3); ++ ++ writel(0x60000000 | (lg ? 0x01 : 0x00), node->membase + CMD); ++ restore_flags(flags); ++ return; ++} ++ ++static void open_rx_connection(nicstar_devp node, ++ int index, ++ u32 status) { ++#if 0 ++ unsigned long flags; ++#endif ++ ++ u32 sram_addr = index * (sizeof(nicstar_rcte)/sizeof(u32)); ++ ++ write_sram(node, 1, sram_addr, status | 0x80000, ++ 0x0, 0x0, 0x0); ++ ++#if 0 ++ /* This is actually unnecessary, I believe, if we add the ++ open connection bit to the SRAM write. Alternately, if ++ we initialize the AAL during init_module, we can just ++ use the open connection command... (SWD) */ ++ save_flags(flags); cli(); ++ while (CMD_BUSY(node)) ; ++ writel(0x20080000 | (sram_addr << 2), node->membase + CMD); ++ restore_flags(flags); ++#endif ++} ++ ++static void close_rx_connection(nicstar_devp node, ++ int index) { ++ unsigned long flags; ++ u32 sram_addr = index * (sizeof(nicstar_rcte)/sizeof(u32)); ++ ++ save_flags(flags); cli(); ++ while (CMD_BUSY(node)) ; ++ writel(0x20000000 | (sram_addr << 2), node->membase + CMD); ++ restore_flags(flags); ++} ++ ++static void push_scq_entry(nicstar_devp node, struct nicstar_scq *scq, ++ nicstar_tbd *entry, ++ int xmit_now) { ++ ++ unsigned long flags; ++ nicstar_tbd magic_bullet = {0xa0000000, scq->id, 0x0, 0x0}; ++ static int delayed_bullet = 0; ++ ++ PRINTK("tail 0x%x next 0x%x\n", ++ (u32) scq->tail, (u32) scq->next); ++ PRINTK("CFG: 0x%x\n",readl(node->membase + CFG)); ++ ++ if (scq->tail == scq->next) { ++ PRINTK ("Going to sleep\n"); ++ /* Sleep until the tail moves */ ++ save_flags(flags); cli(); ++ scq->full = 1; ++ ++ current->timeout = jiffies + SCQFULL_TIMEOUT; ++ interruptible_sleep_on(&scq->scqfull_waitq); ++ restore_flags(flags); ++ ++ if (scq->full) { ++ printk("nicstar%d: SCQ drain timed out.\n",node->index); ++ scq->full = 0; ++ /* XXX Just proceed here, although the SAR's probably hosed ... */ ++ } ++ } ++ ++ *scq->next = *entry; ++ ++ if (scq->next == scq->last) ++ scq->next = scq->base; ++ else ++ scq->next++; ++ ++ if (((scq->next - scq->base) % NUM_SCQ_TRAIL) == NUM_SCQ_TRAIL-1) { ++ delayed_bullet = 1; ++ } ++ ++ if (xmit_now) { ++ if (delayed_bullet) { ++ delayed_bullet = 0; ++ magic_bullet.buf_addr |= (u32)(scq->next - scq->base); ++ if (scq->tail == scq->next) { ++ PRINTK ("Going to sleep!!\n"); ++ /* Sleep until the tail moves */ ++ save_flags(flags); cli(); ++ scq->full = 1; ++ ++ current->timeout = jiffies + SCQFULL_TIMEOUT; ++ interruptible_sleep_on(&scq->scqfull_waitq); ++ restore_flags(flags); ++ ++ if (scq->full) { ++ printk("nicstar%d: SCQ drain timed out.\n",node->index); ++ scq->full = 0; ++ /* XXX Just proceed here, although the SAR's probably hosed ... */ ++ } ++ } ++ *scq->next = magic_bullet; ++ if (scq->next == scq->last) ++ scq->next = scq->base; ++ else ++ scq->next++; ++ } ++ write_sram(node, 1, scq->scd, ++ (u32)(scq->next), ++ 0x0, 0x0, 0x0); ++ } ++ ++ return; ++} ++ ++static int get_ci(nicstar_devp node, ++ struct atm_vcc *vcc, ++ short *vpi, int *vci) { ++ nicstar_vcimap *mapval; ++ ++ PRINTK ("Reserving vci %d\n",(u32) *vci); ++ /* We accept VPI 0 and VCI 0-4095. */ ++ if (*vpi == ATM_VPI_UNSPEC || *vci == ATM_VCI_UNSPEC) return -EINVAL; ++ ++ if (*vpi == ATM_VPI_ANY) *vpi = 0; ++ if (*vpi != 0) return -EINVAL; ++ ++ if (*vci == ATM_VCI_ANY) { ++ /* Find lowest VCI */ ++#ifndef ATM_013 ++ for (*vci = ATM_NOT_RSV_VCI; *vci < NUM_VCI; (*vci)++) { ++ mapval = &(node->vci_map[*vci]); ++ if (vcc->qos.rxtp.traffic_class != ATM_NONE && mapval->rx) continue; ++ if (vcc->qos.txtp.traffic_class != ATM_NONE && mapval->tx) continue; ++ if (vcc->qos.rxtp.traffic_class != ATM_NONE) { ++ mapval->rx = 1; mapval->rx_vcc = vcc; ++ } ++ if (vcc->qos.txtp.traffic_class != ATM_NONE) { ++ mapval->tx = 1; mapval->tx_vcc = vcc; ++ } ++#else ++ if (vcc->qos.rxtp.class != ATM_NONE && mapval->rx) continue; ++ if (vcc->qos.txtp.class != ATM_NONE && mapval->tx) continue; ++ if (vcc->qos.rxtp.class != ATM_NONE) { ++ mapval->rx = 1; mapval->rx_vcc = vcc; ++ } ++ if (vcc->txtp.class != ATM_NONE) { ++ mapval->tx = 1; mapval->tx_vcc = vcc; ++ } ++ break; ++#endif /* ATM_013 */ ++ } ++ if (*vci == NUM_VCI) return -EADDRINUSE; ++ ++ } else { ++ /* Use this particular VCI */ ++ if (*vci >= NUM_VCI) return -EINVAL; ++ mapval = &(node->vci_map[*vci]); ++#ifndef ATM_013 ++ if (vcc->qos.rxtp.traffic_class != ATM_NONE && mapval->rx) return -EADDRINUSE; ++ if (vcc->qos.txtp.traffic_class != ATM_NONE && mapval->tx) return -EADDRINUSE; ++ if (vcc->qos.rxtp.traffic_class != ATM_NONE) { ++ mapval->rx = 1; mapval->rx_vcc = vcc; ++ } ++ if (vcc->qos.txtp.traffic_class != ATM_NONE) { ++ mapval->tx = 1; mapval->tx_vcc = vcc; ++ } ++#else ++ if (vcc->rxtp.class != ATM_NONE && mapval->rx) return -EADDRINUSE; ++ if (vcc->txtp.class != ATM_NONE && mapval->tx) return -EADDRINUSE; ++ if (vcc->rxtp.class != ATM_NONE) { ++ mapval->rx = 1; mapval->rx_vcc = vcc; ++ } ++ if (vcc->txtp.class != ATM_NONE) { ++ mapval->tx = 1; mapval->tx_vcc = vcc; ++ } ++#endif ++ } ++ ++ return 0; ++} ++ ++static void free_rx_buf(nicstar_devp node, int lg, u32 buf_addr) { ++ static u32 sm_buf = 0x0, lg_buf = 0x0; ++ ++ if (lg) { ++ /* Large buffer */ ++ if (lg_buf == 0x0) { ++ lg_buf = buf_addr; ++ } else { ++ u32 buf; ++ buf = buf_addr; ++ push_rxbufs(node, 1, lg_buf, lg_buf, buf, buf); ++ lg_buf = 0x0; ++ } ++ } else { ++ /* Small buffer */ ++ if (sm_buf == 0x0) { ++ sm_buf = buf_addr; ++ } else { ++ u32 buf; ++ buf = buf_addr; ++ push_rxbufs(node, 0, sm_buf, sm_buf, buf, buf); ++ sm_buf = 0x0; ++ } ++ } ++ return; ++} ++ ++static void dequeue_rx(nicstar_devp node) { ++ ++ struct atm_vcc *vcc; ++ struct sk_buff *skb; ++ struct iovec *iov; ++ nicstar_vcimap *mapval; ++ volatile nicstar_rsqe *entry = (volatile nicstar_rsqe *)node->rx_statq_next; ++ unsigned short aal5_len; ++ unsigned short aal0_len; ++ u32 *aal0_ptr; ++ ++ if ((entry->vpi_vci & 0x00ff0000) || ++ ((entry->vpi_vci & 0xffff) > NUM_VCI)) { ++ printk("nicstar%d: SDU received for out of range VC %d.%d.\n", ++ node->index, ++ entry->vpi_vci >> 16, ++ entry->vpi_vci & 0xffff); ++ return; ++ } ++ ++ mapval = &(node->vci_map[entry->vpi_vci]); ++ if (!mapval->rx) { ++ printk("nicstar%d: SDU received on inactive VC 0.%d.\n", ++ node->index, entry->vpi_vci); ++ } ++ vcc = mapval->rx_vcc; ++ ++ if (!(skb = mapval->rx_skb)) { ++ /* Starting new SKB */ ++ skb = mapval->rx_skb = skb_dequeue(&node->rx_skb_queue); ++ if (!skb) { ++ printk("nicstar%d: Out of Rx skb's!\n",node->index); ++ goto drop_message; ++ } ++ } ++ ++ if (vcc->aal == ATM_AAL0) { ++ iov = &(((struct iovec *)skb->data)[skb->atm.iovcnt]); ++ aal0_ptr = (u32 *)entry->buf_handle; ++ aal0_ptr--; ++ *(aal0_ptr) = /* "reconstruct" cell header */ ++ (entry->vpi_vci << 4) | ((entry->status & 0x4000) >> 14)| ++ ((entry->status & 0x400) >> 10); ++ PRINTK("Reconstructed cell header %x at %x, bufhandle %x\n", ++ *aal0_ptr,(u32)aal0_ptr,entry->buf_handle); ++ iov->iov_base = (void *)(aal0_ptr); ++ aal0_len = ATM_CELL_SIZE - 1; ++ iov->iov_len = aal0_len; ++ skb->len = aal0_len; ++ skb->atm.iovcnt++; ++ vcc->stats->rx++; ++ skb->atm.timestamp = xtime; ++ vcc->push(vcc, skb); ++ mapval->rx_skb = NULL; ++ return; ++ } ++ ++ iov = &(((struct iovec *)skb->data)[skb->atm.iovcnt]); ++ iov->iov_base = (void *)entry->buf_handle; ++ ++ if (entry->status & 0x2000) { ++ /* Last buffer, get AAL5 len */ ++ aal5_len = *(unsigned short *)((unsigned char *)entry->buf_handle + ((entry->status & 0x1ff)*48) - 6); ++ aal5_len = ((aal5_len & 0xff) << 8) | ((aal5_len & 0xff00) >> 8); ++ PRINTK ("Last buffer; AAL5 len is %d\n",aal5_len); ++ ++ iov->iov_len = aal5_len - skb->len; ++ skb->len = aal5_len; ++ skb->atm.iovcnt++; ++ vcc->stats->rx++; ++ ++ vcc->push(vcc, skb); ++ mapval->rx_skb = NULL; ++ } else { ++ iov->iov_len = (entry->status & 0x1ff) * 48; ++ skb->len += iov->iov_len; ++ skb->atm.iovcnt++; ++ } ++ return; ++ ++drop_message: ++ printk("nicstar%d: drop_message returned in dequeue_rx.\n",node->index); ++ vcc->stats->rx_drop++; ++ ++ if (entry->status & 0x1000) { ++ /* Large buffer */ ++ free_rx_buf(node, 1, entry->buf_handle); ++ } else { ++ /* Small buffer */ ++ free_rx_buf(node, 0, entry->buf_handle); ++ } ++ ++ return; ++} ++ ++static void nicstar_free_rx_skb(struct atm_vcc *vcc, struct sk_buff *skb) { ++ nicstar_devp node = vcc->dev->dev_data; ++ struct iovec *iov; ++ int i; ++ u32 ptr_chk; ++ ++ if (!skb->atm.iovcnt) { ++ /* XXX mdw: Eventually support this for single-cell transfers */ ++ printk("nicstar%d: free_rx_skb on non-iovec skb?\n", ++ node->index); ++ return; ++ } ++ ++ iov = (struct iovec *)skb->data; ++ for (i = 0; i < skb->atm.iovcnt; i++) { ++ if (((unsigned char *)iov[i].iov_base >= (unsigned char *)node->sm_bufs) && ++ ((unsigned char *)iov[i].iov_base < (unsigned char *)node->sm_bufs + SM_BUFSZ * NUM_SM_BUFS)) { ++ ptr_chk = (u32)iov[i].iov_base == (u32)node->sm_bufs ? 48 : ++ ((u32)iov[i].iov_base - ((u32)node->sm_bufs + 4)) % SM_BUFSZ; ++ if (ptr_chk) { ++ iov[0].iov_base += 4; ++#ifdef NICSTAR_PARANOID ++ if (ptr_chk != 48) { ++ printk ("nicstar%d: Misaligned buffer pointer (offset %d)!\n", ++ node->index,ptr_chk); ++ } ++ ptr_chk = (u32)iov[i].iov_base == (u32)node->sm_bufs ? 48 : ++ ((u32)iov[i].iov_base - ((u32)node->sm_bufs + 4)) % SM_BUFSZ; ++ if (ptr_chk) { ++ printk("nicstar%d: Misaligned pointer STILL NOT FIXED!!! %x %d\n", ++ node->index,(u32)iov[i].iov_base,ptr_chk); ++ } ++#endif ++ } ++ free_rx_buf(node, 0, (u32)(iov[i].iov_base)); ++ } else { ++ /* Large buffer */ ++ free_rx_buf(node, 1, (u32)(iov[i].iov_base)); ++ } ++ } ++ ++ skb->atm.iovcnt = 0; ++ skb->len = 0; ++ skb_queue_tail(&node->rx_skb_queue, skb); ++ ++ return; ++} ++ ++static void drain_scq(nicstar_devp node, struct nicstar_scq *scq, int index) { ++ nicstar_tbd *last = scq->base + index; ++ int sindex = scq->tail - scq->base; ++ struct sk_buff *skb; ++ struct atm_vcc *vcc; ++ ++ while (scq->tail != last) { ++ if ((skb = scq->scq_shadow[sindex].skb)) { ++ vcc = skb->atm.vcc; ++ if (skb->free == 2) printk("drain_scq: Passed skb 0x%x with free == 2.\n", (u32) skb); ++ if (vcc->pop) { ++ vcc->pop(vcc, skb); ++ } else { ++ dev_kfree_skb(skb, FREE_WRITE); ++ } ++ scq->scq_shadow[sindex].skb = 0; ++ } ++ ++ if (scq->tail == scq->last) { ++ scq->tail = scq->base; sindex = 0; ++ } else { ++ scq->tail++; sindex++; ++ } ++ } ++ ++ ++#ifdef NICSTAR_CBR ++ if (scq->closing) { ++ close_cbr_final(node,node->vci_map[(scq->id >> 16) & 0xfff].tx_vcc); ++ } ++#endif ++} ++ ++#ifdef NICSTAR_CBR ++static void alloc_tx(nicstar_devp node, struct atm_vcc *vcc) { ++ int i, j; ++ int slots; ++ int spacing; ++ int vci; ++ ++ vci = vcc->vci; ++ create_scq(&((node->vci_map[vci]).scq),CBRSCQ_SIZE); ++ (node->vci_map[vci].scq)->id = CBRSCQFULL_MAGIC | (vci << 16); ++ PRINTK ("nicstar%d: Allocating CBR SCQ at %x\n",node->index,(u32) ((node->vci_map[vci]).scq)); ++ PRINTK ("nicstar%d: Allocating transmission bandwidth\n",node->index); ++#ifndef ATM_013 ++ printk ("in pcr: %d/%d/%d\n",vcc->qos.txtp.min_pcr, ++ vcc->qos.txtp.max_pcr,node->max_pcr); ++#else ++ printk ("in pcr: %d/%d/%d\n",vcc->txtp.min_pcr, ++ vcc->txtp.max_pcr,node->max_pcr); ++#endif ++ (node->vci_map[vci].scq)->scd = 0; /* initialize SCD pointer */ ++#ifndef ATM_013 ++ slots = (u32) (((float) vcc->qos.txtp.max_pcr / (float) node->max_pcr) * (float) TST_SIZE) + 1; ++#else ++ slots = (u32) (((float) vcc->txtp.max_pcr / (float) node->max_pcr) * (float) TST_SIZE) + 1; ++#endif ++ printk ("out: %d slots\n",slots); ++ if (slots > node->available_slots) { ++ printk("Reducing requested BW from %d to %d slots -- full up\n", ++ slots,node->available_slots); ++ slots = node->available_slots; ++ } ++ node->available_slots -= slots; ++ spacing = TST_SIZE / slots; ++ /* sort of randomly pick starting slot */ ++ i = readl(node->membase + TMR) % TST_SIZE; ++ while (slots > 0) { ++ j = i; ++ while (node->host_tst[j]) { ++ j++; ++ if (j >= TST_SIZE) { ++ j -= TST_SIZE; ++ } ++ } ++ if (!((node->vci_map[vci].scq)->scd)) { ++ (node->vci_map[vci].scq)->scd = NICSTAR_SCD_REGION + 12 * j; ++ write_sram(node, 4, NICSTAR_SCD_REGION + 12 * j, ++ (u32) ((nicstar_vcimap *)vcc->dev_data)->scq->base, /* base + head */ ++ 0x0, /* tail */ ++ 0xffffffff, /* aal5 crc */ ++ 0x0); ++ /* should we also init next 8 words to 0? */ ++ PRINTK ("CBR SCQ at j %d sram %x ptr %x\n",j, ++ NICSTAR_SCD_REGION + 12 * j, ++ read_sram(node,NICSTAR_SCD_REGION + 12 * j)); ++ } ++ node->host_tst[j] = (u32) vcc; ++ write_sram(node, 1, NICSTAR_TST_REGION + j, ++ TSTE_CBR | (node->vci_map[vci].scq)->scd, ++ 0x0, 0x0, 0x0); ++ i += spacing; ++ if (i >= TST_SIZE) { ++ i -= TST_SIZE; ++ } ++ slots--; ++ } ++#if 0 /* dumps TST */ ++ for (i = 0; i < TST_SIZE; i+=4) { ++ printk("%d %08x %08x %08x %08x\n",i, ++ read_sram(node, NICSTAR_TST_REGION + i), ++ read_sram(node, NICSTAR_TST_REGION + i + 1), ++ read_sram(node, NICSTAR_TST_REGION + i + 2), ++ read_sram(node, NICSTAR_TST_REGION + i + 3)); ++ } ++#endif ++} ++ ++/* Closes down a CBR connection. */ ++static void close_cbr (nicstar_devp node, struct atm_vcc *vcc) { ++ unsigned long flags; ++ struct nicstar_scq *scq = ((nicstar_vcimap *)vcc->dev_data)->scq; ++ ++ PRINTK("Initial close down of CBR connection %x...",(u32) vcc); ++ /* Push a TSR */ ++ if (scq->tail == scq->next) { ++ /* Sleep until the tail moves */ ++ save_flags(flags); cli(); ++ scq->full = 1; ++ ++ current->timeout = jiffies + SCQFULL_TIMEOUT; ++ interruptible_sleep_on(&scq->scqfull_waitq); ++ restore_flags(flags); ++ ++ if (scq->full) { ++ printk("nicstar%d: SCQ drain timed out.\n",node->index); ++ scq->full = 0; ++ /* XXX Just proceed here, although the SAR's probably hosed ... */ ++ } ++ } ++ ++ PRINTK("Writing TSR\n"); ++ ++ scq->next->status = 0xa0000000; ++ scq->next->buf_addr = CBRSCQFULL_MAGIC_CLOSE | scq->id | (u32)(scq->next - scq->base); ++ scq->next->ctl_len = 0; ++ scq->next->cell_hdr = 0; ++ ++ if (scq->next == scq->last) ++ scq->next = scq->base; ++ else ++ scq->next++; ++ write_sram(node, 1, scq->scd, ++ (u32)(scq->next), ++ 0x0, 0x0, 0x0); ++} ++ ++static void close_cbr_final (nicstar_devp node, struct atm_vcc *vcc) { ++ int i, count; ++ ++ for (i = 0; i < TST_SIZE; i++) { ++ if (node->host_tst[i] == (u32) vcc) { ++ node->host_tst[i] = 0; ++ node->available_slots += 1; ++ write_sram(node,1, NICSTAR_TST_REGION + i, ++ TSTE_VBR, 0x0, 0x0, 0x0); ++ } ++ } ++ count = 0; ++ for (i = 0; i < TST_SIZE; i++) { ++ if (read_sram(node,NICSTAR_TST_REGION + i) != TSTE_VBR) { ++ count ++; ++ } ++ } ++ PRINTK ("non-VBR Count %d avail slots %d\n",count, node->available_slots); ++ /* free up the CBR SCQ */ ++ kfree(((nicstar_vcimap *)vcc->dev_data)->scq->orig); ++ kfree(((nicstar_vcimap *)vcc->dev_data)->scq); ++} ++#endif ++ ++/* General function for creating transmission SCQs */ ++static int create_scq (struct nicstar_scq **scq, int size) { ++ (*scq) = kmalloc(sizeof(struct nicstar_scq), GFP_KERNEL); ++ (*scq)->orig = kmalloc(2*size, GFP_KERNEL); ++ if (!(*scq)->orig) { ++ return -ENOMEM; ++ } ++ (*scq)->base = (nicstar_tbd *)(((u32)(*scq)->orig + (size - 1)) & ~(size - 1)); ++ (*scq)->next = (*scq)->base; ++ (*scq)->last = (*scq)->base + ((size / TBD_SIZE) - 1); ++ (*scq)->tail = (*scq)->last; /* XXX mdw scq_next */ ++ (*scq)->full = 0; ++ (*scq)->scqfull_waitq = NULL; ++ (*scq)->closing = 0; ++ memset (((*scq)->scq_shadow), 0, ++ (SCQ_ENTRIES) * (sizeof(struct nicstar_scq_shadow))); ++ return 0; ++} +--- ref/include/linux/pci.h Wed Nov 6 11:12:35 1996 ++++ work/include/linux/pci.h Fri Nov 15 19:58:19 1996 +@@ -241,6 +241,9 @@ + #define PCI_DEVICE_ID_VLSI_82C594 0x0007 + #define PCI_DEVICE_ID_VLSI_82C597 0x0009 + ++#define PCI_VENDOR_ID_IDT 0x111d ++#define PCI_DEVICE_ID_IDT_IDT77201 0x0001 ++ + #define PCI_VENDOR_ID_ADL 0x1005 + #define PCI_DEVICE_ID_ADL_2301 0x2301 + +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/include/linux/atm.h Fri Nov 15 20:55:15 1996 @@ -0,0 +1,216 @@ +/* atm.h - general ATM declarations */ + @@ -8587,8 +10820,8 @@ +#endif /* __KERNEL__ */ + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmclip.h Wed Nov 13 11:48:45 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/include/linux/atmclip.h Fri Nov 15 21:36:38 1996 @@ -0,0 +1,37 @@ +/* atmclip.h - Classical IP over ATM */ + @@ -8627,9 +10860,9 @@ +#endif /* __KERNEL__ */ + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmdev.h Wed Nov 13 11:52:05 1996 -@@ -0,0 +1,255 @@ +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/include/linux/atmdev.h Fri Nov 15 20:55:15 1996 +@@ -0,0 +1,257 @@ +/* atmdev.h - ATM device driver declarations */ + +/* Written 1995,1996 by Werner Almesberger, EPFL LRC */ @@ -8867,6 +11100,8 @@ + void (*feedback)(struct atm_vcc *vcc,struct sk_buff *skb, + unsigned long start,unsigned long dest,int len); + int (*change_qos)(struct atm_vcc *vcc,struct atm_qos *qos); ++ void (*free_rx_skb)(struct atm_vcc *vcc, struct sk_buff *skb); ++ /* @@@ temporary hack */ +}; + + @@ -8885,8 +11120,8 @@ +#endif /* __KERNEL__ */ + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmsap.h Wed Nov 6 18:36:55 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/include/linux/atmsap.h Fri Nov 15 19:06:29 1996 @@ -0,0 +1,124 @@ +/* atmsap.h - ATM Service Access Point addressing definitions */ + @@ -9012,8 +11247,8 @@ +}; + +#endif ---- ref/include/linux/skbuff.h Tue Aug 20 17:09:42 1996 -+++ work/include/linux/skbuff.h Wed Nov 13 11:55:46 1996 +--- ref/include/linux/skbuff.h Thu Oct 31 11:06:31 1996 ++++ work/include/linux/skbuff.h Fri Nov 15 20:55:15 1996 @@ -112,6 +112,21 @@ unsigned char *end; /* End pointer */ void (*destructor)(struct sk_buff *); /* Destruct function */ @@ -9036,8 +11271,8 @@ }; #ifdef CONFIG_SKB_LARGE ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/sonet.h Wed Aug 21 10:55:45 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/include/linux/sonet.h Fri Nov 15 19:06:30 1996 @@ -0,0 +1,52 @@ +/* sonet.h - SONET/SHD physical layer control */ + @@ -9091,8 +11326,8 @@ +#define SONET_FRSENSE_SIZE 6 /* C1[3],H1[3] (0xff for unknown) */ + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmsvc.h Thu Nov 7 16:08:51 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/include/linux/atmsvc.h Fri Nov 15 21:36:38 1996 @@ -0,0 +1,51 @@ +/* atmsvc.h - ATM signaling kernel-demon interface definitions */ + @@ -9145,8 +11380,8 @@ + (tp).max_pcr : (tp).min_pcr ? (tp).min_pcr : ATM_MAX_PCR) + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmioc.h Wed Aug 21 10:55:45 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/include/linux/atmioc.h Fri Nov 15 19:06:30 1996 @@ -0,0 +1,32 @@ +/* atmioc.h - ranges for ATM-related ioctl numbers */ + @@ -9181,7 +11416,7 @@ + +#endif --- ref/net/Makefile Thu May 16 15:35:55 1996 -+++ work/net/Makefile Thu Aug 29 12:11:54 1996 ++++ work/net/Makefile Fri Nov 15 19:06:31 1996 @@ -7,13 +7,18 @@ # # Note 2! The CFLAGS definition is now in the main makefile... @@ -9203,8 +11438,8 @@ endif ifeq ($(CONFIG_INET),y) ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/Makefile Wed Aug 21 10:55:46 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/Makefile Fri Nov 15 19:06:31 1996 @@ -0,0 +1,54 @@ +# +# Makefile for the ATM Protocol Families. @@ -9260,8 +11495,8 @@ + + +include $(TOPDIR)/Rules.make ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/clip.c Mon Sep 9 14:04:35 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/clip.c Fri Nov 15 19:06:31 1996 @@ -0,0 +1,116 @@ +/* net/atm/clip.c - Classical IP over ATM */ + @@ -9379,9 +11614,9 @@ + DPRINTK("registered %s,0x%lx\n",dev->name,(unsigned long) vcc); + return CLIP(dev)->number; +} ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/common.c Fri Nov 8 17:40:50 1996 -@@ -0,0 +1,933 @@ +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/common.c Fri Nov 15 20:12:51 1996 +@@ -0,0 +1,953 @@ +/* net/atm/common.c - ATM sockets (common part for PVC and SVC) */ + +/* Written 1995,1996 by Werner Almesberger, EPFL LRC */ @@ -9507,7 +11742,9 @@ + if (vcc->push) vcc->push(vcc,NULL); /* atmarpd has no push */ + while ((skb = skb_dequeue(&vcc->recvq))) { + atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->rx_inuse); -+ kfree_skb(skb,FREE_READ); ++ if (vcc->dev->ops->free_rx_skb) ++ vcc->dev->ops->free_rx_skb(vcc,skb); ++ else kfree_skb(skb,FREE_READ); + } + if (vcc->rx_inuse) + printk(KERN_WARNING "atm_release_vcc: strange ... " @@ -9767,6 +12004,24 @@ + (unsigned long) buff,eff_len); + DPRINTK("RcvM %d -= %d\n",vcc->rx_inuse,skb->truesize); + atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->rx_inuse); ++ if (skb->atm.iovcnt) { /* @@@ hack */ ++ /* iovcnt set, use scatter-gather for receive */ ++ int el, cnt; ++ struct iovec *iov = (struct iovec *)skb->data; ++ unsigned char *p = (unsigned char *)buff; ++ ++ el = eff_len; ++ for (cnt = 0; (cnt < skb->atm.iovcnt) && el; cnt++) { ++ memcpy_tofs(p, iov->iov_base, ++ (iov->iov_len > el) ? el : iov->iov_len); ++ p += iov->iov_len; ++ el -= (iov->iov_len > el)?el:iov->iov_len; ++ iov++; ++ } ++ if (!vcc->dev->ops->free_rx_skb) kfree_skb(skb,FREE_READ); ++ else vcc->dev->ops->free_rx_skb(vcc, skb); ++ return eff_len; ++ } +#ifdef CONFIG_MMU_HACKS + if (vcc->flags & ATM_VF_SCRX) + mmucp_tofs((unsigned long) buff,eff_len,skb, @@ -10315,8 +12570,8 @@ + if (!vcc->dev || !vcc->dev->ops->getsockopt) return -EINVAL; + return vcc->dev->ops->getsockopt(vcc,level,optname,optval,optlen); +} ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/common.h Wed Aug 21 10:55:47 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/common.h Fri Nov 15 19:06:32 1996 @@ -0,0 +1,32 @@ +/* net/atm/common.h - ATM sockets (common part for PVC and SVC) */ + @@ -10350,8 +12605,8 @@ +void svc_callback(struct atm_vcc *vcc); + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/dev.c Wed Aug 21 10:55:47 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/dev.c Fri Nov 15 19:06:32 1996 @@ -0,0 +1,38 @@ +/* net/atm/dev.c - ATM device registeration */ + @@ -10391,8 +12646,8 @@ +{ + free_atm_dev(dev); +} ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/pvc.c Fri Oct 4 14:25:32 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/pvc.c Fri Nov 15 19:06:32 1996 @@ -0,0 +1,175 @@ +/* net/atm/pvc.c - ATM PVC sockets */ + @@ -10569,8 +12824,8 @@ + (void) atm_init_arequipa(); +#endif +} ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/static.c Wed Aug 21 10:55:47 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/static.c Fri Nov 15 19:06:33 1996 @@ -0,0 +1,114 @@ +/* net/atm/static.c - Staticly allocated resources */ + @@ -10686,8 +12941,8 @@ + for (i = 0; i < MAX_ATM_VCC; i++) + if (atm_vcc[i].family) fn(atm_vcc+i); +} ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/static.h Wed Nov 13 11:48:45 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/static.h Fri Nov 15 21:36:38 1996 @@ -0,0 +1,29 @@ +/* net/atm/static.h - Staticly allocated resources */ + @@ -10718,8 +12973,8 @@ +void for_all_vccs(void (*fn)(struct atm_vcc *vcc)); + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/svc.c Thu Oct 17 15:00:17 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/svc.c Fri Nov 15 19:06:33 1996 @@ -0,0 +1,604 @@ +/* net/atm/svc.c - ATM SVC sockets */ + @@ -11325,8 +13580,8 @@ + return; + } +} ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/signaling.c Mon Oct 28 19:03:19 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/signaling.c Fri Nov 15 19:06:34 1996 @@ -0,0 +1,215 @@ +/* net/atm/signaling.c - ATM signaling */ + @@ -11543,8 +13798,8 @@ + wake_up(&sigd_sleep); + return 0; +} ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/signaling.h Wed Nov 13 11:48:45 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/signaling.h Fri Nov 15 21:36:38 1996 @@ -0,0 +1,25 @@ +/* net/atm/signaling.h - ATM signaling */ + @@ -11571,8 +13826,8 @@ +int sigd_attach(struct atm_vcc *vcc); + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/atmarp.c Sun Oct 13 19:41:26 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/atmarp.c Fri Nov 15 19:06:35 1996 @@ -0,0 +1,605 @@ +/* atmarp.c - RFC1577 ATM ARP */ + @@ -12179,8 +14434,8 @@ + register_netdevice_notifier(&clip_dev_notifier); + return 0; +} ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/atmarp.h Wed Nov 13 11:48:45 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/atmarp.h Fri Nov 15 21:36:38 1996 @@ -0,0 +1,53 @@ +/* net/atm/atmarp.h - RFC1577 ATM ARP */ + @@ -12235,8 +14490,8 @@ +int atmarp_encap(struct atm_vcc *vcc,int mode); + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/ipcommon.h Wed Nov 13 11:49:38 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/ipcommon.h Fri Nov 15 21:37:21 1996 @@ -0,0 +1,73 @@ +/* net/atm/ipcommon.h - Common items for all ways of doing IP over ATM */ + @@ -12311,8 +14566,8 @@ +int ipcom_pick_number(int number); + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/ipcommon.c Mon Sep 9 20:07:49 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/ipcommon.c Fri Nov 15 19:06:36 1996 @@ -0,0 +1,214 @@ +/* net/atm/ipcommon.c - Common items for all ways of doing IP over ATM */ + @@ -12528,8 +14783,8 @@ + } + return number; +} ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/arequipa.c Thu Oct 31 11:55:24 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/arequipa.c Fri Nov 15 19:06:36 1996 @@ -0,0 +1,438 @@ +/* net/atm/arequipa.c - Application requested IP over ATM */ + @@ -12969,8 +15224,8 @@ + return 0; + +} ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/tunable.h Wed Aug 21 10:55:50 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/tunable.h Fri Nov 15 19:06:36 1996 @@ -0,0 +1,26 @@ +/* net/atm/tunable.h - Tunable parameters of ATM support */ + @@ -12998,8 +15253,8 @@ + quota per PDU */ + +#endif ---- ref/net/ipv4/af_inet.c Sun Aug 4 11:56:25 1996 -+++ work/net/ipv4/af_inet.c Thu Oct 17 12:32:11 1996 +--- ref/net/ipv4/af_inet.c Fri Oct 18 05:18:54 1996 ++++ work/net/ipv4/af_inet.c Fri Nov 15 19:06:37 1996 @@ -105,6 +105,14 @@ #include #endif @@ -13047,15 +15302,7 @@ sk->socket = sock; #ifdef CONFIG_TCP_NAGLE_OFF sk->nonagle = 1; -@@ -673,6 +692,7 @@ - sk->rcvbuf = SK_RMEM_MAX; - sk->rto = TCP_TIMEOUT_INIT; /*TCP_WRITE_TIME*/ - sk->cong_window = 1; /* start with only sending one packet at a time. */ -+ sk->ssthresh = 0x7fffffff; - sk->priority = 1; - sk->state = TCP_CLOSE; - -@@ -1339,7 +1359,18 @@ +@@ -1340,7 +1359,18 @@ return((*dlci_ioctl_hook)(cmd, (void *) arg)); #endif return -ENOPKG; @@ -13076,7 +15323,7 @@ if ((cmd >= SIOCDEVPRIVATE) && (cmd <= (SIOCDEVPRIVATE + 15))) --- ref/net/protocols.c Sat Mar 30 12:20:34 1996 -+++ work/net/protocols.c Wed Aug 21 10:55:51 1996 ++++ work/net/protocols.c Fri Nov 15 19:06:37 1996 @@ -42,6 +42,10 @@ #include extern void rif_init(struct net_proto *); @@ -13099,8 +15346,8 @@ #endif { NULL, NULL } /* End marker */ }; ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/mmuio.c Wed Aug 21 10:55:51 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/mmuio.c Fri Nov 15 19:06:38 1996 @@ -0,0 +1,455 @@ +/* net/atm/mmuio.c - MMU-supported high-speed I/O */ + @@ -13557,8 +15804,8 @@ +} + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/mmuio.h Wed Nov 13 11:48:45 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/include/linux/mmuio.h Fri Nov 15 21:36:38 1996 @@ -0,0 +1,25 @@ +/* mmuio.h - MMU-supported high-speed I/O */ + @@ -13585,8 +15832,8 @@ +#endif + +#endif ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/raw.c Wed Aug 21 10:55:52 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/raw.c Fri Nov 15 19:06:39 1996 @@ -0,0 +1,139 @@ +/* net/atm/raw.c - Raw AAL0 and AAL5 transports */ + @@ -13727,8 +15974,8 @@ + vcc->push_oam = NULL; + return 0; +} ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/protocols.h Wed Aug 21 10:55:52 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/protocols.h Fri Nov 15 19:06:39 1996 @@ -0,0 +1,17 @@ +/* net/atm/protocols.h - ATM protocol handler entry points */ + @@ -13747,9 +15994,9 @@ +int atm_init_atmarp(struct atm_vcc *vcc);/* ATM ARP */ + +#endif ---- ref/include/linux/netdevice.h Tue Aug 20 17:11:35 1996 -+++ work/include/linux/netdevice.h Wed Nov 13 11:55:46 1996 -@@ -185,6 +185,8 @@ +--- ref/include/linux/netdevice.h Thu Oct 31 11:06:31 1996 ++++ work/include/linux/netdevice.h Fri Nov 15 20:55:15 1996 +@@ -187,6 +187,8 @@ int (*set_mac_address)(struct device *dev, void *addr); #define HAVE_PRIVATE_IOCTL int (*do_ioctl)(struct device *dev, struct ifreq *ifr, int cmd); @@ -13758,17 +16005,17 @@ #define HAVE_SET_CONFIG int (*set_config)(struct device *dev, struct ifmap *map); #define HAVE_HEADER_CACHE -@@ -285,6 +287,8 @@ +@@ -287,6 +289,8 @@ /* These functions live elsewhere (drivers/net/net_init.c, but related) */ extern void ether_setup(struct device *dev); +extern int ether_arp(struct device *dev,unsigned int cmd, + void *arg); extern void tr_setup(struct device *dev); + extern void fddi_setup(struct device *dev); extern int ether_config(struct device *dev, struct ifmap *map); - /* Support for loadable net-drivers */ ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmarp.h Thu Nov 7 16:08:51 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/include/linux/atmarp.h Fri Nov 15 21:36:38 1996 @@ -0,0 +1,99 @@ +/* atmarp.h - ATM ARP protocol and kernel-demon interface definitions */ + @@ -13869,8 +16116,8 @@ +}; + +#endif ---- ref/net/ipv4/udp.c Tue Jun 4 14:34:43 1996 -+++ work/net/ipv4/udp.c Fri Sep 27 14:53:25 1996 +--- ref/net/ipv4/udp.c Sun Oct 6 15:42:09 1996 ++++ work/net/ipv4/udp.c Fri Nov 15 19:06:40 1996 @@ -109,6 +109,11 @@ #include #include @@ -13906,9 +16153,9 @@ skb->sk = sk; if (sk->users) { ---- ref/net/ipv4/tcp.c Sun Aug 4 12:56:54 1996 -+++ work/net/ipv4/tcp.c Fri Oct 18 18:59:46 1996 -@@ -1936,6 +1936,9 @@ +--- ref/net/ipv4/tcp.c Wed Nov 6 13:39:47 1996 ++++ work/net/ipv4/tcp.c Fri Nov 15 19:06:41 1996 +@@ -1948,6 +1948,9 @@ int atype; struct tcphdr *t1; struct rtable *rt; @@ -13918,7 +16165,7 @@ if (sk->state != TCP_CLOSE) return(-EISCONN); -@@ -1991,6 +1994,11 @@ +@@ -2003,6 +2006,11 @@ * Put in the IP header and routing stuff. */ @@ -13930,7 +16177,7 @@ tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev, IPPROTO_TCP, sk->opt, MAX_SYN_SIZE,sk->ip_tos,sk->ip_ttl,&sk->ip_route_cache); if (tmp < 0) -@@ -2002,6 +2010,11 @@ +@@ -2014,6 +2022,11 @@ if ((rt = sk->ip_route_cache) != NULL && !sk->saddr) sk->saddr = rt->rt_src; sk->rcv_saddr = sk->saddr; @@ -13942,7 +16189,7 @@ /* * Set up our outgoing TCP sequence number -@@ -2065,14 +2078,35 @@ +@@ -2062,14 +2075,35 @@ * Put in the TCP options to say MTU. */ @@ -13972,19 +16219,19 @@ + ptr[6] = TCPOLEN_WINDOW; + ptr[7] = sk->rcv_wscale; + buff->csum = csum_partial(ptr,TCPOLEN_MSS+TCPOLEN_NOP+TCPOLEN_WINDOW,0); - tcp_send_check(t1, sk->saddr, sk->daddr, -- sizeof(struct tcphdr) + 4, buff); ++ tcp_send_check(t1, sk->saddr, sk->daddr, + sizeof(struct tcphdr)+TCPOLEN_MSS+TCPOLEN_NOP+TCPOLEN_WINDOW,buff); +#else + buff->csum = csum_partial(ptr, TCPOLEN_MSS, 0); -+ tcp_send_check(t1, sk->saddr, sk->daddr, + tcp_send_check(t1, sk->saddr, sk->daddr, +- sizeof(struct tcphdr) + 4, buff); + sizeof(struct tcphdr) + TCPOLEN_MSS, buff); +#endif /* * This must go first otherwise a really quick response will get reset. ---- ref/net/ipv4/ip_forward.c Wed Aug 7 12:59:29 1996 -+++ work/net/ipv4/ip_forward.c Mon Sep 9 19:04:51 1996 +--- ref/net/ipv4/ip_forward.c Wed Oct 30 02:42:42 1996 ++++ work/net/ipv4/ip_forward.c Fri Nov 15 19:06:42 1996 @@ -39,6 +39,9 @@ #include #include @@ -14007,8 +16254,8 @@ { /* Tell the sender its packet died... */ icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0, dev); ---- ref/include/linux/proc_fs.h Tue Aug 20 17:09:42 1996 -+++ work/include/linux/proc_fs.h Wed Nov 13 11:53:41 1996 +--- ref/include/linux/proc_fs.h Wed Oct 30 03:53:15 1996 ++++ work/include/linux/proc_fs.h Fri Nov 15 20:55:15 1996 @@ -34,6 +34,7 @@ PROC_KSYMS, PROC_DMA, @@ -14050,7 +16297,7 @@ #endif --- ref/fs/proc/root.c Tue Apr 30 12:09:45 1996 -+++ work/fs/proc/root.c Wed Aug 21 10:55:56 1996 ++++ work/fs/proc/root.c Fri Nov 15 19:06:42 1996 @@ -15,6 +15,10 @@ #include #include @@ -14092,7 +16339,7 @@ #ifdef CONFIG_DEBUG_MALLOC proc_register(&proc_root, &(struct proc_dir_entry) { --- ref/fs/proc/inode.c Thu Apr 25 15:32:45 1996 -+++ work/fs/proc/inode.c Wed Aug 21 10:55:56 1996 ++++ work/fs/proc/inode.c Fri Nov 15 19:06:43 1996 @@ -4,6 +4,7 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ @@ -14130,8 +16377,8 @@ case PROC_KCORE: inode->i_mode = S_IFREG | S_IRUSR; inode->i_op = &proc_kcore_inode_operations; ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/proc.c Thu Sep 26 22:12:08 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/proc.c Fri Nov 15 19:06:43 1996 @@ -0,0 +1,501 @@ +/* net/atm/proc.c - ATM /proc interface */ + @@ -14634,9 +16881,9 @@ + proc_register(FILE(PROC_ATM_AREQUIPA,"arequipa",8)); +#endif +} ---- ref/drivers/char/console.c Wed Jul 24 09:49:53 1996 -+++ work/drivers/char/console.c Wed Aug 21 10:55:58 1996 -@@ -1972,6 +1972,43 @@ +--- ref/drivers/char/console.c Thu Nov 7 10:25:21 1996 ++++ work/drivers/char/console.c Fri Nov 15 19:06:44 1996 +@@ -1982,6 +1982,43 @@ } } @@ -14680,7 +16927,7 @@ /* * unsigned long con_init(unsigned long); * -@@ -2090,6 +2127,11 @@ +@@ -2100,6 +2137,11 @@ display_desc, video_num_columns, video_num_lines, MIN_NR_CONSOLES, (MIN_NR_CONSOLES == 1) ? "" : "s", MAX_NR_CONSOLES); @@ -14692,9 +16939,19 @@ /* * can't register TGA yet, because PCI bus probe has *not* taken ---- ref/init/main.c Mon May 20 19:33:57 1996 -+++ work/init/main.c Fri Oct 4 14:16:14 1996 -@@ -172,9 +172,14 @@ +--- ref/init/main.c Wed Oct 30 02:42:41 1996 ++++ work/init/main.c Fri Nov 15 19:06:45 1996 +@@ -36,6 +36,9 @@ + #ifdef CONFIG_ROOT_NFS + #include + #endif ++#ifdef CONFIG_BIGPHYS_AREA ++#include ++#endif + + #include + +@@ -174,6 +177,8 @@ #endif @@ -14703,13 +16960,7 @@ #if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD) extern void ipc_init(void); #endif -+#ifdef CONFIG_BIGPHYS_AREA -+extern void bigphysarea_setup(char *str, int *ints); -+#endif - - /* - * Boot command-line arguments -@@ -409,6 +414,10 @@ +@@ -415,6 +420,10 @@ #ifdef CONFIG_BAYCOM { "baycom=", baycom_setup }, #endif @@ -14720,7 +16971,7 @@ { 0, 0 } }; -@@ -799,6 +808,9 @@ +@@ -806,6 +815,9 @@ memory_start = console_init(memory_start,memory_end); #ifdef CONFIG_PCI memory_start = pci_init(memory_start,memory_end); @@ -14730,8 +16981,8 @@ #endif memory_start = kmalloc_init(memory_start,memory_end); sti(); ---- ref/drivers/block/genhd.c Tue Aug 20 15:44:45 1996 -+++ work/drivers/block/genhd.c Wed Aug 21 10:55:59 1996 +--- ref/drivers/block/genhd.c Wed Aug 21 08:18:07 1996 ++++ work/drivers/block/genhd.c Fri Nov 15 19:06:46 1996 @@ -53,6 +53,7 @@ extern int blk_dev_init(void); extern int scsi_dev_init(void); @@ -14750,9 +17001,9 @@ #endif console_map_init(); ---- ref/drivers/net/net_init.c Sat Jun 29 11:00:46 1996 -+++ work/drivers/net/net_init.c Wed Aug 21 10:55:59 1996 -@@ -181,6 +181,7 @@ +--- ref/drivers/net/net_init.c Wed Nov 6 13:39:42 1996 ++++ work/drivers/net/net_init.c Fri Nov 15 19:06:46 1996 +@@ -199,6 +199,7 @@ dev->set_mac_address = eth_mac_addr; dev->header_cache_bind = eth_header_cache_bind; dev->header_cache_update= eth_header_cache_update; @@ -14760,8 +17011,8 @@ dev->type = ARPHRD_ETHER; dev->hard_header_len = ETH_HLEN; ---- ref/drivers/net/eql.c Mon May 6 11:26:08 1996 -+++ work/drivers/net/eql.c Wed Aug 21 10:56:01 1996 +--- ref/drivers/net/eql.c Sun Sep 22 20:17:08 1996 ++++ work/drivers/net/eql.c Fri Nov 15 19:06:47 1996 @@ -248,6 +248,7 @@ dev->open = eql_open; dev->stop = eql_close; @@ -14771,7 +17022,7 @@ dev->get_stats = eql_get_stats; --- ref/drivers/net/pi2.c Fri Mar 1 06:50:45 1996 -+++ work/drivers/net/pi2.c Wed Aug 21 10:56:02 1996 ++++ work/drivers/net/pi2.c Fri Nov 15 19:06:48 1996 @@ -1414,6 +1414,7 @@ dev->open = pi_open; dev->stop = pi_close; @@ -14780,8 +17031,8 @@ dev->hard_start_xmit = pi_send_packet; dev->get_stats = pi_get_stats; ---- ref/drivers/net/ppp.c Wed Jul 17 06:17:30 1996 -+++ work/drivers/net/ppp.c Thu Aug 29 12:16:26 1996 +--- ref/drivers/net/ppp.c Tue Oct 8 19:21:03 1996 ++++ work/drivers/net/ppp.c Fri Nov 15 19:06:50 1996 @@ -398,6 +398,7 @@ dev->stop = ppp_dev_close; dev->get_stats = ppp_dev_stats; @@ -14790,9 +17041,9 @@ dev->addr_len = 0; dev->tx_queue_len = 10; dev->type = ARPHRD_PPP; ---- ref/net/ipv4/arp.c Thu Aug 1 14:43:04 1996 -+++ work/net/ipv4/arp.c Wed Aug 21 10:56:06 1996 -@@ -2160,7 +2160,7 @@ +--- ref/net/ipv4/arp.c Wed Oct 30 02:42:42 1996 ++++ work/net/ipv4/arp.c Fri Nov 15 19:06:51 1996 +@@ -2201,7 +2201,7 @@ * Handle an ARP layer I/O control request. */ @@ -14801,7 +17052,7 @@ { int err; struct arpreq r; -@@ -2171,12 +2171,7 @@ +@@ -2212,12 +2212,7 @@ { case SIOCDARP: case SIOCSARP: @@ -14814,7 +17065,7 @@ memcpy_fromfs(&r, arg, sizeof(struct arpreq)); break; case OLD_SIOCDARP: -@@ -2365,6 +2360,47 @@ +@@ -2406,6 +2401,47 @@ @@ -14862,8 +17113,8 @@ /* * Called once on startup. */ ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/atmlec.h Thu Nov 7 16:08:51 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/include/linux/atmlec.h Fri Nov 15 21:36:38 1996 @@ -0,0 +1,64 @@ +/* + * @@ -14929,8 +17180,8 @@ + unsigned char receive; /* 1= receive vcc, 0 = send_vcc */ +}; +#endif /* _ATMLEC_H_ */ ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/lec.c Mon Nov 11 13:32:16 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/lec.c Fri Nov 15 19:06:52 1996 @@ -0,0 +1,641 @@ +/* + * lec.c: Lan Emulation driver @@ -15573,8 +17824,8 @@ + + return i; +} ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/lec.h Wed Nov 13 11:48:45 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/lec.h Fri Nov 15 21:36:38 1996 @@ -0,0 +1,107 @@ +/* + * @@ -15683,8 +17934,8 @@ +void lec_push(struct atm_vcc *vcc, struct sk_buff *skb); +#endif _LEC_H_ + ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/lec_arpc.c Mon Nov 11 13:36:12 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/lec_arpc.c Fri Nov 15 19:06:53 1996 @@ -0,0 +1,1055 @@ +#include +#include @@ -16741,8 +18992,8 @@ + lec_arp_unlock(priv); +} + ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/net/atm/lec_arpc.h Wed Nov 13 11:48:45 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/net/atm/lec_arpc.h Fri Nov 15 21:36:38 1996 @@ -0,0 +1,102 @@ +/* + * Lec arp cache @@ -16846,8 +19097,8 @@ + unsigned char *mac_addr, unsigned long tran_id); + +#endif ---- ref/include/net/route.h Tue Aug 20 17:14:55 1996 -+++ work/include/net/route.h Wed Nov 13 11:55:46 1996 +--- ref/include/net/route.h Wed Oct 30 03:58:23 1996 ++++ work/include/net/route.h Fri Nov 15 21:32:57 1996 @@ -26,6 +26,7 @@ #define _ROUTE_H @@ -16910,9 +19161,9 @@ #endif /* _ROUTE_H */ ---- ref/include/net/sock.h Tue Aug 20 17:11:40 1996 -+++ work/include/net/sock.h Wed Nov 13 11:55:46 1996 -@@ -189,6 +189,9 @@ +--- ref/include/net/sock.h Thu Nov 7 10:35:28 1996 ++++ work/include/net/sock.h Fri Nov 15 20:55:15 1996 +@@ -190,6 +190,9 @@ zapped, /* In ax25 & ipx means not linked */ broadcast, nonagle, @@ -16922,7 +19173,7 @@ bsdism; unsigned long lingertime; int proc; -@@ -210,20 +213,34 @@ +@@ -211,7 +214,13 @@ __u32 saddr; /* Sending source */ __u32 rcv_saddr; /* Bound address */ unsigned short max_unacked; @@ -16936,16 +19187,7 @@ __u32 lastwin_seq; /* sequence number when we last updated the window we offer */ __u32 high_seq; /* sequence number when we did current fast retransmit */ volatile unsigned long ato; /* ack timeout */ - volatile unsigned long lrcvtime; /* jiffies at last data rcv */ - volatile unsigned long idletime; /* jiffies at last rcv */ -+#ifdef CONFIG_SCALED_WINDOWS -+ unsigned long bytes_rcv; -+#else - unsigned short bytes_rcv; -+#endif - /* - * mss is min(mtu, max_window) - */ +@@ -224,7 +233,11 @@ unsigned short mtu; /* mss negotiated in the syn's */ volatile unsigned short mss; /* current eff. mss - can change */ volatile unsigned short user_mss; /* mss requested by user in ioctl */ @@ -16957,18 +19199,7 @@ unsigned long window_clamp; unsigned int ssthresh; unsigned short num; -@@ -251,8 +268,8 @@ - unsigned char max_ack_backlog; - unsigned char priority; - unsigned char debug; -- unsigned short rcvbuf; -- unsigned short sndbuf; -+ unsigned long rcvbuf; -+ unsigned long sndbuf; - unsigned short type; - unsigned char localroute; /* Route locally only */ - #ifdef CONFIG_AX25 -@@ -301,7 +318,13 @@ +@@ -302,7 +315,13 @@ int ip_mc_loop; /* Loopback */ char ip_mc_name[MAX_ADDR_LEN];/* Multicast device name */ struct ip_mc_socklist *ip_mc_list; /* Group array */ @@ -16983,8 +19214,8 @@ /* * This part is used for the timeout functions (timer.c). ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/arequipa.h Wed Nov 13 11:51:22 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/include/linux/arequipa.h Fri Nov 15 21:36:38 1996 @@ -0,0 +1,46 @@ +/* arequipa.h - Arequipa interface definitions */ + @@ -17032,8 +19263,8 @@ +#endif /* __KERNEL__ */ + +#endif ---- ref/net/ipv4/tcp_input.c Thu Aug 1 14:25:59 1996 -+++ work/net/ipv4/tcp_input.c Fri Oct 18 19:01:29 1996 +--- ref/net/ipv4/tcp_input.c Wed Oct 30 03:13:01 1996 ++++ work/net/ipv4/tcp_input.c Fri Nov 15 19:56:31 1996 @@ -36,6 +36,11 @@ #include #include @@ -17072,10 +19303,11 @@ } ptr+=opsize-2; length-=opsize; -@@ -428,6 +442,24 @@ +@@ -428,7 +442,24 @@ return; } } +- +#ifdef CONFIG_AREQUIPA + newsk->arequipa = NULL; + if (sk->aq_route) { @@ -17094,10 +19326,10 @@ + } + } +#endif + skb->when = jiffies; /* For timeout */ skb_queue_head_init(&newsk->write_queue); skb_queue_head_init(&newsk->receive_queue); - newsk->send_head = NULL; -@@ -438,6 +470,11 @@ +@@ -440,6 +471,11 @@ newsk->rto = TCP_TIMEOUT_INIT; newsk->mdev = TCP_TIMEOUT_INIT; newsk->max_window = 0; @@ -17109,7 +19341,7 @@ /* * See draft-stevens-tcpca-spec-01 for discussion of the * initialization of these values. -@@ -529,7 +566,7 @@ +@@ -532,7 +568,7 @@ */ rt = ip_rt_route(newsk->opt && newsk->opt->srr ? newsk->opt->faddr : saddr, 0); @@ -17118,7 +19350,7 @@ if(rt!=NULL && (rt->rt_flags&RTF_WINDOW)) newsk->window_clamp = rt->rt_window; -@@ -539,7 +576,8 @@ +@@ -542,7 +578,8 @@ if (sk->user_mss) newsk->mtu = sk->user_mss; else if (rt) @@ -17128,7 +19360,7 @@ else newsk->mtu = 576 - sizeof(struct iphdr) - sizeof(struct tcphdr); -@@ -683,6 +721,9 @@ +@@ -686,6 +723,9 @@ * Have we discovered a larger window */ window_seq = ntohs(th->window); @@ -17138,7 +19370,7 @@ if (window_seq > sk->max_window) { sk->max_window = window_seq; -@@ -1170,6 +1211,10 @@ +@@ -1174,6 +1214,10 @@ sk->rtt = 0; sk->rto = TCP_TIMEOUT_INIT; sk->mdev = TCP_TIMEOUT_INIT; @@ -17149,7 +19381,7 @@ } /* -@@ -1785,6 +1830,13 @@ +@@ -1800,6 +1844,13 @@ skb->free = 1; skb->saddr = daddr; skb->daddr = saddr; @@ -17164,14 +19396,26 @@ /* * We may need to add it to the backlog here. --- ref/net/ipv4/Config.in Fri Jul 19 07:24:05 1996 -+++ work/net/ipv4/Config.in Tue Oct 15 14:16:49 1996 ++++ work/net/ipv4/Config.in Fri Nov 15 19:06:56 1996 @@ -42,3 +42,4 @@ #bool 'IP: Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF bool 'IP: Drop source routed frames' CONFIG_IP_NOSR bool 'IP: Allow large windows (not recommended if <16Mb of memory)' CONFIG_SKB_LARGE +bool 'IP: Window scale option' CONFIG_SCALED_WINDOWS ---- ref/include/net/tcp.h Tue Aug 20 17:14:55 1996 -+++ work/include/net/tcp.h Wed Nov 13 11:53:38 1996 +--- ref/net/core/skbuff.c Thu Jun 6 08:45:39 1996 ++++ work/net/core/skbuff.c Fri Nov 15 21:59:44 1996 +@@ -702,6 +702,9 @@ + skb->end=bptr+len; + skb->len=0; + skb->destructor=NULL; ++#ifdef CONFIG_ATM ++ skb->atm.iovcnt = 0; ++#endif + return skb; + } + +--- ref/include/net/tcp.h Wed Oct 30 03:58:24 1996 ++++ work/include/net/tcp.h Fri Nov 15 21:35:29 1996 @@ -23,16 +23,26 @@ /* @@ -17223,7 +19467,7 @@ /* * The next routines deal with comparing 32 bit unsigned ints -@@ -206,7 +220,11 @@ +@@ -207,7 +221,11 @@ sk->lastwin_seq = sk->acked_seq; oldwin = window; } @@ -17235,8 +19479,8 @@ } /* ---- ref/net/core/sock.c Sat Aug 17 19:28:10 1996 -+++ work/net/core/sock.c Wed Oct 16 09:19:51 1996 +--- ref/net/core/sock.c Wed Oct 30 02:42:42 1996 ++++ work/net/core/sock.c Fri Nov 15 19:06:56 1996 @@ -172,22 +172,32 @@ sk->broadcast=valbool; return 0; @@ -17274,8 +19518,8 @@ sk->rcvbuf = val; return(0); ---- ref/net/ipv4/tcp_output.c Wed Aug 7 08:37:34 1996 -+++ work/net/ipv4/tcp_output.c Fri Oct 18 18:56:18 1996 +--- ref/net/ipv4/tcp_output.c Mon Sep 2 14:18:26 1996 ++++ work/net/ipv4/tcp_output.c Fri Nov 15 19:06:57 1996 @@ -69,7 +69,22 @@ minwin = sk->mtu; maxwin = sk->window_clamp; @@ -17299,7 +19543,7 @@ if (minwin > maxwin/2) minwin = maxwin/2; -@@ -835,6 +850,33 @@ +@@ -845,6 +860,33 @@ t1->rst = 0; t1->psh = 0; t1->ack_seq = htonl(newsk->acked_seq); @@ -17333,7 +19577,7 @@ t1->doff = sizeof(*t1)/4+1; ptr = skb_put(buff,4); ptr[0] = 2; -@@ -843,6 +885,7 @@ +@@ -853,6 +895,7 @@ ptr[3] =(newsk->mtu) & 0xff; buff->csum = csum_partial(ptr, 4, 0); tcp_send_check(t1, newsk->saddr, newsk->daddr, sizeof(*t1)+4, buff); @@ -17341,8 +19585,8 @@ newsk->prot->queue_xmit(newsk, ndev, buff, 0); tcp_reset_xmit_timer(newsk, TIME_WRITE , TCP_TIMEOUT_INIT); skb->sk = newsk; ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/include/linux/bigphysarea.h Fri Oct 4 14:14:31 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/include/linux/bigphysarea.h Fri Nov 15 19:06:57 1996 @@ -0,0 +1,25 @@ +/* linux/mm/bigphysarea.h, M. Welsh (mdw@cs.cornell.edu) + * Copyright (c) 1996 by Matt Welsh. @@ -17370,7 +19614,7 @@ + +#endif __LINUX_BIGPHYSAREA_H --- ref/mm/Makefile Fri Mar 22 11:56:56 1996 -+++ work/mm/Makefile Fri Oct 4 14:14:32 1996 ++++ work/mm/Makefile Fri Nov 15 19:06:57 1996 @@ -12,4 +12,8 @@ kmalloc.o vmalloc.o \ swap.o vmscan.o page_io.o page_alloc.o swap_state.o swapfile.o @@ -17380,8 +19624,8 @@ +endif + include $(TOPDIR)/Rules.make ---- /dev/null Tue Jan 1 05:00:00 1980 -+++ work/mm/bigphysarea.c Fri Oct 4 14:14:32 1996 +--- /dev/null Mon Jul 18 01:46:18 1994 ++++ work/mm/bigphysarea.c Fri Nov 15 19:06:58 1996 @@ -0,0 +1,113 @@ +/* linux/mm/bigphysarea.c, M. Welsh (mdw@cs.cornell.edu) + * Copyright (c) 1996 by Matt Welsh. diff -ur --new-file old/atm/doc/usage.tex new/atm/doc/usage.tex --- old/atm/doc/usage.tex Wed Nov 13 21:55:07 1996 +++ new/atm/doc/usage.tex Sat Nov 16 00:09:08 1996 @@ -1,7 +1,7 @@ %%def%:= %:\begin{verbatim} -%:Usage instructions - ATM on Linux, release 0.22 (pre-alpha) +%:Usage instructions - ATM on Linux, release 0.23 (pre-alpha) %:------------------------------------------------------------- %: %:\end{verbatim} @@ -38,14 +38,14 @@ \title{ATM on Linux \\ User's guide \\ - Release 0.22 (pre-alpha)} + Release 0.23 (pre-alpha)} \author{Werner Almesberger \\ {\tt werner.almesberger@lrc.di.epfl.ch} \\ \\ Laboratoire de R\'eseaux de Communication (LRC) \\ EPFL, CH-1015 Lausanne, Switzerland} -\date{November 13, 1996} +\date{November 16, 1996} \begin{document} \maketitle @@ -82,8 +82,8 @@ \begin{itemize} \item the package itself \url{ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.22.tar.gz} - \item the Linux kernel, version 2.0.14, e.g. from -\url{ftp://ftp.cs.helsinki.fi/pub/Software/Linux/Kernel/v2.0/linux-2.0.14.tar.gz} + \item the Linux kernel, version 2.0.25, e.g. from +\url{ftp://ftp.cs.helsinki.fi/pub/Software/Linux/Kernel/v2.0/linux-2.0.25.tar.gz} \item Perl, version 4 or 5 \item if you want memory debugging: MPR version 1.1, e.g. from \url{ftp://sunsite.unc.edu/pub/Linux/devel/lang/c/mpr-1.1.tar.gz} @@ -104,7 +104,7 @@ and the kernel source: \begin{verbatim} -tar xfz linux-2.0.14.tar.gz +tar xfz linux-2.0.25.tar.gz \end{verbatim} Finally, you can extract the ATM-related patches: @@ -127,7 +127,7 @@ \name{atmdiag}, \name{atmdump}, \name{atmtcp}, \name{sonetdiag}, and \name{zntune} \item[\path{atm/test/}] Test programs: \name{aping}, \name{aread}, - \name{awrite}, \name{br}, \name{bw}, \name{ttcp} + \name{awrite}, \name{br}, \name{bw}, \name{ttcp}, \name{window} \item[\path{atm/ip/}] IP over ATM: \name{clip}, \name{atmarp} \item[\path{atm/arpd/}] ATMARP demon: \name{atmarpd} \item[\path{atm/led/}] LAN Emulation demon: \name{led} @@ -164,6 +164,7 @@ Enable usec resolution timestamps (CONFIG_ATM_ZATM_EXACT_TS) Rolfs TI TNETA1570 (CONFIG_ATM_TNETA1570) Enable extended debugging (CONFIG_ATM_TNETA1570_DEBUG) +IDT 77201 (NICStAR) (CONFIG_ATM_NICSTAR) \end{verbatim} The ``MMU hacks'' add single-copy support for raw AAL5 on adapters whose @@ -173,6 +174,9 @@ The TNETA1570 driver is for a board developed by Rolf Fiedler at TU Chemnitz, see also \url{ftp://ftp.infotech.tu-chemnitz.de/pub/linux-atm}. + +The IDT 77201 driver currently only supports native ATM, i.e. IP over ATM +or LANE are not possible (and should not be tried). Support for a simple type of serial consoles is automatically added by the ATM patch. If you're using \name{LILO}, you can enable it by putting a line diff -ur --new-file old/atm/doc/usage.txt new/atm/doc/usage.txt --- old/atm/doc/usage.txt Wed Nov 13 23:19:59 1996 +++ new/atm/doc/usage.txt Sat Nov 16 00:09:36 1996 @@ -1,4 +1,4 @@ -Usage instructions - ATM on Linux, release 0.22 (pre-alpha) +Usage instructions - ATM on Linux, release 0.23 (pre-alpha) ------------------------------------------------------------- For updates of ATM on Linux, please check the Web page at @@ -18,8 +18,8 @@ - the package itself ftp://lrcftp.epfl.ch/pub/linux/atm/dist/atm-0.22.tar.gz - - the Linux kernel, version 2.0.14, e.g. from - ftp://ftp.cs.helsinki.fi/pub/Software/Linux/Kernel/v2.0/linux-2.0.14.tar.gz + - the Linux kernel, version 2.0.25, e.g. from + ftp://ftp.cs.helsinki.fi/pub/Software/Linux/Kernel/v2.0/linux-2.0.25.tar.gz - Perl, version 4 or 5 - if you want memory debugging: MPR version 1.1, e.g. from ftp://sunsite.unc.edu/pub/Linux/devel/lang/c/mpr-1.1.tar.gz @@ -37,7 +37,7 @@ and the kernel source: -tar xfz linux-2.0.14.tar.gz +tar xfz linux-2.0.25.tar.gz Finally, you can extract the ATM-related patches: @@ -54,7 +54,7 @@ atm/ilmid/ ILMI address registration demon: ilmid atm/maint/ ATM maintenance programs: atmaddr, atmdiag, atmdump, atmtcp, sonetdiag, and zntune - atm/test/ Test programs: aping, aread, awrite, br, bw, ttcp + atm/test/ Test programs: aping, aread, awrite, br, bw, ttcp, window atm/ip/ IP over ATM: clip, atmarp atm/arpd/ ATMARP demon: atmarpd atm/led/ LAN Emulation demon: led @@ -89,6 +89,7 @@ Enable usec resolution timestamps (CONFIG_ATM_ZATM_EXACT_TS) Rolfs TI TNETA1570 (CONFIG_ATM_TNETA1570) Enable extended debugging (CONFIG_ATM_TNETA1570_DEBUG) +IDT 77201 (NICStAR) (CONFIG_ATM_NICSTAR) The "MMU hacks" add single-copy support for raw AAL5 on adapters whose driver supports this (currently only the ENI155p). Extended debugging @@ -97,6 +98,9 @@ The TNETA1570 driver is for a board developed by Rolf Fiedler at TU Chemnitz, see also ftp://ftp.infotech.tu-chemnitz.de/pub/linux-atm . + +The IDT 77201 driver currently only supports native ATM, i.e. IP over ATM +or LANE are not possible (and should not be tried). Support for a simple type of serial consoles is automatically added by the ATM patch. If you're using LILO, you can enable it by putting a line like diff -ur --new-file old/atm/lib/Makefile new/atm/lib/Makefile --- old/atm/lib/Makefile Wed Nov 13 17:04:19 1996 +++ new/atm/lib/Makefile Sat Nov 16 00:23:35 1996 @@ -1,5 +1,10 @@ ATM_OBJS=text2atm.o atm2text.o atmequal.o sdu2cell.o text2qos.o qos2text.o \ - qosequal.o ans_l.o + qosequal.o +ifeq (/usr/lib/libresolv.a,$(wildcard /usr/lib/libresolv.a)) +ATM_OBJS += ans_l.o +else +ATM_OBJS += ans.o +endif ATMD_OBJS=common.o diag.o timer.o AQ_OBJS=arequipa.o PGMS=#test diff -ur --new-file old/atm/lib/atmres.h new/atm/lib/atmres.h --- old/atm/lib/atmres.h Wed Nov 13 13:46:46 1996 +++ new/atm/lib/atmres.h Thu Nov 14 08:06:18 1996 @@ -16,10 +16,10 @@ #define T_ATMA 34 #endif #ifndef ATMA_AESA -#define ATM_AESA 0 +#define ATMA_AESA 0 #endif -#ifndef ATM_E164 -#define ATM_E164 1 +#ifndef ATMA_E164 +#define ATMA_E164 1 #endif /* Return codes for text2atm and atm2text */ diff -ur --new-file old/atm/mkdist new/atm/mkdist --- old/atm/mkdist Wed Nov 13 23:40:23 1996 +++ new/atm/mkdist Sat Nov 16 00:35:40 1996 @@ -1,7 +1,7 @@ #!/bin/sh [ -r ./VERSION ] || exit 1 VERSION=`cat ./VERSION` -SRCDIR=$HOME/k/2014 +SRCDIR=$HOME/k/2025 ARCHDIR=$HOME/l/arch ( cd $SRCDIR diff -ur --new-file old/atm/qgen/qlib.c new/atm/qgen/qlib.c --- old/atm/qgen/qlib.c Fri Sep 27 20:17:40 1996 +++ new/atm/qgen/qlib.c Fri Nov 15 13:05:10 1996 @@ -222,6 +222,8 @@ if (field < 0 || field >= Q_FIELDS) q_report(Q_FATAL,"invalid field value (%d)",field); if (!fields[field].values) { + if (q_test(dsc->field_present,field)) /* probably an error ... */ + q_report(Q_ERROR,"changing field %d",field); q_set(dsc->field_present,field); q_put(dsc->data,fields[field].pos,fields[field].size,value); use_group(dsc,fields[field].parent); diff -ur --new-file old/atm/saal/sscop.c new/atm/saal/sscop.c --- old/atm/saal/sscop.c Wed Nov 13 23:19:31 1996 +++ new/atm/saal/sscop.c Fri Nov 15 13:51:33 1996 @@ -707,13 +707,13 @@ static void initialize_vr_mr(SSCOP_DSC *dsc) { - dsc->vr_mr = SSCOP_CF_MR; /* was MOD24(dsc->vr_h+SSCOP_CF_MR); */ + dsc->vr_mr = SSCOP_CF_MR; } static void update_vr_mr(SSCOP_DSC *dsc) { - initialize_vr_mr(dsc); + dsc->vr_mr = MOD24(dsc->vr_r+SSCOP_CF_MR); } @@ -954,6 +954,7 @@ } while (1) { INC24(dsc->vr_r); + update_vr_mr(dsc); buf = queue_lookup(&dsc->rx_buf,dsc->vr_r); if (!buf) break; queue_remove(&dsc->rx_buf,buf); @@ -968,14 +969,12 @@ if (s == dsc->vr_h) { queue_put(&dsc->rx_buf,buf); INC24(dsc->vr_h); - update_vr_mr(dsc); return; } if (NORM_RX(dsc->vr_h) < NORM_RX(s)) { queue_put(&dsc->rx_buf,buf); send_ustat(dsc,dsc->vr_h,s); dsc->vr_h = MOD24(s+1); - update_vr_mr(dsc); return; } if (queue_lookup(&dsc->rx_buf,s)) queue_put(&dsc->rx_buf,buf); @@ -1002,7 +1001,6 @@ return; } dsc->vr_h = NORM_RX(dsc->vr_mr) < NORM_RX(s) ? dsc->vr_mr : s; - update_vr_mr(dsc); /* K */ curr = 0; i = dsc->vr_r; diff -ur --new-file old/atm/test/Makefile new/atm/test/Makefile --- old/atm/test/Makefile Mon Sep 2 19:41:52 1996 +++ new/atm/test/Makefile Fri Nov 15 23:39:44 1996 @@ -1,4 +1,4 @@ -USRPGMS=aping aread awrite br bw ttcp_atm +USRPGMS=aping aread awrite br bw ttcp_atm window MAN1= include ../Rules.make @@ -9,6 +9,7 @@ br: br.o bw: bw.o ttcp_atm: ttcp_atm.o +window: window.o ttcp_atm.o: ttcp.c gcc -c -w -O2 -o ttcp_atm.o ttcp.c -I../lib .