diff -u --recursive --new-file v2.1.53/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.1.53/linux/Documentation/Configure.help Wed Sep 3 20:52:41 1997 +++ linux/Documentation/Configure.help Sat Sep 6 10:43:49 1997 @@ -680,21 +680,38 @@ VGA driver is used. Note that, at this time, there is no X server for these systems. If unsure, try N. -PCI bios support +PCI support CONFIG_PCI Find out whether you have a PCI motherboard. PCI is the name of a bus system, i.e. the way the CPU talks to the other stuff inside your box. Other bus systems are ISA, EISA, Microchannel (MCA) or - VESA. If you have PCI, say Y, otherwise N. Note: some old PCI - motherboards have BIOS bugs and may crash if "PCI bios support" is - enabled (but they run fine without this option). The PCI-HOWTO, - available via ftp (user: anonymous) in - sunsite.unc.edu:/pub/Linux/docs/HOWTO, contains valuable information - about which PCI hardware does work under Linux and which doesn't. + VESA. If you have PCI, say Y, otherwise N. The PCI-HOWTO, available + via ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO, + contains valuable information about which PCI hardware does work + under Linux and which doesn't. If some of your PCI devices don't work and you get a warning during boot time ("man dmesg"), please follow the instructions at the top of include/linux/pci.h. +PCI BIOS support +CONFIG_PCI_BIOS + If you have enabled PCI bus support above, you probably want to allow + Linux to use your PCI BIOS to detect the PCI devices and determine + their configuration. Note: some old PCI motherboards have BIOS bugs + and may crash if this switch is enabled -- for such motherboards, + you should disable PCI BIOS support and use direct PCI access instead. + Except for some special cases (embedded systems with no BIOS), you + probably should say Y here. + +PCI direct access support +CONFIG_PCI_DIRECT + If you don't want to use the PCI BIOS (e.g., because you run some + embedded system with no BIOS at all) or Linux says it cannot use + your PCI BIOS, you can enable direct PCI hardware here. It might fail + if your machine is based on some unusual chipset, but it usually + works. If both PCI BIOS and direct PCI access are enabled, the use + of BIOS is preferred. If unsure, say Y. + PCI bridge optimization (experimental) CONFIG_PCI_OPTIMIZE This can improve access times for some hardware devices under @@ -2653,6 +2670,26 @@ can only use one protocol at a time, depending on what the other end can understand). +Shortwave radio modem driver +CONFIG_HFMODEM + This experimental driver is used by a package (to be released) + that implements the shortwave radio protocols RTTY, Sitor (Amtor), + Pactor 1 and GTOR using a standard PC soundcard. If unsure, + say N. + +Shortwave radio modem driver support for SoundBlaster and compatible cards +CONFIG_HFMODEM_SBC + This option enables the hfmodem driver to use SoundBlaster and + compatible cards. It requires a 16bit capable card, i.e. + SB16 or better, or ESS1688 or newer. + +Shortwave radio modem driver support for WSS and Crystal cards +CONFIG_HFMODEM_WSS + This option enables the hfmodem driver to use WindowsSoundSystem + compatible cards. These cards feature a codec chip from either + Analog Devices (such as AD1848, AD1845, AD1812) or Crystal + Semiconductors (such as CS4248, CS423x). + Serial port KISS driver for AX.25 CONFIG_MKISS KISS is the protocol used to send IP traffic over AX.25 radio @@ -3056,10 +3093,14 @@ linux, read the Multiple-Ethernet-mini-HOWTO, available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. -ARCnet support +Generic ARCnet support CONFIG_ARCNET If you have a network card of this type, say Y and check out the (arguably) beautiful poetry in Documentation/networking/arcnet.txt. + You need both this driver, and the driver for the particular ARCnet + chipset of your card. If you don't know, then it's probably a + COM90xx type card, so say Y (or M) to ARCnet COM90xx chipset support + below. You might also want to have a look at the Ethernet-HOWTO, available via ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO (even though ARCnet is not really ethernet). This driver is also @@ -3097,6 +3138,31 @@ documentation in Documentation/networking/arcnet.txt for more information about using arc0e and arc0s. +ARCnet COM90xx chipset support +CONFIG_ARCNET_COM90xx + This is the chipset driver for the standard COM90xx cards. If you always + used the old arcnet driver without knowing what type of card you had, + this is probably the one for you. + +ARCnet COM90xx IO mapped mode chipset support +CONFIG_ARCNET_COM90xxIO + This is the chipset driver for the COM90xx cards, using them in IO-mapped + mode instead of memory-mapped mode. This is slower than the normal driver. + Only use it if your card doesn't support shared memory. + +ARCnet RIM I chipset support +CONFIG_ARCNET_RIM_I + This is yet another chipset driver for the COM90xx cards, but this time + only using memory-mapped mode, and no IO ports at all. This driver is + completely untested, so if you have one of these cards, please mail + dwmw2@cam.ac.uk, especially if it works! + +ARCnet COM20020 chipset support +CONFIG_ARCNET_COM20020 + This is the driver for the new COM20020 chipset. It supports such things + as promiscuous mode, so packet sniffing is possible, and extra diagnostic + information. + Cabletron E21xx support CONFIG_E2100 If you have a network (ethernet) card of this type, say Y and read @@ -3222,6 +3288,16 @@ linux, read the Multiple-Ethernet-mini-HOWTO, available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. +NI5010 support +CONFIG_NI5010 + If you have a network (ethernet) card of this type, say Y and read + the Ethernet-HOWTO, available via ftp (user: anonymous) in + sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you plan to use more than + one network card under linux, read the Multiple-Ethernet-mini-HOWTO, + available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Note that this is still experimental code. If you use this driver, + please contact the authors to join the development team. + NI5210 support CONFIG_NI52 If you have a network (ethernet) card of this type, say Y and read @@ -4445,6 +4521,12 @@ other console device, in which case you probably want to say Y to "Console on serial port", below. If unsure, say N. +Software generated cursor +CONFIG_SOFTCURSOR + If you enable this option, you'll be able to do lots of nice things + with your cursor -- for example to turn it into a non-blinking one. + See Documentation/VGA-softcursor.txt for more information. + Standard/generic serial support CONFIG_SERIAL This selects whether you want to include the driver for the standard @@ -4938,6 +5020,18 @@ module is called pcwd.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. Most people will say N. +Acquire SBC Watchdog Timer +CONFIG_ACQUIRE_WDT + This is the driver for the hardware watchdog on the PSC-6x86 Single + Board Computer produced by Acquire Inc (and others). This watchdog + simply watches your kernel to make sure it doesn't freeze, and if + it does, it resets your computer after a certain amount of time. + This driver is like the WDT501 driver but for different hardware. + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module is called pscwdt.o. If you want to compile it as a module, + say M here and read Documentation/modules.txt. Most people will say N. + Enhanced Real Time Clock Support CONFIG_RTC If you say Y here and create a character special file /dev/rtc with @@ -5853,6 +5947,76 @@ sharing a hard disk between i386 and m68k Linux boxes, for example. Say Y if you need this feature; users who are only using their system-native partitioning scheme can say N here. + +Build PowerMac Kernel (not PReP) +CONFIG_PMAC + There are currently two different kinds of PowerPC-based machines + available: Apple Power Macintoshes and clones (such as the Motorola + Starmax series, and PReP (PowerPC Reference Platform) machines such + as the Motorola PowerStack range. Currently, a single kernel binary + only supports one type or the other. Say Y here to compile a kernel + which will run on Power Macintoshes and clones. + +Build PReP Kernel (not PowerMac) +CONFIG_PREP + Say Y here to compile a kernel which will run on PReP (PowerPC + Reference Platform) machines such as the Motorola PowerStack range. + For Power Macintosh clones, including the Motorola Starmaxes, you + should say N (and Y to the previous question). + +Processor type +CONFIG_MCOMMON + If you are compiling a kernel to run on a specific machine, you can + indicate which type of PowerPC processor it has. Currently this + option does very little. + +Support for Open Firmware device tree in /proc +CONFIG_PROC_DEVICETREE + This option adds a device-tree directory under /proc which contains + an image of the device tree that the kernel copies from Open + Firmware. If unsure, say Y here. + +Support for ATI Mach64 display cards +CONFIG_ATY_VIDEO + Several of the newer Power Macintoshes and clones have a video + display interface based on the ATI Mach64 chipset. Say N here if + you are sure you don't need this functionality, otherwise Y. + +Support for IMS Twin Turbo display card +CONFIG_IMSTT_VIDEO + Some Power Macintosh clones have an IMS Twin Turbo video display + interface. Say Y to include support for this. + +MESH (Power Mac internal SCSI) support +CONFIG_SCSI_MESH + Many Power Macintoshes and clones have a MESH (Macintosh Enhanced + SCSI Hardware) SCSI bus adaptor (the 7200 doesn't, but all of the + other Power Macintoshes do). Say Y to include support for this SCSI + adaptor. + +Maximum synchronous transfer rate +CONFIG_SCSI_MESH_SYNC_RATE + On Power Macintoshes (and clones) where the MESH SCSI bus adaptor + drives a bus which is entirely internal to the machine (such as the + 7500, 7600, 8500, etc.), the MESH is capable of synchronous + operation at up to 10MB/s. On machines where the SCSI bus + controlled by the MESH can have external devices connected, it is + usually rated at 5MB/s. 5 is a safe value here unless you know the + MESH SCSI bus is internal only; in that case you can say 10. Say 0 + to disable synchronous operation. + +53C94 (Power Mac external SCSI) support +CONFIG_SCSI_MAC53C94 + On Power Macintoshes (and clones) with two SCSI buses, the external + SCSI bus is usually controlled by a 53C94 SCSI bus adaptor. Older + machines which only have one SCSI bus, such as the 7200, also use + the 53C94. Say Y to include support for the 53C94. + +MACE (Power Mac ethernet) support +CONFIG_MACE + Power Macintoshes and clones with ethernet built-in on the + motherboard will usually use a MACE (Medium Access Control for + Ethernet) interface. Say Y to include support for the MACE chip. # need an empty line after last entry, for sed script in Configure. diff -u --recursive --new-file v2.1.53/linux/Documentation/devices.tex linux/Documentation/devices.tex --- v2.1.53/linux/Documentation/devices.tex Thu Aug 14 20:49:16 1997 +++ linux/Documentation/devices.tex Sat Sep 6 10:28:27 1997 @@ -47,7 +47,7 @@ % \title{{\bf Linux Allocated Devices}} \author{Maintained by H. Peter Anvin $<$hpa@zytor.com$>$} -\date{Last revised: July 28, 1997} +\date{Last revised: September 5, 1997} \maketitle % \noindent @@ -216,7 +216,9 @@ \major{85}{}{char }{Linux/SGI shared memory input queue} \major{86}{}{char }{SCSI media changer} \major{87}{}{char }{Sony Control-A1 stereo control bus} -\major{88}{--119}{}{Unallocated} +\major{88}{}{char }{COMX synchronous serial card} +\major{89}{}{char }{I$^2$C bus interface} +\major{90}{--119}{}{Unallocated} \major{120}{--127}{}{Local/experimental use} \major{128}{--239}{}{Unallocated} \major{240}{--254}{}{Local/experimental use} @@ -525,6 +527,7 @@ \minor{148}{/dev/gfx}{Linux/SGI graphics effects device} \minor{149}{/dev/input/mouse}{Linux/SGI Irix emulation mouse} \minor{150}{/dev/input/keyboard}{Linux/SGI Irix emulation keyboard} + \minor{151}{/dev/led}{Front panel LEDs} \end{devicelist} \begin{devicelist} @@ -1417,8 +1420,8 @@ \begin{devicelist} \major{82}{}{char }{WiNRADiO communications receiver card} - \major{0}{/dev/winradio0}{First WiNRADiO card} - \major{1}{/dev/winradio1}{Second WiNRADiO card} + \minor{0}{/dev/winradio0}{First WiNRADiO card} + \minor{1}{/dev/winradio1}{Second WiNRADiO card} \minordots \end{devicelist} @@ -1465,7 +1468,21 @@ \end{devicelist} \begin{devicelist} -\major{88}{--119}{}{Unallocated} +\major{88}{}{char }{COMX synchronous serial card} + \minor{0}{/dev/comx0}{Channel 0} + \minor{1}{/dev/comx1}{Channel 1} + \minordots +\end{devicelist} + +\begin{devicelist} +\major{89}{}{char }{I$^2$C bus interface} + \minor{0}{/dev/i2c0}{First I$^2$C adapter} + \minor{1}{/dev/i2c1}{Second I$^2$C adapter} + \minordots +\end{devicelist} + +\begin{devicelist} +\major{90}{--119}{}{Unallocated} \end{devicelist} \begin{devicelist} diff -u --recursive --new-file v2.1.53/linux/Documentation/devices.txt linux/Documentation/devices.txt --- v2.1.53/linux/Documentation/devices.txt Thu Aug 14 20:49:16 1997 +++ linux/Documentation/devices.txt Sat Sep 6 10:28:27 1997 @@ -1,7 +1,7 @@ LINUX ALLOCATED DEVICES Maintained by H. Peter Anvin - Last revised: July 28, 1997 + Last revised: September 5, 1997 This list is the successor to Rick Miller's Linux Device List, which he stopped maintaining when he got busy with other things in 1993. It @@ -301,6 +301,7 @@ 148 = /dev/gfx Linux/SGI graphics effects device 149 = /dev/input/mouse Linux/SGI Irix emulation mouse 150 = /dev/input/keyboard Linux/SGI Irix emulation keyboard + 151 = /dev/led Front panel LEDs 11 char Raw keyboard device 0 = /dev/kbd Raw keyboard device @@ -1031,7 +1032,17 @@ 1 = /dev/controla1 Second device on chain ... - 88-119 UNALLOCATED + 88 char COMX synchronous serial card + 0 = /dev/comx0 COMX channel 0 + 1 = /dev/comx1 COMX channel 1 + ... + + 89 char I2C bus interface + 0 = /dev/i2c0 First I2C adapter + 1 = /dev/i2c1 Second I2C adapter + ... + + 90-119 UNALLOCATED 120-127 LOCAL/EXPERIMENTAL USE diff -u --recursive --new-file v2.1.53/linux/Makefile linux/Makefile --- v2.1.53/linux/Makefile Thu Sep 4 17:07:29 1997 +++ linux/Makefile Thu Sep 4 17:07:54 1997 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 53 +SUBLEVEL = 54 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) diff -u --recursive --new-file v2.1.53/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c --- v2.1.53/linux/arch/alpha/kernel/bios32.c Sun Feb 2 05:00:34 1997 +++ linux/arch/alpha/kernel/bios32.c Sat Sep 6 10:43:49 1997 @@ -186,6 +186,7 @@ pcibios_read_config_dword(bus->number, dev->devfn, reg, &base); if (!base) { /* this base-address register is unused */ + dev->base_address[(reg - PCI_BASE_ADDRESS_0)>>2] = 0; continue; } diff -u --recursive --new-file v2.1.53/linux/arch/i386/config.in linux/arch/i386/config.in --- v2.1.53/linux/arch/i386/config.in Wed Sep 3 20:52:41 1997 +++ linux/arch/i386/config.in Sat Sep 6 10:43:49 1997 @@ -23,8 +23,10 @@ bool 'Kernel math emulation' CONFIG_MATH_EMULATION bool 'Networking support' CONFIG_NET -bool 'PCI bios support' CONFIG_PCI +bool 'PCI support' CONFIG_PCI if [ "$CONFIG_PCI" = "y" ]; then + bool ' PCI BIOS support' CONFIG_PCI_BIOS + bool ' PCI direct access support' CONFIG_PCI_DIRECT if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool ' PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE fi diff -u --recursive --new-file v2.1.53/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.1.53/linux/arch/i386/defconfig Mon Aug 18 18:19:42 1997 +++ linux/arch/i386/defconfig Sat Sep 6 10:49:53 1997 @@ -20,6 +20,8 @@ # CONFIG_MATH_EMULATION is not set CONFIG_NET=y CONFIG_PCI=y +CONFIG_PCI_BIOS=y +# CONFIG_PCI_DIRECT is not set # CONFIG_MCA is not set CONFIG_SYSVIPC=y CONFIG_SYSCTL=y @@ -139,7 +141,6 @@ # CONFIG_SCSI_NCR53C406A is not set # CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_NCR53C8XX is not set -# CONFIG_SCSI_PPA is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_QLOGIC_FAS is not set # CONFIG_SCSI_QLOGIC_ISP is not set @@ -162,6 +163,7 @@ # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set # CONFIG_NET_ISA is not set CONFIG_NET_EISA=y # CONFIG_PCNET32 is not set @@ -174,7 +176,6 @@ # CONFIG_NET_POCKET is not set # CONFIG_FDDI is not set # CONFIG_DLCI is not set -# CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_NET_RADIO is not set # CONFIG_SLIP is not set @@ -239,6 +240,7 @@ # CONFIG_APM is not set # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set +# CONFIG_H8 is not set # CONFIG_NVRAM is not set # CONFIG_JOYSTICK is not set diff -u --recursive --new-file v2.1.53/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c --- v2.1.53/linux/arch/i386/kernel/bios32.c Thu Jul 17 10:06:03 1997 +++ linux/arch/i386/kernel/bios32.c Sat Sep 6 10:43:49 1997 @@ -1,7 +1,7 @@ /* * bios32.c - BIOS32, PCI BIOS functions. * - * $Id: bios32.c,v 1.12 1997/06/26 13:33:46 mj Exp $ + * $Id: bios32.c,v 1.14 1997/08/02 22:20:57 mj Exp $ * * Sponsored by * iX Multiuser Multitasking Magazine @@ -61,6 +61,9 @@ * * Jun 20, 1997 : Corrected problems in "conf1" type accesses. * (paubert@iram.es) + * + * Aug 2, 1997 : Split to PCI BIOS handling and direct PCI access parts + * and cleaned it up... Martin Mares */ #include @@ -75,69 +78,12 @@ #include #include -#define PCIBIOS_PCI_FUNCTION_ID 0xb1XX -#define PCIBIOS_PCI_BIOS_PRESENT 0xb101 -#define PCIBIOS_FIND_PCI_DEVICE 0xb102 -#define PCIBIOS_FIND_PCI_CLASS_CODE 0xb103 -#define PCIBIOS_GENERATE_SPECIAL_CYCLE 0xb106 -#define PCIBIOS_READ_CONFIG_BYTE 0xb108 -#define PCIBIOS_READ_CONFIG_WORD 0xb109 -#define PCIBIOS_READ_CONFIG_DWORD 0xb10a -#define PCIBIOS_WRITE_CONFIG_BYTE 0xb10b -#define PCIBIOS_WRITE_CONFIG_WORD 0xb10c -#define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d - - -/* BIOS32 signature: "_32_" */ -#define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24)) - -/* PCI signature: "PCI " */ -#define PCI_SIGNATURE (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24)) - -/* PCI service signature: "$PCI" */ -#define PCI_SERVICE (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24)) - /* - * This is the standard structure used to identify the entry point - * to the BIOS32 Service Directory, as documented in - * Standard BIOS 32-bit Service Directory Proposal - * Revision 0.4 May 24, 1993 - * Phoenix Technologies Ltd. - * Norwood, MA - * and the PCI BIOS specification. + * Generic PCI access -- indirect calls according to detected HW. */ -union bios32 { - struct { - unsigned long signature; /* _32_ */ - unsigned long entry; /* 32 bit physical address */ - unsigned char revision; /* Revision level, 0 */ - unsigned char length; /* Length in paragraphs should be 01 */ - unsigned char checksum; /* All bytes must add up to zero */ - unsigned char reserved[5]; /* Must be zero */ - } fields; - char chars[16]; -}; - -#ifdef CONFIG_PCI -/* - * Physical address of the service directory. I don't know if we're - * allowed to have more than one of these or not, so just in case - * we'll make pcibios_present() take a memory start parameter and store - * the array there. - */ - -static unsigned long bios32_entry = 0; -static struct { - unsigned long address; - unsigned short segment; -} bios32_indirect = { 0, KERNEL_CS }; - - -/* - * function table for accessing PCI configuration space - */ struct pci_access { + int pci_present; int (*find_device)(unsigned short, unsigned short, unsigned short, unsigned char *, unsigned char *); int (*find_class)(unsigned int, unsigned short, unsigned char *, unsigned char *); int (*read_config_byte)(unsigned char, unsigned char, unsigned char, unsigned char *); @@ -148,363 +94,137 @@ int (*write_config_dword)(unsigned char, unsigned char, unsigned char, unsigned int); }; -/* - * pointer to selected PCI access function table - */ -static struct pci_access *access_pci = NULL; - - - -/* - * Returns the entry point for the given service, NULL on error - */ - -static unsigned long bios32_service(unsigned long service) +static int pci_stub(void) { - unsigned char return_code; /* %al */ - unsigned long address; /* %ebx */ - unsigned long length; /* %ecx */ - unsigned long entry; /* %edx */ - unsigned long flags; - - save_flags(flags); cli(); - __asm__("lcall (%%edi)" - : "=a" (return_code), - "=b" (address), - "=c" (length), - "=d" (entry) - : "0" (service), - "1" (0), - "D" (&bios32_indirect)); - restore_flags(flags); - - switch (return_code) { - case 0: - return address + entry; - case 0x80: /* Not present */ - printk("bios32_service(0x%lx) : not present\n", service); - return 0; - default: /* Shouldn't happen */ - printk("bios32_service(0x%lx) : returned 0x%x, mail drew@colorado.edu\n", - service, return_code); - return 0; - } + return PCIBIOS_FUNC_NOT_SUPPORTED; } -static long pcibios_entry = 0; -static struct { - unsigned long address; - unsigned short segment; -} pci_indirect = { 0, KERNEL_CS }; +static struct pci_access pci_access_none = { + 0, /* No PCI present */ + (void *) pci_stub, /* No functions implemented */ + (void *) pci_stub, + (void *) pci_stub, + (void *) pci_stub, + (void *) pci_stub, + (void *) pci_stub, + (void *) pci_stub, + (void *) pci_stub +}; +static struct pci_access *access_pci = &pci_access_none; -__initfunc(static int check_pcibios(void)) +int pcibios_present(void) { - unsigned long signature; - unsigned char present_status; - unsigned char major_revision; - unsigned char minor_revision; - unsigned long flags; - int pack; - - if ((pcibios_entry = bios32_service(PCI_SERVICE))) { - pci_indirect.address = pcibios_entry | PAGE_OFFSET; - - save_flags(flags); cli(); - __asm__("lcall (%%edi)\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:\tshl $8, %%eax\n\t" - "movw %%bx, %%ax" - : "=d" (signature), - "=a" (pack) - : "1" (PCIBIOS_PCI_BIOS_PRESENT), - "D" (&pci_indirect) - : "bx", "cx"); - restore_flags(flags); - - present_status = (pack >> 16) & 0xff; - major_revision = (pack >> 8) & 0xff; - minor_revision = pack & 0xff; - if (present_status || (signature != PCI_SIGNATURE)) { - printk ("pcibios_init : %s : BIOS32 Service Directory says PCI BIOS is present,\n" - " but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n" - " and signature of 0x%08lx (%c%c%c%c). mail drew@Colorado.EDU\n", - (signature == PCI_SIGNATURE) ? "WARNING" : "ERROR", - present_status, signature, - (char) (signature >> 0), (char) (signature >> 8), - (char) (signature >> 16), (char) (signature >> 24)); - - if (signature != PCI_SIGNATURE) - pcibios_entry = 0; - } - if (pcibios_entry) { - printk ("pcibios_init : PCI BIOS revision %x.%02x entry at 0x%lx\n", - major_revision, minor_revision, pcibios_entry); - return 1; - } - } - return 0; + return access_pci->pci_present; } - -static int pci_bios_find_class (unsigned int class_code, unsigned short index, +int pcibios_find_class (unsigned int class_code, unsigned short index, unsigned char *bus, unsigned char *device_fn) { - unsigned long bx; - unsigned long ret; - unsigned long flags; - - save_flags(flags); cli(); - __asm__ ("lcall (%%edi)\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=b" (bx), - "=a" (ret) - : "1" (PCIBIOS_FIND_PCI_CLASS_CODE), - "c" (class_code), - "S" ((int) index), - "D" (&pci_indirect)); - restore_flags(flags); - *bus = (bx >> 8) & 0xff; - *device_fn = bx & 0xff; - return (int) (ret & 0xff00) >> 8; + return access_pci->find_class(class_code, index, bus, device_fn); } - -static int pci_bios_find_device (unsigned short vendor, unsigned short device_id, +int pcibios_find_device (unsigned short vendor, unsigned short device_id, unsigned short index, unsigned char *bus, unsigned char *device_fn) { - unsigned short bx; - unsigned short ret; - unsigned long flags; - - save_flags(flags); cli(); - __asm__("lcall (%%edi)\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=b" (bx), - "=a" (ret) - : "1" (PCIBIOS_FIND_PCI_DEVICE), - "c" (device_id), - "d" (vendor), - "S" ((int) index), - "D" (&pci_indirect)); - restore_flags(flags); - *bus = (bx >> 8) & 0xff; - *device_fn = bx & 0xff; - return (int) (ret & 0xff00) >> 8; + return access_pci->find_device(vendor, device_id, index, bus, device_fn); } -static int pci_bios_read_config_byte(unsigned char bus, +int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned char *value) { - unsigned long ret; - unsigned long bx = (bus << 8) | device_fn; - unsigned long flags; - - save_flags(flags); cli(); - __asm__("lcall (%%esi)\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=c" (*value), - "=a" (ret) - : "1" (PCIBIOS_READ_CONFIG_BYTE), - "b" (bx), - "D" ((long) where), - "S" (&pci_indirect)); - restore_flags(flags); - return (int) (ret & 0xff00) >> 8; + return access_pci->read_config_byte(bus, device_fn, where, value); } -static int pci_bios_read_config_word (unsigned char bus, +int pcibios_read_config_word (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned short *value) { - unsigned long ret; - unsigned long bx = (bus << 8) | device_fn; - unsigned long flags; - - save_flags(flags); cli(); - __asm__("lcall (%%esi)\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=c" (*value), - "=a" (ret) - : "1" (PCIBIOS_READ_CONFIG_WORD), - "b" (bx), - "D" ((long) where), - "S" (&pci_indirect)); - restore_flags(flags); - return (int) (ret & 0xff00) >> 8; + return access_pci->read_config_word(bus, device_fn, where, value); } -static int pci_bios_read_config_dword (unsigned char bus, +int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned int *value) { - unsigned long ret; - unsigned long bx = (bus << 8) | device_fn; - unsigned long flags; - - save_flags(flags); cli(); - __asm__("lcall (%%esi)\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=c" (*value), - "=a" (ret) - : "1" (PCIBIOS_READ_CONFIG_DWORD), - "b" (bx), - "D" ((long) where), - "S" (&pci_indirect)); - restore_flags(flags); - return (int) (ret & 0xff00) >> 8; + return access_pci->read_config_dword(bus, device_fn, where, value); } -static int pci_bios_write_config_byte (unsigned char bus, +int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned char value) { - unsigned long ret; - unsigned long bx = (bus << 8) | device_fn; - unsigned long flags; - - save_flags(flags); cli(); - __asm__("lcall (%%esi)\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=a" (ret) - : "0" (PCIBIOS_WRITE_CONFIG_BYTE), - "c" (value), - "b" (bx), - "D" ((long) where), - "S" (&pci_indirect)); - restore_flags(flags); - return (int) (ret & 0xff00) >> 8; + return access_pci->write_config_byte(bus, device_fn, where, value); } -static int pci_bios_write_config_word (unsigned char bus, +int pcibios_write_config_word (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned short value) { - unsigned long ret; - unsigned long bx = (bus << 8) | device_fn; - unsigned long flags; - - save_flags(flags); cli(); - __asm__("lcall (%%esi)\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=a" (ret) - : "0" (PCIBIOS_WRITE_CONFIG_WORD), - "c" (value), - "b" (bx), - "D" ((long) where), - "S" (&pci_indirect)); - restore_flags(flags); - return (int) (ret & 0xff00) >> 8; + return access_pci->write_config_word(bus, device_fn, where, value); } -static int pci_bios_write_config_dword (unsigned char bus, +int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned int value) { - unsigned long ret; - unsigned long bx = (bus << 8) | device_fn; - unsigned long flags; - - save_flags(flags); cli(); - __asm__("lcall (%%esi)\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=a" (ret) - : "0" (PCIBIOS_WRITE_CONFIG_DWORD), - "c" (value), - "b" (bx), - "D" ((long) where), - "S" (&pci_indirect)); - restore_flags(flags); - return (int) (ret & 0xff00) >> 8; + return access_pci->write_config_dword(bus, device_fn, where, value); } /* - * function table for BIOS32 access + * Direct access to PCI hardware... */ -static struct pci_access pci_bios_access = { - pci_bios_find_device, - pci_bios_find_class, - pci_bios_read_config_byte, - pci_bios_read_config_word, - pci_bios_read_config_dword, - pci_bios_write_config_byte, - pci_bios_write_config_word, - pci_bios_write_config_dword -}; - - /* * Given the vendor and device ids, find the n'th instance of that device * in the system. */ + +#ifdef CONFIG_PCI_DIRECT + static int pci_direct_find_device (unsigned short vendor, unsigned short device_id, unsigned short index, unsigned char *bus, unsigned char *devfn) { unsigned int curr = 0; struct pci_dev *dev; - unsigned long flags; - save_flags(flags); for (dev = pci_devices; dev; dev = dev->next) { if (dev->vendor == vendor && dev->device == device_id) { if (curr == index) { *devfn = dev->devfn; *bus = dev->bus->number; - restore_flags(flags); return PCIBIOS_SUCCESSFUL; } ++curr; } } - restore_flags(flags); return PCIBIOS_DEVICE_NOT_FOUND; } - /* * Given the class, find the n'th instance of that device * in the system. */ + static int pci_direct_find_class (unsigned int class_code, unsigned short index, unsigned char *bus, unsigned char *devfn) { unsigned int curr = 0; struct pci_dev *dev; - unsigned long flags; - save_flags(flags); cli(); for (dev = pci_devices; dev; dev = dev->next) { if (dev->class == class_code) { if (curr == index) { *devfn = dev->devfn; *bus = dev->bus->number; - restore_flags(flags); return PCIBIOS_SUCCESSFUL; } ++curr; } } - restore_flags(flags); return PCIBIOS_DEVICE_NOT_FOUND; } /* * Functions for accessing PCI configuration space with type 1 accesses */ + #define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3)) static int pci_conf1_read_config_byte(unsigned char bus, unsigned char device_fn, @@ -585,10 +305,8 @@ #undef CONFIG_CMD -/* - * functiontable for type 1 - */ static struct pci_access pci_direct_conf1 = { + 1, pci_direct_find_device, pci_direct_find_class, pci_conf1_read_config_byte, @@ -602,6 +320,7 @@ /* * Functions for accessing PCI configuration space with type 2 accesses */ + #define IOADDR(devfn, where) ((0xC000 | ((devfn & 0x78) << 5)) + where) #define FUNC(devfn) (((devfn & 7) << 1) | 0xf0) @@ -698,10 +417,8 @@ #undef IOADDR #undef FUNC -/* - * functiontable for type 2 - */ static struct pci_access pci_direct_conf2 = { + 1, pci_direct_find_device, pci_direct_find_class, pci_conf2_read_config_byte, @@ -712,8 +429,7 @@ pci_conf2_write_config_dword }; - -__initfunc(static struct pci_access *check_direct_pci(void)) +__initfunc(static struct pci_access *pci_check_direct(void)) { unsigned int tmp; unsigned long flags; @@ -721,7 +437,7 @@ save_flags(flags); cli(); /* - * check if configuration type 1 works + * Check if configuration type 1 works. */ outb (0x01, 0xCFB); tmp = inl (0xCF8); @@ -729,153 +445,385 @@ if (inl (0xCF8) == 0x80000000) { outl (tmp, 0xCF8); restore_flags(flags); - printk("pcibios_init: Using configuration type 1\n"); + printk("PCI: Using configuration type 1\n"); return &pci_direct_conf1; } outl (tmp, 0xCF8); /* - * check if configuration type 2 works + * Check if configuration type 2 works. */ outb (0x00, 0xCFB); outb (0x00, 0xCF8); outb (0x00, 0xCFA); if (inb (0xCF8) == 0x00 && inb (0xCFB) == 0x00) { restore_flags(flags); - printk("pcibios_init: Using configuration type 2\n"); + printk("PCI: Using configuration type 2\n"); return &pci_direct_conf2; } restore_flags(flags); - printk("pcibios_init: Not supported chipset for direct PCI access !\n"); + printk("PCI: PCI hardware not found (i.e., not present or not supported).\n"); return NULL; } +#endif + +/* + * BIOS32 and PCI BIOS handling. + */ + +#ifdef CONFIG_PCI_BIOS + +#define PCIBIOS_PCI_FUNCTION_ID 0xb1XX +#define PCIBIOS_PCI_BIOS_PRESENT 0xb101 +#define PCIBIOS_FIND_PCI_DEVICE 0xb102 +#define PCIBIOS_FIND_PCI_CLASS_CODE 0xb103 +#define PCIBIOS_GENERATE_SPECIAL_CYCLE 0xb106 +#define PCIBIOS_READ_CONFIG_BYTE 0xb108 +#define PCIBIOS_READ_CONFIG_WORD 0xb109 +#define PCIBIOS_READ_CONFIG_DWORD 0xb10a +#define PCIBIOS_WRITE_CONFIG_BYTE 0xb10b +#define PCIBIOS_WRITE_CONFIG_WORD 0xb10c +#define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d + +/* BIOS32 signature: "_32_" */ +#define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24)) + +/* PCI signature: "PCI " */ +#define PCI_SIGNATURE (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24)) + +/* PCI service signature: "$PCI" */ +#define PCI_SERVICE (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24)) + +/* + * This is the standard structure used to identify the entry point + * to the BIOS32 Service Directory, as documented in + * Standard BIOS 32-bit Service Directory Proposal + * Revision 0.4 May 24, 1993 + * Phoenix Technologies Ltd. + * Norwood, MA + * and the PCI BIOS specification. + */ + +union bios32 { + struct { + unsigned long signature; /* _32_ */ + unsigned long entry; /* 32 bit physical address */ + unsigned char revision; /* Revision level, 0 */ + unsigned char length; /* Length in paragraphs should be 01 */ + unsigned char checksum; /* All bytes must add up to zero */ + unsigned char reserved[5]; /* Must be zero */ + } fields; + char chars[16]; +}; + +/* + * Physical address of the service directory. I don't know if we're + * allowed to have more than one of these or not, so just in case + * we'll make pcibios_present() take a memory start parameter and store + * the array there. + */ + +static unsigned long bios32_entry = 0; +static struct { + unsigned long address; + unsigned short segment; +} bios32_indirect = { 0, KERNEL_CS }; + +/* + * Returns the entry point for the given service, NULL on error + */ + +static unsigned long bios32_service(unsigned long service) +{ + unsigned char return_code; /* %al */ + unsigned long address; /* %ebx */ + unsigned long length; /* %ecx */ + unsigned long entry; /* %edx */ + unsigned long flags; + + save_flags(flags); cli(); + __asm__("lcall (%%edi)" + : "=a" (return_code), + "=b" (address), + "=c" (length), + "=d" (entry) + : "0" (service), + "1" (0), + "D" (&bios32_indirect)); + restore_flags(flags); + + switch (return_code) { + case 0: + return address + entry; + case 0x80: /* Not present */ + printk("bios32_service(0x%lx): not present\n", service); + return 0; + default: /* Shouldn't happen */ + printk("bios32_service(0x%lx): returned 0x%x, mail drew@colorado.edu\n", + service, return_code); + return 0; + } +} + +static long pcibios_entry = 0; +static struct { + unsigned long address; + unsigned short segment; +} pci_indirect = { 0, KERNEL_CS }; + +__initfunc(static int check_pcibios(void)) +{ + unsigned long signature; + unsigned char present_status; + unsigned char major_revision; + unsigned char minor_revision; + unsigned long flags; + int pack; -/* - * access defined pcibios functions via - * the function table - */ + if ((pcibios_entry = bios32_service(PCI_SERVICE))) { + pci_indirect.address = pcibios_entry | PAGE_OFFSET; -int pcibios_present(void) -{ - return access_pci ? 1 : 0; + save_flags(flags); cli(); + __asm__("lcall (%%edi)\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:\tshl $8, %%eax\n\t" + "movw %%bx, %%ax" + : "=d" (signature), + "=a" (pack) + : "1" (PCIBIOS_PCI_BIOS_PRESENT), + "D" (&pci_indirect) + : "bx", "cx"); + restore_flags(flags); + + present_status = (pack >> 16) & 0xff; + major_revision = (pack >> 8) & 0xff; + minor_revision = pack & 0xff; + if (present_status || (signature != PCI_SIGNATURE)) { + printk ("PCI: %s: BIOS32 Service Directory says PCI BIOS is present,\n" + " but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n" + " and signature of 0x%08lx (%c%c%c%c). Mail drew@Colorado.EDU\n", + (signature == PCI_SIGNATURE) ? "WARNING" : "ERROR", + present_status, signature, + (char) (signature >> 0), (char) (signature >> 8), + (char) (signature >> 16), (char) (signature >> 24)); + + if (signature != PCI_SIGNATURE) + pcibios_entry = 0; + } + if (pcibios_entry) { + printk ("PCI: PCI BIOS revision %x.%02x entry at 0x%lx\n", + major_revision, minor_revision, pcibios_entry); + return 1; + } + } + return 0; } -int pcibios_find_class (unsigned int class_code, unsigned short index, +static int pci_bios_find_class (unsigned int class_code, unsigned short index, unsigned char *bus, unsigned char *device_fn) { - if (access_pci && access_pci->find_class) - return access_pci->find_class(class_code, index, bus, device_fn); - - return PCIBIOS_FUNC_NOT_SUPPORTED; + unsigned long bx; + unsigned long ret; + unsigned long flags; + + save_flags(flags); cli(); + __asm__ ("lcall (%%edi)\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=b" (bx), + "=a" (ret) + : "1" (PCIBIOS_FIND_PCI_CLASS_CODE), + "c" (class_code), + "S" ((int) index), + "D" (&pci_indirect)); + restore_flags(flags); + *bus = (bx >> 8) & 0xff; + *device_fn = bx & 0xff; + return (int) (ret & 0xff00) >> 8; } -int pcibios_find_device (unsigned short vendor, unsigned short device_id, +static int pci_bios_find_device (unsigned short vendor, unsigned short device_id, unsigned short index, unsigned char *bus, unsigned char *device_fn) { - if (access_pci && access_pci->find_device) - return access_pci->find_device(vendor, device_id, index, bus, device_fn); - - return PCIBIOS_FUNC_NOT_SUPPORTED; + unsigned short bx; + unsigned short ret; + unsigned long flags; + + save_flags(flags); cli(); + __asm__("lcall (%%edi)\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=b" (bx), + "=a" (ret) + : "1" (PCIBIOS_FIND_PCI_DEVICE), + "c" (device_id), + "d" (vendor), + "S" ((int) index), + "D" (&pci_indirect)); + restore_flags(flags); + *bus = (bx >> 8) & 0xff; + *device_fn = bx & 0xff; + return (int) (ret & 0xff00) >> 8; } -int pcibios_read_config_byte (unsigned char bus, +static int pci_bios_read_config_byte(unsigned char bus, unsigned char device_fn, unsigned char where, unsigned char *value) { - if (access_pci && access_pci->read_config_byte) - return access_pci->read_config_byte(bus, device_fn, where, value); - - return PCIBIOS_FUNC_NOT_SUPPORTED; + unsigned long ret; + unsigned long bx = (bus << 8) | device_fn; + unsigned long flags; + + save_flags(flags); cli(); + __asm__("lcall (%%esi)\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=c" (*value), + "=a" (ret) + : "1" (PCIBIOS_READ_CONFIG_BYTE), + "b" (bx), + "D" ((long) where), + "S" (&pci_indirect)); + restore_flags(flags); + return (int) (ret & 0xff00) >> 8; } -int pcibios_read_config_word (unsigned char bus, +static int pci_bios_read_config_word (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned short *value) { - if (access_pci && access_pci->read_config_word) - return access_pci->read_config_word(bus, device_fn, where, value); - - return PCIBIOS_FUNC_NOT_SUPPORTED; + unsigned long ret; + unsigned long bx = (bus << 8) | device_fn; + unsigned long flags; + + save_flags(flags); cli(); + __asm__("lcall (%%esi)\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=c" (*value), + "=a" (ret) + : "1" (PCIBIOS_READ_CONFIG_WORD), + "b" (bx), + "D" ((long) where), + "S" (&pci_indirect)); + restore_flags(flags); + return (int) (ret & 0xff00) >> 8; } -int pcibios_read_config_dword (unsigned char bus, +static int pci_bios_read_config_dword (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned int *value) { - if (access_pci && access_pci->read_config_dword) - return access_pci->read_config_dword(bus, device_fn, where, value); - - return PCIBIOS_FUNC_NOT_SUPPORTED; + unsigned long ret; + unsigned long bx = (bus << 8) | device_fn; + unsigned long flags; + + save_flags(flags); cli(); + __asm__("lcall (%%esi)\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=c" (*value), + "=a" (ret) + : "1" (PCIBIOS_READ_CONFIG_DWORD), + "b" (bx), + "D" ((long) where), + "S" (&pci_indirect)); + restore_flags(flags); + return (int) (ret & 0xff00) >> 8; } -int pcibios_write_config_byte (unsigned char bus, +static int pci_bios_write_config_byte (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned char value) { - if (access_pci && access_pci->write_config_byte) - return access_pci->write_config_byte(bus, device_fn, where, value); - - return PCIBIOS_FUNC_NOT_SUPPORTED; + unsigned long ret; + unsigned long bx = (bus << 8) | device_fn; + unsigned long flags; + + save_flags(flags); cli(); + __asm__("lcall (%%esi)\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=a" (ret) + : "0" (PCIBIOS_WRITE_CONFIG_BYTE), + "c" (value), + "b" (bx), + "D" ((long) where), + "S" (&pci_indirect)); + restore_flags(flags); + return (int) (ret & 0xff00) >> 8; } -int pcibios_write_config_word (unsigned char bus, +static int pci_bios_write_config_word (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned short value) { - if (access_pci && access_pci->write_config_word) - return access_pci->write_config_word(bus, device_fn, where, value); - - return PCIBIOS_FUNC_NOT_SUPPORTED; -} + unsigned long ret; + unsigned long bx = (bus << 8) | device_fn; + unsigned long flags; -int pcibios_write_config_dword (unsigned char bus, - unsigned char device_fn, unsigned char where, unsigned int value) -{ - if (access_pci && access_pci->write_config_dword) - return access_pci->write_config_dword(bus, device_fn, where, value); - - return PCIBIOS_FUNC_NOT_SUPPORTED; + save_flags(flags); cli(); + __asm__("lcall (%%esi)\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=a" (ret) + : "0" (PCIBIOS_WRITE_CONFIG_WORD), + "c" (value), + "b" (bx), + "D" ((long) where), + "S" (&pci_indirect)); + restore_flags(flags); + return (int) (ret & 0xff00) >> 8; } -const char *pcibios_strerror (int error) +static int pci_bios_write_config_dword (unsigned char bus, + unsigned char device_fn, unsigned char where, unsigned int value) { - static char buf[80]; - - switch (error) { - case PCIBIOS_SUCCESSFUL: - return "SUCCESSFUL"; - - case PCIBIOS_FUNC_NOT_SUPPORTED: - return "FUNC_NOT_SUPPORTED"; - - case PCIBIOS_BAD_VENDOR_ID: - return "SUCCESSFUL"; - - case PCIBIOS_DEVICE_NOT_FOUND: - return "DEVICE_NOT_FOUND"; - - case PCIBIOS_BAD_REGISTER_NUMBER: - return "BAD_REGISTER_NUMBER"; - - case PCIBIOS_SET_FAILED: - return "SET_FAILED"; - - case PCIBIOS_BUFFER_TOO_SMALL: - return "BUFFER_TOO_SMALL"; + unsigned long ret; + unsigned long bx = (bus << 8) | device_fn; + unsigned long flags; - default: - sprintf (buf, "UNKNOWN RETURN 0x%x", error); - return buf; - } + save_flags(flags); cli(); + __asm__("lcall (%%esi)\n\t" + "jc 1f\n\t" + "xor %%ah, %%ah\n" + "1:" + : "=a" (ret) + : "0" (PCIBIOS_WRITE_CONFIG_DWORD), + "c" (value), + "b" (bx), + "D" ((long) where), + "S" (&pci_indirect)); + restore_flags(flags); + return (int) (ret & 0xff00) >> 8; } +/* + * Function table for BIOS32 access + */ -__initfunc(unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end)) -{ - return mem_start; -} +static struct pci_access pci_bios_access = { + 1, + pci_bios_find_device, + pci_bios_find_class, + pci_bios_read_config_byte, + pci_bios_read_config_word, + pci_bios_read_config_dword, + pci_bios_write_config_byte, + pci_bios_write_config_word, + pci_bios_write_config_dword +}; -#endif +/* + * Try to find PCI BIOS. + */ -__initfunc(unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end)) +__initfunc(static struct pci_access *pci_find_bios(void)) { -#ifdef CONFIG_PCI union bios32 *check; unsigned char sum; int i, length; @@ -884,7 +832,6 @@ * Follow the standard procedure for locating the BIOS32 Service * directory by scanning the permissible address range from * 0xe0000 through 0xfffff for a valid BIOS32 structure. - * */ for (check = (union bios32 *) __va(0xe0000); @@ -901,24 +848,59 @@ if (sum != 0) continue; if (check->fields.revision != 0) { - printk("pcibios_init : unsupported revision %d at 0x%p, mail drew@colorado.edu\n", + printk("PCI: unsupported BIOS32 revision %d at 0x%p, mail drew@colorado.edu\n", check->fields.revision, check); continue; } - printk ("pcibios_init : BIOS32 Service Directory structure at 0x%p\n", check); - if (!bios32_entry) { - if (check->fields.entry >= 0x100000) { - printk("pcibios_init: entry in high memory, trying direct PCI access\n"); - access_pci = check_direct_pci(); - } else { - bios32_entry = check->fields.entry; - printk ("pcibios_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry); - bios32_indirect.address = bios32_entry + PAGE_OFFSET; - } + printk ("PCI: BIOS32 Service Directory structure at 0x%p\n", check); + if (check->fields.entry >= 0x100000) { +#ifdef CONFIG_PCI_DIRECT + printk("PCI: BIOS32 entry in high memory, trying direct PCI access.\n"); + return pci_check_direct(); +#else + printk("PCI: BIOS32 entry in high memory, cannot use.\n"); +#endif + } else { + bios32_entry = check->fields.entry; + printk ("PCI: BIOS32 Service Directory entry at 0x%lx\n", bios32_entry); + bios32_indirect.address = bios32_entry + PAGE_OFFSET; + if (check_pcibios()) + return &pci_bios_access; } + break; /* Hopefully more than one BIOS32 cannot happen... */ } - if (bios32_entry && check_pcibios()) - access_pci = &pci_bios_access; + + return NULL; +} + +#endif + +/* + * No fixup function used. + */ + +__initfunc(unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end)) +{ + return mem_start; +} + +/* + * Initialization. Try all known PCI access methods. + */ + +__initfunc(unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end)) +{ + struct pci_access *a = NULL; + +#ifdef CONFIG_PCI_BIOS + a = pci_find_bios(); +#else +#ifdef CONFIG_PCI_DIRECT + a = pci_check_direct(); #endif +#endif + if (a) + access_pci = a; + return memory_start; } diff -u --recursive --new-file v2.1.53/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c --- v2.1.53/linux/arch/i386/kernel/irq.c Mon Jun 30 15:57:04 1997 +++ linux/arch/i386/kernel/irq.c Sat Sep 6 10:43:49 1997 @@ -42,8 +42,6 @@ extern volatile unsigned long smp_local_timer_ticks[1+NR_CPUS]; #endif -#define CR0_NE 32 - unsigned int local_irq_count[NR_CPUS]; #ifdef __SMP__ atomic_t __intel_bh_counter; @@ -55,6 +53,8 @@ static unsigned int int_count[NR_CPUS][NR_IRQS] = {{0},}; #endif +atomic_t nmi_counter; + /* * This contains the irq mask for both irq controllers */ @@ -199,7 +199,6 @@ * be shot. */ - static void math_error_irq(int cpl, void *dev_id, struct pt_regs *regs) { outb(0,0xF0); @@ -224,28 +223,26 @@ int get_irq_list(char *buf) { - int i, len = 0; + int i; struct irqaction * action; + char *p = buf; for (i = 0 ; i < NR_IRQS ; i++) { action = irq_action[i]; if (!action) continue; - len += sprintf(buf+len, "%2d: %10u %s", + p += sprintf(p, "%3d: %10u %s", i, kstat.interrupts[i], action->name); for (action=action->next; action; action = action->next) { - len += sprintf(buf+len, ", %s", action->name); + p += sprintf(p, ", %s", action->name); } - len += sprintf(buf+len, "\n"); + *p++ = '\n'; } -/* - * Linus - should you add NMI counts here ????? - */ + p += sprintf(p, "NMI: %10u\n", atomic_read(&nmi_counter)); #ifdef __SMP_PROF__ - len+=sprintf(buf+len, "IPI: %8lu received\n", - ipi_count); + p += sprintf(p, "IPI: %10lu\n", ipi_count); #endif - return len; + return p - buf; } #ifdef __SMP_PROF__ diff -u --recursive --new-file v2.1.53/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- v2.1.53/linux/arch/i386/kernel/traps.c Mon Jun 16 16:35:53 1997 +++ linux/arch/i386/kernel/traps.c Sat Sep 6 10:43:49 1997 @@ -29,6 +29,7 @@ #include #include #include +#include asmlinkage int system_call(void); asmlinkage void lcall7(void); @@ -271,7 +272,9 @@ asmlinkage void do_nmi(struct pt_regs * regs, long error_code) { unsigned char reason = inb(0x61); + extern atomic_t nmi_counter; + atomic_inc(&nmi_counter); if (reason & 0x80) mem_parity_error(reason, regs); if (reason & 0x40) @@ -348,7 +351,10 @@ asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs, long error_code) { +#if 0 + /* No need to warn about this any longer. */ printk("Ignoring P6 Local APIC Spurious Interrupt Bug...\n"); +#endif } /* diff -u --recursive --new-file v2.1.53/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c --- v2.1.53/linux/arch/i386/mm/init.c Mon Aug 4 16:25:35 1997 +++ linux/arch/i386/mm/init.c Sat Sep 6 10:15:18 1997 @@ -261,6 +261,43 @@ return free_area_init(start_mem, end_mem); } +/* + * Test if the WP bit works in supervisor mode. It isn't supported on 386's + * and also on some strange 486's (NexGen etc.). All 586+'s are OK. The jumps + * before and after the test are here to work-around some nasty CPU bugs. + */ + +__initfunc(void test_wp_bit(void)) +{ + unsigned char tmp_reg; + unsigned long old = pg0[0]; + + printk("Checking if this processor honours the WP bit even in supervisor mode... "); + pg0[0] = pte_val(mk_pte(PAGE_OFFSET, PAGE_READONLY)); + local_flush_tlb(); + current->mm->mmap->vm_start += PAGE_SIZE; + __asm__ __volatile__( + "jmp 1f; 1:\n" + "movb %0,%1\n" + "movb %1,%0\n" + "jmp 1f; 1:\n" + :"=m" (*(char *) __va(0)), + "=q" (tmp_reg) + :/* no inputs */ + :"memory"); + pg0[0] = old; + local_flush_tlb(); + current->mm->mmap->vm_start -= PAGE_SIZE; + if (wp_works_ok < 0) { + wp_works_ok = 0; + printk("No.\n"); +#ifndef CONFIG_M386 + panic("This kernel doesn't support CPU's with broken WP. Recompile it for a 386!"); +#endif + } else + printk("Ok.\n"); +} + __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem)) { unsigned long start_low_mem = PAGE_SIZE; @@ -339,30 +376,9 @@ reservedpages << (PAGE_SHIFT-10), datapages << (PAGE_SHIFT-10), initpages << (PAGE_SHIFT-10)); -/* test if the WP bit is honoured in supervisor mode */ - if (wp_works_ok < 0) { - unsigned char tmp_reg; - unsigned long old = pg0[0]; - printk("Checking if this processor honours the WP bit even in supervisor mode... "); - pg0[0] = pte_val(mk_pte(PAGE_OFFSET, PAGE_READONLY)); - local_flush_tlb(); - current->mm->mmap->vm_start += PAGE_SIZE; - __asm__ __volatile__( - "movb %0,%1 ; movb %1,%0" - :"=m" (*(char *) __va(0)), - "=q" (tmp_reg) - :/* no inputs */ - :"memory"); - pg0[0] = old; - local_flush_tlb(); - current->mm->mmap->vm_start -= PAGE_SIZE; - if (wp_works_ok < 0) { - wp_works_ok = 0; - printk("No.\n"); - } else - printk("Ok.\n"); - } - return; + + if (wp_works_ok < 0) + test_wp_bit(); } void free_initmem(void) diff -u --recursive --new-file v2.1.53/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig --- v2.1.53/linux/arch/sparc64/defconfig Thu Sep 4 17:07:30 1997 +++ linux/arch/sparc64/defconfig Sat Sep 6 10:04:15 1997 @@ -68,7 +68,7 @@ # # Floppy, IDE, and other block devices # -# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_FD=y CONFIG_BLK_DEV_MD=y CONFIG_MD_LINEAR=m CONFIG_MD_STRIPED=m diff -u --recursive --new-file v2.1.53/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c --- v2.1.53/linux/arch/sparc64/kernel/ebus.c Thu Sep 4 17:07:30 1997 +++ linux/arch/sparc64/kernel/ebus.c Sat Sep 6 10:04:15 1997 @@ -1,4 +1,4 @@ -/* $Id: ebus.c,v 1.7 1997/08/28 02:23:17 ecd Exp $ +/* $Id: ebus.c,v 1.8 1997/09/05 22:59:39 ecd Exp $ * ebus.c: PCI to EBus bridge device. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -39,16 +39,72 @@ extern unsigned int psycho_irq_build(unsigned int full_ino); -__initfunc(void fill_ebus_device(int node, struct linux_ebus_device *dev)) +static inline unsigned long +ebus_alloc(unsigned long *memory_start, size_t size) +{ + unsigned long mem; + + *memory_start = (*memory_start + 7) & ~(7); + mem = *memory_start; + *memory_start += size; + return mem; +} + +__initfunc(void fill_ebus_child(int node, struct linux_ebus_child *dev)) +{ + int regs[PROMREG_MAX]; + int irqs[PROMREG_MAX]; + char lbuf[128]; + int i, len; + + dev->prom_node = node; + prom_getstring(node, "name", lbuf, sizeof(lbuf)); + strcpy(dev->prom_name, lbuf); + + len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); + dev->num_addrs = len / sizeof(regs[0]); + + for (i = 0; i < dev->num_addrs; i++) { + if (regs[i] >= dev->parent->num_addrs) { + prom_printf("UGH: property for %s was %d, need < %d\n", + dev->prom_name, len, dev->parent->num_addrs); + panic(__FUNCTION__); + } + dev->base_address[i] = dev->parent->base_address[regs[i]]; + } + + len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); + if ((len == -1) || (len == 0)) { + dev->num_irqs = 0; + } else { + dev->num_irqs = len / sizeof(irqs[0]); + for (i = 0; i < dev->num_irqs; i++) + dev->irqs[i] = psycho_irq_build(irqs[i]); + } + +#ifdef DEBUG_FILL_EBUS_DEV + printk("child '%s': address%s\n", dev->prom_name, + dev->num_addrs > 1 ? "es" : ""); + for (i = 0; i < dev->num_addrs; i++) + printk(" %016lx\n", dev->base_address[i]); + if (dev->num_irqs) { + printk(" IRQ%s", dev->num_irqs > 1 ? "s" : ""); + for (i = 0; i < dev->num_irqs; i++) + printk(" %08x", dev->irqs[i]); + printk("\n"); + } +#endif +} + +__initfunc(unsigned long fill_ebus_device(int node, struct linux_ebus_device *dev, + unsigned long memory_start)) { struct linux_prom_registers regs[PROMREG_MAX]; + struct linux_ebus_child *child; int irqs[PROMINTR_MAX]; char lbuf[128]; int i, n, len; -#ifndef CONFIG_PCI - return; -#endif dev->prom_node = node; prom_getstring(node, "name", lbuf, sizeof(lbuf)); strcpy(dev->prom_name, lbuf); @@ -90,6 +146,27 @@ printk("\n"); } #endif + if ((node = prom_getchild(node))) { + dev->children = (struct linux_ebus_child *) + ebus_alloc(&memory_start, sizeof(struct linux_ebus_child)); + + child = dev->children; + child->next = 0; + child->parent = dev; + fill_ebus_child(node, child); + + while ((node = prom_getsibling(node))) { + child->next = (struct linux_ebus_child *) + ebus_alloc(&memory_start, sizeof(struct linux_ebus_child)); + + child = child->next; + child->next = 0; + child->parent = dev; + fill_ebus_child(node, child); + } + } + + return memory_start; } __initfunc(unsigned long ebus_init(unsigned long memory_start, @@ -100,31 +177,32 @@ struct linux_ebus_device *dev; struct linux_ebus *ebus; struct pci_dev *pdev; + struct pcidev_cookie *cookie; char lbuf[128]; unsigned long addr, *base; - int nd, len, ebusnd, topnd; + unsigned short pci_command; + int nd, len, ebusnd; int reg, rng, nreg; - int devfn; int num_ebus = 0; -#ifndef CONFIG_PCI - return memory_start; -#endif - - memory_start = ((memory_start + 7) & (~7)); - - topnd = psycho_root->pbm_B.prom_node; - if (!topnd) + if (!pcibios_present()) return memory_start; - ebusnd = prom_searchsiblings(prom_getchild(topnd), "ebus"); - if (ebusnd == 0) { - printk("EBUS: No EBUS's found.\n"); + for (pdev = pci_devices; pdev; pdev = pdev->next) { + if ((pdev->vendor == PCI_VENDOR_ID_SUN) && + (pdev->device == PCI_DEVICE_ID_SUN_EBUS)) + break; + } + if (!pdev) { + printk("ebus: No EBus's found.\n"); return memory_start; } - ebus_chain = ebus = (struct linux_ebus *)memory_start; - memory_start += sizeof(struct linux_ebus); + cookie = pdev->sysdata; + ebusnd = cookie->prom_node; + + ebus_chain = ebus = (struct linux_ebus *) + ebus_alloc(&memory_start, sizeof(struct linux_ebus)); ebus->next = 0; while (ebusnd) { @@ -133,7 +211,16 @@ prom_getstring(ebusnd, "name", lbuf, sizeof(lbuf)); ebus->prom_node = ebusnd; strcpy(ebus->prom_name, lbuf); - ebus->parent = pbm = &psycho_root->pbm_B; + + ebus->self = pdev; + ebus->parent = pbm = cookie->pbm; + + /* Enable BUS Master. */ + pcibios_read_config_word(pdev->bus->number, pdev->devfn, + PCI_COMMAND, &pci_command); + pci_command |= PCI_COMMAND_MASTER; + pcibios_write_config_word(pdev->bus->number, pdev->devfn, + PCI_COMMAND, pci_command); len = prom_getproperty(ebusnd, "reg", (void *)regs, sizeof(regs)); @@ -144,17 +231,6 @@ } nreg = len / sizeof(struct linux_prom_pci_registers); - devfn = (regs[0].phys_hi >> 8) & 0xff; - for (pdev = pbm->pci_bus.devices; pdev; pdev = pdev->sibling) - if (pdev->devfn == devfn) - break; - if (!pdev) { - prom_printf("%s: can't find PCI device\n", - __FUNCTION__); - prom_halt(); - } - ebus->self = pdev; - base = &ebus->self->base_address[0]; for (reg = 0; reg < nreg; reg++) { if (!(regs[reg].phys_hi & 0x03000000)) @@ -181,25 +257,41 @@ prom_ebus_ranges_init(ebus); nd = prom_getchild(ebusnd); - ebus->devices = (struct linux_ebus_device *)memory_start; - memory_start += sizeof(struct linux_ebus_device); + ebus->devices = (struct linux_ebus_device *) + ebus_alloc(&memory_start, sizeof(struct linux_ebus_device)); dev = ebus->devices; dev->next = 0; + dev->children = 0; dev->parent = ebus; - fill_ebus_device(nd, dev); + memory_start = fill_ebus_device(nd, dev, memory_start); while ((nd = prom_getsibling(nd))) { - dev->next = (struct linux_ebus_device *)memory_start; - memory_start += sizeof(struct linux_ebus_device); + dev->next = (struct linux_ebus_device *) + ebus_alloc(&memory_start, sizeof(struct linux_ebus_device)); dev = dev->next; dev->next = 0; + dev->children = 0; dev->parent = ebus; - fill_ebus_device(nd, dev); + memory_start = fill_ebus_device(nd, dev, memory_start); } - ebusnd = prom_searchsiblings(prom_getsibling(ebusnd), "ebus"); + for (pdev = pdev->next; pdev; pdev = pdev->next) { + if ((pdev->vendor == PCI_VENDOR_ID_SUN) && + (pdev->device == PCI_DEVICE_ID_SUN_EBUS)) + break; + } + if (!pdev) + break; + + cookie = pdev->sysdata; + ebusnd = cookie->prom_node; + + ebus->next = (struct linux_ebus *) + ebus_alloc(&memory_start, sizeof(struct linux_ebus)); + ebus = ebus->next; + ebus->next = 0; ++num_ebus; } diff -u --recursive --new-file v2.1.53/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c --- v2.1.53/linux/arch/sparc64/kernel/ioctl32.c Thu Sep 4 17:07:30 1997 +++ linux/arch/sparc64/kernel/ioctl32.c Sat Sep 6 10:04:15 1997 @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.17 1997/09/03 11:54:49 ecd Exp $ +/* $Id: ioctl32.c,v 1.18 1997/09/06 02:25:13 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -33,13 +33,6 @@ #include #include -/* - * XXX: for DaveM: - * This is the kludge to know what size of buffer to - * copy back to the user... (ecd) - */ -int ifr_data_len; - /* As gcc will warn about casting u32 to some ptr, we have to cast it to * unsigned long first, and that's what is A() for. * You just do (void *)A(x), instead of having to type (void *)((unsigned long)x) @@ -203,13 +196,17 @@ case SIOCGPPPVER: { u32 data; + int len; + __get_user(data, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_data)); - /* - * XXX: for DaveM: - * Here we use 'ifr_data_len' to know what size of buffer to - * copy back to the user... (ecd) - */ - if (copy_to_user((char *)A(data), ifr.ifr_data, ifr_data_len)) + if(cmd == SIOCGPPPVER) + len = strlen(PPP_VERSION) + 1; + else if(cmd == SIOCGPPPCSTATS) + len = sizeof(struct ppp_comp_stats); + else + len = sizeof(struct ppp_stats); + + if (copy_to_user((char *)A(data), ifr.ifr_data, len)) return -EFAULT; break; } diff -u --recursive --new-file v2.1.53/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.1.53/linux/drivers/block/floppy.c Mon Aug 18 18:19:45 1997 +++ linux/drivers/block/floppy.c Sat Sep 6 10:09:56 1997 @@ -161,11 +161,6 @@ #include #include /* for the compatibility eject ioctl */ - -#ifndef FLOPPY_MOTOR_MASK -#define FLOPPY_MOTOR_MASK 0xf0 -#endif - #ifndef fd_get_dma_residue #define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA) #endif diff -u --recursive --new-file v2.1.53/linux/drivers/block/hd.c linux/drivers/block/hd.c --- v2.1.53/linux/drivers/block/hd.c Tue May 13 22:41:04 1997 +++ linux/drivers/block/hd.c Sat Sep 6 10:08:56 1997 @@ -584,7 +584,7 @@ unsigned int cmd, unsigned long arg) { struct hd_geometry *loc = (struct hd_geometry *) arg; - int dev, err; + int dev; if ((!inode) || !(inode->i_rdev)) return -EINVAL; @@ -593,19 +593,15 @@ return -EINVAL; switch (cmd) { case HDIO_GETGEO: + { + struct hd_geometry g; if (!loc) return -EINVAL; - err = verify_area(VERIFY_WRITE, loc, sizeof(*loc)); - if (err) - return err; - put_user(hd_info[dev].head, - (char *) &loc->heads); - put_user(hd_info[dev].sect, - (char *) &loc->sectors); - put_user(hd_info[dev].cyl, - (short *) &loc->cylinders); - put_user(hd[MINOR(inode->i_rdev)].start_sect, - (long *) &loc->start); - return 0; + g.heads = hd_info[dev].head; + g.sectors = hd_info[dev].sect; + g.cylinders = hd_info[dev].cyl; + g.start = hd[MINOR(inode->i_rdev)].start_sect; + return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; + } case BLKRASET: if(!suser()) return -EACCES; if(arg > 0xff) return -EINVAL; @@ -613,18 +609,12 @@ return 0; case BLKRAGET: if (!arg) return -EINVAL; - err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); - if (err) - return err; - put_user(read_ahead[MAJOR(inode->i_rdev)],(long *) arg); - return 0; + return put_user(read_ahead[MAJOR(inode->i_rdev)], + (long *) arg); case BLKGETSIZE: /* Return device size */ if (!arg) return -EINVAL; - err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); - if (err) - return err; - put_user(hd[MINOR(inode->i_rdev)].nr_sects, (long *) arg); - return 0; + return put_user(hd[MINOR(inode->i_rdev)].nr_sects, + (long *) arg); case BLKFLSBUF: if(!suser()) return -EACCES; fsync_dev(inode->i_rdev); @@ -817,7 +807,7 @@ /* * This routine is called to flush all partitions and partition tables - * for a changed scsi disk, and then re-read the new partition table. + * for a changed disk, and then re-read the new partition table. * If we are revalidating a disk because of a media change, then we * enter with usage == 0. If we are using an ioctl, we automatically have * usage == 1 (we need an open channel to use an ioctl :-), so this @@ -850,8 +840,11 @@ for (i=max_p - 1; i >=0 ; i--) { int minor = start + i; kdev_t devi = MKDEV(MAJOR_NR, minor); + struct super_block *sb = get_super(devi); + sync_dev(devi); - invalidate_inodes(devi); + if (sb) + invalidate_inodes(sb); invalidate_buffers(devi); gdev->part[minor].start_sect = 0; gdev->part[minor].nr_sects = 0; diff -u --recursive --new-file v2.1.53/linux/drivers/block/raid0.c linux/drivers/block/raid0.c --- v2.1.53/linux/drivers/block/raid0.c Sun May 19 21:50:46 1996 +++ linux/drivers/block/raid0.c Sat Sep 6 10:07:51 1997 @@ -20,13 +20,13 @@ #include #include #include -#include +#include #define MAJOR_NR MD_MAJOR #define MD_DRIVER #define MD_PERSONALITY -static void create_strip_zones (int minor, struct md_dev *mddev) +static int create_strip_zones (int minor, struct md_dev *mddev) { int i, j, c=0; int current_offset=0; @@ -50,8 +50,8 @@ c=0; } - data->strip_zone=kmalloc (sizeof(struct strip_zone)*data->nr_strip_zones, - GFP_KERNEL); + if ((data->strip_zone=vmalloc(sizeof(struct strip_zone)*data->nr_strip_zones)) == NULL) + return 1; data->smallest=NULL; @@ -81,6 +81,7 @@ data->strip_zone[i-1].size) : 0; current_offset=smallest_by_zone->size; } + return 0; } static int raid0_run (int minor, struct md_dev *mddev) @@ -90,17 +91,26 @@ MOD_INC_USE_COUNT; - mddev->private=kmalloc (sizeof (struct raid0_data), GFP_KERNEL); + if ((mddev->private=vmalloc (sizeof (struct raid0_data))) == NULL) return 1; data=(struct raid0_data *) mddev->private; - create_strip_zones (minor, mddev); + if (create_strip_zones (minor, mddev)) + { + vfree(data); + return 1; + } nb_zone=data->nr_zones= md_size[minor]/data->smallest->size + (md_size[minor]%data->smallest->size ? 1 : 0); - - data->hash_table=kmalloc (sizeof (struct raid0_hash)*nb_zone, GFP_KERNEL); + printk ("raid0 : Allocating %d bytes for hash.\n",sizeof(struct raid0_hash)*nb_zone); + if ((data->hash_table=vmalloc (sizeof (struct raid0_hash)*nb_zone)) == NULL) + { + vfree(data->strip_zone); + vfree(data); + return 1; + } size=data->strip_zone[cur].size; i=0; @@ -142,9 +152,9 @@ { struct raid0_data *data=(struct raid0_data *) mddev->private; - kfree (data->hash_table); - kfree (data->strip_zone); - kfree (data); + vfree (data->hash_table); + vfree (data->strip_zone); + vfree (data); MOD_DEC_USE_COUNT; return 0; diff -u --recursive --new-file v2.1.53/linux/drivers/block/rd.c linux/drivers/block/rd.c --- v2.1.53/linux/drivers/block/rd.c Thu Jul 17 10:06:04 1997 +++ linux/drivers/block/rd.c Sat Sep 6 10:23:14 1997 @@ -447,7 +447,7 @@ struct inode inode, out_inode; struct file infile, outfile; struct dentry in_dentry, out_dentry; - unsigned short fs; + unsigned long fs; kdev_t ram_device; int nblocks, i; char *buf; diff -u --recursive --new-file v2.1.53/linux/drivers/char/Config.in linux/drivers/char/Config.in --- v2.1.53/linux/drivers/char/Config.in Thu Aug 14 20:49:16 1997 +++ linux/drivers/char/Config.in Sat Sep 6 10:16:07 1997 @@ -101,8 +101,10 @@ fi tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG + tristate ' Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT fi bool 'Enhanced Real Time Clock Support' CONFIG_RTC +bool 'Tadpole ANA H8 Support' CONFIG_H8 tristate '/dev/nvram support' CONFIG_NVRAM tristate 'PC joystick support' CONFIG_JOYSTICK endmenu diff -u --recursive --new-file v2.1.53/linux/drivers/char/Makefile linux/drivers/char/Makefile --- v2.1.53/linux/drivers/char/Makefile Thu Aug 14 20:49:16 1997 +++ linux/drivers/char/Makefile Sat Sep 6 10:16:07 1997 @@ -204,6 +204,16 @@ endif endif +ifeq ($(CONFIG_ACQUIRE_WDT),y) +M = y +L_OBJS += acquirewdt.o +else + ifeq ($(CONFIG_ACQUIRE_WDT),m) + M_OBJS += acquirewdt.o + MM = m + endif +endif + ifeq ($(CONFIG_AMIGAMOUSE),y) M = y L_OBJS += amigamouse.o @@ -290,6 +300,11 @@ ifdef CONFIG_APM LX_OBJS += apm_bios.o +M = y +endif + +ifdef CONFIG_H8 +LX_OBJS += h8.o M = y endif diff -u --recursive --new-file v2.1.53/linux/drivers/char/acquirewdt.c linux/drivers/char/acquirewdt.c --- v2.1.53/linux/drivers/char/acquirewdt.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/acquirewdt.c Sat Sep 6 10:16:07 1997 @@ -0,0 +1,221 @@ +/* + * Acquire Single Board Computer Watchdog Timer driver for Linux 2.1.x + * + * Based on wdt.c. Original copyright messages: + * + * (c) Copyright 1996 Alan Cox , All Rights Reserved. + * http://www.cymru.net + * + * 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. + * + * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 1995 Alan Cox + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int acq_is_open=0; + +/* + * You must set these - there is no sane way to probe for this board. + */ + +#define WDT_STOP 0x43 +#define WDT_START 0x443 +#define WATCHDOG_MINOR 130 + +#define WD_TIMO (100*60) /* 1 minute */ + + +/* + * Kernel methods. + */ + + +static void acq_ping(void) +{ + /* Write a watchdog value */ + inb_p(WDT_START); +} + +static long acq_write(struct inode *inode, struct file *file, const char *buf, unsigned long count) +{ + if(count) + { + acq_ping(); + return 1; + } + return 0; +} + +static long acq_read(struct inode *inode, struct file *file, char *buf, unsigned long count) +{ + return -EINVAL; +} + + + +static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + static struct watchdog_info ident= + { + WDIOF_KEEPALIVEPING, 1, "Acquire WDT" + }; + + switch(cmd) + { + case WDIOC_GETSUPPORT: + if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) + return -EFAULT; + break; + + case WDIOC_GETSTATUS: + if (copy_to_user((int *)arg, &acq_is_open, sizeof(int))) + return -EFAULT; + break; + + case WDIOC_KEEPALIVE: + acq_ping(); + break; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static int acq_open(struct inode *inode, struct file *file) +{ + switch(MINOR(inode->i_rdev)) + { + case WATCHDOG_MINOR: + if(acq_is_open) + return -EBUSY; + MOD_INC_USE_COUNT; + /* + * Activate + */ + + acq_is_open=1; + inb_p(WDT_START); + return 0; + default: + return -ENODEV; + } +} + +static int acq_close(struct inode *inode, struct file *file) +{ + if(MINOR(inode->i_rdev)==WATCHDOG_MINOR) + { +#ifndef CONFIG_WATCHDOG_NOWAYOUT + inb_p(WDT_STOP); +#endif + acq_is_open=0; + } + MOD_DEC_USE_COUNT; + return 0; +} + +/* + * Notifier for system down + */ + +static int acq_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if(code==SYS_DOWN || code==SYS_HALT) + { + /* Turn the card off */ + inb_p(WDT_STOP); + } + return NOTIFY_DONE; +} + +/* + * Kernel Interfaces + */ + + +static struct file_operations acq_fops = { + NULL, + acq_read, + acq_write, + NULL, /* No Readdir */ + NULL, /* No Select */ + acq_ioctl, + NULL, /* No mmap */ + acq_open, + acq_close +}; + +static struct miscdevice acq_miscdev= +{ + WATCHDOG_MINOR, + "Acquire WDT", + &acq_fops +}; + + +/* + * The WDT card needs to learn about soft shutdowns in order to + * turn the timebomb registers off. + */ + +static struct notifier_block acq_notifier= +{ + acq_notify_sys, + NULL, + 0 +}; + +#ifdef MODULE + +#define acq_init init_module + +void cleanup_module(void) +{ + misc_deregister(&acq_miscdev); + unregister_reboot_notifier(&acq_notifier); + release_region(WDT_STOP,1); + release_region(WDT_START,1); +} + +#endif + +__initfunc(int acq_init(void)) +{ + printk("WDT driver for Acquire single board computer initialising.\n"); + + misc_register(&acq_miscdev); + request_region(WDT_STOP, 1, "Acquire WDT"); + request_region(WDT_START, 1, "Acquire WDT"); + unregister_reboot_notifier(&acq_notifier); + return 0; +} + diff -u --recursive --new-file v2.1.53/linux/drivers/char/h8.c linux/drivers/char/h8.c --- v2.1.53/linux/drivers/char/h8.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/h8.c Sat Sep 6 10:16:07 1997 @@ -0,0 +1,1272 @@ +/* + */ +/* + * Hitachi H8/337 Microcontroller driver + * + * The H8 is used to deal with the power and thermal environment + * of a system. + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_PROC_FS +#include +#include +#endif +#include +#include +#include + +#define __KERNEL_SYSCALLS__ +#include + +#include "h8.h" + +#define DEBUG_H8 + +#ifdef DEBUG_H8 +#define Dprintk printk +#else +#define Dprintk +#endif + +#define XDprintk if(h8_debug==-1)printk + +/* + * The h8 device is one of the misc char devices. + */ +#define H8_MINOR_DEV 140 + +/* + * Forward declarations. + */ +int h8_init(void); +int h8_display_blank(void); +int h8_display_unblank(void); + +static int h8_open(struct inode *, struct file *); +static void h8_release(struct inode *, struct file *); +static long h8_read(struct inode *, struct file *, char *, u_long); +static int h8_select(struct inode *, struct file *, int, select_table *); +static int h8_ioctl(struct inode *, struct file *, u_int, u_long); + +static void h8_intr(int irq, void *dev_id, struct pt_regs *regs); + +#ifdef CONFIG_PROC_FS +static int h8_get_info(char *, char **, off_t, int, int); +#endif + +/* + * Support Routines. + */ +static void h8_hw_init(void); +static void h8_start_new_cmd(void); +static void h8_send_next_cmd_byte(void); +static void h8_read_event_status(void); +static void h8_sync(void); +static void h8_q_cmd(u_char *, int, int); +static void h8_cmd_done(h8_cmd_q_t *qp); +static int h8_alloc_queues(void); + +static u_long h8_get_cpu_speed(void); +static int h8_get_curr_temp(u_char curr_temp[]); +static void h8_get_max_temp(void); +static void h8_get_upper_therm_thold(void); +static void h8_set_upper_therm_thold(int); +static int h8_get_ext_status(u_char stat_word[]); + +static int h8_monitor_thread(void *); + +static int h8_manage_therm(void); +static void h8_set_cpu_speed(int speed_divisor); + +static void h8_start_monitor_timer(unsigned long secs); +static void h8_activate_monitor(unsigned long unused); + +/* in arch/alpha/kernel/lca.c */ +extern void lca_clock_print(void); +extern int lca_get_clock(void); +extern void lca_clock_fiddle(int); + +static void h8_set_event_mask(int); +static void h8_clear_event_mask(int); + +/* + * Driver structures + */ + +static struct timer_list h8_monitor_timer; +static int h8_monitor_timer_active = 0; + +static char driver_version[] = "X0.0";/* no spaces */ + +static struct file_operations h8_fops = { + NULL, /* lseek */ + h8_read, + NULL, /* write */ + NULL, /* readdir */ + h8_select, + h8_ioctl, + NULL, /* mmap */ + h8_open, + h8_release, + NULL, /* fsync */ + NULL /* fasync */ +}; + +static struct miscdevice h8_device = { + H8_MINOR_DEV, + "h8", + &h8_fops +}; + +#ifdef CONFIG_PROC_FS +static struct proc_dir_entry h8_proc_entry = { + 0, 3, "h8", S_IFREG | S_IRUGO, 1, 0, 0, 0, 0, h8_get_info +}; +#endif + +union intr_buf intrbuf; +int intr_buf_ptr; +union intr_buf xx; +u_char last_temp; + +/* + * I/O Macros for register reads and writes. + */ +#define H8_READ(a) inb((a)) +#define H8_WRITE(d,a) outb((d),(a)) + +#define H8_GET_STATUS H8_READ((h8_base) + H8_STATUS_REG_OFF) +#define H8_READ_DATA H8_READ((h8_base) + H8_DATA_REG_OFF) +#define WRITE_DATA(d) H8_WRITE((d), h8_base + H8_DATA_REG_OFF) +#define WRITE_CMD(d) H8_WRITE((d), h8_base + H8_CMD_REG_OFF) + +unsigned int h8_base = H8_BASE_ADDR; +unsigned int h8_irq = H8_IRQ; +unsigned int h8_state = H8_IDLE; +unsigned int h8_index = -1; +unsigned int h8_enabled = 0; + +queue_head_t h8_actq, h8_cmdq, h8_freeq; + +/* + * Globals used in thermal control of Alphabook1. + */ +int cpu_speed_divisor = -1; +int h8_event_mask = 0; +struct wait_queue *h8_monitor_wait = NULL; +unsigned int h8_command_mask = 0; +int h8_uthermal_threshold = DEFAULT_UTHERMAL_THRESHOLD; +int h8_uthermal_window = UTH_HYSTERESIS; +int h8_debug = 0xfffffdfc; +int h8_ldamp = MHZ_115; +int h8_udamp = MHZ_57; +u_char h8_current_temp = 0; +u_char h8_system_temp = 0; +int h8_sync_channel = 0; +struct wait_queue *h8_sync_wait = NULL; +int h8_init_performed; + +/* CPU speeds and clock divisor values */ +int speed_tab[6] = {230, 153, 115, 57, 28, 14}; + +/* + * H8 interrupt handler + */ +static void h8_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + u_char stat_reg, data_reg; + h8_cmd_q_t *qp = (h8_cmd_q_t *)QUEUE_FIRST(&h8_actq, link); + + stat_reg = H8_GET_STATUS; + data_reg = H8_READ_DATA; + + XDprintk("h8_intr: state %d status 0x%x data 0x%x\n", h8_state, stat_reg, data_reg); + + switch (h8_state) { + /* Response to an asynchronous event. */ + case H8_IDLE: { /* H8_IDLE */ + if (stat_reg & H8_OFULL) { + if (data_reg == H8_INTR) { + h8_state = H8_INTR_MODE; + /* Executing a command to determine what happened. */ + WRITE_CMD(H8_RD_EVENT_STATUS); + intr_buf_ptr = 1; + WRITE_CMD(H8_RD_EVENT_STATUS); + } else { + Dprintk("h8_intr: idle stat 0x%x data 0x%x\n", + stat_reg, data_reg); + } + } else { + Dprintk("h8_intr: bogus interrupt\n"); + } + break; + } + case H8_INTR_MODE: { /* H8_INTR_MODE */ + XDprintk("H8 intr/intr_mode\n"); + if (data_reg == H8_BYTE_LEVEL_ACK) { + return; + } else if (data_reg == H8_CMD_ACK) { + return; + } else { + intrbuf.byte[intr_buf_ptr] = data_reg; + if(!intr_buf_ptr) { + h8_state = H8_IDLE; + h8_read_event_status(); + } + intr_buf_ptr--; + } + break; + } + /* Placed in this state by h8_start_new_cmd(). */ + case H8_XMIT: { /* H8_XMIT */ + XDprintk("H8 intr/xmit\n"); + /* If a byte level acknowledgement has been received */ + if (data_reg == H8_BYTE_LEVEL_ACK) { + XDprintk("H8 intr/xmit BYTE ACK\n"); + qp->nacks++; + if (qp->nacks > qp->ncmd) + if(h8_debug & 0x1) + Dprintk("h8intr: bogus # of acks!\n"); + /* + * If the number of bytes sent is less than the total + * number of bytes in the command. + */ + if (qp->cnt < qp->ncmd) { + h8_send_next_cmd_byte(); + } + return; + /* If the complete command has produced an acknowledgement. */ + } else if (data_reg == H8_CMD_ACK) { + XDprintk("H8 intr/xmit CMD ACK\n"); + /* If there are response bytes */ + if (qp->nrsp) + h8_state = H8_RCV; + else + h8_state = H8_IDLE; + qp->cnt = 0; + return; + /* Error, need to start over with a clean slate. */ + } else if (data_reg == H8_NACK) { + XDprintk("h8_intr: NACK received restarting command\n"); + qp->nacks = 0; + qp->cnt = 0; + h8_state = H8_IDLE; + WRITE_CMD(H8_SYNC); + return; + } else { + Dprintk ("h8intr: xmit unknown data 0x%x \n", data_reg); + return; + } + break; + } + case H8_RESYNC: { /* H8_RESYNC */ + XDprintk("H8 intr/resync\n"); + if (data_reg == H8_BYTE_LEVEL_ACK) { + return; + } else if (data_reg == H8_SYNC_BYTE) { + h8_state = H8_IDLE; + if (!QUEUE_EMPTY(&h8_actq, link)) + h8_send_next_cmd_byte(); + } else { + Dprintk ("h8_intr: resync unknown data 0x%x \n", data_reg); + return; + } + break; + } + case H8_RCV: { /* H8_RCV */ + XDprintk("H8 intr/rcv\n"); + if (qp->cnt < qp->nrsp) { + qp->rcvbuf[qp->cnt] = data_reg; + qp->cnt++; + /* If command reception finished. */ + if (qp->cnt == qp->nrsp) { + h8_state = H8_IDLE; + QUEUE_REMOVE(&h8_actq, qp, link); + h8_cmd_done (qp); + /* More commands to send over? */ + if (!QUEUE_EMPTY(&h8_cmdq, link)) + h8_start_new_cmd(); + } + return; + } else { + Dprintk ("h8intr: rcv overflow cmd 0x%x\n", qp->cmdbuf[0]); + } + break; + } + default: /* default */ + Dprintk("H8 intr/unknown\n"); + break; + } + return; +} + +#ifdef MODULE + +int init_module(void) +{ + printk("H8 module at %X(Interrupt %d)\n", h8_base, h8_irq); + if(request_irq(h8_irq, h8_intr, SA_INTERRUPT, "h8", NULL)) + { + printk("H8: error: IRQ %d is not free.\n", h8_irq); + return -EIO; + } + + misc_register(&h8_device); + request_region(h8_base, 8, "h8"); + +#ifdef CONFIG_PROC_FS + proc_register_dynamic(&proc_root, &h8_proc_entry); +#endif + + QUEUE_INIT(&h8_actq, link, h8_cmd_q_t *); + QUEUE_INIT(&h8_cmdq, link, h8_cmd_q_t *); + QUEUE_INIT(&h8_freeq, link, h8_cmd_q_t *); + h8_alloc_queues(); + + h8_hw_init(); + + kernel_thread(h8_monitor_thread, NULL, 0); + + return 0; +} + +void cleanup_module(void) +{ + misc_deregister(&h8_device); + release_region(h8_base, 8); + free_irq(h8_irq, NULL); +} + +#else /* MODULE */ + +int h8_init(void) +{ + if(request_irq(h8_irq, h8_intr, SA_INTERRUPT, "h8", NULL)) + { + printk("H8: error: IRQ %d is not free\n", h8_irq); + return -EIO; + } + printk("H8 at 0x%x IRQ %d\n", h8_base, h8_irq); + +#ifdef CONFIG_PROC_FS + proc_register_dynamic(&proc_root, &h8_proc_entry); +#endif + + misc_register(&h8_device); + request_region(h8_base, 8, "h8"); + + QUEUE_INIT(&h8_actq, link, h8_cmd_q_t *); + QUEUE_INIT(&h8_cmdq, link, h8_cmd_q_t *); + QUEUE_INIT(&h8_freeq, link, h8_cmd_q_t *); + h8_alloc_queues(); + + h8_hw_init(); + + kernel_thread(h8_monitor_thread, NULL, 0); + + return 0; +} +#endif /* MODULE */ + +void h8_hw_init(void) +{ + u_char buf[H8_MAX_CMD_SIZE]; + + /* set CPU speed to max for booting */ + h8_set_cpu_speed(MHZ_230); + + /* + * Initialize the H8 + */ + h8_sync(); /* activate interrupts */ + + /* To clear conditions left by console */ + h8_read_event_status(); + + /* Perform a conditioning read */ + buf[0] = H8_DEVICE_CONTROL; + buf[1] = 0xff; + buf[2] = 0x0; + h8_q_cmd(buf, 3, 1); + + /* Turn on built-in and external mice, capture power switch */ + buf[0] = H8_DEVICE_CONTROL; + buf[1] = 0x0; + buf[2] = H8_ENAB_INT_PTR | H8_ENAB_EXT_PTR | + /*H8_DISAB_PWR_OFF_SW |*/ H8_ENAB_LOW_SPD_IND; + h8_q_cmd(buf, 3, 1); + + h8_enabled = 1; + return; +} + +#ifdef CONFIG_PROC_FS +int h8_get_info(char *buf, char **start, off_t fpos, int length, int dummy) +{ + char *p; + + if (!h8_enabled) + return 0; + p = buf; + + + /* + 0) Linux driver version (this will change if format changes) + 1) + 2) + 3) + 4) + */ + + p += sprintf(p, "%s \n", + driver_version + ); + + return p - buf; +} +#endif + +static long h8_read(struct inode *inode, struct file *fp, char *buf, + u_long count) +{ + printk("h8_read: IMPDEL\n"); + return 0; +} + +static int h8_select(struct inode *inode, struct file *fp, int sel_type, + select_table * wait) +{ + printk("h8_select: IMPDEL\n"); + return 0; +} + +static int h8_ioctl(struct inode * inode, struct file *filp, + u_int cmd, u_long arg) +{ + printk("h8_ioctl: IMPDEL\n"); + return 0; +} + +static void h8_release(struct inode * inode, struct file * filp) +{ + printk("h8_release: IMPDEL\n"); +} + +static int h8_open(struct inode * inode, struct file * filp) +{ + printk("h8_open: IMPDEL\n"); + return 0; +} + +/* Called from console driver -- must make sure h8_enabled. */ +int h8_display_blank(void) +{ +#ifdef CONFIG_H8_DISPLAY_BLANK + int error; + + if (!h8_enabled) + return 0; + error = h8_set_display_power_state(H8_STATE_STANDBY); + if (error == H8_SUCCESS) + return 1; + h8_error("set display standby", error); +#endif + return 0; +} + +/* Called from console driver -- must make sure h8_enabled. */ +int h8_display_unblank(void) +{ +#ifdef CONFIG_H8_DISPLAY_BLANK + int error; + + if (!h8_enabled) + return 0; + error = h8_set_display_power_state(H8_STATE_READY); + if (error == H8_SUCCESS) + return 1; + h8_error("set display ready", error); +#endif + return 0; +} + +int +h8_alloc_queues(void) +{ + h8_cmd_q_t *qp; + unsigned long flags; + int i; + + qp = (h8_cmd_q_t *)kmalloc((sizeof (h8_cmd_q_t) * H8_Q_ALLOC_AMOUNT), + GFP_KERNEL); + + if (!qp) { + printk("H8: could not allocate memory for command queue\n"); + return(0); + } + /* add to the free queue */ + save_flags(flags); cli(); + for (i = 0; i < H8_Q_ALLOC_AMOUNT; i++) { + /* place each at front of freeq */ + QUEUE_ENTER(&h8_freeq, &qp[i], link, h8_cmd_q_t *); + } + restore_flags(flags); + return (1); +} + +/* + * Basic means by which commands are sent to the H8. + */ +void +h8_q_cmd(u_char *cmd, int cmd_size, int resp_size) +{ + h8_cmd_q_t *qp; + unsigned long flags; + int i; + + /* get cmd buf */ + save_flags(flags); cli(); + while (QUEUE_EMPTY(&h8_freeq, link)) { + Dprintk("H8: need to allocate more cmd buffers\n"); + restore_flags(flags); + h8_alloc_queues(); + save_flags(flags); cli(); + } + /* get first element from queue */ + qp = (h8_cmd_q_t *)QUEUE_FIRST(&h8_freeq, link); + QUEUE_REMOVE(&h8_freeq, qp, link); + + restore_flags(flags); + + /* fill it in */ + for (i = 0; i < cmd_size; i++) + qp->cmdbuf[i] = cmd[i]; + qp->ncmd = cmd_size; + qp->nrsp = resp_size; + + /* queue it at the end of the cmd queue */ + save_flags(flags); cli(); + + QUEUE_ENTER(&h8_cmdq, qp, link, h8_cmd_q_t *); + + restore_flags(flags); + + h8_start_new_cmd(); +} + +void +h8_start_new_cmd(void) +{ + unsigned long flags; + h8_cmd_q_t *qp; + + save_flags(flags); cli(); + if (h8_state != H8_IDLE) { + if (h8_debug & 0x1) + Dprintk("h8_start_new_cmd: not idle\n"); + restore_flags(flags); + return; + } + + if (!QUEUE_EMPTY(&h8_actq, link)) { + Dprintk("h8_start_new_cmd: inconsistency: IDLE with non-empty active queue!\n"); + restore_flags(flags); + return; + } + + if (QUEUE_EMPTY(&h8_cmdq, link)) { + Dprintk("h8_start_new_cmd: no command to dequeue\n"); + restore_flags(flags); + return; + } + /* + * Take first command off of the command queue and put + * it on the active queue. + */ + qp = (h8_cmd_q_t *) QUEUE_FIRST(&h8_cmdq, link); + QUEUE_REMOVE(&h8_cmdq, qp, link); + QUEUE_ENTER(&h8_actq, qp, link, h8_cmd_q_t *); + h8_state = H8_XMIT; + if (h8_debug & 0x1) + Dprintk("h8_start_new_cmd: Starting a command\n"); + + qp->cnt = 1; + WRITE_CMD(qp->cmdbuf[0]); /* Kick it off */ + + restore_flags(flags); + return; +} + +void +h8_send_next_cmd_byte(void) +{ + h8_cmd_q_t *qp = (h8_cmd_q_t *)QUEUE_FIRST(&h8_actq, link); + int cnt; + + cnt = qp->cnt; + qp->cnt++; + + if (h8_debug & 0x1) + Dprintk("h8 sending next cmd byte 0x%x (0x%x)\n", + cnt, qp->cmdbuf[cnt]); + + if (cnt) { + WRITE_DATA(qp->cmdbuf[cnt]); + } else { + WRITE_CMD(qp->cmdbuf[cnt]); + } + return; +} + +/* + * Synchronize H8 communications channel for command transmission. + */ +void +h8_sync(void) +{ + u_char buf[H8_MAX_CMD_SIZE]; + + buf[0] = H8_SYNC; + buf[1] = H8_SYNC_BYTE; + h8_q_cmd(buf, 2, 1); +} + +/* + * Responds to external interrupt. Reads event status word and + * decodes type of interrupt. + */ +void +h8_read_event_status(void) +{ + + if(h8_debug & 0x200) + printk("h8_read_event_status: value 0x%x\n", intrbuf.word); + + /* + * Power related items + */ + if (intrbuf.word & H8_DC_CHANGE) { + if(h8_debug & 0x4) + printk("h8_read_event_status: DC_CHANGE\n"); + /* see if dc added or removed, set batt/dc flag, send event */ + + h8_set_event_mask(H8_MANAGE_BATTERY); + wake_up(&h8_monitor_wait); + } + + if (intrbuf.word & H8_POWER_BUTTON) { + printk("Power switch pressed - please wait - preparing to power +off\n"); + h8_set_event_mask(H8_POWER_BUTTON); + wake_up(&h8_monitor_wait); + } + + /* + * Thermal related items + */ + if (intrbuf.word & H8_THERMAL_THRESHOLD) { + if(h8_debug & 0x4) + printk("h8_read_event_status: THERMAL_THRESHOLD\n"); + h8_set_event_mask(H8_MANAGE_UTHERM); + wake_up(&h8_monitor_wait); + } + + /* + * nops -for now + */ + if (intrbuf.word & H8_DOCKING_STATION_STATUS) { + if(h8_debug & 0x4) + printk("h8_read_event_status: DOCKING_STATION_STATUS\n"); + /* read_ext_status */ + } + if (intrbuf.word & H8_EXT_BATT_STATUS) { + if(h8_debug & 0x4) + printk("h8_read_event_status: EXT_BATT_STATUS\n"); + + } + if (intrbuf.word & H8_EXT_BATT_CHARGE_STATE) { + if(h8_debug & 0x4) + printk("h8_read_event_status: EXT_BATT_CHARGE_STATE\n"); + + } + if (intrbuf.word & H8_BATT_CHANGE_OVER) { + if(h8_debug & 0x4) + printk("h8_read_event_status: BATT_CHANGE_OVER\n"); + + } + if (intrbuf.word & H8_WATCHDOG) { + if(h8_debug & 0x4) + printk("h8_read_event_status: WATCHDOG\n"); + /* nop */ + } + if (intrbuf.word & H8_SHUTDOWN) { + if(h8_debug & 0x4) + printk("h8_read_event_status: SHUTDOWN\n"); + /* nop */ + } + if (intrbuf.word & H8_KEYBOARD) { + if(h8_debug & 0x4) + printk("h8_read_event_status: KEYBOARD\n"); + /* nop */ + } + if (intrbuf.word & H8_EXT_MOUSE_OR_CASE_SWITCH) { + if(h8_debug & 0x4) + printk("h8_read_event_status: EXT_MOUSE_OR_CASE_SWITCH\n"); + /* read_ext_status*/ + } + if (intrbuf.word & H8_INT_BATT_LOW) { + if(h8_debug & 0x4) + printk("h8_read_event_status: INT_BATT_LOW\n"); + /* post event, warn user */ + } + if (intrbuf.word & H8_INT_BATT_CHARGE_STATE) { + if(h8_debug & 0x4) + printk("h8_read_event_status: INT_BATT_CHARGE_STATE\n"); + /* nop - happens often */ + } + if (intrbuf.word & H8_INT_BATT_STATUS) { + if(h8_debug & 0x4) + printk("h8_read_event_status: INT_BATT_STATUS\n"); + + } + if (intrbuf.word & H8_INT_BATT_CHARGE_THRESHOLD) { + if(h8_debug & 0x4) + printk("h8_read_event_status: INT_BATT_CHARGE_THRESHOLD\n"); + /* nop - happens often */ + } + if (intrbuf.word & H8_EXT_BATT_LOW) { + if(h8_debug & 0x4) + printk("h8_read_event_status: EXT_BATT_LOW\n"); + /*if no internal, post event, warn user */ + /* else nop */ + } + + return; +} + +/* + * Function called when H8 has performed requested command. + */ +void +h8_cmd_done(h8_cmd_q_t *qp) +{ + + /* what to do */ + switch (qp->cmdbuf[0]) { + case H8_SYNC: + if (h8_debug & 0x40000) + printk("H8: Sync command done - byte returned was 0x%x\n", + qp->rcvbuf[0]); + QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *); + break; + + case H8_RD_SN: + case H8_RD_ENET_ADDR: + printk("H8: Read ethernet addr - command done - address: %x - %x - %x - %x - %x - %x \n", + qp->rcvbuf[0], qp->rcvbuf[1], qp->rcvbuf[2], + qp->rcvbuf[3], qp->rcvbuf[4], qp->rcvbuf[5]); + QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *); + break; + + case H8_RD_HW_VER: + case H8_RD_MIC_VER: + case H8_RD_MAX_TEMP: + printk("H8: Max recorded CPU temp %d, Sys temp %d\n", + qp->rcvbuf[0], qp->rcvbuf[1]); + QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *); + break; + + case H8_RD_MIN_TEMP: + printk("H8: Min recorded CPU temp %d, Sys temp %d\n", + qp->rcvbuf[0], qp->rcvbuf[1]); + QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *); + break; + + case H8_RD_CURR_TEMP: + h8_sync_channel |= H8_RD_CURR_TEMP; + xx.byte[0] = qp->rcvbuf[0]; + xx.byte[1] = qp->rcvbuf[1]; + wake_up(&h8_sync_wait); + QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *); + break; + + case H8_RD_SYS_VARIENT: + case H8_RD_PWR_ON_CYCLES: + printk(" H8: RD_PWR_ON_CYCLES command done\n"); + break; + + case H8_RD_PWR_ON_SECS: + printk("H8: RD_PWR_ON_SECS command done\n"); + break; + + case H8_RD_RESET_STATUS: + case H8_RD_PWR_DN_STATUS: + case H8_RD_EVENT_STATUS: + case H8_RD_ROM_CKSM: + case H8_RD_EXT_STATUS: + xx.byte[1] = qp->rcvbuf[0]; + xx.byte[0] = qp->rcvbuf[1]; + h8_sync_channel |= H8_GET_EXT_STATUS; + wake_up(&h8_sync_wait); + QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *); + break; + + case H8_RD_USER_CFG: + case H8_RD_INT_BATT_VOLT: + case H8_RD_DC_INPUT_VOLT: + case H8_RD_HORIZ_PTR_VOLT: + case H8_RD_VERT_PTR_VOLT: + case H8_RD_EEPROM_STATUS: + case H8_RD_ERR_STATUS: + case H8_RD_NEW_BUSY_SPEED: + case H8_RD_CONFIG_INTERFACE: + case H8_RD_INT_BATT_STATUS: + printk("H8: Read int batt status cmd done - returned was %x %x %x\n", + qp->rcvbuf[0], qp->rcvbuf[1], qp->rcvbuf[2]); + QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *); + break; + + case H8_RD_EXT_BATT_STATUS: + case H8_RD_PWR_UP_STATUS: + case H8_RD_EVENT_STATUS_MASK: + case H8_CTL_EMU_BITPORT: + case H8_DEVICE_CONTROL: + if(h8_debug & 0x20000) { + printk("H8: Device control cmd done - byte returned was 0x%x\n", + qp->rcvbuf[0]); + } + QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *); + break; + + case H8_CTL_TFT_BRT_DC: + case H8_CTL_WATCHDOG: + case H8_CTL_MIC_PROT: + case H8_CTL_INT_BATT_CHG: + case H8_CTL_EXT_BATT_CHG: + case H8_CTL_MARK_SPACE: + case H8_CTL_MOUSE_SENSITIVITY: + case H8_CTL_DIAG_MODE: + case H8_CTL_IDLE_AND_BUSY_SPDS: + printk("H8: Idle and busy speed command done\n"); + break; + + case H8_CTL_TFT_BRT_BATT: + case H8_CTL_UPPER_TEMP: + if(h8_debug & 0x10) { + XDprintk("H8: ctl upper thermal thresh cmd done - returned was %d\n", + qp->rcvbuf[0]); + } + QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *); + break; + + case H8_CTL_LOWER_TEMP: + case H8_CTL_TEMP_CUTOUT: + case H8_CTL_WAKEUP: + case H8_CTL_CHG_THRESHOLD: + case H8_CTL_TURBO_MODE: + case H8_SET_DIAG_STATUS: + case H8_SOFTWARE_RESET: + case H8_RECAL_PTR: + case H8_SET_INT_BATT_PERCENT: + case H8_WRT_CFG_INTERFACE_REG: + case H8_WRT_EVENT_STATUS_MASK: + case H8_ENTER_POST_MODE: + case H8_EXIT_POST_MODE: + case H8_RD_EEPROM: + case H8_WRT_EEPROM: + case H8_WRT_TO_STATUS_DISP: + printk("H8: Write IO status display command done\n"); + break; + + case H8_DEFINE_SPC_CHAR: + case H8_DEFINE_TABLE_STRING_ENTRY: + case H8_PERFORM_EMU_CMD: + case H8_EMU_RD_REG: + case H8_EMU_WRT_REG: + case H8_EMU_RD_RAM: + case H8_EMU_WRT_RAM: + case H8_BQ_RD_REG: + case H8_BQ_WRT_REG: + case H8_PWR_OFF: + printk ("H8: misc command completed\n"); + break; + } + return; +} + +/* + * Retrieve the current cpu temperature and case temperature. Provides + * the feedback for the thermal control algorithm. Synchcronized via + * sleep() for priority so that no other actions in the process will take + * place before the data becomes available. + */ +int +h8_get_curr_temp(u_char curr_temp[]) +{ + u_char buf[H8_MAX_CMD_SIZE]; + unsigned long flags; + + memset(buf, 0, H8_MAX_CMD_SIZE); + buf[0] = H8_RD_CURR_TEMP; + + h8_q_cmd(buf, 1, 2); + + save_flags(flags); cli(); + + while((h8_sync_channel & H8_RD_CURR_TEMP) == 0) + sleep_on(&h8_sync_wait); + + restore_flags(flags); + + h8_sync_channel &= ~H8_RD_CURR_TEMP; + curr_temp[0] = xx.byte[0]; + curr_temp[1] = xx.byte[1]; + xx.word = 0; + + if(h8_debug & 0x8) + printk("H8: curr CPU temp %d, Sys temp %d\n", + curr_temp[0], curr_temp[1]); + return 0; +} + +static void +h8_get_max_temp(void) +{ + u_char buf[H8_MAX_CMD_SIZE]; + + buf[0] = H8_RD_MAX_TEMP; + h8_q_cmd(buf, 1, 2); +} + +/* + * Assigns an upper limit to the value of the H8 thermal interrupt. + * As an example setting a value of 115 F here will cause the + * interrupt to trigger when the cpu temperature reaches 115 F. + */ +static void +h8_set_upper_therm_thold(int thold) +{ + u_char buf[H8_MAX_CMD_SIZE]; + + /* write 0 to reinitialize interrupt */ + buf[0] = H8_CTL_UPPER_TEMP; + buf[1] = 0x0; + buf[2] = 0x0; + h8_q_cmd(buf, 3, 1); + + /* Do it for real */ + buf[0] = H8_CTL_UPPER_TEMP; + buf[1] = 0x0; + buf[2] = thold; + h8_q_cmd(buf, 3, 1); +} + +static void +h8_get_upper_therm_thold(void) +{ + u_char buf[H8_MAX_CMD_SIZE]; + + buf[0] = H8_CTL_UPPER_TEMP; + buf[1] = 0xff; + buf[2] = 0; + h8_q_cmd(buf, 3, 1); +} + +/* + * The external status word contains information on keyboard controller, + * power button, changes in external batt status, change in DC state, + * docking station, etc. General purpose querying use. + */ +int +h8_get_ext_status(u_char stat_word[]) +{ + u_char buf[H8_MAX_CMD_SIZE]; + unsigned long flags; + + memset(buf, 0, H8_MAX_CMD_SIZE); + buf[0] = H8_RD_EXT_STATUS; + + h8_q_cmd(buf, 1, 2); + + save_flags(flags); cli(); + + while((h8_sync_channel & H8_GET_EXT_STATUS) == 0) + sleep_on(&h8_sync_wait); + + restore_flags(flags); + + h8_sync_channel &= ~H8_GET_EXT_STATUS; + stat_word[0] = xx.byte[0]; + stat_word[1] = xx.byte[1]; + xx.word = 0; + + if(h8_debug & 0x8) + printk("H8: curr ext status %x, %x\n", + stat_word[0], stat_word[1]); + + return 0; +} + +/* + * Thread attached to task 0 manages thermal/physcial state of Alphabook. + * When a condition is detected by the interrupt service routine, the + * isr does a wakeup() on h8_monitor_wait. The mask value is then + * screened for the appropriate action. + */ + +int +h8_monitor_thread(void * unused) +{ + u_char curr_temp[2]; + + /* + * Need a logic based safety valve here. During boot when this thread is + * started and the thermal interrupt is not yet initialized this logic + * checks the temperature and acts accordingly. When this path is acted + * upon system boot is painfully slow, however, the priority associated + * with overheating is high enough to warrant this action. + */ + h8_get_curr_temp(curr_temp); + + printk("H8: Initial CPU temp: %d\n", curr_temp[0]); + + if(curr_temp[0] >= h8_uthermal_threshold) { + h8_set_event_mask(H8_MANAGE_UTHERM); + h8_manage_therm(); + } else { + /* + * Arm the upper thermal limit of the H8 so that any temp in + * excess will trigger the thermal control mechanism. + */ + h8_set_upper_therm_thold(h8_uthermal_threshold); + } + + for(;;) { + sleep_on(&h8_monitor_wait); + + if(h8_debug & 0x2) + printk("h8_monitor_thread awakened, mask:%x\n", + h8_event_mask); + + if (h8_event_mask & (H8_MANAGE_UTHERM|H8_MANAGE_LTHERM)) { + h8_manage_therm(); + } + +#if 0 + if (h8_event_mask & H8_POWER_BUTTON) { + h8_system_down(); + } + + /* + * If an external DC supply is removed or added make + * appropriate cpu speed adjustments. + */ + if (h8_event_mask & H8_MANAGE_BATTERY) { + h8_run_level_3_manage(H8_RUN); + h8_clear_event_mask(H8_MANAGE_BATTERY); + } +#endif + } +} + +/* + * Function implements the following policy. When the machine is booted + * the system is set to run at full clock speed. When the upper thermal + * threshold is reached as a result of full clock a damping factor is + * applied to cool off the cpu. The default value is one quarter clock + * (57 Mhz). When as a result of this cooling a temperature lower by + * hmc_uthermal_window is reached, the machine is reset to a higher + * speed, one half clock (115 Mhz). One half clock is maintained until + * the upper thermal threshold is again reached restarting the cycle. + */ + +int +h8_manage_therm(void) +{ + u_char curr_temp[2]; + + if(h8_event_mask & H8_MANAGE_UTHERM) { + /* Upper thermal interrupt received, need to cool down. */ + if(h8_debug & 0x10) + printk("H8: Thermal threshold %d F reached\n", + h8_uthermal_threshold); + h8_set_cpu_speed(h8_udamp); + h8_clear_event_mask(H8_MANAGE_UTHERM); + h8_set_event_mask(H8_MANAGE_LTHERM); + /* Check again in 30 seconds for cpu temperature */ + h8_start_monitor_timer(H8_TIMEOUT_INTERVAL); + } else if (h8_event_mask & H8_MANAGE_LTHERM) { + /* See how cool the system has become as a result + of the reduction in speed. */ + h8_get_curr_temp(curr_temp); + last_temp = curr_temp[0]; + if (curr_temp[0] < (h8_uthermal_threshold - h8_uthermal_window)) + { + /* System cooling has progressed to a point + that the cpu may be speeded up. */ + h8_set_upper_therm_thold(h8_uthermal_threshold); + h8_set_cpu_speed(h8_ldamp); /* adjustable */ + if(h8_debug & 0x10) + printk("H8: CPU cool, applying cpu_divisor: %d \n", + h8_ldamp); + h8_clear_event_mask(H8_MANAGE_LTHERM); + } + else /* Not cool enough yet, check again in 30 seconds. */ + h8_start_monitor_timer(H8_TIMEOUT_INTERVAL); + } else { + + } + return 0; +} + +/* + * Function conditions the value of global_rpb_counter before + * calling the primitive which causes the actual speed change. + */ +void +h8_set_cpu_speed(int speed_divisor) +{ + +#ifdef NOT_YET +/* + * global_rpb_counter is consumed by alpha_delay() in determining just + * how much time to delay. It is necessary that the number of microseconds + * in DELAY(n) be kept consistent over a variety of cpu clock speeds. + * To that end global_rpb_counter is here adjusted. + */ + + switch (speed_divisor) { + case 0: + global_rpb_counter = rpb->rpb_counter * 2L; + break; + case 1: + global_rpb_counter = rpb->rpb_counter * 4L / 3L ; + break; + case 3: + global_rpb_counter = rpb->rpb_counter / 2L; + break; + case 4: + global_rpb_counter = rpb->rpb_counter / 4L; + break; + case 5: + global_rpb_counter = rpb->rpb_counter / 8L; + break; + /* + * This case most commonly needed for cpu_speed_divisor + * of 2 which is the value assigned by the firmware. + */ + default: + global_rpb_counter = rpb->rpb_counter; + break; + } +#endif /* NOT_YET */ + + if(h8_debug & 0x8) + printk("H8: Setting CPU speed to %d MHz\n", + speed_tab[speed_divisor]); + + /* Make the actual speed change */ + lca_clock_fiddle(speed_divisor); +} + +/* + * Gets value stored in rpb representing cpu clock speed and adjusts this + * value based on the current clock speed divisor. + */ +u_long +h8_get_cpu_speed(void) +{ + u_long speed = 0; + u_long counter; + +#ifdef NOT_YET + counter = rpb->rpb_counter / 1000000L; + + switch (alphabook_get_clock()) { + case 0: + speed = counter * 2L; + break; + case 1: + speed = counter * 4L / 3L ; + break; + case 2: + speed = counter; + break; + case 3: + speed = counter / 2L; + break; + case 4: + speed = counter / 4L; + break; + case 5: + speed = counter / 8L; + break; + default: + break; + } + if(h8_debug & 0x8) + printk("H8: CPU speed current setting: %d MHz\n", speed); +#endif /* NOT_YET */ + return speed; +} + +static void +h8_activate_monitor(unsigned long unused) +{ + unsigned long flags; + + save_flags(flags); cli(); + h8_monitor_timer_active = 0; + restore_flags(flags); + + wake_up(&h8_monitor_wait); +} + +static void +h8_start_monitor_timer(unsigned long secs) +{ + unsigned long flags; + + if (h8_monitor_timer_active) + return; + + save_flags(flags); cli(); + h8_monitor_timer_active = 1; + restore_flags(flags); + + init_timer(&h8_monitor_timer); + h8_monitor_timer.function = h8_activate_monitor; + h8_monitor_timer.expires = secs * HZ + jiffies; + add_timer(&h8_monitor_timer); +} + +static void h8_set_event_mask(int mask) +{ + unsigned long flags; + + save_flags(flags); cli(); + h8_event_mask |= mask; + restore_flags(flags); +} + +static void h8_clear_event_mask(int mask) +{ + unsigned long flags; + + save_flags(flags); cli(); + h8_event_mask &= (~mask); + restore_flags(flags); +} diff -u --recursive --new-file v2.1.53/linux/drivers/char/h8.h linux/drivers/char/h8.h --- v2.1.53/linux/drivers/char/h8.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/h8.h Sat Sep 6 10:16:07 1997 @@ -0,0 +1,250 @@ +/* + */ + +#ifndef __H8_H__ +#define __H8_H__ + +/* + * Register address and offsets + */ +#define H8_BASE_ADDR 0x170 /* default */ +#define H8_IRQ 9 /* default */ +#define H8_STATUS_REG_OFF 0x4 +#define H8_CMD_REG_OFF 0x4 +#define H8_DATA_REG_OFF 0x0 + + +/* H8 register bit definitions */ +/* status register */ +#define H8_OFULL 0x1 /* output data register full */ +#define H8_IFULL 0x2 /* input data register full */ +#define H8_CMD 0x8 /* command / not data */ + +#define H8_INTR 0xfa +#define H8_NACK 0xfc +#define H8_BYTE_LEVEL_ACK 0xfd +#define H8_CMD_ACK 0xfe +#define H8_SYNC_BYTE 0x99 + +/* + * H8 command definitions + */ +/* System info commands */ +#define H8_SYNC 0x0 +#define H8_RD_SN 0x1 +#define H8_RD_ENET_ADDR 0x2 +#define H8_RD_HW_VER 0x3 +#define H8_RD_MIC_VER 0x4 +#define H8_RD_MAX_TEMP 0x5 +#define H8_RD_MIN_TEMP 0x6 +#define H8_RD_CURR_TEMP 0x7 +#define H8_RD_SYS_VARIENT 0x8 +#define H8_RD_PWR_ON_CYCLES 0x9 +#define H8_RD_PWR_ON_SECS 0xa +#define H8_RD_RESET_STATUS 0xb +#define H8_RD_PWR_DN_STATUS 0xc +#define H8_RD_EVENT_STATUS 0xd +#define H8_RD_ROM_CKSM 0xe +#define H8_RD_EXT_STATUS 0xf +#define H8_RD_USER_CFG 0x10 +#define H8_RD_INT_BATT_VOLT 0x11 +#define H8_RD_DC_INPUT_VOLT 0x12 +#define H8_RD_HORIZ_PTR_VOLT 0x13 +#define H8_RD_VERT_PTR_VOLT 0x14 +#define H8_RD_EEPROM_STATUS 0x15 +#define H8_RD_ERR_STATUS 0x16 +#define H8_RD_NEW_BUSY_SPEED 0x17 +#define H8_RD_CONFIG_INTERFACE 0x18 +#define H8_RD_INT_BATT_STATUS 0x19 +#define H8_RD_EXT_BATT_STATUS 0x1a +#define H8_RD_PWR_UP_STATUS 0x1b +#define H8_RD_EVENT_STATUS_MASK 0x56 + +/* Read/write/modify commands */ +#define H8_CTL_EMU_BITPORT 0x32 +#define H8_DEVICE_CONTROL 0x21 +#define H8_CTL_TFT_BRT_DC 0x22 +#define H8_CTL_WATCHDOG 0x23 +#define H8_CTL_MIC_PROT 0x24 +#define H8_CTL_INT_BATT_CHG 0x25 +#define H8_CTL_EXT_BATT_CHG 0x26 +#define H8_CTL_MARK_SPACE 0x27 +#define H8_CTL_MOUSE_SENSITIVITY 0x28 +#define H8_CTL_DIAG_MODE 0x29 +#define H8_CTL_IDLE_AND_BUSY_SPDS 0x2a +#define H8_CTL_TFT_BRT_BATT 0x2b +#define H8_CTL_UPPER_TEMP 0x2c +#define H8_CTL_LOWER_TEMP 0x2d +#define H8_CTL_TEMP_CUTOUT 0x2e +#define H8_CTL_WAKEUP 0x2f +#define H8_CTL_CHG_THRESHOLD 0x30 +#define H8_CTL_TURBO_MODE 0x31 +#define H8_SET_DIAG_STATUS 0x40 +#define H8_SOFTWARE_RESET 0x41 +#define H8_RECAL_PTR 0x42 +#define H8_SET_INT_BATT_PERCENT 0x43 +#define H8_WRT_CFG_INTERFACE_REG 0x45 +#define H8_WRT_EVENT_STATUS_MASK 0x57 +#define H8_ENTER_POST_MODE 0x46 +#define H8_EXIT_POST_MODE 0x47 + +/* Block transfer commands */ +#define H8_RD_EEPROM 0x50 +#define H8_WRT_EEPROM 0x51 +#define H8_WRT_TO_STATUS_DISP 0x52 +#define H8_DEFINE_SPC_CHAR 0x53 + +/* Generic commands */ +#define H8_DEFINE_TABLE_STRING_ENTRY 0x60 + +/* Battery control commands */ +#define H8_PERFORM_EMU_CMD 0x70 +#define H8_EMU_RD_REG 0x71 +#define H8_EMU_WRT_REG 0x72 +#define H8_EMU_RD_RAM 0x73 +#define H8_EMU_WRT_RAM 0x74 +#define H8_BQ_RD_REG 0x75 +#define H8_BQ_WRT_REG 0x76 + +/* System admin commands */ +#define H8_PWR_OFF 0x80 + +/* + * H8 command related definitions + */ + +/* device control argument bits */ +#define H8_ENAB_EXTSMI 0x1 +#define H8_DISAB_IRQ 0x2 +#define H8_ENAB_FLASH_WRT 0x4 +#define H8_ENAB_THERM 0x8 +#define H8_ENAB_INT_PTR 0x10 +#define H8_ENAB_LOW_SPD_IND 0x20 +#define H8_ENAB_EXT_PTR 0x40 +#define H8_DISAB_PWR_OFF_SW 0x80 +#define H8_POWER_OFF 0x80 + +/* H8 read event status bits */ +#define H8_DC_CHANGE 0x1 +#define H8_INT_BATT_LOW 0x2 +#define H8_INT_BATT_CHARGE_THRESHOLD 0x4 +#define H8_INT_BATT_CHARGE_STATE 0x8 +#define H8_INT_BATT_STATUS 0x10 +#define H8_EXT_BATT_CHARGE_STATE 0x20 +#define H8_EXT_BATT_LOW 0x40 +#define H8_EXT_BATT_STATUS 0x80 +#define H8_THERMAL_THRESHOLD 0x100 +#define H8_WATCHDOG 0x200 +#define H8_DOCKING_STATION_STATUS 0x400 +#define H8_EXT_MOUSE_OR_CASE_SWITCH 0x800 +#define H8_KEYBOARD 0x1000 +#define H8_BATT_CHANGE_OVER 0x2000 +#define H8_POWER_BUTTON 0x4000 +#define H8_SHUTDOWN 0x8000 + +/* H8 control idle and busy speeds */ +#define H8_SPEED_LOW 0x1 +#define H8_SPEED_MED 0x2 +#define H8_SPEED_HI 0x3 +#define H8_SPEED_LOCKED 0x80 + +#define H8_MAX_CMD_SIZE 18 +#define H8_Q_ALLOC_AMOUNT 10 + +/* H8 state field values */ +#define H8_IDLE 1 +#define H8_XMIT 2 +#define H8_RCV 3 +#define H8_RESYNC 4 +#define H8_INTR_MODE 5 + +/* Mask values for control functions */ +#define UTH_HYSTERESIS 5 +#define DEFAULT_UTHERMAL_THRESHOLD 115 +#define H8_TIMEOUT_INTERVAL 30 +#define H8_RUN 4 + +#define H8_GET_MAX_TEMP 0x1 +#define H8_GET_CURR_TEMP 0x2 +#define H8_GET_UPPR_THRMAL_THOLD 0x4 +#define H8_GET_ETHERNET_ADDR 0x8 +#define H8_SYNC_OP 0x10 +#define H8_SET_UPPR_THRMAL_THOLD 0x20 +#define H8_GET_INT_BATT_STAT 0x40 +#define H8_GET_CPU_SPD 0x80 +#define H8_MANAGE_UTHERM 0x100 +#define H8_MANAGE_LTHERM 0x200 +#define H8_HALT 0x400 +#define H8_CRASH 0x800 +#define H8_GET_EXT_STATUS 0x10000 +#define H8_MANAGE_QUIET 0x20000 +#define H8_MANAGE_SPEEDUP 0x40000 +#define H8_MANAGE_BATTERY 0x80000 +#define H8_SYSTEM_DELAY_TEST 0x100000 +#define H8_POWER_SWITCH_TEST 0x200000 + +/* cpu speeds and clock divisor values */ +#define MHZ_14 5 +#define MHZ_28 4 +#define MHZ_57 3 +#define MHZ_115 2 +#define MHZ_230 0 + +/* + * H8 data + */ +struct h8_data { + u_int ser_num; + u_char ether_add[6]; + u_short hw_ver; + u_short mic_ver; + u_short max_tmp; + u_short min_tmp; + u_short cur_tmp; + u_int sys_var; + u_int pow_on; + u_int pow_on_secs; + u_char reset_status; + u_char pwr_dn_status; + u_short event_status; + u_short rom_cksm; + u_short ext_status; + u_short u_cfg; + u_char ibatt_volt; + u_char dc_volt; + u_char ptr_horiz; + u_char ptr_vert; + u_char eeprom_status; + u_char error_status; + u_char new_busy_speed; + u_char cfg_interface; + u_short int_batt_status; + u_short ext_batt_status; + u_char pow_up_status; + u_char event_status_mask; +}; + + +/* + * H8 command buffers + */ +typedef struct h8_cmd_q { + DLNODE(struct h8_cmd_q) link; /* double linked list */ + int ncmd; /* number of bytes in command */ + int nrsp; /* number of bytes in response */ + int cnt; /* number of bytes sent/received */ + int nacks; /* number of byte level acks */ + u_char cmdbuf[H8_MAX_CMD_SIZE]; /* buffer to store command */ + u_char rcvbuf[H8_MAX_CMD_SIZE]; /* buffer to store response */ +} h8_cmd_q_t; + +typedef struct __queue_head { + DLNODE(struct h8_cmd_q) link; +} queue_head_t; + +union intr_buf { + u_char byte[2]; + u_int word; +}; + +#endif /* __H8_H_ */ diff -u --recursive --new-file v2.1.53/linux/drivers/char/mem.c linux/drivers/char/mem.c --- v2.1.53/linux/drivers/char/mem.c Wed Sep 3 20:52:42 1997 +++ linux/drivers/char/mem.c Sat Sep 6 10:27:18 1997 @@ -339,13 +339,6 @@ return 0; } -static long read_full(struct inode * node, struct file * file, - char * buf, unsigned long count) -{ - file->f_pos += count; - return count; -} - static long write_full(struct inode * inode, struct file * file, const char * buf, unsigned long count) { @@ -390,7 +383,9 @@ #define mmap_kmem mmap_mem #define zero_lseek null_lseek +#define full_lseek null_lseek #define write_zero write_null +#define read_full read_zero static struct file_operations mem_fops = { memory_lseek, @@ -457,7 +452,7 @@ }; static struct file_operations full_fops = { - memory_lseek, + full_lseek, read_full, write_full, NULL, /* full_readdir */ diff -u --recursive --new-file v2.1.53/linux/drivers/char/misc.c linux/drivers/char/misc.c --- v2.1.53/linux/drivers/char/misc.c Mon Aug 11 14:47:04 1997 +++ linux/drivers/char/misc.c Sat Sep 6 10:16:07 1997 @@ -71,10 +71,12 @@ extern int sun_mouse_init(void); extern void watchdog_init(void); extern void wdt_init(void); +extern void acq_init(void); extern void pcwatchdog_init(void); extern int rtc_init(void); extern int dsp56k_init(void); extern int nvram_init(void); +extern void hfmodem_init(void); #ifdef CONFIG_PROC_FS static int misc_read_proc(char *buf, char **start, off_t offset, @@ -231,17 +233,26 @@ #ifdef CONFIG_WDT wdt_init(); #endif +#ifdef CONFIG_ACQUIRE_WDT + acq_init(); +#endif #ifdef CONFIG_SOFT_WATCHDOG watchdog_init(); #endif #ifdef CONFIG_APM apm_bios_init(); #endif +#ifdef CONFIG_H8 + h8_init(); +#endif #ifdef CONFIG_RTC rtc_init(); #endif #ifdef CONFIG_ATARI_DSP56K dsp56k_init(); +#endif +#ifdef CONFIG_HFMODEM + hfmodem_init(); #endif #ifdef CONFIG_NVRAM nvram_init(); diff -u --recursive --new-file v2.1.53/linux/drivers/misc/parport_share.c linux/drivers/misc/parport_share.c --- v2.1.53/linux/drivers/misc/parport_share.c Wed Sep 3 20:52:42 1997 +++ linux/drivers/misc/parport_share.c Fri Sep 5 20:42:57 1997 @@ -18,6 +18,8 @@ #include #include +#include + #ifdef CONFIG_KERNELD #include #endif diff -u --recursive --new-file v2.1.53/linux/drivers/net/arc-rimi.c linux/drivers/net/arc-rimi.c --- v2.1.53/linux/drivers/net/arc-rimi.c Thu Sep 4 17:07:30 1997 +++ linux/drivers/net/arc-rimi.c Sat Sep 6 10:05:42 1997 @@ -1,4 +1,5 @@ -/* arc-rimi.c: +/* $Id: arc-rimi.c,v 1.2 1997/09/05 08:57:51 mj Exp $ + Derived from the original arcnet.c, Written 1994-1996 by Avery Pennarun, which was in turn derived from skeleton.c by Donald Becker. @@ -75,41 +76,11 @@ #undef SLOW_XMIT_COPY - - -/* External functions from arcnet.c */ - - - -#if ARCNET_DEBUG_MAX & D_SKB -extern void arcnet_dump_skb(struct device *dev,struct sk_buff *skb, - char *desc); -#else -#define arcnet_dump_skb(dev,skb,desc) ; -#endif - -#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX) -extern void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext, - char *desc); -#else -#define arcnet_dump_packet(dev,buffer,ext,desc) ; -#endif - -extern void arcnet_tx_done(struct device *dev, struct arcnet_local *lp); -extern void arcnet_makename(char *device); -extern void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs); -extern void arcnet_setup(struct device *dev); -extern int arcnet_go_tx(struct device *dev,int enable_irq); -extern void arcnetA_continue_tx(struct device *dev); -extern void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr); -extern void arcnet_use_count(int open); - - - /* Internal function declarations */ + static int arcrimi_probe(struct device *dev); static void arcrimi_rx(struct device *dev,int recbuf); -static int arcrimi_found(struct device *dev,int ioaddr,int airq,u_long shmem); +static int arcrimi_found(struct device *dev,int ioaddr,int airq,u_long shmem); static void arcrimi_inthandler (struct device *dev); static int arcrimi_reset (struct device *dev, int reset_delay); static void arcrimi_setmask (struct device *dev, u_char mask); @@ -122,7 +93,6 @@ /* Module parameters */ - #ifdef MODULE static int shmem=0x0; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */ static int irq=0; /* or use the insmod io= irq= shmem= options */ @@ -142,7 +112,6 @@ /* Handy defines for ARCnet specific stuff */ - /* COM 9026 controller chip --> ARCnet register addresses */ #define _INTMASK (ioaddr+0) /* writable */ #define _STATUS (ioaddr+0) /* readable */ @@ -155,20 +124,14 @@ #define RDDATAflag 0x00 /* Next access is a read/~write */ - - - #define ARCSTATUS readb(_STATUS) #define ACOMMAND(cmd) writeb((cmd),_COMMAND) #define ARCRESET writeb(TESTvalue,ioaddr-0x800) /* fake reset */ #define AINTMASK(msk) writeb((msk),_INTMASK) #define SETCONF writeb(lp->config,_CONFIG) - static const char *version = -"arc-rimi.c: v2.91 97/08/19 Avery Pennarun et al.\n"; - - +"arc-rimi.c: v2.92 97/09/02 Avery Pennarun et al.\n"; /**************************************************************************** * * @@ -186,26 +149,25 @@ BUGLVL(D_NORMAL) printk(version); BUGMSG(D_NORMAL,"Given: node %02Xh, shmem %lXh, irq %d\n", dev->dev_addr[0],dev->mem_start,dev->irq); - + if (dev->mem_start<=0 || dev->irq<=0) { BUGMSG(D_NORMAL,"No autoprobe for RIM I; you " "must specify the shmem and irq!\n"); return -ENODEV; } - + if (dev->dev_addr[0]==0) { BUGMSG(D_NORMAL,"You need to specify your card's station " "ID!\n"); return -ENODEV; } - + return arcrimi_found(dev,dev->dev_addr[0],dev->irq,dev->mem_start); } - /* Set up the struct device associated with this card. Called after * probing succeeds. */ @@ -214,7 +176,7 @@ struct arcnet_local *lp; u_long first_mirror,last_mirror; int mirror_size; - + /* reserve the irq */ if (request_irq(airq,&arcnet_interrupt,0,"arcnet (RIM I)",NULL)) { @@ -223,15 +185,15 @@ } irq2dev_map[airq]=dev; dev->irq=airq; - + dev->base_addr=0; writeb(TESTvalue,shmem); writeb(node,shmem+1); /* actually the node ID */ - + /* find the real shared memory start/end points, including mirrors */ #define BUFFER_SIZE (512) #define MIRROR_SIZE (BUFFER_SIZE*4) - + /* guess the actual size of one "memory mirror" - the number of * bytes between copies of the shared memory. On most cards, it's * 2k (or there are no mirrors at all) but on some, it's 4k. @@ -241,21 +203,21 @@ && readb(shmem-mirror_size)!=TESTvalue && readb(shmem-2*mirror_size)==TESTvalue) mirror_size*=2; - + first_mirror=last_mirror=shmem; while (readb(first_mirror)==TESTvalue) first_mirror-=mirror_size; first_mirror+=mirror_size; - + while (readb(last_mirror)==TESTvalue) last_mirror+=mirror_size; last_mirror-=mirror_size; - + dev->mem_start=first_mirror; dev->mem_end=last_mirror+MIRROR_SIZE-1; dev->rmem_start=dev->mem_start+BUFFER_SIZE*0; dev->rmem_end=dev->mem_start+BUFFER_SIZE*2-1; - + /* Initialize the rest of the device structure. */ - + dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL); if (dev->priv == NULL) { @@ -274,26 +236,26 @@ lp->openclose_device=arcrimi_openclose; lp->prepare_tx=arcrimi_prepare_tx; lp->inthandler=arcrimi_inthandler; - + /* Fill in the fields of the device structure with generic * values. */ arcnet_setup(dev); - + /* And now fill particular fields with arcnet values */ dev->mtu=1500; /* completely arbitrary - agrees with ether, though */ dev->hard_header_len=sizeof(struct ClientData); lp->sequence=1; lp->recbuf=0; - + BUGMSG(D_DURING,"ClientData header size is %d.\n", sizeof(struct ClientData)); BUGMSG(D_DURING,"HardHeader size is %d.\n", sizeof(struct archdr)); - + /* get and check the station ID from offset 1 in shmem */ lp->stationid = readb(first_mirror+1); - + if (lp->stationid==0) BUGMSG(D_NORMAL,"WARNING! Station address 00 is reserved " "for broadcasts!\n"); @@ -301,13 +263,13 @@ BUGMSG(D_NORMAL,"WARNING! Station address FF may confuse " "DOS networking programs!\n"); dev->dev_addr[0]=lp->stationid; - + BUGMSG(D_NORMAL,"ARCnet RIM I: station %02Xh found at IRQ %d, " "ShMem %lXh (%ld*%d bytes).\n", lp->stationid, dev->irq, dev->mem_start, (dev->mem_end-dev->mem_start+1)/mirror_size,mirror_size); - + return 0; } @@ -324,46 +286,46 @@ struct arcnet_local *lp=(struct arcnet_local *)dev->priv; short ioaddr=dev->mem_start + 0x800; int recbuf=lp->recbuf; - + if (reset_delay==3) { ARCRESET; return 0; } - + /* no IRQ's, please! */ lp->intmask=0; SETMASK; - + BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n", dev->name,ARCSTATUS); - + ACOMMAND(CFLAGScmd|RESETclear); /* clear flags & end reset */ ACOMMAND(CFLAGScmd|CONFIGclear); - + /* clear out status variables */ recbuf=lp->recbuf=0; lp->txbuf=2; - + /* enable extended (512-byte) packets */ ACOMMAND(CONFIGcmd|EXTconf); - + #ifndef SLOW_XMIT_COPY /* clean out all the memory to make debugging make more sense :) */ BUGLVL(D_DURING) memset_io(dev->mem_start,0x42,2048); #endif - + /* and enable receive of our first packet to the first buffer */ EnableReceiver(); - + /* re-enable interrupts */ lp->intmask|=NORXflag; #ifdef DETECT_RECONFIGS lp->intmask|=RECONflag; #endif SETMASK; - + /* done! return success. */ return 0; } @@ -380,28 +342,25 @@ static void arcrimi_setmask(struct device *dev, u_char mask) { int ioaddr=dev->mem_start+0x800; - + AINTMASK(mask); } static u_char arcrimi_status(struct device *dev) { int ioaddr=dev->mem_start+0x800; - + return ARCSTATUS; } static void arcrimi_command(struct device *dev, u_char cmd) { int ioaddr=dev->mem_start+0x800; - + ACOMMAND(cmd); } - - - /* The actual interrupt handler routine - handle various IRQ's generated * by the card. */ @@ -410,18 +369,17 @@ { struct arcnet_local *lp=(struct arcnet_local *)dev->priv; int ioaddr=dev->mem_start+0x800, status, boguscount = 3, didsomething; - + AINTMASK(0); - + BUGMSG(D_DURING,"in arcrimi_inthandler (status=%Xh, intmask=%Xh)\n", ARCSTATUS,lp->intmask); - + do { status = ARCSTATUS; didsomething=0; - - + /* RESET flag was enabled - card is resetting and if RX * is disabled, it's NOT because we just got a packet. */ @@ -430,44 +388,43 @@ BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n", status); arcrimi_reset(dev,0); - + /* all other flag values are just garbage */ break; } - - + /* RX is inhibited - we must have received something. */ if (status & lp->intmask & NORXflag) { int recbuf=lp->recbuf=!lp->recbuf; - + BUGMSG(D_DURING,"receive irq (status=%Xh)\n", status); - + /* enable receive of our next packet */ EnableReceiver(); - + /* Got a packet. */ arcrimi_rx(dev,!recbuf); - + didsomething++; } - + /* it can only be an xmit-done irq if we're xmitting :) */ /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/ if (status & lp->intmask & TXFREEflag) { struct Outgoing *out=&(lp->outgoing); int was_sending=lp->sending; - + lp->intmask &= ~TXFREEflag; - + lp->in_txhandler++; if (was_sending) lp->sending--; - + BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n", status,out->numsegs,out->segnum,out->skb); - + if (was_sending && !(status&TXACKflag)) { if (lp->lasttrans_dest != 0) @@ -484,11 +441,11 @@ lp->lasttrans_dest); } } - + /* send packet if there is one */ arcnet_go_tx(dev,0); didsomething++; - + if (lp->intx) { BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n", @@ -496,24 +453,24 @@ lp->in_txhandler--; continue; } - + if (!lp->outgoing.skb) { BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n"); - + /* inform upper layers */ if (!lp->txready) arcnet_tx_done(dev, lp); lp->in_txhandler--; continue; } - + /* if more than one segment, and not all segments * are done, then continue xmit. */ if (out->segnumnumsegs) arcnetA_continue_tx(dev); arcnet_go_tx(dev,0); - + /* if segnum==numsegs, the transmission is finished; * free the skb. */ @@ -527,12 +484,12 @@ dev_kfree_skb(out->skb,FREE_WRITE); } out->skb=NULL; - + /* inform upper layers */ if (!lp->txready) arcnet_tx_done(dev, lp); } didsomething++; - + lp->in_txhandler--; } else if (lp->txready && !lp->sending && !lp->intx) @@ -542,20 +499,18 @@ arcnet_go_tx(dev,0); didsomething++; } - + #ifdef DETECT_RECONFIGS if (status & (lp->intmask) & RECONflag) { ACOMMAND(CFLAGScmd|CONFIGclear); lp->stats.tx_carrier_errors++; - + #ifdef SHOW_RECONFIGS BUGMSG(D_NORMAL,"Network reconfiguration detected (status=%Xh)\n", status); - - #endif /* SHOW_RECONFIGS */ - + #ifdef RECON_THRESHOLD /* is the RECON info empty or old? */ if (!lp->first_recon || !lp->last_recon || @@ -565,19 +520,19 @@ BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n"); lp->first_recon=lp->last_recon=jiffies; lp->num_recons=lp->network_down=0; - + BUGMSG(D_DURING,"recon: clearing counters.\n"); } else /* add to current RECON counter */ { lp->last_recon=jiffies; lp->num_recons++; - + BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n", lp->num_recons, (lp->last_recon-lp->first_recon)/HZ, lp->network_down); - + /* if network is marked up; * and first_recon and last_recon are 60+ sec * apart; @@ -609,26 +564,24 @@ BUGMSG(D_NORMAL,"cabling restored?\n"); lp->first_recon=lp->last_recon=0; lp->num_recons=lp->network_down=0; - + BUGMSG(D_DURING,"not recon: clearing counters anyway.\n"); #endif } #endif /* DETECT_RECONFIGS */ } while (--boguscount && didsomething); - + BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n", ARCSTATUS,boguscount); BUGMSG(D_DURING,"\n"); - + SETMASK; /* put back interrupt mask */ - } - /* A packet has arrived; grab it from the buffers and pass it to the generic * arcnet_rx routing to deal with it. - */ + */ static void arcrimi_rx(struct device *dev,int recbuf) @@ -640,11 +593,11 @@ u_char *arcsoft; short length,offset; u_char daddr,saddr; - + lp->stats.rx_packets++; - + saddr=arcpacket->hardheader.source; - + /* if source is 0, it's a "used" packet! */ if (saddr==0) { @@ -654,11 +607,11 @@ return; } /* Set source address to zero to mark it as old */ - + arcpacket->hardheader.source=0; - + daddr=arcpacket->hardheader.destination; - + if (arcpacket->hardheader.offset1) /* Normal Packet */ { offset=arcpacket->hardheader.offset1; @@ -669,26 +622,22 @@ { offset=arcpacket->hardheader.offset2; arcsoft=&arcpacket->raw[offset]; - + length=512-offset; } - - + arcnet_rx(lp, arcsoft, length, saddr, daddr); - - + BUGLVL(D_RX) arcnet_dump_packet(lp->adev,arcpacket->raw,length>240,"rx"); - + #ifndef SLOW_XMIT_COPY /* clean out the page to make debugging make more sense :) */ BUGLVL(D_DURING) memset((void *)arcpacket->raw,0x42,512); #endif - } - /* Given an skb, copy a packet into the ARCnet buffers for later transmission * by arcnet_go_tx. */ @@ -699,45 +648,45 @@ struct arcnet_local *lp = (struct arcnet_local *)dev->priv; union ArcPacket *arcpacket = (union ArcPacket *)phys_to_virt(dev->mem_start+512*(lp->txbuf^1)); - + #ifdef SLOW_XMIT_COPY char *iptr,*iend,*optr; #endif - + lp->txbuf=lp->txbuf^1; /* XOR with 1 to alternate between 2 and 3 */ - + length+=hdrlen; - + BUGMSG(D_TX,"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n", hdr,length,data); - + #ifndef SLOW_XMIT_COPY /* clean out the page to make debugging make more sense :) */ BUGLVL(D_DURING) memset_io(dev->mem_start+lp->txbuf*512,0x42,512); #endif - + arcpacket->hardheader.destination=daddr; - + /* load packet into shared memory */ if (length<=MTU) /* Normal (256-byte) Packet */ arcpacket->hardheader.offset1=offset=offset?offset:256-length; - + else if (length>=MinTU || offset) /* Extended (512-byte) Packet */ { arcpacket->hardheader.offset1=0; - arcpacket->hardheader.offset2=offset=offset?offset:512-length; + arcpacket->hardheader.offset2=offset=offset?offset:512-length; } else if (exceptA) /* RFC1201 Exception Packet */ { arcpacket->hardheader.offset1=0; arcpacket->hardheader.offset2=offset=512-length-4; - + /* exception-specific stuff - these four bytes * make the packet long enough to fit in a 512-byte * frame. */ - + arcpacket->raw[offset+0]=hdr[0]; arcpacket->raw[offset+1]=0xFF; /* FF flag */ arcpacket->raw[offset+2]=0xFF; /* FF padding */ @@ -748,17 +697,17 @@ { /* RFC1051 - set 4 trailing bytes to 0 */ memset(&arcpacket->raw[508],0,4); - + /* now round up to MinTU */ arcpacket->hardheader.offset1=0; arcpacket->hardheader.offset2=offset=512-MinTU; } - - + + /* copy the packet into ARCnet shmem * - the first bytes of ClientData header are skipped */ - + memcpy((u_char*)arcpacket+offset, (u_char*)hdr,hdrlen); #ifdef SLOW_XMIT_COPY for (iptr=data,iend=iptr+length-hdrlen,optr=(char *)arcpacket+offset+hdrlen; @@ -770,18 +719,17 @@ #else memcpy((u_char*)arcpacket+offset+hdrlen, data,length-hdrlen); #endif - + BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n", daddr,length); - + BUGLVL(D_TX) arcnet_dump_packet(dev,arcpacket->raw,length>MTU,"tx"); - + lp->lastload_dest=daddr; lp->txready=lp->txbuf; /* packet is ready for sending */ } - /**************************************************************************** * * * Kernel Loadable Module Support * @@ -806,13 +754,13 @@ if (device) strcpy(dev->name,device); else arcnet_makename(dev->name); - + if (node && node != 0xff) dev->dev_addr[0]=node; - + dev->irq=irq; if (dev->irq==2) dev->irq=9; - + if (shmem) { dev->mem_start=shmem; @@ -820,7 +768,7 @@ dev->rmem_start=thiscard.mem_start+512*0; dev->rmem_end=thiscard.mem_start+512*2-1; } - + if (register_netdev(dev) != 0) return -EIO; arcnet_use_count(1); @@ -831,9 +779,9 @@ { struct device *dev=&thiscard; int ioaddr=dev->mem_start; - + if (dev->start) (*dev->stop)(dev); - + /* Flush TX and disable RX */ if (ioaddr) { @@ -841,13 +789,13 @@ ACOMMAND(NOTXcmd); /* stop transmit */ ACOMMAND(NORXcmd); /* disable receive */ } - + if (dev->irq) { irq2dev_map[dev->irq] = NULL; free_irq(dev->irq,NULL); } - + unregister_netdev(dev); kfree(dev->priv); dev->priv = NULL; @@ -856,7 +804,6 @@ #else - __initfunc(void arcrimi_setup (char *str, int *ints)) { struct device *dev; @@ -867,9 +814,9 @@ MAX_ARCNET_DEVS); return; } - + dev=&arcnet_devs[arcnet_num_devs]; - + if (ints[0] < 3) { printk("ARCnet RIM I: You must give address, IRQ and node ID.\n"); @@ -888,20 +835,17 @@ case 2: /* IRQ */ dev->irq=ints[2]; - + case 1: /* Mem address */ dev->mem_start=ints[1]; } dev->name = (char *)&arcnet_dev_names[arcnet_num_devs]; - + if (str) strncpy(dev->name, str, 9); - + arcnet_num_devs++; } #endif /* MODULE */ - - - diff -u --recursive --new-file v2.1.53/linux/drivers/net/arcnet.c linux/drivers/net/arcnet.c --- v2.1.53/linux/drivers/net/arcnet.c Thu Sep 4 17:07:30 1997 +++ linux/drivers/net/arcnet.c Sat Sep 6 10:05:42 1997 @@ -1,8 +1,9 @@ -/* arcnet.c: +/* $Id: arcnet.c,v 1.30 1997/09/05 08:57:46 mj Exp $ + Written 1994-1996 by Avery Pennarun, derived from skeleton.c by Donald Becker. - Contact Avery at: apenwarr@foxnet.net or + Contact Avery at: apenwarr@bond.net or RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9 ********************** @@ -17,6 +18,12 @@ ********************** + v2.92 ALPHA (97/02/09) + - Code cleanup [Martin Mares ] + - Better probing for the COM90xx chipset, although only as + a temporary solution until we implement adding of all found + devices at once. [mj] + v2.91 ALPHA (97/19/08) - Add counting of octets in/out. @@ -122,12 +129,13 @@ - Smarter recovery from RECON-during-transmit conditions. (ie. retransmit immediately) - Add support for the new 1.3.x IP header cache, and other features. - - Debug level should be changed with a system call, not a hack to - the "metric" flag. + - Replace setting of debug level with the "metric" flag hack by + something better. SIOCDEVPRIVATE is a good candidate, but it would + require an extra user-level utility. - What about cards with shared memory that can be "turned off?" (or that have none at all, like the SMC PC500longboard) - Does this work now, with IO_MAPPED_BUFFERS? + Does this work now, with IO_MAPPED_BUFFERS? - Autoconfigure PDI5xxPlus cards. (I now have a PDI508Plus to play with temporarily.) Update: yes, the Pure Data config program @@ -154,9 +162,7 @@ */ static const char *version = - "arcnet.c: v2.91 97/08/19 Avery Pennarun et al.\n"; - - + "arcnet.c: v2.92 97/09/02 Avery Pennarun et al.\n"; #include #include @@ -200,16 +206,14 @@ /**************************************************************************/ -/* These are now provided by the chipset driver. There's a performance +/* These are now provided by the chipset driver. There's a performance * overhead in using them. */ - #define AINTMASK(x) ((*lp->asetmask)(dev, x)) #define ARCSTATUS ((*lp->astatus)(dev)) #define ACOMMAND(x) ((*lp->acommand)(dev, x)) - int arcnet_debug=ARCNET_DEBUG; /* Exported function prototypes */ @@ -235,7 +239,6 @@ void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs); void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr); - EXPORT_SYMBOL(arcnet_debug); EXPORT_SYMBOL(arcnet_tx_done); EXPORT_SYMBOL(arcnet_use_count); @@ -302,10 +305,6 @@ #endif - - - - /**************************************************************************** * * * Packet dumps for debugging * @@ -334,6 +333,7 @@ } #endif + /* Dump the contents of an ARCnet buffer */ #if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX) @@ -357,8 +357,6 @@ #endif - - /* Setup a struct device for ARCnet. This should really be in net_init.c * but since there are three different ARCnet devices ANYWAY... * @@ -385,8 +383,7 @@ dev->pa_mask = 0; dev->pa_alen = 4; - - /* Put in this stuff here, so we don't have to export the symbols + /* Put in this stuff here, so we don't have to export the symbols * to the chipset drivers. */ @@ -405,7 +402,6 @@ * * ****************************************************************************/ - /* Open/initialize the board. This is called sometime after booting when * the 'ifconfig' program is run. * @@ -417,39 +413,33 @@ arcnet_open(struct device *dev) { struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - + if (dev->metric>=1000) { arcnet_debug=dev->metric-1000; printk(KERN_INFO "%6s: debug level set to %d\n",dev->name,arcnet_debug); dev->metric=1; } - + BUGMSG(D_INIT,"arcnet_open: resetting card.\n"); - + /* try to put the card in a defined state - if it fails the first * time, actually reset it. */ if ((*lp->arcnet_reset)(dev,0) && (*lp->arcnet_reset)(dev,1)) return -ENODEV; -#if 0 - /* reset the card twice in case something goes wrong the first time. - */ - if ((*(lp->arcnet_reset))(dev,1) && (*(lp->arcnet_reset))(dev,1)) - return -ENODEV; -#endif - + dev->tbusy=0; dev->interrupt=0; lp->intx=0; lp->in_txhandler=0; - + /* The RFC1201 driver is the default - just store */ lp->adev=dev; /* we're started */ dev->start=1; - + #ifdef CONFIG_ARCNET_ETH /* Initialize the ethernet-encap protocol driver */ lp->edev=(struct device *)kmalloc(sizeof(struct device),GFP_KERNEL); @@ -467,7 +457,7 @@ lp->edev->init=arcnetE_init; register_netdev(lp->edev); #endif - + #ifdef CONFIG_ARCNET_1051 /* Initialize the RFC1051-encap protocol driver */ lp->sdev=(struct device *)kmalloc(sizeof(struct device),GFP_KERNEL); @@ -477,27 +467,27 @@ lp->sdev->init=arcnetS_init; register_netdev(lp->sdev); #endif - + /* Enable TX if we need to */ if (lp->en_dis_able_TX) (*lp->en_dis_able_TX)(dev, 1); - + /* make sure we're ready to receive IRQ's. * arcnet_reset sets this for us, but if we receive one before * START is set to 1, it could be ignored. So, we turn IRQ's * off, then on again to clean out the IRQ controller. */ - + AINTMASK(0); udelay(1); /* give it time to set the mask before * we reset it again. (may not even be * necessary) */ SETMASK; - + /* Let it increase its use count */ (*lp->openclose_device)(1); - + return 0; } @@ -508,7 +498,7 @@ arcnet_close(struct device *dev) { struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - + if (test_and_set_bit(0, (int *)&dev->tbusy)) BUGMSG(D_NORMAL, "arcnet_close: tbusy already set!\n"); @@ -522,36 +512,32 @@ lp->edev->start=0; #endif - /* Shut down the card */ - + /* Disable TX if we need to */ if (lp->en_dis_able_TX) (*lp->en_dis_able_TX)(dev, 0); - + (*lp->arcnet_reset)(dev, 3); /* reset IRQ won't run if START=0 */ #if 0 lp->intmask=0; - SETMASK; /* no IRQ's (except RESET, of course) */ + SETMASK; /* no IRQ's (except RESET, of course) */ ACOMMAND(NOTXcmd); /* stop transmit */ ACOMMAND(NORXcmd); /* disable receive */ #endif - + /* reset more flags */ - dev->interrupt=0; + dev->interrupt=0; #ifdef CONFIG_ARCNET_ETH - lp->edev->interrupt=0; + lp->edev->interrupt=0; #endif #ifdef CONFIG_ARCNET_1051 - lp->sdev->interrupt=0; + lp->sdev->interrupt=0; #endif - - - /* do NOT free lp->adev!! It's static! */ lp->adev=NULL; - + #ifdef CONFIG_ARCNET_ETH /* free the ethernet-encap protocol device */ lp->edev->priv=NULL; @@ -561,7 +547,7 @@ kfree(lp->edev); lp->edev=NULL; #endif - + #ifdef CONFIG_ARCNET_1051 /* free the RFC1051-encap protocol device */ lp->sdev->priv=NULL; @@ -571,17 +557,16 @@ kfree(lp->sdev); lp->sdev=NULL; #endif - + /* Update the statistics here. (not necessary in ARCnet) */ - + /* Decrease the use count */ (*lp->openclose_device)(0); - + return 0; } - /**************************************************************************** * * * Transmitter routines * @@ -594,24 +579,24 @@ arcnet_send_packet_bad(struct sk_buff *skb, struct device *dev) { struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - + BUGMSG(D_DURING,"transmit requested (status=%Xh, inTX=%d)\n", ARCSTATUS,lp->intx); - + if (lp->in_txhandler) { BUGMSG(D_NORMAL,"send_packet called while in txhandler!\n"); lp->stats.tx_dropped++; return 1; } - + if (lp->intx>1) { BUGMSG(D_NORMAL,"send_packet called while intx!\n"); lp->stats.tx_dropped++; return 1; } - + if (test_bit(0, (int *)&dev->tbusy)) { /* If we get here, some higher level has decided we are broken. @@ -619,7 +604,7 @@ int tickssofar = jiffies - dev->trans_start; int status=ARCSTATUS; - + if (tickssofar < TX_TIMEOUT) { BUGMSG(D_DURING,"premature kickme! (status=%Xh ticks=%d o.skb=%ph numsegs=%d segnum=%d\n", @@ -628,10 +613,10 @@ lp->outgoing.segnum); return 1; } - + lp->intmask &= ~TXFREEflag; SETMASK; - + if (status&TXFREEflag) /* transmit _DID_ finish */ { BUGMSG(D_NORMAL,"tx timeout - missed IRQ? (status=%Xh, ticks=%d, mask=%Xh, dest=%02Xh)\n", @@ -644,17 +629,17 @@ status,tickssofar,lp->intmask,lp->lasttrans_dest); lp->stats.tx_errors++; lp->stats.tx_aborted_errors++; - + ACOMMAND(NOTXcmd); } - + if (lp->outgoing.skb) { dev_kfree_skb(lp->outgoing.skb,FREE_WRITE); lp->stats.tx_dropped++; } lp->outgoing.skb=NULL; - + #ifdef CONFIG_ARCNET_ETH lp->edev->tbusy=0; #endif @@ -666,10 +651,10 @@ lp->txready=0; lp->sending=0; - + return 1; } - + if (lp->txready) /* transmit already in progress! */ { BUGMSG(D_NORMAL,"trying to start new packet while busy! (status=%Xh)\n", @@ -681,10 +666,10 @@ lp->stats.tx_errors++; lp->stats.tx_fifo_errors++; lp->txready=0; /* we definitely need this line! */ - + return 1; } - + /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ if (test_and_set_bit(0, (int *)&lp->adev->tbusy)) @@ -701,7 +686,7 @@ #ifdef CONFIG_ARCNET_ETH lp->edev->tbusy=1; #endif - + return 0; } @@ -714,13 +699,13 @@ struct arcnet_local *lp = (struct arcnet_local *)dev->priv; int bad,oldmask=0; struct Outgoing *out=&(lp->outgoing); - + lp->intx++; - + oldmask |= lp->intmask; lp->intmask=0; SETMASK; - + bad=arcnet_send_packet_bad(skb,dev); if (bad) { @@ -729,20 +714,20 @@ SETMASK; return bad; } - + /* arcnet_send_packet_pad has already set tbusy - don't bother here. */ - + lp->intmask = oldmask & ~TXFREEflag; SETMASK; - + out->length = 1 < skb->len ? skb->len : 1; out->hdr=(struct ClientData*)skb->data; out->skb=skb; - + BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"tx"); - + out->hdr->sequence=(lp->sequence++); - + /* fits in one packet? */ if (out->length-EXTRA_CLIENTDATA<=XMTU) { @@ -759,12 +744,12 @@ ((char *)skb->data)+sizeof(struct ClientData), out->length-sizeof(struct ClientData), out->hdr->daddr,1,0); - + /* done right away */ lp->stats.tx_bytes += out->skb->len; dev_kfree_skb(out->skb,FREE_WRITE); out->skb=NULL; - + if (arcnet_go_tx(dev,1)) { /* inform upper layers */ @@ -774,19 +759,19 @@ else /* too big for one - split it */ { int maxsegsize=XMTU-4; - + out->data=(u_char *)skb->data + sizeof(struct ClientData); out->dataleft=out->length-sizeof(struct ClientData); out->numsegs=(out->dataleft+maxsegsize-1)/maxsegsize; out->segnum=0; - + BUGMSG(D_TX,"packet (%d bytes) split into %d fragments:\n", out->length,out->numsegs); - + /* if a packet waiting, launch it */ arcnet_go_tx(dev,1); - + if (!lp->txready) { /* prepare a packet, launch it and prepare @@ -799,7 +784,7 @@ arcnet_go_tx(dev,1); } } - + /* if segnum==numsegs, the transmission is finished; * free the skb right away. */ @@ -816,14 +801,14 @@ out->skb=NULL; } } - + dev->trans_start=jiffies; lp->intx--; - + /* make sure we didn't ignore a TX IRQ while we were in here */ lp->intmask |= TXFREEflag; SETMASK; - + return 0; } @@ -837,38 +822,38 @@ struct arcnet_local *lp = (struct arcnet_local *)dev->priv; int maxsegsize=XMTU-4; struct Outgoing *out=&(lp->outgoing); - + BUGMSG(D_DURING,"continue_tx called (status=%Xh, intx=%d, intxh=%d, intmask=%Xh\n", ARCSTATUS,lp->intx,lp->in_txhandler,lp->intmask); - + if (lp->txready) { BUGMSG(D_NORMAL,"continue_tx: called with packet in buffer!\n"); return; } - + if (out->segnum>=out->numsegs) { BUGMSG(D_NORMAL,"continue_tx: building segment %d of %d!\n", out->segnum+1,out->numsegs); } - + if (!out->segnum) /* first packet */ out->hdr->split_flag=((out->numsegs-2)<<1)+1; else out->hdr->split_flag=out->segnum<<1; - + out->seglen=maxsegsize; if (out->seglen>out->dataleft) out->seglen=out->dataleft; - + BUGMSG(D_TX,"building packet #%d (%d bytes) of %d (%d total), splitflag=%d\n", out->segnum+1,out->seglen,out->numsegs, out->length,out->hdr->split_flag); - + (*lp->prepare_tx)(dev,((char *)out->hdr)+EXTRA_CLIENTDATA, sizeof(struct ClientData)-EXTRA_CLIENTDATA, out->data,out->seglen,out->hdr->daddr,1,0); - + out->dataleft-=out->seglen; out->data+=out->seglen; out->segnum++; @@ -936,30 +921,29 @@ { struct device *dev = (struct device *)(irq2dev_map[irq]); struct arcnet_local *lp; - + if (dev==NULL) { BUGLVL(D_DURING) printk(KERN_DEBUG "arcnet: irq %d for unknown device.\n", irq); return; } - + BUGMSG(D_DURING,"in arcnet_interrupt\n"); - - + lp=(struct arcnet_local *)dev->priv; - + /* RESET flag was enabled - if !dev->start, we must clear it right * away (but nothing else) since inthandler() is never called. */ - + if (!dev->start) - { + { if (ARCSTATUS & RESETflag) ACOMMAND(CFLAGScmd|RESETclear); return; } - + if (test_and_set_bit(0, (int *)&dev->interrupt)) { @@ -1000,7 +984,7 @@ if (!test_and_clear_bit(0, (int *)&dev->tbusy)) BUGMSG(D_NORMAL, "In arcnet_tx_done: Someone cleared our dev->tbusy" " flag!\n"); - + mark_bh(NET_BH); } } @@ -1012,7 +996,7 @@ * * ****************************************************************************/ -/* +/* * This is a generic packet receiver that calls arcnet??_rx depending on the * protocol ID found. */ @@ -1020,10 +1004,10 @@ void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr) { struct device *dev=lp->adev; - + BUGMSG(D_DURING,"received packet from %02Xh to %02Xh (%d bytes)\n", saddr,daddr,length); - + /* call the right receiver for the protocol */ switch (arcsoft[0]) { @@ -1059,13 +1043,13 @@ lp->stats.rx_crc_errors++; break; } - + /* If any worth-while packets have been received, a mark_bh(NET_BH) * has been done by netif_rx and Linux will handle them after we * return. */ - - + + } @@ -1079,33 +1063,33 @@ struct arcnet_local *lp = (struct arcnet_local *)dev->priv; struct sk_buff *skb; struct ClientData *arcsoft,*soft; - + BUGMSG(D_DURING,"it's an RFC1201 packet (length=%d)\n", length); - + /* compensate for EXTRA_CLIENTDATA (which isn't actually in the * packet) */ arcsoft=(struct ClientData *)(buf-EXTRA_CLIENTDATA); length+=EXTRA_CLIENTDATA; - + if (arcsoft->split_flag==0xFF) /* Exception Packet */ { BUGMSG(D_DURING,"compensating for exception packet\n"); - + /* skip over 4-byte junkola */ arcsoft=(struct ClientData *) ((u_char *)arcsoft + 4); length-=4; } - + if (!arcsoft->split_flag) /* not split */ { struct Incoming *in=&lp->incoming[saddr]; - + BUGMSG(D_RX,"incoming is not split (splitflag=%d)\n", arcsoft->split_flag); - + if (in->skb) /* already assembling one! */ { BUGMSG(D_EXTRA,"aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n", @@ -1117,9 +1101,9 @@ lp->stats.rx_missed_errors++; in->skb=NULL; } - + in->sequence=arcsoft->sequence; - + skb = alloc_skb(length, GFP_ATOMIC); if (skb == NULL) { BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n"); @@ -1127,16 +1111,16 @@ return; } soft=(struct ClientData *)skb->data; - + skb_put(skb,length); skb->dev = dev; - + memcpy((u_char *)soft+EXTRA_CLIENTDATA, (u_char *)arcsoft+EXTRA_CLIENTDATA, length-EXTRA_CLIENTDATA); soft->daddr=daddr; soft->saddr=saddr; - + /* ARP packets have problems when sent from DOS. * source address is always 0 on some systems! So we take * the hardware source addr (which is impossible to fumble) @@ -1146,12 +1130,12 @@ { struct arphdr *arp=(struct arphdr *) ((char *)soft+sizeof(struct ClientData)); - + /* make sure addresses are the right length */ if (arp->ar_hln==1 && arp->ar_pln==4) { char *cptr=(char *)(arp)+sizeof(struct arphdr); - + if (!*cptr) /* is saddr = 00? */ { BUGMSG(D_EXTRA,"ARP source address was 00h, set to %02Xh.\n", @@ -1173,9 +1157,9 @@ lp->stats.rx_crc_errors++; } } - + BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx"); - + lp->stats.rx_bytes += skb->len; skb->protocol=arcnetA_type_trans(skb,dev); netif_rx(skb); @@ -1198,12 +1182,12 @@ * ARCnet card possible on the network. Seems rather like * a waste of memory. Necessary? */ - + struct Incoming *in=&lp->incoming[saddr]; - + BUGMSG(D_RX,"packet is split (splitflag=%d, seq=%d)\n", arcsoft->split_flag,in->sequence); - + if (in->skb && in->sequence!=arcsoft->sequence) { BUGMSG(D_EXTRA,"wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n", @@ -1215,7 +1199,7 @@ lp->stats.rx_missed_errors++; in->lastpacket=in->numpackets=0; } - + if (arcsoft->split_flag & 1) /* first packet in split */ { BUGMSG(D_RX,"brand new splitpacket (splitflag=%d)\n", @@ -1229,11 +1213,11 @@ lp->stats.rx_missed_errors++; kfree_skb(in->skb,FREE_WRITE); } - + in->sequence=arcsoft->sequence; in->numpackets=((unsigned)arcsoft->split_flag>>1)+2; in->lastpacket=1; - + if (in->numpackets>16) { BUGMSG(D_EXTRA,"incoming packet more than 16 segments; dropping. (splitflag=%d)\n", @@ -1242,7 +1226,7 @@ lp->stats.rx_length_errors++; return; } - + in->skb=skb=alloc_skb(508*in->numpackets + sizeof(struct ClientData), GFP_ATOMIC); @@ -1251,12 +1235,12 @@ lp->stats.rx_dropped++; return; } - + soft=(struct ClientData *)skb->data; - + skb_put(skb,sizeof(struct ClientData)); skb->dev=dev; - + memcpy((u_char *)soft+EXTRA_CLIENTDATA, (u_char *)arcsoft+EXTRA_CLIENTDATA, sizeof(struct ClientData)-EXTRA_CLIENTDATA); @@ -1265,7 +1249,7 @@ else /* not first packet */ { int packetnum=((unsigned)arcsoft->split_flag>>1) + 1; - + /* if we're not assembling, there's no point * trying to continue. */ @@ -1280,7 +1264,7 @@ } return; } - + in->lastpacket++; if (packetnum!=in->lastpacket) /* not the right flag! */ { @@ -1293,7 +1277,7 @@ lp->stats.rx_frame_errors++; return; } - + /* "bad" duplicate, kill reassembly */ BUGMSG(D_EXTRA,"out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n", in->sequence,arcsoft->split_flag, @@ -1306,20 +1290,20 @@ in->lastpacket=in->numpackets=0; return; } - + soft=(struct ClientData *)in->skb->data; } - + skb=in->skb; - + memcpy(skb->data+skb->len, (u_char *)arcsoft+sizeof(struct ClientData), length-sizeof(struct ClientData)); skb_put(skb,length-sizeof(struct ClientData)); - + soft->daddr=daddr; soft->saddr=saddr; - + /* are we done? */ if (in->lastpacket == in->numpackets) { @@ -1332,9 +1316,9 @@ { in->skb=NULL; in->lastpacket=in->numpackets=0; - + BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx"); - + lp->stats.rx_bytes += skb->len; skb->protocol=arcnetA_type_trans(skb,dev); netif_rx(skb); @@ -1344,15 +1328,12 @@ } - - /**************************************************************************** * * * Miscellaneous routines * * * ****************************************************************************/ - /* Get the current statistics. This may be called with the card open or * closed. */ @@ -1360,7 +1341,7 @@ static struct net_device_stats *arcnet_get_stats(struct device *dev) { struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - + return &lp->stats; } @@ -1376,12 +1357,12 @@ struct ClientData *head = (struct ClientData *) skb_push(skb,dev->hard_header_len); struct arcnet_local *lp=(struct arcnet_local *)(dev->priv); - + BUGMSG(D_DURING,"create header from %d to %d; protocol %d (%Xh); size %u.\n", saddr ? *(u_char*)saddr : -1, daddr ? *(u_char*)daddr : -1, type,type,len); - + /* set the protocol ID according to RFC1201 */ switch(type) { @@ -1409,7 +1390,7 @@ lp->stats.tx_aborted_errors++; return 0; } - + /* * Set the source hardware address. * @@ -1422,10 +1403,10 @@ head->saddr=((u_char*)saddr)[0]; else head->saddr=((u_char*)(dev->dev_addr))[0]; - + head->split_flag=0; /* split packets are done elsewhere */ head->sequence=0; /* so are sequence numbers */ - + /* supposedly if daddr is NULL, we should ignore it... */ if(daddr) { @@ -1434,12 +1415,11 @@ } else head->daddr=0; /* better fill one in anyway */ - + return -dev->hard_header_len; } - /* Rebuild the ARCnet ClientData header. This is called after an ARP * (or in future other address resolution) has completed on this * sk_buff. We now let ARP fill in the other fields. @@ -1450,13 +1430,13 @@ struct device *dev=skb->dev; struct arcnet_local *lp=(struct arcnet_local *)(dev->priv); int status; - + /* * Only ARP and IP are currently supported * * FIXME: Anyone want to spec IPv6 over ARCnet ? */ - + if(head->protocol_id != ARC_P_IP) { BUGMSG(D_NORMAL,"I don't understand protocol type %d (%Xh) addresses!\n", @@ -1467,7 +1447,7 @@ /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/ return 0; } - + /* * Try to get ARP to resolve the header. */ @@ -1492,12 +1472,12 @@ { struct ClientData *head; struct arcnet_local *lp=(struct arcnet_local *) (dev->priv); - + /* Pull off the arcnet header. */ skb->mac.raw=skb->data; skb_pull(skb,dev->hard_header_len); head=(struct ClientData *)skb->mac.raw; - + if (head->daddr==0) skb->pkt_type=PACKET_BROADCAST; else if (dev->flags&IFF_PROMISC) @@ -1506,14 +1486,14 @@ if (head->daddr != dev->dev_addr[0]) skb->pkt_type=PACKET_OTHERHOST; } - + /* now return the protocol number */ switch (head->protocol_id) { case ARC_P_IP: return htons(ETH_P_IP); case ARC_P_ARP: return htons(ETH_P_ARP); case ARC_P_RARP: return htons(ETH_P_RARP); - + case ARC_P_IPX: case ARC_P_NOVELL_EC: return htons(ETH_P_802_3); @@ -1522,7 +1502,7 @@ lp->stats.rx_crc_errors++; return 0; } - + return htons(ETH_P_IP); } @@ -1539,7 +1519,7 @@ static int arcnetE_init(struct device *dev) { struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - + ether_setup(dev); /* we're emulating ether here, not ARCnet */ dev->dev_addr[0]=0; dev->dev_addr[5]=lp->stationid; @@ -1547,7 +1527,7 @@ dev->open=arcnetE_open_close; dev->stop=arcnetE_open_close; dev->hard_start_xmit=arcnetE_send_packet; - + return 0; } @@ -1571,13 +1551,13 @@ u_char daddr; short offset,length=skb->len+1; u_char proto=ARC_P_ETHER; - + lp->intx++; - + oldmask |= lp->intmask; lp->intmask=0; SETMASK; - + bad=arcnet_send_packet_bad(skb,dev); if (bad) { @@ -1586,31 +1566,31 @@ SETMASK; return bad; } - + /* arcnet_send_packet_pad has already set tbusy - don't bother here. */ lp->intmask=oldmask; SETMASK; - + if (length>XMTU) { BUGMSG(D_NORMAL,"MTU must be <= 493 for ethernet encap (length=%d).\n", length); BUGMSG(D_NORMAL,"transmit aborted.\n"); - + dev_kfree_skb(skb,FREE_WRITE); lp->intx--; return 0; } - + BUGMSG(D_DURING,"starting tx sequence...\n"); - + /* broadcasts have address FF:FF:FF:FF:FF:FF in etherspeak */ if (((struct ethhdr*)(skb->data))->h_dest[0] == 0xFF) daddr=0; else daddr=((struct ethhdr*)(skb->data))->h_dest[5]; - + /* load packet into shared memory */ offset=512-length; if (length>MTU) /* long/exception packet */ @@ -1621,17 +1601,13 @@ { offset-=256; } - + BUGMSG(D_DURING," length=%Xh, offset=%Xh\n", length,offset); - - - (*lp->prepare_tx)(dev, &proto, 1, skb->data, length-1, daddr, 0, + (*lp->prepare_tx)(dev, &proto, 1, skb->data, length-1, daddr, 0, offset); - - - + dev_kfree_skb(skb,FREE_WRITE); if (arcnet_go_tx(dev,1)) @@ -1639,7 +1615,7 @@ /* inform upper layers */ arcnet_tx_done(lp->adev, lp); } - + dev->trans_start=jiffies; lp->intx--; @@ -1697,9 +1673,9 @@ static int arcnetS_init(struct device *dev) { struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - + arcnet_setup(dev); - + /* And now fill particular fields with arcnet values */ dev->dev_addr[0]=lp->stationid; dev->hard_header_len=sizeof(struct S_ClientData); @@ -1710,7 +1686,7 @@ dev->hard_start_xmit=arcnetS_send_packet; dev->hard_header=arcnetS_header; dev->rebuild_header=arcnetS_rebuild_header; - + return 0; } @@ -1732,9 +1708,9 @@ struct arcnet_local *lp = (struct arcnet_local *)dev->priv; int bad,length; struct S_ClientData *hdr=(struct S_ClientData *)skb->data; - + lp->intx++; - + bad=arcnet_send_packet_bad(skb,dev); if (bad) { @@ -1743,11 +1719,11 @@ } /* arcnet_send_packet_pad has already set tbusy - don't bother here. */ - + length = 1 < skb->len ? skb->len : 1; - + BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"tx"); - + /* fits in one packet? */ if (length-S_EXTRA_CLIENTDATA<=XMTU) { @@ -1757,10 +1733,10 @@ skb->data+sizeof(struct S_ClientData), length-sizeof(struct S_ClientData), hdr->daddr,0,0); - + /* done right away */ dev_kfree_skb(skb,FREE_WRITE); - + if (arcnet_go_tx(dev,1)) { /* inform upper layers */ @@ -1775,14 +1751,14 @@ lp->stats.tx_dropped++; arcnet_tx_done(lp->adev, lp); } - + dev->trans_start=jiffies; lp->intx--; - + /* make sure we didn't ignore a TX IRQ while we were in here */ lp->intmask |= TXFREEflag; SETMASK; - + return 0; } @@ -1796,17 +1772,15 @@ struct arcnet_local *lp = (struct arcnet_local *)dev->priv; struct sk_buff *skb; struct S_ClientData *arcsoft,*soft; - + arcsoft=(struct S_ClientData *)(buf-S_EXTRA_CLIENTDATA); length+=S_EXTRA_CLIENTDATA; - + BUGMSG(D_DURING,"it's an RFC1051 packet (length=%d)\n", length); - - - + { /* was "if not split" in A protocol, S is never split */ - + skb = alloc_skb(length, GFP_ATOMIC); if (skb == NULL) { BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n"); @@ -1823,9 +1797,9 @@ soft->daddr=daddr; soft->saddr=saddr; skb->dev = dev; /* is already lp->sdev */ - + BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx"); - + lp->stats.rx_bytes += skb->len; skb->protocol=arcnetS_type_trans(skb,dev); netif_rx(skb); @@ -1844,7 +1818,7 @@ struct S_ClientData *head = (struct S_ClientData *) skb_push(skb,dev->hard_header_len); struct arcnet_local *lp=(struct arcnet_local *)(dev->priv); - + /* set the protocol ID according to RFC1051 */ switch(type) { @@ -1863,7 +1837,7 @@ lp->stats.tx_aborted_errors++; return 0; } - + /* * Set the source hardware address. * @@ -1876,7 +1850,7 @@ head->saddr=((u_char*)saddr)[0]; else head->saddr=((u_char*)(dev->dev_addr))[0]; - + /* supposedly if daddr is NULL, we should ignore it... */ if(daddr) { @@ -1885,7 +1859,7 @@ } else head->daddr=0; /* better fill one in anyway */ - + return -dev->hard_header_len; } @@ -1899,11 +1873,11 @@ struct device *dev=skb->dev; struct S_ClientData *head = (struct S_ClientData *)skb->data; struct arcnet_local *lp=(struct arcnet_local *)(dev->priv); - + /* * Only ARP and IP are currently supported */ - + if(head->protocol_id != ARC_P_IP_RFC1051) { BUGMSG(D_NORMAL,"I don't understand protocol type %d (%Xh) addresses!\n", @@ -1914,7 +1888,7 @@ /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/ return 0; } - + /* * Try to get ARP to resolve the header. */ @@ -1934,12 +1908,12 @@ { struct S_ClientData *head; struct arcnet_local *lp=(struct arcnet_local *) (dev->priv); - + /* Pull off the arcnet header. */ skb->mac.raw=skb->data; skb_pull(skb,dev->hard_header_len); head=(struct S_ClientData *)skb->mac.raw; - + if (head->daddr==0) skb->pkt_type=PACKET_BROADCAST; else if (dev->flags&IFF_PROMISC) @@ -1948,7 +1922,7 @@ if (head->daddr != dev->dev_addr[0]) skb->pkt_type=PACKET_OTHERHOST; } - + /* now return the protocol number */ switch (head->protocol_id) { @@ -1960,20 +1934,19 @@ lp->stats.rx_crc_errors++; return 0; } - + return htons(ETH_P_IP); } #endif /* CONFIG_ARCNET_1051 */ + /**************************************************************************** * * * Kernel Loadable Module Support * * * ****************************************************************************/ - - #ifdef MODULE void cleanup_module(void) @@ -1982,7 +1955,7 @@ } void arcnet_use_count(int open) -{ +{ if (open) MOD_INC_USE_COUNT; else @@ -1999,14 +1972,14 @@ int arcnet_num_devs=0; char arcnet_dev_names[MAX_ARCNET_DEVS][10]; -void arcnet_init(void) +__initfunc(void arcnet_init(void)) { int c; - - (void) init_module(); + + init_module(); /* Don't register_netdev here. The chain hasn't been initialised. */ - + #ifdef CONFIG_ARCNET_COM90xx if ((!com90xx_explicit) && arcnet_num_devs < MAX_ARCNET_DEVS) { @@ -2020,7 +1993,7 @@ if (!arcnet_num_devs) { printk("Don't forget to load the chipset driver.\n"); - return; + return; } /* Link into the device chain */ @@ -2033,20 +2006,24 @@ arcnet_devs[c].next=dev_base; dev_base=&arcnet_devs[0]; - + /* Give names to those without them */ - + for (c=0; c< arcnet_num_devs; c++) if (!arcnet_dev_names[c][0]) arcnet_makename((char *)&arcnet_dev_names[c]); - } -static + #endif /* MODULE */ -int init_module() + + +#ifdef MODULE +int init_module(void) +#else +__initfunc(static int init_module(void)) +#endif { - -#if 1 +#ifdef ALPHA_WARNING BUGLVL(D_EXTRA) { printk("arcnet: ***\n"); @@ -2058,8 +2035,7 @@ } #endif - printk("%sGeneric arcnet support for Linux kernel.\n" - "Available protocols: ARCnet RFC1201" + printk("%sAvailable protocols: ARCnet RFC1201" #ifdef CONFIG_ARCNET_ETH ", Ethernet-Encap" #endif @@ -2074,50 +2050,20 @@ } - - - void arcnet_makename(char *device) { - __u32 arcmask=0; struct device *dev; - char *c; int arcnum; - for (dev = dev_base; dev; dev=dev->next) - { - arcnum=0; - - if (!strncmp(dev->name, "arc", 3)) - { - c = &dev->name[3]; - while ((*c)>='0' && (*c)<='9') - { - arcnum *= 10; - arcnum += (*(c++)-'0'); - } - - if (arcnum<32) - arcmask |= ((__u32)1 << arcnum); - } - - - } - - /* arcmask now holds a mask of the first 32 arcnet names available */ - - if ((__u32)~arcmask) - { - for (arcnum=0; arcmask&1; arcnum++, arcmask >>=1) - ; - - sprintf (device, "arc%d",arcnum); - } - else + arcnum = 0; + for (;;) { - printk (KERN_INFO "arcnet: Can't find name for device\n"); - sprintf (device, "arc???"); + sprintf(device, "arc%d", arcnum); + for (dev = dev_base; dev; dev=dev->next) + if (dev->name != device && !strcmp(dev->name, device)) + break; + if (!dev) + return; + arcnum++; } } - - diff -u --recursive --new-file v2.1.53/linux/drivers/net/com20020.c linux/drivers/net/com20020.c --- v2.1.53/linux/drivers/net/com20020.c Thu Sep 4 17:07:30 1997 +++ linux/drivers/net/com20020.c Sat Sep 6 10:05:42 1997 @@ -1,4 +1,5 @@ -/* com20020.c: +/* $Id: com20020.c,v 1.2 1997/09/05 08:57:50 mj Exp $ + Written 1997 by David Woodhouse Derived from the original arcnet.c, @@ -59,36 +60,6 @@ #include - - - -/* External functions from arcnet.c */ - - - -#if ARCNET_DEBUG_MAX & D_SKB -extern void arcnet_dump_skb(struct device *dev,struct sk_buff *skb, - char *desc); -#else -#define arcnet_dump_skb(dev,skb,desc) ; -#endif - -#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX) -extern void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext, - char *desc); -#else -#define arcnet_dump_packet(dev,buffer,ext,desc) ; -#endif -extern void arcnet_tx_done(struct device *dev, struct arcnet_local *lp); -extern void arcnet_makename(char *device); -extern void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs); -extern void arcnet_setup(struct device *dev); -extern int arcnet_go_tx(struct device *dev,int enable_irq); -extern void arcnetA_continue_tx(struct device *dev); -extern void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr); -extern void arcnet_use_count(int open); - - /* Internal function declarations */ static int arc20020_probe(struct device *dev); @@ -136,7 +107,6 @@ #endif - /* Handy defines for ARCnet specific stuff */ static char *clockrates[]={"2.5 Mb/s","1.25Mb/s","625 Kb/s","312.5 Kb/s", @@ -144,7 +114,7 @@ "Reserved"}; -/* The number of low I/O ports used by the ethercard. */ +/* The number of low I/O ports used by the card. */ #define ARCNET_TOTAL_SIZE 9 #define _INTMASK (ioaddr+0) /* writable */ @@ -156,7 +126,6 @@ #define _ADDR_HI (ioaddr+2) /* Control registers for said */ #define _ADDR_LO (ioaddr+3) - #define RDDATAflag 0x80 /* Next access is a read/~write */ #define NEWNXTIDflag 0x02 /* ID to which token is passed has changed */ @@ -178,7 +147,6 @@ outb(0x18 , _CONFIG); \ } - #define ARCSTATUS inb(_STATUS) #define ACOMMAND(cmd) outb((cmd),_COMMAND) #define AINTMASK(msk) outb((msk),_INTMASK) @@ -247,7 +215,7 @@ static const char *version = - "com20020.c: v2.91 97/08/19 Avery Pennarun et al.\n"; + "com20020.c: v2.92 97/09/02 Avery Pennarun et al.\n"; /**************************************************************************** * * @@ -256,7 +224,6 @@ ****************************************************************************/ - /* We cannot probe for an IO mapped card either, although we can check that * it's where we were told it was, and even autoirq */ @@ -300,15 +267,12 @@ return -ENODEV; } - BUGMSG(D_INIT_REASONS,"Status after reset: %X\n",status); - /* Enable TX */ outb(0x39,_CONFIG); outb(inb(ioaddr+8),ioaddr+7); - ACOMMAND(CFLAGScmd|RESETclear|CONFIGclear); BUGMSG(D_INIT_REASONS,"Status after reset acknowledged: %X\n",status); @@ -364,7 +328,6 @@ } - /* Set up the struct device associated with this card. Called after * probing succeeds. */ @@ -385,12 +348,10 @@ request_region(ioaddr,ARCNET_TOTAL_SIZE,"arcnet (COM20020)"); dev->base_addr=ioaddr; - dev->mem_start=dev->mem_end=dev->rmem_start=dev->rmem_end=(long)NULL; - - + /* Initialize the rest of the device structure. */ - + dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL); if (dev->priv == NULL) { @@ -404,7 +365,7 @@ lp=(struct arcnet_local *)(dev->priv); lp->card_type = ARC_20020; lp->card_type_str = "COM 20020"; - + lp->arcnet_reset=arc20020_reset; lp->asetmask=arc20020_setmask; lp->astatus=arc20020_status; @@ -413,31 +374,30 @@ lp->openclose_device=arc20020_openclose; lp->prepare_tx=arc20020_prepare_tx; lp->inthandler=arc20020_inthandler; - - + dev->set_multicast_list = arc20020_set_mc_list; - + /* Fill in the fields of the device structure with generic * values. */ arcnet_setup(dev); - + /* And now fill particular fields with arcnet values */ dev->mtu=1500; /* completely arbitrary - agrees with ether, though */ dev->hard_header_len=sizeof(struct ClientData); lp->sequence=1; lp->recbuf=0; - + BUGMSG(D_DURING,"ClientData header size is %d.\n", sizeof(struct ClientData)); BUGMSG(D_DURING,"HardHeader size is %d.\n", sizeof(struct archdr)); - + /* get and check the station ID from offset 1 in shmem */ lp->timeout = dev->dev_addr[3] & 3; dev->dev_addr[3]=0; lp->backplane =dev->dev_addr[1] & 1; dev->dev_addr[1]=0; lp->setup = (dev->dev_addr[2] & 7) << 1; dev->dev_addr[2]=0; - + if (dev->dev_addr[0]) lp->stationid=dev->dev_addr[0]; else @@ -447,11 +407,11 @@ /* Default 0x38 + register: Node ID */ SETCONF; outb(lp->stationid, ioaddr+7); - + REGSETUP; SETCONF; outb(lp->setup, ioaddr+7); - + if (!lp->stationid) BUGMSG(D_NORMAL,"WARNING! Station address 00 is reserved " "for broadcasts!\n"); @@ -459,19 +419,19 @@ BUGMSG(D_NORMAL,"WARNING! Station address FF may confuse " "DOS networking programs!\n"); dev->dev_addr[0]=lp->stationid; - + BUGMSG(D_NORMAL,"ARCnet COM20020: station %02Xh found at %03lXh, IRQ %d.\n", lp->stationid, dev->base_addr,dev->irq); - + if (lp->backplane) BUGMSG (D_NORMAL, "Using backplane mode.\n"); - + if (lp->timeout != 3) BUGMSG (D_NORMAL, "Using Extended Timeout value of %d.\n",lp->timeout); if (lp->setup) { BUGMSG (D_NORMAL, "Using CKP %d - Data rate %s.\n", - lp->setup >>1,clockrates[lp->setup >> 1] ); + lp->setup >>1,clockrates[lp->setup >> 1] ); } return 0; } @@ -479,7 +439,7 @@ /**************************************************************************** * * - * Utility routines for arcnet.c * + * Utility routines * * * ****************************************************************************/ @@ -495,59 +455,59 @@ struct arcnet_local *lp=(struct arcnet_local *)dev->priv; short ioaddr=dev->base_addr; int delayval,recbuf=lp->recbuf; - + if (reset_delay==3) { ARCRESET; return 0; } - + /* no IRQ's, please! */ lp->intmask=0; SETMASK; - + BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n", dev->name,ARCSTATUS); - - lp->config = 0x20 | (lp->timeout<<3) | (lp->backplane<<2); + + lp->config = 0x20 | (lp->timeout<<3) | (lp->backplane<<2); /* power-up defaults */ SETCONF; - + if (reset_delay) { /* reset the card */ ARCRESET; JIFFER(RESETtime); } - + ACOMMAND(CFLAGScmd|RESETclear); /* clear flags & end reset */ ACOMMAND(CFLAGScmd|CONFIGclear); - + /* verify that the ARCnet signature byte is present */ - + if (get_buffer_byte(dev,0) != TESTvalue) { BUGMSG(D_NORMAL,"reset failed: TESTvalue not present.\n"); return 1; } - + /* clear out status variables */ recbuf=lp->recbuf=0; lp->txbuf=2; - + /* enable extended (512-byte) packets */ ACOMMAND(CONFIGcmd|EXTconf); - + /* and enable receive of our first packet to the first buffer */ EnableReceiver(); - + /* re-enable interrupts */ lp->intmask|=NORXflag; #ifdef DETECT_RECONFIGS lp->intmask|=RECONflag; #endif SETMASK; - + /* done! return success. */ return 0; } @@ -565,7 +525,7 @@ { struct arcnet_local *lp=dev->priv; int ioaddr=dev->base_addr; - + if ((dev->flags & IFF_PROMISC) && (dev->flags & IFF_UP)) { /* Enable promiscuous mode */ if (!(lp->setup & PROMISCflag)) @@ -583,7 +543,7 @@ SETCONF; lp->setup &= ~PROMISCflag; outb(lp->setup,ioaddr+7); - } + } } @@ -595,11 +555,12 @@ MOD_DEC_USE_COUNT; } + static void arc20020_en_dis_able_TX(struct device *dev, int enable) { struct arcnet_local *lp=(struct arcnet_local *)dev->priv; int ioaddr=dev->base_addr; - + lp->config=enable?(lp->config | TXENflag):(lp->config & ~TXENflag); SETCONF; } @@ -608,10 +569,11 @@ static void arc20020_setmask(struct device *dev, u_char mask) { short ioaddr=dev->base_addr; - + AINTMASK(mask); } + static u_char arc20020_status(struct device *dev) { short ioaddr=dev->base_addr; @@ -619,6 +581,7 @@ return ARCSTATUS; } + static void arc20020_command(struct device *dev, u_char cmd) { short ioaddr=dev->base_addr; @@ -634,22 +597,20 @@ arc20020_inthandler(struct device *dev) { struct arcnet_local *lp=(struct arcnet_local *)dev->priv; - int ioaddr=dev->base_addr, status, boguscount = 3, didsomething, + int ioaddr=dev->base_addr, status, boguscount = 3, didsomething, dstatus; - - - + AINTMASK(0); - + BUGMSG(D_DURING,"in arc20020_inthandler (status=%Xh, intmask=%Xh)\n", ARCSTATUS,lp->intmask); - + do { status = ARCSTATUS; didsomething=0; - - + + /* RESET flag was enabled - card is resetting and if RX * is disabled, it's NOT because we just got a packet. */ @@ -658,56 +619,53 @@ BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n", status); arc20020_reset(dev,0); - + /* all other flag values are just garbage */ break; } - - + /* RX is inhibited - we must have received something. */ if (status & lp->intmask & NORXflag) { int recbuf=lp->recbuf=!lp->recbuf; int oldaddr=0; - + BUGMSG(D_DURING,"receive irq (status=%Xh)\n", status); - + /* enable receive of our next packet */ EnableReceiver(); - + if (lp->intx) oldaddr=(inb(_ADDR_HI)<<8) | inb(_ADDR_LO); - - + /* Got a packet. */ arc20020_rx(dev,!recbuf); - - + if (lp->intx) { outb( (oldaddr >> 8), _ADDR_HI); outb( oldaddr & 0xff, _ADDR_LO); } - + didsomething++; } - + /* it can only be an xmit-done irq if we're xmitting :) */ /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/ if (status & lp->intmask & TXFREEflag) { struct Outgoing *out=&(lp->outgoing); int was_sending=lp->sending; - + lp->intmask &= ~TXFREEflag; - + lp->in_txhandler++; if (was_sending) lp->sending--; - + BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n", status,out->numsegs,out->segnum,out->skb); - + if (was_sending && !(status&TXACKflag)) { if (lp->lasttrans_dest != 0) @@ -724,11 +682,11 @@ lp->lasttrans_dest); } } - + /* send packet if there is one */ arcnet_go_tx(dev,0); didsomething++; - + if (lp->intx) { BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n", @@ -736,24 +694,24 @@ lp->in_txhandler--; continue; } - + if (!lp->outgoing.skb) { BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n"); - + /* inform upper layers */ if (!lp->txready) arcnet_tx_done(dev, lp); lp->in_txhandler--; continue; } - + /* if more than one segment, and not all segments * are done, then continue xmit. */ if (out->segnumnumsegs) arcnetA_continue_tx(dev); arcnet_go_tx(dev,0); - + /* if segnum==numsegs, the transmission is finished; * free the skb. */ @@ -767,12 +725,12 @@ dev_kfree_skb(out->skb,FREE_WRITE); } out->skb=NULL; - + /* inform upper layers */ if (!lp->txready) arcnet_tx_done(dev, lp); } didsomething++; - + lp->in_txhandler--; } else if (lp->txready && !lp->sending && !lp->intx) @@ -782,27 +740,26 @@ arcnet_go_tx(dev,0); didsomething++; } - + if ((dstatus=inb(_DIAGSTAT)) & NEWNXTIDflag) { REGNXTID; SETCONF; BUGMSG(D_EXTRA,"New NextID detected: %X\n",inb(ioaddr+7)); } - - + + #ifdef DETECT_RECONFIGS if (status & (lp->intmask) & RECONflag) { ACOMMAND(CFLAGScmd|CONFIGclear); lp->stats.tx_carrier_errors++; - + #ifdef SHOW_RECONFIGS - BUGMSG(D_NORMAL,"Network reconfiguration detected (status=%Xh, diag status=%Xh, config=%X)\n", status,dstatus,lp->config); #endif /* SHOW_RECONFIGS */ - + #ifdef RECON_THRESHOLD /* is the RECON info empty or old? */ if (!lp->first_recon || !lp->last_recon || @@ -812,19 +769,19 @@ BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n"); lp->first_recon=lp->last_recon=jiffies; lp->num_recons=lp->network_down=0; - + BUGMSG(D_DURING,"recon: clearing counters.\n"); } else /* add to current RECON counter */ { lp->last_recon=jiffies; lp->num_recons++; - + BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n", lp->num_recons, (lp->last_recon-lp->first_recon)/HZ, lp->network_down); - + /* if network is marked up; * and first_recon and last_recon are 60+ sec * apart; @@ -856,26 +813,25 @@ BUGMSG(D_NORMAL,"cabling restored?\n"); lp->first_recon=lp->last_recon=0; lp->num_recons=lp->network_down=0; - + BUGMSG(D_DURING,"not recon: clearing counters anyway.\n"); #endif } #endif /* DETECT_RECONFIGS */ } while (--boguscount && didsomething); - + BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n", ARCSTATUS,boguscount); BUGMSG(D_DURING,"\n"); - + SETMASK; /* put back interrupt mask */ - -} +} /* A packet has arrived; grab it from the buffers and pass it to the generic * arcnet_rx routing to deal with it. - */ + */ static void arc20020_rx(struct device *dev,int recbuf) @@ -887,13 +843,13 @@ u_char *arcsoft; short length,offset; u_char daddr,saddr; - + lp->stats.rx_packets++; - + get_whole_buffer(dev,recbuf*512,4,(char *)arcpacket); - + saddr=arcpacket->hardheader.source; - + /* if source is 0, it's a "used" packet! */ if (saddr==0) { @@ -903,13 +859,13 @@ return; } /* Set source address to zero to mark it as old */ - + put_buffer_byte(dev,recbuf*512,0); - + arcpacket->hardheader.source=0; - + daddr=arcpacket->hardheader.destination; - + if (arcpacket->hardheader.offset1) /* Normal Packet */ { offset=arcpacket->hardheader.offset1; @@ -922,16 +878,15 @@ arcsoft=&arcpacket->raw[offset]; length=512-offset; } - + get_whole_buffer(dev,recbuf*512+offset,length,(char *)arcpacket+offset); - + arcnet_rx(lp, arcsoft, length, saddr, daddr); - + BUGLVL(D_RX) arcnet_dump_packet(lp->adev,arcpacket->raw,length>240,"rx"); } - /* Given an skb, copy a packet into the ARCnet buffers for later transmission * by arcnet_go_tx. */ @@ -940,20 +895,20 @@ char *data,int length,int daddr,int exceptA, int offset) { struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - + lp->txbuf=lp->txbuf^1; /* XOR with 1 to alternate between 2 and 3 */ - + length+=hdrlen; - + BUGMSG(D_TX,"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n", hdr,length,data); - + put_buffer_byte(dev, lp->txbuf*512+1, daddr); /* load packet into shared memory */ if (length<=MTU) /* Normal (256-byte) Packet */ put_buffer_byte(dev, lp->txbuf*512+2, offset=offset?offset:256-length); - + else if (length>=MinTU || offset) /* Extended (512-byte) Packet */ { put_buffer_byte(dev, lp->txbuf*512+2, 0); @@ -963,36 +918,36 @@ { put_buffer_byte(dev, lp->txbuf*512+2, 0); put_buffer_byte(dev, lp->txbuf*512+3, offset=512-length-4); - + /* exception-specific stuff - these four bytes * make the packet long enough to fit in a 512-byte * frame. */ - + put_whole_buffer(dev, lp->txbuf*512+offset,4,"\0\0xff\0xff\0xff"); offset+=4; } else /* "other" Exception packet */ { /* RFC1051 - set 4 trailing bytes to 0 */ - + put_whole_buffer(dev,lp->txbuf*512+508,4,"\0\0\0\0"); - + /* now round up to MinTU */ put_buffer_byte(dev, lp->txbuf*512+2, 0); put_buffer_byte(dev, lp->txbuf*512+3, offset=512-MinTU); } - + /* copy the packet into ARCnet shmem * - the first bytes of ClientData header are skipped */ - + put_whole_buffer(dev, 512*lp->txbuf+offset, hdrlen,(u_char *)hdr); put_whole_buffer(dev, 512*lp->txbuf+offset+hdrlen,length-hdrlen,data); - + BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n", daddr,length); - + lp->lastload_dest=daddr; lp->txready=lp->txbuf; /* packet is ready for sending */ } @@ -1014,13 +969,13 @@ int init_module(void) { struct device *dev; - + cards[0]=dev=(struct device *)kmalloc(sizeof(struct device), GFP_KERNEL); if (!dev) return -ENOMEM; - + memset(dev, 0, sizeof(struct device)); - + dev->name=(char *)kmalloc(9, GFP_KERNEL); if (!dev->name) { @@ -1035,19 +990,19 @@ if (node && node != 0xff) dev->dev_addr[0]=node; - + if (backplane) dev->dev_addr[1]=backplane?1:0; if (clock) dev->dev_addr[2]=clock&7; dev->dev_addr[3]=timeout&3; dev->base_addr=io; dev->irq=irq; - + if (dev->irq==2) dev->irq=9; if (register_netdev(dev) != 0) return -EIO; - + /* Increase use count of arcnet.o */ arcnet_use_count(1); @@ -1058,9 +1013,9 @@ { struct device *dev=cards[0]; int ioaddr=dev->base_addr; - + if (dev->start) (*dev->stop)(dev); - + /* Flush TX and disable RX */ if (ioaddr) { @@ -1068,21 +1023,22 @@ ACOMMAND(NOTXcmd); /* stop transmit */ ACOMMAND(NORXcmd); /* disable receive */ } - + if (dev->irq) { irq2dev_map[dev->irq] = NULL; free_irq(dev->irq,NULL); } - + if (dev->base_addr) release_region(dev->base_addr,ARCNET_TOTAL_SIZE); unregister_netdev(dev); kfree(dev->priv); dev->priv = NULL; - + /* Decrease use count of arcnet.o */ arcnet_use_count(0); } + #else __initfunc(void com20020_setup (char *str, int *ints)) @@ -1095,9 +1051,9 @@ MAX_ARCNET_DEVS); return; } - + dev=&arcnet_devs[arcnet_num_devs]; - + if (ints[0] < 1) { printk("com20020: You must give an IO address.\n"); @@ -1126,19 +1082,16 @@ case 2: /* IRQ */ dev->irq=ints[2]; - + case 1: /* IO address */ dev->base_addr=ints[1]; } dev->name = (char *)&arcnet_dev_names[arcnet_num_devs]; - + if (str) strncpy(dev->name, str, 9); - + arcnet_num_devs++; } #endif /* MODULE */ - - - diff -u --recursive --new-file v2.1.53/linux/drivers/net/com90io.c linux/drivers/net/com90io.c --- v2.1.53/linux/drivers/net/com90io.c Thu Sep 4 17:07:30 1997 +++ linux/drivers/net/com90io.c Sat Sep 6 10:05:42 1997 @@ -1,11 +1,12 @@ -/* com90io.c: +/* $Id: com90io.c,v 1.2 1997/09/05 08:57:52 mj Exp $ + Written 1997 by David Woodhouse Derived from the original arcnet.c, Written 1994-1996 by Avery Pennarun, which was in turn derived from skeleton.c by Donald Becker. - Contact Avery at: apenwarr@foxnet.net or + Contact Avery at: apenwarr@bond.net or RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9 ********************** @@ -59,36 +60,6 @@ #include - - - -/* External functions from arcnet.c */ - - - -#if ARCNET_DEBUG_MAX & D_SKB -extern void arcnet_dump_skb(struct device *dev,struct sk_buff *skb, - char *desc); -#else -#define arcnet_dump_skb(dev,skb,desc) ; -#endif - -#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX) -extern void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext, - char *desc); -#else -#define arcnet_dump_packet(dev,buffer,ext,desc) ; -#endif -extern void arcnet_tx_done(struct device *dev, struct arcnet_local *lp); -extern void arcnet_makename(char *device); -extern void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs); -extern void arcnet_setup(struct device *dev); -extern int arcnet_go_tx(struct device *dev,int enable_irq); -extern void arcnetA_continue_tx(struct device *dev); -extern void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr); -extern void arcnet_use_count(int open); - - /* Internal function declarations */ static int arc90io_probe(struct device *dev); @@ -127,13 +98,12 @@ #endif - /* Handy defines for ARCnet specific stuff */ -/* The number of low I/O ports used by the ethercard. */ +/* The number of low I/O ports used by the card. */ #define ARCNET_TOTAL_SIZE 16 - /* COM 9026 controller chip --> ARCnet register addresses */ +/* COM 9026 controller chip --> ARCnet register addresses */ #define _INTMASK (ioaddr+0) /* writable */ #define _STATUS (ioaddr+0) /* readable */ #define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */ @@ -149,7 +119,6 @@ #define ARCRESET inb(_RESET) - #define SETCONF outb((lp->config),_CONFIG) @@ -163,7 +132,7 @@ { int ioaddr=dev->base_addr; - outb(offset >> 8, _ADDR_HI); + outb(offset >> 8, _ADDR_HI); outb(offset & 0xff, _ADDR_LO); return inb(_MEMDATA); @@ -173,7 +142,7 @@ { int ioaddr=dev->base_addr; - outb(offset >> 8, _ADDR_HI); + outb(offset >> 8, _ADDR_HI); outb(offset & 0xff, _ADDR_LO); outb(datum, _MEMDATA); @@ -204,7 +173,7 @@ outb( (offset >> 8) | AUTOINCflag, _ADDR_HI); outb( offset & 0xff, _ADDR_LO); - + while (length--) #ifdef ONE_AT_A_TIME_TX put_buffer_byte(dev,offset++,*(dest++)); @@ -217,14 +186,13 @@ static const char *version = "com90io.c: v2.91 97/08/19 Avery Pennarun et al.\n"; + /**************************************************************************** * * * Probe and initialization * * * ****************************************************************************/ - - /* We cannot probe for an IO mapped card either, although we can check that * it's where we were told it was, and even autoirq */ @@ -233,104 +201,100 @@ { int ioaddr=dev->base_addr,status,delayval; unsigned long airqmask; - + BUGLVL(D_NORMAL) printk(version); - + if (ioaddr<0x200) { BUGMSG(D_NORMAL,"No autoprobe for IO mapped cards; you " "must specify the base address!\n"); return -ENODEV; } - + if (check_region(ioaddr, ARCNET_TOTAL_SIZE)) { BUGMSG(D_INIT_REASONS,"IO check_region %x-%x failed.\n", ioaddr,ioaddr+ARCNET_TOTAL_SIZE-1); return -ENXIO; } - + if (ARCSTATUS == 0xFF) { BUGMSG(D_INIT_REASONS,"IO address %x empty\n",ioaddr); return -ENODEV; } - + ARCRESET; JIFFER(RESETtime); - + status=ARCSTATUS; - + if ((status & 0x9D) != (NORXflag|RECONflag|TXFREEflag|RESETflag)) { BUGMSG(D_INIT_REASONS,"Status invalid (%Xh).\n",status); return -ENODEV; } - - + BUGMSG(D_INIT_REASONS,"Status after reset: %X\n",status); - - + ACOMMAND(CFLAGScmd|RESETclear|CONFIGclear); - + BUGMSG(D_INIT_REASONS,"Status after reset acknowledged: %X\n",status); - + status=ARCSTATUS; - + if (status & RESETflag) { BUGMSG(D_INIT_REASONS,"Eternal reset (status=%Xh)\n",status); return -ENODEV; } - + outb((0x16 | IOMAPflag) &~ENABLE16flag, _CONFIG); - - + /* Read first loc'n of memory */ - + outb(AUTOINCflag ,_ADDR_HI); outb(0,_ADDR_LO); - + if ((status=inb(_MEMDATA)) != 0xd1) { BUGMSG(D_INIT_REASONS,"Signature byte not found" " (%Xh instead).\n", status); return -ENODEV; } - + if (!dev->irq) { /* if we do this, we're sure to get an IRQ since the * card has just reset and the NORXflag is on until * we tell it to start receiving. */ - + airqmask = probe_irq_on(); outb(NORXflag,_INTMASK); udelay(1); outb(0,_INTMASK); dev->irq = probe_irq_off(airqmask); - + if (dev->irq<=0) { BUGMSG(D_INIT_REASONS,"Autoprobe IRQ failed\n"); return -ENODEV; } } - + return arc90io_found(dev,dev->base_addr,dev->irq); } - /* Set up the struct device associated with this card. Called after * probing succeeds. */ __initfunc(int arc90io_found(struct device *dev,int ioaddr,int airq)) { struct arcnet_local *lp; - + /* reserve the irq */ if (request_irq(airq,&arcnet_interrupt,0,"arcnet (COM90xx-IO)",NULL)) { @@ -339,17 +303,15 @@ } irq2dev_map[airq]=dev; dev->irq=airq; - + /* reserve the I/O region - guaranteed to work by check_region */ request_region(ioaddr,ARCNET_TOTAL_SIZE,"arcnet (COM90xx-IO)"); dev->base_addr=ioaddr; - - + dev->mem_start=dev->mem_end=dev->rmem_start=dev->rmem_end=(long)NULL; - - + /* Initialize the rest of the device structure. */ - + dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL); if (dev->priv == NULL) { @@ -363,7 +325,7 @@ lp=(struct arcnet_local *)(dev->priv); lp->card_type = ARC_90xx_IO; lp->card_type_str = "COM 90xx (IO)"; - + lp->arcnet_reset=arc90io_reset; lp->asetmask=arc90io_setmask; lp->astatus=arc90io_status; @@ -371,33 +333,30 @@ lp->openclose_device=arc90io_openclose; lp->prepare_tx=arc90io_prepare_tx; lp->inthandler=arc90io_inthandler; - - - /* Fill in the fields of the device structure with generic * values. */ arcnet_setup(dev); - + /* And now fill particular fields with arcnet values */ dev->mtu=1500; /* completely arbitrary - agrees with ether, though */ dev->hard_header_len=sizeof(struct ClientData); lp->sequence=1; lp->recbuf=0; - + BUGMSG(D_DURING,"ClientData header size is %d.\n", sizeof(struct ClientData)); BUGMSG(D_DURING,"HardHeader size is %d.\n", sizeof(struct archdr)); - + lp->config = (0x16 | IOMAPflag) & ~ENABLE16flag; SETCONF; - + /* get and check the station ID from offset 1 in shmem */ lp->stationid = get_buffer_byte(dev,1); - + if (!lp->stationid) BUGMSG(D_NORMAL,"WARNING! Station address 00 is reserved " "for broadcasts!\n"); @@ -405,19 +364,19 @@ BUGMSG(D_NORMAL,"WARNING! Station address FF may confuse " "DOS networking programs!\n"); dev->dev_addr[0]=lp->stationid; - + BUGMSG(D_NORMAL,"ARCnet COM90xx in IO-mapped mode: " "station %02Xh found at %03lXh, IRQ %d.\n", lp->stationid, dev->base_addr,dev->irq); - + return 0; } /**************************************************************************** * * - * Utility routines for arcnet.c * + * Utility routines * * * ****************************************************************************/ @@ -433,59 +392,59 @@ struct arcnet_local *lp=(struct arcnet_local *)dev->priv; short ioaddr=dev->base_addr; int delayval,recbuf=lp->recbuf; - + if (reset_delay==3) { ARCRESET; return 0; } - + /* no IRQ's, please! */ lp->intmask=0; SETMASK; - + BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n", dev->name,ARCSTATUS); - + /* Set the thing to IO-mapped, 8-bit mode */ lp->config = (0x1C|IOMAPflag) & ~ENABLE16flag; SETCONF; - + if (reset_delay) { /* reset the card */ ARCRESET; JIFFER(RESETtime); } - + ACOMMAND(CFLAGScmd|RESETclear); /* clear flags & end reset */ ACOMMAND(CFLAGScmd|CONFIGclear); - + /* verify that the ARCnet signature byte is present */ - + if (get_buffer_byte(dev,0) != TESTvalue) { BUGMSG(D_NORMAL,"reset failed: TESTvalue not present.\n"); return 1; } - + /* clear out status variables */ recbuf=lp->recbuf=0; lp->txbuf=2; - + /* enable extended (512-byte) packets */ ACOMMAND(CONFIGcmd|EXTconf); - + /* and enable receive of our first packet to the first buffer */ EnableReceiver(); - + /* re-enable interrupts */ lp->intmask|=NORXflag; #ifdef DETECT_RECONFIGS lp->intmask|=RECONflag; #endif SETMASK; - + /* done! return success. */ return 0; } @@ -500,11 +459,10 @@ } - static void arc90io_setmask(struct device *dev, u_char mask) { short ioaddr=dev->base_addr; - + AINTMASK(mask); } @@ -530,22 +488,18 @@ arc90io_inthandler(struct device *dev) { struct arcnet_local *lp=(struct arcnet_local *)dev->priv; - int ioaddr=dev->base_addr, status, boguscount = 3, didsomething; + int ioaddr=dev->base_addr, status, boguscount = 3, didsomething; - - - AINTMASK(0); - + BUGMSG(D_DURING,"in arc90io_inthandler (status=%Xh, intmask=%Xh)\n", ARCSTATUS,lp->intmask); - + do { status = ARCSTATUS; didsomething=0; - - + /* RESET flag was enabled - card is resetting and if RX * is disabled, it's NOT because we just got a packet. */ @@ -554,56 +508,55 @@ BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n", status); arc90io_reset(dev,0); - + /* all other flag values are just garbage */ break; } - - + /* RX is inhibited - we must have received something. */ if (status & lp->intmask & NORXflag) { int recbuf=lp->recbuf=!lp->recbuf; int oldaddr=0; - + BUGMSG(D_DURING,"receive irq (status=%Xh)\n", status); - + /* enable receive of our next packet */ EnableReceiver(); - + if (lp->intx) oldaddr=(inb(_ADDR_HI)<<8) | inb(_ADDR_LO); - - + + /* Got a packet. */ arc90io_rx(dev,!recbuf); - - + + if (lp->intx) { outb( (oldaddr >> 8), _ADDR_HI); outb( oldaddr & 0xff, _ADDR_LO); } - + didsomething++; } - + /* it can only be an xmit-done irq if we're xmitting :) */ /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/ if (status & lp->intmask & TXFREEflag) { struct Outgoing *out=&(lp->outgoing); int was_sending=lp->sending; - + lp->intmask &= ~TXFREEflag; - + lp->in_txhandler++; if (was_sending) lp->sending--; - + BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n", status,out->numsegs,out->segnum,out->skb); - + if (was_sending && !(status&TXACKflag)) { if (lp->lasttrans_dest != 0) @@ -620,11 +573,11 @@ lp->lasttrans_dest); } } - + /* send packet if there is one */ arcnet_go_tx(dev,0); didsomething++; - + if (lp->intx) { BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n", @@ -632,24 +585,24 @@ lp->in_txhandler--; continue; } - + if (!lp->outgoing.skb) { BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n"); - + /* inform upper layers */ if (!lp->txready) arcnet_tx_done(dev, lp); lp->in_txhandler--; continue; } - + /* if more than one segment, and not all segments * are done, then continue xmit. */ if (out->segnumnumsegs) arcnetA_continue_tx(dev); arcnet_go_tx(dev,0); - + /* if segnum==numsegs, the transmission is finished; * free the skb. */ @@ -663,12 +616,12 @@ dev_kfree_skb(out->skb,FREE_WRITE); } out->skb=NULL; - + /* inform upper layers */ if (!lp->txready) arcnet_tx_done(dev, lp); } didsomething++; - + lp->in_txhandler--; } else if (lp->txready && !lp->sending && !lp->intx) @@ -678,21 +631,19 @@ arcnet_go_tx(dev,0); didsomething++; } - - + #ifdef DETECT_RECONFIGS if (status & (lp->intmask) & RECONflag) { ACOMMAND(CFLAGScmd|CONFIGclear); lp->stats.tx_carrier_errors++; - + #ifdef SHOW_RECONFIGS - BUGMSG(D_NORMAL,"Network reconfiguration detected" " (status=%Xh, config=%X)\n", status,lp->config); #endif /* SHOW_RECONFIGS */ - + #ifdef RECON_THRESHOLD /* is the RECON info empty or old? */ if (!lp->first_recon || !lp->last_recon || @@ -702,19 +653,19 @@ BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n"); lp->first_recon=lp->last_recon=jiffies; lp->num_recons=lp->network_down=0; - + BUGMSG(D_DURING,"recon: clearing counters.\n"); } else /* add to current RECON counter */ { lp->last_recon=jiffies; lp->num_recons++; - + BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n", lp->num_recons, (lp->last_recon-lp->first_recon)/HZ, lp->network_down); - + /* if network is marked up; * and first_recon and last_recon are 60+ sec * apart; @@ -746,26 +697,24 @@ BUGMSG(D_NORMAL,"cabling restored?\n"); lp->first_recon=lp->last_recon=0; lp->num_recons=lp->network_down=0; - + BUGMSG(D_DURING,"not recon: clearing counters anyway.\n"); #endif } #endif /* DETECT_RECONFIGS */ } while (--boguscount && didsomething); - + BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n", ARCSTATUS,boguscount); BUGMSG(D_DURING,"\n"); - + SETMASK; /* put back interrupt mask */ - } - /* A packet has arrived; grab it from the buffers and pass it to the generic * arcnet_rx routing to deal with it. - */ + */ static void arc90io_rx(struct device *dev,int recbuf) @@ -777,13 +726,13 @@ u_char *arcsoft; short length,offset; u_char daddr,saddr; - + lp->stats.rx_packets++; - + get_whole_buffer(dev,recbuf*512,4,(char *)arcpacket); - + saddr=arcpacket->hardheader.source; - + /* if source is 0, it's a "used" packet! */ if (saddr==0) { @@ -793,13 +742,13 @@ return; } /* Set source address to zero to mark it as old */ - + put_buffer_byte(dev,recbuf*512,0); - + arcpacket->hardheader.source=0; - + daddr=arcpacket->hardheader.destination; - + if (arcpacket->hardheader.offset1) /* Normal Packet */ { offset=arcpacket->hardheader.offset1; @@ -812,16 +761,15 @@ arcsoft=&arcpacket->raw[offset]; length=512-offset; } - + get_whole_buffer(dev,recbuf*512+offset,length,(char *)arcpacket+offset); - + arcnet_rx(lp, arcsoft, length, saddr, daddr); - + BUGLVL(D_RX) arcnet_dump_packet(lp->adev,arcpacket->raw,length>240,"rx"); } - /* Given an skb, copy a packet into the ARCnet buffers for later transmission * by arcnet_go_tx. */ @@ -830,20 +778,20 @@ char *data,int length,int daddr,int exceptA, int offset) { struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - + lp->txbuf=lp->txbuf^1; /* XOR with 1 to alternate between 2 and 3 */ - + length+=hdrlen; - + BUGMSG(D_TX,"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n", hdr,length,data); - + put_buffer_byte(dev, lp->txbuf*512+1, daddr); /* load packet into shared memory */ if (length<=MTU) /* Normal (256-byte) Packet */ put_buffer_byte(dev, lp->txbuf*512+2, offset=offset?offset:256-length); - + else if (length>=MinTU || offset) /* Extended (512-byte) Packet */ { put_buffer_byte(dev, lp->txbuf*512+2, 0); @@ -853,36 +801,36 @@ { put_buffer_byte(dev, lp->txbuf*512+2, 0); put_buffer_byte(dev, lp->txbuf*512+3, offset=512-length-4); - + /* exception-specific stuff - these four bytes * make the packet long enough to fit in a 512-byte * frame. */ - + put_whole_buffer(dev, lp->txbuf*512+offset,4,"\0\0xff\0xff\0xff"); offset+=4; } else /* "other" Exception packet */ { /* RFC1051 - set 4 trailing bytes to 0 */ - + put_whole_buffer(dev,lp->txbuf*512+508,4,"\0\0\0\0"); - + /* now round up to MinTU */ put_buffer_byte(dev, lp->txbuf*512+2, 0); put_buffer_byte(dev, lp->txbuf*512+3, offset=512-MinTU); } - + /* copy the packet into ARCnet shmem * - the first bytes of ClientData header are skipped */ - + put_whole_buffer(dev, 512*lp->txbuf+offset, hdrlen,(u_char *)hdr); put_whole_buffer(dev, 512*lp->txbuf+offset+hdrlen,length-hdrlen,data); - + BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n", daddr,length); - + lp->lastload_dest=daddr; lp->txready=lp->txbuf; /* packet is ready for sending */ } @@ -904,13 +852,13 @@ int init_module(void) { struct device *dev=cards[0]; - + cards[0]=dev=(struct device *)kmalloc(sizeof(struct device), GFP_KERNEL); if (!dev) return -ENOMEM; - + memset(dev, 0, sizeof(struct device)); - + dev->name=(char *)kmalloc(9, GFP_KERNEL); if (!dev->name) { @@ -918,19 +866,19 @@ return -ENOMEM; } dev->init=arc90io_probe; - + if (device) strcpy(dev->name,device); else arcnet_makename(dev->name); dev->base_addr=io; dev->irq=irq; - + if (dev->irq==2) dev->irq=9; - + if (register_netdev(dev) != 0) return -EIO; - + /* Increase use count of arcnet.o */ arcnet_use_count(1); return 0; @@ -940,9 +888,9 @@ { struct device *dev=cards[0]; int ioaddr=dev->base_addr; - + if (dev->start) (*dev->stop)(dev); - + /* Flush TX and disable RX */ if (ioaddr) { @@ -954,23 +902,23 @@ driver is loaded later */ outb( (inb(_CONFIG)&~IOMAPflag),_CONFIG); } - + if (dev->irq) { irq2dev_map[dev->irq] = NULL; free_irq(dev->irq,NULL); } - + if (dev->base_addr) release_region(dev->base_addr,ARCNET_TOTAL_SIZE); unregister_netdev(dev); kfree(dev->priv); dev->priv = NULL; - + /* Decrease use count of arcnet.o */ arcnet_use_count(0); } -#else +#else __initfunc(void com90io_setup (char *str, int *ints)) { @@ -982,9 +930,9 @@ MAX_ARCNET_DEVS); return; } - + dev=&arcnet_devs[arcnet_num_devs]; - + if (ints[0] < 1) { printk("com90xx IO-MAP: You must give an IO address.\n"); @@ -1000,20 +948,17 @@ case 2: /* IRQ */ dev->irq=ints[2]; - + case 1: /* IO address */ dev->base_addr=ints[1]; } dev->name = (char *)&arcnet_dev_names[arcnet_num_devs]; - + if (str) strncpy(dev->name, str, 9); - + arcnet_num_devs++; } #endif /* MODULE */ - - - diff -u --recursive --new-file v2.1.53/linux/drivers/net/com90xx.c linux/drivers/net/com90xx.c --- v2.1.53/linux/drivers/net/com90xx.c Thu Sep 4 17:07:30 1997 +++ linux/drivers/net/com90xx.c Sat Sep 6 10:05:42 1997 @@ -1,9 +1,10 @@ -/* com90xx.c: +/* $Id: com90xx.c,v 1.3 1997/09/05 18:27:23 mj Exp $ + Derived from the original arcnet.c, Written 1994-1996 by Avery Pennarun, which was in turn derived from skeleton.c by Donald Becker. - Contact Avery at: apenwarr@foxnet.net or + Contact Avery at: apenwarr@bond.net or RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9 ********************** @@ -90,47 +91,13 @@ #undef FAST_PROBE - - - - -/* External functions from arcnet.c */ - - - -#if ARCNET_DEBUG_MAX & D_SKB -extern void arcnet_dump_skb(struct device *dev,struct sk_buff *skb, - char *desc); -#else -#define arcnet_dump_skb(dev,skb,desc) ; -#endif - -#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX) -extern void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext, - char *desc); -#else -#define arcnet_dump_packet(dev,buffer,ext,desc) ; -#endif - - -extern void arcnet_tx_done(struct device *dev, struct arcnet_local *lp); -extern void arcnet_makename(char *device); -extern void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs); -extern void arcnet_setup(struct device *dev); -extern int arcnet_go_tx(struct device *dev,int enable_irq); -extern void arcnetA_continue_tx(struct device *dev); -extern void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr); -extern void arcnet_use_count(int open); - - - /* Internal function declarations */ -#ifdef MODULE -static +#ifdef MODULE +static #endif int arc90xx_probe(struct device *dev); static void arc90xx_rx(struct device *dev,int recbuf); -static int arc90xx_found(struct device *dev,int ioaddr,int airq,u_long shmem); +static int arc90xx_found(struct device *dev,int ioaddr,int airq,u_long shmem,int more); static void arc90xx_inthandler (struct device *dev); static int arc90xx_reset (struct device *dev, int reset_delay); static void arc90xx_setmask (struct device *dev, u_char mask); @@ -160,18 +127,15 @@ extern struct device arcnet_devs[]; extern char arcnet_dev_names[][10]; extern int arcnet_num_devs; - #endif - - /* Handy defines for ARCnet specific stuff */ -/* The number of low I/O ports used by the ethercard. */ +/* The number of low I/O ports used by the card. */ #define ARCNET_TOTAL_SIZE 16 - /* COM 9026 controller chip --> ARCnet register addresses */ +/* COM 9026 controller chip --> ARCnet register addresses */ #define _INTMASK (ioaddr+0) /* writable */ #define _STATUS (ioaddr+0) /* readable */ #define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */ @@ -183,14 +147,14 @@ #define RDDATAflag 0x00 /* Next access is a read/~write */ - #define ARCSTATUS inb(_STATUS) - #define ACOMMAND(cmd) outb((cmd),_COMMAND) - #define AINTMASK(msk) outb((msk),_INTMASK) - #define SETCONF outb(lp->config,_CONFIG) - #define ARCRESET inb(_RESET) +#define ARCSTATUS inb(_STATUS) +#define ACOMMAND(cmd) outb((cmd),_COMMAND) +#define AINTMASK(msk) outb((msk),_INTMASK) +#define SETCONF outb(lp->config,_CONFIG) +#define ARCRESET inb(_RESET) static const char *version = - "com90xx.c: v2.91 97/08/19 Avery Pennarun et al.\n"; + "com90xx.c: v2.92 97/09/02 Avery Pennarun et al.\n"; /**************************************************************************** @@ -220,32 +184,28 @@ static int init_once = 0; static int numports=sizeof(ports)/sizeof(ports[0]), numshmems=sizeof(shmems)/sizeof(shmems[0]); - int count,status,delayval,ioaddr,numprint,airq,retval=-ENODEV, openparen=0; unsigned long airqmask; int *port; u_long *shmem; - + if (!init_once) { for (count=0x200; count<=0x3f0; count+=16) ports[(count-0x200)/16] = count; for (count=0xA0000; count<=0xFF800; count+=2048) shmems[(count-0xA0000)/2048] = count; - init_once=1; - } - - BUGLVL(D_NORMAL) printk(version); - BUGMSG(D_DURING,"space used for probe buffers: %d+%d=%d bytes\n", + BUGLVL(D_NORMAL) printk(version); + BUGMSG(D_DURING,"space used for probe buffers: %d+%d=%d bytes\n", sizeof(ports),sizeof(shmems), sizeof(ports)+sizeof(shmems)); - - - + } + init_once++; + BUGMSG(D_INIT,"given: base %lXh, IRQ %d, shmem %lXh\n", dev->base_addr,dev->irq,dev->mem_start); - + if (dev->base_addr > 0x1ff) /* Check a single specified port */ { ports[0]=dev->base_addr; @@ -253,17 +213,16 @@ } else if (dev->base_addr > 0) /* Don't probe at all. */ return -ENXIO; - + if (dev->mem_start) { shmems[0]=dev->mem_start; numshmems=1; } - - + /* Stage 1: abandon any reserved ports, or ones with status==0xFF - * (empty), and reset any others by reading the reset port. - */ + * (empty), and reset any others by reading the reset port. + */ BUGMSG(D_INIT,"Stage 1: "); numprint=0; for (port = &ports[0]; port-ports8) - { - BUGMSG2(D_INIT,"\n"); - BUGMSG(D_INIT,"Stage 2: "); - numprint=1; - } - BUGMSG2(D_INIT,"%Xh ",*port); - } - BUGMSG2(D_INIT,"\n"); - JIFFER(RESETtime); - - - /* Stage 3: abandon any shmem addresses that don't have the signature - * 0xD1 byte in the right place, or are read-only. - */ - BUGMSG(D_INIT,"Stage 3: "); - numprint=0; - for (shmem = &shmems[0]; shmem-shmems8) - { - BUGMSG2(D_INIT,"\n"); - BUGMSG(D_INIT,"Stage 3: "); - numprint=1; - } - BUGMSG2(D_INIT,"%lXh ",*shmem); - - ptr=(u_long)(*shmem); - - if (readb(ptr) != TESTvalue) - { - BUGMSG2(D_INIT_REASONS,"(mem=%02Xh, not %02Xh)\n", - readb(ptr),TESTvalue); - BUGMSG(D_INIT_REASONS,"Stage 3: "); - BUGLVL(D_INIT_REASONS) numprint=0; - *shmem=shmems[numshmems-1]; - numshmems--; - shmem--; - continue; - } - - /* By writing 0x42 to the TESTvalue location, we also make - * sure no "mirror" shmem areas show up - if they occur - * in another pass through this loop, they will be discarded - * because *cptr != TESTvalue. - */ - writeb(0x42,ptr); - if (readb(ptr) != 0x42) - { - BUGMSG2(D_INIT_REASONS,"(read only)\n"); - BUGMSG(D_INIT_REASONS,"Stage 3: "); - *shmem=shmems[numshmems-1]; - numshmems--; - shmem--; - continue; - } - - BUGMSG2(D_INIT_REASONS,"\n"); - BUGMSG(D_INIT_REASONS,"Stage 3: "); - BUGLVL(D_INIT_REASONS) numprint=0; - } - BUGMSG2(D_INIT,"\n"); - - if (!numshmems) - { - BUGMSG(D_NORMAL,"Stage 3: No ARCnet cards found.\n"); - return -ENODEV; - } - - /* Stage 4: something of a dummy, to report the shmems that are - * still possible after stage 3. - */ - BUGMSG(D_INIT,"Stage 4: "); - numprint=0; - for (shmem = &shmems[0]; shmem-shmems8) - { - BUGMSG2(D_INIT,"\n"); - BUGMSG(D_INIT,"Stage 4: "); - numprint=1; - } - BUGMSG2(D_INIT,"%lXh ",*shmem); - } - BUGMSG2(D_INIT,"\n"); - - - /* Stage 5: for any ports that have the correct status, can disable - * the RESET flag, and (if no irq is given) generate an autoirq, - * register an ARCnet device. - * - * Currently, we can only register one device per probe, so quit - * after the first one is found. - */ - BUGMSG(D_INIT,"Stage 5: "); - numprint=0; - for (port = &ports[0]; port-ports8) - { - BUGMSG2(D_INIT,"\n"); - BUGMSG(D_INIT,"Stage 5: "); - numprint=1; - } - BUGMSG2(D_INIT,"%Xh ",*port); - - ioaddr=*port; - status=ARCSTATUS; - - if ((status & 0x9D) - != (NORXflag|RECONflag|TXFREEflag|RESETflag)) - { - BUGMSG2(D_INIT_REASONS,"(status=%Xh)\n",status); - BUGMSG(D_INIT_REASONS,"Stage 5: "); - BUGLVL(D_INIT_REASONS) numprint=0; - *port=ports[numports-1]; - numports--; - port--; - continue; - } - - ACOMMAND(CFLAGScmd|RESETclear|CONFIGclear); - status=ARCSTATUS; - if (status & RESETflag) - { - BUGMSG2(D_INIT_REASONS," (eternal reset, status=%Xh)\n", - status); - BUGMSG(D_INIT_REASONS,"Stage 5: "); - BUGLVL(D_INIT_REASONS) numprint=0; - *port=ports[numports-1]; - numports--; - port--; - continue; - } - - /* skip this completely if an IRQ was given, because maybe - * we're on a machine that locks during autoirq! - */ - if (!dev->irq) - { - /* if we do this, we're sure to get an IRQ since the - * card has just reset and the NORXflag is on until - * we tell it to start receiving. - */ - airqmask = probe_irq_on(); - AINTMASK(NORXflag); - udelay(1); - AINTMASK(0); - airq = probe_irq_off(airqmask); - - if (airq<=0) - { - BUGMSG2(D_INIT_REASONS,"(airq=%d)\n",airq); - BUGMSG(D_INIT_REASONS,"Stage 5: "); - BUGLVL(D_INIT_REASONS) numprint=0; - *port=ports[numports-1]; - numports--; - port--; - continue; - } - } - else - { - airq=dev->irq; - } - - BUGMSG2(D_INIT,"(%d,", airq); - openparen=1; - - /* Everything seems okay. But which shmem, if any, puts - * back its signature byte when the card is reset? - * - * If there are multiple cards installed, there might be - * multiple shmems still in the list. - */ + BUGMSG(D_INIT,"Stage 2: "); + numprint=0; + for (port = &ports[0]; port-ports8) + { + BUGMSG2(D_INIT,"\n"); + BUGMSG(D_INIT,"Stage 2: "); + numprint=1; + } + BUGMSG2(D_INIT,"%Xh ",*port); + } + BUGMSG2(D_INIT,"\n"); + JIFFER(RESETtime); + + /* Stage 3: abandon any shmem addresses that don't have the signature + * 0xD1 byte in the right place, or are read-only. + */ + BUGMSG(D_INIT,"Stage 3: "); + numprint=0; + for (shmem = &shmems[0]; shmem-shmems8) + { + BUGMSG2(D_INIT,"\n"); + BUGMSG(D_INIT,"Stage 3: "); + numprint=1; + } + BUGMSG2(D_INIT,"%lXh ",*shmem); + + ptr=(u_long)(*shmem); + + if (readb(ptr) != TESTvalue) + { + BUGMSG2(D_INIT_REASONS,"(mem=%02Xh, not %02Xh)\n", + readb(ptr),TESTvalue); + BUGMSG(D_INIT_REASONS,"Stage 3: "); + BUGLVL(D_INIT_REASONS) numprint=0; + *shmem=shmems[numshmems-1]; + numshmems--; + shmem--; + continue; + } + + /* By writing 0x42 to the TESTvalue location, we also make + * sure no "mirror" shmem areas show up - if they occur + * in another pass through this loop, they will be discarded + * because *cptr != TESTvalue. + */ + writeb(0x42,ptr); + if (readb(ptr) != 0x42) + { + BUGMSG2(D_INIT_REASONS,"(read only)\n"); + BUGMSG(D_INIT_REASONS,"Stage 3: "); + *shmem=shmems[numshmems-1]; + numshmems--; + shmem--; + continue; + } + + BUGMSG2(D_INIT_REASONS,"\n"); + BUGMSG(D_INIT_REASONS,"Stage 3: "); + BUGLVL(D_INIT_REASONS) numprint=0; + } + BUGMSG2(D_INIT,"\n"); + + if (!numshmems) + { + BUGMSG(D_NORMAL,"Stage 3: No ARCnet cards found.\n"); + return -ENODEV; + } + + /* Stage 4: something of a dummy, to report the shmems that are + * still possible after stage 3. + */ + BUGMSG(D_INIT,"Stage 4: "); + numprint=0; + for (shmem = &shmems[0]; shmem-shmems8) + { + BUGMSG2(D_INIT,"\n"); + BUGMSG(D_INIT,"Stage 4: "); + numprint=1; + } + BUGMSG2(D_INIT,"%lXh ",*shmem); + } + BUGMSG2(D_INIT,"\n"); + + /* Stage 5: for any ports that have the correct status, can disable + * the RESET flag, and (if no irq is given) generate an autoirq, + * register an ARCnet device. + * + * Currently, we can only register one device per probe, so quit + * after the first one is found. + */ + BUGMSG(D_INIT,"Stage 5: "); + numprint=0; + for (port = &ports[0]; port-ports8) + { + BUGMSG2(D_INIT,"\n"); + BUGMSG(D_INIT,"Stage 5: "); + numprint=1; + } + BUGMSG2(D_INIT,"%Xh ",*port); + + ioaddr=*port; + status=ARCSTATUS; + + if ((status & 0x9D) + != (NORXflag|RECONflag|TXFREEflag|RESETflag)) + { + BUGMSG2(D_INIT_REASONS,"(status=%Xh)\n",status); + BUGMSG(D_INIT_REASONS,"Stage 5: "); + BUGLVL(D_INIT_REASONS) numprint=0; + *port=ports[numports-1]; + numports--; + port--; + continue; + } + + ACOMMAND(CFLAGScmd|RESETclear|CONFIGclear); + status=ARCSTATUS; + if (status & RESETflag) + { + BUGMSG2(D_INIT_REASONS," (eternal reset, status=%Xh)\n", + status); + BUGMSG(D_INIT_REASONS,"Stage 5: "); + BUGLVL(D_INIT_REASONS) numprint=0; + *port=ports[numports-1]; + numports--; + port--; + continue; + } + + /* skip this completely if an IRQ was given, because maybe + * we're on a machine that locks during autoirq! + */ + if (!dev->irq) + { + /* if we do this, we're sure to get an IRQ since the + * card has just reset and the NORXflag is on until + * we tell it to start receiving. + */ + airqmask = probe_irq_on(); + AINTMASK(NORXflag); + udelay(1); + AINTMASK(0); + airq = probe_irq_off(airqmask); + + if (airq<=0) + { + BUGMSG2(D_INIT_REASONS,"(airq=%d)\n",airq); + BUGMSG(D_INIT_REASONS,"Stage 5: "); + BUGLVL(D_INIT_REASONS) numprint=0; + *port=ports[numports-1]; + numports--; + port--; + continue; + } + } + else + { + airq=dev->irq; + } + + BUGMSG2(D_INIT,"(%d,", airq); + openparen=1; + + /* Everything seems okay. But which shmem, if any, puts + * back its signature byte when the card is reset? + * + * If there are multiple cards installed, there might be + * multiple shmems still in the list. + */ #ifdef FAST_PROBE - if (numports>1 || numshmems>1) - { - ARCRESET; - JIFFER(RESETtime); - } - else - { - /* just one shmem and port, assume they match */ - writeb(TESTvalue,shmems[0]); - } + if (numports>1 || numshmems>1) + { + ARCRESET; + JIFFER(RESETtime); + } + else + { + /* just one shmem and port, assume they match */ + writeb(TESTvalue,shmems[0]); + } #else - ARCRESET; - JIFFER(RESETtime); + ARCRESET; + JIFFER(RESETtime); #endif - - - for (shmem = &shmems[0]; shmem-shmems 1) + probe_more = numshmems - 1; + else + probe_more = 0; + retval=arc90xx_found(dev,*port,airq,*shmem,probe_more); + if (retval) openparen=0; + + /* remove shmem from the list */ + *shmem=shmems[numshmems-1]; + numshmems--; + + break; + } + else + { + BUGMSG2(D_INIT_REASONS,"%Xh-", readb(ptr)); + } + } + + if (openparen) + { + BUGMSG2(D_INIT,"no matching shmem)\n"); + BUGMSG(D_INIT_REASONS,"Stage 5: "); + BUGLVL(D_INIT_REASONS) numprint=0; + } + + *port=ports[numports-1]; + numports--; + port--; + + if (!retval) break; + } + BUGMSG(D_INIT_REASONS,"\n"); + + /* Now put back TESTvalue on all leftover shmems. + */ + for (shmem = &shmems[0]; shmem-shmemsirq=airq; - - + /* reserve the I/O region - guaranteed to work by check_region */ request_region(ioaddr,ARCNET_TOTAL_SIZE,"arcnet (90xx)"); dev->base_addr=ioaddr; - + /* find the real shared memory start/end points, including mirrors */ #define BUFFER_SIZE (512) #define MIRROR_SIZE (BUFFER_SIZE*4) - + /* guess the actual size of one "memory mirror" - the number of - * bytes between copies of the shared memory. On most cards, it's - * 2k (or there are no mirrors at all) but on some, it's 4k. - */ + * bytes between copies of the shared memory. On most cards, it's + * 2k (or there are no mirrors at all) but on some, it's 4k. + */ mirror_size=MIRROR_SIZE; if (readb(shmem)==TESTvalue && readb(shmem-mirror_size)!=TESTvalue && readb(shmem-2*mirror_size)==TESTvalue) mirror_size*=2; - + first_mirror=last_mirror=shmem; while (readb(first_mirror)==TESTvalue) first_mirror-=mirror_size; first_mirror+=mirror_size; - + while (readb(last_mirror)==TESTvalue) last_mirror+=mirror_size; last_mirror-=mirror_size; - + dev->mem_start=first_mirror; dev->mem_end=last_mirror+MIRROR_SIZE-1; dev->rmem_start=dev->mem_start+BUFFER_SIZE*0; dev->rmem_end=dev->mem_start+BUFFER_SIZE*2-1; - - /* Initialize the rest of the device structure. */ - + + /* Initialize the rest of the device structure. */ + dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL); if (dev->priv == NULL) { @@ -642,27 +601,26 @@ lp->openclose_device=arc90xx_openclose; lp->prepare_tx=arc90xx_prepare_tx; lp->inthandler=arc90xx_inthandler; - - + /* Fill in the fields of the device structure with generic * values. */ arcnet_setup(dev); - + /* And now fill particular fields with arcnet values */ dev->mtu=1500; /* completely arbitrary - agrees with ether, though */ dev->hard_header_len=sizeof(struct ClientData); lp->sequence=1; lp->recbuf=0; - + BUGMSG(D_DURING,"ClientData header size is %d.\n", sizeof(struct ClientData)); BUGMSG(D_DURING,"HardHeader size is %d.\n", sizeof(struct archdr)); - + /* get and check the station ID from offset 1 in shmem */ lp->stationid = readb(first_mirror+1); - + if (lp->stationid==0) BUGMSG(D_NORMAL,"WARNING! Station address 00 is reserved " "for broadcasts!\n"); @@ -670,53 +628,35 @@ BUGMSG(D_NORMAL,"WARNING! Station address FF may confuse " "DOS networking programs!\n"); dev->dev_addr[0]=lp->stationid; - + BUGMSG(D_NORMAL,"ARCnet COM90xx: station %02Xh found at %03lXh, IRQ %d, " "ShMem %lXh (%ld*%xh).\n", lp->stationid, dev->base_addr, dev->irq, dev->mem_start, (dev->mem_end-dev->mem_start+1)/mirror_size,mirror_size); -#ifdef CONFIG_ARCNET_COM90xx - /* OK. We're finished. Now do we need to probe for other cards? */ + /* OK. We're finished. If there are probably other cards, add other + * COM90xx drivers to the device chain, so they get probed later. + */ - if (!com90xx_explicit) +#ifndef MODULE + while (!com90xx_explicit && more--) { - /* We need to check whether there's another card here. - * Just add another COM90xx driver to the device chain. - */ - if (arcnet_num_devs < MAX_ARCNET_DEVS) { arcnet_devs[arcnet_num_devs].next=dev->next; dev->next=&arcnet_devs[arcnet_num_devs]; - dev->next->name=(char *)&arcnet_dev_names[arcnet_num_devs]; + dev=dev->next; + dev->name=(char *)&arcnet_dev_names[arcnet_num_devs]; arcnet_num_devs++; } else { - while (dev->next) dev=dev->next; - - dev->next=kmalloc(sizeof(struct device), GFP_KERNEL); - if (!dev->next) - { - BUGMSG(D_NORMAL, "No memory for allocating next device - no more " - "will be probed for.\n"); - return 0; - } - memset(dev->next,0,sizeof(struct device)); - dev->next->name=kmalloc(10, GFP_KERNEL); - if (!dev->next->name) - { - BUGMSG(D_NORMAL, "No memory for allocating next device - no more " - "will be probed for.\n"); - kfree(dev->next); - dev->next=NULL; - return 0; - } + BUGMSG(D_NORMAL, "Too many arcnet devices - no more will be probed for.\n"); + return 0; } - arcnet_makename(dev->next->name); - dev->next->init=arc90xx_probe; + arcnet_makename(dev->name); + dev->init=arc90xx_probe; } #endif @@ -724,7 +664,6 @@ } - /* Do a hardware reset on the card, and set up necessary registers. * * This should be called as little as possible, because it disrupts the @@ -734,67 +673,68 @@ */ int arc90xx_reset(struct device *dev,int reset_delay) { - struct arcnet_local *lp=(struct arcnet_local *)dev->priv; - short ioaddr=dev->base_addr; - int delayval,recbuf=lp->recbuf; + struct arcnet_local *lp=(struct arcnet_local *)dev->priv; + short ioaddr=dev->base_addr; + int delayval,recbuf=lp->recbuf; if (reset_delay==3) { ARCRESET; return 0; } - - /* no IRQ's, please! */ - lp->intmask=0; - SETMASK; - BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n", - dev->name,ARCSTATUS); + /* no IRQ's, please! */ + lp->intmask=0; + SETMASK; - if (reset_delay) - { - /* reset the card */ - ARCRESET; - JIFFER(RESETtime); - } + BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n", + dev->name,ARCSTATUS); + + if (reset_delay) + { + /* reset the card */ + ARCRESET; + JIFFER(RESETtime); + } - ACOMMAND(CFLAGScmd|RESETclear); /* clear flags & end reset */ - ACOMMAND(CFLAGScmd|CONFIGclear); + ACOMMAND(CFLAGScmd|RESETclear); /* clear flags & end reset */ + ACOMMAND(CFLAGScmd|CONFIGclear); - /* verify that the ARCnet signature byte is present */ - if (readb(dev->mem_start) != TESTvalue) - { - BUGMSG(D_NORMAL,"reset failed: TESTvalue not present.\n"); - return 1; - } + /* verify that the ARCnet signature byte is present */ + if (readb(dev->mem_start) != TESTvalue) + { + BUGMSG(D_NORMAL,"reset failed: TESTvalue not present.\n"); + return 1; + } - /* clear out status variables */ - recbuf=lp->recbuf=0; - lp->txbuf=2; + /* clear out status variables */ + recbuf=lp->recbuf=0; + lp->txbuf=2; - /* enable extended (512-byte) packets */ - ACOMMAND(CONFIGcmd|EXTconf); + /* enable extended (512-byte) packets */ + ACOMMAND(CONFIGcmd|EXTconf); #ifndef SLOW_XMIT_COPY - /* clean out all the memory to make debugging make more sense :) */ - BUGLVL(D_DURING) - memset_io(dev->mem_start,0x42,2048); + /* clean out all the memory to make debugging make more sense :) */ + BUGLVL(D_DURING) + memset_io(dev->mem_start,0x42,2048); #endif - /* and enable receive of our first packet to the first buffer */ - EnableReceiver(); + /* and enable receive of our first packet to the first buffer */ + EnableReceiver(); - /* re-enable interrupts */ - lp->intmask|=NORXflag; + /* re-enable interrupts */ + lp->intmask|=NORXflag; #ifdef DETECT_RECONFIGS - lp->intmask|=RECONflag; + lp->intmask|=RECONflag; #endif - SETMASK; + SETMASK; - /* done! return success. */ - return 0; + /* done! return success. */ + return 0; } + static void arc90xx_openclose(int open) { if (open) @@ -811,6 +751,7 @@ AINTMASK(mask); } + static u_char arc90xx_status(struct device *dev) { short ioaddr=dev->base_addr; @@ -818,6 +759,7 @@ return ARCSTATUS; } + static void arc90xx_command(struct device *dev, u_char cmd) { short ioaddr=dev->base_addr; @@ -834,226 +776,219 @@ { struct arcnet_local *lp=(struct arcnet_local *)dev->priv; int ioaddr=dev->base_addr, status, boguscount = 3, didsomething; - - + AINTMASK(0); - + BUGMSG(D_DURING,"in arcnet_inthandler (status=%Xh, intmask=%Xh)\n", ARCSTATUS,lp->intmask); - + do { status = ARCSTATUS; - didsomething=0; - - - /* RESET flag was enabled - card is resetting and if RX - * is disabled, it's NOT because we just got a packet. - */ - if (status & RESETflag) - { - BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n", - status); - arc90xx_reset(dev,0); - - /* all other flag values are just garbage */ - break; - } - - - /* RX is inhibited - we must have received something. */ - if (status & lp->intmask & NORXflag) - { - int recbuf=lp->recbuf=!lp->recbuf; - - BUGMSG(D_DURING,"receive irq (status=%Xh)\n", - status); - - /* enable receive of our next packet */ - EnableReceiver(); - - /* Got a packet. */ - arc90xx_rx(dev,!recbuf); - - didsomething++; - } - - /* it can only be an xmit-done irq if we're xmitting :) */ - /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/ - if (status & lp->intmask & TXFREEflag) - { - struct Outgoing *out=&(lp->outgoing); - int was_sending=lp->sending; - - lp->intmask &= ~TXFREEflag; - - lp->in_txhandler++; - if (was_sending) lp->sending--; - - BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n", - status,out->numsegs,out->segnum,out->skb); - - if (was_sending && !(status&TXACKflag)) - { - if (lp->lasttrans_dest != 0) - { - BUGMSG(D_EXTRA,"transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n", - status,lp->lasttrans_dest); - lp->stats.tx_errors++; - lp->stats.tx_carrier_errors++; - } - else - { - BUGMSG(D_DURING,"broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n", - status, - lp->lasttrans_dest); - } - } - - /* send packet if there is one */ - arcnet_go_tx(dev,0); - didsomething++; - - if (lp->intx) - { - BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n", - ARCSTATUS,lp->intx); - lp->in_txhandler--; - continue; - } - - if (!lp->outgoing.skb) - { - BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n"); - - /* inform upper layers */ - if (!lp->txready) arcnet_tx_done(dev, lp); - lp->in_txhandler--; - continue; - } - - /* if more than one segment, and not all segments - * are done, then continue xmit. - */ - if (out->segnumnumsegs) - arcnetA_continue_tx(dev); - arcnet_go_tx(dev,0); - - /* if segnum==numsegs, the transmission is finished; - * free the skb. - */ - if (out->segnum>=out->numsegs) - { - /* transmit completed */ - out->segnum++; - if (out->skb) - { - lp->stats.tx_bytes += out->skb->len; - dev_kfree_skb(out->skb,FREE_WRITE); - } - out->skb=NULL; - - /* inform upper layers */ - if (!lp->txready) arcnet_tx_done(dev, lp); - } - didsomething++; - - lp->in_txhandler--; - } - else if (lp->txready && !lp->sending && !lp->intx) - { - BUGMSG(D_NORMAL,"recovery from silent TX (status=%Xh)\n", - status); - arcnet_go_tx(dev,0); - didsomething++; - } + didsomething=0; + + /* RESET flag was enabled - card is resetting and if RX + * is disabled, it's NOT because we just got a packet. + */ + if (status & RESETflag) + { + BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n", + status); + arc90xx_reset(dev,0); + + /* all other flag values are just garbage */ + break; + } + + /* RX is inhibited - we must have received something. */ + if (status & lp->intmask & NORXflag) + { + int recbuf=lp->recbuf=!lp->recbuf; + + BUGMSG(D_DURING,"receive irq (status=%Xh)\n", + status); + + /* enable receive of our next packet */ + EnableReceiver(); + + /* Got a packet. */ + arc90xx_rx(dev,!recbuf); + + didsomething++; + } + + /* it can only be an xmit-done irq if we're xmitting :) */ + /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/ + if (status & lp->intmask & TXFREEflag) + { + struct Outgoing *out=&(lp->outgoing); + int was_sending=lp->sending; + + lp->intmask &= ~TXFREEflag; + + lp->in_txhandler++; + if (was_sending) lp->sending--; + + BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n", + status,out->numsegs,out->segnum,out->skb); + + if (was_sending && !(status&TXACKflag)) + { + if (lp->lasttrans_dest != 0) + { + BUGMSG(D_EXTRA,"transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n", + status,lp->lasttrans_dest); + lp->stats.tx_errors++; + lp->stats.tx_carrier_errors++; + } + else + { + BUGMSG(D_DURING,"broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n", + status, + lp->lasttrans_dest); + } + } + + /* send packet if there is one */ + arcnet_go_tx(dev,0); + didsomething++; + + if (lp->intx) + { + BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n", + ARCSTATUS,lp->intx); + lp->in_txhandler--; + continue; + } + + if (!lp->outgoing.skb) + { + BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n"); + + /* inform upper layers */ + if (!lp->txready) arcnet_tx_done(dev, lp); + lp->in_txhandler--; + continue; + } + + /* if more than one segment, and not all segments + * are done, then continue xmit. + */ + if (out->segnumnumsegs) + arcnetA_continue_tx(dev); + arcnet_go_tx(dev,0); + + /* if segnum==numsegs, the transmission is finished; + * free the skb. + */ + if (out->segnum>=out->numsegs) + { + /* transmit completed */ + out->segnum++; + if (out->skb) + { + lp->stats.tx_bytes += out->skb->len; + dev_kfree_skb(out->skb,FREE_WRITE); + } + out->skb=NULL; + + /* inform upper layers */ + if (!lp->txready) arcnet_tx_done(dev, lp); + } + didsomething++; + + lp->in_txhandler--; + } + else if (lp->txready && !lp->sending && !lp->intx) + { + BUGMSG(D_NORMAL,"recovery from silent TX (status=%Xh)\n", + status); + arcnet_go_tx(dev,0); + didsomething++; + } #ifdef DETECT_RECONFIGS - if (status & (lp->intmask) & RECONflag) - { - ACOMMAND(CFLAGScmd|CONFIGclear); - lp->stats.tx_carrier_errors++; - + if (status & (lp->intmask) & RECONflag) + { + ACOMMAND(CFLAGScmd|CONFIGclear); + lp->stats.tx_carrier_errors++; + #ifdef SHOW_RECONFIGS - BUGMSG(D_NORMAL,"Network reconfiguration detected (status=%Xh)\n", - status); - - + BUGMSG(D_NORMAL,"Network reconfiguration detected (status=%Xh)\n", + status); #endif /* SHOW_RECONFIGS */ - + #ifdef RECON_THRESHOLD - /* is the RECON info empty or old? */ - if (!lp->first_recon || !lp->last_recon || - jiffies-lp->last_recon > HZ*10) - { - if (lp->network_down) - BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n"); - lp->first_recon=lp->last_recon=jiffies; - lp->num_recons=lp->network_down=0; - - BUGMSG(D_DURING,"recon: clearing counters.\n"); - } - else /* add to current RECON counter */ - { - lp->last_recon=jiffies; - lp->num_recons++; - - BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n", - lp->num_recons, - (lp->last_recon-lp->first_recon)/HZ, - lp->network_down); - - /* if network is marked up; - * and first_recon and last_recon are 60+ sec - * apart; - * and the average no. of recons counted is - * > RECON_THRESHOLD/min; - * then print a warning message. - */ - if (!lp->network_down - && (lp->last_recon-lp->first_recon)<=HZ*60 - && lp->num_recons >= RECON_THRESHOLD) - { - lp->network_down=1; - BUGMSG(D_NORMAL,"many reconfigurations detected: cabling problem?\n"); - } - else if (!lp->network_down - && lp->last_recon-lp->first_recon > HZ*60) - { - /* reset counters if we've gone for - * over a minute. - */ - lp->first_recon=lp->last_recon; - lp->num_recons=1; - } - } - } - else if (lp->network_down && jiffies-lp->last_recon > HZ*10) - { - if (lp->network_down) - BUGMSG(D_NORMAL,"cabling restored?\n"); - lp->first_recon=lp->last_recon=0; - lp->num_recons=lp->network_down=0; - - BUGMSG(D_DURING,"not recon: clearing counters anyway.\n"); + /* is the RECON info empty or old? */ + if (!lp->first_recon || !lp->last_recon || + jiffies-lp->last_recon > HZ*10) + { + if (lp->network_down) + BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n"); + lp->first_recon=lp->last_recon=jiffies; + lp->num_recons=lp->network_down=0; + + BUGMSG(D_DURING,"recon: clearing counters.\n"); + } + else /* add to current RECON counter */ + { + lp->last_recon=jiffies; + lp->num_recons++; + + BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n", + lp->num_recons, + (lp->last_recon-lp->first_recon)/HZ, + lp->network_down); + + /* if network is marked up; + * and first_recon and last_recon are 60+ sec + * apart; + * and the average no. of recons counted is + * > RECON_THRESHOLD/min; + * then print a warning message. + */ + if (!lp->network_down + && (lp->last_recon-lp->first_recon)<=HZ*60 + && lp->num_recons >= RECON_THRESHOLD) + { + lp->network_down=1; + BUGMSG(D_NORMAL,"many reconfigurations detected: cabling problem?\n"); + } + else if (!lp->network_down + && lp->last_recon-lp->first_recon > HZ*60) + { + /* reset counters if we've gone for + * over a minute. + */ + lp->first_recon=lp->last_recon; + lp->num_recons=1; + } + } + } + else if (lp->network_down && jiffies-lp->last_recon > HZ*10) + { + if (lp->network_down) + BUGMSG(D_NORMAL,"cabling restored?\n"); + lp->first_recon=lp->last_recon=0; + lp->num_recons=lp->network_down=0; + + BUGMSG(D_DURING,"not recon: clearing counters anyway.\n"); #endif - } + } #endif /* DETECT_RECONFIGS */ } while (--boguscount && didsomething); - + BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n", ARCSTATUS,boguscount); BUGMSG(D_DURING,"\n"); - + SETMASK; /* put back interrupt mask */ - } - /* A packet has arrived; grab it from the buffers and pass it to the generic * arcnet_rx routing to deal with it. - */ + */ static void arc90xx_rx(struct device *dev,int recbuf) @@ -1065,11 +1000,11 @@ u_char *arcsoft; short length,offset; u_char daddr,saddr; - + lp->stats.rx_packets++; - + saddr=arcpacket->hardheader.source; - + /* if source is 0, it's a "used" packet! */ if (saddr==0) { @@ -1079,11 +1014,11 @@ return; } /* Set source address to zero to mark it as old */ - + arcpacket->hardheader.source=0; - + daddr=arcpacket->hardheader.destination; - + if (arcpacket->hardheader.offset1) /* Normal Packet */ { offset=arcpacket->hardheader.offset1; @@ -1094,28 +1029,22 @@ { offset=arcpacket->hardheader.offset2; arcsoft=&arcpacket->raw[offset]; - + length=512-offset; } - - - arcnet_rx(lp, arcsoft, length, saddr, daddr); + arcnet_rx(lp, arcsoft, length, saddr, daddr); BUGLVL(D_RX) arcnet_dump_packet(lp->adev,arcpacket->raw,length>240,"rx"); - #ifndef SLOW_XMIT_COPY /* clean out the page to make debugging make more sense :) */ BUGLVL(D_DURING) memset((void *)arcpacket->raw,0x42,512); #endif - } - - /* Given an skb, copy a packet into the ARCnet buffers for later transmission * by arcnet_go_tx. */ @@ -1126,45 +1055,45 @@ struct arcnet_local *lp = (struct arcnet_local *)dev->priv; union ArcPacket *arcpacket = (union ArcPacket *)phys_to_virt(dev->mem_start+512*(lp->txbuf^1)); - + #ifdef SLOW_XMIT_COPY char *iptr,*iend,*optr; #endif - + lp->txbuf=lp->txbuf^1; /* XOR with 1 to alternate between 2 and 3 */ - + length+=hdrlen; - + BUGMSG(D_TX,"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n", hdr,length,data); - + #ifndef SLOW_XMIT_COPY /* clean out the page to make debugging make more sense :) */ BUGLVL(D_DURING) memset_io(dev->mem_start+lp->txbuf*512,0x42,512); #endif - + arcpacket->hardheader.destination=daddr; - + /* load packet into shared memory */ if (length<=MTU) /* Normal (256-byte) Packet */ arcpacket->hardheader.offset1=offset=offset?offset:256-length; - + else if (length>=MinTU || offset) /* Extended (512-byte) Packet */ { arcpacket->hardheader.offset1=0; - arcpacket->hardheader.offset2=offset=offset?offset:512-length; + arcpacket->hardheader.offset2=offset=offset?offset:512-length; } else if (exceptA) /* RFC1201 Exception Packet */ { arcpacket->hardheader.offset1=0; arcpacket->hardheader.offset2=offset=512-length-4; - + /* exception-specific stuff - these four bytes * make the packet long enough to fit in a 512-byte * frame. */ - + arcpacket->raw[offset+0]=hdr[0]; arcpacket->raw[offset+1]=0xFF; /* FF flag */ arcpacket->raw[offset+2]=0xFF; /* FF padding */ @@ -1175,13 +1104,12 @@ { /* RFC1051 - set 4 trailing bytes to 0 */ memset(&arcpacket->raw[508],0,4); - + /* now round up to MinTU */ arcpacket->hardheader.offset1=0; arcpacket->hardheader.offset2=offset=512-MinTU; } - - + /* copy the packet into ARCnet shmem * - the first bytes of ClientData header are skipped */ @@ -1197,12 +1125,12 @@ #else memcpy((u_char*)arcpacket+offset+hdrlen, data,length-hdrlen); #endif - + BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n", daddr,length); - + BUGLVL(D_TX) arcnet_dump_packet(dev,arcpacket->raw,length>MTU,"tx"); - + lp->lastload_dest=daddr; lp->txready=lp->txbuf; /* packet is ready for sending */ } @@ -1232,12 +1160,12 @@ if (device) strcpy(dev->name,device); else arcnet_makename(dev->name); - + dev->base_addr=io; - + dev->irq=irq; if (dev->irq==2) dev->irq=9; - + if (shmem) { dev->mem_start=shmem; @@ -1245,7 +1173,7 @@ dev->rmem_start=thiscard.mem_start+512*0; dev->rmem_end=thiscard.mem_start+512*2-1; } - + if (register_netdev(dev) != 0) return -EIO; arcnet_use_count(1); @@ -1254,37 +1182,38 @@ void cleanup_module(void) { - struct device *dev=&thiscard; - int ioaddr=dev->mem_start; + struct device *dev=&thiscard; + int ioaddr=dev->mem_start; - if (dev->start) (*dev->stop)(dev); + if (dev->start) (*dev->stop)(dev); - /* Flush TX and disable RX */ - if (ioaddr) - { - AINTMASK(0); /* disable IRQ's */ - ACOMMAND(NOTXcmd); /* stop transmit */ - ACOMMAND(NORXcmd); /* disable receive */ + /* Flush TX and disable RX */ + if (ioaddr) + { + AINTMASK(0); /* disable IRQ's */ + ACOMMAND(NOTXcmd); /* stop transmit */ + ACOMMAND(NORXcmd); /* disable receive */ #if defined(IO_MAPPED_BUFFERS) && !defined(COM20020) - /* Set the thing back to MMAP mode, in case the old - driver is loaded later */ - outb( (inb(_CONFIG)&~IOMAPflag),_CONFIG); + /* Set the thing back to MMAP mode, in case the old + driver is loaded later */ + outb( (inb(_CONFIG)&~IOMAPflag),_CONFIG); #endif - } + } - if (dev->irq) - { - irq2dev_map[dev->irq] = NULL; - free_irq(dev->irq,NULL); - } + if (dev->irq) + { + irq2dev_map[dev->irq] = NULL; + free_irq(dev->irq,NULL); + } - if (dev->base_addr) release_region(dev->base_addr,ARCNET_TOTAL_SIZE); - unregister_netdev(dev); - kfree(dev->priv); - dev->priv = NULL; - arcnet_use_count(0); + if (dev->base_addr) release_region(dev->base_addr,ARCNET_TOTAL_SIZE); + unregister_netdev(dev); + kfree(dev->priv); + dev->priv = NULL; + arcnet_use_count(0); } + #else __initfunc(void com90xx_setup (char *str, int *ints)) @@ -1297,7 +1226,7 @@ MAX_ARCNET_DEVS); return; } - + if (!ints[0] && (!str || !*str)) { printk("com90xx: Disabled.\n"); @@ -1306,7 +1235,7 @@ } dev=&arcnet_devs[arcnet_num_devs]; - + dev->dev_addr[3]=3; dev->init=arc90xx_probe; @@ -1320,13 +1249,13 @@ case 2: /* IRQ */ dev->irq=ints[2]; - + case 1: /* IO address */ dev->base_addr=ints[1]; } dev->name = (char *)&arcnet_dev_names[arcnet_num_devs]; - + if (str) strncpy(dev->name, str, 9); diff -u --recursive --new-file v2.1.53/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c --- v2.1.53/linux/drivers/net/eepro100.c Wed Sep 3 20:52:42 1997 +++ linux/drivers/net/eepro100.c Fri Sep 5 20:41:41 1997 @@ -462,13 +462,16 @@ /* 'options' is used to pass a transceiver override or full-duplex flag e.g. "options=16" for FD, "options=32" for 100mbps-only. */ static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1}; + #ifdef MODULE + static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1}; static int debug = -1; /* The debug level */ -#endif /* A list of all installed Speedo devices, for removing the driver module. */ static struct device *root_speedo_dev = NULL; + +#endif int eepro100_init(struct device *dev) { diff -u --recursive --new-file v2.1.53/linux/drivers/net/ppp.c linux/drivers/net/ppp.c --- v2.1.53/linux/drivers/net/ppp.c Tue May 13 22:41:09 1997 +++ linux/drivers/net/ppp.c Sat Sep 6 10:05:42 1997 @@ -521,7 +521,7 @@ extern inline int lock_buffer (register struct ppp_buffer *buf) { - register int state; + register long state; int flags; /* * Save the current state and if free then set it to the "busy" state @@ -1071,6 +1071,7 @@ */ if (ppp->flags & SC_LOG_RAWIN) ppp_print_buffer ("receive buffer", data, count); + /* * Collect the character and error condition for the character. Set the toss * flag for the first character error. @@ -1083,6 +1084,7 @@ ppp->toss = *flags; ++flags; } + /* * Set the flags for 8 data bits and no parity. * @@ -1467,6 +1469,7 @@ { __u16 proto = PPP_PROTOCOL (data); ppp_proto_type *proto_ptr; + /* * Ignore empty frames */ @@ -1507,6 +1510,7 @@ int addr, ctrl, proto; int new_count; __u8 *new_data; + /* * If there is a pending error from the receiver then log it and discard * the damaged frame. diff -u --recursive --new-file v2.1.53/linux/drivers/pci/pci.c linux/drivers/pci/pci.c --- v2.1.53/linux/drivers/pci/pci.c Thu Aug 14 20:49:16 1997 +++ linux/drivers/pci/pci.c Sat Sep 6 10:43:50 1997 @@ -1,5 +1,5 @@ /* - * drivers/pci/pci.c + * $Id: pci.c,v 1.44 1997/09/03 05:08:22 richard Exp $ * * PCI services that are built on top of the BIOS32 service. * @@ -20,7 +20,6 @@ struct pci_bus pci_root; struct pci_dev *pci_devices = 0; - /* * The bridge_id field is an offset of an item into the array * BRIDGE_MAPPING_TYPE. 0xff indicates that the device is not a PCI @@ -68,6 +67,7 @@ DEVICE( VLSI, VLSI_82C597, "82C597-AFC2"), DEVICE( VLSI, VLSI_VAS96011, "VAS96011 PowerPC"), DEVICE( ADL, ADL_2301, "2301"), + DEVICE( NS, NS_87415, "87415"), DEVICE( NS, NS_87410, "87410"), DEVICE( TSENG, TSENG_W32P_2, "ET4000W32P"), DEVICE( TSENG, TSENG_W32P_b, "ET4000W32P rev B"), @@ -78,8 +78,9 @@ DEVICE( WEITEK, WEITEK_P9100, "P9100"), BRIDGE( DEC, DEC_BRD, "DC21050", 0x00), DEVICE( DEC, DEC_TULIP, "DC21040"), - DEVICE( DEC, DEC_TGA, "DC21030"), + DEVICE( DEC, DEC_TGA, "TGA"), DEVICE( DEC, DEC_TULIP_FAST, "DC21140"), + DEVICE( DEC, DEC_TGA2, "TGA2"), DEVICE( DEC, DEC_FDDI, "DEFPA"), DEVICE( DEC, DEC_TULIP_PLUS, "DC21041"), DEVICE( DEC, DEC_21142, "DC21142"), @@ -181,6 +182,9 @@ DEVICE( OLICOM, OLICOM_OC2183, "OC-2183/2185"), DEVICE( OLICOM, OLICOM_OC2326, "OC-2326"), DEVICE( OLICOM, OLICOM_OC6151, "OC-6151/6152"), + DEVICE( SUN, SUN_EBUS, "EBUS"), + DEVICE( SUN, SUN_HAPPYMEAL, "Happy Meal"), + BRIDGE( SUN, SUN_PBM, "PCI Bus Module", 0x02), DEVICE( CMD, CMD_640, "640 (buggy)"), DEVICE( CMD, CMD_643, "643"), DEVICE( CMD, CMD_646, "646"), @@ -596,6 +600,7 @@ case PCI_VENDOR_ID_CONTAQ: return "Contaq"; case PCI_VENDOR_ID_FOREX: return "Forex"; case PCI_VENDOR_ID_OLICOM: return "Olicom"; + case PCI_VENDOR_ID_SUN: return "Sun Microsystems"; case PCI_VENDOR_ID_CMD: return "CMD"; case PCI_VENDOR_ID_VISION: return "Vision"; case PCI_VENDOR_ID_BROOKTREE: return "Brooktree"; @@ -668,6 +673,36 @@ } +const char *pcibios_strerror(int error) +{ + static char buf[32]; + + switch (error) { + case PCIBIOS_SUCCESSFUL: + case PCIBIOS_BAD_VENDOR_ID: + return "SUCCESSFUL"; + + case PCIBIOS_FUNC_NOT_SUPPORTED: + return "FUNC_NOT_SUPPORTED"; + + case PCIBIOS_DEVICE_NOT_FOUND: + return "DEVICE_NOT_FOUND"; + + case PCIBIOS_BAD_REGISTER_NUMBER: + return "BAD_REGISTER_NUMBER"; + + case PCIBIOS_SET_FAILED: + return "SET_FAILED"; + + case PCIBIOS_BUFFER_TOO_SMALL: + return "BUFFER_TOO_SMALL"; + + default: + sprintf (buf, "PCI ERROR 0x%x", error); + return buf; + } +} + /* * Turn on/off PCI bridge optimization. This should allow benchmarking. @@ -793,7 +828,7 @@ if (len + 40 > size) { return -1; } - len += sprintf(buf + len, "IRQ %d. ", dev->irq); + len += sprintf(buf + len, "IRQ %x. ", dev->irq); } if (dev->master) { @@ -811,20 +846,24 @@ len += sprintf(buf + len, "Max Lat=%d.", max_lat); } - for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) { + for (reg = 0; reg < 6; reg++) { if (len + 40 > size) { return -1; } - pcibios_read_config_dword(bus, devfn, reg, &l); - base = l; - if (!base) { + pcibios_read_config_dword(bus, devfn, + PCI_BASE_ADDRESS_0 + (reg << 2), &l); + if (l == 0xffffffff) + base = 0; + else + base = l; + if (!base) continue; - } if (base & PCI_BASE_ADDRESS_SPACE_IO) { len += sprintf(buf + len, - "\n I/O at 0x%lx.", - base & PCI_BASE_ADDRESS_IO_MASK); + "\n I/O at 0x%lx [0x%lx].", + base & PCI_BASE_ADDRESS_IO_MASK, + dev->base_address[reg]); } else { const char *pref, *type = "unknown"; @@ -848,8 +887,9 @@ } len += sprintf(buf + len, "\n %srefetchable %s memory at " - "0x%lx.", pref, type, - base & PCI_BASE_ADDRESS_MEM_MASK); + "0x%lx [0x%lx].", pref, type, + base & PCI_BASE_ADDRESS_MEM_MASK, + dev->base_address[reg]); } } @@ -892,7 +932,7 @@ void *mem; #ifdef DEBUG - printk("...pci_malloc(size=%ld,mem=%p)", size, *mem_startp); + printk("...pci_malloc(size=%ld,mem=%p)", size, (void *)*mem_startp); #endif mem = (void*) *mem_startp; *mem_startp += (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); @@ -901,16 +941,18 @@ } -__initfunc(static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_startp)) +unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp) { unsigned int devfn, l, max; - unsigned char cmd, tmp, hdr_type = 0; + unsigned char cmd, tmp, irq, hdr_type = 0; struct pci_dev_info *info; struct pci_dev *dev; struct pci_bus *child; + int reg; #ifdef DEBUG - printk("...scan_bus(busno=%d,mem=%p)\n", bus->number, *mem_startp); + printk("...pci_scan_bus(busno=%d,mem=%p)\n", bus->number, + (void *)*mem_startp); #endif max = bus->secondary; @@ -952,7 +994,7 @@ */ info = pci_lookup_dev(dev->vendor, dev->device); if (!info) { - printk("Warning : Unknown PCI device (%x:%x). Please read include/linux/pci.h \n", + printk("PCI: Warning: Unknown PCI device (%x:%x). Please read include/linux/pci.h\n", dev->vendor, dev->device); } else { /* Some BIOS' are lazy. Let's do their job: */ @@ -975,7 +1017,20 @@ /* read irq level (may be changed during pcibios_fixup()): */ pcibios_read_config_byte(bus->number, devfn, - PCI_INTERRUPT_LINE, &dev->irq); + PCI_INTERRUPT_LINE, &irq); + dev->irq = irq; + + /* read base address registers, again pcibios_fixup() can + * tweak these + */ + for (reg = 0; reg < 6; reg++) { + pcibios_read_config_dword(bus->number, devfn, + PCI_BASE_ADDRESS_0 + (reg << 2), &l); + if (l == 0xffffffff) + dev->base_address[reg] = 0; + else + dev->base_address[reg] = l; + } /* check to see if this device is a PCI-PCI bridge: */ pcibios_read_config_dword(bus->number, devfn, @@ -1033,7 +1088,7 @@ child->secondary = (buses >> 8) & 0xFF; child->subordinate = (buses >> 16) & 0xFF; child->number = child->secondary; - max = scan_bus(child, mem_startp); + max = pci_scan_bus(child, mem_startp); } else { @@ -1050,7 +1105,7 @@ /* * Now we can scan all subordinate buses: */ - max = scan_bus(child, mem_startp); + max = pci_scan_bus(child, mem_startp); /* * Set the subordinate bus number to its real * value: @@ -1081,14 +1136,14 @@ mem_start = pcibios_init(mem_start, mem_end); if (!pcibios_present()) { - printk("pci_init: no PCI BIOS detected\n"); + printk("PCI: No PCI bus detected\n"); return mem_start; } printk("Probing PCI hardware.\n"); memset(&pci_root, 0, sizeof(pci_root)); - pci_root.subordinate = scan_bus(&pci_root, &mem_start); + pci_root.subordinate = pci_scan_bus(&pci_root, &mem_start); /* give BIOS a chance to apply platform specific fixes: */ mem_start = pcibios_fixup(mem_start, mem_end); diff -u --recursive --new-file v2.1.53/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c --- v2.1.53/linux/drivers/sbus/char/pcikbd.c Thu Sep 4 17:07:31 1997 +++ linux/drivers/sbus/char/pcikbd.c Sat Sep 6 10:04:15 1997 @@ -1,4 +1,4 @@ -/* $Id: pcikbd.c,v 1.3 1997/09/04 05:50:35 ecd Exp $ +/* $Id: pcikbd.c,v 1.4 1997/09/05 22:59:53 ecd Exp $ * pcikbd.c: Ultra/AX PC keyboard support. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -404,51 +404,37 @@ { struct linux_ebus *ebus; struct linux_ebus_device *edev; - int node, index, irq; + struct linux_ebus_child *child; for_all_ebusdev(edev, ebus) { if(!strcmp(edev->prom_name, "8042")) { - node = prom_getchild(edev->prom_node); - node = prom_searchsiblings(node, "kb_ps2"); - if (node == kbd_node) - goto found; + for_each_edevchild(edev, child) { + if (!strcmp(child->prom_name, "kb_ps2")) + goto found; + } } } - printk("pcikbd_init: no 8042 found\n"); + printk("pcikbd_probe: no 8042 found\n"); return -ENODEV; found: - if (prom_getproperty(node, "reg", (char *)&index, sizeof(index)) != - sizeof(index)) { - printk("8042: can't get property '%s' from '%s'\n", - "reg", "kb_ps2"); - return -ENODEV; - } - - if (prom_getproperty(node, "interrupts", (char *)&irq, sizeof(irq)) != - sizeof(irq)) { - printk("8042: can't get property '%s' from '%s'\n", - "interrupts", "kb_ps2"); - return -ENODEV; - } - - pcikbd_iobase = edev->base_address[index]; + pcikbd_iobase = child->base_address[0]; if (check_region(pcikbd_iobase, sizeof(unsigned long))) { printk("8042: can't get region %lx, %d\n", pcikbd_iobase, (int)sizeof(unsigned long)); return -ENODEV; } - request_region(pcikbd_iobase, sizeof(unsigned long), "8042 controller"); - printk("8042(kbd): iobase[%016lx] irq[%x]\n", pcikbd_iobase, irq); - pcikbd_irq = irq; + pcikbd_irq = child->irqs[0]; if (request_irq(pcikbd_irq, &pcikbd_interrupt, SA_SHIRQ, "keyboard", NULL)) { printk("8042: cannot register IRQ %x\n", pcikbd_irq); return -ENODEV; } + printk("8042(kbd): iobase[%016lx] irq[%x]\n", pcikbd_iobase, pcikbd_irq); + /* pcikbd_init(); */ kbd_read_mask = KBD_STAT_OBF; return 0; @@ -806,36 +792,21 @@ { struct linux_ebus *ebus; struct linux_ebus_device *edev; - int node, index, irq; + struct linux_ebus_child *child; for_all_ebusdev(edev, ebus) { if(!strcmp(edev->prom_name, "8042")) { - node = prom_getchild(edev->prom_node); - node = prom_searchsiblings(node, "kdmouse"); - if (node == ms_node) - goto found; + for_each_edevchild(edev, child) { + if (!strcmp(child->prom_name, "kdmouse")) + goto found; + } } } printk("pcimouse_init: no 8042 found\n"); return -ENODEV; found: - if (prom_getproperty(node, "reg", (char *)&index, sizeof(index)) != - sizeof(index)) { - printk("8042: can't get property '%s' from '%s'\n", - "reg", "kdmouse"); - return -ENODEV; - } - - if (prom_getproperty(node, "interrupts", (char *)&irq, sizeof(irq)) != - sizeof(irq)) { - printk("8042: can't get property '%s' from '%s'\n", - "interrupts", "kdmouse"); - return -ENODEV; - } - - pcimouse_iobase = edev->base_address[index]; - + pcimouse_iobase = child->base_address[0]; /* * Just in case the iobases for kbd/mouse ever differ... */ @@ -843,15 +814,16 @@ request_region(pcimouse_iobase, sizeof(unsigned long), "8042 controller"); - printk("8042(mouse): iobase[%016lx] irq[%x]\n", pcimouse_iobase, irq); - pcimouse_irq = irq; - + pcimouse_irq = child->irqs[0]; if (request_irq(pcimouse_irq, &pcimouse_interrupt, SA_SHIRQ, "mouse", NULL)) { printk("8042: Cannot register IRQ %x\n", pcimouse_irq); return -ENODEV; } + printk("8042(mouse): iobase[%016lx] irq[%x]\n", + pcimouse_iobase, pcimouse_irq); + printk("8042: PS/2 auxiliary pointing device detected.\n"); aux_present = 1; kbd_read_mask = AUX_STAT_OBF; @@ -873,7 +845,7 @@ poll_aux_status(); outb(KBD_CCMD_WRITE_MODE, pcimouse_iobase + KBD_CNTL_REG); poll_aux_status(); - outb(AUX_INTS_OFF, KBD_DATA_REG); + outb(AUX_INTS_OFF, pcimouse_iobase + KBD_DATA_REG); poll_aux_status(); aux_end_atomic(); diff -u --recursive --new-file v2.1.53/linux/drivers/scsi/esp.c linux/drivers/scsi/esp.c --- v2.1.53/linux/drivers/scsi/esp.c Mon Aug 4 16:25:38 1997 +++ linux/drivers/scsi/esp.c Sat Sep 6 10:04:15 1997 @@ -12,6 +12,7 @@ * 3) Add tagged queueing. */ +#include #include #include #include @@ -34,6 +35,7 @@ #include #include #include +#include #include #define DEBUG_ESP @@ -642,6 +644,9 @@ */ __initfunc(int esp_detect(Scsi_Host_Template *tpnt)) { +#ifdef __sparc_v9__ + struct devid_cookie dcookie; +#endif struct Sparc_ESP *esp, *elink; struct Scsi_Host *esp_host; struct linux_sbus *sbus; @@ -655,8 +660,13 @@ int esp_node, i; espchain = 0; - if(!SBus_chain) + if(!SBus_chain) { +#ifdef CONFIG_PCI + return 0; +#else panic("No SBUS in esp_detect()"); +#endif + } for_each_sbus(sbus) { for_each_sbusdev(sbdev_iter, sbus) { struct linux_sbus_device *espdma = 0; @@ -782,6 +792,7 @@ esp->edev->reg_addrs[0].reg_size; esp->ehost->irq = esp->irq = esp->edev->irqs[0].pri; +#ifndef __sparc_v9__ /* Allocate the irq only if necessary */ for_each_esp(elink) { if((elink != esp) && (esp->irq == elink->irq)) { @@ -793,6 +804,22 @@ panic("Cannot acquire ESP irq line"); esp_irq_acquired: printk("esp%d: IRQ %d ", esp->esp_id, esp->ehost->irq); +#else + /* On Ultra we must always call request_irq for each + * esp, so that imap registers get setup etc. + */ + dcookie.real_dev_id = esp; + dcookie.imap = dcookie.iclr = 0; + dcookie.pil = -1; + dcookie.bus_cookie = sbus; + if(request_irq(esp->ehost->irq, esp_intr, + (SA_SHIRQ | SA_SBUS | SA_DCOOKIE), + "Sparc ESP SCSI", &dcookie)) + panic("Cannot acquire ESP irq line"); + esp->ehost->irq = esp->irq = dcookie.ret_ino; + printk("esp%d: INO[%x] IRQ %d ", + esp->esp_id, esp->ehost->irq, dcookie.ret_pil); +#endif /* Figure out our scsi ID on the bus */ esp->scsi_id = prom_getintdefault(esp->prom_node, @@ -2323,11 +2350,6 @@ /* Please go to msgout phase, please please please... */ ESPLOG(("esp%d: !BSERV after data, probably to msgout\n", esp->esp_id)); -#ifdef __SMP__ - ESPLOG(("esp%d: local_irq_count[%x:%x:%x:%x]\n", esp->esp_id, - local_irq_count[0], local_irq_count[1], - local_irq_count[2], local_irq_count[3])); -#endif return esp_do_phase_determine(esp, eregs, dregs); } @@ -2410,11 +2432,6 @@ ESPLOG(("esp%d: use_sg=%d ptr=%p this_residual=%d\n", esp->esp_id, SCptr->use_sg, SCptr->SCp.ptr, SCptr->SCp.this_residual)); -#ifdef __SMP__ - ESPLOG(("esp%d: local_irq_count[%x:%x:%x:%x]\n", esp->esp_id, - local_irq_count[0], local_irq_count[1], - local_irq_count[2], local_irq_count[3])); -#endif bytes_sent = 0; } @@ -4021,6 +4038,8 @@ return; } +#ifndef __sparc_v9__ + #ifndef __SMP__ static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs) { @@ -4031,14 +4050,7 @@ repeat: again = 0; for_each_esp(esp) { - /* XXX Ultra: This is gross, what we really need - * XXX is a sbusirq_to_sparc_pil() function, call - * XXX that and stick the result in the esp soft - * XXX state structure. -DaveM - */ -#ifndef __sparc_v9__ if((esp->irq & 0xf) == irq) { -#endif if(DMA_IRQ_P(esp->dregs)) { again = 1; @@ -4050,23 +4062,12 @@ DMA_INTSON(esp->dregs); } -#ifndef __sparc_v9__ } -#endif } if(again) goto repeat; } #else - -/* XXX Gross hack for sun4u SMP, fix it right later... -DaveM */ -#ifdef __sparc_v9__ -extern unsigned char ino_to_pil[]; -#define INO_TO_PIL(esp) (ino_to_pil[(esp)->irq]) -#else -#define INO_TO_PIL(esp) ((esp)->irq & 0xf) -#endif - /* For SMP we only service one ESP on the list list at our IRQ level! */ static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs) { @@ -4074,7 +4075,7 @@ /* Handle all ESP interrupts showing at this IRQ level. */ for_each_esp(esp) { - if(INO_TO_PIL(esp) == irq) { + if(((esp)->irq & 0xf) == irq) { if(DMA_IRQ_P(esp->dregs)) { DMA_INTSOFF(esp->dregs); @@ -4089,4 +4090,23 @@ } } } +#endif + +#else /* __sparc_v9__ */ + +static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs) +{ + struct Sparc_ESP *esp = dev_id; + + if(DMA_IRQ_P(esp->dregs)) { + DMA_INTSOFF(esp->dregs); + + ESPIRQ(("I[%d:%d](", smp_processor_id(), esp->esp_id)); + esp_handle(esp); + ESPIRQ((")")); + + DMA_INTSON(esp->dregs); + } +} + #endif diff -u --recursive --new-file v2.1.53/linux/drivers/scsi/g_NCR5380.c linux/drivers/scsi/g_NCR5380.c --- v2.1.53/linux/drivers/scsi/g_NCR5380.c Mon Jun 16 16:35:56 1997 +++ linux/drivers/scsi/g_NCR5380.c Sat Sep 6 10:13:06 1997 @@ -736,4 +736,11 @@ #include #include "scsi_module.c" + +MODULE_PARM(ncr_irq, "i"); +MODULE_PARM(ncr_dma, "i"); +MODULE_PARM(ncr_addr, "i"); +MODULE_PARM(ncr_5380, "i"); +MODULE_PARM(ncr_53c400, "i"); + #endif diff -u --recursive --new-file v2.1.53/linux/drivers/scsi/mesh.c linux/drivers/scsi/mesh.c --- v2.1.53/linux/drivers/scsi/mesh.c Mon Aug 18 18:19:46 1997 +++ linux/drivers/scsi/mesh.c Sat Sep 6 10:04:15 1997 @@ -7,9 +7,7 @@ * Paul Mackerras, August 1996. * Copyright (C) 1996 Paul Mackerras. */ - #include - #include #include #include diff -u --recursive --new-file v2.1.53/linux/drivers/scsi/qlogicpti.c linux/drivers/scsi/qlogicpti.c --- v2.1.53/linux/drivers/scsi/qlogicpti.c Thu Jul 17 10:06:05 1997 +++ linux/drivers/scsi/qlogicpti.c Sat Sep 6 10:04:16 1997 @@ -37,6 +37,7 @@ #include #include #include +#include #include @@ -351,7 +352,7 @@ unsigned short csum = 0; unsigned short param[6]; unsigned long flags; -#ifndef MODULE +#if !defined(MODULE) && !defined(__sparc_v9__) unsigned long dvma_addr; #endif int i, timeout; @@ -419,8 +420,7 @@ } /* Load the firmware. */ -#ifndef MODULE - /* XXX THIS SHIT DOES NOT WORK ON ULTRA... FIXME -DaveM */ +#if !defined(MODULE) && !defined(__sparc_v9__) dvma_addr = (unsigned long) mmu_lockarea((char *)&risc_code01[0], (sizeof(u_short) * risc_code_length01)); param[0] = MBOX_LOAD_RAM; @@ -435,9 +435,9 @@ restore_flags(flags); return 1; } - /* XXX THIS SHIT DOES NOT WORK ON ULTRA... FIXME -DaveM */ mmu_unlockarea((char *)dvma_addr, (sizeof(u_short) * risc_code_length01)); #else + /* We need to do it this slow way always on Ultra. */ for(i = 0; i < risc_code_length01; i++) { param[0] = MBOX_WRITE_RAM_WORD; param[1] = risc_code_addr01 + i; @@ -566,6 +566,9 @@ /* Detect all PTI Qlogic ISP's in the machine. */ __initfunc(int qlogicpti_detect(Scsi_Host_Template *tpnt)) { +#ifdef __sparc_v9__ + struct devid_cookie dcookie; +#endif struct qlogicpti *qpti, *qlink; struct Scsi_Host *qpti_host; struct linux_sbus *sbus; @@ -643,7 +646,7 @@ /* Map this one read only. */ qpti->sreg = sreg = (volatile unsigned char *) sparc_alloc_io((qpti->qdev->reg_addrs[0].phys_addr + - (16 * PAGE_SIZE)), 0, + (16 * 4096)), 0, sizeof(unsigned char), "PTI Qlogic/ISP Status Reg", qpti->qdev->reg_addrs[0].which_io, 1); @@ -659,6 +662,7 @@ qpti_host->irq = qpti->irq = qpti->qdev->irqs[0].pri; +#ifndef __sparc_v9__ /* Allocate the irq only if necessary. */ for_each_qlogicpti(qlink) { if((qlink != qpti) && (qpti->irq == qlink->irq)) { @@ -673,6 +677,25 @@ } qpti_irq_acquired: printk("qpti%d: IRQ %d ", qpti->qpti_id, qpti->qhost->irq); +#else + /* On Ultra we must always call request_irq for each + * qpti, so that imap registers get setup etc. + */ + dcookie.real_dev_id = qpti; + dcookie.imap = dcookie.iclr = 0; + dcookie.pil = -1; + dcookie.bus_cookie = sbus; + if(request_irq(qpti->qhost->irq, qlogicpti_intr_handler, + (SA_SHIRQ | SA_SBUS | SA_DCOOKIE), + "PTI Qlogic/ISP SCSI", &dcookie)) { + printk("Cannot acquire PTI Qlogic/ISP irq line\n"); + /* XXX Unmap regs, unregister scsi host, free things. */ + continue; + } + qpti->qhost->irq = qpti->irq = dcookie.ret_ino; + printk("qpti%d: INO[%x] IRQ %d ", + qpti->qpti_id, qpti->qhost->irq, dcookie.ret_pil); +#endif /* Figure out our scsi ID on the bus */ qpti->scsi_id = prom_getintdefault(qpti->prom_node, @@ -805,7 +828,11 @@ memset(cmd, 0, sizeof(struct Command_Entry)); cmd->hdr.entry_cnt = 1; cmd->hdr.entry_type = ENTRY_COMMAND; - cmd->handle = (u_int) ((unsigned long)Cmnd); /* magic mushroom */ +#ifdef __sparc_v9__ + cmd->handle = (u_int) (((unsigned long)Cmnd) - PAGE_OFFSET); /* magic mushroom */ +#else + cmd->handle = (u_int) ((unsigned long)Cmnd); /* magic mushroom */ +#endif cmd->target_id = Cmnd->target; cmd->target_lun = Cmnd->lun; cmd->cdb_length = Cmnd->cmd_len; @@ -1013,6 +1040,8 @@ return (sts->scsi_status & STATUS_MASK) | (host_status << 16); } +#ifndef __sparc_v9__ + static void qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs) { static int running = 0; @@ -1098,6 +1127,76 @@ goto repeat; running--; } + +#else /* __sparc_v9__ */ + +static void qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + struct qlogicpti *qpti = dev_id; + Scsi_Cmnd *Cmnd; + struct Status_Entry *sts; + u_int in_ptr, out_ptr; + + if(qpti->qregs->sbus_stat & SBUS_STAT_RINT) { + struct qlogicpti_regs *qregs = qpti->qregs; + + in_ptr = qregs->mbox5; + qregs->hcctrl = HCCTRL_CRIRQ; + if(qregs->sbus_semaphore & SBUS_SEMAPHORE_LCK) { + switch(qregs->mbox0) { + case ASYNC_SCSI_BUS_RESET: + case EXECUTION_TIMEOUT_RESET: + qpti->send_marker = 1; + break; + case INVALID_COMMAND: + case HOST_INTERFACE_ERROR: + case COMMAND_ERROR: + case COMMAND_PARAM_ERROR: + break; + } + qregs->sbus_semaphore = 0; + } + + /* This looks like a network driver! */ + out_ptr = qpti->res_out_ptr; + while(out_ptr != in_ptr) { + sts = (struct Status_Entry *) &qpti->res_cpu[out_ptr]; + out_ptr = NEXT_RES_PTR(out_ptr); + Cmnd = (Scsi_Cmnd *) (((unsigned long)sts->handle)+PAGE_OFFSET); + + if(sts->completion_status == CS_RESET_OCCURRED || + sts->completion_status == CS_ABORTED || + (sts->status_flags & STF_BUS_RESET)) + qpti->send_marker = 1; + + if(sts->state_flags & SF_GOT_SENSE) + memcpy(Cmnd->sense_buffer, sts->req_sense_data, + sizeof(Cmnd->sense_buffer)); + + if(sts->hdr.entry_type == ENTRY_STATUS) + Cmnd->result = qlogicpti_return_status(sts); + else + Cmnd->result = DID_ERROR << 16; + + if(Cmnd->use_sg) + mmu_release_scsi_sgl((struct mmu_sglist *) + Cmnd->buffer, + Cmnd->use_sg - 1, + qpti->qdev->my_bus); + else + mmu_release_scsi_one((__u32)((unsigned long)Cmnd->SCp.ptr), + Cmnd->request_bufflen, + qpti->qdev->my_bus); + + qpti->cmd_count[Cmnd->target]--; + qregs->mbox5 = out_ptr; + Cmnd->scsi_done(Cmnd); + } + qpti->res_out_ptr = out_ptr; + } +} + +#endif int qlogicpti_abort(Scsi_Cmnd *Cmnd) { diff -u --recursive --new-file v2.1.53/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h --- v2.1.53/linux/drivers/scsi/scsi.h Mon Jul 7 16:02:51 1997 +++ linux/drivers/scsi/scsi.h Sat Sep 6 10:51:02 1997 @@ -37,6 +37,7 @@ #endif #define MAX_SCSI_DEVICE_CODE 10 +extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE]; extern void scsi_make_blocked_list(void); extern volatile int in_scan_scsis; diff -u --recursive --new-file v2.1.53/linux/drivers/scsi/scsi_syms.c linux/drivers/scsi/scsi_syms.c --- v2.1.53/linux/drivers/scsi/scsi_syms.c Fri Jan 3 01:33:26 1997 +++ linux/drivers/scsi/scsi_syms.c Sat Sep 6 10:13:06 1997 @@ -72,5 +72,7 @@ EXPORT_SYMBOL(scsi_hosts); EXPORT_SYMBOL(scsi_devicelist); EXPORT_SYMBOL(scsi_devices); +EXPORT_SYMBOL(scsi_device_types); + #endif /* CONFIG_MODULES */ diff -u --recursive --new-file v2.1.53/linux/fs/autofs/autofs_i.h linux/fs/autofs/autofs_i.h --- v2.1.53/linux/fs/autofs/autofs_i.h Mon Aug 4 16:25:38 1997 +++ linux/fs/autofs/autofs_i.h Sat Sep 6 10:51:49 1997 @@ -23,39 +23,7 @@ #include #include #include - -#define kver(a,b,c) (((a) << 16) + ((b) << 8) + (c)) - -#if LINUX_VERSION_CODE < kver(2,1,0) - -/* Segmentation stuff for pre-2.1 kernels */ -#include - -static inline int copy_to_user(void *dst, void *src, unsigned long len) -{ - int rv = verify_area(VERIFY_WRITE, dst, len); - if ( rv ) - return -1; - memcpy_tofs(dst,src,len); - return 0; -} - -static inline int copy_from_user(void *dst, void *src, unsigned long len) -{ - int rv = verify_area(VERIFY_READ, src, len); - if ( rv ) - return -1; - memcpy_fromfs(dst,src,len); - return 0; -} - -#else - -/* Segmentation stuff for post-2.1 kernels */ #include -#define register_symtab(x) ((void)0) - -#endif #ifdef DEBUG #define DPRINTK(D) (printk D) @@ -65,9 +33,15 @@ #define AUTOFS_SUPER_MAGIC 0x0187 -#define AUTOFS_NEGATIVE_TIMEOUT (60*HZ) /* Time before asking the daemon again */ +/* + * If the daemon returns a negative response (AUTOFS_IOC_FAIL) then the + * kernel will keep the negative response cached for up to the time given + * here, although the time can be shorter if the kernel throws the dcache + * entry away. This probably should be settable from user space. + */ +#define AUTOFS_NEGATIVE_TIMEOUT (60*HZ) /* 1 minute */ -/* Structures associated with the root directory hash */ +/* Structures associated with the root directory hash table */ #define AUTOFS_HASH_SIZE 67 @@ -135,20 +109,14 @@ u32 symlink_bitmap[AUTOFS_SYMLINK_BITMAP_LEN]; }; -/* autofs_oz_mode(): do we see the man behind the curtain? */ +/* autofs_oz_mode(): do we see the man behind the curtain? (The + processes which do manipulations for us in user space sees the raw + filesystem without "magic".) */ + static inline int autofs_oz_mode(struct autofs_sb_info *sbi) { return sbi->catatonic || current->pgrp == sbi->oz_pgrp; } -/* Debug the mysteriously disappearing wait list */ - -#ifdef DEBUG_WAITLIST -#define CHECK_WAITLIST(S,O) autofs_check_waitlist_integrity(S,O) -void autofs_check_waitlist_integrity(struct autofs_sb_info *,char *); -#else -#define CHECK_WAITLIST(S,O) -#endif - /* Hash operations */ void autofs_initialize_hash(struct autofs_dirhash *); @@ -182,5 +150,5 @@ #ifdef DEBUG void autofs_say(const char *name, int len); #else -#define autofs_say(n,l) +#define autofs_say(n,l) ((void)0) #endif diff -u --recursive --new-file v2.1.53/linux/fs/autofs/init.c linux/fs/autofs/init.c --- v2.1.53/linux/fs/autofs/init.c Thu Jun 26 12:33:39 1997 +++ linux/fs/autofs/init.c Fri Sep 5 20:15:37 1997 @@ -11,17 +11,12 @@ * ------------------------------------------------------------------------- */ #include -#include "autofs_i.h" - -#if LINUX_VERSION_CODE < kver(2,1,36) -#define __initfunc(X) X -#else #include -#endif +#include "autofs_i.h" static struct file_system_type autofs_fs_type = { "autofs", - 0 /* FS_NO_DCACHE doesn't work correctly */, + 0, autofs_read_super, NULL }; @@ -29,11 +24,7 @@ #ifdef MODULE int init_module(void) { - int status; - - if ((status = register_filesystem(&autofs_fs_type)) == 0) - register_symtab(0); - return status; + return register_filesystem(&autofs_fs_type); } void cleanup_module(void) diff -u --recursive --new-file v2.1.53/linux/fs/autofs/root.c linux/fs/autofs/root.c --- v2.1.53/linux/fs/autofs/root.c Thu Aug 14 20:49:17 1997 +++ linux/fs/autofs/root.c Fri Sep 5 20:15:37 1997 @@ -394,16 +394,9 @@ int rv; unsigned long ntimeout; -#if LINUX_VERSION_CODE < kver(2,1,0) - if ( (rv = verify_area(VERIFY_WRITE, p, sizeof(unsigned long))) ) - return rv; - ntimeout = get_user(p); - put_user(sbi->exp_timeout/HZ, p); -#else if ( (rv = get_user(ntimeout, p)) || (rv = put_user(sbi->exp_timeout/HZ, p)) ) return rv; -#endif if ( ntimeout > ULONG_MAX/HZ ) sbi->exp_timeout = 0; @@ -416,15 +409,7 @@ /* Return protocol version */ static inline int autofs_get_protover(int *p) { -#if LINUX_VERSION_CODE < kver(2,1,0) - int rv; - if ( (rv = verify_area(VERIFY_WRITE, p, sizeof(int))) ) - return rv; - put_user(AUTOFS_PROTO_VERSION, p); - return 0; -#else return put_user(AUTOFS_PROTO_VERSION, p); -#endif } /* Perform an expiry operation */ diff -u --recursive --new-file v2.1.53/linux/fs/autofs/waitq.c linux/fs/autofs/waitq.c --- v2.1.53/linux/fs/autofs/waitq.c Thu Jul 17 10:06:06 1997 +++ linux/fs/autofs/waitq.c Sat Sep 6 10:23:14 1997 @@ -42,7 +42,7 @@ static int autofs_write(struct file *file, const void *addr, int bytes) { - unsigned short fs; + unsigned long fs; unsigned long old_signal; const char *data = (const char *)addr; int written = 0; diff -u --recursive --new-file v2.1.53/linux/fs/binfmt_aout.c linux/fs/binfmt_aout.c --- v2.1.53/linux/fs/binfmt_aout.c Mon Aug 4 16:25:38 1997 +++ linux/fs/binfmt_aout.c Sat Sep 6 10:23:14 1997 @@ -82,7 +82,7 @@ struct dentry * dentry = NULL; struct inode * inode = NULL; struct file file; - unsigned short fs; + unsigned long fs; int has_dumped = 0; char corefile[6+sizeof(current->comm)]; unsigned long dump_start, dump_size; diff -u --recursive --new-file v2.1.53/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c --- v2.1.53/linux/fs/binfmt_elf.c Mon Aug 18 18:19:46 1997 +++ linux/fs/binfmt_elf.c Sat Sep 6 10:23:14 1997 @@ -391,14 +391,14 @@ struct elfhdr interp_elf_ex; struct file * file; struct exec interp_ex; - struct dentry *interpreter_dentry; - unsigned long load_addr; + struct dentry *interpreter_dentry = NULL; /* to shut gcc up */ + unsigned long load_addr, load_bias; int load_addr_set = 0; unsigned int interpreter_type = INTERPRETER_NONE; unsigned char ibcs2_interpreter; int i; - int old_fs; - int error; + unsigned long old_fs; + unsigned long error; struct elf_phdr * elf_ppnt, *elf_phdata; int elf_exec_fileno; unsigned long elf_bss, k, elf_brk; @@ -503,7 +503,16 @@ if (retval >= 0) { old_fs = get_fs(); /* This could probably be optimized */ set_fs(get_ds()); - interpreter_dentry = open_namei(elf_interpreter, 0, 0); +#ifdef __sparc__ + if (ibcs2_interpreter) { + unsigned long old_pers = current->personality; + + current->personality = PER_SVR4; + interpreter_dentry = open_namei(elf_interpreter, 0, 0); + current->personality = old_pers; + } else +#endif + interpreter_dentry = open_namei(elf_interpreter, 0, 0); set_fs(old_fs); if (IS_ERR(interpreter_dentry)) retval = PTR_ERR(interpreter_dentry); @@ -593,6 +602,12 @@ bprm->p = setup_arg_pages(bprm->p, bprm); current->mm->start_stack = bprm->p; + /* Try and get dynamic programs out of the way of the default mmap + base, as well as whatever program they might try to exec. This + is because the brk will follow the loader, and is not movable. */ + + load_bias = (elf_ex.e_type == ET_DYN ? ELF_ET_DYN_BASE : 0); + /* Now we do a little grungy work by mmaping the ELF image into the correct location in memory. At this point, we assume that the image should be loaded at fixed address, not at a variable @@ -602,39 +617,47 @@ set_fs(get_ds()); for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) { if (elf_ppnt->p_type == PT_LOAD) { - int elf_prot = 0; + int elf_prot = 0, elf_flags; + unsigned long vaddr = 0; + if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; + elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE; + + if (elf_ex.e_type == ET_EXEC || load_addr_set) { + vaddr = elf_ppnt->p_vaddr; + elf_flags |= MAP_FIXED; + } + error = do_mmap(file, - ELF_PAGESTART(elf_ppnt->p_vaddr), + ELF_PAGESTART(load_bias + vaddr), (elf_ppnt->p_filesz + ELF_PAGEOFFSET(elf_ppnt->p_vaddr)), - elf_prot, - (MAP_FIXED | MAP_PRIVATE | - MAP_DENYWRITE | MAP_EXECUTABLE), + elf_prot, elf_flags, (elf_ppnt->p_offset - ELF_PAGEOFFSET(elf_ppnt->p_vaddr))); #ifdef LOW_ELF_STACK - if (ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack) - elf_stack = ELF_PAGESTART(elf_ppnt->p_vaddr); + if (error < elf_stack) + elf_stack = error-1; #endif if (!load_addr_set) { - load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset; - load_addr_set = 1; + load_addr_set = 1; + load_addr = (elf_ppnt->p_vaddr - + elf_ppnt->p_offset); + if (elf_ex.e_type == ET_DYN) { + load_bias = error; + load_addr += error; + } } k = elf_ppnt->p_vaddr; if (k < start_code) start_code = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; if (k > elf_bss) elf_bss = k; -#if 1 if ((elf_ppnt->p_flags & PF_X) && end_code < k) -#else - if ( !(elf_ppnt->p_flags & PF_W) && end_code < k) -#endif end_code = k; if (end_data < k) end_data = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; @@ -643,6 +666,13 @@ } set_fs(old_fs); + elf_entry += load_bias; + elf_bss += load_bias; + elf_brk += load_bias; + start_code += load_bias; + end_code += load_bias; + end_data += load_bias; + if (elf_interpreter) { if (interpreter_type & 1) elf_entry = load_aout_interp(&interp_ex, @@ -683,7 +713,7 @@ current->executable = dget(bprm->dentry); #endif #ifdef LOW_ELF_STACK - current->start_stack = bprm->p = elf_stack - 4; + current->start_stack = bprm->p = elf_stack; #endif current->suid = current->euid = current->fsuid = bprm->e_uid; current->sgid = current->egid = current->fsgid = bprm->e_gid; @@ -1011,7 +1041,7 @@ struct file file; struct dentry *dentry; struct inode *inode; - unsigned short fs; + unsigned long fs; char corefile[6+sizeof(current->comm)]; int segs; int i; diff -u --recursive --new-file v2.1.53/linux/fs/dcache.c linux/fs/dcache.c --- v2.1.53/linux/fs/dcache.c Thu Sep 4 17:07:31 1997 +++ linux/fs/dcache.c Fri Sep 5 18:13:07 1997 @@ -360,8 +360,6 @@ */ void d_move(struct dentry * dentry, struct dentry * target) { - struct list_head * oldhead; - if (!dentry->d_inode) printk("VFS: moving negative dcache entry\n"); diff -u --recursive --new-file v2.1.53/linux/fs/inode.c linux/fs/inode.c --- v2.1.53/linux/fs/inode.c Wed Sep 3 20:52:43 1997 +++ linux/fs/inode.c Thu Sep 4 17:07:07 1997 @@ -563,23 +563,6 @@ } while (i); } -/* - * Check whether we can mount. - */ -int fs_may_mount(kdev_t dev) -{ - return 1; -} - -/* - * Check whether we can unmount. - */ -int fs_may_umount(struct super_block *sb, struct dentry * root) -{ - shrink_dcache(); - return root->d_count == 1; -} - /* This belongs in file_table.c, not here... */ int fs_may_remount_ro(struct super_block *sb) { diff -u --recursive --new-file v2.1.53/linux/fs/nfs/inode.c linux/fs/nfs/inode.c --- v2.1.53/linux/fs/nfs/inode.c Wed Sep 3 20:52:43 1997 +++ linux/fs/nfs/inode.c Fri Sep 5 12:57:24 1997 @@ -81,6 +81,7 @@ nfs_delete_inode(struct inode * inode) { dprintk("NFS: delete_inode(%x/%ld)\n", inode->i_dev, inode->i_ino); + clear_inode(inode); } void diff -u --recursive --new-file v2.1.53/linux/fs/proc/openpromfs.c linux/fs/proc/openpromfs.c --- v2.1.53/linux/fs/proc/openpromfs.c Wed Sep 3 20:52:43 1997 +++ linux/fs/proc/openpromfs.c Sat Sep 6 10:04:16 1997 @@ -1,4 +1,4 @@ -/* $Id: openpromfs.c,v 1.18 1997/07/17 02:24:01 davem Exp $ +/* $Id: openpromfs.c,v 1.21 1997/08/19 02:05:48 davem Exp $ * openpromfs.c: /proc/openprom handling routines * * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) diff -u --recursive --new-file v2.1.53/linux/fs/proc/root.c linux/fs/proc/root.c --- v2.1.53/linux/fs/proc/root.c Mon Aug 18 18:19:46 1997 +++ linux/fs/proc/root.c Sat Sep 6 10:04:16 1997 @@ -551,8 +551,12 @@ #ifdef __powerpc__ static struct proc_dir_entry proc_root_ppc_htab = { PROC_PPC_HTAB, 8, "ppc_htab", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_ppc_htab_inode_operations + S_IFREG | S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 1, 0, 0, + 0, &proc_ppc_htab_inode_operations, + NULL, NULL, /* get_info, fill_inode */ + NULL, /* next */ + NULL, NULL /* parent, subdir */ + }; #endif diff -u --recursive --new-file v2.1.53/linux/fs/super.c linux/fs/super.c --- v2.1.53/linux/fs/super.c Wed Sep 3 20:52:44 1997 +++ linux/fs/super.c Thu Sep 4 17:07:07 1997 @@ -727,6 +727,19 @@ } /* + * Check whether we can mount the specified device. + */ +int fs_may_mount(kdev_t dev) +{ + struct super_block * sb = get_super(dev); + int busy; + + busy = sb && sb->s_root && + (sb->s_root->d_count != 1 || sb->s_root->d_covers != sb->s_root); + return !busy; +} + +/* * do_mount() does the actual mounting after sys_mount has done the ugly * parameter parsing. When enough time has gone by, and everything uses the * new mount() parameters, sys_mount() can then be cleaned up. @@ -754,43 +767,56 @@ struct vfsmount *vfsmnt; int error; + error = -EACCES; if (!(flags & MS_RDONLY) && dev && is_read_only(dev)) - return -EACCES; + goto out; /*flags |= MS_RDONLY;*/ dir_d = namei(dir_name); error = PTR_ERR(dir_d); if (IS_ERR(dir_d)) - return error; + goto out; - if (dir_d->d_covers != dir_d) { - dput(dir_d); - return -EBUSY; - } - if (!S_ISDIR(dir_d->d_inode->i_mode)) { - dput(dir_d); - return -ENOTDIR; - } - if (!fs_may_mount(dev)) { - dput(dir_d); - return -EBUSY; - } - sb = read_super(dev,type,flags,data,0); - if (!sb) { - dput(dir_d); - return -EINVAL; - } - if (sb->s_root->d_covers != sb->s_root) { - dput(dir_d); - return -EBUSY; + error = -ENOTDIR; + if (!S_ISDIR(dir_d->d_inode->i_mode)) + goto dput_and_out; + + error = -EBUSY; + if (dir_d->d_covers != dir_d) + goto dput_and_out; + + /* + * Check whether to read the super block + */ + sb = get_super(dev); + if (!sb || !sb->s_root) { + error = -EINVAL; + sb = read_super(dev,type,flags,data,0); + if (!sb) + goto dput_and_out; } + + /* + * We may have slept while reading the super block, + * so we check afterwards whether it's safe to mount. + */ + error = -EBUSY; + if (!fs_may_mount(dev)) + goto dput_and_out; + + error = -ENOMEM; vfsmnt = add_vfsmnt(dev, dev_name, dir_name); if (vfsmnt) { vfsmnt->mnt_sb = sb; vfsmnt->mnt_flags = flags; + d_mount(dir_d, sb->s_root); + return 0; /* we don't dput(dir) - see umount */ } - d_mount(dir_d, sb->s_root); - return 0; /* we don't dput(dir) - see umount */ + +dput_and_out: + dput(dir_d); +out: + return error; } diff -u --recursive --new-file v2.1.53/linux/include/asm-alpha/elf.h linux/include/asm-alpha/elf.h --- v2.1.53/linux/include/asm-alpha/elf.h Sun Aug 18 00:37:57 1996 +++ linux/include/asm-alpha/elf.h Sat Sep 6 10:23:14 1997 @@ -34,6 +34,13 @@ #define USE_ELF_CORE_DUMP #define ELF_EXEC_PAGESIZE 8192 +/* This is the location that an ET_DYN program is loaded if exec'ed. Typical + use of this is to invoke "./ld.so someprog" to test out a new version of + the loader. We need to make sure that it is out of the way of the program + that it will "exec", and that there is sufficient room for the brk. */ + +#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) + /* $0 is set by ld.so to a pointer to a function which might be registered using atexit. This provides a mean for the dynamic linker to call DT_FINI functions for shared libraries that have diff -u --recursive --new-file v2.1.53/linux/include/asm-alpha/floppy.h linux/include/asm-alpha/floppy.h --- v2.1.53/linux/include/asm-alpha/floppy.h Sat Sep 28 12:05:41 1996 +++ linux/include/asm-alpha/floppy.h Sat Sep 6 10:09:56 1997 @@ -48,6 +48,8 @@ #define N_FDC 2 #define N_DRIVE 8 +#define FLOPPY_MOTOR_MASK 0xf0 + /* * Most Alphas have no problems with floppy DMA crossing 64k borders. Sigh... */ diff -u --recursive --new-file v2.1.53/linux/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h --- v2.1.53/linux/include/asm-alpha/pgtable.h Mon Jul 7 08:18:55 1997 +++ linux/include/asm-alpha/pgtable.h Sat Sep 6 10:10:48 1997 @@ -18,6 +18,7 @@ #define flush_cache_range(mm, start, end) do { } while (0) #define flush_cache_page(vma, vmaddr) do { } while (0) #define flush_page_to_ram(page) do { } while (0) +#define flush_icache_range(start, end) do { } while (0) /* * Force a context reload. This is needed when we diff -u --recursive --new-file v2.1.53/linux/include/asm-alpha/uaccess.h linux/include/asm-alpha/uaccess.h --- v2.1.53/linux/include/asm-alpha/uaccess.h Mon Apr 14 16:28:18 1997 +++ linux/include/asm-alpha/uaccess.h Sat Sep 6 10:23:14 1997 @@ -10,6 +10,10 @@ * performed or not. If get_fs() == USER_DS, checking is performed, with * get_fs() == KERNEL_DS, checking is bypassed. * + * Or at least it did once upon a time. Nowadays it is a mask that + * defines which bits of the address space are off limits. This is a + * wee bit faster than the above. + * * For historical reasons, these macros are grossly misnamed. */ @@ -20,8 +24,16 @@ #define VERIFY_WRITE 1 #define get_fs() (current->tss.fs) -#define set_fs(x) (current->tss.fs = (x)) #define get_ds() (KERNEL_DS) + +/* Our scheme relies on all bits being preserved. Trap those evil + Intellists in their plot to use unsigned short. */ + +extern unsigned long __bad_fs_size(void); + +#define set_fs(x) (current->tss.fs = \ + sizeof(x) == sizeof(unsigned long) ? (x) \ + : __bad_fs_size()) /* * Is a address valid? This does a straighforward calculation rather diff -u --recursive --new-file v2.1.53/linux/include/asm-i386/bugs.h linux/include/asm-i386/bugs.h --- v2.1.53/linux/include/asm-i386/bugs.h Mon Jul 7 16:02:01 1997 +++ linux/include/asm-i386/bugs.h Sat Sep 6 10:50:21 1997 @@ -15,12 +15,12 @@ #define CONFIG_BUGi386 -static void no_halt(char *s, int *ints) +__initfunc(static void no_halt(char *s, int *ints)) { hlt_works_ok = 0; } -static void no_387(char *s, int *ints) +__initfunc(static void no_387(char *s, int *ints)) { hard_math = 0; __asm__("movl %%cr0,%%eax\n\t" @@ -28,9 +28,9 @@ "movl %%eax,%%cr0\n\t" : : : "ax"); } -static char fpu_error = 0; +static char __initdata fpu_error = 0; -static void copro_timeout(void) +__initfunc(static void copro_timeout(void)) { fpu_error = 1; timer_table[COPRO_TIMER].expires = jiffies+100; @@ -41,7 +41,7 @@ outb_p(0,0xf0); } -static void check_fpu(void) +__initfunc(static void check_fpu(void)) { static double x = 4195835.0; static double y = 3145727.0; @@ -99,7 +99,7 @@ printk("Hmm, FDIV bug i%c86 system\n", '0'+x86); } -static void check_hlt(void) +__initfunc(static void check_hlt(void)) { printk(KERN_INFO "Checking 'hlt' instruction... "); if (!hlt_works_ok) { @@ -110,7 +110,7 @@ printk("Ok.\n"); } -static void check_tlb(void) +__initfunc(static void check_tlb(void)) { #ifndef CONFIG_M386 /* @@ -125,7 +125,7 @@ #endif } -static void check_bugs(void) +__initfunc(static void check_bugs(void)) { check_tlb(); check_fpu(); diff -u --recursive --new-file v2.1.53/linux/include/asm-i386/elf.h linux/include/asm-i386/elf.h --- v2.1.53/linux/include/asm-i386/elf.h Fri Oct 18 09:55:51 1996 +++ linux/include/asm-i386/elf.h Sat Sep 6 10:23:14 1997 @@ -27,17 +27,23 @@ #define ELF_DATA ELFDATA2LSB; #define ELF_ARCH EM_386 - /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program - starts %edx contains a pointer to a function which might be - registered using `atexit'. This provides a mean for the - dynamic linker to call DT_FINI functions for shared libraries - that have been loaded before the code runs. +/* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program starts %edx + contains a pointer to a function which might be registered using `atexit'. + This provides a mean for the dynamic linker to call DT_FINI functions for + shared libraries that have been loaded before the code runs. - A value of 0 tells we have no such handler. */ + A value of 0 tells we have no such handler. */ #define ELF_PLAT_INIT(_r) _r->edx = 0 #define USE_ELF_CORE_DUMP #define ELF_EXEC_PAGESIZE 4096 + +/* This is the location that an ET_DYN program is loaded if exec'ed. Typical + use of this is to invoke "./ld.so someprog" to test out a new version of + the loader. We need to make sure that it is out of the way of the program + that it will "exec", and that there is sufficient room for the brk. */ + +#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) /* Wow, the "main" arch needs arch dependent functions too.. :) */ diff -u --recursive --new-file v2.1.53/linux/include/asm-i386/floppy.h linux/include/asm-i386/floppy.h --- v2.1.53/linux/include/asm-i386/floppy.h Mon Jul 7 16:02:14 1997 +++ linux/include/asm-i386/floppy.h Sat Sep 6 10:50:31 1997 @@ -283,6 +283,8 @@ #define N_FDC 2 #define N_DRIVE 8 +#define FLOPPY_MOTOR_MASK 0xf0 + /* * The DMA channel used by the floppy controller cannot access data at * addresses >= 16MB diff -u --recursive --new-file v2.1.53/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h --- v2.1.53/linux/include/asm-i386/pgtable.h Thu Aug 14 20:49:17 1997 +++ linux/include/asm-i386/pgtable.h Sat Sep 6 10:50:21 1997 @@ -19,6 +19,7 @@ #define flush_cache_range(mm, start, end) do { } while (0) #define flush_cache_page(vma, vmaddr) do { } while (0) #define flush_page_to_ram(page) do { } while (0) +#define flush_icache_range(start, end) do { } while (0) /* * TLB flushing: diff -u --recursive --new-file v2.1.53/linux/include/asm-i386/uaccess.h linux/include/asm-i386/uaccess.h --- v2.1.53/linux/include/asm-i386/uaccess.h Mon Jul 7 16:02:14 1997 +++ linux/include/asm-i386/uaccess.h Sat Sep 6 10:50:21 1997 @@ -18,9 +18,19 @@ * For historical reasons, these macros are grossly misnamed. */ +extern unsigned long __bad_fs_size(void); + #define get_fs() (current->tss.segment) -#define set_fs(x) (current->tss.segment = (x)) #define get_ds() (KERNEL_DS) + +/* Some architectures -- Alpha for one -- use "segment" schemes that + require all bits to be preserved, thus the i386 traditional `ushort' + doesn't work. To head off problems early, force the Intel folks + to do it Right as well. */ + +#define set_fs(x) (current->tss.segment = \ + sizeof(x) == sizeof(unsigned long) ? (x) \ + : __bad_fs_size()) /* * Address Ok: diff -u --recursive --new-file v2.1.53/linux/include/asm-mips/floppy.h linux/include/asm-mips/floppy.h --- v2.1.53/linux/include/asm-mips/floppy.h Mon Aug 18 18:19:46 1997 +++ linux/include/asm-mips/floppy.h Sat Sep 6 10:09:56 1997 @@ -95,6 +95,8 @@ #define N_FDC 1 /* do you *really* want a second controller? */ #define N_DRIVE 8 +#define FLOPPY_MOTOR_MASK 0xf0 + /* * The DMA channel used by the floppy controller cannot access data at * addresses >= 16MB diff -u --recursive --new-file v2.1.53/linux/include/asm-mips/namei.h linux/include/asm-mips/namei.h --- v2.1.53/linux/include/asm-mips/namei.h Thu Sep 4 17:07:31 1997 +++ linux/include/asm-mips/namei.h Sat Sep 6 10:04:16 1997 @@ -25,7 +25,16 @@ if (IS_ERR (base)) return base; - return lookup_dentry (name, base, follow_link); + base = lookup_dentry (name, base, follow_link); + + if (IS_ERR (base)) return base; + + if (!base->d_inode) { + dput(base); + return ERR_PTR(-ENOENT); + } + + return base; } #ifdef CONFIG_BINFMT_IRIX diff -u --recursive --new-file v2.1.53/linux/include/asm-ppc/floppy.h linux/include/asm-ppc/floppy.h --- v2.1.53/linux/include/asm-ppc/floppy.h Wed Dec 18 00:54:09 1996 +++ linux/include/asm-ppc/floppy.h Sat Sep 6 10:09:56 1997 @@ -46,6 +46,8 @@ #define N_FDC 2 /* Don't change this! */ #define N_DRIVE 8 +#define FLOPPY_MOTOR_MASK 0xf0 + /* * The PowerPC has no problems with floppy DMA crossing 64k borders. */ diff -u --recursive --new-file v2.1.53/linux/include/asm-sparc/namei.h linux/include/asm-sparc/namei.h --- v2.1.53/linux/include/asm-sparc/namei.h Thu Sep 4 17:07:31 1997 +++ linux/include/asm-sparc/namei.h Sat Sep 6 10:04:16 1997 @@ -1,4 +1,4 @@ -/* $Id: namei.h,v 1.7 1997/08/29 15:52:27 jj Exp $ +/* $Id: namei.h,v 1.8 1997/09/05 12:38:51 jj Exp $ * linux/include/asm-sparc/namei.h * * Routines to handle famous /usr/gnemul/s*. @@ -31,7 +31,16 @@ if (IS_ERR (base)) return base; - return lookup_dentry (name, base, follow_link); + base = lookup_dentry (name, base, follow_link); + + if (IS_ERR (base)) return base; + + if (!base->d_inode) { + dput(base); + return ERR_PTR(-ENOENT); + } + + return base; } #define __prefix_lookup_dentry(name, follow_link) \ diff -u --recursive --new-file v2.1.53/linux/include/asm-sparc64/ebus.h linux/include/asm-sparc64/ebus.h --- v2.1.53/linux/include/asm-sparc64/ebus.h Thu Sep 4 17:07:31 1997 +++ linux/include/asm-sparc64/ebus.h Sat Sep 6 10:04:16 1997 @@ -1,4 +1,4 @@ -/* $Id: ebus.h,v 1.2 1997/08/17 22:40:07 ecd Exp $ +/* $Id: ebus.h,v 1.3 1997/09/05 23:00:14 ecd Exp $ * ebus.h: PCI to Ebus pseudo driver software state. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -9,8 +9,20 @@ #include +struct linux_ebus_child { + struct linux_ebus_child *next; + struct linux_ebus_device *parent; + int prom_node; + char prom_name[64]; + unsigned long base_address[PROMREG_MAX]; + int num_addrs; + unsigned int irqs[PROMINTR_MAX]; + int num_irqs; +}; + struct linux_ebus_device { struct linux_ebus_device *next; + struct linux_ebus_child *children; struct linux_ebus *parent; int prom_node; char prom_name[64]; @@ -19,7 +31,7 @@ unsigned int irqs[PROMINTR_MAX]; int num_irqs; }; - + struct linux_ebus { struct linux_ebus *next; struct linux_ebus_device *devices; @@ -31,6 +43,39 @@ int num_ebus_ranges; }; +struct linux_ebus_dma { + unsigned int dcsr; + unsigned int dacr; + unsigned int dbcr; +}; + +#define EBUS_DCSR_INT_PEND 0x00000001 +#define EBUS_DCSR_ERR_PEND 0x00000002 +#define EBUS_DCSR_DRAIN 0x00000004 +#define EBUS_DCSR_INT_EN 0x00000010 +#define EBUS_DCSR_RESET 0x00000080 +#define EBUS_DCSR_WRITE 0x00000100 +#define EBUS_DCSR_EN_DMA 0x00000200 +#define EBUS_DCSR_CYC_PEND 0x00000400 +#define EBUS_DCSR_DIAG_RD_DONE 0x00000800 +#define EBUS_DCSR_DIAG_WR_DONE 0x00001000 +#define EBUS_DCSR_EN_CNT 0x00002000 +#define EBUS_DCSR_TC 0x00004000 +#define EBUS_DCSR_DIS_CSR_DRN 0x00010000 +#define EBUS_DCSR_BURST_SZ_MASK 0x000c0000 +#define EBUS_DCSR_BURST_SZ_1 0x00080000 +#define EBUS_DCSR_BURST_SZ_4 0x00000000 +#define EBUS_DCSR_BURST_SZ_8 0x00040000 +#define EBUS_DCSR_BURST_SZ_16 0x000c0000 +#define EBUS_DCSR_DIAG_EN 0x00100000 +#define EBUS_DCSR_DIS_ERR_PEND 0x00400000 +#define EBUS_DCSR_TCI_DIS 0x00800000 +#define EBUS_DCSR_EN_NEXT 0x01000000 +#define EBUS_DCSR_DMA_ON 0x02000000 +#define EBUS_DCSR_A_LOADED 0x04000000 +#define EBUS_DCSR_NA_LOADED 0x08000000 +#define EBUS_DCSR_DEV_ID_MASK 0xf0000000 + extern struct linux_ebus *ebus_chain; extern unsigned long ebus_init(unsigned long, unsigned long); @@ -40,6 +85,9 @@ #define for_each_ebusdev(dev, bus) \ for((dev) = (bus)->devices; (dev); (dev) = (dev)->next) + +#define for_each_edevchild(dev, child) \ + for((child) = (dev)->children; (child); (child) = (child)->next) #define for_all_ebusdev(dev, bus) \ for ((bus) = ebus_chain, ((dev) = (bus) ? (bus)->devices : 0); \ diff -u --recursive --new-file v2.1.53/linux/include/asm-sparc64/floppy.h linux/include/asm-sparc64/floppy.h --- v2.1.53/linux/include/asm-sparc64/floppy.h Thu Jul 17 10:06:08 1997 +++ linux/include/asm-sparc64/floppy.h Sat Sep 6 10:09:56 1997 @@ -1,13 +1,17 @@ -/* $Id: floppy.h,v 1.3 1997/07/11 03:03:22 davem Exp $ +/* $Id: floppy.h,v 1.4 1997/09/05 23:00:15 ecd Exp $ * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * + * Ultra/PCI support added: Sep 1997 Eddie C. Dost (ecd@skynet.be) */ #ifndef __ASM_SPARC64_FLOPPY_H #define __ASM_SPARC64_FLOPPY_H +#include + #include #include #include @@ -23,19 +27,12 @@ * 3) Intel 82077 controller manual */ struct sun_flpy_controller { - volatile unsigned char status_82072; /* Main Status reg. */ -#define dcr_82072 status_82072 /* Digital Control reg. */ -#define status1_82077 status_82072 /* Auxiliary Status reg. 1 */ - - volatile unsigned char data_82072; /* Data fifo. */ -#define status2_82077 data_82072 /* Auxiliary Status reg. 2 */ - + volatile unsigned char status1_82077; /* Auxiliary Status reg. 1 */ + volatile unsigned char status2_82077; /* Auxiliary Status reg. 2 */ volatile unsigned char dor_82077; /* Digital Output reg. */ volatile unsigned char tapectl_82077; /* What the? Tape control reg? */ - volatile unsigned char status_82077; /* Main Status Register. */ #define drs_82077 status_82077 /* Digital Rate Select reg. */ - volatile unsigned char data_82077; /* Data fifo. */ volatile unsigned char ___unused; volatile unsigned char dir_82077; /* Digital Input reg. */ @@ -47,40 +44,42 @@ volatile unsigned char *fdc_status; struct sun_floppy_ops { - unsigned char (*fd_inb)(int port); - void (*fd_outb)(unsigned char value, int port); + unsigned char (*fd_inb) (unsigned long port); + void (*fd_outb) (unsigned char value, unsigned long port); + void (*fd_enable_dma) (void); + void (*fd_disable_dma) (void); + void (*fd_set_dma_mode) (int); + void (*fd_set_dma_addr) (char *); + void (*fd_set_dma_count) (int); + unsigned int (*get_dma_residue) (void); + void (*fd_enable_irq) (void); + void (*fd_disable_irq) (void); + int (*fd_request_irq) (void); + void (*fd_free_irq) (void); + int (*fd_eject) (int); }; static struct sun_floppy_ops sun_fdops; #define fd_inb(port) sun_fdops.fd_inb(port) #define fd_outb(value,port) sun_fdops.fd_outb(value,port) -#define fd_enable_dma() sun_fd_enable_dma() -#define fd_disable_dma() sun_fd_disable_dma() +#define fd_enable_dma() sun_fdops.fd_enable_dma() +#define fd_disable_dma() sun_fdops.fd_disable_dma() #define fd_request_dma() (0) /* nothing... */ #define fd_free_dma() /* nothing... */ #define fd_clear_dma_ff() /* nothing... */ -#define fd_set_dma_mode(mode) sun_fd_set_dma_mode(mode) -#define fd_set_dma_addr(addr) sun_fd_set_dma_addr(addr) -#define fd_set_dma_count(count) sun_fd_set_dma_count(count) -#define fd_enable_irq() /* nothing... */ -#define fd_disable_irq() /* nothing... */ +#define fd_set_dma_mode(mode) sun_fdops.fd_set_dma_mode(mode) +#define fd_set_dma_addr(addr) sun_fdops.fd_set_dma_addr(addr) +#define fd_set_dma_count(count) sun_fdops.fd_set_dma_count(count) +#define get_dma_residue(x) sun_fdops.get_dma_residue() +#define fd_enable_irq() sun_fdops.fd_enable_irq() +#define fd_disable_irq() sun_fdops.fd_disable_irq() #define fd_cacheflush(addr, size) /* nothing... */ -#define fd_request_irq() sun_fd_request_irq() -#define fd_free_irq() /* nothing... */ -#if 0 /* P3: added by Alain, these cause a MMU corruption. 19960524 XXX */ -#define fd_dma_mem_alloc(size) ((unsigned long) vmalloc(size)) -#define fd_dma_mem_free(addr,size) (vfree((void *)(addr))) -#endif - -#define FLOPPY_MOTOR_MASK 0x10 - -/* It's all the same... */ -#define virt_to_bus(x) (x) -#define bus_to_virt(x) (x) +#define fd_request_irq() sun_fdops.fd_request_irq() +#define fd_free_irq() sun_fdops.fd_free_irq() +#define fd_eject(drive) sun_fdops.fd_eject(drive) -/* XXX This isn't really correct. XXX */ -#define get_dma_residue(x) (0) +static int FLOPPY_MOTOR_MASK = 0x10; #define FLOPPY0_TYPE 4 #define FLOPPY1_TYPE 0 @@ -94,7 +93,7 @@ */ #define FDC1 sun_floppy_init() -static int FDC2=-1; +static int FDC2 = -1; #define N_FDC 1 #define N_DRIVE 8 @@ -102,63 +101,11 @@ /* No 64k boundary crossing problems on the Sparc. */ #define CROSS_64KB(a,s) (0) -/* Routines unique to each controller type on a Sun. */ -static unsigned char sun_82072_fd_inb(int port) +static unsigned char sun_82077_fd_inb(unsigned long port) { switch(port & 7) { default: - printk("floppy: Asked to read unknown port %d\n", port); - panic("floppy: Port bolixed."); - case 4: /* FD_STATUS */ - return sun_fdc->status_82072 & ~STATUS_DMA; - case 5: /* FD_DATA */ - return sun_fdc->data_82072; - case 7: /* FD_DIR */ - return (*AUXREG & AUXIO_FLPY_DCHG)? 0x80: 0; - }; - panic("sun_82072_fd_inb: How did I get here?"); -} - -static void sun_82072_fd_outb(unsigned char value, int port) -{ - switch(port & 7) { - default: - printk("floppy: Asked to write to unknown port %d\n", port); - panic("floppy: Port bolixed."); - case 2: /* FD_DOR */ - /* Oh geese, 82072 on the Sun has no DOR register, - * the functionality is implemented via the AUXIO - * I/O register. So we must emulate the behavior. - * - * ASSUMPTIONS: There will only ever be one floppy - * drive attached to a Sun controller - * and it will be at drive zero. - */ - { - unsigned bits = 0; - if (value & 0x10) bits |= AUXIO_FLPY_DSEL; - if ((value & 0x80) == 0) bits |= AUXIO_FLPY_EJCT; - set_auxio(bits, (~bits) & (AUXIO_FLPY_DSEL|AUXIO_FLPY_EJCT)); - } - break; - case 5: /* FD_DATA */ - sun_fdc->data_82072 = value; - break; - case 7: /* FD_DCR */ - sun_fdc->dcr_82072 = value; - break; - case 4: /* FD_STATUS */ - sun_fdc->status_82072 = value; - break; - }; - return; -} - -static unsigned char sun_82077_fd_inb(int port) -{ - switch(port & 7) { - default: - printk("floppy: Asked to read unknown port %d\n", port); + printk("floppy: Asked to read unknown port %lx\n", port); panic("floppy: Port bolixed."); case 4: /* FD_STATUS */ return sun_fdc->status_82077 & ~STATUS_DMA; @@ -171,11 +118,11 @@ panic("sun_82072_fd_inb: How did I get here?"); } -static void sun_82077_fd_outb(unsigned char value, int port) +static void sun_82077_fd_outb(unsigned char value, unsigned long port) { switch(port & 7) { default: - printk("floppy: Asked to write to unknown port %d\n", port); + printk("floppy: Asked to write to unknown port %lx\n", port); panic("floppy: Port bolixed."); case 2: /* FD_DOR */ /* Happily, the 82077 has a real DOR register. */ @@ -218,7 +165,7 @@ /* nothing... */ } -static __inline__ void sun_fd_disable_dma(void) +static void sun_fd_disable_dma(void) { doing_pdma = 0; if (pdma_base) { @@ -227,7 +174,7 @@ } } -static __inline__ void sun_fd_set_dma_mode(int mode) +static void sun_fd_set_dma_mode(int mode) { switch(mode) { case DMA_MODE_READ: @@ -242,17 +189,17 @@ } } -static __inline__ void sun_fd_set_dma_addr(char *buffer) +static void sun_fd_set_dma_addr(char *buffer) { pdma_vaddr = buffer; } -static __inline__ void sun_fd_set_dma_count(int length) +static void sun_fd_set_dma_count(int length) { pdma_size = length; } -static __inline__ void sun_fd_enable_dma(void) +static void sun_fd_enable_dma(void) { pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size); pdma_base = pdma_vaddr; @@ -274,23 +221,207 @@ } else return 0; } +static void sun_fd_enable_irq(void) +{ +} + +static void sun_fd_disable_irq(void) +{ +} + +static void sun_fd_free_irq(void) +{ +} + +static unsigned int sun_get_dma_residue(void) +{ + /* XXX This isn't really correct. XXX */ + return 0; +} + +static int sun_fd_eject(int drive) +{ + set_dor(0x00, 0xff, 0x90); + udelay(500); + set_dor(0x00, 0x6f, 0x00); + udelay(500); + return 0; +} + +#ifdef CONFIG_PCI +#include + +static struct linux_ebus_dma *sun_fd_ebus_dma; + +extern void floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs); + +static unsigned char sun_pci_fd_inb(unsigned long port) +{ + return inb(port); +} + +static void sun_pci_fd_outb(unsigned char val, unsigned long port) +{ + outb(val, port); +} + +static void sun_pci_fd_enable_dma(void) +{ + unsigned int dcsr; + + dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr); + dcsr |= (EBUS_DCSR_EN_DMA | EBUS_DCSR_EN_CNT); + writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr); +} + +static void sun_pci_fd_disable_dma(void) +{ + unsigned int dcsr; + + dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr); + dcsr &= ~(EBUS_DCSR_EN_DMA | EBUS_DCSR_EN_CNT); + writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr); +} + +static void sun_pci_fd_set_dma_mode(int mode) +{ + unsigned int dcsr; + + dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr); + /* + * For EBus WRITE means to system memory, which is + * READ for us. + */ + if (mode == DMA_MODE_WRITE) + dcsr &= ~(EBUS_DCSR_WRITE); + else + dcsr |= EBUS_DCSR_WRITE; + writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr); +} + +static void sun_pci_fd_set_dma_count(int length) +{ + writel(length, (unsigned long)&sun_fd_ebus_dma->dbcr); +} + +static void sun_pci_fd_set_dma_addr(char *buffer) +{ + unsigned int addr; + + addr = virt_to_bus(buffer); + writel(addr, (unsigned long)&sun_fd_ebus_dma->dacr); +} + +static void sun_pci_fd_enable_irq(void) +{ + unsigned int dcsr; + + dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr); + dcsr |= EBUS_DCSR_INT_EN; + writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr); +} + +static void sun_pci_fd_disable_irq(void) +{ + unsigned int dcsr; + + dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr); + dcsr &= ~(EBUS_DCSR_INT_EN); + writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr); +} + +static int sun_pci_fd_request_irq(void) +{ + int error; + + error = request_irq(FLOPPY_IRQ, floppy_interrupt, SA_SHIRQ, "floppy", sun_fdc); + return ((error == 0) ? 0 : -1); +} + +static void sun_pci_fd_free_irq(void) +{ + free_irq(FLOPPY_IRQ, sun_fdc); +} + +static unsigned int sun_pci_get_dma_residue(void) +{ + unsigned int res; + + res = readl((unsigned long)&sun_fd_ebus_dma->dbcr); + return res; +} + +static int sun_pci_fd_eject(int drive) +{ + return -EINVAL; +} +#endif + static struct linux_prom_registers fd_regs[2]; -static int sun_floppy_init(void) +static unsigned long sun_floppy_init(void) { char state[128]; int fd_node, num_regs; struct linux_sbus *bus; struct linux_sbus_device *sdev; - use_virtual_dma = 1; - FLOPPY_IRQ = 11; for_all_sbusdev (sdev, bus) { if (!strcmp(sdev->prom_name, "SUNW,fdtwo")) break; } - if (!bus) return -1; + if (!bus) { +#ifdef CONFIG_PCI + struct linux_ebus *ebus; + struct linux_ebus_device *edev; + + for_all_ebusdev(edev, ebus) { + if (!strcmp(edev->prom_name, "fdthree")) + break; + } + if (!edev) + return -1; + + if (check_region(edev->base_address[1], sizeof(struct linux_ebus_dma))) { + printk("sun_floppy_init: can't get region %016lx (%d)\n", + edev->base_address[1], (int)sizeof(struct linux_ebus_dma)); + return -1; + } + request_region(edev->base_address[1], sizeof(struct linux_ebus_dma), "floppy DMA"); + + sun_fdc = (struct sun_flpy_controller *)edev->base_address[0]; + FLOPPY_IRQ = edev->irqs[0]; + + sun_fd_ebus_dma = (struct linux_ebus_dma *)edev->base_address[1]; + writel(EBUS_DCSR_BURST_SZ_16, (unsigned long)&sun_fd_ebus_dma->dcsr); + + sun_fdops.fd_inb = sun_pci_fd_inb; + sun_fdops.fd_outb = sun_pci_fd_outb; + + use_virtual_dma = 0; + sun_fdops.fd_enable_dma = sun_pci_fd_enable_dma; + sun_fdops.fd_disable_dma = sun_pci_fd_disable_dma; + sun_fdops.fd_set_dma_mode = sun_pci_fd_set_dma_mode; + sun_fdops.fd_set_dma_addr = sun_pci_fd_set_dma_addr; + sun_fdops.fd_set_dma_count = sun_pci_fd_set_dma_count; + sun_fdops.get_dma_residue = sun_pci_get_dma_residue; + + sun_fdops.fd_enable_irq = sun_pci_fd_enable_irq; + sun_fdops.fd_disable_irq = sun_pci_fd_disable_irq; + sun_fdops.fd_request_irq = sun_pci_fd_request_irq; + sun_fdops.fd_free_irq = sun_pci_fd_free_irq; + + sun_fdops.fd_eject = sun_pci_fd_eject; + + fdc_status = &sun_fdc->status_82077; + FLOPPY_MOTOR_MASK = 0xf0; + + return (unsigned long)sun_fdc; +#else + return -1; +#endif + } fd_node = sdev->prom_node; prom_getproperty(fd_node, "status", state, sizeof(state)); if(!strcmp(state, "disabled")) return -1; @@ -304,29 +435,34 @@ fd_regs[0].which_io, 0x0); /* Last minute sanity check... */ - if(sun_fdc->status_82072 == 0xff) { + if(sun_fdc->status1_82077 == 0xff) { sun_fdc = NULL; return -1; } sun_fdops.fd_inb = sun_82077_fd_inb; sun_fdops.fd_outb = sun_82077_fd_outb; + + use_virtual_dma = 1; + sun_fdops.fd_enable_dma = sun_fd_enable_dma; + sun_fdops.fd_disable_dma = sun_fd_disable_dma; + sun_fdops.fd_set_dma_mode = sun_fd_set_dma_mode; + sun_fdops.fd_set_dma_addr = sun_fd_set_dma_addr; + sun_fdops.fd_set_dma_count = sun_fd_set_dma_count; + sun_fdops.get_dma_residue = sun_get_dma_residue; + + sun_fdops.fd_enable_irq = sun_fd_enable_irq; + sun_fdops.fd_disable_irq = sun_fd_disable_irq; + sun_fdops.fd_request_irq = sun_fd_request_irq; + sun_fdops.fd_free_irq = sun_fd_free_irq; + + sun_fdops.fd_eject = sun_fd_eject; + fdc_status = &sun_fdc->status_82077; /* printk("DOR @0x%p\n", &sun_fdc->dor_82077); */ /* P3 */ /* Success... */ - return (int) ((unsigned long)sun_fdc); + return (unsigned long)sun_fdc; } - -static int sparc_eject(void) -{ - set_dor(0x00, 0xff, 0x90); - udelay(500); - set_dor(0x00, 0x6f, 0x00); - udelay(500); - return 0; -} - -#define fd_eject(drive) sparc_eject() #endif /* !(__ASM_SPARC64_FLOPPY_H) */ diff -u --recursive --new-file v2.1.53/linux/include/asm-sparc64/namei.h linux/include/asm-sparc64/namei.h --- v2.1.53/linux/include/asm-sparc64/namei.h Thu Sep 4 17:07:31 1997 +++ linux/include/asm-sparc64/namei.h Sat Sep 6 10:04:16 1997 @@ -1,4 +1,4 @@ -/* $Id: namei.h,v 1.7 1997/09/04 15:46:31 jj Exp $ +/* $Id: namei.h,v 1.8 1997/09/06 02:25:27 davem Exp $ * linux/include/asm-sparc64/namei.h * * Routines to handle famous /usr/gnemul/s*. @@ -14,7 +14,6 @@ static inline struct dentry * __sparc64_lookup_dentry(const char *name, int follow_link) { - int error; struct dentry *base; switch (current->personality) { diff -u --recursive --new-file v2.1.53/linux/include/linux/arcdevice.h linux/include/linux/arcdevice.h --- v2.1.53/linux/include/linux/arcdevice.h Thu Sep 4 17:07:31 1997 +++ linux/include/linux/arcdevice.h Sat Sep 6 10:05:42 1997 @@ -5,7 +5,7 @@ * * Definitions for the ARCnet handlers. * - * Version: @(#)arcdevice.h 1.0 31/07/97 + * Version: $Id: arcdevice.h,v 1.2 1997/09/05 08:57:56 mj Exp $ * * Authors: Avery Pennarun * David Woodhouse @@ -24,7 +24,6 @@ #ifdef __KERNEL__ - #define ARC_20020 1 #define ARC_RIM_I 2 #define ARC_90xx 3 @@ -50,6 +49,7 @@ #define DETECT_RECONFIGS #undef SHOW_RECONFIGS + /* RECON_THRESHOLD is the maximum number of RECON messages to receive within * one minute before printing a "cabling problem" warning. You must have * DETECT_RECONFIGS enabled if you want to use this. The default value @@ -62,6 +62,7 @@ */ #define RECON_THRESHOLD 30 + /* Define this to the minimum "timeout" value. If a transmit takes longer * than TX_TIMEOUT jiffies, Linux will abort the TX and retry. On a large * network, or one with heavy network traffic, this timeout may need to be @@ -71,6 +72,11 @@ #define TX_TIMEOUT 20 +/* Display warnings about the driver being an ALPHA version. + */ +#define ALPHA_WARNING + + /* New debugging bitflags: each option can be enabled individually. * * These can be set while the driver is running by typing: @@ -195,7 +201,6 @@ }; - /* the "client data" header - RFC1201 information * notice that this screws up if it's not an even number of bytes * @@ -235,7 +240,6 @@ #define S_EXTRA_CLIENTDATA (sizeof(struct S_ClientData)-1) - /* "Incoming" is information needed for each address that could be sending * to us. Mostly for partially-received split packets. */ @@ -260,7 +264,6 @@ }; - struct arcnet_local { struct net_device_stats stats; u_short sequence; /* sequence number (incs with each packet) */ @@ -268,12 +271,12 @@ u_char stationid, /* our 8-bit station address */ recbuf, /* receive buffer # (0 or 1) */ txbuf, /* transmit buffer # (2 or 3) */ - txready, /* buffer where a packet is ready to send */ - config, /* current value of CONFIG register */ - timeout, /* Extended timeout for COM20020 */ - backplane, /* Backplane flag for COM20020 */ - setup, /* Contents of setup register */ - intmask; /* current value of INTMASK register */ + txready, /* buffer where a packet is ready to send */ + config, /* current value of CONFIG register */ + timeout, /* Extended timeout for COM20020 */ + backplane, /* Backplane flag for COM20020 */ + setup, /* Contents of setup register */ + intmask; /* current value of INTMASK register */ short intx, /* in TX routine? */ in_txhandler, /* in TX_IRQ handler? */ sending, /* transmit in progress? */ @@ -282,8 +285,8 @@ #if defined(DETECT_RECONFIGS) && defined(RECON_THRESHOLD) time_t first_recon, /* time of "first" RECON message to count */ - last_recon; /* time of most recent RECON */ - int num_recons, /* number of RECONs between first and last. */ + last_recon; /* time of most recent RECON */ + int num_recons, /* number of RECONs between first and last. */ network_down; /* do we think the network is down? */ #endif @@ -302,8 +305,7 @@ void (*en_dis_able_TX) (struct device *dev, int enable); void (*prepare_tx)(struct device *dev,u_char *hdr,int hdrlen, char *data,int length,int daddr,int exceptA, int offset); - void (*openclose_device)(int open); - + void (*openclose_device)(int open); struct device *adev; /* RFC1201 protocol device */ @@ -318,12 +320,34 @@ #ifdef CONFIG_ARCNET_1051 struct device *sdev; /* RFC1051 protocol device */ #endif +}; +/* Functions exported by arcnet.c + */ -}; +#if ARCNET_DEBUG_MAX & D_SKB +extern void arcnet_dump_skb(struct device *dev,struct sk_buff *skb, + char *desc); +#else +#define arcnet_dump_skb(dev,skb,desc) ; +#endif +#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX) +extern void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext, + char *desc); +#else +#define arcnet_dump_packet(dev,buffer,ext,desc) ; +#endif -#endif /* __KERNEL__ */ -#endif /* _LINUX_ARCDEVICE_H */ +extern void arcnet_tx_done(struct device *dev, struct arcnet_local *lp); +extern void arcnet_makename(char *device); +extern void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs); +extern void arcnet_setup(struct device *dev); +extern int arcnet_go_tx(struct device *dev,int enable_irq); +extern void arcnetA_continue_tx(struct device *dev); +extern void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr); +extern void arcnet_use_count(int open); +#endif /* __KERNEL__ */ +#endif /* _LINUX_ARCDEVICE_H */ diff -u --recursive --new-file v2.1.53/linux/include/linux/fd.h linux/include/linux/fd.h --- v2.1.53/linux/include/linux/fd.h Sun Jan 19 05:27:58 1997 +++ linux/include/linux/fd.h Sat Sep 6 10:09:56 1997 @@ -248,7 +248,7 @@ int dtr; unsigned char version; /* FDC version code */ unsigned char dor; - int address; /* io address */ + unsigned long address; /* io address */ unsigned int rawcmd:2; unsigned int reset:1; unsigned int need_configure:1; diff -u --recursive --new-file v2.1.53/linux/include/linux/if_arcnet.h linux/include/linux/if_arcnet.h --- v2.1.53/linux/include/linux/if_arcnet.h Thu Sep 4 17:07:31 1997 +++ linux/include/linux/if_arcnet.h Sat Sep 6 10:05:42 1997 @@ -5,7 +5,7 @@ * * Global definitions for the ARCnet interface. * - * Version: @(#)if_arcnet.h 1.0 07/08/97 + * Version: $Id: if_arcnet.h,v 1.2 1997/09/05 08:57:54 mj Exp $ * * Author: David Woodhouse * Avery Pennarun @@ -50,7 +50,7 @@ /* * This is an ARCnet frame header. */ - + struct archdr /* was struct HardHeader */ { u_char source, /* source ARCnet - filled in automagically */ @@ -61,4 +61,3 @@ }; #endif /* _LINUX_IF_ARCNET_H */ - diff -u --recursive --new-file v2.1.53/linux/include/linux/kernel.h linux/include/linux/kernel.h --- v2.1.53/linux/include/linux/kernel.h Mon Jun 30 15:23:11 1997 +++ linux/include/linux/kernel.h Fri Sep 5 20:30:43 1997 @@ -68,6 +68,16 @@ */ #define fsuser() (current->fsuid == 0) +/* + * Display an IP address in readable format. + */ + +#define NIPQUAD(addr) \ + (((addr) >> 0) & 0xff), \ + (((addr) >> 8) & 0xff), \ + (((addr) >> 16) & 0xff), \ + (((addr) >> 24) & 0xff) + #endif /* __KERNEL__ */ #define SI_LOAD_SHIFT 16 diff -u --recursive --new-file v2.1.53/linux/include/linux/openpic.h linux/include/linux/openpic.h --- v2.1.53/linux/include/linux/openpic.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/openpic.h Sat Sep 6 10:04:16 1997 @@ -0,0 +1,364 @@ +/* + * linux/openpic.h -- OpenPIC definitions + * + * Copyright (C) 1997 Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * This file is based on the following documentation: + * + * The Open Programmable Interrupt Controller (PIC) + * Register Interface Specification Revision 1.2 + * + * Issue Date: October 1995 + * + * Issued jointly by Advanced Micro Devices and Cyrix Corporation + * + * AMD is a registered trademark of Advanced Micro Devices, Inc. + * Copyright (C) 1995, Advanced Micro Devices, Inc. and Cyrix, Inc. + * All Rights Reserved. + * + * To receive a copy of this documentation, send an email to openpic@amd.com. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#ifndef _LINUX_OPENPIC_H +#define _LINUX_OPENPIC_H + +#if !defined(__powerpc__) && !defined(__i386__) +#error Unsupported OpenPIC platform +#endif + + +#ifdef __KERNEL__ + + /* + * OpenPIC supports up to 2048 interrupt sources and up to 32 processors + */ + +#define OPENPIC_MAX_SOURCES 2048 +#define OPENPIC_MAX_PROCESSORS 32 + +#define OPENPIC_NUM_TIMERS 4 +#define OPENPIC_NUM_IPI 4 +#define OPENPIC_NUM_PRI 16 +#define OPENPIC_NUM_VECTORS 256 + + + /* + * OpenPIC Registers are 32 bits and aligned on 128 bit boundaries + */ + +typedef struct _OpenPIC_Reg { + u_int Reg; /* Little endian! */ + char Pad[0xc]; +} OpenPIC_Reg; + + + /* + * Per Processor Registers + */ + +typedef struct _OpenPIC_Processor { + /* + * Private Shadow Registers (for SLiC backwards compatibility) + */ + u_int IPI0_Dispatch_Shadow; /* Write Only */ + char Pad1[0x4]; + u_int IPI0_Vector_Priority_Shadow; /* Read/Write */ + char Pad2[0x34]; + /* + * Interprocessor Interrupt Command Ports + */ + OpenPIC_Reg _IPI_Dispatch[OPENPIC_NUM_IPI]; /* Write Only */ + /* + * Current Task Priority Register + */ + OpenPIC_Reg _Current_Task_Priority; /* Read/Write */ +#ifndef __powerpc__ + /* + * Who Am I Register + */ + OpenPIC_Reg _Who_Am_I; /* Read Only */ +#else + char Pad3[0x10]; +#endif +#ifndef __i386__ + /* + * Interrupt Acknowledge Register + */ + OpenPIC_Reg _Interrupt_Acknowledge; /* Read Only */ +#else + char Pad4[0x10]; +#endif + /* + * End of Interrupt (EOI) Register + */ + OpenPIC_Reg _EOI; /* Read/Write */ + char Pad5[0xf40]; +} OpenPIC_Processor; + + + /* + * Timer Registers + */ + +typedef struct _OpenPIC_Timer { + OpenPIC_Reg _Current_Count; /* Read Only */ + OpenPIC_Reg _Base_Count; /* Read/Write */ + OpenPIC_Reg _Vector_Priority; /* Read/Write */ + OpenPIC_Reg _Destination; /* Read/Write */ +} OpenPIC_Timer; + + + /* + * Global Registers + */ + +typedef struct _OpenPIC_Global { + /* + * Feature Reporting Registers + */ + OpenPIC_Reg _Feature_Reporting0; /* Read Only */ + OpenPIC_Reg _Feature_Reporting1; /* Future Expansion */ + /* + * Global Configuration Registers + */ + OpenPIC_Reg _Global_Configuration0; /* Read/Write */ + OpenPIC_Reg _Global_Configuration1; /* Future Expansion */ + /* + * Vendor Specific Registers + */ + OpenPIC_Reg _Vendor_Specific[4]; + /* + * Vendor Identification Register + */ + OpenPIC_Reg _Vendor_Identification; /* Read Only */ + /* + * Processor Initialization Register + */ + OpenPIC_Reg _Processor_Initialization; /* Read/Write */ + /* + * IPI Vector/Priority Registers + */ + OpenPIC_Reg _IPI_Vector_Priority[OPENPIC_NUM_IPI]; /* Read/Write */ + /* + * Spurious Vector Register + */ + OpenPIC_Reg _Spurious_Vector; /* Read/Write */ + /* + * Global Timer Registers + */ + OpenPIC_Reg _Timer_Frequency; /* Read/Write */ + OpenPIC_Timer Timer[OPENPIC_NUM_TIMERS]; + char Pad1[0xee00]; +} OpenPIC_Global; + + + /* + * Interrupt Source Registers + */ + +typedef struct _OpenPIC_Source { + OpenPIC_Reg _Vector_Priority; /* Read/Write */ + OpenPIC_Reg _Destination; /* Read/Write */ +} OpenPIC_Source; + + + /* + * OpenPIC Register Map + */ + +struct OpenPIC { +#ifndef __powerpc__ + /* + * Per Processor Registers --- Private Access + */ + OpenPIC_Processor Private; +#else + char Pad1[0x1000]; +#endif + /* + * Global Registers + */ + OpenPIC_Global Global; + /* + * Interrupt Source Configuration Registers + */ + OpenPIC_Source Source[OPENPIC_MAX_SOURCES]; + /* + * Per Processor Registers + */ + OpenPIC_Processor Processor[OPENPIC_MAX_PROCESSORS]; +}; + +extern volatile struct OpenPIC *OpenPIC; + + + /* + * Current Task Priority Register + */ + +#define OPENPIC_CURRENT_TASK_PRIORITY_MASK 0x0000000f + + /* + * Who Am I Register + */ + +#define OPENPIC_WHO_AM_I_ID_MASK 0x0000001f + + /* + * Feature Reporting Register 0 + */ + +#define OPENPIC_FEATURE_LAST_SOURCE_MASK 0x07ff0000 +#define OPENPIC_FEATURE_LAST_SOURCE_SHIFT 16 +#define OPENPIC_FEATURE_LAST_PROCESSOR_MASK 0x00001f00 +#define OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT 8 +#define OPENPIC_FEATURE_VERSION_MASK 0x000000ff + + /* + * Global Configuration Register 0 + */ + +#define OPENPIC_CONFIG_RESET 0x80000000 +#define OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE 0x20000000 +#define OPENPIC_CONFIG_BASE_MASK 0x000fffff + + /* + * Vendor Identification Register + */ + +#define OPENPIC_VENDOR_ID_STEPPING_MASK 0x00ff0000 +#define OPENPIC_VENDOR_ID_STEPPING_SHIFT 16 +#define OPENPIC_VENDOR_ID_DEVICE_ID_MASK 0x0000ff00 +#define OPENPIC_VENDOR_ID_DEVICE_ID_SHIFT 8 +#define OPENPIC_VENDOR_ID_VENDOR_ID_MASK 0x000000ff + + /* + * Vector/Priority Registers + */ + +#define OPENPIC_MASK 0x80000000 +#define OPENPIC_ACTIVITY 0x40000000 /* Read Only */ +#define OPENPIC_PRIORITY_MASK 0x000f0000 +#define OPENPIC_PRIORITY_SHIFT 16 +#define OPENPIC_VECTOR_MASK 0x000000ff + + + /* + * Interrupt Source Registers + */ + +#define OPENPIC_SENSE_POLARITY 0x00800000 /* Undoc'd */ +#define OPENPIC_SENSE_LEVEL 0x00400000 + + + /* + * Timer Registers + */ + +#define OPENPIC_COUNT_MASK 0x7fffffff +#define OPENPIC_TIMER_TOGGLE 0x80000000 +#define OPENPIC_TIMER_COUNT_INHIBIT 0x80000000 + + + /* + * Aliases to make life simpler + */ + +/* Per Processor Registers */ +#define IPI_Dispatch(i) _IPI_Dispatch[i].Reg +#define Current_Task_Priority _Current_Task_Priority.Reg +#ifndef __powerpc__ +#define Who_Am_I _Who_Am_I.Reg +#endif +#ifndef __i386__ +#define Interrupt_Acknowledge _Interrupt_Acknowledge.Reg +#endif +#define EOI _EOI.Reg + +/* Global Registers */ +#define Feature_Reporting0 _Feature_Reporting0.Reg +#define Feature_Reporting1 _Feature_Reporting1.Reg +#define Global_Configuration0 _Global_Configuration0.Reg +#define Global_Configuration1 _Global_Configuration1.Reg +#define Vendor_Specific(i) _Vendor_Specific[i].Reg +#define Vendor_Identification _Vendor_Identification.Reg +#define Processor_Initialization _Processor_Initialization.Reg +#define IPI_Vector_Priority(i) _IPI_Vector_Priority[i].Reg +#define Spurious_Vector _Spurious_Vector.Reg +#define Timer_Frequency _Timer_Frequency.Reg + +/* Timer Registers */ +#define Current_Count _Current_Count.Reg +#define Base_Count _Base_Count.Reg +#define Vector_Priority _Vector_Priority.Reg +#define Destination _Destination.Reg + +/* Interrupt Source Registers */ +#define Vector_Priority _Vector_Priority.Reg +#define Destination _Destination.Reg + + + /* + * Vendor and Device IDs + */ + +#define OPENPIC_VENDOR_ID_APPLE 0x14 +#define OPENPIC_DEVICE_ID_APPLE_HYDRA 0x46 + + + /* + * OpenPIC Operations + */ + +/* Global Operations */ +extern void openpic_init(void); +extern void openpic_reset(void); +extern void openpic_enable_8259_pass_through(void); +extern void openpic_disable_8259_pass_through(void); +#ifndef __i386__ +extern u_int openpic_irq(u_int cpu); +#endif +#ifndef __powerpc__ +extern void openpic_eoi(void); +extern u_int openpic_get_priority(void); +extern void openpic_set_priority(u_int pri); +#else +extern void openpic_eoi(u_int cpu); +extern u_int openpic_get_priority(u_int cpu); +extern void openpic_set_priority(u_int cpu, u_int pri); +#endif +extern u_int openpic_get_spurious(void); +extern void openpic_set_spurious(u_int vector); +extern void openpic_init_processor(u_int cpumask); + +/* Interprocessor Interrupts */ +extern void openpic_initipi(u_int ipi, u_int pri, u_int vector); +#ifndef __powerpc__ +extern void openpic_cause_IPI(u_int ipi, u_int cpumask); +#else +extern void openpic_cause_IPI(u_int cpu, u_int ipi, u_int cpumask); +#endif + +/* Timer Interrupts */ +extern void openpic_inittimer(u_int timer, u_int pri, u_int vector); +extern void openpic_maptimer(u_int timer, u_int cpumask); + +/* Interrupt Sources */ +extern void openpic_enable_irq(u_int irq); +extern void openpic_disable_irq(u_int irq); +extern void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity, + int is_level); +extern void openpic_mapirq(u_int irq, u_int cpumask); +extern void openpic_set_sense(u_int irq, int sense); + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_OPENPIC_H */ diff -u --recursive --new-file v2.1.53/linux/include/linux/pci.h linux/include/linux/pci.h --- v2.1.53/linux/include/linux/pci.h Thu Aug 14 20:49:17 1997 +++ linux/include/linux/pci.h Sat Sep 6 10:43:50 1997 @@ -256,6 +256,7 @@ #define PCI_DEVICE_ID_ADL_2301 0x2301 #define PCI_VENDOR_ID_NS 0x100b +#define PCI_DEVICE_ID_NS_87415 0x0002 #define PCI_DEVICE_ID_NS_87410 0xd001 #define PCI_VENDOR_ID_TSENG 0x100c @@ -274,6 +275,7 @@ #define PCI_DEVICE_ID_DEC_TULIP 0x0002 #define PCI_DEVICE_ID_DEC_TGA 0x0004 #define PCI_DEVICE_ID_DEC_TULIP_FAST 0x0009 +#define PCI_DEVICE_ID_DEC_TGA2 0x000D #define PCI_DEVICE_ID_DEC_FDDI 0x000F #define PCI_DEVICE_ID_DEC_TULIP_PLUS 0x0014 #define PCI_DEVICE_ID_DEC_21142 0x0019 @@ -441,6 +443,11 @@ #define PCI_DEVICE_ID_OLICOM_OC2326 0x0014 #define PCI_DEVICE_ID_OLICOM_OC6151 0x0021 +#define PCI_VENDOR_ID_SUN 0x108e +#define PCI_DEVICE_ID_SUN_EBUS 0x1000 +#define PCI_DEVICE_ID_SUN_HAPPYMEAL 0x1001 +#define PCI_DEVICE_ID_SUN_PBM 0x8000 + #define PCI_VENDOR_ID_CMD 0x1095 #define PCI_DEVICE_ID_CMD_640 0x0640 #define PCI_DEVICE_ID_CMD_643 0x0643 @@ -775,7 +782,12 @@ * necessary. The field must not be 0 unless the device * cannot generate interrupts at all. */ - unsigned char irq; /* irq generated by this device */ + unsigned int irq; /* irq generated by this device */ + + /* Base registers for this device, can be adjusted by + * pcibios_fixup() as necessary. + */ + unsigned long base_address[6]; }; struct pci_bus { @@ -811,6 +823,8 @@ extern unsigned long pci_init (unsigned long mem_start, unsigned long mem_end); + +extern unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp); extern struct pci_dev_info *pci_lookup_dev (unsigned int vendor, unsigned int dev); diff -u --recursive --new-file v2.1.53/linux/include/linux/tty.h linux/include/linux/tty.h --- v2.1.53/linux/include/linux/tty.h Mon Aug 18 18:19:47 1997 +++ linux/include/linux/tty.h Sat Sep 6 10:50:21 1997 @@ -73,6 +73,7 @@ #define VIDEO_TYPE_TGAC 0x40 /* DEC TGA */ #define VIDEO_TYPE_SUN 0x50 /* Sun frame buffer. */ +#define VIDEO_TYPE_SUNPCI 0x51 /* Sun PCI based frame buffer. */ #define VIDEO_TYPE_PMAC 0x60 /* PowerMacintosh frame buffer. */ diff -u --recursive --new-file v2.1.53/linux/include/net/inet_common.h linux/include/net/inet_common.h --- v2.1.53/linux/include/net/inet_common.h Thu Sep 4 17:07:31 1997 +++ linux/include/net/inet_common.h Fri Sep 5 20:40:38 1997 @@ -1,8 +1,6 @@ #ifndef _INET_COMMON_H #define _INET_COMMON_H -#include - extern struct proto_ops inet_stream_ops; extern struct proto_ops inet_dgram_ops; diff -u --recursive --new-file v2.1.53/linux/include/net/snmp.h linux/include/net/snmp.h --- v2.1.53/linux/include/net/snmp.h Thu Sep 4 17:07:31 1997 +++ linux/include/net/snmp.h Fri Sep 5 20:40:28 1997 @@ -19,8 +19,6 @@ #ifndef _SNMP_H #define _SNMP_H -#include - /* * We use all unsigned longs. Linux will soon be so reliable that even these * will rapidly get too small 8-). Seriously consider the IpInReceives count diff -u --recursive --new-file v2.1.53/linux/init/main.c linux/init/main.c --- v2.1.53/linux/init/main.c Mon Aug 4 16:25:40 1997 +++ linux/init/main.c Sat Sep 6 10:04:16 1997 @@ -72,6 +72,7 @@ extern unsigned long pci_init(unsigned long, unsigned long); extern long mca_init(long, long); extern long sbus_init(long, long); +extern long powermac_init(unsigned long, unsigned long); extern void sysctl_init(void); extern void filescache_init(void); @@ -86,6 +87,18 @@ extern void lp_setup(char *str, int *ints); #endif extern void eth_setup(char *str, int *ints); +#ifdef CONFIG_ARCNET_COM20020 +extern void com20020_setup(char *str, int *ints); +#endif +#ifdef CONFIG_ARCNET_RIM_I +extern void arcrimi_setup(char *str, int *ints); +#endif +#ifdef CONFIG_ARCNET_COM90xxIO +extern void com90io_setup(char *str, int *ints); +#endif +#ifdef CONFIG_ARCNET_COM90xx +extern void com90xx_setup(char *str, int *ints); +#endif #ifdef CONFIG_DECNET extern void decnet_setup(char *str, int *ints); #endif @@ -212,6 +225,10 @@ #ifdef CONFIG_SOUNDMODEM extern void sm_setup(char *str, int *ints); #endif +#ifdef CONFIG_PMAC_CONSOLE +extern void pmac_cons_setup(char *str, int *ints); +extern void pmac_vmode_setup(char *str, int *ints); +#endif #ifdef CONFIG_WDT extern void wdt_setup(char *str, int *ints); #endif @@ -221,6 +238,9 @@ #ifdef CONFIG_PLIP extern void plip_setup(char *str, int *ints); #endif +#ifdef CONFIG_HFMODEM +extern void hfmodem_setup(char *str, int *ints); +#endif #if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD) extern void ipc_init(void); @@ -329,6 +349,18 @@ #ifdef CONFIG_INET { "ether=", eth_setup }, #endif +#ifdef CONFIG_ARCNET_COM20020 + { "com20020=", com20020_setup }, +#endif +#ifdef CONFIG_ARCNET_RIM_I + { "arcrimi=", arcrimi_setup }, +#endif +#ifdef CONFIG_ARCNET_COM90xxIO + { "com90io=", com90io_setup }, +#endif +#ifdef CONFIG_ARCNET_COM90xx + { "com90xx=", com90xx_setup }, +#endif #ifdef CONFIG_DECNET { "decnet=", decnet_setup }, #endif @@ -517,6 +549,13 @@ #ifdef CONFIG_PLIP { "plip=", plip_setup }, #endif +#ifdef CONFIG_SOUNDMODEM + { "hfmodem=", hfmodem_setup }, +#endif +#ifdef CONFIG_PMAC_CONSOLE + { "console=", pmac_cons_setup }, + { "vmode=", pmac_vmode_setup }, +#endif { 0, 0 } }; @@ -875,6 +914,9 @@ } #ifdef CONFIG_SBUS memory_start = sbus_init(memory_start,memory_end); +#endif +#ifdef CONFIG_PMAC + memory_start = powermac_init(memory_start, memory_end); #endif memory_start = console_init(memory_start,memory_end); #ifdef CONFIG_PCI diff -u --recursive --new-file v2.1.53/linux/ipc/shm.c linux/ipc/shm.c --- v2.1.53/linux/ipc/shm.c Thu Jul 17 10:06:09 1997 +++ linux/ipc/shm.c Sat Sep 6 10:12:16 1997 @@ -498,8 +498,14 @@ if (shmflg & SHM_REMAP) goto out; err = -ENOMEM; - if (!(addr = get_unmapped_area(0, shp->shm_segsz))) + addr = 0; + again: + if (!(addr = get_unmapped_area(addr, shp->shm_segsz))) goto out; + if(addr & (SHMLBA - 1)) { + addr = (addr + (SHMLBA - 1)) & ~(SHMLBA - 1); + goto again; + } } else if (addr & (SHMLBA-1)) { if (shmflg & SHM_RND) addr &= ~(SHMLBA-1); /* round down */ diff -u --recursive --new-file v2.1.53/linux/kernel/exit.c linux/kernel/exit.c --- v2.1.53/linux/kernel/exit.c Wed Sep 3 20:52:44 1997 +++ linux/kernel/exit.c Sat Sep 6 10:11:31 1997 @@ -523,10 +523,8 @@ NORET_TYPE void do_exit(long code) { - if (in_interrupt()) { - local_irq_count[smp_processor_id()] = 0; /* Not really correct */ + if (in_interrupt()) printk("Aiee, killing interrupt handler\n"); - } fake_volatile: acct_process(code); current->flags |= PF_EXITING; diff -u --recursive --new-file v2.1.53/linux/kernel/module.c linux/kernel/module.c --- v2.1.53/linux/kernel/module.c Mon Jul 7 08:18:56 1997 +++ linux/kernel/module.c Sat Sep 6 10:10:48 1997 @@ -9,6 +9,7 @@ #include #include #include +#include /* * Originally by Anonymous (as far as I know...) @@ -293,6 +294,10 @@ error = -EFAULT; goto err3; } + + /* On some machines it is necessary to do something here + to make the I and D caches consistent. */ + flush_icache_range((unsigned long)mod, (unsigned long)mod + mod->size); /* Update module references. */ mod->next = mod_tmp.next; diff -u --recursive --new-file v2.1.53/linux/kernel/sys.c linux/kernel/sys.c --- v2.1.53/linux/kernel/sys.c Thu Jul 17 10:06:09 1997 +++ linux/kernel/sys.c Sat Sep 6 10:23:14 1997 @@ -366,7 +366,7 @@ int acct_process(long exitcode) { struct acct ac; - unsigned short fs; + unsigned long fs; if (acct_active) { strncpy(ac.ac_comm, current->comm, ACCT_COMM); diff -u --recursive --new-file v2.1.53/linux/kernel/time.c linux/kernel/time.c --- v2.1.53/linux/kernel/time.c Wed Apr 23 19:01:29 1997 +++ linux/kernel/time.c Fri Sep 5 08:53:26 1997 @@ -15,7 +15,7 @@ * 1993-10-08 Torsten Duwe * adjtime interface update and CMOS clock write code * 1995-08-13 Torsten Duwe - * kernel PLL updated to 1994-12-13 specs (rfc-1489) + * kernel PLL updated to 1994-12-13 specs (rfc-1589) */ #include diff -u --recursive --new-file v2.1.53/linux/lib/vsprintf.c linux/lib/vsprintf.c --- v2.1.53/linux/lib/vsprintf.c Mon Aug 4 16:25:40 1997 +++ linux/lib/vsprintf.c Fri Sep 5 20:31:57 1997 @@ -253,41 +253,6 @@ } continue; - case 'I': /* IPv4 / IPv6 printout */ - { - __u8 *ip4; - char sbuf[6]; - if (qualifier == 'l') { - __u16 *ip6 = va_arg(args, __u16 *); - i = 6; - for ( ; i > 0; --i, ++ip6) - if (*ip6 != 0) - break; - if (i < 6) - *str++ = ':'; - for ( ; i > 0; --i, ++ip6) { - sprintf(sbuf,":%04x",(int)(*ip6)); - s = sbuf; - while (*s) - *str++ = *s++; - } - *str++ = ':'; - ip4 = (__u8*) ip6; - } else { - ip4 = va_arg(args, __u8 *); - } - for (i = 0; i < 4; ++i, ++ip4) { - if (i == 3) - sprintf(sbuf,"%d", 0xFF & (*ip4)); - else - sprintf(sbuf,"%d.", 0xFF & (*ip4)); - s = sbuf; - while (*s) - *str++ = *s++; - } - } - continue; - /* integer number formats - set up the flags and "break" */ case 'o': base = 8; diff -u --recursive --new-file v2.1.53/linux/mm/filemap.c linux/mm/filemap.c --- v2.1.53/linux/mm/filemap.c Wed Sep 3 20:52:44 1997 +++ linux/mm/filemap.c Sat Sep 6 10:23:14 1997 @@ -892,8 +892,9 @@ static inline int do_write_page(struct inode * inode, struct file * file, const char * page, unsigned long offset) { - int old_fs, retval; + int retval; unsigned long size; + unsigned long old_fs; size = offset + PAGE_SIZE; /* refuse to extend file size.. */ diff -u --recursive --new-file v2.1.53/linux/net/ipv4/ip_fragment.c linux/net/ipv4/ip_fragment.c --- v2.1.53/linux/net/ipv4/ip_fragment.c Thu Sep 4 17:07:32 1997 +++ linux/net/ipv4/ip_fragment.c Sat Sep 6 10:05:42 1997 @@ -5,7 +5,7 @@ * * The IP fragmentation functionality. * - * Version: $Id: ip_fragment.c,v 1.25 1997/08/17 05:56:07 freitag Exp $ + * Version: $Id: ip_fragment.c,v 1.26 1997/09/04 22:35:00 davem Exp $ * * Authors: Fred N. van Kempen * Alan Cox @@ -313,8 +313,7 @@ len = qp->ihlen + qp->len; if(len>65535) { - printk(KERN_INFO "Oversized IP packet from %I.\n", - &qp->iph->saddr); + printk(KERN_INFO "Oversized IP packet from %d.%d.%d.%d.\n", NIPQUAD(qp->iph->saddr)); ip_statistics.IpReasmFails++; ip_free(qp); return NULL; @@ -322,8 +321,7 @@ if ((skb = dev_alloc_skb(len)) == NULL) { ip_statistics.IpReasmFails++; - NETDEBUG(printk(KERN_ERR "IP: queue_glue: no memory for gluing " - "queue %p\n", qp)); + NETDEBUG(printk(KERN_ERR "IP: queue_glue: no memory for gluing queue %p\n", qp)); ip_free(qp); return NULL; } @@ -436,8 +434,7 @@ /* Attempt to construct an oversize packet. */ if(ntohs(iph->tot_len)+(int)offset>65535) { - printk(KERN_INFO "Oversized packet received from %I\n", - &iph->saddr); + printk(KERN_INFO "Oversized packet received from %d.%d.%d.%d\n", NIPQUAD(iph->saddr)); frag_kfree_skb(skb, FREE_READ); ip_statistics.IpReasmFails++; return NULL; diff -u --recursive --new-file v2.1.53/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c --- v2.1.53/linux/net/ipv4/tcp.c Thu Sep 4 17:07:32 1997 +++ linux/net/ipv4/tcp.c Sat Sep 6 09:16:02 1997 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp.c,v 1.70 1997/09/01 03:14:28 davem Exp $ + * Version: $Id: tcp.c,v 1.71 1997/09/06 05:11:45 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -1503,10 +1503,11 @@ * Wait for an incoming connection, avoid race * conditions. This must be called with the socket locked. */ -static struct open_request * wait_for_connect(struct sock * sk) +static struct open_request * wait_for_connect(struct sock * sk, + struct open_request **pprev) { struct wait_queue wait = { current, NULL }; - struct open_request *req = NULL, *dummy; + struct open_request *req = NULL; add_wait_queue(sk->sleep, &wait); for (;;) { @@ -1514,7 +1515,7 @@ release_sock(sk); schedule(); lock_sock(sk); - req = tcp_find_established(&(sk->tp_pinfo.af_tcp), &dummy); + req = tcp_find_established(&(sk->tp_pinfo.af_tcp), pprev); if (req) break; if (current->signal & ~current->blocked) @@ -1569,7 +1570,7 @@ error = EAGAIN; if (flags & O_NONBLOCK) goto out; - req = wait_for_connect(sk); + req = wait_for_connect(sk, &prev); if (req) goto got_new_connect; error = ERESTARTSYS; diff -u --recursive --new-file v2.1.53/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c --- v2.1.53/linux/net/ipv4/tcp_ipv4.c Thu Sep 4 17:07:32 1997 +++ linux/net/ipv4/tcp_ipv4.c Sat Sep 6 10:05:42 1997 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_ipv4.c,v 1.61 1997/09/02 09:46:55 freitag Exp $ + * Version: $Id: tcp_ipv4.c,v 1.62 1997/09/04 22:34:59 davem Exp $ * * IPv4 specific functions * @@ -1440,14 +1440,14 @@ case CHECKSUM_HW: if (tcp_v4_check(th,len,saddr,daddr,skb->csum)) { struct iphdr * iph = skb->nh.iph; - printk(KERN_DEBUG "TCPv4 bad checksum from %I:%04x to %I:%04x, len=%d/%d/%d\n", - &saddr, ntohs(th->source), &daddr, + printk(KERN_DEBUG "TCPv4 bad checksum from %d.%d.%d.%d:%04x to %d.%d.%d.%d:%04x, len=%d/%d/%d\n", + NIPQUAD(saddr), ntohs(th->source), NIPQUAD(daddr), ntohs(th->dest), len, skb->len, ntohs(iph->tot_len)); goto discard_it; } default: /* CHECKSUM_UNNECESSARY */ - }; + } tcp_statistics.TcpInSegs++; diff -u --recursive --new-file v2.1.53/linux/net/netsyms.c linux/net/netsyms.c --- v2.1.53/linux/net/netsyms.c Thu Sep 4 17:07:32 1997 +++ linux/net/netsyms.c Sat Sep 6 10:07:22 1997 @@ -341,6 +341,8 @@ EXPORT_SYMBOL(ip_rcv); EXPORT_SYMBOL(arp_rcv); +EXPORT_SYMBOL(if_port_text); + #if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE) #include EXPORT_SYMBOL(ltalk_setup);