D: ISAPnP fixes in sb_card.c
S: Italy
+N: Alessandro Zummo
+E: azummo@ita.flashnet.it
+W: http://freepage.logicom.it/azummo/
+D: CMI8330 support is sb_card.c
+D: ISAPnP fixes in sb_card.c
+S: Italy
+
N: Marc Zyngier
E: maz@wild-wind.fr.eu.org
D: MD driver
You will get a boot time penguin logo at no additional cost. Please
read Documentation/fb/vesafb.txt. If unsure, say Y.
+VGA 16-color planar support
+CONFIG_FBCON_VGA_PLANES
+ This low level frame buffer console driver enable the kernel to use
+ the 16-color planar modes of the old VGA cards where the bits of each
+ pixel are separated into 4 plans.
+ Only answer Y here if you have an (very old) VGA card that isn't
+ VESA 2 compatible.
+
VGA 16-color graphics console
CONFIG_FB_VGA16
This is the frame buffer device driver for VGA 16 color graphic
running kernel whenever you want), say M here and read
Documentation/modules.txt. The module will be called vga16fb.o.
+VGA 8x16 font
+CONFIG_FONT_8x16
+ This is the "high resolution" font for the VGA frame buffer (the one
+ provided by the text console 80x25 mode.
+
+Support only 8 pixels wide fonts
+CONFIG_FBCON_FONTWIDTH8_ONLY
+ Answer Y here will make the kernel provide only the 8x8 fonts (these
+ are the less readable).
+
+VGA 8x8 font
+CONFIG_FONT_8x8
+ This is the "high resolution" font for the VGA frame buffer (the one
+ provided by the text console 80x50 (and higher) modes.
+ Note this is a poor quality font. The VGA 8x16 font is quite a lot
+ more readable.
+ Given the resolution provided by the frame buffer device, anwser N
+ here is safe.
+
Backward compatibility mode for Xpmac
CONFIG_FB_COMPAT_XPMAC
If you use the Xpmac X server (common with mklinux), you'll need to
Ultra/AX machines. This code is also available as a module (say M),
called parport_ax.o. If in doubt, saying N is the safe plan.
+Support IEEE1284 status readback
+CONFIG_PRINTER_READBACK
+ If you have a device on your parrallel port that support this protocol,
+ this option'll enable it to report its status.
+ It is safe to say Y.
+
IEEE1284 transfer modes
CONFIG_PARPORT_1284
If you have a printer that supports status readback or device ID, or
Documentation/networking/net-modules.txt.
DECchip Tulip (dc21x4x) PCI support
-CONFIG_DEC_ELCP
+CONFIG_TULIP
This driver is developed for the SMC EtherPower series Ethernet
cards and also works with cards based on the DECchip
21040/21041/21140 (Tulip series) chips. Some LinkSys PCI cards are
from the Microsoft fat filesystem family or from JOLIET CDROMs
correctly on the screen, you need to include the appropriate
input/output character sets. Say Y here for the Latin 8 character
- set, which adds the last accented vowels for Welsh (and Manx Gaelic)
- that were missing in Latin 1. http://linux.speech.cymru.org/
- has further information.
+ set, which adds the last accented vowels for Welsh (aka Cymraeg)
+ (and Manx Gaelic) hat were missing in Latin 1.
+ http://linux.speech.cymru.org/ has further information.
nls iso8859-15
CONFIG_NLS_ISO8859_15
If unsure, say N.
+Enter S1 for sleep (EXPERIMENTAL)
+CONFIG_ACPI_S1_SLEEP
+ This enable ACPI compliant devices to enter level 1 of ACPI saving
+ power levels. Basically, this will let them entering in sleep mode.
+
Advanced Power Management
CONFIG_APM
APM is a BIOS specification for saving power using several different
If you do not have any Quicknet telephony cards, you can safely
ignore this option.
-
+
+/dev/agpgart (AGP Support) (EXPERIMENTAL)
+CONFIG_AGP
+ The agpgart kernel module is necessary to use the AGP features
+ of your 3D rendering video card. It acts as a sort of "AGP
+ driver" for the motherboard's chipset.
+ Loading this module into the kernel will allow the glx module to
+ program the GART (graphics aperture relocation table) registers
+ with appropriate values to transfer commands to the card.
+
+ If you need more texture memory than you can get with the AGP GART
+ (theoretically up to 256 megs, but in practice usually 64 or 128
+ megs due to kernel allocation issues), you could use PCI accesses
+ and have up to a couple gigs of texture space.
+
+ Note that this is the only meas to have get XFree4/GLX use
+ write-combining with MTRR support on AGP bus. Without, OpenGL
+ direct rendering will be a lot slower but still faster than PIO.
+
+ For the moment, most people should say no, unless you want to
+ test the GLX component which can be downloaded from
+ http://glx.on.openprojects.net/
+
+ or need to use the 810 Xserver in XFree 3.3.6
+
+Intel 440LX/BX/GX support
+CONFIG_AGP_INTEL
+ This option give you AGP support for the GLX component of the
+ "soon to be released" XFree86-4 on Intel 440LX/BX/GX chipsets.
+
+ For the moment, most people should say no, unless you want to
+ test the GLX component which can be downloaded from
+ http://glx.on.openprojects.net/
+
+Intel I810/I810 DC100/I810e support
+CONFIG_AGP_I810
+ This option give you AGP support for the Xserver for the intel
+ 810 chipset boards. This is required to do any useful video
+ modes.
+
+VIA VP3/MVP3/Apollo Pro support
+CONFIG_AGP_VIA
+ This option give you AGP support for the GLX component of the
+ "soon to be released" XFree86-4 on VIA MPV3/Apollo Pro chipsets.
+
+ For the moment, most people should say no, unless you want to
+ test the GLX component which can be downloaded from
+ http://glx.on.openprojects.net/
+
+AMD Irongate support
+CONFIG_AGP_AMD
+ This option give you AGP support for the GLX component of the
+ "soon to be released" XFree86-4 on Intel AMD Irongate chipset.
+
+ For the moment, most people should say no, unless you want to
+ test the GLX component which can be downloaded from
+ http://glx.on.openprojects.net/
+
+Generic SiS support
+CONFIG_AGP_SIS
+ This option give you AGP support for the GLX component of the
+ "soon to be released" XFree86-4 on Silicon Integrated Systems [SiS]
+ chipsets.
+
+ Note than 5591/5592 AGP chipsets are NOT supported.
+
+ For the moment, most people should say no, unless you want to
+ test the GLX component which can be downloaded from
+ http://glx.on.openprojects.net/
+
+ALI M1541 support
+CONFIG_AGP_ALI
+ This option give you AGP support for the GLX component of the
+ "soon to be released" XFree86-4 on ALI M1541 chipset.
+
+ For the moment, most people should say no, unless you want to
+ test the GLX component which can be downloaded from
+ http://glx.on.openprojects.net/
#
# ARM options
The kHTTPd is experimental. Be careful when using it on a production
machine. Also note that kHTTPd doesn't support virtual servers yet.
-#
I2C support
CONFIG_I2C
I2C (pronounce: I-square-C) is a slow bus protocol developed by
files, usually found in the /dev directory on your system. They
make it possible to have user-space programs use the I2C bus.
+#
# A couple of things I keep forgetting:
# capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet,
# Intel, IRQ, Linux, MSDOS, NetWare, NetWinder, NFS,
# CONFIG_APRICOT is not set
# CONFIG_CS89x0 is not set
# CONFIG_DE4X5 is not set
-# CONFIG_DEC_ELCP is not set
+# CONFIG_TULIP is not set
# CONFIG_DGRS is not set
CONFIG_EEXPRESS_PRO100=y
# CONFIG_NE2K_PCI is not set
endif
endif
-ifdef CONFIG_ACPI
-OX_OBJS += pm.o
-else
-ifdef CONFIG_APM
-OX_OBJS += pm.o
-endif
-endif
-
ifeq ($(CONFIG_ACPI),y)
O_OBJS += acpi.o
else
}
}
+static void __init pci_fixup_ide_trash(struct pci_dev *d)
+{
+ int i;
+
+ /*
+ * There exist PCI IDE controllers which have utter garbage
+ * in first four base registers. Ignore that.
+ */
+ DBG("PCI: IDE base address trash cleared for %s\n", d->slot_name);
+ for(i=0; i<4; i++)
+ d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0;
+}
+
struct pci_fixup pcibios_fixups[] = {
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_RCC, PCI_DEVICE_ID_RCC_HE, pci_fixup_rcc },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_RCC, PCI_DEVICE_ID_RCC_LE, pci_fixup_rcc },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_6010, pci_fixup_compaq },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash },
{ PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases },
{ 0 }
};
+++ /dev/null
-/*
- * pm.c - Power management interface
- *
- * Copyright (C) 2000 Andrew Henroid
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/pm.h>
-
-int pm_active = 0;
-
-static spinlock_t pm_devs_lock = SPIN_LOCK_UNLOCKED;
-static LIST_HEAD(pm_devs);
-
-/*
- * Register a device with power management
- */
-struct pm_dev *pm_register(pm_dev_t type,
- unsigned long id,
- pm_callback callback)
-{
- struct pm_dev *dev = kmalloc(sizeof(struct pm_dev), GFP_KERNEL);
- if (dev) {
- unsigned long flags;
-
- memset(dev, 0, sizeof(*dev));
- dev->type = type;
- dev->id = id;
- dev->callback = callback;
-
- spin_lock_irqsave(&pm_devs_lock, flags);
- list_add(&dev->entry, &pm_devs);
- spin_unlock_irqrestore(&pm_devs_lock, flags);
- }
- return dev;
-}
-
-/*
- * Unregister a device with power management
- */
-void pm_unregister(struct pm_dev *dev)
-{
- if (dev) {
- unsigned long flags;
-
- spin_lock_irqsave(&pm_devs_lock, flags);
- list_del(&dev->entry);
- spin_unlock_irqrestore(&pm_devs_lock, flags);
-
- kfree(dev);
- }
-}
-
-/*
- * Unregister all devices with matching callback
- */
-void pm_unregister_all(pm_callback callback)
-{
- struct list_head *entry;
-
- if (!callback)
- return;
-
- entry = pm_devs.next;
- while (entry != &pm_devs) {
- struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
- entry = entry->next;
- if (dev->callback == callback)
- pm_unregister(dev);
- }
-}
-
-/*
- * Send request to an individual device
- */
-static int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
- int status = 0;
- int next_state;
- switch (rqst) {
- case PM_SUSPEND:
- case PM_RESUME:
- next_state = (int) data;
- if (dev->state != next_state) {
- if (dev->callback)
- status = (*dev->callback)(dev, rqst, data);
- if (!status)
- dev->state = next_state;
- }
- break;
- default:
- if (dev->callback)
- status = (*dev->callback)(dev, rqst, data);
- break;
- }
- return status;
-}
-
-/*
- * Undo incomplete request
- */
-static void pm_undo_request(struct pm_dev *last, pm_request_t undo, void *data)
-{
- struct list_head *entry = last->entry.prev;
- while (entry != &pm_devs) {
- struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
- if (dev->callback)
- pm_send(dev, undo, data);
- entry = entry->prev;
- }
-}
-
-/*
- * Send a request to all devices
- */
-int pm_send_request(pm_request_t rqst, void *data)
-{
- struct list_head *entry = pm_devs.next;
- while (entry != &pm_devs) {
- struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
- if (dev->callback) {
- int status = pm_send(dev, rqst, data);
- if (status) {
- /* resume devices on failed suspend request */
- if (rqst == PM_SUSPEND)
- pm_undo_request(dev, PM_RESUME, 0);
- return status;
- }
- }
- entry = entry->next;
- }
- return 0;
-}
-
-/*
- * Find a device
- */
-struct pm_dev *pm_find(pm_dev_t type, struct pm_dev *from)
-{
- struct list_head *entry = from ? from->entry.next:pm_devs.next;
- while (entry != &pm_devs) {
- struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
- if (type == PM_UNKNOWN_DEV || dev->type == type)
- return dev;
- entry = entry->next;
- }
- return 0;
-}
-
-EXPORT_SYMBOL(pm_register);
-EXPORT_SYMBOL(pm_unregister);
-EXPORT_SYMBOL(pm_unregister_all);
-EXPORT_SYMBOL(pm_send_request);
-EXPORT_SYMBOL(pm_find);
* responsibility of the caller). Added spinlocks.
*
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/delay.h>
decl_config_access_method(galaxy);
-void __init
-galaxy_pcibios_fixup(void)
-{
-
-}
-
-void __init
-galaxy_setup_pci_ptrs(void)
-{
- set_config_access_method(galaxy);
-
- ppc_md.pcibios_fixup = galaxy_pcibios_fixup;
-}
-
-int
-galaxy_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned char *val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned short *val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned int *val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned char val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned short val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned int val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-/*
- *
- * Copyright (c) 2000 Grant Erickson <grant@borg.umn.edu>
- * All rights reserved.
- *
- * Module name: galaxy_pci.c
- *
- * Description:
- * PCI interface code for the IBM PowerPC 405GP on-chip PCI bus
- * interface.
- *
- * Why is this file called "galaxy_pci"? Because on the original
- * IBM "Walnut" evaluation board schematic I have, the 405GP is
- * is labeled "GALAXY".
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-
-#include "pci.h"
-
-
-/* Preprocessor Defines */
-
-#define PCICFGADDR (volatile unsigned int *)(0xEEC00000)
-#define PCICFGDATA (volatile unsigned int *)(0xEEC00004)
-
-
-/* Function Prototypes */
-
-decl_config_access_method(galaxy);
-
-
-void __init
-galaxy_pcibios_fixup(void)
-{
-
-}
-
-void __init
-galaxy_setup_pci_ptrs(void)
-{
- set_config_access_method(galaxy);
-
- ppc_md.pcibios_fixup = galaxy_pcibios_fixup;
-}
-
-int
-galaxy_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned char *val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned short *val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned int *val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned char val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned short val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned int val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-/*
- *
- * Copyright (c) 2000 Grant Erickson <grant@borg.umn.edu>
- * All rights reserved.
- *
- * Module name: galaxy_pci.c
- *
- * Description:
- * PCI interface code for the IBM PowerPC 405GP on-chip PCI bus
- * interface.
- *
- * Why is this file called "galaxy_pci"? Because on the original
- * IBM "Walnut" evaluation board schematic I have, the 405GP is
- * is labeled "GALAXY".
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-
-#include "pci.h"
-
-
-/* Preprocessor Defines */
-
-#define PCICFGADDR (volatile unsigned int *)(0xEEC00000)
-#define PCICFGDATA (volatile unsigned int *)(0xEEC00004)
-
-
-/* Function Prototypes */
-
-decl_config_access_method(galaxy);
-
-
-void __init
-galaxy_pcibios_fixup(void)
-{
-
-}
-
-void __init
-galaxy_setup_pci_ptrs(void)
-{
- set_config_access_method(galaxy);
-
- ppc_md.pcibios_fixup = galaxy_pcibios_fixup;
-}
-
-int
-galaxy_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned char *val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned short *val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned int *val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned char val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned short val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned int val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-/*
- *
- * Copyright (c) 2000 Grant Erickson <grant@borg.umn.edu>
- * All rights reserved.
- *
- * Module name: galaxy_pci.c
- *
- * Description:
- * PCI interface code for the IBM PowerPC 405GP on-chip PCI bus
- * interface.
- *
- * Why is this file called "galaxy_pci"? Because on the original
- * IBM "Walnut" evaluation board schematic I have, the 405GP is
- * is labeled "GALAXY".
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-
-#include "pci.h"
-
-
-/* Preprocessor Defines */
-
-#define PCICFGADDR (volatile unsigned int *)(0xEEC00000)
-#define PCICFGDATA (volatile unsigned int *)(0xEEC00004)
-
-
-/* Function Prototypes */
-
-decl_config_access_method(galaxy);
-
-
-void __init
-galaxy_pcibios_fixup(void)
-{
-
-}
-
-void __init
-galaxy_setup_pci_ptrs(void)
-{
- set_config_access_method(galaxy);
-
- ppc_md.pcibios_fixup = galaxy_pcibios_fixup;
-}
-
-int
-galaxy_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned char *val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned short *val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned int *val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned char val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned short val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned int val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-/*
- *
- * Copyright (c) 2000 Grant Erickson <grant@borg.umn.edu>
- * All rights reserved.
- *
- * Module name: galaxy_pci.c
- *
- * Description:
- * PCI interface code for the IBM PowerPC 405GP on-chip PCI bus
- * interface.
- *
- * Why is this file called "galaxy_pci"? Because on the original
- * IBM "Walnut" evaluation board schematic I have, the 405GP is
- * is labeled "GALAXY".
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-
-#include "pci.h"
-
-
-/* Preprocessor Defines */
-
-#define PCICFGADDR (volatile unsigned int *)(0xEEC00000)
-#define PCICFGDATA (volatile unsigned int *)(0xEEC00004)
-
-
-/* Function Prototypes */
-
-decl_config_access_method(galaxy);
-
-
-void __init
-galaxy_pcibios_fixup(void)
-{
-
-}
-
-void __init
-galaxy_setup_pci_ptrs(void)
-{
- set_config_access_method(galaxy);
-
- ppc_md.pcibios_fixup = galaxy_pcibios_fixup;
-}
-
-int
-galaxy_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned char *val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned short *val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned int *val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned char val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned short val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-
-int
-galaxy_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned int val)
-{
-
- return (PCIBIOS_SUCCESSFUL);
-}
-/*
- *
- * Copyright (c) 2000 Grant Erickson <grant@borg.umn.edu>
- * All rights reserved.
- *
- * Module name: galaxy_pci.c
- *
- * Description:
- * PCI interface code for the IBM PowerPC 405GP on-chip PCI bus
- * interface.
- *
- * Why is this file called "galaxy_pci"? Because on the original
- * IBM "Walnut" evaluation board schematic I have, the 405GP is
- * is labeled "GALAXY".
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-
-#include "pci.h"
-
-
-/* Preprocessor Defines */
-
-#define PCICFGADDR (volatile unsigned int *)(0xEEC00000)
-#define PCICFGDATA (volatile unsigned int *)(0xEEC00004)
-
-
-/* Function Prototypes */
-
-decl_config_access_method(galaxy);
-
-
void __init
galaxy_pcibios_fixup(void)
{
* for more details.
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
}
-/*
- *
- * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- * Module name: walnut_setup.c
- *
- * Description:
- * Architecture- / platform-specific boot-time initialization code for
- * the IBM PowerPC 403GP "Walnut" evaluation board. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
- * <dan@net4x.com>.
- *
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/threads.h>
-#include <linux/interrupt.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/blk.h>
-
-#include <asm/processor.h>
-#include <asm/board.h>
-#include <asm/machdep.h>
-#include <asm/page.h>
-
-#include "local_irq.h"
-#include "ppc4xx_pic.h"
-#include "time.h"
-#include "walnut_setup.h"
-
-
-/* Function Prototypes */
-
-extern void abort(void);
-
-/* Global Variables */
-
-unsigned char __res[sizeof(bd_t)];
-
-
-/*
- * void __init walnut_init()
- *
- * Description:
- * This routine...
- *
- * Input(s):
- * r3 - Optional pointer to a board information structure.
- * r4 - Optional pointer to the physical starting address of the init RAM
- * disk.
- * r5 - Optional pointer to the physical ending address of the init RAM
- * disk.
- * r6 - Optional pointer to the physical starting address of any kernel
- * command-line parameters.
- * r7 - Optional pointer to the physical ending address of any kernel
- * command-line parameters.
- *
- * Output(s):
- * N/A
- *
- * Returns:
- * N/A
- *
- */
-void __init
-walnut_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- /*
- * If we were passed in a board information, copy it into the
- * residual data area.
- */
- if (r3) {
- memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
- }
-
-#if defined(CONFIG_BLK_DEV_INITRD)
- /*
- * If the init RAM disk has been configured in, and there's a valid
- * starting address for it, set it up.
- */
- if (r4) {
- initrd_start = r4 + KERNELBASE;
- initrd_end = r5 + KERNELBASE;
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
-
- /* Copy the kernel command line arguments to a safe place. */
-
- if (r6) {
- *(char *)(r7 + KERNELBASE) = 0;
- strcpy(cmd_line, (char *)(r6 + KERNELBASE));
- }
-
- /* Initialize machine-dependency vectors */
-
- ppc_md.setup_arch = walnut_setup_arch;
- ppc_md.setup_residual = walnut_setup_residual;
- ppc_md.get_cpuinfo = NULL;
- ppc_md.irq_cannonicalize = NULL;
- ppc_md.init_IRQ = walnut_init_IRQ;
- ppc_md.get_irq = walnut_get_irq;
- ppc_md.init = NULL;
-
- ppc_md.restart = walnut_restart;
- ppc_md.power_off = walnut_power_off;
- ppc_md.halt = walnut_halt;
-
- ppc_md.time_init = walnut_time_init;
- ppc_md.set_rtc_time = walnut_set_rtc_time;
- ppc_md.get_rtc_time = walnut_get_rtc_time;
- ppc_md.calibrate_decr = walnut_calibrate_decr;
-
- ppc_md.kbd_setkeycode = NULL;
- ppc_md.kbd_getkeycode = NULL;
- ppc_md.kbd_translate = NULL;
- ppc_md.kbd_unexpected_up = NULL;
- ppc_md.kbd_leds = NULL;
- ppc_md.kbd_init_hw = NULL;
-
-#if defined(CONFIG_MAGIC_SYSRQ)
- ppc_md.ppc_kbd_sysrq_xlate = NULL;
-#endif
-
- return;
-}
-
-/*
- * Document me.
- */
-void __init
-walnut_setup_arch(void)
-{
- /* XXX - Implement me */
-}
-
-/*
- * int walnut_setup_residual()
- *
- * Description:
- * This routine pretty-prints the platform's internal CPU and bus clock
- * frequencies into the buffer for usage in /proc/cpuinfo.
- *
- * Input(s):
- * *buffer - Buffer into which CPU and bus clock frequencies are to be
- * printed.
- *
- * Output(s):
- * *buffer - Buffer with the CPU and bus clock frequencies.
- *
- * Returns:
- * The number of bytes copied into 'buffer' if OK, otherwise zero or less
- * on error.
- */
-int
-walnut_setup_residual(char *buffer)
-{
- int len = 0;
- bd_t *bp = (bd_t *)__res;
-
- len += sprintf(len + buffer,
- "clock\t\t: %dMHz\n"
- "bus clock\t\t: %dMHz\n",
- bp->bi_intfreq / 1000000,
- bp->bi_busfreq / 1000000);
-
- return (len);
-}
-
-/*
- * Document me.
- */
-void __init
-walnut_init_IRQ(void)
-{
- int i;
-
- ppc4xx_pic_init();
-
- for (i = 0; i < NR_IRQS; i++) {
- irq_desc[i].handler = ppc4xx_pic;
- }
-
- return;
-}
-
-/*
- * Document me.
- */
-int
-walnut_get_irq(struct pt_regs *regs)
-{
- return (ppc4xx_pic_get_irq(regs));
-}
-
-/*
- * Document me.
- */
-void
-walnut_restart(char *cmd)
-{
- abort();
-}
-
-/*
- * Document me.
- */
-void
-walnut_power_off(void)
-{
- walnut_restart(NULL);
-}
-
-/*
- * Document me.
- */
-void
-walnut_halt(void)
-{
- walnut_restart(NULL);
-}
-
-/*
- * Document me.
- */
-void __init
-walnut_time_init(void)
-{
- /* XXX - Implement me */
-}
-
-/*
- * Document me.
- */
-int __init
-walnut_set_rtc_time(unsigned long time)
-{
- /* XXX - Implement me */
-
- return (0);
-}
-
-/*
- * Document me.
- */
-unsigned long __init
-walnut_get_rtc_time(void)
-{
- /* XXX - Implement me */
-
- return (0);
-}
-
-/*
- * void __init walnut_calibrate_decr()
- *
- * Description:
- * This routine retrieves the internal processor frequency from the board
- * information structure, sets up the kernel timer decrementer based on
- * that value, enables the 403 programmable interval timer (PIT) and sets
- * it up for auto-reload.
- *
- * Input(s):
- * N/A
- *
- * Output(s):
- * N/A
- *
- * Returns:
- * N/A
- *
- */
-void __init
-walnut_calibrate_decr(void)
-{
- unsigned int freq;
- bd_t *bip = (bd_t *)__res;
-
- freq = bip->bi_intfreq;
-
- decrementer_count = freq / HZ;
- count_period_num = 1;
- count_period_den = freq;
-
- /* Enable the PIT and set auto-reload of its value */
-
- mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
-
- /* Clear any pending timer interrupts */
-
- mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
-}
-/*
- *
- * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- * Module name: walnut_setup.c
- *
- * Description:
- * Architecture- / platform-specific boot-time initialization code for
- * the IBM PowerPC 403GP "Walnut" evaluation board. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
- * <dan@net4x.com>.
- *
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/threads.h>
-#include <linux/interrupt.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/blk.h>
-
-#include <asm/processor.h>
-#include <asm/board.h>
-#include <asm/machdep.h>
-#include <asm/page.h>
-
-#include "local_irq.h"
-#include "ppc4xx_pic.h"
-#include "time.h"
-#include "walnut_setup.h"
-
-
-/* Function Prototypes */
-
-extern void abort(void);
-
-/* Global Variables */
-
-unsigned char __res[sizeof(bd_t)];
-
-
-/*
- * void __init walnut_init()
- *
- * Description:
- * This routine...
- *
- * Input(s):
- * r3 - Optional pointer to a board information structure.
- * r4 - Optional pointer to the physical starting address of the init RAM
- * disk.
- * r5 - Optional pointer to the physical ending address of the init RAM
- * disk.
- * r6 - Optional pointer to the physical starting address of any kernel
- * command-line parameters.
- * r7 - Optional pointer to the physical ending address of any kernel
- * command-line parameters.
- *
- * Output(s):
- * N/A
- *
- * Returns:
- * N/A
- *
- */
-void __init
-walnut_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- /*
- * If we were passed in a board information, copy it into the
- * residual data area.
- */
- if (r3) {
- memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
- }
-
-#if defined(CONFIG_BLK_DEV_INITRD)
- /*
- * If the init RAM disk has been configured in, and there's a valid
- * starting address for it, set it up.
- */
- if (r4) {
- initrd_start = r4 + KERNELBASE;
- initrd_end = r5 + KERNELBASE;
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
-
- /* Copy the kernel command line arguments to a safe place. */
-
- if (r6) {
- *(char *)(r7 + KERNELBASE) = 0;
- strcpy(cmd_line, (char *)(r6 + KERNELBASE));
- }
-
- /* Initialize machine-dependency vectors */
-
- ppc_md.setup_arch = walnut_setup_arch;
- ppc_md.setup_residual = walnut_setup_residual;
- ppc_md.get_cpuinfo = NULL;
- ppc_md.irq_cannonicalize = NULL;
- ppc_md.init_IRQ = walnut_init_IRQ;
- ppc_md.get_irq = walnut_get_irq;
- ppc_md.init = NULL;
-
- ppc_md.restart = walnut_restart;
- ppc_md.power_off = walnut_power_off;
- ppc_md.halt = walnut_halt;
-
- ppc_md.time_init = walnut_time_init;
- ppc_md.set_rtc_time = walnut_set_rtc_time;
- ppc_md.get_rtc_time = walnut_get_rtc_time;
- ppc_md.calibrate_decr = walnut_calibrate_decr;
-
- ppc_md.kbd_setkeycode = NULL;
- ppc_md.kbd_getkeycode = NULL;
- ppc_md.kbd_translate = NULL;
- ppc_md.kbd_unexpected_up = NULL;
- ppc_md.kbd_leds = NULL;
- ppc_md.kbd_init_hw = NULL;
-
-#if defined(CONFIG_MAGIC_SYSRQ)
- ppc_md.ppc_kbd_sysrq_xlate = NULL;
-#endif
-
- return;
-}
-
-/*
- * Document me.
- */
-void __init
-walnut_setup_arch(void)
-{
- /* XXX - Implement me */
-}
-
-/*
- * int walnut_setup_residual()
- *
- * Description:
- * This routine pretty-prints the platform's internal CPU and bus clock
- * frequencies into the buffer for usage in /proc/cpuinfo.
- *
- * Input(s):
- * *buffer - Buffer into which CPU and bus clock frequencies are to be
- * printed.
- *
- * Output(s):
- * *buffer - Buffer with the CPU and bus clock frequencies.
- *
- * Returns:
- * The number of bytes copied into 'buffer' if OK, otherwise zero or less
- * on error.
- */
-int
-walnut_setup_residual(char *buffer)
-{
- int len = 0;
- bd_t *bp = (bd_t *)__res;
-
- len += sprintf(len + buffer,
- "clock\t\t: %dMHz\n"
- "bus clock\t\t: %dMHz\n",
- bp->bi_intfreq / 1000000,
- bp->bi_busfreq / 1000000);
-
- return (len);
-}
-
-/*
- * Document me.
- */
-void __init
-walnut_init_IRQ(void)
-{
- int i;
-
- ppc4xx_pic_init();
-
- for (i = 0; i < NR_IRQS; i++) {
- irq_desc[i].handler = ppc4xx_pic;
- }
-
- return;
-}
-
-/*
- * Document me.
- */
-int
-walnut_get_irq(struct pt_regs *regs)
-{
- return (ppc4xx_pic_get_irq(regs));
-}
-
-/*
- * Document me.
- */
-void
-walnut_restart(char *cmd)
-{
- abort();
-}
-
-/*
- * Document me.
- */
-void
-walnut_power_off(void)
-{
- walnut_restart(NULL);
-}
-
-/*
- * Document me.
- */
-void
-walnut_halt(void)
-{
- walnut_restart(NULL);
-}
-
-/*
- * Document me.
- */
-void __init
-walnut_time_init(void)
-{
- /* XXX - Implement me */
-}
-
-/*
- * Document me.
- */
-int __init
-walnut_set_rtc_time(unsigned long time)
-{
- /* XXX - Implement me */
-
- return (0);
-}
-
-/*
- * Document me.
- */
-unsigned long __init
-walnut_get_rtc_time(void)
-{
- /* XXX - Implement me */
-
- return (0);
-}
-
-/*
- * void __init walnut_calibrate_decr()
- *
- * Description:
- * This routine retrieves the internal processor frequency from the board
- * information structure, sets up the kernel timer decrementer based on
- * that value, enables the 403 programmable interval timer (PIT) and sets
- * it up for auto-reload.
- *
- * Input(s):
- * N/A
- *
- * Output(s):
- * N/A
- *
- * Returns:
- * N/A
- *
- */
-void __init
-walnut_calibrate_decr(void)
-{
- unsigned int freq;
- bd_t *bip = (bd_t *)__res;
-
- freq = bip->bi_intfreq;
-
- decrementer_count = freq / HZ;
- count_period_num = 1;
- count_period_den = freq;
-
- /* Enable the PIT and set auto-reload of its value */
-
- mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
-
- /* Clear any pending timer interrupts */
-
- mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
-}
-/*
- *
- * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- * Module name: walnut_setup.c
- *
- * Description:
- * Architecture- / platform-specific boot-time initialization code for
- * the IBM PowerPC 403GP "Walnut" evaluation board. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
- * <dan@net4x.com>.
- *
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/threads.h>
-#include <linux/interrupt.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/blk.h>
-
-#include <asm/processor.h>
-#include <asm/board.h>
-#include <asm/machdep.h>
-#include <asm/page.h>
-
-#include "local_irq.h"
-#include "ppc4xx_pic.h"
-#include "time.h"
-#include "walnut_setup.h"
-
-
-/* Function Prototypes */
-
-extern void abort(void);
-
-/* Global Variables */
-
-unsigned char __res[sizeof(bd_t)];
-
-
-/*
- * void __init walnut_init()
- *
- * Description:
- * This routine...
- *
- * Input(s):
- * r3 - Optional pointer to a board information structure.
- * r4 - Optional pointer to the physical starting address of the init RAM
- * disk.
- * r5 - Optional pointer to the physical ending address of the init RAM
- * disk.
- * r6 - Optional pointer to the physical starting address of any kernel
- * command-line parameters.
- * r7 - Optional pointer to the physical ending address of any kernel
- * command-line parameters.
- *
- * Output(s):
- * N/A
- *
- * Returns:
- * N/A
- *
- */
-void __init
-walnut_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- /*
- * If we were passed in a board information, copy it into the
- * residual data area.
- */
- if (r3) {
- memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
- }
-
-#if defined(CONFIG_BLK_DEV_INITRD)
- /*
- * If the init RAM disk has been configured in, and there's a valid
- * starting address for it, set it up.
- */
- if (r4) {
- initrd_start = r4 + KERNELBASE;
- initrd_end = r5 + KERNELBASE;
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
-
- /* Copy the kernel command line arguments to a safe place. */
-
- if (r6) {
- *(char *)(r7 + KERNELBASE) = 0;
- strcpy(cmd_line, (char *)(r6 + KERNELBASE));
- }
-
- /* Initialize machine-dependency vectors */
-
- ppc_md.setup_arch = walnut_setup_arch;
- ppc_md.setup_residual = walnut_setup_residual;
- ppc_md.get_cpuinfo = NULL;
- ppc_md.irq_cannonicalize = NULL;
- ppc_md.init_IRQ = walnut_init_IRQ;
- ppc_md.get_irq = walnut_get_irq;
- ppc_md.init = NULL;
-
- ppc_md.restart = walnut_restart;
- ppc_md.power_off = walnut_power_off;
- ppc_md.halt = walnut_halt;
-
- ppc_md.time_init = walnut_time_init;
- ppc_md.set_rtc_time = walnut_set_rtc_time;
- ppc_md.get_rtc_time = walnut_get_rtc_time;
- ppc_md.calibrate_decr = walnut_calibrate_decr;
-
- ppc_md.kbd_setkeycode = NULL;
- ppc_md.kbd_getkeycode = NULL;
- ppc_md.kbd_translate = NULL;
- ppc_md.kbd_unexpected_up = NULL;
- ppc_md.kbd_leds = NULL;
- ppc_md.kbd_init_hw = NULL;
-
-#if defined(CONFIG_MAGIC_SYSRQ)
- ppc_md.ppc_kbd_sysrq_xlate = NULL;
-#endif
-
- return;
-}
-
-/*
- * Document me.
- */
-void __init
-walnut_setup_arch(void)
-{
- /* XXX - Implement me */
-}
-
-/*
- * int walnut_setup_residual()
- *
- * Description:
- * This routine pretty-prints the platform's internal CPU and bus clock
- * frequencies into the buffer for usage in /proc/cpuinfo.
- *
- * Input(s):
- * *buffer - Buffer into which CPU and bus clock frequencies are to be
- * printed.
- *
- * Output(s):
- * *buffer - Buffer with the CPU and bus clock frequencies.
- *
- * Returns:
- * The number of bytes copied into 'buffer' if OK, otherwise zero or less
- * on error.
- */
-int
-walnut_setup_residual(char *buffer)
-{
- int len = 0;
- bd_t *bp = (bd_t *)__res;
-
- len += sprintf(len + buffer,
- "clock\t\t: %dMHz\n"
- "bus clock\t\t: %dMHz\n",
- bp->bi_intfreq / 1000000,
- bp->bi_busfreq / 1000000);
-
- return (len);
-}
-
-/*
- * Document me.
- */
-void __init
-walnut_init_IRQ(void)
-{
- int i;
-
- ppc4xx_pic_init();
-
- for (i = 0; i < NR_IRQS; i++) {
- irq_desc[i].handler = ppc4xx_pic;
- }
-
- return;
-}
-
-/*
- * Document me.
- */
-int
-walnut_get_irq(struct pt_regs *regs)
-{
- return (ppc4xx_pic_get_irq(regs));
-}
-
-/*
- * Document me.
- */
-void
-walnut_restart(char *cmd)
-{
- abort();
-}
-
-/*
- * Document me.
- */
-void
-walnut_power_off(void)
-{
- walnut_restart(NULL);
-}
-
-/*
- * Document me.
- */
-void
-walnut_halt(void)
-{
- walnut_restart(NULL);
-}
-
-/*
- * Document me.
- */
-void __init
-walnut_time_init(void)
-{
- /* XXX - Implement me */
-}
-
-/*
- * Document me.
- */
-int __init
-walnut_set_rtc_time(unsigned long time)
-{
- /* XXX - Implement me */
-
- return (0);
-}
-
-/*
- * Document me.
- */
-unsigned long __init
-walnut_get_rtc_time(void)
-{
- /* XXX - Implement me */
-
- return (0);
-}
-
-/*
- * void __init walnut_calibrate_decr()
- *
- * Description:
- * This routine retrieves the internal processor frequency from the board
- * information structure, sets up the kernel timer decrementer based on
- * that value, enables the 403 programmable interval timer (PIT) and sets
- * it up for auto-reload.
- *
- * Input(s):
- * N/A
- *
- * Output(s):
- * N/A
- *
- * Returns:
- * N/A
- *
- */
-void __init
-walnut_calibrate_decr(void)
-{
- unsigned int freq;
- bd_t *bip = (bd_t *)__res;
-
- freq = bip->bi_intfreq;
-
- decrementer_count = freq / HZ;
- count_period_num = 1;
- count_period_den = freq;
-
- /* Enable the PIT and set auto-reload of its value */
-
- mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
-
- /* Clear any pending timer interrupts */
-
- mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
-}
-/*
- *
- * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- * Module name: walnut_setup.c
- *
- * Description:
- * Architecture- / platform-specific boot-time initialization code for
- * the IBM PowerPC 403GP "Walnut" evaluation board. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
- * <dan@net4x.com>.
- *
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/threads.h>
-#include <linux/interrupt.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/blk.h>
-
-#include <asm/processor.h>
-#include <asm/board.h>
-#include <asm/machdep.h>
-#include <asm/page.h>
-
-#include "local_irq.h"
-#include "ppc4xx_pic.h"
-#include "time.h"
-#include "walnut_setup.h"
-
-
-/* Function Prototypes */
-
-extern void abort(void);
-
-/* Global Variables */
-
-unsigned char __res[sizeof(bd_t)];
-
-
-/*
- * void __init walnut_init()
- *
- * Description:
- * This routine...
- *
- * Input(s):
- * r3 - Optional pointer to a board information structure.
- * r4 - Optional pointer to the physical starting address of the init RAM
- * disk.
- * r5 - Optional pointer to the physical ending address of the init RAM
- * disk.
- * r6 - Optional pointer to the physical starting address of any kernel
- * command-line parameters.
- * r7 - Optional pointer to the physical ending address of any kernel
- * command-line parameters.
- *
- * Output(s):
- * N/A
- *
- * Returns:
- * N/A
- *
- */
-void __init
-walnut_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- /*
- * If we were passed in a board information, copy it into the
- * residual data area.
- */
- if (r3) {
- memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
- }
-
-#if defined(CONFIG_BLK_DEV_INITRD)
- /*
- * If the init RAM disk has been configured in, and there's a valid
- * starting address for it, set it up.
- */
- if (r4) {
- initrd_start = r4 + KERNELBASE;
- initrd_end = r5 + KERNELBASE;
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
-
- /* Copy the kernel command line arguments to a safe place. */
-
- if (r6) {
- *(char *)(r7 + KERNELBASE) = 0;
- strcpy(cmd_line, (char *)(r6 + KERNELBASE));
- }
-
- /* Initialize machine-dependency vectors */
-
- ppc_md.setup_arch = walnut_setup_arch;
- ppc_md.setup_residual = walnut_setup_residual;
- ppc_md.get_cpuinfo = NULL;
- ppc_md.irq_cannonicalize = NULL;
- ppc_md.init_IRQ = walnut_init_IRQ;
- ppc_md.get_irq = walnut_get_irq;
- ppc_md.init = NULL;
-
- ppc_md.restart = walnut_restart;
- ppc_md.power_off = walnut_power_off;
- ppc_md.halt = walnut_halt;
-
- ppc_md.time_init = walnut_time_init;
- ppc_md.set_rtc_time = walnut_set_rtc_time;
- ppc_md.get_rtc_time = walnut_get_rtc_time;
- ppc_md.calibrate_decr = walnut_calibrate_decr;
-
- ppc_md.kbd_setkeycode = NULL;
- ppc_md.kbd_getkeycode = NULL;
- ppc_md.kbd_translate = NULL;
- ppc_md.kbd_unexpected_up = NULL;
- ppc_md.kbd_leds = NULL;
- ppc_md.kbd_init_hw = NULL;
-
-#if defined(CONFIG_MAGIC_SYSRQ)
- ppc_md.ppc_kbd_sysrq_xlate = NULL;
-#endif
-
- return;
-}
-
-/*
- * Document me.
- */
-void __init
-walnut_setup_arch(void)
-{
- /* XXX - Implement me */
-}
-
-/*
- * int walnut_setup_residual()
- *
- * Description:
- * This routine pretty-prints the platform's internal CPU and bus clock
- * frequencies into the buffer for usage in /proc/cpuinfo.
- *
- * Input(s):
- * *buffer - Buffer into which CPU and bus clock frequencies are to be
- * printed.
- *
- * Output(s):
- * *buffer - Buffer with the CPU and bus clock frequencies.
- *
- * Returns:
- * The number of bytes copied into 'buffer' if OK, otherwise zero or less
- * on error.
- */
-int
-walnut_setup_residual(char *buffer)
-{
- int len = 0;
- bd_t *bp = (bd_t *)__res;
-
- len += sprintf(len + buffer,
- "clock\t\t: %dMHz\n"
- "bus clock\t\t: %dMHz\n",
- bp->bi_intfreq / 1000000,
- bp->bi_busfreq / 1000000);
-
- return (len);
-}
-
-/*
- * Document me.
- */
-void __init
-walnut_init_IRQ(void)
-{
- int i;
-
- ppc4xx_pic_init();
-
- for (i = 0; i < NR_IRQS; i++) {
- irq_desc[i].handler = ppc4xx_pic;
- }
-
- return;
-}
-
-/*
- * Document me.
- */
-int
-walnut_get_irq(struct pt_regs *regs)
-{
- return (ppc4xx_pic_get_irq(regs));
-}
-
-/*
- * Document me.
- */
-void
-walnut_restart(char *cmd)
-{
- abort();
-}
-
-/*
- * Document me.
- */
-void
-walnut_power_off(void)
-{
- walnut_restart(NULL);
-}
-
-/*
- * Document me.
- */
-void
-walnut_halt(void)
-{
- walnut_restart(NULL);
-}
-
-/*
- * Document me.
- */
-void __init
-walnut_time_init(void)
-{
- /* XXX - Implement me */
-}
-
-/*
- * Document me.
- */
-int __init
-walnut_set_rtc_time(unsigned long time)
-{
- /* XXX - Implement me */
-
- return (0);
-}
-
-/*
- * Document me.
- */
-unsigned long __init
-walnut_get_rtc_time(void)
-{
- /* XXX - Implement me */
-
- return (0);
-}
-
-/*
- * void __init walnut_calibrate_decr()
- *
- * Description:
- * This routine retrieves the internal processor frequency from the board
- * information structure, sets up the kernel timer decrementer based on
- * that value, enables the 403 programmable interval timer (PIT) and sets
- * it up for auto-reload.
- *
- * Input(s):
- * N/A
- *
- * Output(s):
- * N/A
- *
- * Returns:
- * N/A
- *
- */
-void __init
-walnut_calibrate_decr(void)
-{
- unsigned int freq;
- bd_t *bip = (bd_t *)__res;
-
- freq = bip->bi_intfreq;
-
- decrementer_count = freq / HZ;
- count_period_num = 1;
- count_period_den = freq;
-
- /* Enable the PIT and set auto-reload of its value */
-
- mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
-
- /* Clear any pending timer interrupts */
-
- mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
-}
extern void walnut_calibrate_decr(void);
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __WALNUT_SETUP_H__ */
-/*
- *
- * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- * Module name: walnut_setup.c
- *
- * Description:
- * Architecture- / platform-specific boot-time initialization code for
- * the IBM PowerPC 405GP "Walnut" evaluation board. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
- * <dan@netx4.com>.
- *
- */
-
-#ifndef __WALNUT_SETUP_H__
-#define __WALNUT_SETUP_H__
-
-#include <asm/ptrace.h>
-#include <asm/board.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern unsigned char __res[sizeof(bd_t)];
-
-extern void walnut_init(unsigned long r3,
- unsigned long ird_start,
- unsigned long ird_end,
- unsigned long cline_start,
- unsigned long cline_end);
-extern void walnut_setup_arch(void);
-extern int walnut_setup_residual(char *buffer);
-extern void walnut_init_IRQ(void);
-extern int walnut_get_irq(struct pt_regs *regs);
-extern void walnut_restart(char *cmd);
-extern void walnut_power_off(void);
-extern void walnut_halt(void);
-extern void walnut_time_init(void);
-extern int walnut_set_rtc_time(unsigned long now);
-extern unsigned long walnut_get_rtc_time(void);
-extern void walnut_calibrate_decr(void);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __WALNUT_SETUP_H__ */
-/*
- *
- * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- * Module name: walnut_setup.c
- *
- * Description:
- * Architecture- / platform-specific boot-time initialization code for
- * the IBM PowerPC 405GP "Walnut" evaluation board. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
- * <dan@netx4.com>.
- *
- */
-
-#ifndef __WALNUT_SETUP_H__
-#define __WALNUT_SETUP_H__
-
-#include <asm/ptrace.h>
-#include <asm/board.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern unsigned char __res[sizeof(bd_t)];
-
-extern void walnut_init(unsigned long r3,
- unsigned long ird_start,
- unsigned long ird_end,
- unsigned long cline_start,
- unsigned long cline_end);
-extern void walnut_setup_arch(void);
-extern int walnut_setup_residual(char *buffer);
-extern void walnut_init_IRQ(void);
-extern int walnut_get_irq(struct pt_regs *regs);
-extern void walnut_restart(char *cmd);
-extern void walnut_power_off(void);
-extern void walnut_halt(void);
-extern void walnut_time_init(void);
-extern int walnut_set_rtc_time(unsigned long now);
-extern unsigned long walnut_get_rtc_time(void);
-extern void walnut_calibrate_decr(void);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __WALNUT_SETUP_H__ */
-/*
- *
- * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- * Module name: walnut_setup.c
- *
- * Description:
- * Architecture- / platform-specific boot-time initialization code for
- * the IBM PowerPC 405GP "Walnut" evaluation board. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
- * <dan@netx4.com>.
- *
- */
-
-#ifndef __WALNUT_SETUP_H__
-#define __WALNUT_SETUP_H__
-
-#include <asm/ptrace.h>
-#include <asm/board.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern unsigned char __res[sizeof(bd_t)];
-
-extern void walnut_init(unsigned long r3,
- unsigned long ird_start,
- unsigned long ird_end,
- unsigned long cline_start,
- unsigned long cline_end);
-extern void walnut_setup_arch(void);
-extern int walnut_setup_residual(char *buffer);
-extern void walnut_init_IRQ(void);
-extern int walnut_get_irq(struct pt_regs *regs);
-extern void walnut_restart(char *cmd);
-extern void walnut_power_off(void);
-extern void walnut_halt(void);
-extern void walnut_time_init(void);
-extern int walnut_set_rtc_time(unsigned long now);
-extern unsigned long walnut_get_rtc_time(void);
-extern void walnut_calibrate_decr(void);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __WALNUT_SETUP_H__ */
-/*
- *
- * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- * Module name: walnut_setup.c
- *
- * Description:
- * Architecture- / platform-specific boot-time initialization code for
- * the IBM PowerPC 405GP "Walnut" evaluation board. Adapted from original
- * code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
- * <dan@netx4.com>.
- *
- */
-
-#ifndef __WALNUT_SETUP_H__
-#define __WALNUT_SETUP_H__
-
-#include <asm/ptrace.h>
-#include <asm/board.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern unsigned char __res[sizeof(bd_t)];
-
-extern void walnut_init(unsigned long r3,
- unsigned long ird_start,
- unsigned long ird_end,
- unsigned long cline_start,
- unsigned long cline_end);
-extern void walnut_setup_arch(void);
-extern int walnut_setup_residual(char *buffer);
-extern void walnut_init_IRQ(void);
-extern int walnut_get_irq(struct pt_regs *regs);
-extern void walnut_restart(char *cmd);
-extern void walnut_power_off(void);
-extern void walnut_halt(void);
-extern void walnut_time_init(void);
-extern int walnut_set_rtc_time(unsigned long now);
-extern unsigned long walnut_get_rtc_time(void);
-extern void walnut_calibrate_decr(void);
-
-
#ifdef __cplusplus
}
#endif
-# $Id: config.in,v 1.85 2000/02/08 08:57:45 jj Exp $
+# $Id: config.in,v 1.86 2000/02/10 02:51:10 davem Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
comment 'SCSI support type (disk, tape, CDrom)'
dep_tristate ' SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
+
+ if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then
+ int 'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40
+ fi
+
dep_tristate ' SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
+
+ if [ "$CONFIG_BLK_DEV_ST" != "n" ]; then
+ int 'Maximum number of SCSI tapes that can be loaded as modules' CONFIG_ST_EXTRA_DEVS 2
+ fi
+
dep_tristate ' SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
+
if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
bool ' Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR
+ int 'Maximum number of CDROM devices that can be loaded as modules' CONFIG_SR_EXTRA_DEVS 2
fi
+
dep_tristate ' SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
bool ' Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN
bool ' Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS
+ bool ' SCSI logging facility' CONFIG_SCSI_LOGGING
mainmenu_option next_comment
comment 'SCSI low-level drivers'
# SCSI support type (disk, tape, CDrom)
#
CONFIG_BLK_DEV_SD=y
+CONFIG_SD_EXTRA_DEVS=40
CONFIG_CHR_DEV_ST=y
+CONFIG_ST_EXTRA_DEVS=2
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_SR_EXTRA_DEVS=2
CONFIG_CHR_DEV_SG=m
#
#
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
#
# SCSI low-level drivers
-# $Id: config.in,v 1.94 2000/02/08 08:57:50 jj Exp $
+# $Id: config.in,v 1.95 2000/02/10 02:51:12 davem Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
comment 'SCSI support type (disk, tape, CDrom)'
dep_tristate ' SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
+
+ if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then
+ int 'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40
+ fi
+
dep_tristate ' SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
+
+ if [ "$CONFIG_BLK_DEV_ST" != "n" ]; then
+ int 'Maximum number of SCSI tapes that can be loaded as modules' CONFIG_ST_EXTRA_DEVS 2
+ fi
+
dep_tristate ' SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
+
if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
bool ' Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR
+ int 'Maximum number of CDROM devices that can be loaded as modules' CONFIG_SR_EXTRA_DEVS 2
fi
+
dep_tristate ' SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
bool ' Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN
bool ' Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS
+ bool ' SCSI logging facility' CONFIG_SCSI_LOGGING
mainmenu_option next_comment
comment 'SCSI low-level drivers'
# SCSI support type (disk, tape, CDrom)
#
CONFIG_BLK_DEV_SD=y
+CONFIG_SD_EXTRA_DEVS=40
CONFIG_CHR_DEV_ST=y
+CONFIG_ST_EXTRA_DEVS=2
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_SR_EXTRA_DEVS=2
CONFIG_CHR_DEV_SG=m
#
#
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
#
# SCSI low-level drivers
* development and support.
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
a file structure */
lo->lo_backing_file = NULL;
} else if (S_ISREG(inode->i_mode)) {
- if (!inode->i_op->get_block) {
+ /*
+ * Total crap. We should just use pagecache instead of trying
+ * to redirect on block level.
+ */
+ if (!inode->i_mapping->a_ops->bmap) {
printk(KERN_ERR "loop: device has no block access/not implemented\n");
goto out_putf;
}
int (*remove_memory) (agp_memory *, off_t, int);
agp_memory *(*alloc_by_type) (size_t, int);
void (*free_by_type) (agp_memory *);
-
- /* Links to vendor/device specific setup functions */
-#ifdef CONFIG_AGP_INTEL
- void (*intel_generic_setup) (void);
-#endif
-#ifdef CONFIG_AGP_I810
- void (*intel_i810_setup) (struct pci_dev *);
-#endif
-#ifdef CONFIG_AGP_VIA
- void (*via_generic_setup) (void);
-#endif
-#ifdef CONFIG_AGP_SIS
- void (*sis_generic_setup) (void);
-#endif
-#ifdef CONFIG_AGP_AMD
- void (*amd_irongate_setup) (void);
-#endif
-#ifdef CONFIG_AGP_ALI
- void (*ali_generic_setup) (void);
-#endif
};
#define OUTREG32(mmap, addr, val) __raw_writel((val), (mmap)+(addr))
#define min(a,b) (((a)<(b))?(a):(b))
#endif
+#define arraysize(x) (sizeof(x)/sizeof(*(x)))
+
+#define AGPGART_MODULE_NAME "agpgart"
+#define PFX AGPGART_MODULE_NAME ": "
+
#define PGE_EMPTY(p) (!(p) || (p) == (unsigned long) agp_bridge.scratch_page)
#ifndef PCI_DEVICE_ID_VIA_82C691_0
{
atomic_set(&cpus_waiting, smp_num_cpus - 1);
if (smp_call_function(ipi_handler, NULL, 1, 0) != 0)
- panic("agpgart: timed out waiting for the other CPUs!\n");
+ panic(PFX "timed out waiting for the other CPUs!\n");
flush_cache();
while (atomic_read(&cpus_waiting) > 0)
barrier();
values = A_SIZE_FIX(agp_bridge.aperture_sizes);
if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) {
- printk("agpgart: i810 is disabled\n");
+ printk(KERN_WARNING PFX "i810 is disabled\n");
return 0;
}
if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) {
if ((INREG32(intel_i810_private.registers, I810_DRAM_CTL)
& I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) {
/* This will need to be dynamically assigned */
- printk(KERN_INFO
- "agpgart: detected 4MB dedicated video ram.\n");
+ printk(KERN_INFO PFX "detected 4MB dedicated video ram.\n");
intel_i810_private.num_dcache_entries = 1024;
}
pci_read_config_dword(intel_i810_private.i810_dev, I810_GMADDR, &temp);
return addr | agp_bridge.masks[type].mask;
}
-static void intel_i810_setup(struct pci_dev *i810_dev)
+static int __init intel_i810_setup(struct pci_dev *i810_dev)
{
intel_i810_private.i810_dev = i810_dev;
agp_bridge.remove_memory = intel_i810_remove_entries;
agp_bridge.alloc_by_type = intel_i810_alloc_by_type;
agp_bridge.free_by_type = intel_i810_free_by_type;
+
+ return 0;
}
-#endif
+#endif /* CONFIG_AGP_I810 */
#ifdef CONFIG_AGP_INTEL
{4, 1024, 0, 63}
};
-static void intel_generic_setup(void)
+static int __init intel_generic_setup (struct pci_dev *pdev)
{
agp_bridge.masks = intel_generic_masks;
agp_bridge.num_of_masks = 1;
agp_bridge.remove_memory = agp_generic_remove_memory;
agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
agp_bridge.free_by_type = agp_generic_free_by_type;
+
+ return 0;
+
+ (void) pdev; /* unused */
}
-#endif
+#endif /* CONFIG_AGP_INTEL */
#ifdef CONFIG_AGP_VIA
{0x00000000, 0}
};
-static void via_generic_setup(void)
+static int __init via_generic_setup (struct pci_dev *pdev)
{
agp_bridge.masks = via_generic_masks;
agp_bridge.num_of_masks = 1;
agp_bridge.remove_memory = agp_generic_remove_memory;
agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
agp_bridge.free_by_type = agp_generic_free_by_type;
+
+ return 0;
+
+ (void) pdev; /* unused */
}
-#endif
+#endif /* CONFIG_AGP_VIA */
#ifdef CONFIG_AGP_SIS
{0x00000000, 0}
};
-static void sis_generic_setup(void)
+static int __init sis_generic_setup (struct pci_dev *pdev)
{
agp_bridge.masks = sis_generic_masks;
agp_bridge.num_of_masks = 1;
agp_bridge.remove_memory = agp_generic_remove_memory;
agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
agp_bridge.free_by_type = agp_generic_free_by_type;
+
+ return 0;
+
+ (void) pdev; /* unused */
}
-#endif
+#endif /* CONFIG_AGP_SIS */
#ifdef CONFIG_AGP_AMD
{0x00000001, 0}
};
-static void amd_irongate_setup(void)
+static int __init amd_irongate_setup (struct pci_dev *pdev)
{
agp_bridge.masks = amd_irongate_masks;
agp_bridge.num_of_masks = 1;
agp_bridge.remove_memory = agp_generic_remove_memory;
agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
agp_bridge.free_by_type = agp_generic_free_by_type;
+
+ return 0;
+
+ (void) pdev; /* unused */
}
-#endif
+#endif /* CONFIG_AGP_AMD */
#ifdef CONFIG_AGP_ALI
{4, 1024, 0, 3}
};
-static void ali_generic_setup(void)
+static int __init ali_generic_setup (struct pci_dev *pdev)
{
agp_bridge.masks = ali_generic_masks;
agp_bridge.num_of_masks = 1;
agp_bridge.remove_memory = agp_generic_remove_memory;
agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
agp_bridge.free_by_type = agp_generic_free_by_type;
+
+ return 0;
+
+ (void) pdev; /* unused */
}
-#endif
+#endif /* CONFIG_AGP_ALI */
+
+
+/* per-chipset initialization data.
+ * note -- all chipsets for a single vendor MUST be grouped together
+ */
+static struct {
+ unsigned short device_id; /* first, to make table easier to read */
+ unsigned short vendor_id;
+ enum chipset_type chipset;
+ const char *vendor_name;
+ const char *chipset_name;
+ int (*chipset_setup) (struct pci_dev *pdev);
+} agp_bridge_info[] __initdata = {
+
+#ifdef CONFIG_AGP_ALI
+ { PCI_DEVICE_ID_AL_M1541_0,
+ PCI_VENDOR_ID_AL,
+ ALI_M1541,
+ "Ali",
+ "M1541",
+ ali_generic_setup },
+ { 0,
+ PCI_VENDOR_ID_AL,
+ ALI_GENERIC,
+ "Ali",
+ "Generic",
+ ali_generic_setup },
+#endif /* CONFIG_AGP_ALI */
+
+#ifdef CONFIG_AGP_AMD
+ { PCI_DEVICE_ID_AMD_IRONGATE_0,
+ PCI_VENDOR_ID_AMD,
+ AMD_IRONGATE,
+ "AMD",
+ "Irongate",
+ amd_irongate_setup },
+ { 0,
+ PCI_VENDOR_ID_AMD,
+ AMD_GENERIC,
+ "AMD",
+ "Generic",
+ amd_irongate_setup },
+#endif /* CONFIG_AGP_AMD */
+
+#ifdef CONFIG_AGP_INTEL
+ { PCI_DEVICE_ID_INTEL_82443LX_0,
+ PCI_VENDOR_ID_INTEL,
+ INTEL_LX,
+ "Intel",
+ "440LX",
+ intel_generic_setup },
+ { PCI_DEVICE_ID_INTEL_82443BX_0,
+ PCI_VENDOR_ID_INTEL,
+ INTEL_BX,
+ "Intel",
+ "440BX",
+ intel_generic_setup },
+ { PCI_DEVICE_ID_INTEL_82443GX_0,
+ PCI_VENDOR_ID_INTEL,
+ INTEL_GX,
+ "Intel",
+ "440GX",
+ intel_generic_setup },
+ { 0,
+ PCI_VENDOR_ID_INTEL,
+ INTEL_GENERIC,
+ "Intel",
+ "Generic",
+ intel_generic_setup },
+#endif /* CONFIG_AGP_INTEL */
+
+#ifdef CONFIG_AGP_SIS
+ { 0,
+ PCI_VENDOR_ID_SI,
+ SIS_GENERIC,
+ "SiS",
+ "Generic",
+ sis_generic_setup },
+#endif /* CONFIG_AGP_SIS */
+
+#ifdef CONFIG_AGP_VIA
+ { PCI_DEVICE_ID_VIA_8501_0,
+ PCI_VENDOR_ID_VIA,
+ VIA_MVP4,
+ "Via",
+ "MVP4",
+ via_generic_setup },
+ { PCI_DEVICE_ID_VIA_82C597_0,
+ PCI_VENDOR_ID_VIA,
+ VIA_VP3,
+ "Via",
+ "VP3",
+ via_generic_setup },
+ { PCI_DEVICE_ID_VIA_82C598_0,
+ PCI_VENDOR_ID_VIA,
+ VIA_MVP3,
+ "Via",
+ "MVP3",
+ via_generic_setup },
+ { PCI_DEVICE_ID_VIA_82C691_0,
+ PCI_VENDOR_ID_VIA,
+ VIA_APOLLO_PRO,
+ "Via",
+ "Apollo Pro",
+ via_generic_setup },
+ { 0,
+ PCI_VENDOR_ID_VIA,
+ VIA_GENERIC,
+ "Via",
+ "Generic",
+ via_generic_setup },
+#endif /* CONFIG_AGP_VIA */
+
+ { 0, }, /* dummy final entry, always present */
+};
+
+
+/* scan table above for supported devices */
+static int __init agp_lookup_host_bridge (struct pci_dev *pdev)
+{
+ int i;
+
+ for (i = 0; i < arraysize (agp_bridge_info); i++)
+ if (pdev->vendor == agp_bridge_info[i].vendor_id)
+ break;
+
+ if (i >= arraysize (agp_bridge_info)) {
+ printk (KERN_DEBUG PFX "unsupported bridge\n");
+ return -ENODEV;
+ }
+
+ while ((i < arraysize (agp_bridge_info)) &&
+ (agp_bridge_info[i].vendor_id == pdev->vendor)) {
+ if (pdev->device == agp_bridge_info[i].device_id) {
+ printk (KERN_INFO PFX "Detected %s %s chipset\n",
+ agp_bridge_info[i].vendor_name,
+ agp_bridge_info[i].chipset_name);
+ agp_bridge.type = agp_bridge_info[i].chipset;
+ return agp_bridge_info[i].chipset_setup (pdev);
+ }
+
+ i++;
+ }
+
+ i--; /* point to vendor generic entry (device_id == 0) */
+
+ /* try init anyway, if user requests it AND
+ * there is a 'generic' bridge entry for this vendor */
+ if (agp_try_unsupported && agp_bridge_info[i].device_id == 0) {
+ printk(KERN_WARNING PFX "Trying generic %s routines"
+ " for device id: %x\n",
+ agp_bridge_info[i].vendor_name, pdev->device);
+ agp_bridge.type = agp_bridge_info[i].chipset;
+ return agp_bridge_info[i].chipset_setup (pdev);
+ }
+ printk(KERN_ERR PFX "Unsupported %s chipset,"
+ " you might want to try "
+ "agp_try_unsupported=1.\n",
+ agp_bridge_info[i].vendor_name);
+ return -ENODEV;
+}
/* Supported Device Scanning routine */
-static void agp_find_supported_device(void)
+static int __init agp_find_supported_device(void)
{
struct pci_dev *dev = NULL;
u8 cap_ptr = 0x00;
u32 cap_id, scratch;
- if ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8, NULL)) == NULL) {
- agp_bridge.type = NOT_SUPPORTED;
- return;
- }
+ if ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8, NULL)) == NULL)
+ return -ENODEV;
+
agp_bridge.dev = dev;
/* Need to test for I810 here */
PCI_DEVICE_ID_INTEL_810_1,
NULL);
if (i810_dev == NULL) {
- printk("agpgart: Detected an Intel i810,"
+ printk(KERN_ERR PFX "Detected an Intel i810,"
" but could not find the secondary"
" device.\n");
- agp_bridge.type = NOT_SUPPORTED;
- return;
+ return -ENODEV;
}
- printk(KERN_INFO "agpgart: Detected an Intel "
+ printk(KERN_INFO PFX "Detected an Intel "
"i810 Chipset.\n");
agp_bridge.type = INTEL_I810;
- agp_bridge.intel_i810_setup(i810_dev);
- return;
+ return intel_i810_setup (i810_dev);
case PCI_DEVICE_ID_INTEL_810_DC100_0:
i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_810_DC100_1,
NULL);
if (i810_dev == NULL) {
- printk("agpgart: Detected an Intel i810 "
+ printk(KERN_ERR PFX "Detected an Intel i810 "
"DC100, but could not find the "
"secondary device.\n");
- agp_bridge.type = NOT_SUPPORTED;
- return;
+ return -ENODEV;
}
- printk(KERN_INFO "agpgart: Detected an Intel i810 "
+ printk(KERN_INFO PFX "Detected an Intel i810 "
"DC100 Chipset.\n");
agp_bridge.type = INTEL_I810;
- agp_bridge.intel_i810_setup(i810_dev);
- return;
+ return intel_i810_setup(i810_dev);
case PCI_DEVICE_ID_INTEL_810_E_0:
i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_810_E_1,
NULL);
if (i810_dev == NULL) {
- printk("agpgart: Detected an Intel i810 E"
+ printk(KERN_ERR PFX "Detected an Intel i810 E"
", but could not find the secondary "
"device.\n");
- agp_bridge.type = NOT_SUPPORTED;
- return;
+ return -ENODEV;
}
- printk(KERN_INFO "agpgart: Detected an Intel i810 E "
+ printk(KERN_INFO PFX "Detected an Intel i810 E "
"Chipset.\n");
agp_bridge.type = INTEL_I810;
- agp_bridge.intel_i810_setup(i810_dev);
- return;
+ return intel_i810_setup(i810_dev);
+
default:
break;
}
}
-#endif
+#endif /* CONFIG_AGP_I810 */
+
/* find capndx */
pci_read_config_dword(dev, 0x04, &scratch);
+ if (!(scratch & 0x00100000))
+ return -ENODEV;
- if (!(scratch & 0x00100000)) {
- agp_bridge.type = NOT_SUPPORTED;
- return;
- }
pci_read_config_byte(dev, 0x34, &cap_ptr);
-
if (cap_ptr != 0x00) {
do {
pci_read_config_dword(dev, cap_ptr, &cap_id);
}
while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00));
}
- if (cap_ptr == 0x00) {
- agp_bridge.type = NOT_SUPPORTED;
- return;
- }
+ if (cap_ptr == 0x00)
+ return -ENODEV;
agp_bridge.capndx = cap_ptr;
/* Fill in the mode register */
agp_bridge.capndx + 4,
&agp_bridge.mode);
- switch (dev->vendor) {
-#ifdef CONFIG_AGP_INTEL
- case PCI_VENDOR_ID_INTEL:
- switch (dev->device) {
- case PCI_DEVICE_ID_INTEL_82443LX_0:
- agp_bridge.type = INTEL_LX;
- printk(KERN_INFO "agpgart: Detected an Intel 440LX"
- " Chipset.\n");
- agp_bridge.intel_generic_setup();
- return;
-
- case PCI_DEVICE_ID_INTEL_82443BX_0:
- agp_bridge.type = INTEL_BX;
- printk(KERN_INFO "agpgart: Detected an Intel 440BX "
- "Chipset.\n");
- agp_bridge.intel_generic_setup();
- return;
-
- case PCI_DEVICE_ID_INTEL_82443GX_0:
- agp_bridge.type = INTEL_GX;
- printk(KERN_INFO "agpgart: Detected an Intel 440GX "
- "Chipset.\n");
- agp_bridge.intel_generic_setup();
- return;
-
- default:
- if (agp_try_unsupported != 0) {
- printk("agpgart: Trying generic intel "
- "routines for device id: %x\n",
- dev->device);
- agp_bridge.type = INTEL_GENERIC;
- agp_bridge.intel_generic_setup();
- return;
- } else {
- printk("agpgart: Unsupported intel chipset,"
- " you might want to try "
- "agp_try_unsupported=1.\n");
- agp_bridge.type = NOT_SUPPORTED;
- return;
- }
- }
- break;
-#endif
-
-#ifdef CONFIG_AGP_VIA
- case PCI_VENDOR_ID_VIA:
- switch (dev->device) {
- case PCI_DEVICE_ID_VIA_82C597_0:
- agp_bridge.type = VIA_VP3;
- printk(KERN_INFO "agpgart: Detected a VIA VP3 "
- "Chipset.\n");
- agp_bridge.via_generic_setup();
- return;
-
- case PCI_DEVICE_ID_VIA_82C598_0:
- agp_bridge.type = VIA_MVP3;
- printk(KERN_INFO "agpgart: Detected a VIA MVP3 "
- "Chipset.\n");
- agp_bridge.via_generic_setup();
- return;
-
- case PCI_DEVICE_ID_VIA_82C691_0:
- agp_bridge.type = VIA_APOLLO_PRO;
- printk(KERN_INFO "agpgart: Detected a VIA Apollo "
- "Pro Chipset.\n");
- agp_bridge.via_generic_setup();
- return;
-
- default:
- if (agp_try_unsupported != 0) {
- printk("agpgart: Trying generic VIA routines"
- " for device id: %x\n", dev->device);
- agp_bridge.type = VIA_GENERIC;
- agp_bridge.via_generic_setup();
- return;
- } else {
- printk("agpgart: Unsupported VIA chipset,"
- " you might want to try "
- "agp_try_unsupported=1.\n");
- agp_bridge.type = NOT_SUPPORTED;
- return;
- }
- }
- break;
-#endif
-
-#ifdef CONFIG_AGP_SIS
- case PCI_VENDOR_ID_SI:
- switch (dev->device) {
- /* ToDo need to find out the
- * specific devices supported.
- */
- default:
- if (agp_try_unsupported != 0) {
- printk("agpgart: Trying generic SiS routines"
- " for device id: %x\n", dev->device);
- agp_bridge.type = SIS_GENERIC;
- agp_bridge.sis_generic_setup();
- return;
- } else {
- printk("agpgart: Unsupported SiS chipset, "
- "you might want to try "
- "agp_try_unsupported=1.\n");
- agp_bridge.type = NOT_SUPPORTED;
- return;
- }
- }
- break;
-#endif
-
-#ifdef CONFIG_AGP_AMD
- case PCI_VENDOR_ID_AMD:
- switch (dev->device) {
- case PCI_DEVICE_ID_AMD_IRONGATE_0:
- agp_bridge.type = AMD_IRONGATE;
- printk(KERN_INFO "agpgart: Detected an AMD Irongate"
- " Chipset.\n");
- agp_bridge.amd_irongate_setup();
- return;
-
- default:
- if (agp_try_unsupported != 0) {
- printk("agpgart: Trying Amd irongate"
- " routines for device id: %x\n",
- dev->device);
- agp_bridge.type = AMD_GENERIC;
- agp_bridge.amd_irongate_setup();
- return;
- } else {
- printk("agpgart: Unsupported Amd chipset,"
- " you might want to try "
- "agp_try_unsupported=1.\n");
- agp_bridge.type = NOT_SUPPORTED;
- return;
- }
- }
- break;
-#endif
-
-#ifdef CONFIG_AGP_ALI
- case PCI_VENDOR_ID_AL:
- switch (dev->device) {
- case PCI_DEVICE_ID_AL_M1541_0:
- agp_bridge.type = ALI_M1541;
- printk(KERN_INFO "agpgart: Detected an ALi M1541"
- " Chipset\n");
- agp_bridge.ali_generic_setup();
- return;
- default:
- if (agp_try_unsupported != 0) {
- printk("agpgart: Trying ALi generic routines"
- " for device id: %x\n", dev->device);
- agp_bridge.type = ALI_GENERIC;
- agp_bridge.ali_generic_setup();
- return;
- } else {
- printk("agpgart: Unsupported ALi chipset,"
- " you might want to type "
- "agp_try_unsupported=1.\n");
- agp_bridge.type = NOT_SUPPORTED;
- return;
- }
- }
- break;
-#endif
- default:
- agp_bridge.type = NOT_SUPPORTED;
- return;
- }
+ /* probe for known chipsets */
+ return agp_lookup_host_bridge (dev);
}
struct agp_max_table {
int agp;
};
-static struct agp_max_table maxes_table[9] =
+static struct agp_max_table maxes_table[9] __initdata =
{
{0, 0},
{32, 4},
{4096, 3932}
};
-static int agp_find_max(void)
+static int __init agp_find_max (void)
{
long memory, index, result;
(maxes_table[index].agp - maxes_table[index - 1].agp)) /
(maxes_table[index].mem - maxes_table[index - 1].mem);
- printk(KERN_INFO "agpgart: Maximum main memory to use "
+ printk(KERN_INFO PFX "Maximum main memory to use "
"for agp memory: %ldM\n", result);
result = result << (20 - PAGE_SHIFT);
return result;
AGPGART_VERSION_MINOR
};
-static int agp_backend_initialize(void)
+static int __init agp_backend_initialize(void)
{
- int size_value;
+ int size_value, rc, got_gatt=0, got_keylist=0;
memset(&agp_bridge, 0, sizeof(struct agp_bridge_data));
agp_bridge.type = NOT_SUPPORTED;
-#ifdef CONFIG_AGP_INTEL
- agp_bridge.intel_generic_setup = intel_generic_setup;
-#endif
-#ifdef CONFIG_AGP_I810
- agp_bridge.intel_i810_setup = intel_i810_setup;
-#endif
-#ifdef CONFIG_AGP_VIA
- agp_bridge.via_generic_setup = via_generic_setup;
-#endif
-#ifdef CONFIG_AGP_SIS
- agp_bridge.sis_generic_setup = sis_generic_setup;
-#endif
-#ifdef CONFIG_AGP_AMD
- agp_bridge.amd_irongate_setup = amd_irongate_setup;
-#endif
-#ifdef CONFIG_AGP_ALI
- agp_bridge.ali_generic_setup = ali_generic_setup;
-#endif
agp_bridge.max_memory_agp = agp_find_max();
agp_bridge.version = &agp_current_version;
- agp_find_supported_device();
+
+ rc = agp_find_supported_device();
+ if (rc) {
+ /* not KERN_ERR because error msg should have already printed */
+ printk(KERN_DEBUG PFX "no supported devices found.\n");
+ return rc;
+ }
if (agp_bridge.needs_scratch_page == TRUE) {
agp_bridge.scratch_page = agp_alloc_page();
if (agp_bridge.scratch_page == 0) {
- printk("agpgart: unable to get memory for "
+ printk(KERN_ERR PFX "unable to get memory for "
"scratch page.\n");
return -ENOMEM;
}
agp_bridge.scratch_page =
agp_bridge.mask_memory(agp_bridge.scratch_page, 0);
}
- if (agp_bridge.type == NOT_SUPPORTED) {
- printk("agpgart: no supported devices found.\n");
- return -EINVAL;
- }
+
size_value = agp_bridge.fetch_size();
if (size_value == 0) {
- printk("agpgart: unable to detrimine aperture size.\n");
- return -EINVAL;
+ printk(KERN_ERR PFX "unable to detrimine aperture size.\n");
+ rc = -EINVAL;
+ goto err_out;
}
if (agp_bridge.create_gatt_table()) {
- printk("agpgart: unable to get memory for graphics "
+ printk(KERN_ERR PFX "unable to get memory for graphics "
"translation table.\n");
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto err_out;
}
+ got_gatt = 1;
+
agp_bridge.key_list = vmalloc(PAGE_SIZE * 4);
-
if (agp_bridge.key_list == NULL) {
- printk("agpgart: error allocating memory for key lists.\n");
- agp_bridge.free_gatt_table();
- return -ENOMEM;
+ printk(KERN_ERR PFX "error allocating memory for key lists.\n");
+ rc = -ENOMEM;
+ goto err_out;
}
+ got_keylist = 1;
+
+ /* FIXME vmalloc'd memory not guaranteed contiguous */
memset(agp_bridge.key_list, 0, PAGE_SIZE * 4);
if (agp_bridge.configure()) {
- printk("agpgart: error configuring host chipset.\n");
- agp_bridge.free_gatt_table();
- vfree(agp_bridge.key_list);
- return -EINVAL;
+ printk(KERN_ERR PFX "error configuring host chipset.\n");
+ rc = -EINVAL;
+ goto err_out;
}
- printk(KERN_INFO "agpgart: Physical address of the agp aperture:"
- " 0x%lx\n", agp_bridge.gart_bus_addr);
- printk(KERN_INFO "agpgart: Agp aperture is %dM in size.\n",
- size_value);
+
+ printk(KERN_INFO PFX "AGP aperture is %dM @ 0x%lx\n",
+ size_value, agp_bridge.gart_bus_addr);
+
return 0;
+
+err_out:
+ if (agp_bridge.needs_scratch_page == TRUE) {
+ agp_bridge.scratch_page &= ~(0x00000fff);
+ agp_destroy_page((unsigned long)
+ phys_to_virt(agp_bridge.scratch_page));
+ }
+ if (got_gatt)
+ agp_bridge.free_gatt_table();
+ if (got_keylist)
+ vfree(agp_bridge.key_list);
+ return rc;
}
+
+/* cannot be __exit b/c as it could be called from __init code */
static void agp_backend_cleanup(void)
{
agp_bridge.cleanup();
printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Jeff Hartmann\n",
AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR);
- ret_val = agp_backend_initialize();
- if (ret_val != 0) {
+ ret_val = agp_backend_initialize();
+ if (ret_val)
return ret_val;
- }
- ret_val = agp_frontend_initialize();
- if (ret_val != 0) {
+ ret_val = agp_frontend_initialize();
+ if (ret_val) {
agp_backend_cleanup();
return ret_val;
}
+
return 0;
}
#include <asm/page.h>
#include <asm/mman.h>
+#include "agp.h"
+
static struct agp_front_data agp_fe;
static agp_memory *agp_find_mem_by_key(int key)
agp_memory *memory;
memory = agp_allocate_memory(pg_count, type);
- printk("memory : %p\n", memory);
+ printk(KERN_DEBUG "memory : %p\n", memory);
if (memory == NULL) {
return NULL;
}
unsigned int cmd, unsigned long arg)
{
agp_file_private *curr_priv = (agp_file_private *) file->private_data;
- int ret_val;
+ int ret_val = -ENOTTY;
AGP_LOCK();
if ((agp_fe.current_controller == NULL) &&
(cmd != AGPIOC_ACQUIRE)) {
- return -EINVAL;
+ ret_val = -EINVAL;
+ goto ioctl_out;
}
if ((agp_fe.backend_acquired != TRUE) &&
(cmd != AGPIOC_ACQUIRE)) {
- return -EBUSY;
+ ret_val = -EBUSY;
+ goto ioctl_out;
}
if (cmd != AGPIOC_ACQUIRE) {
if (!(test_bit(AGP_FF_IS_CONTROLLER,
&curr_priv->access_flags))) {
- return -EPERM;
+ ret_val = -EPERM;
+ goto ioctl_out;
}
/* Use the original pid of the controller,
* in case it's threaded */
if (agp_fe.current_controller->pid != curr_priv->my_pid) {
- return -EBUSY;
+ ret_val = -EBUSY;
+ goto ioctl_out;
}
}
switch (cmd) {
case AGPIOC_INFO:
{
ret_val = agpioc_info_wrap(curr_priv, arg);
- AGP_UNLOCK();
- return ret_val;
+ goto ioctl_out;
}
case AGPIOC_ACQUIRE:
{
ret_val = agpioc_acquire_wrap(curr_priv, arg);
- AGP_UNLOCK();
- return ret_val;
+ goto ioctl_out;
}
case AGPIOC_RELEASE:
{
ret_val = agpioc_release_wrap(curr_priv, arg);
- AGP_UNLOCK();
- return ret_val;
+ goto ioctl_out;
}
case AGPIOC_SETUP:
{
ret_val = agpioc_setup_wrap(curr_priv, arg);
- AGP_UNLOCK();
- return ret_val;
+ goto ioctl_out;
}
case AGPIOC_RESERVE:
{
ret_val = agpioc_reserve_wrap(curr_priv, arg);
- AGP_UNLOCK();
- return ret_val;
+ goto ioctl_out;
}
case AGPIOC_PROTECT:
{
ret_val = agpioc_protect_wrap(curr_priv, arg);
- AGP_UNLOCK();
- return ret_val;
+ goto ioctl_out;
}
case AGPIOC_ALLOCATE:
{
ret_val = agpioc_allocate_wrap(curr_priv, arg);
- AGP_UNLOCK();
- return ret_val;
+ goto ioctl_out;
}
case AGPIOC_DEALLOCATE:
{
ret_val = agpioc_deallocate_wrap(curr_priv, arg);
- AGP_UNLOCK();
- return ret_val;
+ goto ioctl_out;
}
case AGPIOC_BIND:
{
ret_val = agpioc_bind_wrap(curr_priv, arg);
- AGP_UNLOCK();
- return ret_val;
+ goto ioctl_out;
}
case AGPIOC_UNBIND:
{
ret_val = agpioc_unbind_wrap(curr_priv, arg);
- AGP_UNLOCK();
- return ret_val;
+ goto ioctl_out;
}
}
-
+
+ioctl_out:
AGP_UNLOCK();
- return -ENOTTY;
+ return ret_val;
}
static struct file_operations agp_fops =
static struct miscdevice agp_miscdev =
{
AGPGART_MINOR,
- "agpgart",
+ AGPGART_MODULE_NAME,
&agp_fops
};
-int agp_frontend_initialize(void)
+int __init agp_frontend_initialize(void)
{
memset(&agp_fe, 0, sizeof(struct agp_front_data));
AGP_LOCK_INIT();
if (misc_register(&agp_miscdev)) {
- printk("agpgart: unable to get minor: %d\n", AGPGART_MINOR);
+ printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR);
return -EIO;
}
return 0;
}
-void agp_frontend_cleanup(void)
+void __exit agp_frontend_cleanup(void)
{
misc_deregister(&agp_miscdev);
- return;
}
*/
static struct file_operations efi_rtc_fops = {
- NULL,
- NULL, /* no read */
- NULL, /* No write */
- NULL, /* No readdir */
- NULL,
- efi_rtc_ioctl,
- NULL, /* No mmap */
- efi_rtc_open,
- NULL, /* flush */
- efi_rtc_close
+ ioctl: efi_rtc_ioctl,
+ open: efi_rtc_open,
+ release: efi_rtc_close,
};
static struct miscdevice efi_rtc_dev=
/*
* Linux driver for the PC110 pad
+ */
+
+/**
+ * DOC: PC110 Digitizer Hardware
*
* The pad provides triples of data. The first byte has
* 0x80=bit 8 X, 0x01=bit 7 X, 0x08=bit 8 Y, 0x01=still down
* The third is bits 0-6 Y
*
* This is read internally and used to synthesize a stream of
- * triples in the form expected from a PS/2 device.
+ * triples in the form expected from a PS/2 device. Specialist
+ * applications can choose to obtain the pad data in other formats
+ * including a debugging mode.
+ *
+ * It would be good to add a joystick driver mode to this pad so
+ * that doom and other game playing are better. One possible approach
+ * would be to deactive the mouse mode while the joystick port is opened.
+ */
+
+/*
+ * History
*
* 0.0 1997-05-16 Alan Cox <alan@redhat.com> - Pad reader
* 0.1 1997-05-19 Robin O'Leary <robin@acm.org> - PS/2 emulation
* 0.2 1997-06-03 Robin O'Leary <robin@acm.org> - tap gesture
* 0.3 1997-06-27 Alan Cox <alan@redhat.com> - 2.1 commit
* 0.4 1997-11-09 Alan Cox <alan@redhat.com> - Single Unix VFS API changes
+ * 0.5 2000-02-10 Alan Cox <alan@redhat.com> - 2.3.x cleanup, documentation
*/
#include <linux/module.h>
static struct semaphore reader_lock;
/*
- * Utility to reset a timer to go off some time in the future.
+ * set_timer_callback:
+ *
+ * Utility to reset a timer to go off some time in the future.
*/
static void set_timer_callback(struct timer_list *timer, int ticks)
}
-/*
- * Take care of letting any waiting processes know that
- * now would be a good time to do a read(). Called
- * whenever a state transition occurs, real or synthetic.
+/**
+ * wake_readers:
+ *
+ * Take care of letting any waiting processes know that
+ * now would be a good time to do a read(). Called
+ * whenever a state transition occurs, real or synthetic. Also
+ * issue any SIGIO's to programs that use SIGIO on mice (eg
+ * Executor)
*/
static void wake_readers(void)
static struct timer_list tap_timer = { NULL, NULL, 0, 0, tap_timeout };
-/*
+/**
+ * tap_timeout:
+ * @data: Unused
+ *
* This callback goes off a short time after an up/down transition;
* before it goes off, transitions will be considered part of a
* single PS/2 event and counted in transition_count. Once the
}
-/*
+/**
+ * notify_pad_up_down:
+ *
* Called by the raw pad read routines when a (debounced) up/down
* transition is detected.
*/
wake_readers();
}
+/**
+ * read_button:
+ * @b: pointer to the button status.
+ *
+ * The actual button state depends on what we are seeing. We have to check
+ * for the tap gesture and also for dragging.
+ */
static void read_button(int *b)
{
static struct timer_list bounce_timer = { NULL, NULL, 0, 0, bounce_timeout };
+
+/**
+ * bounce_timeout:
+ * @data: Unused
+ *
+ * No further up/down transitions happened within the
+ * bounce period, so treat this as a genuine transition.
+ */
+
static void bounce_timeout(unsigned long data)
{
- /*
- * No further up/down transitions happened within the
- * bounce period, so treat this as a genuine transition.
- */
switch(bounce)
{
case NO_BOUNCE:
* Strange; the timer callback should only go off if
* we were expecting to do bounce processing!
*/
- printk("pc110pad, bounce_timeout: bounce flag not set!\n");
+ printk(KERN_WARNING "pc110pad, bounce_timeout: bounce flag not set!\n");
break;
}
case JUST_GONE_UP:
bounce=NO_BOUNCE;
if(debounced_down==raw_down)
{
- printk("pc110pad, bounce_timeout: raw already debounced!\n");
+ printk(KERN_WARNING "pc110pad, bounce_timeout: raw already debounced!\n");
}
debounced_down=raw_down;
}
-/*
+/**
+ * pad_irq:
+ * @irq: Interrupt number
+ * @ptr: Unused
+ * @regs: Unused
+ *
* Callback when pad's irq goes off; copies values in to raw_* globals;
- * initiates debounce processing.
+ * initiates debounce processing. This isn't SMP safe however there are
+ * no SMP machines with a PC110 touchpad on them.
*/
+
static void pad_irq(int irq, void *ptr, struct pt_regs *regs)
{
}
}
+/**
+ * read_raw_pad:
+ * @down: set if the pen is down
+ * @debounced: set if the debounced pen position is down
+ * @x: X position
+ * @y: Y position
+ *
+ * Retrieve the data saved by the interrupt handler and indicate we
+ * have no more pending XY to do.
+ *
+ * FIXME: We should switch to a spinlock for this.
+ */
static void read_raw_pad(int *down, int *debounced, int *x, int *y)
{
static int read_bytes[3];
static int read_byte_count=0;
+/**
+ * sample_raw:
+ * @d: sample buffer
+ *
+ * Retrieve a triple of sample data.
+ */
static void sample_raw(int d[3])
d[2]=raw_data[2];
}
+/**
+ * sample_rare:
+ * @d: sample buffer
+ *
+ * Retrieve a triple of sample data and sanitize it. We do the needed
+ * scaling and masking to get the current status.
+ */
+
static void sample_rare(int d[3])
{
d[2]=thisy%256;
}
+/**
+ * sample_debug:
+ * @d: sample buffer
+ *
+ * Retrieve a triple of sample data and mix it up with the state
+ * information in the gesture parser. Not useful for normal users but
+ * handy when debugging
+ */
static void sample_debug(int d[3])
{
int thisd, thisdd, thisx, thisy;
int b;
+ unsigned long flags;
+
+ save_flags(flags);
cli();
read_raw_pad(&thisd, &thisdd, &thisx, &thisy);
d[0]=(thisd?0x80:0) | (thisdd?0x40:0) | bounce;
d[1]=(recent_transition?0x80:0)+transition_count;
read_button(&b);
d[2]=(synthesize_tap<<4) | (b?0x01:0);
- sti();
+ restore_flags(flags);
}
+/**
+ * sample_ps2:
+ * @d: sample buffer
+ *
+ * Retrieve a triple of sample data and turn the debounced tap and
+ * stroke information into what appears to be a PS/2 mouse. This means
+ * the PC110 pad needs no funny application side support.
+ */
+
static void sample_ps2(int d[3])
{
}
-
+/**
+ * fasync_pad:
+ * @fd: file number for the file
+ * @filp: file handle
+ * @on: 1 to add, 0 to remove a notifier
+ *
+ * Update the queue of asynchronous event notifiers. We can use the
+ * same helper the mice do and that does almost everything we need.
+ */
+
static int fasync_pad(int fd, struct file *filp, int on)
{
int retval;
}
-/*
- * close access to the pad
+/**
+ * close_pad:
+ * @inode: inode of pad
+ * @file: file handle to pad
+ *
+ * Close access to the pad. We turn the pad power off if this is the
+ * last user of the pad. I've not actually measured the power draw but
+ * the DOS driver is careful to do this so we follow suit.
*/
+
static int close_pad(struct inode * inode, struct file * file)
{
fasync_pad(-1, file, 0);
}
-/*
- * open access to the pad
+/**
+ * open_pad:
+ * @inode: inode of pad
+ * @file: file handle to pad
+ *
+ * Open access to the pad. We turn the pad off first (we turned it off
+ * on close but if this is the first open after a crash the state is
+ * indeterminate). The device has a small fifo so we empty that before
+ * we kick it back into action.
*/
+
static int open_pad(struct inode * inode, struct file * file)
{
unsigned long flags;
}
-/*
- * writes are disallowed
+/**
+ * write_pad:
+ * @file: File handle to the pad
+ * @buffer: Unused
+ * @count: Unused
+ * @ppos: Unused
+ *
+ * Writes are disallowed. A true PS/2 mouse lets you write stuff. Everyone
+ * seems happy with this and not faking the write modes.
*/
+
static ssize_t write_pad(struct file * file, const char * buffer, size_t count, loff_t *ppos)
{
return -EINVAL;
}
+/*
+ * new_sample:
+ * @d: sample buffer
+ *
+ * Fetch a new sample according the current mouse mode the pad is
+ * using.
+ */
+
void new_sample(int d[3])
{
switch(current_params.mode)
}
-/*
- * Read pad data. Currently never blocks.
+/**
+ * read_pad:
+ * @file: File handle to pad
+ * @buffer: Target for the mouse data
+ * @count: Buffer length
+ * @ppos: Offset (unused)
+ *
+ * Read data from the pad. We use the reader_lock to avoid mess when there are
+ * two readers. This shouldnt be happening anyway but we play safe.
*/
+
static ssize_t read_pad(struct file * file, char * buffer, size_t count, loff_t *ppos)
{
int r;
}
-/*
- * select for pad input
+/**
+ * pad_poll:
+ * @file: File of the pad device
+ * @wait: Poll table
+ *
+ * The pad is ready to read if there is a button or any position change
+ * pending in the queue. The reading and interrupt routines maintain the
+ * required state for us and do needed wakeups.
*/
static unsigned int pad_poll(struct file *file, poll_table * wait)
}
+/**
+ * pad_ioctl;
+ * @inode: Inode of the pad
+ * @file: File handle to the pad
+ * @cmd: Ioctl command
+ * @arg: Argument pointer
+ *
+ * The PC110 pad supports two ioctls both of which use the pc110pad_params
+ * structure. GETP queries the current pad status. SETP changes the pad
+ * configuration. Changing configuration during normal mouse operations
+ * may give momentarily odd results as things like tap gesture state
+ * may be lost.
+ */
+
static int pad_ioctl(struct inode *inode, struct file * file,
unsigned int cmd, unsigned long arg)
{
};
+/**
+ * pc110pad_init:
+ *
+ * We configure the pad with the default parameters (that is PS/2
+ * emulation mode. We then claim the needed I/O and interrupt resources.
+ * Finally as a matter of paranoia we turn the pad off until we are
+ * asked to open it by an application.
+ */
+
int pc110pad_init(void)
{
current_params = default_params;
#ifdef MODULE
+/**
+ * pc110pad_unload:
+ *
+ * Free the resources we acquired when the module was loaded. We also
+ * turn the pad off to be sure we don't leave it using power.
+ */
+
static void pc110pad_unload(void)
{
outb(0x30, current_params.io+2); /* switch off digitiser */
#ifndef MODULE
-/*
- * Setup options
+/**
+ * wdt_setup:
+ * @str: command line string
+ *
+ * Setup options. The board isn't really probe-able so we have to
+ * get the user to tell us the configuration. Sane people build it
+ * modular but the others come here.
*/
static int __init wdt_setup(char *str)
* Kernel methods.
*/
+
+/**
+ * wdt_status:
+ *
+ * Extract the status information from a WDT watchdog device. There are
+ * several board variants so we have to know which bits are valid. Some
+ * bits default to one and some to zero in order to be maximally painful.
+ *
+ * we then map the bits onto the status ioctl flags.
+ */
+
static int wdt_status(void)
{
/*
return flag;
}
+/**
+ * wdt_interrupt:
+ * @irq: Interrupt number
+ * @dev_id: Unused as we don't allow multiple devices.
+ * @regs: Unused.
+ *
+ * Handle an interrupt from the board. These are raised when the status
+ * map changes in what the board considers an interesting way. That means
+ * a failure condition occuring.
+ *
+ * FIXME: We need to pass a dev_id as the PCI card can share irqs
+ * although its arguably a _very_ dumb idea to share watchdog
+ * irq lines
+ */
+
void wdt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
/*
* Read the status register see what is up and
- * then printk it.
+ * then printk it.
*/
unsigned char status=inb_p(WDT_SR);
return -ESPIPE;
}
+/**
+ * wdt_ping:
+ *
+ * Reload counter one with the watchdog timeout. We don't bother reloading
+ * the cascade counter.
+ */
+
static void wdt_ping(void)
{
/* Write a watchdog value */
outb_p(0, WDT_DC);
}
+/**
+ * wdt_write:
+ * @file: file handle to the watchdog
+ * @buf: buffer to write (unused as data does not matter here
+ * @count: count of bytes
+ * @ppos: pointer to the position to write. No seeks allowed
+ *
+ * A write to a watchdog device is defined as a keepalive signal. Any
+ * write of data will do, as we we don't define content meaning.
+ */
+
static ssize_t wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
/* Can't seek (pwrite) on this device */
return 0;
}
-/*
- * Read reports the temperature in degrees Fahrenheit.
+/**
+ * wdt_read:
+ * @file: file handle to the watchdog board
+ * @buf: buffer to write 1 byte into
+ * @count: length of buffer
+ * @ptr: offset (no seek allowed)
+ *
+ * Read reports the temperature in degrees Fahrenheit. The API is in
+ * farenheit. It was designed by an imperial measurement luddite.
*/
static ssize_t wdt_read(struct file *file, char *buf, size_t count, loff_t *ptr)
}
}
+/**
+ * wdt_ioctl:
+ * @inode: inode of the device
+ * @file: file handle to the device
+ * @cmd: watchdog command
+ * @arg: argument pointer
+ *
+ * The watchdog API defines a common set of functions for all watchdogs
+ * according to their available features. We only actually usefully support
+ * querying capabilities and current status.
+ */
+
static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
}
}
+/**
+ * wdt_open:
+ * @inode: inode of device
+ * @file: file handle to device
+ *
+ * One of our two misc devices has been opened. The watchdog device is
+ * single open and on opening we load the counters. Counter zero is a
+ * 100Hz cascade, into counter 1 which downcounts to reboot. When the
+ * counter triggers counter 2 downcounts the length of the reset pulse
+ * which set set to be as long as possible.
+ */
+
static int wdt_open(struct inode *inode, struct file *file)
{
switch(MINOR(inode->i_rdev))
}
}
+/**
+ * wdt_close:
+ * @inode: inode to board
+ * @file: file handle to board
+ *
+ * The watchdog has a configurable API. There is a religious dispute
+ * between people who want their watchdog to be able to shut down and
+ * those who want to be sure if the watchdog manager dies the machine
+ * reboots. In the former case we disable the counters, in the latter
+ * case you have to open it again very soon.
+ */
+
static int wdt_release(struct inode *inode, struct file *file)
{
if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
return 0;
}
-/*
- * Notifier for system down
+/**
+ * notify_sys:
+ * @this: our notifier block
+ * @code: the event being reported
+ * @unused: unused
+ *
+ * Our notifier is called on system shutdowns. We want to turn the card
+ * off at reboot otherwise the machine will reboot again during memory
+ * test or worse yet during the following fsck. This would suck, in fact
+ * trust me - if it happens it does suck.
*/
static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
#define wdt_init init_module
+/**
+ * cleanup_module:
+ *
+ * Unload the watchdog. You cannot do this with any file handles open.
+ * If your watchdog is set to continue ticking on close and you unload
+ * it, well it keeps ticking. We won't get the interrupt but the board
+ * will not touch PC memory so all is fine. You just have to load a new
+ * module in 60 seconds or reboot.
+ */
+
void cleanup_module(void)
{
misc_deregister(&wdt_miscdev);
#endif
+/**
+ * wdt_init:
+ *
+ * Set up the WDT watchdog board. All we have to do is grab the
+ * resources we require and bitch if anyone beat us to them.
+ * The open() function will actually kick the board off.
+ */
+
int __init wdt_init(void)
{
printk(KERN_INFO "WDT500/501-P driver 0.07 at %X (Interrupt %d)\n", io,irq);
* packet to arrive. When one arrives it is copied out of the buffer
* and delivered to the kernel. The card is reloaded and off we go.
*
- * When transmitting dev->tbusy is set and the card is reset (from
+ * When transmitting lp->txing is set and the card is reset (from
* receive mode) [possibly losing a packet just received] to command
* mode. A packet is loaded and transmit mode triggered. The interrupt
* handler runs different code for transmit interrupts and can handle
int el1_probe(struct net_device *dev);
static int el1_probe1(struct net_device *dev, int ioaddr);
static int el_open(struct net_device *dev);
+static void el_timeout(struct net_device *dev);
static int el_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void el_receive(struct net_device *dev);
int tx_pkt_start; /* The length of the current Tx packet. */
int collisions; /* Tx collisions this packet */
int loading; /* Spot buffer load collisions */
+ int txing; /* True if card is in TX mode */
spinlock_t lock; /* Serializing lock */
};
dev->open = &el_open;
dev->hard_start_xmit = &el_start_xmit;
+ dev->tx_timeout = &el_timeout;
+ dev->watchdog_timeo = HZ;
dev->stop = &el1_close;
dev->get_stats = &el1_get_stats;
dev->set_multicast_list = &set_multicast_list;
el_reset(dev);
spin_unlock_irqrestore(&lp->lock, flags);
- dev->start = 1;
-
+ lp->txing = 0; /* Board in RX mode */
outb(AX_RX, AX_CMD); /* Aux control, irq and receive enabled */
+ netif_start_queue(dev);
MOD_INC_USE_COUNT;
return 0;
}
/**
- * e1_start_xmit:
+ * el_timeout:
+ * @dev: The 3c501 card that has timed out
+ *
+ * Attempt to restart the board. This is basically a mixture of extreme
+ * violence and prayer
+ *
+ */
+
+static void el_timeout(struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+
+ if (el_debug)
+ printk (KERN_DEBUG "%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n",
+ dev->name, inb(TX_STATUS), inb(AX_STATUS), inb(RX_STATUS));
+ lp->stats.tx_errors++;
+ outb(TX_NORM, TX_CMD);
+ outb(RX_NORM, RX_CMD);
+ outb(AX_OFF, AX_CMD); /* Just trigger a false interrupt. */
+ outb(AX_RX, AX_CMD); /* Aux control, irq and receive enabled */
+ lp->txing = 0; /* Ripped back in to RX */
+ netif_wake_queue(dev);
+}
+
+
+/**
+ * el_start_xmit:
* @skb: The packet that is queued to be sent
* @dev: The 3c501 card we want to throw it down
*
int ioaddr = dev->base_addr;
unsigned long flags;
- if(dev->interrupt) /* May be unloading, don't stamp on */
- return 1; /* the packet buffer this time */
-
- if (dev->tbusy)
- {
- if (jiffies - dev->trans_start < HZ)
- {
- if (el_debug > 2)
- printk(" transmitter busy, deferred.\n");
- return 1;
- }
- if (el_debug)
- printk ("%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n",
- dev->name, inb(TX_STATUS), inb(AX_STATUS), inb(RX_STATUS));
- lp->stats.tx_errors++;
- outb(TX_NORM, TX_CMD);
- outb(RX_NORM, RX_CMD);
- outb(AX_OFF, AX_CMD); /* Just trigger a false interrupt. */
- outb(AX_RX, AX_CMD); /* Aux control, irq and receive enabled */
- dev->tbusy = 0;
- dev->trans_start = jiffies;
- }
-
/*
- * Avoid incoming interrupts between us flipping tbusy and flipping
- * mode as the driver assumes tbusy is a faithful indicator of card
+ * Avoid incoming interrupts between us flipping txing and flipping
+ * mode as the driver assumes txing is a faithful indicator of card
* state
*/
* Avoid timer-based retransmission conflicts.
*/
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- {
- spin_unlock_irqrestore(&lp->lock, flags);
- printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
- }
- else
+ netif_stop_queue(dev);
+
+ do
{
int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN);
unsigned char *buf = skb->data;
-load_it_again_sam:
lp->tx_pkt_start = gp_start;
lp->collisions = 0;
inb_p(RX_STATUS);
inb_p(TX_STATUS);
- lp->loading=1;
+ lp->loading = 1;
+ lp->txing = 1;
/*
* Turn interrupts back on while we spend a pleasant afternoon
outw(gp_start, GP_LOW); /* aim - packet will be loaded into buffer start */
outsb(DATAPORT,buf,skb->len); /* load buffer (usual thing each byte increments the pointer) */
outw(gp_start, GP_LOW); /* the board reuses the same register */
-
- if(lp->loading==2) /* A receive upset our load, despite our best efforts */
+
+ if(lp->loading != 2)
{
- if(el_debug>2)
- printk("%s: burped during tx load.\n", dev->name);
- spin_lock_irqsave(&lp->lock, flags);
- goto load_it_again_sam; /* Sigh... */
+ outb(AX_XMIT, AX_CMD); /* fire ... Trigger xmit. */
+ lp->loading=0;
+ dev->trans_start = jiffies;
+ if (el_debug > 2)
+ printk(" queued xmit.\n");
+ dev_kfree_skb (skb);
+ return 0;
}
- outb(AX_XMIT, AX_CMD); /* fire ... Trigger xmit. */
- lp->loading=0;
- dev->trans_start = jiffies;
+ /* A receive upset our load, despite our best efforts */
+ if(el_debug>2)
+ printk("%s: burped during tx load.\n", dev->name);
+ spin_lock_irqsave(&lp->lock, flags);
}
+ while(1);
- if (el_debug > 2)
- printk(" queued xmit.\n");
- dev_kfree_skb (skb);
- return 0;
}
\f
int ioaddr;
int axsr; /* Aux. status reg. */
- if (dev == NULL || dev->irq != irq)
- {
- printk (KERN_ERR "3c501 driver: irq %d for unknown device.\n", irq);
- return;
- }
-
ioaddr = dev->base_addr;
lp = (struct net_local *)dev->priv;
if (el_debug > 3)
printk(KERN_DEBUG "%s: el_interrupt() aux=%#02x", dev->name, axsr);
- if (dev->interrupt)
- printk(KERN_WARNING "%s: Reentering the interrupt driver!\n", dev->name);
- dev->interrupt = 1;
- if(lp->loading==1 && !dev->tbusy)
+
+ if(lp->loading==1 && !lp->txing)
printk(KERN_WARNING "%s: Inconsistent state loading while not in tx\n",
dev->name);
- if (dev->tbusy)
+ if (lp->txing)
{
/*
printk(" txsr=%02x gp=%04x rp=%04x]\n", txsr, inw(GP_LOW),inw(RX_LOW));
}
lp->loading=2; /* Force a reload */
- dev->interrupt = 0;
spin_unlock(&lp->lock);
return;
}
printk("%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x"
" gp=%03x rp=%03x.\n", dev->name, txsr, axsr,
inw(ioaddr + EL1_DATAPTR), inw(ioaddr + EL1_RXPTR));
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ lp->txing = 0;
+ netif_wake_queue(dev);
}
else if (txsr & TX_16COLLISIONS)
{
if (el_debug)
printk("%s: Transmit failed 16 times, Ethernet jammed?\n",dev->name);
outb(AX_SYS, AX_CMD);
+ lp->txing = 0;
lp->stats.tx_aborted_errors++;
+ netif_wake_queue(dev);
}
else if (txsr & TX_COLLISION)
{
outw(lp->tx_pkt_start, GP_LOW);
outb(AX_XMIT, AX_CMD);
lp->stats.collisions++;
- dev->interrupt = 0;
spin_unlock(&lp->lock);
return;
}
* This is safe the interrupt is atomic WRT itself.
*/
- dev->tbusy = 0;
- mark_bh(NET_BH); /* In case more to transmit */
+ lp->txing = 0;
+ netif_wake_queue(dev); /* In case more to transmit */
}
}
else
outw(0x00, RX_BUF_CLR);
inb(RX_STATUS); /* Be certain that interrupts are cleared. */
inb(TX_STATUS);
- dev->interrupt = 0;
spin_unlock(&lp->lock);
return;
}
static void el_reset(struct net_device *dev)
{
+ struct net_local *lp = (struct net_local *)dev->priv;
int ioaddr = dev->base_addr;
if (el_debug> 2)
outb(RX_NORM, RX_CMD); /* Set Rx commands. */
inb(RX_STATUS); /* Clear status. */
inb(TX_STATUS);
- dev->interrupt = 0;
- dev->tbusy = 0;
+ lp->txing = 0;
}
/**
if (el_debug > 2)
printk("%s: Shutting down Ethernet card at %#x.\n", dev->name, ioaddr);
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue(dev);
/*
* Free and disable the IRQ.
ei_status.saved_irq = dev->irq;
- dev->start = 0;
dev->open = &el2_open;
dev->stop = &el2_close;
info that the casual reader might think that it documents the i82586 :-<.
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
/* Initialize the 82586 memory and start it. */
init_82586_mem(dev);
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue(dev);
MOD_INC_USE_COUNT;
unsigned long shmem = dev->mem_start;
unsigned long flags;
- if (dev->tbusy)
+#if 0 /* LINK_STATE_XOFF is never set when we reach here */
+ if (test_bit(LINK_STATE_XOFF, &dev->flags))
{
/* If we get here, some higher level has decided we are broken.
There should really be a "kick me" function call instead. */
outb(0, ioaddr + SIGNAL_CA); /* Issue channel-attn. */
lp->last_restart = lp->stats.tx_packets;
}
- dev->tbusy=0;
+ netif_start_queue(dev);
dev->trans_start = jiffies;
}
+#endif
- /* Block a timer-based transmit from overlapping. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk("%s: Transmitter access conflict.\n", dev->name);
- else
{
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
unsigned char *buf = skb->data;
+ spin_lock_irqsave(&lp->lock, flags);
+
lp->stats.tx_bytes+=length;
/* Disable the 82586's input to the interrupt line. */
outb(0x80, ioaddr + MISC_CTRL);
-#ifdef CONFIG_SMP
- spin_lock_irqsave(&lp->lock, flags);
- hardware_send_packet(dev, buf, length);
- spin_unlock_irqrestore(&lp->lock, flags);
-#else
+
hardware_send_packet(dev, buf, length);
-#endif
+
dev->trans_start = jiffies;
/* Enable the 82586 interrupt input. */
outb(0x84, ioaddr + MISC_CTRL);
+
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ netif_stop_queue(dev);
}
dev_kfree_skb (skb);
printk ("net_interrupt(): irq %d for unknown device.\n", irq);
return;
}
- dev->interrupt = 1;
-
ioaddr = dev->base_addr;
lp = (struct net_local *)dev->priv;
if (tx_status & 0x2000) {
lp->stats.tx_packets++;
lp->stats.collisions += tx_status & 0xf;
- dev->tbusy = 0;
- mark_bh(NET_BH); /* Inform upper layers. */
+ netif_wake_queue(dev);
} else {
lp->stats.tx_errors++;
if (tx_status & 0x0600) lp->stats.tx_carrier_errors++;
/* Acknowledge the interrupt sources. */
ack_cmd = status & 0xf000;
- if ((status & 0x0700) != 0x0200 && dev->start) {
+ if ((status & 0x0700) != 0x0200 &&
+ (test_bit(LINK_STATE_START, &dev->state))) {
if (net_debug)
printk("%s: Command unit stopped, status %04x, restarting.\n",
dev->name, status);
ack_cmd |= CUC_RESUME;
}
- if ((status & 0x0070) != 0x0040 && dev->start)
+ if ((status & 0x0070) != 0x0040 &&
+ (test_bit(LINK_STATE_START, &dev->state)))
{
static void init_rx_bufs(struct net_device *);
/* The Rx unit is not ready, it must be hung. Restart the receiver by
/* Enable the 82586's interrupt input. */
outb(0x84, ioaddr + MISC_CTRL);
spin_unlock(&lp->lock);
-
- return;
}
static int el16_close(struct net_device *dev)
int ioaddr = dev->base_addr;
unsigned long shmem = dev->mem_start;
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue(dev);
/* Flush the Tx and disable Rx. */
isa_writew(RX_SUSPEND | CUC_SUSPEND,shmem+iSCB_CMD);
}
if (lp->tx_head != lp->tx_reap)
- dev->tbusy = 0;
+ netif_start_queue(dev);
}
static void el16_rx(struct net_device *dev)
#include <linux/module.h>
#include <linux/mca.h>
+#include <linux/isapnp.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/interrupt.h>
static int el3_rx(struct net_device *dev);
static int el3_close(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
+static void el3_tx_timeout (struct net_device *dev);
#ifdef CONFIG_MCA
struct el3_mca_adapters_struct {
};
#endif
+#ifdef CONFIG_ISAPNP
+struct el3_isapnp_adapters_struct {
+ unsigned short vendor, function;
+ char *name;
+};
+struct el3_isapnp_adapters_struct el3_isapnp_adapters[] = {
+ {ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090), "3Com Etherlink III (TP)"},
+ {ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5091), "3Com Etherlink III"},
+ {ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5094), "3Com Etherlink III (combo)"},
+ {ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5095), "3Com Etherlink III (TPO)"},
+ {ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5098), "3Com Etherlink III (TPC)"},
+ {ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_FUNCTION(0x80f8), "3Com Etherlink III compatible"},
+ {0, }
+};
+u16 el3_isapnp_phys_addr[8][3] = {
+ {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
+ {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}
+};
+#endif
+static int nopnp = 0;
+
int el3_probe(struct net_device *dev)
{
short lrs_state = 0xff, i;
int ioaddr, irq, if_port;
u16 phys_addr[3];
static int current_tag = 0;
+ static int pnp_cards = 0;
int mca_slot = -1;
/* First check all slots of the EISA bus. The next slot address to
return -ENODEV;
}
#endif
- /* Reset the ISA PnP mechanism on 3c509b. */
- outb(0x02, 0x279); /* Select PnP config control register. */
- outb(0x02, 0xA79); /* Return to WaitForKey state. */
+
+#ifdef CONFIG_ISAPNP
+ if (nopnp == 1)
+ goto no_pnp;
+
+ for (i=0; el3_isapnp_adapters[i].vendor != 0; i++) {
+ struct pci_dev *idev = NULL;
+ int j;
+ while ((idev = isapnp_find_dev(NULL,
+ el3_isapnp_adapters[i].vendor,
+ el3_isapnp_adapters[i].function,
+ idev))) {
+ idev->prepare(idev);
+ /* Deactivation is needed if the driver was called
+ with "nopnp=1" before, does not harm if not. */
+ idev->deactivate(idev);
+ idev->activate(idev);
+ if (!idev->resource[0].start || check_region(idev->resource[0].start,16))
+ continue;
+ ioaddr = idev->resource[0].start;
+ irq = idev->irq_resource[0].start;
+ if (el3_debug > 3)
+ printk ("ISAPnP reports %s at i/o 0x%x, irq %d\n",
+ el3_isapnp_adapters[i].name, ioaddr, irq);
+ EL3WINDOW(0);
+ for (j = 0; j < 3; j++)
+ el3_isapnp_phys_addr[pnp_cards][j] =
+ phys_addr[j] =
+ htons(read_eeprom(ioaddr, j));
+ if_port = read_eeprom(ioaddr, 8) >> 14;
+ pnp_cards++;
+ goto found;
+ }
+ }
+no_pnp:
+#endif
+
/* Select an open I/O location at 0x1*0 to do contention select. */
for ( ; id_port < 0x200; id_port += 0x10) {
if (check_region(id_port, 1))
phys_addr[i] = htons(id_read_eeprom(i));
}
+#ifdef CONFIG_ISAPNP
+ if (nopnp == 0) {
+ /* The ISA PnP 3c509 cards respond to the ID sequence.
+ This check is needed in order not to register them twice. */
+ for (i = 0; i < pnp_cards; i++) {
+ if (phys_addr[0] == el3_isapnp_phys_addr[i][0] &&
+ phys_addr[1] == el3_isapnp_phys_addr[i][1] &&
+ phys_addr[2] == el3_isapnp_phys_addr[i][2])
+ {
+ if (el3_debug > 3)
+ printk("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
+ phys_addr[0] & 0xff, phys_addr[0] >> 8,
+ phys_addr[1] & 0xff, phys_addr[1] >> 8,
+ phys_addr[2] & 0xff, phys_addr[2] >> 8);
+ /* Set the adaptor tag so that the next card can be found. */
+ outb(0xd0 + ++current_tag, id_port);
+ goto no_pnp;
+ }
+ }
+ }
+#endif
+
{
unsigned int iobase = id_read_eeprom(8);
if_port = iobase >> 14;
{
const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
- printk("%s: 3c509 at %#3.3lx tag %d, %s port, address ",
- dev->name, dev->base_addr, current_tag, if_names[dev->if_port]);
+ printk("%s: 3c509 at %#3.3lx, %s port, address ",
+ dev->name, dev->base_addr, if_names[dev->if_port]);
}
/* Read in the station address. */
dev->stop = &el3_close;
dev->get_stats = &el3_get_stats;
dev->set_multicast_list = &set_multicast_list;
+ dev->tx_timeout = el3_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
/* Fill in the generic fields of the device structure. */
ether_setup(dev);
outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
- dev->interrupt = 0;
- dev->tbusy = 0;
- dev->start = 1;
+ netif_start_queue(dev);
outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
return 0; /* Always succeed */
}
-static int
-el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static void
+el3_tx_timeout (struct net_device *dev)
{
struct el3_private *lp = (struct el3_private *)dev->priv;
int ioaddr = dev->base_addr;
/* Transmitter timeout, serious problems. */
- if (dev->tbusy) {
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < TX_TIMEOUT)
- return 1;
- printk("%s: transmit timed out, Tx_status %2.2x status %4.4x "
- "Tx FIFO room %d.\n",
- dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS),
- inw(ioaddr + TX_FREE));
- lp->stats.tx_errors++;
- dev->trans_start = jiffies;
- /* Issue TX_RESET and TX_START commands. */
- outw(TxReset, ioaddr + EL3_CMD);
- outw(TxEnable, ioaddr + EL3_CMD);
- dev->tbusy = 0;
- }
+ printk("%s: transmit timed out, Tx_status %2.2x status %4.4x "
+ "Tx FIFO room %d.\n",
+ dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS),
+ inw(ioaddr + TX_FREE));
+ lp->stats.tx_errors++;
+ dev->trans_start = jiffies;
+ /* Issue TX_RESET and TX_START commands. */
+ outw(TxReset, ioaddr + EL3_CMD);
+ outw(TxEnable, ioaddr + EL3_CMD);
+ netif_start_queue(dev);
+}
+
+
+static int
+el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct el3_private *lp = (struct el3_private *)dev->priv;
+ int ioaddr = dev->base_addr;
+ unsigned long flags;
lp->stats.tx_bytes += skb->len;
}
#endif
#endif
- /* Avoid timer-based retransmission conflicts. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk("%s: Transmitter access conflict.\n", dev->name);
- else {
- /*
- * We lock the driver against other processors. Note
- * we don't need to lock versus the IRQ as we suspended
- * that. This means that we lose the ability to take
- * an RX during a TX upload. That sucks a bit with SMP
- * on an original 3c509 (2K buffer)
- *
- * Using disable_irq stops us crapping on other
- * time sensitive devices.
- */
-
-#ifdef __SMP__
- disable_irq_nosync(dev->irq);
- spin_lock(&lp->lock);
-#endif
+ /*
+ * We lock the driver against other processors. Note
+ * we don't need to lock versus the IRQ as we suspended
+ * that. This means that we lose the ability to take
+ * an RX during a TX upload. That sucks a bit with SMP
+ * on an original 3c509 (2K buffer)
+ *
+ * Using disable_irq stops us crapping on other
+ * time sensitive devices.
+ */
+
+ spin_lock_irqsave(&lp->lock, flags);
- /* Put out the doubleword header... */
- outw(skb->len, ioaddr + TX_FIFO);
- outw(0x00, ioaddr + TX_FIFO);
- /* ... and the packet rounded to a doubleword. */
+ /* Put out the doubleword header... */
+ outw(skb->len, ioaddr + TX_FIFO);
+ outw(0x00, ioaddr + TX_FIFO);
+ /* ... and the packet rounded to a doubleword. */
#ifdef __powerpc__
- outsl_unswapped(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+ outsl_unswapped(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
#else
- outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+ outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
#endif
- dev->trans_start = jiffies;
- if (inw(ioaddr + TX_FREE) > 1536) {
- dev->tbusy = 0;
- } else
- /* Interrupt us when the FIFO has room for max-sized packet. */
- outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
-#ifdef __SMP__
- spin_unlock(&lp->lock);
- enable_irq(dev->irq);
-#endif
- }
+ dev->trans_start = jiffies;
+ if (inw(ioaddr + TX_FREE) > 1536)
+ netif_start_queue(dev);
+ else
+ /* Interrupt us when the FIFO has room for max-sized packet. */
+ outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
+
+ spin_unlock_irqrestore(&lp->lock, flags);
dev_kfree_skb (skb);
lp = (struct el3_private *)dev->priv;
spin_lock(&lp->lock);
- if (dev->interrupt)
- printk("%s: Re-entering the interrupt handler.\n", dev->name);
- dev->interrupt = 1;
-
ioaddr = dev->base_addr;
if (el3_debug > 4) {
printk(" TX room bit was handled.\n");
/* There's room in the FIFO for a full-sized packet. */
outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue (dev);
}
if (status & (AdapterFailure | RxEarly | StatsFull | TxComplete)) {
/* Handle all uncommon interrupts. */
inw(ioaddr + EL3_STATUS));
}
spin_unlock(&lp->lock);
- dev->interrupt = 0;
return;
}
if (el3_debug > 2)
printk("%s: Shutting down ethercard.\n", dev->name);
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue(dev);
/* Turn off statistics ASAP. We update lp->stats below. */
outw(StatsDisable, ioaddr + EL3_CMD);
MODULE_PARM(irq,"1-8i");
MODULE_PARM(xcvr,"1-8i");
MODULE_PARM(max_interrupt_work, "i");
+MODULE_PARM(nopnp, "i");
int
init_module(void)
if(!p->scb->cmd) break; \
DELAY_16(); \
if(i == 1023) { \
- printk("%s:%d: scb_cmd timed out .. resetting i82586\n",\
+ printk(KERN_WARNING "%s:%d: scb_cmd timed out .. resetting i82586\n",\
dev->name,__LINE__); \
elmc_id_reset586(); } } }
static int elmc_close(struct net_device *dev);
static int elmc_send_packet(struct sk_buff *, struct net_device *);
static struct net_device_stats *elmc_get_stats(struct net_device *dev);
+static void elmc_timeout(struct net_device *dev);
#ifdef ELMC_MULTICAST
static void set_multicast_list(struct net_device *dev);
#endif
static int elmc_close(struct net_device *dev)
{
+ netif_stop_queue(dev);
elmc_id_reset586(); /* the hard way to stop the receiver */
-
free_irq(dev->irq, dev);
-
- dev->start = 0;
- dev->tbusy = 0;
-
-#ifdef MODULE
MOD_DEC_USE_COUNT;
-#endif
-
return 0;
}
if (request_irq(dev->irq, &elmc_interrupt, SA_SHIRQ | SA_SAMPLE_RANDOM,
"3c523", dev)
) {
- printk("%s: couldn't get irq %d\n", dev->name, dev->irq);
+ printk(KERN_ERR "%s: couldn't get irq %d\n", dev->name, dev->irq);
elmc_id_reset586();
return -EAGAIN;
}
alloc586(dev);
init586(dev);
startrecv586(dev);
-
- dev->interrupt = 0;
- dev->tbusy = 0;
- dev->start = 1;
-
-#ifdef MODULE
+ netif_wake_queue(dev);
MOD_INC_USE_COUNT;
-#endif
-
return 0; /* most done by init */
}
DELAY(2);
if (p->iscp->busy) {
- printk("%s: Init-Problems (alloc).\n", dev->name);
+ printk(KERN_ERR "%s: Init-Problems (alloc).\n", dev->name);
}
memset((char *) p->scb, 0, sizeof(struct scb_struct));
}
mca_set_adapter_procfn(slot, (MCA_ProcFn) elmc_getinfo, dev);
/* if we get this far, adapter has been found - carry on */
- printk("%s: 3c523 adapter found in slot %d\n", dev->name, slot + 1);
+ printk(KERN_INFO "%s: 3c523 adapter found in slot %d\n", dev->name, slot + 1);
/* Now we extract configuration info from the card.
The 3c523 provides information in two of the POS registers, but
((struct priv *) (dev->priv))->slot = slot;
- printk("%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision,
+ printk(KERN_INFO "%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision,
dev->base_addr);
/* Determine if we're using the on-board transceiver (i.e. coax) or
size = 0x4000; /* check for 16K mem */
if (!check586(dev, dev->mem_start, size)) {
- printk("%s: memprobe, Can't find memory at 0x%lx!\n", dev->name,
+ printk(KERN_ERR "%s: memprobe, Can't find memory at 0x%lx!\n", dev->name,
dev->mem_start);
release_region(dev->base_addr, ELMC_IO_EXTENT);
return ENODEV;
((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16;
/* dump all the assorted information */
- printk("%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name,
+ printk(KERN_INFO "%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name,
dev->irq, dev->if_port ? "ex" : "in",
dev->mem_start, dev->mem_end - 1);
/* The hardware address for the 3c523 is stored in the first six
bytes of the IO address. */
- printk("%s: hardware address ", dev->name);
+ printk(KERN_INFO "%s: hardware address ", dev->name);
for (i = 0; i < 6; i++) {
dev->dev_addr[i] = inb(dev->base_addr + i);
printk(" %02x", dev->dev_addr[i]);
dev->stop = &elmc_close;
dev->get_stats = &elmc_get_stats;
dev->hard_start_xmit = &elmc_send_packet;
+ dev->tx_timeout = &elmc_timeout;
+ dev->watchdog_timeo = HZ;
#ifdef ELMC_MULTICAST
dev->set_multicast_list = &set_multicast_list;
#else
ether_setup(dev);
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 0;
-
/* note that we haven't actually requested the IRQ from the kernel.
That gets done in elmc_open(). I'm not sure that's such a good idea,
but it works, so I'll go with it. */
}
if ((cfg_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_COMPL | STAT_OK)) {
- printk("%s (elmc): configure command failed: %x\n", dev->name, cfg_cmd->cmd_status);
+ printk(KERN_WARNING "%s (elmc): configure command failed: %x\n", dev->name, cfg_cmd->cmd_status);
return 1;
}
/*
}
if ((ias_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_OK | STAT_COMPL)) {
- printk("%s (elmc): individual address setup command failed: %04x\n", dev->name, ias_cmd->cmd_status);
+ printk(KERN_WARNING "%s (elmc): individual address setup command failed: %04x\n", dev->name, ias_cmd->cmd_status);
return 1;
}
/*
s = jiffies;
while (!(tdr_cmd->cmd_status & STAT_COMPL)) {
if (jiffies - s > 30*HZ/100) {
- printk("%s: %d Problems while running the TDR.\n", dev->name, __LINE__);
+ printk(KERN_WARNING "%s: %d Problems while running the TDR.\n", dev->name, __LINE__);
result = 1;
break;
}
if (result & TDR_LNK_OK) {
/* empty */
} else if (result & TDR_XCVR_PRB) {
- printk("%s: TDR: Transceiver problem!\n", dev->name);
+ printk(KERN_WARNING "%s: TDR: Transceiver problem!\n", dev->name);
} else if (result & TDR_ET_OPN) {
- printk("%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK);
+ printk(KERN_WARNING "%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK);
} else if (result & TDR_ET_SRT) {
if (result & TDR_TIMEMASK) /* time == 0 -> strange :-) */
- printk("%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK);
+ printk(KERN_WARNING "%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK);
} else {
- printk("%s: TDR: Unknown status %04x\n", dev->name, result);
+ printk(KERN_WARNING "%s: TDR: Unknown status %04x\n", dev->name, result);
}
}
/*
/* I don't understand this: do we really need memory after the init? */
int len = ((char *) p->iscp - (char *) ptr - 8) / 6;
if (len <= 0) {
- printk("%s: Ooooops, no memory for MC-Setup!\n", dev->name);
+ printk(KERN_ERR "%s: Ooooops, no memory for MC-Setup!\n", dev->name);
} else {
if (len < num_addrs) {
num_addrs = len;
- printk("%s: Sorry, can only apply %d MC-Address(es).\n",
+ printk(KERN_WARNING "%s: Sorry, can only apply %d MC-Address(es).\n",
dev->name, num_addrs);
}
mc_cmd = (struct mcsetup_cmd_struct *) ptr;
break;
}
if (!(mc_cmd->cmd_status & STAT_COMPL)) {
- printk("%s: Can't apply multicast-address-list.\n", dev->name);
+ printk(KERN_WARNING "%s: Can't apply multicast-address-list.\n", dev->name);
}
}
}
p->xmit_buffs[i] = (struct tbd_struct *) ptr; /* TBD */
ptr = (char *) ptr + sizeof(struct tbd_struct);
if ((void *) ptr > (void *) p->iscp) {
- printk("%s: not enough shared-mem for your configuration!\n", dev->name);
+ printk(KERN_ERR "%s: not enough shared-mem for your configuration!\n", dev->name);
return 1;
}
memset((char *) (p->xmit_cmds[i]), 0, sizeof(struct transmit_cmd_struct));
struct priv *p;
if (dev == NULL) {
- printk("elmc-interrupt: irq %d for unknown device.\n", (int) -(((struct pt_regs *) reg_ptr)->orig_eax + 2));
+ printk(KERN_ERR "elmc-interrupt: irq %d for unknown device.\n", (int) -(((struct pt_regs *) reg_ptr)->orig_eax + 2));
return;
- } else if (!dev->start) {
+ } else if (!test_bit(LINK_STATE_START, &dev->state)) {
/* The 3c523 has this habit of generating interrupts during the
reset. I'm not sure if the ni52 has this same problem, but it's
really annoying if we haven't finished initializing it. I was
p = (struct priv *) dev->priv;
- dev->interrupt = 1;
-
while ((stat = p->scb->status & STAT_MASK))
{
p->scb->cmd = stat;
#ifndef NO_NOPCOMMANDS
if (stat & STAT_CNA) {
/* CU went 'not ready' */
- if (dev->start) {
- printk("%s: oops! CU has left active state. stat: %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status);
+ if (test_bit(LINK_STATE_START, &dev->state)) {
+ printk(KERN_WARNING "%s: oops! CU has left active state. stat: %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status);
}
}
#endif
p->scb->cmd = RUC_RESUME;
elmc_attn586();
} else {
- printk("%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status);
+ printk(KERN_WARNING "%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n", dev->name, (int) stat, (int) p->scb->status);
elmc_rnr_int(dev);
}
}
break;
}
}
-
- dev->interrupt = 0;
}
/*******************************************************
p->stats.rx_dropped++;
}
} else {
- printk("%s: received oversized frame.\n", dev->name);
+ printk(KERN_WARNING "%s: received oversized frame.\n", dev->name);
p->stats.rx_dropped++;
}
} else { /* frame !(ok), only with 'save-bad-frames' */
- printk("%s: oops! rfd-error-status: %04x\n", dev->name, status);
+ printk(KERN_WARNING "%s: oops! rfd-error-status: %04x\n", dev->name, status);
p->stats.rx_errors++;
}
p->rfd_top->status = 0;
alloc_rfa(dev, (char *) p->rfd_first);
startrecv586(dev); /* restart RU */
- printk("%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->status);
+ printk(KERN_WARNING "%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->status);
}
status = p->xmit_cmds[p->xmit_last]->cmd_status;
if (!(status & STAT_COMPL)) {
- printk("%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name);
+ printk(KERN_WARNING "%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name);
}
if (status & STAT_OK) {
p->stats.tx_packets++;
} else {
p->stats.tx_errors++;
if (status & TCMD_LATECOLL) {
- printk("%s: late collision detected.\n", dev->name);
+ printk(KERN_WARNING "%s: late collision detected.\n", dev->name);
p->stats.collisions++;
} else if (status & TCMD_NOCARRIER) {
p->stats.tx_carrier_errors++;
- printk("%s: no carrier detected.\n", dev->name);
+ printk(KERN_WARNING "%s: no carrier detected.\n", dev->name);
} else if (status & TCMD_LOSTCTS) {
- printk("%s: loss of CTS detected.\n", dev->name);
+ printk(KERN_WARNING "%s: loss of CTS detected.\n", dev->name);
} else if (status & TCMD_UNDERRUN) {
p->stats.tx_fifo_errors++;
- printk("%s: DMA underrun detected.\n", dev->name);
+ printk(KERN_WARNING "%s: DMA underrun detected.\n", dev->name);
} else if (status & TCMD_MAXCOLL) {
- printk("%s: Max. collisions exceeded.\n", dev->name);
+ printk(KERN_WARNING "%s: Max. collisions exceeded.\n", dev->name);
p->stats.collisions += 16;
}
}
}
#endif
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
}
/***********************************************************
WAIT_4_SCB_CMD(); /* wait for accept cmd. (no timeout!!) */
}
+/******************************************************
+ * timeout
+ */
+
+static void elmc_timeout(struct net_device *dev)
+{
+ struct priv *p = (struct priv *) dev->priv;
+ /* COMMAND-UNIT active? */
+ if (p->scb->status & CU_ACTIVE) {
+#ifdef DEBUG
+ printk("%s: strange ... timeout with CU active?!?\n", dev->name);
+ printk("%s: X0: %04x N0: %04x N1: %04x %d\n", dev->name, (int) p->xmit_cmds[0]->cmd_status, (int) p->nop_cmds[0]->cmd_status, (int) p->nop_cmds[1]->cmd_status, (int) p->nop_point);
+#endif
+ p->scb->cmd = CUC_ABORT;
+ elmc_attn586();
+ WAIT_4_SCB_CMD();
+ p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]);
+ p->scb->cmd = CUC_START;
+ elmc_attn586();
+ WAIT_4_SCB_CMD();
+ netif_wake_queue(dev);
+ } else {
+#ifdef DEBUG
+ printk("%s: xmitter timed out, try to restart! stat: %04x\n", dev->name, p->scb->status);
+ printk("%s: command-stats: %04x %04x\n", dev->name, p->xmit_cmds[0]->cmd_status, p->xmit_cmds[1]->cmd_status);
+#endif
+ elmc_close(dev);
+ elmc_open(dev);
+ }
+}
+
/******************************************************
* send frame
*/
#endif
struct priv *p = (struct priv *) dev->priv;
- if (dev->tbusy) {
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 5) {
- return 1;
- }
- /* COMMAND-UNIT active? */
- if (p->scb->status & CU_ACTIVE) {
- dev->tbusy = 0;
-#ifdef DEBUG
- printk("%s: strange ... timeout with CU active?!?\n", dev->name);
- printk("%s: X0: %04x N0: %04x N1: %04x %d\n", dev->name, (int) p->xmit_cmds[0]->cmd_status, (int) p->nop_cmds[0]->cmd_status, (int) p->nop_cmds[1]->cmd_status, (int) p->nop_point);
-#endif
- p->scb->cmd = CUC_ABORT;
- elmc_attn586();
- WAIT_4_SCB_CMD();
- p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]);
- p->scb->cmd = CUC_START;
- elmc_attn586();
- WAIT_4_SCB_CMD();
- dev->trans_start = jiffies;
- return 0;
- } else {
-#ifdef DEBUG
- printk("%s: xmitter timed out, try to restart! stat: %04x\n", dev->name, p->scb->status);
- printk("%s: command-stats: %04x %04x\n", dev->name, p->xmit_cmds[0]->cmd_status, p->xmit_cmds[1]->cmd_status);
-#endif
- elmc_close(dev);
- elmc_open(dev);
- }
- dev->trans_start = jiffies;
- return 0;
- }
- if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
- printk("%s: Transmitter access conflict.\n", dev->name);
- } else {
- memcpy((char *) p->xmit_cbuffs[p->xmit_count], (char *) (skb->data), skb->len);
- len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
+ netif_stop_queue(dev);
+
+ memcpy((char *) p->xmit_cbuffs[p->xmit_count], (char *) (skb->data), skb->len);
+ len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
#if (NUM_XMIT_BUFFS == 1)
#ifdef NO_NOPCOMMANDS
- p->xmit_buffs[0]->size = TBD_LAST | len;
- for (i = 0; i < 16; i++) {
- p->scb->cbl_offset = make16(p->xmit_cmds[0]);
- p->scb->cmd = CUC_START;
- p->xmit_cmds[0]->cmd_status = 0;
-
+ p->xmit_buffs[0]->size = TBD_LAST | len;
+ for (i = 0; i < 16; i++) {
+ p->scb->cbl_offset = make16(p->xmit_cmds[0]);
+ p->scb->cmd = CUC_START;
+ p->xmit_cmds[0]->cmd_status = 0;
elmc_attn586();
- dev->trans_start = jiffies;
- if (!i) {
- dev_kfree_skb(skb);
- }
- WAIT_4_SCB_CMD();
- if ((p->scb->status & CU_ACTIVE)) { /* test it, because CU sometimes doesn't start immediately */
- break;
- }
- if (p->xmit_cmds[0]->cmd_status) {
- break;
- }
- if (i == 15) {
- printk("%s: Can't start transmit-command.\n", dev->name);
- }
+ dev->trans_start = jiffies;
+ if (!i) {
+ dev_kfree_skb(skb);
}
+ WAIT_4_SCB_CMD();
+ if ((p->scb->status & CU_ACTIVE)) { /* test it, because CU sometimes doesn't start immediately */
+ break;
+ }
+ if (p->xmit_cmds[0]->cmd_status) {
+ break;
+ }
+ if (i == 15) {
+ printk(KERN_WARNING "%s: Can't start transmit-command.\n", dev->name);
+ }
+ }
#else
- next_nop = (p->nop_point + 1) & 0x1;
- p->xmit_buffs[0]->size = TBD_LAST | len;
-
- p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link
- = make16((p->nop_cmds[next_nop]));
- p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0;
-
- p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0]));
- dev->trans_start = jiffies;
- p->nop_point = next_nop;
- dev_kfree_skb(skb);
+ next_nop = (p->nop_point + 1) & 0x1;
+ p->xmit_buffs[0]->size = TBD_LAST | len;
+
+ p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link
+ = make16((p->nop_cmds[next_nop]));
+ p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0;
+
+ p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0]));
+ dev->trans_start = jiffies;
+ p->nop_point = next_nop;
+ dev_kfree_skb(skb);
#endif
#else
- p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len;
- if ((next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS) {
- next_nop = 0;
- }
- p->xmit_cmds[p->xmit_count]->cmd_status = 0;
- p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link
- = make16((p->nop_cmds[next_nop]));
- p->nop_cmds[next_nop]->cmd_status = 0;
-
+ p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len;
+ if ((next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS) {
+ next_nop = 0;
+ }
+ p->xmit_cmds[p->xmit_count]->cmd_status = 0;
+ p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link
+ = make16((p->nop_cmds[next_nop]));
+ p->nop_cmds[next_nop]->cmd_status = 0;
p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count]));
- dev->trans_start = jiffies;
- p->xmit_count = next_nop;
-
- cli();
- if (p->xmit_count != p->xmit_last) {
- dev->tbusy = 0;
- }
- sti();
- dev_kfree_skb(skb);
+ dev->trans_start = jiffies;
+ p->xmit_count = next_nop;
+ if (p->xmit_count != p->xmit_last)
+ netif_wake_queue(dev);
+ dev_kfree_skb(skb);
#endif
- }
return 0;
}
static int mc32_probe1(struct net_device *dev, int ioaddr);
static int mc32_open(struct net_device *dev);
+static void mc32_timeout(struct net_device *dev);
static int mc32_send_packet(struct sk_buff *skb, struct net_device *dev);
static void mc32_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int mc32_close(struct net_device *dev);
dev->hard_start_xmit = mc32_send_packet;
dev->get_stats = mc32_get_stats;
dev->set_multicast_list = mc32_set_multicast_list;
+ dev->tx_timeout = mc32_timeout;
+ dev->watchdog_timeo = HZ*5; /* Board does all the work */
lp->rx_halted = 1;
lp->tx_halted = 1;
u8 one=1;
u8 regs;
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
-
/*
* Interrupts enabled
*/
mc32_rx_begin(dev);
mc32_tx_begin(dev);
-
+
+ netif_wake_queue(dev);
MOD_INC_USE_COUNT;
return 0;
}
+/**
+ * mc32_timeout:
+ * @dev: 3c527 that timed out
+ *
+ * Handle a timeout on transmit from the 3c527. This normally means
+ * bad things as the hardware handles cable timeouts and mess for
+ * us.
+ *
+ */
+
+static void mc32_timeout(struct net_device *dev)
+{
+ printk(KERN_WARNING "%s: transmit timed out?\n", dev->name);
+ /* Try to restart the adaptor. */
+ netif_wake_queue(dev);
+}
+
/**
* mc32_send_packet:
* @skb: buffer to transmit
static int mc32_send_packet(struct sk_buff *skb, struct net_device *dev)
{
struct mc32_local *lp = (struct mc32_local *)dev->priv;
-
- if (dev->tbusy) {
- /*
- * If we get here, some higher level has decided we are broken.
- * There should really be a "kick me" function call instead.
- */
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < HZ/20)
- return 1;
- printk(KERN_WARNING "%s: transmit timed out?\n", dev->name);
- /* Try to restart the adaptor. */
- dev->tbusy=0;
- dev->trans_start = jiffies;
- }
-
- /*
- * 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, (void*)&dev->tbusy) != 0)
- {
- printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
- dev_kfree_skb(skb);
- }
- else
- {
- unsigned long flags;
+ unsigned long flags;
- u16 tx_head;
- volatile struct skb_header *p, *np;
+ u16 tx_head;
+ volatile struct skb_header *p, *np;
- save_flags(flags);
- cli();
+ netif_stop_queue(dev);
+
+ save_flags(flags);
+ cli();
- if(atomic_read(&lp->tx_count)==0)
- {
- dev->tbusy=1;
- restore_flags(flags);
- return 1;
- }
-
- tx_head = lp->tx_box->data[0];
- atomic_dec(&lp->tx_count);
+ if(atomic_read(&lp->tx_count)==0)
+ {
+ restore_flags(flags);
+ return 1;
+ }
- /* We will need this to flush the buffer out */
-
- lp->tx_skb[lp->tx_skb_end] = skb;
- lp->tx_skb_end++;
- lp->tx_skb_end&=(TX_RING_MAX-1);
-
- /* P is the last sending/sent buffer as a pointer */
- p=(struct skb_header *)bus_to_virt(lp->base+tx_head);
-
- /* NP is the buffer we will be loading */
- np=(struct skb_header *)bus_to_virt(lp->base+p->next);
+ tx_head = lp->tx_box->data[0];
+ atomic_dec(&lp->tx_count);
+ /* We will need this to flush the buffer out */
+
+ lp->tx_skb[lp->tx_skb_end] = skb;
+ lp->tx_skb_end++;
+ lp->tx_skb_end&=(TX_RING_MAX-1);
+
+ /* P is the last sending/sent buffer as a pointer */
+ p=(struct skb_header *)bus_to_virt(lp->base+tx_head);
+
+ /* NP is the buffer we will be loading */
+ np=(struct skb_header *)bus_to_virt(lp->base+p->next);
- np->control |= (1<<6); /* EOL */
- wmb();
+ np->control |= (1<<6); /* EOL */
+ wmb();
- np->length = skb->len;
+ np->length = skb->len;
- if(np->length < 60)
- np->length = 60;
+ if(np->length < 60)
+ np->length = 60;
- np->data = virt_to_bus(skb->data);
- np->status = 0;
- np->control = (1<<7)|(1<<6); /* EOP EOL */
- wmb();
+ np->data = virt_to_bus(skb->data);
+ np->status = 0;
+ np->control = (1<<7)|(1<<6); /* EOP EOL */
+ wmb();
- p->status = 0;
- p->control &= ~(1<<6);
-
- dev->tbusy = 0; /* Keep feeding me */
-
- lp->tx_box->mbox=0;
- restore_flags(flags);
- }
+ p->status = 0;
+ p->control &= ~(1<<6);
+
+ lp->tx_box->mbox=0;
+ restore_flags(flags);
+
+ netif_wake_queue(dev);
return 0;
}
printk(KERN_WARNING "%s: irq %d for unknown device.\n", cardname, irq);
return;
}
- dev->interrupt = 1;
-
ioaddr = dev->base_addr;
lp = (struct mc32_local *)dev->priv;
lp->tx_skb_top++;
lp->tx_skb_top&=(TX_RING_MAX-1);
atomic_inc(&lp->tx_count);
- dev->tbusy=0;
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
break;
case 3: /* Halt */
case 4: /* Abort */
if(rx_event)
mc32_rx_ring(dev);
- dev->interrupt = 0;
return;
}
u8 regs;
u16 one=1;
+ netif_stop_queue(dev);
+
/*
* Send the indications on command (handy debug check)
*/
mc32_flush_rx_ring(lp);
mc32_flush_tx_ring(lp);
- dev->tbusy = 1;
- dev->start = 0;
-
/* Update the statistics here. */
MOD_DEC_USE_COUNT;
-/* EtherLinkXL.c: A 3Com EtherLink PCI III/XL ethernet driver for linux. */
+/* 3c59x.c: A 3Com EtherLink PCI III/XL ethernet driver for linux. */
/*
Written 1996-1998 by Donald Becker.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
-*/
+
+ Version history:
+ 0.99H+lk1.0 - Jeff Garzik <jgarzik@mandrakesoft.com>
+ Remove compatibility defines for kernel versions < 2.2.x.
+ Update for new 2.3.x module interface
+
+ */
static char *version =
-"3c59x.c:v0.99H 11/17/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
+"3c59x.c:v0.99H+lk1.0 Feb 9, 2000 The Linux Kernel Team http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
/* "Knobs" that adjust features and parameters. */
/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
#include <linux/config.h>
#include <linux/version.h>
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
#include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/errno.h>
#include <linux/in.h>
+#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-#if LINUX_VERSION_CODE < 0x20155 || defined(CARDBUS)
-#include <linux/bios32.h>
-#endif
#include <asm/irq.h> /* For NR_IRQS only. */
#include <asm/bitops.h>
#include <asm/io.h>
#include <linux/delay.h>
-#if (LINUX_VERSION_CODE <= 0x20100)
-#ifndef __alpha__
-#define ioremap(a,b) \
- (((a)<0x100000) ? (void *)((u_long)(a)) : vremap(a,b))
-#define iounmap(v) \
- do { if ((u_long)(v) > 0x100000) vfree(v); } while (0)
-#endif
-#endif
-#if LINUX_VERSION_CODE <= 0x20139
-#define net_device_stats enet_statistics
-#define NETSTATS_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20138
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#define le32_to_cpu(val) (val)
-#define cpu_to_le32(val) (val)
-#endif
-#if LINUX_VERSION_CODE < 0x20155
-#define PCI_SUPPORT_VER1
-#else
#define PCI_SUPPORT_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20159
-#define DEV_FREE_SKB(skb) dev_kfree_skb (skb, FREE_WRITE);
-#else /* Grrr, unneeded incompatible change. */
#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
-#endif
-#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_DESCRIPTION("3Com 3c590/3c900 series Vortex/Boomerang driver");
MODULE_PARM(debug, "i");
MODULE_PARM(compaq_ioaddr, "i");
MODULE_PARM(compaq_irq, "i");
MODULE_PARM(compaq_device_id, "i");
-#endif
/* Operational parameter that usually are not changed. */
const char *name;
u16 vendor_id, device_id, device_id_mask, flags;
int drv_flags, io_size;
- struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
+ struct net_device *(*probe1)(struct pci_dev *pdev, long ioaddr, int irq, int chip_idx, int fnd_cnt);
};
enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4,
HAS_PWR_CTRL=0x10, HAS_MII=0x20, HAS_NWAY=0x40, HAS_CB_FNS=0x80, };
-static struct net_device *vortex_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq, int dev_id, int card_idx);
+static struct net_device *vortex_probe1(struct pci_dev *pdev, long ioaddr, int irq, int dev_id, int card_idx);
static struct pci_id_info pci_tbl[] = {
{"3c590 Vortex 10Mbps", 0x10B7, 0x5900, 0xffff,
/* A list of all installed Vortex devices, for removing the driver module. */
static struct net_device *root_vortex_dev = NULL;
-#ifdef MODULE
#ifndef CARDBUS
/* Variables to work-around the Compaq PCI BIOS32 problem. */
static int compaq_ioaddr = 0, compaq_irq = 0, compaq_device_id = 0x5900;
{
u16 dev_id, vendor_id;
u32 io;
- u8 bus, devfn, irq;
+ u8 irq;
struct net_device *dev;
+ struct pci_dev *pdev;
int chip_idx;
if (loc->bus != LOC_PCI) return NULL;
- bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
- pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
- pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
- pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor_id);
- pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
+ pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn);
+ if (!pdev) return NULL;
+ io = pdev->resource[0].start;
+ irq = pdev->irq;
+ vendor_id = pdev->vendor;
+ dev_id = pdev->device;
printk(KERN_INFO "vortex_attach(bus %d, function %d, device %4.4x)\n",
- bus, devfn, dev_id);
+ pdev->bus->number, pdev->devfn, dev_id);
io &= ~3;
if (io == 0 || irq == 0) {
printk(KERN_ERR "The 3Com CardBus Ethernet interface was not "
"vortex_attach().\n", vendor_id, dev_id);
return NULL;
}
- dev = vortex_probe1(bus, devfn, io, irq, chip_idx, MAX_UNITS+1);
+ dev = vortex_probe1(pdev, io, irq, chip_idx, MAX_UNITS+1);
if (dev) {
dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
strcpy(node->dev_name, dev->name);
#endif /* Cardbus support */
-int init_module(void)
+static int __init vortex_init_module (void)
{
if (vortex_debug)
printk(KERN_INFO "%s", version);
#endif
}
-#else
-int tc59x_probe(void)
-{
- static int scanned=0;
- if(scanned++)
- return -ENODEV;
- printk(KERN_INFO "%s", version);
- return vortex_scan(pci_tbl);
-}
-#endif /* not MODULE */
-
#ifndef CARDBUS
static int vortex_scan(struct pci_id_info pci_tbl[])
{
be best done a central PCI probe dispatch, which wouldn't work
well with the current structure. So instead we detect 3Com cards
in slot order. */
- if (pcibios_present()) {
+ if (pci_present()) {
static int pci_index = 0;
unsigned char pci_bus, pci_device_fn;
u16 vendor, device, pci_command, new_command, pwr_cmd;
int chip_idx, irq;
long ioaddr;
+ struct pci_dev *pdev;
if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index,
&pci_bus, &pci_device_fn)
!= PCIBIOS_SUCCESSFUL)
break;
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_VENDOR_ID, &vendor);
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_DEVICE_ID, &device);
+ pdev = pci_find_slot (pci_bus, pci_device_fn);
+ if (!pdev) continue;
+ vendor = pdev->vendor;
+ device = pdev->device;
for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
if (vendor == pci_tbl[chip_idx].vendor_id
&& (device & pci_tbl[chip_idx].device_id_mask) ==
}
/* Power-up the card. */
- pcibios_read_config_word(pci_bus, pci_device_fn,
- 0xe0, &pwr_cmd);
+ pci_read_config_word(pdev, 0xe0, &pwr_cmd);
+
if (pwr_cmd & 0x3) {
/* Save the ioaddr and IRQ info! */
printk(KERN_INFO " A 3Com network adapter is powered down!"
" Setting the power state %4.4x->%4.4x.\n",
pwr_cmd, pwr_cmd & ~3);
- pcibios_write_config_word(pci_bus, pci_device_fn,
- 0xe0, pwr_cmd & ~3);
+ pci_write_config_word(pdev, 0xe0, pwr_cmd & ~3);
printk(KERN_INFO " Setting the IRQ to %d, IOADDR to %#lx.\n",
irq, ioaddr);
- pcibios_write_config_byte(pci_bus, pci_device_fn,
- PCI_INTERRUPT_LINE, irq);
- pcibios_write_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_0, ioaddr);
+ pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
+ pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, ioaddr);
}
if (ioaddr == 0) {
continue;
/* Activate the card. */
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, &pci_command);
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+
new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
if (pci_command != new_command) {
printk(KERN_INFO " The PCI BIOS has not enabled the device "
"at %d/%d. Updating PCI command %4.4x->%4.4x.\n",
pci_bus, pci_device_fn, pci_command, new_command);
- pcibios_write_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, new_command);
+ pci_write_config_word(pdev, PCI_COMMAND, new_command);
}
- dev = vortex_probe1(pci_bus, pci_device_fn, ioaddr, irq,
- chip_idx, cards_found);
+ dev = vortex_probe1(pdev, ioaddr, irq,
+ chip_idx, cards_found);
if (dev) {
/* Get and check the latency values. On the 3c590 series
u8 pci_latency;
u8 new_latency = (device & 0xff00) == 0x5900 ? 248 : 32;
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, &pci_latency);
+ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
if (pci_latency < new_latency) {
printk(KERN_INFO "%s: Overriding PCI latency"
" timer (CFLT) setting of %d, new value is %d.\n",
dev->name, pci_latency, new_latency);
- pcibios_write_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, new_latency);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, new_latency);
}
dev = 0;
cards_found++;
device_id = (inb(ioaddr + 0xC82)<<8) + inb(ioaddr + 0xC83);
if ((device_id & 0xFF00) != 0x5900)
continue;
- vortex_probe1(0, 0, ioaddr, inw(ioaddr + 0xC88) >> 12,
- 4, cards_found);
+ vortex_probe1(NULL, ioaddr, inw(ioaddr + 0xC88) >> 12,
+ 4, cards_found);
cards_found++;
}
}
-#ifdef MODULE
/* Special code to work-around the Compaq PCI BIOS32 problem. */
if (compaq_ioaddr) {
- vortex_probe1(0, 0, compaq_ioaddr, compaq_irq,
+ vortex_probe1(NULL, compaq_ioaddr, compaq_irq,
compaq_device_id, cards_found++);
dev = 0;
}
-#endif
return cards_found ? 0 : -ENODEV;
}
#endif /* ! Cardbus */
-static struct net_device *vortex_probe1(int pci_bus, int pci_devfn,
- long ioaddr, int irq, int chip_idx, int card_idx)
+/*
+ * vortex_probe1 - initialize one vortex board, after probing
+ * has located one during bus scan.
+ *
+ * NOTE: pdev==NULL is a valid condition, indicating
+ * non-PCI (generally EISA) bus device
+ */
+static struct net_device *vortex_probe1(struct pci_dev *pdev,
+ long ioaddr, int irq,
+ int chip_idx, int card_idx)
{
struct vortex_private *vp;
int option;
root_vortex_dev = dev;
vp->chip_id = chip_idx;
- vp->pci_bus = pci_bus;
- vp->pci_devfn = pci_devfn;
- vp->pdev = pci_find_slot(pci_bus, pci_devfn);
+ vp->pci_bus = pdev == NULL ? 0 : pdev->bus->number;
+ vp->pci_devfn = pdev == NULL ? 0 : pdev->devfn;
+ vp->pdev = pdev;
- vp->priv_addr = pci_alloc_consistent(vp->pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE
- + sizeof(struct boom_tx_desc) * TX_RING_SIZE
- + 15, &vp->ring_dma);
+ vp->priv_addr = pci_alloc_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE
+ + sizeof(struct boom_tx_desc) * TX_RING_SIZE
+ + 15, &vp->ring_dma);
/* Make sure rings are 16 byte aligned. */
vp->rx_ring = (void *)(((long)vp->priv_addr + 15) & ~15);
vp->tx_ring = (struct boom_tx_desc *)(vp->rx_ring + RX_RING_SIZE);
if (pci_tbl[vp->chip_id].drv_flags & HAS_CB_FNS) {
u32 fn_st_addr; /* Cardbus function status space */
- pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_2,
- &fn_st_addr);
+ fn_st_addr = pdev == NULL ? 0 : pdev->resource[2].start;
if (fn_st_addr)
vp->cb_fn_base = ioremap(fn_st_addr & ~3, 128);
printk("%s: CardBus functions mapped %8.8x->%p (PCMCIA committee"
outl(0, ioaddr + UpListPtr);
for (i = 0; i < RX_RING_SIZE; i++)
if (vp->rx_skbuff[i]) {
-#if LINUX_VERSION_CODE < 0x20100
- vp->rx_skbuff[i]->free = 1;
-#endif
pci_unmap_single(vp->pdev, le32_to_cpu(vp->rx_ring[i].addr), PKT_BUF_SZ);
DEV_FREE_SKB(vp->rx_skbuff[i]);
vp->rx_skbuff[i] = 0;
return;
}
-\f
-#ifdef MODULE
-void cleanup_module(void)
+
+static void __exit vortex_cleanup_module (void)
{
struct net_device *next_dev;
}
}
-#endif /* MODULE */
-\f
+module_init(vortex_init_module);
+module_exit(vortex_cleanup_module);
+
+
/*
* Local variables:
* compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
tristate ' Apricot Xen-II on board Ethernet' CONFIG_APRICOT
tristate ' CS89x0 support' CONFIG_CS89x0
tristate ' Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
- tristate ' DECchip Tulip (dc21x4x) PCI support' CONFIG_DEC_ELCP
+ tristate ' DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP
tristate ' Digi Intl. RightSwitch SE-X support' CONFIG_DGRS
tristate ' EtherExpressPro/100 support' CONFIG_EEXPRESS_PRO100
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
endif
endif
-ifeq ($(CONFIG_SK98LIN),y)
-SUB_DIRS += sk98lin
-obj-y += sk98lin/sk98lin.o
-else
- ifeq ($(CONFIG_SK98LIN),m)
- MOD_IN_SUB_DIRS += sk98lin
- endif
-endif
-
ifeq ($(CONFIG_TR),y)
SUB_DIRS += tokenring
MOD_IN_SUB_DIRS += tokenring
endif
endif
+#
+# link order important here
+#
+obj-$(CONFIG_PLIP) += plip.o
+
+obj-$(CONFIG_ROADRUNNER) += rrunner.o
+
+obj-$(CONFIG_HAPPYMEAL) += sunhme.o
+obj-$(CONFIG_SUNLANCE) += sunlance.o
+obj-$(CONFIG_SUNQE) += sunqe.o
+obj-$(CONFIG_SUNBMAC) += sunbmac.o
+obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o
+
+obj-$(CONFIG_MACE) += mace.o
+obj-$(CONFIG_BMAC) += bmac.o
+obj-$(CONFIG_GMAC) += gmac.o
+obj-$(CONFIG_NCR885E) += ncr885e.o
+
+obj-$(CONFIG_OAKNET) += oaknet.o 8390.o
+
+obj-$(CONFIG_DGRS) += dgrs.o
+obj-$(CONFIG_RCPCI) += rcpci.o
+obj-$(CONFIG_VORTEX) += 3c59x.o
+obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
+obj-$(CONFIG_PCNET32) += pcnet32.o
+obj-$(CONFIG_EEXPRESS_PRO100) += eepro100.o
+obj-$(CONFIG_TLAN) += tlan.o
+obj-$(CONFIG_TULIP) += tulip.o
+obj-$(CONFIG_EPIC100) += epic100.o
+obj-$(CONFIG_SIS900) += sis900.o
+obj-$(CONFIG_DM9102) += dmfe.o
+obj-$(CONFIG_YELLOWFIN) += yellowfin.o
+obj-$(CONFIG_ACENIC) += acenic.o
+
+ifeq ($(CONFIG_SK98LIN),y)
+SUB_DIRS += sk98lin
+obj-y += sk98lin/sk98lin.o
+else
+ ifeq ($(CONFIG_SK98LIN),m)
+ MOD_IN_SUB_DIRS += sk98lin
+ endif
+endif
+
+obj-$(CONFIG_VIA_RHINE) += via-rhine.o
+obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
+#
+# end link order section
+#
obj-$(CONFIG_AIRONET4500) += aironet4500_core.o
obj-$(CONFIG_AIRONET4500_NONCS) += aironet4500_card.o
obj-$(CONFIG_ARM_ETHERH) += 8390.o
obj-$(CONFIG_WD80x3) += wd.o 8390.o
obj-$(CONFIG_EL2) += 3c503.o 8390.o
-obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
obj-$(CONFIG_NE2000) += ne.o 8390.o
obj-$(CONFIG_NE2_MCA) += ne2.o 8390.o
obj-$(CONFIG_HPLAN) += hp.o 8390.o
obj-$(CONFIG_ES3210) += es3210.o 8390.o
obj-$(CONFIG_LNE390) += lne390.o 8390.o
obj-$(CONFIG_NE3210) += ne3210.o 8390.o
-obj-$(CONFIG_PLIP) += plip.o
# bsd_comp.o is *always* a module, for some documented reason
# (licensing).
obj-$(CONFIG_AT1500) += lance.o
obj-$(CONFIG_LANCE) += lance.o
obj-$(CONFIG_SUN3LANCE) += sun3lance.o
-obj-$(CONFIG_PCNET32) += pcnet32.o
obj-$(CONFIG_DEFXX) += defxx.o
-obj-$(CONFIG_SUNLANCE) += sunlance.o
obj-$(CONFIG_SGISEEQ) += sgiseeq.o
-obj-$(CONFIG_HAPPYMEAL) += sunhme.o
-obj-$(CONFIG_SUNQE) += sunqe.o
-obj-$(CONFIG_SUNBMAC) += sunbmac.o
-obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o
obj-$(CONFIG_AT1700) += at1700.o
obj-$(CONFIG_FMV18X) += fmv18x.o
obj-$(CONFIG_EL1) += 3c501.o
obj-$(CONFIG_ELMC_II) += 3c527.o
obj-$(CONFIG_EL3) += 3c509.o
obj-$(CONFIG_3C515) += 3c515.o
-obj-$(CONFIG_VORTEX) += 3c59x.o
obj-$(CONFIG_EEXPRESS) += eexpress.o
obj-$(CONFIG_EEXPRESS_PRO) += eepro.o
-obj-$(CONFIG_EEXPRESS_PRO100) += eepro100.o
obj-$(CONFIG_RTL8139) += rtl8139.o
-obj-$(CONFIG_SIS900) += sis900.o
-obj-$(CONFIG_DM9102) += dmfe.o
-obj-$(CONFIG_YELLOWFIN) += yellowfin.o
-obj-$(CONFIG_ACENIC) += acenic.o
obj-$(CONFIG_WAVELAN) += wavelan.o
obj-$(CONFIG_ARLAN) += arlan.o arlan-proc.o
-obj-$(CONFIG_TLAN) += tlan.o
-obj-$(CONFIG_VIA_RHINE) += via-rhine.o
obj-$(CONFIG_ZNET) += znet.o
obj-$(CONFIG_DEPCA) += depca.o
obj-$(CONFIG_EWRK3) += ewrk3.o
obj-$(CONFIG_APRICOT) += 82596.o
obj-$(CONFIG_MVME16x_NET) += 82596.o
obj-$(CONFIG_BVME6000_NET) += 82596.o
-obj-$(CONFIG_DEC_ELCP) += tulip.o
obj-$(CONFIG_ETH16I) += eth16i.o
-obj-$(CONFIG_EPIC100) += epic100.o
obj-$(CONFIG_ARIADNE2) += ariadne2.o 8390.o
obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
obj-$(CONFIG_A2065) += a2065.o
obj-$(CONFIG_HYDRA) += hydra.o
obj-$(CONFIG_ARIADNE) += ariadne.o
-obj-$(CONFIG_DGRS) += dgrs.o
obj-$(CONFIG_CS89x0) += cs89x0.o
obj-$(CONFIG_LTPC) += ltpc.o
obj-$(CONFIG_COPS) += cops.o
obj-$(CONFIG_IPDDP) += ipddp.o
-obj-$(CONFIG_RCPCI) += rcpci.o
-obj-$(CONFIG_MACE) += mace.o
obj-$(CONFIG_MACSONIC) += macsonic.o
obj-$(CONFIG_MACMACE) += macmace.o
obj-$(CONFIG_MAC89x0) += mac89x0.o
-obj-$(CONFIG_BMAC) += bmac.o
-obj-$(CONFIG_GMAC) += gmac.o
-obj-$(CONFIG_NCR885E) += ncr885e.o
-obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
-obj-$(CONFIG_OAKNET) += oaknet.o 8390.o
#
# HIPPI adapters
#
-obj-$(CONFIG_ROADRUNNER) += rrunner.o
# Extract lists of the multi-part drivers.
# The 'int-*' lists are the intermediate files used to build the multi's.
static int ac_close_card(struct net_device *dev)
{
- dev->start = 0;
- dev->tbusy = 1;
-
if (ei_debug > 1)
printk("%s: Shutting down ethercard.\n", dev->name);
#include <linux/config.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#define wmb() mb()
#endif
-#if (LINUX_VERSION_CODE < 0x02030e)
-#define net_device device
-#endif
-
#include "acenic.h"
/*
return 1;
}
-int __init acenic_probe(void)
+static int __init acenic_probe(void)
{
int boards_found = 0;
int version_disp;
* dev->base_addr since it was means for I/O port
* addresses but who gives a damn.
*/
-#if (LINUX_VERSION_CODE < 0x02030d)
- dev->base_addr = pdev->base_address[0];
-#else
dev->base_addr = pdev->resource[0].start;
-#endif
ap->regs = (struct ace_regs *)ioremap(dev->base_addr, 0x4000);
if (!ap->regs){
}
-#ifdef MODULE
-#if LINUX_VERSION_CODE > 0x20118
MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@cern.ch>");
MODULE_DESCRIPTION("AceNIC/3C985 Gigabit Ethernet driver");
MODULE_PARM(link, "1-" __MODULE_STRING(8) "i");
MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i");
MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i");
MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i");
-#endif
-int init_module(void)
+static int __init acenic_init_module (void)
{
int cards;
}
-void cleanup_module(void)
+static void __exit acenic_cleanup_module (void)
{
struct ace_private *ap;
struct ace_regs *regs;
root_dev = next;
}
}
-#endif
+
+module_init(acenic_init_module);
+module_exit(acenic_cleanup_module);
/*
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/proc_fs.h>
+#include <linux/init.h>
#include <asm/prom.h>
#include <asm/dbdma.h>
#include <asm/io.h>
return 1;
}
-int bmac_probe(void)
+static int __init bmac_probe (void)
{
int j, rev;
struct bmac_data *bp;
static struct device_node *all_bmacs = NULL, *next_bmac;
struct net_device *dev = NULL;
+#ifdef MODULE
+ if(bmac_devs != NULL)
+ return -EBUSY;
+#endif
+
if (all_bmacs == NULL) {
all_bmacs = find_devices("bmac");
is_bmac_plus = 0;
return len;
}
-#ifdef MODULE
MODULE_AUTHOR("Randy Gobbel/Paul Mackerras");
MODULE_DESCRIPTION("PowerMac BMAC ethernet driver.");
-int init_module(void)
-{
- int res;
-
- if(bmac_devs != NULL)
- return -EBUSY;
- res = bmac_probe();
- return res;
-}
-void cleanup_module(void)
+static void __exit bmac_cleanup (void)
{
+#ifdef MODULE
struct bmac_data *bp;
if (bmac_devs == 0)
#endif
kfree(bmac_devs);
bmac_devs = NULL;
+#endif
}
-#endif
+module_init(bmac_probe);
+module_exit(bmac_cleanup);
struct bus_type *lp = &bus;
int i, status=0;
char *tmp;
- dma_addr_t dma_rx_bufs;
/* Ensure we're not sleeping */
if (lp->bus == EISA) {
}
#else
- dma_rx_bufs = lp->dma_rings + (NUM_RX_DESC + NUM_TX_DESC)
- * sizeof(struct de4x5_desc);
- dma_rx_bufs = (dma_rx_bufs + ALIGN) & ~ALIGN;
- lp->rx_bufs = (char *)(((long)(lp->rx_ring + NUM_RX_DESC
- + NUM_TX_DESC) + ALIGN) & ~ALIGN);
- for (i=0; i<NUM_RX_DESC; i++) {
- lp->rx_ring[i].status = 0;
- lp->rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ);
- lp->rx_ring[i].buf = cpu_to_le32(dma_rx_bufs+i*RX_BUFF_SZ);
- lp->rx_ring[i].next = 0;
- lp->rx_skb[i] = (struct sk_buff *) 1; /* Dummy entry */
+ {
+ dma_addr_t dma_rx_bufs;
+
+ dma_rx_bufs = lp->dma_rings + (NUM_RX_DESC + NUM_TX_DESC)
+ * sizeof(struct de4x5_desc);
+ dma_rx_bufs = (dma_rx_bufs + ALIGN) & ~ALIGN;
+ lp->rx_bufs = (char *)(((long)(lp->rx_ring + NUM_RX_DESC
+ + NUM_TX_DESC) + ALIGN) & ~ALIGN);
+ for (i=0; i<NUM_RX_DESC; i++) {
+ lp->rx_ring[i].status = 0;
+ lp->rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ);
+ lp->rx_ring[i].buf =
+ cpu_to_le32(dma_rx_bufs+i*RX_BUFF_SZ);
+ lp->rx_ring[i].next = 0;
+ lp->rx_skb[i] = (struct sk_buff *) 1; /* Dummy entry */
+ }
+
}
#endif
/*
* Chain of device structures
*/
-#ifdef MODULE
- static struct net_device *dgrs_root_dev = NULL;
-#endif
+static struct net_device *dgrs_root_dev = NULL;
/*
* Private per-board data structure (dev->priv)
)
{
int i;
- ulong csr;
+ ulong csr = 0;
DGRS_PRIV *priv = (DGRS_PRIV *) dev->priv;
if (pciaddr)
printk("%s: xmit len=%d\n", devN->name, (int) skb->len);
devN->trans_start = jiffies;
- devN->tbusy = 0;
+ netif_start_queue(devN);
if (priv0->rfdp->cmd & I596_RFD_EL)
{ /* Out of RFD's */
static int
dgrs_open( struct net_device *dev )
{
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue(dev);
-#ifdef MODULE
MOD_INC_USE_COUNT;
-#endif
return (0);
}
*/
static int dgrs_close( struct net_device *dev )
{
- dev->start = 0;
- dev->tbusy = 1;
+ netif_stop_queue(dev);
-#ifdef MODULE
MOD_DEC_USE_COUNT;
-#endif
return (0);
}
if (dgrs_nicmode)
{
for (i = 0; i < priv0->nports; ++i)
- priv0->devtbl[i]->tbusy = 0;
+ netif_wake_queue (priv0->devtbl[i]);
}
else
- dev0->tbusy = 0;
+ netif_wake_queue (dev0);
/* if (bd->flags & TX_QUEUED)
DL_sched(bd, bdd); */
}
return cards_found;
}
-/*
- * Module/driver initialization points. Two ways, depending on
- * whether we are a module or statically linked, ala Don Becker's
- * 3c59x driver.
- */
-
-#ifdef MODULE
/*
- * Variables that can be overriden from command line
+ * Variables that can be overriden from module command line
*/
static int debug = -1;
static int dma = -1;
MODULE_PARM(ipxnet, "i");
MODULE_PARM(nicmode, "i");
-int
-init_module(void)
+static int __init dgrs_init_module (void)
{
int cards_found;
int i;
return cards_found ? 0 : -ENODEV;
}
-void
-cleanup_module(void)
+static void __exit dgrs_cleanup_module (void)
{
while (dgrs_root_dev)
{
}
}
-#else
-
-int __init
-dgrs_probe(struct net_device *dev)
-{
- int cards_found;
-
- cards_found = dgrs_scan();
- if (dgrs_debug && cards_found)
- printk("dgrs: SW=%s FW=Build %d %s\n",
- version, dgrs_firmnum, dgrs_firmdate);
- return cards_found ? 0 : -ENODEV;
-}
-#endif
+module_init(dgrs_init_module);
+module_exit(dgrs_cleanup_module);
};
/* function declaration ------------------------------------- */
-int dmfe_reg_board(void);
+static int dmfe_reg_board(void);
static int dmfe_open(struct net_device *);
static int dmfe_start_xmit(struct sk_buff *, struct net_device *);
static int dmfe_stop(struct net_device *);
* Search DM910X board, allocate space and register it
*/
-int __init dmfe_reg_board(void)
+static int __init dmfe_reg_board(void)
{
u32 pci_iobase;
u16 dm9102_count = 0;
while ((net_dev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, net_dev)))
{
u32 pci_id;
- u8 pci_cmd;
index++;
if (pci_read_config_dword(net_dev, PCI_VENDOR_ID, &pci_id) != DMFE_SUCC)
pci_iobase = net_dev->resource[0].start;
pci_irqline = net_dev->irq;
+ if (check_region(pci_iobase, DM9102_IO_SIZE)) /* IO range check */
+ continue;
+
/* Enable Master/IO access, Disable memory access */
+ pci_enable_device (net_dev);
pci_set_master(net_dev);
- pci_read_config_byte(net_dev, PCI_COMMAND, &pci_cmd);
- pci_cmd |= PCI_COMMAND_IO;
- pci_cmd &= ~PCI_COMMAND_MEMORY;
- pci_write_config_byte(net_dev, PCI_COMMAND, pci_cmd);
-
/* Set Latency Timer 80h */
/* FIXME: setting values > 32 breaks some SiS 559x stuff.
/* IO range and interrupt check */
- if (check_region(pci_iobase, DM9102_IO_SIZE)) /* IO range check */
- continue;
-
/* Found DM9102 card and PCI resource allocated OK */
dm9102_count++; /* Found a DM9102 card */
/* Init network device */
- dev = init_etherdev(NULL, 0);
+ dev = init_etherdev(NULL, sizeof(*db));
+ if (dev == NULL)
+ continue;
+
+ db = dev->priv;
- /* Allocated board information structure */
- db = (void *) (kmalloc(sizeof(*db), GFP_KERNEL | GFP_DMA));
- if(db==NULL)
- continue; /* Out of memory */
-
memset(db, 0, sizeof(*db));
- dev->priv = db; /* link device and board info */
db->next_dev = dmfe_root_dev;
dmfe_root_dev = dev;
}
-#ifdef MODULE
if (!dm9102_count)
printk(KERN_WARNING "dmfe: Can't find DM910X board\n");
-#endif
+
return dm9102_count ? 0 : -ENODEV;
}
}
-#ifdef MODULE
MODULE_AUTHOR("Sten Wang, sten_wang@davicom.com.tw");
MODULE_DESCRIPTION("Davicom DM910X fast ethernet driver");
* to initilize and register.
*/
-int init_module(void)
+static int __init dmfe_init_module(void)
{
DMFE_DBUG(0, "init_module() ", debug);
* to un-register device.
*/
-void cleanup_module(void)
+static void __exit dmfe_cleanup_module(void)
{
struct net_device *next_dev;
DMFE_DBUG(0, "clean_module() exit", 0);
}
-#endif /* MODULE */
+module_init(dmfe_init_module);
+module_exit(dmfe_cleanup_module);
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-
-
-/* need to remove these asap */
-/* 2.1.xx compatibility macros... */
-/* */
-
-
-#include <linux/version.h>
-
-/* For linux 2.1.xx */
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/delay.h>
/* udelay(2) */
#define compat_init_data __initdata
-#else
-/* for 2.x */
-
-#define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb), (mode) )
-#define test_and_set_bit(a,b) set_bit((a),(b))
-#define SLOW_DOWN SLOW_DOWN_IO
-#define compat_init_data
-
-#endif
-
/* First, a few definitions that the brave might change. */
/* A zero-terminated list of I/O addresses to be probed. */
int version; /* a flag to indicate if this is a TX or FX
version of the 82595 chip. */
int stepping;
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+
spinlock_t lock; /* Serializing lock */
-#endif
};
/* The station (ethernet) address prefix, used for IDing the board. */
#define ee_id_eepro10p0 0x10 /* ID for eepro/10+ */
#define ee_id_eepro10p1 0x31
+#define TX_TIMEOUT 40
/* Index to functions, as function prototypes. */
static int eepro_close(struct net_device *dev);
static struct enet_statistics *eepro_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
+static void eepro_tx_timeout (struct net_device *dev);
static int read_eeprom(int ioaddr, int location);
static void hardware_send_packet(struct net_device *dev, void *buf, short length);
return -ENOMEM;
memset(dev->priv, 0, sizeof(struct eepro_local));
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
- spin_lock_init(&(((struct eepro_local *)dev->priv)->lock));
-#endif
+ ((struct eepro_local *)dev->priv)->lock = SPIN_LOCK_UNLOCKED;
+
dev->open = eepro_open;
dev->stop = eepro_close;
dev->hard_start_xmit = eepro_send_packet;
dev->get_stats = eepro_get_stats;
dev->set_multicast_list = &set_multicast_list;
+ dev->tx_timeout = eepro_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
/* Fill in the fields of the device structure with
ethernet generic values */
lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT << 8; /* or = RCV_RAM */
lp->tx_last = 0;
-
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+
+ netif_start_queue(dev);
if (net_debug > 3)
printk(KERN_DEBUG "%s: exiting eepro_open routine.\n", dev->name);
return 0;
}
-static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev)
+static void eepro_tx_timeout (struct net_device *dev)
{
- struct eepro_local *lp = (struct eepro_local *)dev->priv;
+ struct eepro_local *lp = (struct eepro_local *) dev->priv;
int ioaddr = dev->base_addr;
int rcv_ram = dev->mem_end;
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+ /* if (net_debug > 1) */
+ printk (KERN_ERR "%s: transmit timed out, %s?\n", dev->name,
+ "network cable problem");
+ /* This is not a duplicate. One message for the console,
+ one for the the log file */
+ printk (KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name,
+ "network cable problem");
+ lp->stats.tx_errors++;
+
+ /* Try to restart the adaptor. */
+ outb (SEL_RESET_CMD, ioaddr);
+ /* We are supposed to wait for 2 us after a SEL_RESET */
+ SLOW_DOWN;
+ SLOW_DOWN;
+
+ /* Do I also need to flush the transmit buffers here? YES? */
+ lp->tx_start = lp->tx_end = rcv_ram;
+ lp->tx_last = 0;
+
+ dev->trans_start = jiffies;
+ netif_start_queue (dev);
+
+ outb (RCV_ENABLE_CMD, ioaddr);
+}
+
+
+static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+ struct eepro_local *lp = (struct eepro_local *)dev->priv;
unsigned long flags;
-#endif
if (net_debug > 5)
printk(KERN_DEBUG "%s: entering eepro_send_packet routine.\n", dev->name);
- if (dev->tbusy) {
- /* If we get here, some higher level has decided we are broken.
- There should really be a "kick me" function call instead. */
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 40)
- return 1;
-
- /* if (net_debug > 1) */
- printk(KERN_ERR "%s: transmit timed out, %s?\n", dev->name,
- "network cable problem");
- /* This is not a duplicate. One message for the console,
- one for the the log file */
- printk(KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name,
- "network cable problem");
- lp->stats.tx_errors++;
-
- /* Try to restart the adaptor. */
- outb(SEL_RESET_CMD, ioaddr);
- /* We are supposed to wait for 2 us after a SEL_RESET */
- SLOW_DOWN;
- SLOW_DOWN;
-
- /* Do I also need to flush the transmit buffers here? YES? */
- lp->tx_start = lp->tx_end = rcv_ram;
- lp->tx_last = 0;
-
- dev->tbusy=0;
- dev->trans_start = jiffies;
-
- outb(RCV_ENABLE_CMD, ioaddr);
-
- }
-
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20155
- /* If some higher layer thinks we've missed an tx-done interrupt
- we are passed NULL. Caution: dev_tint() handles the cli()/sti()
- itself. */
- /* if (skb == NULL) {
- dev_tint(dev);
- return 0;
- }*/
- /* according to A. Cox, this is obsolete since 1.0 */
-#endif
-
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
spin_lock_irqsave(&lp->lock, flags);
-#endif
-
- /* Block a timer-based transmit from overlapping. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
- printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
- spin_unlock_irqrestore(&lp->lock, flags);
-#endif
- } else {
+ {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
unsigned char *buf = skb->data;
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
lp->stats.tx_bytes+=skb->len;
-#endif
hardware_send_packet(dev, buf, length);
dev->trans_start = jiffies;
if (net_debug > 5)
printk(KERN_DEBUG "%s: exiting eepro_send_packet routine.\n", dev->name);
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
spin_unlock_irqrestore(&lp->lock, flags);
-#endif
return 0;
}
return;
}
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
spin_lock(&lp->lock);
-#endif
-
- if (dev->interrupt) {
- printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
-
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
- spin_unlock(&lp->lock);
- /* FIXME : with the lock, could this ever happen ? */
-#endif
-
- return;
- }
- dev->interrupt = 1;
if (net_debug > 5)
printk(KERN_DEBUG "%s: entering eepro_interrupt routine.\n", dev->name);
} while ((boguscount-- > 0) && (status & 0x06));
- dev->interrupt = 0;
-
if (net_debug > 5)
printk(KERN_DEBUG "%s: exiting eepro_interrupt routine.\n", dev->name);
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
spin_unlock(&lp->lock);
-#endif
return;
}
int rcv_ram = dev->mem_end;
short temp_reg;
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue(dev);
outb(BANK1_SELECT, ioaddr); /* Switch back to Bank 1 */
service routines. */
outb(ALL_MASK, ioaddr + INT_MASK_REG);
- if (dev->interrupt == 1) {
- /* Enable RX and TX interrupts */
- outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
- continue;
- }
-
/* determine how much of the transmit buffer space is available */
if (lp->tx_end > lp->tx_start)
tx_available = XMT_RAM - (lp->tx_end - lp->tx_start);
lp->tx_last = last;
lp->tx_end = end;
- if (dev->tbusy) {
- dev->tbusy = 0;
- }
+ if (test_bit(LINK_STATE_XOFF, &dev->flags))
+ netif_start_queue(dev);
/* Enable RX and TX interrupts */
outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
return;
}
- dev->tbusy = 1;
+ netif_stop_queue(dev);
if (net_debug > 5)
printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name);
}
/* Malloc up new buffer. */
struct sk_buff *skb;
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
lp->stats.rx_bytes+=rcv_size;
-#endif
rcv_size &= 0x3fff;
skb = dev_alloc_skb(rcv_size+5);
if (skb == NULL) {
xmt_status = inw(ioaddr+IO_PORT);
lp->tx_start = inw(ioaddr+IO_PORT);
- dev->tbusy = 0;
- mark_bh(NET_BH);
+ netif_wake_queue (dev);
if (xmt_status & 0x2000)
lp->stats.tx_packets++;
}
}
-#ifdef MODULE
-
#define MAX_EEPRO 8
static char devicename[MAX_EEPRO][9];
static struct net_device dev_eepro[MAX_EEPRO];
static int n_eepro = 0;
/* For linux 2.1.xx */
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+
MODULE_AUTHOR("Pascal Dupuis <dupuis@lei.ucl.ac.be> for the 2.1 stuff (locking,...)");
MODULE_DESCRIPTION("Intel i82595 ISA EtherExpressPro10/10+ driver");
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_EEPRO) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_EEPRO) "i");
MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_EEPRO) "i");
-#endif
+
+#ifdef MODULE
int
init_module(void)
e.g. "options=16" for FD, "options=32" for 100mbps-only. */
static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-#ifdef MODULE
static int debug = -1; /* The debug level */
-#endif
/* A few values that may be tweaked. */
/* The ring sizes should be a power of two for efficiency. */
#endif
#endif
#include <linux/spinlock.h>
+#include <linux/init.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
-#if LINUX_VERSION_CODE > 0x20118 && defined(MODULE)
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_DESCRIPTION("Intel i82557/i82558 PCI EtherExpressPro driver");
MODULE_PARM(debug, "i");
MODULE_PARM(rx_copybreak, "i");
MODULE_PARM(max_interrupt_work, "i");
MODULE_PARM(multicast_filter_limit, "i");
-#endif
#define RUN_AT(x) (jiffies + (x))
int i, option;
u16 eeprom[0x100];
int acpi_idle_state = 0;
-#ifndef MODULE
+
static int did_version = 0; /* Already printed version info. */
if (speedo_debug > 0 && did_version++ == 0)
printk(version);
-#endif
pdev = pci_find_slot(pci_bus, pci_devfn);
sp->rx_mode = new_rx_mode;
}
-\f
-#ifdef MODULE
-int init_module(void)
+
+static int __init eepro100_init_module(void)
{
int cards_found;
return 0;
}
-void cleanup_module(void)
+static void __exit eepro100_cleanup_module(void)
{
struct net_device *next_dev;
}
}
-#else /* not MODULE */
+module_init(eepro100_init_module);
+module_exit(eepro100_cleanup_module);
-int eepro100_probe(void)
-{
- int cards_found = 0;
-
- cards_found = eepro100_init();
-
- /* Only emit the version if the driver is being used. */
- if (speedo_debug > 0 && cards_found)
- printk(version);
-
- return cards_found ? 0 : -ENODEV;
-}
-#endif /* MODULE */
-\f
/*
* Local variables:
* compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS` `[ -f ./pci-netif.h ] && echo -DHAS_PCI_NETIF`"
#define TX_FIFO_THRESH 256 /* Rounded down to 4 byte units. */
#define RX_FIFO_THRESH 1 /* 0-3, 0==32, 64,96, or 3==128 bytes */
-#include <linux/version.h> /* Evil, but neccessary */
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
#include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#if LINUX_VERSION_CODE >= 0x20155
+#include <linux/init.h>
#define PCI_SUPPORT_VER2
-#else
-#include <linux/bios32.h>
-#endif
#include <linux/delay.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
/* Kernel compatibility defines, common to David Hind's PCMCIA package.
This is only in the support-all-kernels source code. */
-#if ! defined (LINUX_VERSION_CODE) || LINUX_VERSION_CODE < 0x20000
-#warning This driver version is only for kernel versions 2.0.0 and later.
-#endif
-
#define RUN_AT(x) (jiffies + (x))
-#if defined(MODULE) && (LINUX_VERSION_CODE >= 0x20115)
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_DESCRIPTION("SMC 83c170 EPIC series Ethernet driver");
MODULE_PARM(debug, "i");
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
MODULE_PARM(rx_copybreak, "i");
MODULE_PARM(max_interrupt_work, "i");
-#endif
-#if LINUX_VERSION_CODE < 0x20123
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#endif
-#if LINUX_VERSION_CODE <= 0x20139
-#define net_device_stats enet_statistics
-#define NETSTATS_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20159
-#define DEV_FREE_SKB(skb) dev_kfree_skb(skb, FREE_WRITE);
-#else /* Grrr, unneeded incompatible change. */
#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
-#endif
/* The I/O extent. */
#define EPIC_TOTAL_SIZE 0x100
/* The rest of these values should never change. */
-static struct net_device *epic_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq,
+static struct net_device *epic_probe1(struct pci_dev *pdev, long ioaddr, int irq,
int chip_id, int card_idx);
enum pci_flags_bit {
const char *name;
u16 vendor_id, device_id, device_id_mask, pci_flags;
int io_size, min_latency;
- struct net_device *(*probe1)(int pci_bus, int pci_devfn,
- long ioaddr, int irq, int chip_idx, int fnd_cnt);
+ struct net_device *(*probe1)(struct pci_dev *pdev,
+ long ioaddr, int irq, int chip_idx,
+ int fnd_cnt);
} chip_tbl[] = {
{"SMSC EPIC/100 83c170", 0x10B8, 0x0005, 0x7fff,
PCI_USES_IO|PCI_USES_MASTER|PCI_ADDR0, EPIC_TOTAL_SIZE, 32, epic_probe1},
char devname[8]; /* Used only for kernel debugging. */
const char *product_name;
struct net_device *next_module;
+
+ spinlock_t lock;
/* Tx and Rx rings here so that they remain paragraph aligned. */
struct epic_rx_desc rx_ring[RX_RING_SIZE];
static struct net_device *root_epic_dev = NULL;
#ifndef CARDBUS
-int epic100_probe(void)
+static int __init epic100_probe(void)
{
int cards_found = 0;
int chip_idx, irq;
unsigned char pci_bus, pci_device_fn;
struct net_device *dev;
-#ifdef PCI_SUPPORT_VER2
struct pci_dev *pcidev = NULL;
while ((pcidev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pcidev))
!= NULL) {
pci_bus = pcidev->bus->number;
pci_device_fn = pcidev->devfn;
irq = pcidev->irq;
-#else
- int pci_index;
-
- if ( ! pcibios_present())
- return -ENODEV;
-
- for (pci_index = 0; pci_index < 0xff; pci_index++) {
- u8 pci_irq_line;
- u16 vendor, device;
- u32 pci_ioaddr;
-
- if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
- pci_index, &pci_bus, &pci_device_fn)
- != PCIBIOS_SUCCESSFUL)
- break;
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_VENDOR_ID, &vendor);
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_DEVICE_ID, &device);
-
- for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++)
- if (vendor == chip_tbl[chip_idx].vendor_id
- && (device & chip_tbl[chip_idx].device_id_mask) ==
- chip_tbl[chip_idx].device_id)
- break;
- if (chip_tbl[chip_idx].vendor_id == 0) /* Compiled out! */
- continue;
-
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_0, &pci_ioaddr);
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_INTERRUPT_LINE, &pci_irq_line);
- /* Remove I/O space marker in bit 0. */
- pci_ioaddr &= ~3;
- irq = pci_irq_line;
-
- if (check_region(pci_ioaddr, chip_tbl[chip_idx].io_size))
- continue;
-#endif
/* EPIC-specific code: Soft-reset the chip ere setting as master. */
outl(0x0001, pci_ioaddr + GENCTL);
/* Activate the card: fix for brain-damaged Win98 BIOSes. */
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, &pci_command);
+ pci_read_config_word(pcidev, PCI_COMMAND, &pci_command);
new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
if (pci_command != new_command) {
printk(KERN_INFO " The PCI BIOS has not enabled Ethernet"
" device %4.4x-%4.4x."
" Updating PCI command %4.4x->%4.4x.\n",
vendor, device, pci_command, new_command);
- pcibios_write_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, new_command);
+ pci_write_config_word(pcidev, PCI_COMMAND, new_command);
}
- dev = chip_tbl[chip_idx].probe1(pci_bus, pci_device_fn, pci_ioaddr,
- irq, chip_idx, cards_found);
+ dev = chip_tbl[chip_idx].probe1(pcidev, pci_ioaddr, irq,
+ chip_idx, cards_found);
/* Check the latency timer. */
if (dev) {
u8 pci_latency;
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, &pci_latency);
+ pci_read_config_byte(pcidev, PCI_LATENCY_TIMER, &pci_latency);
if (pci_latency < chip_tbl[chip_idx].min_latency) {
printk(KERN_INFO " PCI latency timer (CFLT) value of %d is "
"unreasonably low, setting to %d.\n", pci_latency,
chip_tbl[chip_idx].min_latency);
- pcibios_write_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER,
+ pci_write_config_byte(pcidev, PCI_LATENCY_TIMER,
chip_tbl[chip_idx].min_latency);
}
dev = 0;
}
#endif /* not CARDBUS */
-static struct net_device *epic_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq,
- int chip_idx, int card_idx)
+static struct net_device *epic_probe1(struct pci_dev *pdev, long ioaddr, int irq,
+ int chip_idx, int card_idx)
{
struct epic_private *ep;
int i, option = 0, duplex = 0;
ep->next_module = root_epic_dev;
root_epic_dev = dev;
- ep->pci_bus = pci_bus;
- ep->pci_dev_fn = pci_devfn;
-#if defined(PCI_SUPPORT_VER2)
- ep->chip_id = pci_find_slot(pci_bus, pci_devfn)->device;
-#else
- ep->chip_id = chip_tbl[chip_idx].device_id;
-#endif
+ ep->lock = SPIN_LOCK_UNLOCKED;
+ ep->pci_bus = pdev->bus->number;
+ ep->pci_dev_fn = pdev->devfn;
+ ep->chip_id = pdev->device;
/* Find the connected MII xcvrs.
Doing this in open() would allow detecting external xcvrs later, but
dev->get_stats = &epic_get_stats;
dev->set_multicast_list = &set_rx_mode;
dev->do_ioctl = &mii_ioctl;
+ dev->tx_timeout = epic_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
return dev;
}
set_rx_mode(dev);
outl(0x000A, ioaddr + COMMAND);
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue(dev);
/* Enable interrupts by setting the interrupt mask. */
outl((ep->chip_id == 6 ? PCIBusErr175 : PCIBusErr170)
int entry;
u32 flag;
- /* 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, (void*)&dev->tbusy) != 0) {
- if (jiffies - dev->trans_start < TX_TIMEOUT)
- return 1;
- epic_tx_timeout(dev);
- return 1;
- }
-
/* Caution: the write order is important here, set the base address
with the "ownership" bits last. */
if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
flag = 0x10; /* No interrupt */
- clear_bit(0, (void*)&dev->tbusy);
+ netif_start_queue(dev);
} else if (ep->cur_tx - ep->dirty_tx == TX_RING_SIZE/2) {
flag = 0x14; /* Tx-done intr. */
- clear_bit(0, (void*)&dev->tbusy);
+ netif_start_queue(dev);
} else if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE - 2) {
flag = 0x10; /* No Tx-done intr. */
- clear_bit(0, (void*)&dev->tbusy);
+ netif_start_queue(dev);
} else {
/* Leave room for two additional entries. */
flag = 0x14; /* Tx-done intr. */
long ioaddr = dev->base_addr;
int status, boguscnt = max_interrupt_work;
-#if defined(__i386__)
- /* A lock to prevent simultaneous entry bug on Intel SMP machines. */
- if (test_and_set_bit(0, (void*)&dev->interrupt)) {
- printk(KERN_ERR "%s: SMP simultaneous entry of an interrupt handler.\n",
- dev->name);
- dev->interrupt = 0; /* Avoid halting machine. */
- return;
- }
-#else
- if (dev->interrupt) {
- printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
- return;
- }
- dev->interrupt = 1;
-#endif
+ spin_lock (&ep->lock);
do {
status = inl(ioaddr + INTSTAT);
}
#endif
- if (ep->tx_full && dev->tbusy
- && dirty_tx > ep->cur_tx - TX_RING_SIZE + 2) {
+ if (ep->tx_full &&
+ test_bit(LINK_STATE_XOFF, &dev->flags) &&
+ dirty_tx > ep->cur_tx - TX_RING_SIZE + 2) {
/* The ring is no longer full, clear tbusy. */
ep->tx_full = 0;
- clear_bit(0, (void*)&dev->tbusy);
- mark_bh(NET_BH);
+ netif_wake_queue (dev);
}
ep->dirty_tx = dirty_tx;
printk(KERN_DEBUG "%s: exiting interrupt, intr_status=%#4.4x.\n",
dev->name, inl(ioaddr + INTSTAT));
-#if defined(__i386__)
- clear_bit(0, (void*)&dev->interrupt);
-#else
- dev->interrupt = 0;
-#endif
- return;
+ spin_unlock (&ep->lock);
}
static int epic_rx(struct net_device *dev)
struct epic_private *ep = (struct epic_private *)dev->priv;
int i;
- dev->start = 0;
- dev->tbusy = 1;
+ netif_stop_queue(dev);
if (epic_debug > 1)
printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
ep->rx_ring[i].buflength = 0;
ep->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */
if (skb) {
-#if LINUX_VERSION_CODE < 0x20100
- skb->free = 1;
-#endif
DEV_FREE_SKB(skb);
}
}
struct epic_private *ep = (struct epic_private *)dev->priv;
long ioaddr = dev->base_addr;
- if (dev->start) {
+ if (test_bit(LINK_STATE_START, &dev->state)) {
/* Update the error counts. */
ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
data[0] = ((struct epic_private *)dev->priv)->phys[0] & 0x1f;
/* Fall Through */
case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
- if (! dev->start) {
+ if (! test_bit(LINK_STATE_START, &dev->state)) {
outl(0x0200, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
}
data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
- if (! dev->start) {
+ if (! test_bit(LINK_STATE_START, &dev->state)) {
#ifdef notdef
outl(0x0008, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
if (!suser())
return -EPERM;
- if (! dev->start) {
+ if (! test_bit(LINK_STATE_START, &dev->state)) {
outl(0x0200, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
}
mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
- if (! dev->start) {
+ if (! test_bit(LINK_STATE_START, &dev->state)) {
#ifdef notdef
outl(0x0008, ioaddr + GENCTL);
outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
u16 dev_id;
u32 io;
u8 bus, devfn, irq;
+ struct pci_dev *pdev;
if (loc->bus != LOC_PCI) return NULL;
- bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
+ pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn);
+ if (!pdev) return NULL;
printk(KERN_DEBUG "epic_attach(bus %d, function %d)\n", bus, devfn);
- pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
- pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
- pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
+ io = pdev->resource[0].start;
+ irq = pdev->irq;
+ dev_id = pdev->device;
io &= ~3;
if (io == 0 || irq == 0) {
printk(KERN_ERR "The EPIC/C CardBus Ethernet interface was not "
#endif /* Cardbus support */
-\f
-#ifdef MODULE
-int init_module(void)
+static int __init epic100_init_module(void)
{
if (epic_debug)
printk(KERN_INFO "%s", version);
#endif
}
-void cleanup_module(void)
+static void __exit epic100_cleanup_module(void)
{
struct net_device *next_dev;
}
}
-#endif /* MODULE */
-\f
+module_init(epic100_init_module);
+module_exit(epic100_cleanup_module);
+
+
/*
* Local variables:
* compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/timer.h>
+#include <linux/init.h>
#include <asm/prom.h>
#include <asm/io.h>
#include <asm/pgtable.h>
static void gmac_receive(struct net_device *dev);
static void gmac_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static struct net_device_stats *gmac_stats(struct net_device *dev);
-int gmac_probe(struct net_device *dev);
+static int gmac_probe(void);
/* Stuff for talking to the physical-layer chip */
static int
return &gm->stats;
}
-int gmac_probe(struct net_device *dev)
+static int __init gmac_probe(void)
{
static int gmacs_found;
static struct device_node *next_gmac;
unsigned char *addr;
int i;
+ if (gmacs != NULL)
+ return -EBUSY;
+
/*
* We could (and maybe should) do this using PCI scanning
* for vendor/net_device ID 0x106b/0x21.
return 0;
}
-#ifdef MODULE
-
MODULE_AUTHOR("Paul Mackerras");
MODULE_DESCRIPTION("PowerMac GMAC driver.");
-int init_module(void)
-{
- if (gmacs != NULL)
- return -EBUSY;
- return gmac_probe(NULL);
-}
-void cleanup_module(void)
+static void __exit gmac_cleanup_module(void)
{
struct gmac *gm;
gmacs = NULL;
}
-#endif
+module_init(gmac_probe);
+module_exit(gmac_cleanup_module);
+
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
+#include <linux/spinlock.h>
#include <asm/bitops.h>
#include <asm/io.h>
struct hp100_private {
struct hp100_eisa_id *id;
+ spinlock_t lock;
u_short chip;
u_short soft_model;
u_int memory_size;
struct pci_dev *pci_dev;
#endif
short mem_mapped; /* memory mapped access */
- u32 *mem_ptr_virt; /* virtual memory mapped area, maybe NULL */
+ void *mem_ptr_virt; /* virtual memory mapped area, maybe NULL */
unsigned long mem_ptr_phys; /* physical memory mapped area */
short lan_type; /* 10Mb/s, 100Mb/s or -1 (error) */
int hub_status; /* was login to hub successful? */
static hp100_stats_t *hp100_get_stats( struct net_device *dev );
static void hp100_misc_interrupt( struct net_device *dev );
static void hp100_update_stats( struct net_device *dev );
-static void hp100_clear_stats( int ioaddr );
+static void hp100_clear_stats( struct hp100_private *lp, int ioaddr );
static void hp100_set_multicast_list( struct net_device *dev);
static void hp100_interrupt( int irq, void *dev_id, struct pt_regs *regs );
static void hp100_start_interface( struct net_device *dev );
u_short local_mode, lsw;
short mem_mapped;
unsigned long mem_ptr_phys;
- u32 **mem_ptr_virt;
+ void **mem_ptr_virt;
struct hp100_private *lp;
struct hp100_eisa_id *eid;
else
{
#ifdef HP100_DEBUG
- printk( "hp100: %s: remapped 0x%x bytes high PCI memory at 0x%lx to 0x%lx.\n", dev->name, virt_memory_size, mem_ptr_phys, (u_long)mem_ptr_virt);
+ printk( "hp100: %s: remapped 0x%x bytes high PCI memory at 0x%lx to %p.\n", dev->name, virt_memory_size, mem_ptr_phys, mem_ptr_virt);
#endif
break;
}
lp = (struct hp100_private *)dev->priv;
memset( lp, 0, sizeof( struct hp100_private ) );
+ lp->lock = SPIN_LOCK_UNLOCKED;
lp->id = eid;
lp->chip = chip;
lp->mode = local_mode;
dev->dev_addr[ i ] = hp100_inb( LAN_ADDR + i );
/* Reset statistics (counters) */
- hp100_clear_stats( ioaddr );
+ hp100_clear_stats( lp, ioaddr );
ether_setup( dev );
dev->name,mem_ptr_phys,
(mem_ptr_phys+(mem_ptr_phys>0x100000?(u_long)lp->memory_size:16*1024))-1 );
if ( mem_ptr_virt )
- printk( " (virtual base 0x%lx)", (u_long)mem_ptr_virt );
+ printk( " (virtual base %p)", mem_ptr_virt );
printk( ".\n" );
/* Set for info when doing ifconfig */
MOD_INC_USE_COUNT;
- dev->tbusy = 0;
dev->trans_start = jiffies;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue(dev);
lp->lan_type = hp100_sense_lan( dev );
lp->mac1_mode = HP100_MAC1MODE3;
if ( lp->lan_type == HP100_LAN_100 )
lp->hub_status=hp100_login_to_vg_hub( dev, FALSE );
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue(dev);
free_irq( dev->irq, dev );
* we have to turn int's off before modifying this, otherwise
* a tx_pdl_cleanup could occur at the same time
*/
- save_flags( flags );
- cli();
+ spin_lock_irqsave (&lp->lock, flags);
ringptr=lp->txrtail;
lp->txrtail=ringptr->next;
hp100_outl( ringptr->pdl_paddr, TX_PDA_L ); /* Low Prio. Queue */
lp->txrcommit++;
- restore_flags( flags );
+ spin_unlock_irqrestore (&lp->lock, flags);
/* Update statistics */
lp->stats.tx_packets++;
if ( lp->mem_ptr_virt ) /* high pci memory was remapped */
{
/* Note: The J2585B needs alignment to 32bits here! */
- memcpy( lp->mem_ptr_virt, skb->data, ( skb->len + 3 ) & ~3 );
+ memcpy_toio( lp->mem_ptr_virt, skb->data, ( skb->len + 3 ) & ~3 );
if ( !ok_flag )
- memset( lp->mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb->len );
+ memset_io( lp->mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb->len );
}
else
{
if ( lp->mode==2 )
{
if ( lp->mem_ptr_virt )
- memcpy( ptr, lp->mem_ptr_virt, pkt_len );
+ memcpy_fromio( ptr, lp->mem_ptr_virt, pkt_len );
/* Note alignment to 32bit transfers */
else
isa_memcpy_fromio( ptr, lp->mem_ptr_phys, pkt_len );
lp->stats.tx_errors++;
}
-static void hp100_clear_stats( int ioaddr )
+static void hp100_clear_stats( struct hp100_private *lp, int ioaddr )
{
unsigned long flags;
printk("hp100: %s: clear_stats\n", dev->name);
#endif
- save_flags( flags );
- cli();
+ spin_lock_irqsave (&lp->lock, flags);
hp100_page( MAC_CTRL ); /* get all statistics bytes */
hp100_inw( DROPPED );
hp100_inb( CRC );
hp100_inb( ABORT );
hp100_page( PERFORMANCE );
- restore_flags( flags );
+ spin_unlock_irqrestore (&lp->lock, flags);
}
\f
printk("hp100: %s: set_mc_list\n", dev->name);
#endif
- save_flags( flags );
- cli();
+ spin_lock_irqsave (&lp->lock, flags);
hp100_ints_off();
hp100_page( MAC_CTRL );
hp100_andb( ~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1 ); /* stop rx/tx */
hp100_page( PERFORMANCE );
hp100_ints_on();
- restore_flags( flags );
+ spin_unlock_irqrestore (&lp->lock, flags);
}
\f
if ( dev == NULL ) return;
ioaddr = dev->base_addr;
+
+ spin_lock (&lp->lock);
- if ( dev->interrupt )
- printk( "hp100: %s: re-entering the interrupt handler\n", dev->name );
hp100_ints_off();
- dev->interrupt = 1; /* mark that we are inside the handler */
#ifdef HP100_DEBUG_B
hp100_outw( 0x4219, TRACE );
if(val==0) /* might be a shared interrupt */
{
- dev->interrupt=0;
+ spin_unlock (&lp->lock);
hp100_ints_on();
return;
}
}
hp100_misc_interrupt( dev );
}
-
- dev->interrupt = 0;
+
+ spin_unlock (&lp->lock);
hp100_ints_on();
}
printk("hp100: %s: hp100_start_interface\n",dev->name);
#endif
- save_flags( flags );
- cli();
+ spin_lock_irqsave (&lp->lock, flags);
/* Ensure the adapter does not want to request an interrupt when */
/* enabling the IRQ line to be active on the bus (i.e. not tri-stated) */
/* Enable MAC Tx and RX, set MAC modes, ... */
hp100_set_multicast_list( dev );
- restore_flags( flags );
+ spin_unlock_irqrestore (&lp->lock, flags);
}
\f
}
/* handles "ltpc=io,irq,dma" kernel command lines */
-void __init ltpc_setup(char *str, int *ints)
+static int __init ltpc_setup(char *str)
{
+ int ints[5];
+
+ str = get_options(str, ARRAY_SIZE(ints), ints);
+
if (ints[0] == 0) {
if (str && !strncmp(str, "auto", 4)) {
/* do nothing :-) */
printk (KERN_ERR
"ltpc: usage: ltpc=auto|iobase[,irq[,dma]]\n");
}
- return;
+ return 1;
} else {
io = ints[1];
if (ints[0] > 1) {
irq = ints[2];
- return;
+ return 1;
}
if (ints[0] > 2) {
dma = ints[3];
- return;
+ return 1;
}
/* ignore any other paramters */
}
- return;
+ return 1;
}
+__setup("ltpc=", ltpc_setup);
+
#ifdef MODULE
static char dev_name[8];
* Copyright (C) 1996 Paul Mackerras.
*/
-#ifdef MODULE
#include <linux/module.h>
#include <linux/version.h>
-#endif
-
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/timer.h>
+#include <linux/init.h>
#include <asm/prom.h>
#include <asm/dbdma.h>
#include <asm/io.h>
return d;
}
-int mace_probe(void)
+static int __init mace_probe (void)
{
int j, rev;
struct net_device *dev;
static int maces_found = 0;
static struct device_node *next_mace;
+#ifdef MODULE
+ if(mace_devs != NULL)
+ return -EBUSY;
+#endif
+
if (!maces_found) {
next_mace = find_devices("mace");
maces_found = 1;
}
}
-#ifdef MODULE
-#if LINUX_VERSION_CODE > 0x20118
MODULE_AUTHOR("Paul Mackerras");
MODULE_DESCRIPTION("PowerMac MACE driver.");
-#endif
-int init_module(void)
-{
- int res;
-
- if(mace_devs != NULL)
- return -EBUSY;
- res = mace_probe();
- return res;
-}
-
-void cleanup_module(void)
+static void __exit mace_cleanup (void)
{
+#ifdef MODULE
struct mace_data *mp = (struct mace_data *) mace_devs->priv;
unregister_netdev(mace_devs);
kfree(mace_devs);
mace_devs = NULL;
+#endif
}
-#endif
+module_init(mace_probe);
+module_exit(mace_cleanup);
return 0;
}
-int __init myri_sbus_probe(void)
+static int __init myri_sbus_probe(void)
{
struct net_device *dev = NULL;
struct sbus_bus *bus;
static int called = 0;
int cards = 0, v;
+#ifdef MODULE
+ root_myri_dev = NULL;
+#endif
+
if (called)
return ENODEV;
called++;
return 0;
}
-#ifdef MODULE
-
-int
-init_module(void)
-{
- root_myri_dev = NULL;
- return myri_sbus_probe();
-}
-
-void
-cleanup_module(void)
+static void __exit myri_sbus_cleanup(void)
{
+#ifdef MODULE
/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
while (root_myri_dev) {
struct myri_eth *next = root_myri_dev->next_module;
kfree(root_myri_dev->dev);
root_myri_dev = next;
}
+#endif /* MODULE */
}
-#endif /* MODULE */
+module_init(myri_sbus_probe);
+module_exit(myri_sbus_cleanup);
"ncr885e.c:v0.8 11/30/98 dan@synergymicro.com\n";
#include <linux/config.h>
-
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
#include <linux/module.h>
#include <linux/version.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/timer.h>
int ncr885e_debug = NCR885E_DEBUG;
static int print_version = 0;
+static int debug = NCR885E_DEBUG; /* module parm */
+
struct ncr885e_private {
spinlock_t lock;
};
-#ifdef MODULE
static struct net_device *root_dev = NULL;
-#endif
-
static int ncr885e_open( struct net_device *dev );
static int ncr885e_close( struct net_device *dev );
unsigned char *p;
int i;
+ if (!request_region( ioaddr, NCR885E_TOTAL_SIZE, dev->name))
+ return -EBUSY;
+
dev = init_etherdev(NULL, 0 );
/* construct private data for the 885 ethernet */
dev->priv = kmalloc( sizeof( struct ncr885e_private ), GFP_KERNEL );
- if ( dev->priv == NULL )
+ if ( dev->priv == NULL ) {
+ release_region( ioaddr, NCR885E_TOTAL_SIZE );
return -ENOMEM;
+ }
sp = (struct ncr885e_private *) dev->priv;
memset( sp, 0, sizeof( struct ncr885e_private ));
printk(", IRQ %d.\n", irq );
- request_region( ioaddr, NCR885E_TOTAL_SIZE, dev->name );
-
/* set up a timer */
init_timer( &sp->tx_timeout );
sp->timeout_active = 0;
dev->hard_start_xmit = ncr885e_xmit_start;
dev->set_multicast_list = ncr885e_set_multicast;
dev->set_mac_address = ncr885e_set_address;
+
+ root_dev = dev;
return 0;
}
* worry about the rest.
*/
-int __init ncr885e_probe(void)
+static int __init ncr885e_probe(void)
{
struct pci_dev *pdev = NULL;
unsigned int ioaddr, chips = 0;
unsigned short cmd;
unsigned char irq, latency;
+ if ( debug >= 0)
+ ncr885e_debug = debug;
+
while(( pdev = pci_find_device( PCI_VENDOR_ID_NCR,
PCI_DEVICE_ID_NCR_53C885_ETHERNET,
pdev )) != NULL ) {
#endif /* NCR885E_DEBUG_MII */
-#ifdef MODULE
-#if defined(LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20118
MODULE_AUTHOR("dan@synergymicro.com");
MODULE_DESCRIPTION("Symbios 53C885 Ethernet driver");
MODULE_PARM(debug, "i");
-#endif
-static int debug = 1;
-int
-init_module(void)
-{
- if ( debug >= 0)
- ncr885e_debug = debug;
-
- return ncr885e_probe();
-}
-
-void
-cleanup_module(void)
+static void __exit ncr885e_cleanup (void)
{
struct ncr885e_private *np;
root_dev = NULL;
}
}
-#endif /* MODULE */
+
+module_init(ncr885e_probe);
+module_exit(ncr885e_cleanup);
+
/*
* Local variables:
if (ei_status.dmaing)
{
printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
- "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
- dev->name, ei_status.dmaing, ei_status.irqlock,
- dev->interrupt);
+ "[DMAstat:%d][irqlock:%d].\n",
+ dev->name, ei_status.dmaing, ei_status.irqlock);
return;
}
if (ei_status.dmaing)
{
printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
- "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
- dev->name, ei_status.dmaing, ei_status.irqlock,
- dev->interrupt);
+ "[DMAstat:%d][irqlock:%d].\n",
+ dev->name, ei_status.dmaing, ei_status.irqlock);
return;
}
ei_status.dmaing |= 0x01;
if (ei_status.dmaing)
{
printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
- "[DMAstat:%d][irqlock:%d][intr:%ld]\n",
- dev->name, ei_status.dmaing, ei_status.irqlock,
- dev->interrupt);
+ "[DMAstat:%d][irqlock:%d]\n",
+ dev->name, ei_status.dmaing, ei_status.irqlock);
return;
}
ei_status.dmaing |= 0x01;
#define NESM_START_PG 0x40 /* First page of TX buffer */
#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
-int ne2k_pci_probe(void);
+static int ne2k_pci_probe(void);
static struct net_device *ne2k_pci_probe1(long ioaddr, int irq, int chip_idx);
static int ne2k_pci_open(struct net_device *dev);
/* A list of all installed devices, for removing the driver module. */
static struct ne2k_pci_card *ne2k_card_list = NULL;
-#ifdef MODULE
-
-int
-init_module(void)
+static int __init ne2k_pci_init_module(void)
{
/* We must emit version information. */
if (debug)
return 0;
}
-void
-cleanup_module(void)
+static void __exit ne2k_pci_cleanup_module(void)
{
struct net_device *dev;
struct ne2k_pci_card *this_card;
unlock_8390_module();
}
-#endif /* MODULE */
+module_init(ne2k_pci_init_module);
+module_exit(ne2k_pci_cleanup_module);
/*
NEx000-clone boards have a Station Address (SA) PROM (SAPROM) in the packet
{"ne2k_pci", ne2k_pci_probe1, NE_IO_EXTENT, 0};
#endif
-int __init ne2k_pci_probe(void)
+static int __init ne2k_pci_probe(void)
{
struct pci_dev *pdev = NULL;
int cards_found = 0;
if (check_region(pci_ioaddr, NE_IO_EXTENT))
continue;
-#ifndef MODULE
{
static unsigned version_printed = 0;
if (version_printed++ == 0)
printk(KERN_INFO "%s", version);
}
-#endif
/* Activate the card: fix for brain-damaged Win98 BIOSes. */
new_command = pci_command | PCI_COMMAND_IO;
{
static unsigned version_printed = 0;
int i;
- unsigned int data;
+ unsigned int data = 0;
int boguscount = 40;
/*
*/
static void ni65_interrupt(int irq, void * dev_id, struct pt_regs * regs)
{
- int csr0;
+ int csr0 = 0;
struct net_device *dev = dev_id;
struct priv *p;
int bcnt = 32;
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
+#include <linux/init.h>
#include <asm/board.h>
#include <asm/io.h>
static const char *name = "National DP83902AV";
-#if defined(MODULE)
-static struct net_device *oaknet_devs;
-#endif
+static struct net_device *oaknet_devs = NULL;
/* Function Prototypes */
* 0 if OK, otherwise system error number on error.
*
*/
-int
-oaknet_init(void)
+static int __init oaknet_init(void)
{
register int i;
int reg0, regd;
tmp.base_addr = ioaddr;
dev = &tmp;
+ if (!request_region(OAKNET_IO_BASE, OAKNET_IO_SIZE, name))
+ return -EBUSY;
+
/* Quick register check to see if the device is really there. */
- if ((reg0 = ei_ibp(ioaddr)) == 0xFF)
+ if ((reg0 = ei_ibp(ioaddr)) == 0xFF) {
+ release_region(OAKNET_IO_BASE, OAKNET_IO_SIZE);
return (ENODEV);
+ }
/*
* That worked. Now a more thorough check, using the multicast
ei_obp(regd, ioaddr + 0x0D);
dev->base_addr = 0;
+ release_region(dev->base_addr, OAKNET_IO_SIZE);
return (ENODEV);
}
* sure its symbols are loaded.
*/
- if (load_8390_module("oaknet.c"))
+ if (load_8390_module("oaknet.c")) {
+ release_region(dev->base_addr, OAKNET_IO_SIZE);
return (-ENOSYS);
+ }
/*
* We're not using the old-style probing API, so we have to allocate
*/
dev = init_etherdev(0, 0);
-#if defined(MODULE)
oaknet_devs = dev;
-#endif
/*
* This controller is on an embedded board, so the base address
if (ethdev_init(dev)) {
printk(" unable to get memory for dev->priv.\n");
+ release_region(dev->base_addr, OAKNET_IO_SIZE);
return (-ENOMEM);
}
printk("%s: unable to request interrupt %d.\n",
dev->name, dev->irq);
kfree(dev->priv);
- dev->priv = NULL;
+ release_region(dev->base_addr, OAKNET_IO_SIZE);
return (EAGAIN);
}
- request_region(dev->base_addr, OAKNET_IO_SIZE, name);
-
/* Tell the world about what and where we've found. */
printk("%s: %s at", dev->name, name);
return;
}
-#if defined(MODULE)
/*
* Oak Ethernet module load interface.
*/
-int
-init_module(void)
+static int __init oaknet_init_module (void)
{
int status;
status = oaknet_init()
- lock_8390_module();
+ if (status == 0)
+ lock_8390_module();
return (status);
}
/*
* Oak Ethernet module unload interface.
*/
-void
-cleanup_module(void)
+static void __exit oaknet_cleanup_module (void)
{
if (oaknet_devs == NULL)
return;
oaknet_devs = NULL;
unlock_8390_module();
-
- return;
}
-#endif /* MODULE */
+
+module_init(oaknet_init_module);
+module_exit(oaknet_cleanup_module);
static int pcnet32_debug = 1;
static int tx_start = 1; /* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */
-#ifdef MODULE
static struct net_device *pcnet32_dev = NULL;
-#endif
static const int max_interrupt_work = 80;
static const int rx_copybreak = 200;
#endif
full_duplex:1, /* full duplex possible */
mii:1; /* mii port available */
-#ifdef MODULE
struct net_device *next;
-#endif
};
-int pcnet32_probe(void);
+static int pcnet32_probe(void);
static int pcnet32_probe1(unsigned long, unsigned char, int, int);
static int pcnet32_open(struct net_device *);
static int pcnet32_init_ring(struct net_device *);
static int pcnet32_start_xmit(struct sk_buff *, struct net_device *);
static int pcnet32_rx(struct net_device *);
+static void pcnet32_tx_timeout (struct net_device *dev);
static void pcnet32_interrupt(int, void *, struct pt_regs *);
static int pcnet32_close(struct net_device *);
static struct net_device_stats *pcnet32_get_stats(struct net_device *);
\f
-int __init pcnet32_probe(void)
+static int __init pcnet32_probe(void)
{
unsigned long ioaddr = 0; // FIXME dev ? dev->base_addr: 0;
unsigned int irq_line = 0; // FIXME dev ? dev->irq : 0;
#ifdef HAVE_PRIVATE_IOCTL
dev->do_ioctl = &pcnet32_mii_ioctl;
#endif
+ dev->tx_timeout = pcnet32_tx_timeout;
+ dev->watchdog_timeo = (HZ >> 1);
-
-#ifdef MODULE
lp->next = pcnet32_dev;
pcnet32_dev = dev;
-#endif
/* Fill in the generic fields of the device structure. */
ether_setup(dev);
lp->a.write_csr (ioaddr, 4, 0x0915);
lp->a.write_csr (ioaddr, 0, 0x0001);
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue(dev);
+
i = 0;
while (i++ < 100)
if (lp->a.read_csr (ioaddr, 0) & 0x0100)
lp->a.write_csr (ioaddr, 0, csr0_bits);
}
-static int
-pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
+
+static void
+pcnet32_tx_timeout (struct net_device *dev)
{
struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
unsigned int ioaddr = dev->base_addr;
- u16 status;
- int entry;
- unsigned long flags;
/* Transmitter timeout, serious problems. */
- if (dev->tbusy) {
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < HZ/2)
- return 1;
printk("%s: transmit timed out, status %4.4x, resetting.\n",
dev->name, lp->a.read_csr (ioaddr, 0));
lp->a.write_csr (ioaddr, 0, 0x0004);
}
pcnet32_restart(dev, 0x0042);
- dev->tbusy = 0;
dev->trans_start = jiffies;
- dev_kfree_skb(skb);
- return 0;
- }
+ netif_start_queue(dev);
+}
+
+
+static int
+pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
+ unsigned int ioaddr = dev->base_addr;
+ u16 status;
+ int entry;
+ unsigned long flags;
if (pcnet32_debug > 3) {
printk("%s: pcnet32_start_xmit() called, csr0 %4.4x.\n",
dev->name, lp->a.read_csr (ioaddr, 0));
}
- /* 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, (void*)&dev->tbusy) != 0) {
- printk("%s: Transmitter access conflict.\n", dev->name);
- return 1;
- }
-
spin_lock_irqsave(&lp->lock, flags);
/* Default status -- will not enable Successful-TxDone
dev->trans_start = jiffies;
if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0)
- clear_bit (0, (void *)&dev->tbusy);
+ netif_start_queue(dev);
else
lp->tx_full = 1;
spin_unlock_irqrestore(&lp->lock, flags);
spin_lock(&lp->lock);
- if (dev->interrupt)
- printk("%s: Re-entering the interrupt handler.\n", dev->name);
-
- dev->interrupt = 1;
-
rap = lp->a.read_rap(ioaddr);
while ((csr0 = lp->a.read_csr (ioaddr, 0)) & 0x8600 && --boguscnt >= 0) {
/* Acknowledge all of the current interrupt sources ASAP. */
dirty_tx += TX_RING_SIZE;
}
#endif
- if (lp->tx_full && dev->tbusy
- && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
+ if (lp->tx_full &&
+ test_bit(LINK_STATE_XOFF, &dev->flags) &&
+ dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
/* The ring is no longer full, clear tbusy. */
lp->tx_full = 0;
- clear_bit(0, (void *)&dev->tbusy);
- mark_bh(NET_BH);
+ netif_wake_queue (dev);
}
lp->dirty_tx = dirty_tx;
}
printk("%s: exiting interrupt, csr0=%#4.4x.\n",
dev->name, lp->a.read_csr (ioaddr, 0));
- dev->interrupt = 0;
-
spin_unlock(&lp->lock);
- return;
}
static int
struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
int i;
- dev->start = 0;
- set_bit (0, (void *)&dev->tbusy);
+ netif_stop_queue(dev);
lp->stats.rx_missed_errors = lp->a.read_csr (ioaddr, 112);
}
#endif /* HAVE_PRIVATE_IOCTL */
-#ifdef MODULE
MODULE_PARM(debug, "i");
MODULE_PARM(max_interrupt_work, "i");
MODULE_PARM(rx_copybreak, "i");
MODULE_PARM(tx_start_pt, "i");
MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-
+MODULE_AUTHOR("Thomas Bogendoerfer");
+MODULE_DESCRIPTION("Driver for PCnet32 and PCnetPCI based ethercards");
/* An additional parameter that may be passed in... */
static int debug = -1;
static int tx_start_pt = -1;
-int
-init_module(void)
+static int __init pcnet32_init_module(void)
{
if (debug > 0)
pcnet32_debug = debug;
return pcnet32_probe();
}
-void
-cleanup_module(void)
+static void __exit pcnet32_cleanup_module(void)
{
struct net_device *next_dev;
pcnet32_dev = next_dev;
}
}
-#endif /* MODULE */
+module_init(pcnet32_init_module);
+module_exit(pcnet32_cleanup_module);
-\f
/*
* Local variables:
* compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c pcnet32.c"
static int plip_open(struct net_device *dev);
static int plip_close(struct net_device *dev);
static struct net_device_stats *plip_get_stats(struct net_device *dev);
-static int plip_config(struct net_device *dev, struct ifmap *map);
static int plip_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
static int plip_preempt(void *handle);
static void plip_wakeup(void *handle);
static struct net_device *dev_plip[PLIP_MAX] = { NULL, };
-#ifdef MODULE
-void
-cleanup_module(void)
+static void __exit plip_cleanup_module (void)
{
int i;
}
}
-#define plip_init init_module
-
-#else /* !MODULE */
+#ifndef MODULE
static int parport_ptr = 0;
-void plip_setup(char *str, int *ints)
+static void __init plip_setup(char *str)
{
+ int ints[4];
+
+ str = get_options(str, ARRAY_SIZE(ints), ints);
+
/* Ugh. */
if (!strncmp(str, "parport", 7)) {
int n = simple_strtoul(str+7, NULL, 10);
}
}
-#endif /* MODULE */
+__setup("plip=", plip_setup);
+
+#endif /* !MODULE */
static int inline
plip_searchfor(int list[], int a)
return 0;
}
-int __init
-plip_init(void)
+static int __init plip_init (void)
{
struct parport *pb = parport_enumerate();
int i=0;
}
return 0;
}
-\f
+
+module_init(plip_init);
+module_exit(plip_cleanup_module);
+
/*
* Local variables:
* compile-command: "gcc -DMODULE -DMODVERSIONS -D__KERNEL__ -Wall -Wstrict-prototypes -O2 -g -fomit-frame-pointer -pipe -c plip.c"
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/in.h>
+#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <asm/irq.h> /* For NR_IRQS only. */
#include <asm/bitops.h>
#include <asm/io.h>
-
-#if LINUX_VERSION_CODE >= 0x020100
-#define LINUX_2_1
-#endif
-
-#ifdef LINUX_2_1
#include <asm/uaccess.h>
-#endif
#include <linux/if_ether.h>
#include <linux/netdevice.h>
#define NEW_MULTICAST
#include <linux/delay.h>
-#ifndef LINUX_2_1
-#define ioremap vremap
-#define iounmap vfree
-#endif
-
/* PCI/45 Configuration space values */
#define RC_PCI45_VENDOR_ID 0x4916
#define RC_PCI45_DEVICE_ID 0x1960
/* A list of all installed RC devices, for removing the driver module. */
static struct net_device *root_RCdev = NULL;
-#ifdef MODULE
-int init_module(void)
-#else
-int rcpci_probe(void)
-#endif
+static int __init rcpci_init_module (void)
{
int cards_found;
printk("rc: skb = 0x%x\n", (uint)skb);
#endif
BufferContext++;
-#ifdef LINUX_2_1
dev_kfree_skb (skb);
-#else
- dev_kfree_skb (skb, FREE_WRITE);
-#endif
}
dev->tbusy = 0;
while(PktCount--)
{
skb = (struct sk_buff *)PacketDescBlock[0];
-#ifndef LINUX_2_1
- skb->free = 1;
- skb->lock = 0;
-#endif
#ifdef RCDEBUG
printk("free skb 0x%p\n", skb);
#endif
-#ifdef LINUX_2_1
dev_kfree_skb (skb);
-#else
- dev_kfree_skb(skb, FREE_READ);
-#endif
pDpa->numOutRcvBuffers--;
PacketDescBlock += BD_SIZE; /* point to next context field */
}
if ( RCPostRecvBuffers(pDpa->id, (PRCTCB)ptcb ) != RC_RTN_NO_ERROR)
{
printk("rc: RCrecv_callback: post buffer failed!\n");
-#ifdef LINUX_2_1
dev_kfree_skb (skb);
-#else
- skb->free = 1;
- dev_kfree_skb(skb, FREE_READ);
-#endif
}
else
{
case RCU_COMMAND:
{
-#ifdef LINUX_2_1
if(copy_from_user(&RCuser, rq->ifr_data, sizeof(RCuser)))
return -EFAULT;
-#else
- int error;
- error=verify_area(VERIFY_WRITE, rq->ifr_data, sizeof(RCuser));
- if (error) {
- return error;
- }
- memcpy_fromfs(&RCuser, rq->ifr_data, sizeof(RCuser));
-#endif
#ifdef RCDEBUG
printk("RCioctl: RCuser_cmd = 0x%x\n", RCuser.cmd);
RCUD_DEFAULT -> rc = 0x11223344;
break;
}
-#ifdef LINUX_2_1
copy_to_user(rq->ifr_data, &RCuser, sizeof(RCuser));
-#else
- memcpy_tofs(rq->ifr_data, &RCuser, sizeof(RCuser));
-#endif
break;
} /* RCU_COMMAND */
}
-#ifdef MODULE
-void
-cleanup_module(void)
+static void __exit rcpci_cleanup_module (void)
{
PDPA pDpa;
struct net_device *next;
root_RCdev = next;
}
}
-#endif
+
+module_init(rcpci_init_module);
+module_exit(rcpci_clenaup_module);
static int
while(p[0])
{
skb = (struct sk_buff *)pB->context;
-#ifndef LINUX_2_1
- skb->free = 1;
-#endif
#ifdef RCDEBUG
printk("rc: freeing 0x%x\n", (uint)skb);
#endif
-#ifdef LINUX_2_1
dev_kfree_skb (skb);
-#else
- dev_kfree_skb(skb, FREE_READ);
-#endif
p[0]--;
pB++;
}
#include <linux/init.h>
#include <linux/netlink.h>
-extern int plip_init(void);
extern int mkiss_init_ctrl_dev(void);
extern int ppp_init(void);
extern int slip_init_ctrl_dev(void);
extern int scc_init(void);
extern int yam_init(void);
-extern int acenic_probe(void);
extern int awc4500_pci_probe(void);
extern int awc4500_isa_probe(void);
extern int awc4500_pnp_probe(void);
extern int awc4500_365_probe(void);
extern int arcnet_init(void);
-extern int bigmac_probe(void);
-extern int bmac_probe(void);
-extern int gmac_probe(void);
extern int cpm_enet_init(void);
-extern int oaknet_init(void);
extern int dlci_setup(void);
-extern int dgrs_probe(void);
-extern int dmfe_reg_board(void);
-extern int eepro100_probe(void);
-extern int epic100_probe(void);
-extern int happy_meal_probe(void);
extern int lapbeth_init(void);
-extern int mace_probe(void);
-extern int myri_sbus_probe(void);
-extern int ncr885e_probe(void);
-extern int ne2k_pci_probe(void);
-extern int pcnet32_probe(void);
-extern int qec_probe(void);
-extern int rcpci_probe(void);
-extern int rr_hippi_probe(void);
-extern int rtl8139_probe(void);
extern int sdla_setup(void);
extern int sdla_c_setup(void);
-extern int sis900_probe(void);
-extern int skge_probe(void);
-extern int sparc_lance_probe(void);
-extern int starfire_probe(void);
-extern int tc59x_probe(void);
-extern int tlan_probe(void);
-extern int tulip_probe(void);
-extern int via_rhine_probe(void);
-extern int yellowfin_probe(void);
extern int abyss_probe(void);
extern int madgemc_probe(void);
#if defined(CONFIG_LAPBETHER)
{lapbeth_init, 0},
#endif
-#if defined(CONFIG_PLIP)
- {plip_init, 0},
-#endif
#if defined(CONFIG_ARCNET)
{arcnet_init, 0},
#endif
{slhc_install, 0},
#endif
#endif
-/*
- * HIPPI
- */
-#ifdef CONFIG_ROADRUNNER
- {rr_hippi_probe, 0},
-#endif
-
-/*
- * ETHERNET
- */
-
-/*
- * SBUS Ethernet
- */
-
-#ifdef CONFIG_HAPPYMEAL
- {happy_meal_probe, 0},
-#endif
-#ifdef CONFIG_SUNLANCE
- {sparc_lance_probe, 0},
-#endif
-#ifdef CONFIG_SUNQE
- {qec_probe, 0},
-#endif
-#ifdef CONFIG_SUNBMAC
- {bigmac_probe, 0},
-#endif
-#ifdef CONFIG_MYRI_SBUS
- {myri_sbus_probe, 0},
-#endif
-
-/*
- * PowerPC Mainboard
- */
-
-#ifdef CONFIG_MACE
- {mace_probe, 0},
-#endif
-#ifdef CONFIG_BMAC
- {bmac_probe, 0},
-#endif
-#ifdef CONFIG_GMAC
- {gmac_probe, 0},
-#endif
-#ifdef CONFIG_NCR885E
- {ncr885e_probe, 0},
-#endif
-
-/*
- * IBM "Oak" Evaluation board
- */
-#ifdef CONFIG_OAKNET
- {oaknet_init, 0},
-#endif
-
-/*
- * PCI Ethernet
- */
-#ifdef CONFIG_DGRS
- {dgrs_probe, 0},
-#endif
-#ifdef CONFIG_RCPCI
- {rcpci_probe, 0},
-#endif
-#ifdef CONFIG_VORTEX
- {tc59x_probe, 0},
-#endif
-#ifdef CONFIG_NE2K_PCI
- {ne2k_pci_probe, 0},
-#endif
-#ifdef CONFIG_PCNET32
- {pcnet32_probe, 0},
-#endif
-#ifdef CONFIG_EEXPRESS_PRO100 /* Intel EtherExpress Pro/100 */
- {eepro100_probe, 0},
-#endif
-#ifdef CONFIG_TLAN
- {tlan_probe, 0},
-#endif
-#ifdef CONFIG_DEC_ELCP
- {tulip_probe, 0},
-#endif
-#ifdef CONFIG_EPIC100
- {epic100_probe, 0},
-#endif
-#ifdef CONFIG_RTL8139
- {rtl8139_probe, 0},
-#endif
-#ifdef CONFIG_SIS900
- {sis900_probe, 0},
-#endif
-
-#ifdef CONFIG_DM9102
- {dmfe_reg_board, 0},
-#endif
-
-#ifdef CONFIG_YELLOWFIN
- {yellowfin_probe, 0},
-#endif
-#ifdef CONFIG_ACENIC
- {acenic_probe, 0},
-#endif
-#ifdef CONFIG_SK98LIN
- {skge_probe, 0},
-#endif
-#ifdef CONFIG_VIA_RHINE
- {via_rhine_probe, 0},
-#endif
-#ifdef CONFIG_ADAPTEC_STARFIRE
- {starfire_probe, 0},
-#endif
/*
*
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
+#include <linux/init.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
struct net_device *next_module;
struct net_device_stats stats;
struct pci_dev * pci_dev;
+
+ spinlock_t lock;
struct mac_chip_info * mac;
struct mii_phy * mii;
int LinkOn;
};
-#ifdef MODULE
-#if LINUX_VERSION_CODE > 0x20115
MODULE_AUTHOR("Jim Huang <cmhuang@sis.com.tw>");
MODULE_DESCRIPTION("SiS 900 PCI Fast Ethernet driver");
MODULE_PARM(multicast_filter_limit, "i");
MODULE_PARM(max_interrupt_work, "i");
MODULE_PARM(debug, "i");
-#endif
-#endif
static int sis900_open(struct net_device *net_dev);
static int sis900_mii_probe (struct net_device * net_dev);
static struct net_device *root_sis900_dev = NULL;
/* walk through every ethernet PCI devices to see if some of them are matched with our card list*/
-int sis900_probe (struct net_device * net_dev)
+static int __init sis900_probe (void)
{
int found = 0;
struct pci_dev * pci_dev = NULL;
- if (!pci_present())
- return -ENODEV;
-
while ((pci_dev = pci_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_dev)) != NULL) {
/* pci_dev contains all ethernet devices */
u32 pci_io_base;
struct mac_chip_info * mac;
+ struct net_device *net_dev = NULL;
for (mac = mac_chip_table; mac->vendor_id; mac++) {
/* try to match our card list */
continue;
/* setup various bits in PCI command register */
+ pci_enable_device (pci_dev);
pci_set_master(pci_dev);
/* do the real low level jobs */
net_dev->irq = irq;
sis_priv->pci_dev = pci_dev;
sis_priv->mac = mac;
+ sis_priv->lock = SPIN_LOCK_UNLOCKED;
/* probe for mii transciver */
if (sis900_mii_probe(net_dev) == 0) {
net_dev->get_stats = &sis900_get_stats;
net_dev->set_multicast_list = &set_rx_mode;
net_dev->do_ioctl = &mii_ioctl;
+ net_dev->tx_timeout = sis900_tx_timeout;
+ net_dev->watchdog_timeo = TX_TIMEOUT;
return net_dev;
}
set_rx_mode(net_dev);
- net_dev->tbusy = 0;
- net_dev->interrupt = 0;
- net_dev->start = 1;
+ netif_start_queue(net_dev);
/* Enable all known interrupts by setting the interrupt mask. */
outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
}
net_dev->trans_start = jiffies;
- net_dev->tbusy = sis_priv->tx_full = 0;
+ sis_priv->tx_full = 0;
+ netif_start_queue(net_dev);
/* FIXME: Should we restart the transmission thread here ?? */
long ioaddr = net_dev->base_addr;
unsigned int entry;
- /* test tbusy to see if we have timeout situation then set it */
- if (test_and_set_bit(0, (void*)&net_dev->tbusy) != 0) {
- if (jiffies - net_dev->trans_start > TX_TIMEOUT)
- sis900_tx_timeout(net_dev);
- return 1;
- }
-
/* Calculate the next Tx descriptor entry. */
entry = sis_priv->cur_tx % NUM_TX_DESC;
sis_priv->tx_skbuff[entry] = skb;
if (++sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC) {
/* Typical path, clear tbusy to indicate more
transmission is possible */
- clear_bit(0, (void*)&net_dev->tbusy);
+ netif_start_queue(net_dev);
} else {
/* no more transmit descriptor avaiable, tbusy remain set */
sis_priv->tx_full = 1;
static void sis900_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
{
struct net_device *net_dev = (struct net_device *)dev_instance;
+ struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv;
int boguscnt = max_interrupt_work;
long ioaddr = net_dev->base_addr;
u32 status;
-#if defined(__i386__)
- /* A lock to prevent simultaneous entry bug on Intel SMP machines. */
- if (test_and_set_bit(0, (void*)&net_dev->interrupt)) {
- printk(KERN_INFO "%s: SMP simultaneous entry of "
- "an interrupt handler.\n", net_dev->name);
- net_dev->interrupt = 0; /* Avoid halting machine. */
- return;
- }
-#else
- if (net_dev->interrupt) {
- printk(KERN_INFO "%s: Re-entering the interrupt handler.\n",
- net_dev->name);
- return;
- }
- net_dev->interrupt = 1;
-#endif
+ spin_lock (&sis_priv->lock);
do {
status = inl(ioaddr + isr);
"interrupt status = 0x%#8.8x.\n",
net_dev->name, inl(ioaddr + isr));
-#if defined(__i386__)
- clear_bit(0, (void*)&net_dev->interrupt);
-#else
- net_dev->interrupt = 0;
-#endif
+ spin_unlock (&sis_priv->lock);
return;
}
sis_priv->tx_ring[entry].cmdsts = 0;
}
- if (sis_priv->tx_full && net_dev->tbusy &&
+ if (sis_priv->tx_full && test_bit(LINK_STATE_XOFF, &net_dev->flags) &&
sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC - 4) {
/* The ring is no longer full, clear tbusy, tx_full and
schedule more transmission by marking NET_BH */
sis_priv->tx_full = 0;
- clear_bit(0, (void *)&net_dev->tbusy);
- mark_bh(NET_BH);
+ netif_wake_queue (net_dev);
}
}
struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv;
int i;
- net_dev->start = 0;
- net_dev->tbusy = 1;
+ netif_stop_queue(net_dev);
/* Disable interrupts by clearing the interrupt mask. */
outl(0x0000, ioaddr + imr);
outl(PESEL, ioaddr + cfg);
}
-#ifdef MODULE
-int init_module(void)
-{
- return sis900_probe(NULL);
-}
-
-void
-cleanup_module(void)
+static void __exit sis900_cleanup_module(void)
{
/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
while (root_sis900_dev) {
}
}
-#endif /* MODULE */
+module_init(sis900_probe);
+module_exit(sis900_cleanup_module);
"@(#)SK-BUILD: 3.02 (19991111) PL: 01";
#include <linux/module.h>
+#include <linux/init.h>
#include "h/skdrv1st.h"
#include "h/skdrv2nd.h"
* 0, if everything is ok
* !=0, on error
*/
-int __init skge_probe (struct net_device *dev)
+static int __init skge_probe (void)
{
-int boards_found = 0;
-int version_disp = 0;
-SK_AC *pAC;
-struct pci_dev *pdev = NULL;
-unsigned long base_address;
+ int boards_found = 0;
+ int version_disp = 0;
+ SK_AC *pAC;
+ struct pci_dev *pdev = NULL;
+ unsigned long base_address;
+ struct net_device *dev = NULL;
if (probed)
return -ENODEV;
}
dev = init_etherdev(dev, sizeof(SK_AC));
- if (dev == NULL){
+ if (dev == NULL || dev->priv == NULL){
printk(KERN_ERR "Unable to allocate etherdev "
"structure!\n");
break;
}
- if (!dev->priv)
- dev->priv = kmalloc(sizeof(SK_AC), GFP_KERNEL);
- if (dev->priv == NULL){
- printk(KERN_ERR "Unable to allocate adapter "
- "structure!\n");
- break;
- }
-
-
memset(dev->priv, 0, sizeof(SK_AC));
pAC = dev->priv;
* or more boards. Otherwise, return failure (-ENODEV).
*/
-#ifdef MODULE
return boards_found;
-#else
- if (boards_found > 0)
- return 0;
- else
- return -ENODEV;
-#endif
} /* skge_probe */
} /* FreeResources */
-#ifdef MODULE
-
MODULE_AUTHOR("Christoph Goos <cgoos@syskonnect.de>");
MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver");
MODULE_PARM(AutoNeg_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
MODULE_PARM(options, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i");
MODULE_PARM(debug, "i");
-#endif // MODULE
-
#ifdef AUTO_NEG_A
static char *AutoNeg_A[SK_MAX_CARD_PARAM] = AUTO_NEG_A;
#endif
-#ifdef MODULE
-
static int debug = 0; /* not used */
static int options[SK_MAX_CARD_PARAM] = {0, }; /* not used */
/*****************************************************************************
*
- * init_module - module initialization function
+ * skge_init_module - module initialization function
*
* Description:
* Very simple, only call skge_probe and return approriate result.
* 0, if everything is ok
* !=0, on error
*/
-int init_module(void)
+static int __init skge_init_module(void)
{
-int cards;
+ int cards;
root_dev = NULL;
debug = 0;
options[0] = 0;
- cards = skge_probe(NULL);
+ cards = skge_probe();
if (cards == 0) {
printk("No adapter found\n");
}
return cards ? 0 : -ENODEV;
-} /* init_module */
+} /* skge_init_module */
/*****************************************************************************
*
- * cleanup_module - module unload function
+ * skge_cleanup_module - module unload function
*
* Description:
* Disable adapter if it is still running, free resources,
*
* Returns: N/A
*/
-void cleanup_module(void)
+static void __exit skge_cleanup_module(void)
{
SK_AC *pAC;
struct net_device *next;
root_dev = next;
}
-}
-#endif /* cleanup_module */
+} /* skge_cleanup_module */
+module_init(skge_init_module);
+module_exit(skge_cleanup_module);
/*****************************************************************************
*
#include <asm/bitops.h>
#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/spinlock.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
static SK_RAM *board; /* pointer to our memory mapped board components */
+static spinlock_t SK_lock = SPIN_LOCK_UNLOCKED;
+
/* Macros */
\f
if (!(i = SK_lance_init(dev, 0))) /* LANCE init OK? */
{
-
-
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue(dev);
#ifdef SK_DEBUG
PRINTK(("## %s: LANCE init failed: CSR0: %#06x\n",
SK_NAME, SK_read_reg(CSR0)));
- dev->start = 0; /* Device not ready */
return -EAGAIN;
}
struct priv *p = (struct priv *) dev->priv;
struct tmd *tmdp;
- if (dev->tbusy)
+ if (test_bit(LINK_STATE_XOFF, &dev->flags))
{
/* if Transmitter more than 150ms busy -> time_out */
SK_lance_init(dev, MODE_NORMAL); /* Reinit LANCE */
- dev->tbusy = 0; /* Clear Transmitter flag */
+ netif_start_queue(dev); /* Clear Transmitter flag */
dev->trans_start = jiffies; /* Mark Start of transmission */
* This means check if we are already in.
*/
- if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) /* dev->tbusy already set ? */
- {
- printk("%s: Transmitter access conflict.\n", dev->name);
- }
- else
+ netif_stop_queue (dev);
+
{
+
/* Evaluate Packet length */
short len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
* We own next buffer and are ready to transmit, so
* clear busy flag
*/
- dev->tbusy = 0;
+ netif_start_queue(dev);
}
p->stats.tx_bytes += skb->len;
+
}
+
dev_kfree_skb(skb);
return 0;
} /* End of SK_send_packet */
printk("SK_interrupt(): IRQ %d for unknown device.\n", irq);
}
-
- if (dev->interrupt)
- {
- printk("%s: Re-entering the interrupt handler.\n", dev->name);
- }
+ spin_lock (&SK_lock);
csr0 = SK_read_reg(CSR0); /* store register for checking */
- dev->interrupt = 1; /* We are handling an interrupt */
-
/*
* Acknowledge all of the current interrupt sources, disable
* Interrupts (INEA = 0)
SK_write_reg(CSR0, CSR0_INEA); /* Enable Interrupts */
- dev->interrupt = 0; /* We are out */
+ spin_unlock (&SK_lock);
} /* End of SK_interrupt() */
\f
* We mark transmitter not busy anymore, because now we have a free
* transmit descriptor which can be filled by SK_send_packet and
* afterwards sent by the LANCE
- */
-
- dev->tbusy = 0;
-
- /*
- * mark_bh(NET_BH);
- * This will cause net_bh() to run after this interrupt handler.
- *
+ *
* The function which do handle slow IRQ parts is do_bottom_half()
* which runs at normal kernel priority, that means all interrupt are
* enabled. (see kernel/irq.c)
* - try to transmit something from the send queue
*/
- mark_bh(NET_BH);
+ netif_wake_queue(dev);
} /* End of SK_txintr() */
PRINTK(("## %s: SK_close(). CSR0: %#06x\n",
SK_NAME, SK_read_reg(CSR0)));
- dev->tbusy = 1; /* Transmitter busy */
- dev->start = 0; /* Card down */
+ netif_stop_queue(dev); /* Transmitter busy */
printk("%s: Shutting %s down CSR0 %#06x\n", dev->name, SK_NAME,
(int) SK_read_reg(CSR0));
printk("## Device Name: %s Base Address: %#06lx IRQ: %d\n",
dev->name, dev->base_addr, dev->irq);
- printk("## FLAGS: start: %d tbusy: %ld int: %ld\n",
- dev->start, dev->tbusy, dev->interrupt);
-
printk("## next device: %#08x init function: %#08x\n",
(int) dev->next, (int) dev->init);
}
#error You must compile this driver with "-O".
#endif
-/* Include files, designed to support most kernel versions 2.0.0 and later. */
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
#include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+#include <linux/init.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/bitops.h>
#include <asm/io.h>
#define RUN_AT(x) (jiffies + (x))
-#ifdef MODULE
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
MODULE_PARM(max_interrupt_work, "i");
MODULE_PARM(rx_copybreak, "i");
MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-#endif
/*
Theory of Operation
unsigned char pci_bus, pci_device_fn;
struct net_device *dev;
- if ( ! pcibios_present())
- return -ENODEV;
-
for (;pci_index < 0xff; pci_index++) {
struct pci_dev *pdev;
u16 vendor, device, pci_command, new_command;
&pci_bus, &pci_device_fn)
!= PCIBIOS_SUCCESSFUL)
break;
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_VENDOR_ID, &vendor);
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_DEVICE_ID, &device);
+ pdev = pci_find_slot (pci_bus, pci_device_fn);
+ if (!pdev) continue;
+ vendor = pdev->vendor;
+ device = pdev->device;
for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
if (vendor == pci_tbl[chip_idx].vendor_id
&& (device & pci_tbl[chip_idx].device_id_mask) ==
pci_tbl[chip_idx].device_id)
break;
- if (pci_tbl[chip_idx].vendor_id == 0) /* Compiled out! */
+ if (pci_tbl[chip_idx].vendor_id == 0) /* Compiled out! */
continue;
- pdev = pci_find_slot(pci_bus, pci_device_fn);
-
- {
- pciaddr = pdev->resource[0].start;
+ pciaddr = pdev->resource[0].start;
#if defined(ADDR_64BITS) && defined(__alpha__)
- pciaddr |= ((long)pdev->base_address[1]) << 32;
+ pciaddr |= ((long)pdev->base_address[1]) << 32;
#endif
- irq = pdev->irq;
- }
+ irq = pdev->irq;
if (debug > 2)
printk(KERN_INFO "Found %s at PCI address %#lx, IRQ %d.\n",
continue;
}
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, &pci_command);
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
new_command = pci_command | (pci_tbl[chip_idx].flags & 7);
if (pci_command != new_command) {
printk(KERN_INFO " The PCI BIOS has not enabled the"
" device at %d/%d! Updating PCI command %4.4x->%4.4x.\n",
pci_bus, pci_device_fn, pci_command, new_command);
- pcibios_write_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, new_command);
+ pci_write_config_word(pdev, PCI_COMMAND, new_command);
}
dev = pci_tbl[chip_idx].probe1(pdev, pci_bus, pci_device_fn, ioaddr,
if (dev && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) {
u8 pci_latency;
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, &pci_latency);
+ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
if (pci_latency < min_pci_latency) {
printk(KERN_INFO " PCI latency timer (CFLT) is "
"unreasonably low at %d. Setting to %d clocks.\n",
pci_latency, min_pci_latency);
- pcibios_write_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, min_pci_latency);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, min_pci_latency);
}
}
cards_found++;
return cards_found ? 0 : -ENODEV;
}
-int starfire_probe(void)
-{
- if (pci_etherdev_probe(pci_tbl) < 0)
- return -ENODEV;
- printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
- return 0;
-}
-
-
static struct net_device *
starfire_probe1(struct pci_dev *pdev, int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_id, int card_idx)
{
struct netdev_private *np;
int i, option = card_idx < MAX_UNITS ? options[card_idx] : 0;
- struct net_device *dev = init_etherdev(NULL, sizeof(struct netdev_private));
+ struct net_device *dev = init_etherdev(NULL, 0);
+
+ if (!dev)
+ return NULL;
printk(KERN_INFO "%s: %s at 0x%lx, ",
dev->name, skel_netdrv_tbl[chip_id].chip_name, ioaddr);
skb->len);
/* Scavenge the descriptor. */
- dev_kfree_skb(skb);
+ kfree_skb(skb);
np->tx_info[entry].skb = NULL;
np->tx_info[entry].mapping = 0;
np->dirty_tx++;
/* We should lock this segment of code for SMP eventually, although
the vulnerability window is very small and statistics are
non-critical. */
-#if LINUX_VERSION_CODE > 0x20119
np->stats.tx_bytes = readl(ioaddr + 0x57010);
np->stats.rx_bytes = readl(ioaddr + 0x57044);
-#endif
np->stats.tx_packets = readl(ioaddr + 0x57000);
np->stats.tx_aborted_errors =
readl(ioaddr + 0x57024) + readl(ioaddr + 0x57028);
np->rx_ring[i].rxaddr = cpu_to_le32(0xBADF00D0); /* An invalid address. */
if (np->rx_info[i].skb != NULL) {
pci_unmap_single(np->pdev, np->rx_info[i].mapping, np->rx_buf_sz);
- dev_kfree_skb(np->rx_info[i].skb);
+ kfree_skb(np->rx_info[i].skb);
}
np->rx_info[i].skb = NULL;
np->rx_info[i].mapping = 0;
pci_unmap_single(np->pdev,
np->tx_info[i].mapping,
skb->len);
- dev_kfree_skb(skb);
+ kfree_skb(skb);
}
np->tx_info[i].skb = NULL;
np->tx_info[i].mapping = 0;
return 0;
}
-\f
-#ifdef MODULE
-int init_module(void)
+static int __init starfire_init_module (void)
{
if (debug) /* Emit version even if no cards detected. */
printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
#endif
}
-void cleanup_module(void)
+static void __exit starfire_cleanup_module (void)
{
struct net_device *next_dev;
}
}
-#endif /* MODULE */
-\f
+module_init(starfire_init_module);
+module_exit(starfire_cleanup_module);
+
+
/*
* Local variables:
* compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c starfire.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
return 1;
}
-int __init bigmac_probe(void)
+static int __init bigmac_probe(void)
{
struct net_device *dev = NULL;
struct sbus_bus *sbus;
static int called = 0;
int cards = 0, v;
+#ifdef MODULE
+ root_bigmac_dev = NULL;
+#endif
+
if (called)
return ENODEV;
called++;
return 0;
}
-#ifdef MODULE
-
-int
-init_module(void)
-{
- root_bigmac_dev = NULL;
- return bigmac_probe();
-}
-
-void
-cleanup_module(void)
+static void __exit bigmac_cleanup(void)
{
+#ifdef MODULE
/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
while (root_bigmac_dev) {
struct bigmac *bp = root_bigmac_dev;
kfree(bp->dev);
root_bigmac_dev = bp_nxt;
}
+#endif /* MODULE */
}
-#endif /* MODULE */
+module_init(bigmac_probe);
+module_exit(bigmac_cleanup);
}
#endif
-int __init happy_meal_probe(void)
+static int __init happy_meal_probe(void)
{
struct net_device *dev = NULL;
static int called = 0;
int cards;
+#ifdef MODULE
+ root_happy_dev = NULL;
+#endif
+
if (called)
return ENODEV;
called++;
return 0;
}
-#ifdef MODULE
-
-int
-init_module(void)
-{
- root_happy_dev = NULL;
- return happy_meal_probe();
-}
-void
-cleanup_module(void)
+static void __exit cleanup_module(void)
{
+#ifdef MODULE
/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
while (root_happy_dev) {
struct happy_meal *hp = root_happy_dev;
kfree(hp->dev);
root_happy_dev = next;
}
+#endif /* MODULE */
}
-#endif /* MODULE */
+module_init(happy_meal_probe);
+module_exit(happy_meal_cleanup_module);
#include <asm/sun4paddr.h>
/* Find all the lance cards on the system and initialize them */
-int __init sparc_lance_probe(void)
+static int __init sparc_lance_probe(void)
{
static struct sbus_dev sdev;
static int called = 0;
+#ifdef MODULE
+ root_lance_dev = NULL;
+#endif
+
if (called)
return ENODEV;
called++;
#else /* !CONFIG_SUN4 */
/* Find all the lance cards on the system and initialize them */
-int __init sparc_lance_probe(void)
+static int __init sparc_lance_probe(void)
{
struct sbus_bus *bus;
struct sbus_dev *sdev = 0;
static int called = 0;
int cards = 0, v;
+#ifdef MODULE
+ root_lance_dev = NULL;
+#endif
+
if (called)
return ENODEV;
called++;
}
#endif /* !CONFIG_SUN4 */
-#ifdef MODULE
-
-int
-init_module(void)
-{
- root_lance_dev = NULL;
- return sparc_lance_probe();
-}
-
-void
-cleanup_module(void)
+static void __exit sparc_lance_cleanup(void)
{
+#ifdef MODULE
struct lance_private *lp;
while (root_lance_dev) {
kfree(root_lance_dev->dev);
root_lance_dev = lp;
}
+#endif /* MODULE */
}
-#endif /* MODULE */
+module_init(sparc_lance_probe);
+module_exit(sparc_lance_cleanup);
return 1;
}
-int __init qec_probe(void)
+static int __init qec_probe(void)
{
struct net_device *dev = NULL;
struct sbus_bus *bus;
static int called = 0;
int cards = 0, v;
+#ifdef MODULE
+ root_qec_dev = NULL;
+#endif
+
if (called)
return ENODEV;
called++;
return 0;
}
-#ifdef MODULE
-
-int
-init_module(void)
-{
- root_qec_dev = NULL;
- return qec_probe();
-}
-
-void
-cleanup_module(void)
+static void __exit qec_cleanup(void)
{
+#ifdef MODULE
struct sunqec *next_qec;
int i;
kfree(root_qec_dev);
root_qec_dev = next_qec;
}
+#endif /* MODULE */
}
-#endif /* MODULE */
+module_init(qec_probe);
+module_exit(qec_cleanup);
static int duplex = 0;
static int speed = 0;
-#ifdef MODULE
-
MODULE_PARM(aui, "i");
MODULE_PARM(duplex, "i");
MODULE_PARM(speed, "i");
MODULE_PARM(debug, "i");
EXPORT_NO_SYMBOLS;
-#endif
-
/* Turn on debugging. See linux/Documentation/networking/tlan.txt for details */
static int debug = 0;
**************************************************************/
-void __exit tlan_exit(void)
+static void __exit tlan_exit(void)
{
struct net_device *dev;
TLanPrivateInfo *priv;
*
**************************************************************/
-int __init tlan_probe(void)
+static int __init tlan_probe(void)
{
struct net_device *dev;
return -EAGAIN;
}
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
+ netif_start_queue(dev);
/* NOTE: It might not be necessary to read the stats before a
reset if you don't care what the values are.
if ( tail_list->cStat != TLAN_CSTAT_UNUSED ) {
TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: %s is busy (Head=%d Tail=%d)\n", dev->name, priv->txHead, priv->txTail );
- dev->tbusy = 1;
+ netif_stop_queue(dev);
priv->txBusyCount++;
return 1;
}
priv = (TLanPrivateInfo *) dev->priv;
spin_lock(&priv->lock);
- if ( dev->interrupt ) {
- printk( "TLAN: Re-entering interrupt handler for %s: %ld.\n" , dev->name, dev->interrupt );
- }
- dev->interrupt++;
host_int = inw( dev->base_addr + TLAN_HOST_INT );
outw( host_int, dev->base_addr + TLAN_HOST_INT );
outl( host_cmd, dev->base_addr + TLAN_HOST_CMD );
}
- dev->interrupt--;
spin_unlock(&priv->lock);
} /* TLan_HandleInterrupts */
{
TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
- dev->start = 0;
- dev->tbusy = 1;
+ netif_stop_queue(dev);
TLan_ReadAndClearStats( dev, TLAN_RECORD );
outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD );
priv->stats.tx_bytes += head_list->frameSize;
head_list->cStat = TLAN_CSTAT_UNUSED;
- dev->tbusy = 0;
+ netif_start_queue(dev);
CIRC_INC( priv->txHead, TLAN_NUM_TX_LISTS );
if ( eoc ) {
TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: Handling TX EOC (Head=%d Tail=%d)\n", priv->txHead, priv->txTail );
TLan_FreeLists( dev );
TLan_ResetLists( dev );
TLan_ResetAdapter( dev );
- dev->tbusy = 0;
+ netif_start_queue(dev);
ack = 0;
} else {
TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Status Check\n", dev->name );
outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR);
sio = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO;
- if ( dev->interrupt == 0 )
- spin_lock_irqsave(&priv->lock, flags);
- dev->interrupt++;
+ spin_lock_irqsave(&priv->lock, flags);
TLan_MiiSync(dev->base_addr);
*val = tmp;
- dev->interrupt--;
- if ( dev->interrupt == 0 )
- spin_unlock_irqrestore(&priv->lock, flags);
-
+ spin_unlock_irqrestore(&priv->lock, flags);
return err;
} /* TLan_MiiReadReg */
outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR);
sio = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO;
- if ( dev->interrupt == 0 )
- spin_lock_irqsave(&priv->lock, flags);
- dev->interrupt++;
+ spin_lock_irqsave(&priv->lock, flags);
TLan_MiiSync( dev->base_addr );
if ( minten )
TLan_SetBit( TLAN_NET_SIO_MINTEN, sio );
- dev->interrupt--;
- if ( dev->interrupt == 0 )
- spin_unlock_irqrestore(&priv->lock, flags);
-
+ spin_unlock_irqrestore(&priv->lock, flags);
} /* TLan_MiiWriteReg */
unsigned long flags = 0;
int ret=0;
- if ( dev->interrupt == 0 )
- spin_lock_irqsave(&priv->lock, flags);
- dev->interrupt++;
+ spin_lock_irqsave(&priv->lock, flags);
TLan_EeSendStart( dev->base_addr );
err = TLan_EeSendByte( dev->base_addr, 0xA0, TLAN_EEPROM_ACK );
goto fail;
}
TLan_EeReceiveByte( dev->base_addr, data, TLAN_EEPROM_STOP );
-fail:
- dev->interrupt--;
- if ( dev->interrupt == 0 )
- spin_unlock_irqrestore(&priv->lock, flags);
+fail:
+ spin_unlock_irqrestore(&priv->lock, flags);
return ret;
} /* TLan_EeReadByte */
int ioaddr = smctr_portlist[i];
if(check_region(ioaddr, SMCTR_IO_EXTENT))
continue;
- if(smctr_probe1(dev, ioaddr))
- {
-#ifndef MODULE
- tr_freedev(dev);
-#endif
- }
- else
+ if (!smctr_probe1(dev, ioaddr))
return (0);
}
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
+#include <linux/init.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/bitops.h>
#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs)
#endif
-#if (LINUX_VERSION_CODE < 0x20123)
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#endif
-
/* This my implementation of shared IRQs, now only used for 1.2.13. */
#ifdef HAVE_SHARED_IRQ
#define USE_SHARED_IRQ
u32 setup_frame[48]; /* Pseudo-Tx frame to init address table. */
int chip_id;
int revision;
-#if LINUX_VERSION_CODE > 0x20139
struct net_device_stats stats;
-#else
- struct enet_statistics stats;
-#endif
struct timer_list timer; /* Media selection timer. */
spinlock_t tx_lock;
unsigned int cur_rx, cur_tx; /* The next free ring entry */
This allows the probe routine to use the old driver initialization
interface. */
-int tulip_probe(void)
+static int __init tulip_probe(void)
{
int cards_found = 0;
static int pci_index = 0; /* Static, for multiple probe calls. */
well with the current structure. So instead we detect just the
Tulip cards in slot order. */
-#if LINUX_VERSION_CODE >= 0x20155
if (! pci_present())
return -ENODEV;
-#else
- if (! pcibios_present())
- return -ENODEV;
-#endif
for (;pci_index < 0xff; pci_index++) {
u16 vendor, device, pci_command, new_command;
unsigned long pci_ioaddr = 0;
int chip_idx = 0;
+ struct pci_dev *pdev;
if (pcibios_find_class
(PCI_CLASS_NETWORK_ETHERNET << 8,
else
break;
}
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_VENDOR_ID, &vendor);
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_DEVICE_ID, &device);
+
+ pdev = pci_find_slot (pci_bus, pci_device_fn);
+ vendor = pdev->vendor;
+ device = pdev->device;
for (chip_idx = 0; tulip_tbl[chip_idx].chip_name; chip_idx++)
if (vendor == tulip_tbl[chip_idx].vendor_id &&
vendor, device);
continue;
}
-#if LINUX_VERSION_CODE >= 0x20155
pci_ioaddr = pci_find_slot(pci_bus, pci_device_fn)->resource[0].start;
-#else
- pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_0,
- &pci_ioaddr);
-#endif
/* Remove I/O space marker in bit 0. */
pci_ioaddr &= ~3;
if (check_region(pci_ioaddr, tulip_tbl[chip_idx].io_size))
continue;
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, &pci_command);
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
if (pci_command != new_command) {
printk(KERN_INFO " The PCI BIOS has not enabled this"
" device! Updating PCI command %4.4x->%4.4x.\n",
pci_command, new_command);
- pcibios_write_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, new_command);
+ pci_write_config_word(pdev, PCI_COMMAND, new_command);
}
if(tulip_probe1(pci_bus, pci_device_fn, chip_idx, cards_found))
{
/* Get and check the bus-master and latency values. */
unsigned char pci_latency;
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, &pci_latency);
+ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
if (pci_latency < 10) {
printk(KERN_INFO " PCI latency timer (CFLT) is "
"unreasonably low at %d. Setting to 64 clocks.\n",
pci_latency);
- pcibios_write_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, 64);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
} else if (tulip_debug > 1)
printk(KERN_INFO " PCI latency timer (CFLT) is %#x, "
" PCI command is %4.4x.\n",
pci_latency, new_command);
/* Bring the 21143 out power-down mode. */
if (device == PCI_DEVICE_ID_DEC_TULIP_21142)
- pcibios_write_config_dword(pci_bus, pci_device_fn,
- 0x40, 0x40000000);
+ pci_write_config_dword(pdev, 0x40, 0x40000000);
cards_found++;
}
}
/* When a module we don't have 'x86' to check. */
outl(0x01A00000 | 0x4800, ioaddr + CSR0);
#else
-#if (LINUX_VERSION_CODE > 0x2014c)
#define x86 boot_cpu_data.x86
-#endif
outl(0x01A00000 | (x86 <= 4 ? 0x4800 : 0x8000), ioaddr + CSR0);
if (x86 <= 4)
printk(KERN_INFO "%s: This is a 386/486 PCI system, setting cache "
#ifdef ETHER_STATS
if (status & 0x0001) tp->stats.tx_deferred++;
#endif
-#if LINUX_VERSION_CODE > 0x20127
tp->stats.tx_bytes += tp->tx_ring[entry].length & 0x7ff;
-#endif
tp->stats.collisions += (status >> 3) & 15;
tp->stats.tx_packets++;
}
/* Free the original skb. */
-#if (LINUX_VERSION_CODE > 0x20155)
dev_kfree_skb_irq(tp->tx_skbuff[entry]);
-#else
- dev_kfree_skb(tp->tx_skbuff[entry], FREE_WRITE);
-#endif
tp->tx_skbuff[entry] = 0;
}
netif_rx(skb);
dev->last_rx = jiffies;
tp->stats.rx_packets++;
-#if LINUX_VERSION_CODE > 0x20127
tp->stats.rx_bytes += pkt_len;
-#endif
}
entry = (++tp->cur_rx) % RX_RING_SIZE;
}
tp->rx_ring[i].length = 0;
tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */
if (skb) {
-#if LINUX_VERSION_CODE < 0x20100
- skb->free = 1;
-#endif
-#if (LINUX_VERSION_CODE > 0x20155)
dev_kfree_skb(skb);
-#else
- dev_kfree_skb(skb, FREE_WRITE);
-#endif
}
}
for (i = 0; i < TX_RING_SIZE; i++) {
if (tp->tx_skbuff[i])
-#if (LINUX_VERSION_CODE > 0x20155)
dev_kfree_skb(tp->tx_skbuff[i]);
-#else
- dev_kfree_skb(tp->tx_skbuff[i], FREE_WRITE);
-#endif
tp->tx_skbuff[i] = 0;
}
u32 io;
u8 bus, devfn;
struct net_device *dev;
+ struct pci_dev *pdev;
if (loc->bus != LOC_PCI) return NULL;
- bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
+ pdev = pci_find_slot (loc->b.pci.bus, loc->b.pci.devfn);
+ if (!pdev) return NULL;
printk(KERN_INFO "tulip_attach(bus %d, function %d)\n", bus, devfn);
- pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
- pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
+ io = pdev->resource[0].start;
+ dev_id = pdev->device;
io &= ~3;
dev = tulip_probe1(bus, devfn, DC21142, -1);
if (dev) {
#endif /* Cardbus support */
-\f
-#ifdef MODULE
-#if LINUX_VERSION_CODE > 0x20118
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver");
MODULE_PARM(debug, "i");
MODULE_PARM(rx_copybreak, "i");
MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-#endif
/* An additional parameter that may be passed in... */
static int debug = -1;
-int
-init_module(void)
+static int __init tulip_init_module (void)
{
if (debug >= 0)
tulip_debug = debug;
#endif
}
-void
-cleanup_module(void)
+static void __exit tulip_cleanup_module (void)
{
struct net_device *next_dev;
}
}
-#endif /* MODULE */
-\f
+module_init(tulip_init_module);
+module_exit(tulip_cleanup_module);
+
+
/*
* Local variables:
* SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c tulip.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+#include <linux/init.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/bitops.h>
#include <asm/io.h>
#define RUN_AT(x) (jiffies + (x))
-#ifdef MODULE
-char kernel_version[] = UTS_RELEASE;
-#endif
-#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver");
MODULE_PARM(max_interrupt_work, "i");
MODULE_PARM(rx_copybreak, "i");
MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-#endif
-#if LINUX_VERSION_CODE < 0x20123
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#endif
-#if LINUX_VERSION_CODE <= 0x20139
-#define net_device_stats enet_statistics
-#else
-#define NETSTATS_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20155 || defined(CARDBUS)
-/* Grrrr, the PCI code changed, but did not consider CardBus... */
-#include <linux/bios32.h>
-#define PCI_SUPPORT_VER1
-#else
-#define PCI_SUPPORT_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20159
-#define dev_free_skb(skb) dev_kfree_skb(skb, FREE_WRITE);
-#else
-#define dev_free_skb(skb) dev_kfree_skb(skb);
-#endif
/*
const char *name;
u16 vendor_id, device_id, device_id_mask, flags;
int io_size;
- struct net_device *(*probe1)(int pci_bus, int pci_devfn, long ioaddr, int irq, int chip_idx, int fnd_cnt);
+ struct net_device *(*probe1)(struct pci_dev *pdev, long ioaddr, int irq, int chip_idx, int fnd_cnt);
};
-static struct net_device *via_probe1(int pci_bus, int pci_devfn, long ioaddr, int irq,
+static struct net_device *via_probe1(struct pci_dev *pdev, long ioaddr, int irq,
int chp_idx, int fnd_cnt);
static struct pci_id_info pci_tbl[] = {
struct net_device *next_module; /* Link for devices of this type. */
struct net_device_stats stats;
struct timer_list timer; /* Media monitoring timer. */
- unsigned char pci_bus, pci_devfn;
+ spinlock_t lock;
/* Frequently used values: keep some adjacent for cache effect. */
int chip_id;
long in_interrupt; /* Word-long for SMP locks. */
unsigned char pci_bus, pci_device_fn;
struct net_device *dev;
- if ( ! pcibios_present())
- return -ENODEV;
-
for (;pci_index < 0xff; pci_index++) {
u16 vendor, device, pci_command, new_command;
int chip_idx, irq;
long pciaddr;
long ioaddr;
+ struct pci_dev *pdev;
if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index,
&pci_bus, &pci_device_fn)
!= PCIBIOS_SUCCESSFUL)
break;
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_VENDOR_ID, &vendor);
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_DEVICE_ID, &device);
+
+ pdev = pci_find_slot (pci_bus, pci_device_fn);
+ if (!pdev) continue;
+ vendor = pdev->vendor;
+ device = pdev->device;
for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
if (vendor == pci_tbl[chip_idx].vendor_id
if (pci_tbl[chip_idx].vendor_id == 0) /* Compiled out! */
continue;
- {
-#if defined(PCI_SUPPORT_VER2)
- struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
#ifdef VIA_USE_IO
- pciaddr = pdev->resource[0].start;
+ pciaddr = pdev->resource[0].start;
#else
- pciaddr = pdev->resource[1].start;
+ pciaddr = pdev->resource[1].start;
#endif
- irq = pdev->irq;
-#else
- u32 pci_memaddr;
- u8 pci_irq_line;
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_INTERRUPT_LINE, &pci_irq_line);
-#ifdef VIA_USE_IO
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_0, &pci_memaddr);
- pciaddr = pci_memaddr;
-#else
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_1, &pci_memaddr);
- pciaddr = pci_memaddr;
-#endif
- irq = pci_irq_line;
-#endif
- }
+ irq = pdev->irq;
if (debug > 2)
printk(KERN_INFO "Found %s at PCI address %#lx, IRQ %d.\n",
continue;
}
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, &pci_command);
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
new_command = pci_command | (pci_tbl[chip_idx].flags & 7);
if (pci_command != new_command) {
printk(KERN_INFO " The PCI BIOS has not enabled the"
" device at %d/%d! Updating PCI command %4.4x->%4.4x.\n",
- pci_bus, pci_device_fn, pci_command, new_command);
- pcibios_write_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, new_command);
+ pdev->bus->number, pdev->devfn, pci_command, new_command);
+ pci_write_config_word(pdev, PCI_COMMAND, new_command);
}
- dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, ioaddr,
- irq, chip_idx, cards_found);
+ dev = pci_tbl[chip_idx].probe1(pdev, ioaddr, irq, chip_idx, cards_found);
if (dev && (pci_tbl[chip_idx].flags & PCI_COMMAND_MASTER)) {
u8 pci_latency;
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, &pci_latency);
+ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
if (pci_latency < min_pci_latency) {
printk(KERN_INFO " PCI latency timer (CFLT) is "
"unreasonably low at %d. Setting to %d clocks.\n",
pci_latency, min_pci_latency);
- pcibios_write_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, min_pci_latency);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, min_pci_latency);
}
}
dev = 0;
return cards_found ? 0 : -ENODEV;
}
-#ifndef MODULE
-int via_rhine_probe(void)
-{
- printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
- return pci_etherdev_probe(pci_tbl);
-}
-#endif
-static struct net_device *via_probe1(int pci_bus, int pci_devfn,
- long ioaddr, int irq,
- int chip_id, int card_idx)
+static struct net_device *via_probe1(struct pci_dev *pdev,
+ long ioaddr, int irq,
+ int chip_id, int card_idx)
{
struct net_device *dev;
struct netdev_private *np;
printk(KERN_INFO "%s: %s at 0x%lx, ",
dev->name, pci_tbl[chip_id].name, ioaddr);
+#ifdef VIA_USE_IO
+ if (!request_region(ioaddr, pci_tbl[chip_id].io_size, dev->name)) {
+ unregister_netdev (dev);
+ kfree (dev);
+ return NULL;
+ }
+#endif
+
/* Ideally we would be read the EEPROM but access may be locked. */
for (i = 0; i <6; i++)
dev->dev_addr[i] = readb(ioaddr + StationAddr + i);
printk("%2.2x:", dev->dev_addr[i]);
printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
-#ifdef VIA_USE_IO
- request_region(ioaddr, pci_tbl[chip_id].io_size, dev->name);
-#endif
-
/* Reset the chip to erase previous misconfiguration. */
writew(CmdReset, ioaddr + ChipCmd);
np->next_module = root_net_dev;
root_net_dev = dev;
- np->pci_bus = pci_bus;
- np->pci_devfn = pci_devfn;
+ np->lock = SPIN_LOCK_UNLOCKED;
np->chip_id = chip_id;
if (dev->mem_start)
dev->get_stats = &get_stats;
dev->set_multicast_list = &set_rx_mode;
dev->do_ioctl = &mii_ioctl;
+ dev->tx_timeout = tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
if (cap_tbl[np->chip_id].flags & CanHaveMII) {
int phy, phy_idx = 0;
if (dev->if_port == 0)
dev->if_port = np->default_port;
- dev->tbusy = 0;
- dev->interrupt = 0;
+ netif_start_queue(dev);
np->in_interrupt = 0;
set_rx_mode(dev);
- dev->start = 1;
-
/* Enable interrupts by setting the interrupt mask. */
writew(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow| IntrRxDropped|
IntrTxDone | IntrTxAbort | IntrTxUnderrun |
struct netdev_private *np = (struct netdev_private *)dev->priv;
unsigned entry;
- /* 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, (void*)&dev->tbusy) != 0) {
- if (jiffies - dev->trans_start < TX_TIMEOUT)
- return 1;
- tx_timeout(dev);
- return 1;
- }
-
/* Caution: the write order is important here, set the field
with the "ownership" bits last. */
writew(CmdTxDemand | np->chip_cmd, dev->base_addr + ChipCmd);
if (np->cur_tx - np->dirty_tx < TX_RING_SIZE - 1)
- clear_bit(0, (void*)&dev->tbusy); /* Typical path */
+ netif_start_queue(dev); /* Typical path */
else
np->tx_full = 1;
dev->trans_start = jiffies;
ioaddr = dev->base_addr;
np = (struct netdev_private *)dev->priv;
-#if defined(__i386__)
- /* A lock to prevent simultaneous entry bug on Intel SMP machines. */
- if (test_and_set_bit(0, (void*)&dev->interrupt)) {
- printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
- dev->name);
- dev->interrupt = 0; /* Avoid halting machine. */
- return;
- }
-#else
- if (dev->interrupt) {
- printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
- return;
- }
- dev->interrupt = 1;
-#endif
+
+ spin_lock (&np->lock);
do {
u32 intr_status = readw(ioaddr + IntrStatus);
if (txstatus & 0x0100) np->stats.tx_aborted_errors++;
if (txstatus & 0x0080) np->stats.tx_heartbeat_errors++;
if (txstatus & 0x0002) np->stats.tx_fifo_errors++;
-#ifdef ETHER_STATS
- if (txstatus & 0x0100) np->stats.collisions16++;
-#endif
/* Transmitter restarted in 'abnormal' handler. */
} else {
-#ifdef ETHER_STATS
- if (txstatus & 0x0001) np->stats.tx_deferred++;
-#endif
np->stats.collisions += (txstatus >> 3) & 15;
-#if defined(NETSTATS_VER2)
np->stats.tx_bytes += np->tx_ring[entry].desc_length & 0x7ff;
-#endif
np->stats.tx_packets++;
}
/* Free the original skb. */
- dev_free_skb(np->tx_skbuff[entry]);
+ kfree_skb(np->tx_skbuff[entry]);
np->tx_skbuff[entry] = 0;
}
- if (np->tx_full && dev->tbusy
- && np->cur_tx - np->dirty_tx < TX_RING_SIZE - 4) {
+ if (np->tx_full &&
+ test_bit(LINK_STATE_XOFF, &dev->flags) &&
+ np->cur_tx - np->dirty_tx < TX_RING_SIZE - 4) {
/* The ring is no longer full, clear tbusy. */
np->tx_full = 0;
- clear_bit(0, (void*)&dev->tbusy);
- mark_bh(NET_BH);
+ netif_wake_queue (dev);
}
/* Abnormal error summary/uncommon events handlers. */
printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
dev->name, readw(ioaddr + IntrStatus));
-#if defined(__i386__)
- clear_bit(0, (void*)&dev->interrupt);
-#else
- dev->interrupt = 0;
-#endif
- return;
+ spin_unlock (&np->lock);
}
/* This routine is logically part of the interrupt handler, but isolated
struct netdev_private *np = (struct netdev_private *)dev->priv;
int i;
- dev->start = 0;
- dev->tbusy = 1;
+ netif_stop_queue(dev);
if (debug > 1)
printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n",
np->rx_ring[i].rx_length = 0;
np->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */
if (np->rx_skbuff[i]) {
-#if LINUX_VERSION_CODE < 0x20100
- np->rx_skbuff[i]->free = 1;
-#endif
- dev_free_skb(np->rx_skbuff[i]);
+ kfree_skb(np->rx_skbuff[i]);
}
np->rx_skbuff[i] = 0;
}
for (i = 0; i < TX_RING_SIZE; i++) {
if (np->tx_skbuff[i])
- dev_free_skb(np->tx_skbuff[i]);
+ kfree_skb(np->tx_skbuff[i]);
np->tx_skbuff[i] = 0;
}
return 0;
}
-\f
-#ifdef MODULE
-int init_module(void)
+static int __init via_rhine_init_module (void)
{
if (debug) /* Emit version even if no cards detected. */
printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
#endif
}
-void cleanup_module(void)
+static void __exit via_rhine_cleanup_module (void)
{
#ifdef CARDBUS
}
}
-#endif /* MODULE */
-\f
+module_init(via_rhine_init_module);
+module_exit(via_rhine_cleanup_module);
+
+
/*
* Local variables:
* compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c via-rhine.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
+#include <linux/init.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/bitops.h>
#include <asm/unaligned.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-/* Kernel compatibility defines, most common to the PCCard package. */
-#include <linux/version.h> /* Evil and unneccessary */
-
#define RUN_AT(x) (jiffies + (x))
-#if (LINUX_VERSION_CODE < 0x20123)
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#endif
-#if LINUX_VERSION_CODE <= 0x20139
-#define net_device_stats enet_statistics
-#define NETSTATS_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20155
-#define PCI_SUPPORT_VER1
-#define pci_present pcibios_present
-#endif
-#if LINUX_VERSION_CODE < 0x20159
-#define DEV_FREE_SKB(skb) dev_kfree_skb(skb, FREE_WRITE);
-#else
#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
-#endif
/* The PCI I/O space extent. */
#define YELLOWFIN_TOTAL_SIZE 0x100
struct tx_status_words tx_status[TX_RING_SIZE];
struct timer_list timer; /* Media selection timer. */
struct enet_statistics stats;
+ spinlock_t lock;
/* Frequently used and paired value: keep adjacent for cache effect. */
int chip_id;
- int in_interrupt;
struct yellowfin_desc *rx_head_desc;
struct tx_status_words *tx_tail_desc;
unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */
u32 pad[4]; /* Used for 32-byte alignment */
};
-#ifdef MODULE
-
-#if LINUX_VERSION_CODE > 0x20115
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_DESCRIPTION("Packet Engines Yellowfin G-NIC Gigabit Ethernet driver");
MODULE_PARM(max_interrupt_work, "i");
MODULE_PARM(rx_copybreak, "i");
MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-#endif
-
-#endif
static struct net_device *yellowfin_probe1(long ioaddr, int irq, int chip_id, int options);
static int read_eeprom(long ioaddr, int location);
/* A list of all installed Yellowfin devices, for removing the driver module. */
static struct net_device *root_yellowfin_dev = NULL;
-int yellowfin_probe(void)
+static int __init yellowfin_probe(void)
{
int cards_found = 0;
int pci_index = 0;
int chip_idx;
int irq;
long ioaddr;
+ struct pci_dev *pdev;
if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
pci_index,
!= PCIBIOS_SUCCESSFUL)
break;
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_VENDOR_ID, &vendor);
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_DEVICE_ID, &device);
+ pdev = pci_find_slot (pci_bus, pci_device_fn);
+ if (!pdev) break;
+ vendor = pdev->vendor;
+ device = pdev->device;
for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++)
if (vendor == chip_tbl[chip_idx].vendor_id
if (check_region(ioaddr, YELLOWFIN_TOTAL_SIZE))
continue;
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, &pci_command);
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
if (pci_command != new_command) {
printk(KERN_INFO " The PCI BIOS has not enabled the"
" device at %d/%d! Updating PCI command %4.4x->%4.4x.\n",
pci_bus, pci_device_fn, pci_command, new_command);
- pcibios_write_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, new_command);
+ pci_write_config_word(pdev, PCI_COMMAND, new_command);
}
if(yellowfin_probe1(ioaddr, irq, chip_idx, cards_found))
{
/* Get and check the bus-master and latency values. */
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, &pci_latency);
+ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
if (pci_latency < min_pci_latency) {
printk(KERN_INFO " PCI latency timer (CFLT) is "
"unreasonably low at %d. Setting to %d clocks.\n",
pci_latency, min_pci_latency);
- pcibios_write_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, min_pci_latency);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, min_pci_latency);
} else if (yellowfin_debug > 1)
printk(KERN_INFO " PCI latency timer (CFLT) is %#x.\n",
pci_latency);
root_yellowfin_dev = dev;
yp->chip_id = chip_id;
+ yp->lock = SPIN_LOCK_UNLOCKED;
option = card_idx < MAX_UNITS ? options[card_idx] : 0;
if (dev->mem_start)
#ifdef HAVE_PRIVATE_IOCTL
dev->do_ioctl = &mii_ioctl;
#endif
+ dev->tx_timeout = yellowfin_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
if (mtu)
dev->mtu = mtu;
if (dev->if_port == 0)
dev->if_port = yp->default_port;
- dev->tbusy = 0;
- dev->interrupt = 0;
- yp->in_interrupt = 0;
+ netif_start_queue(dev);
/* Setting the Rx mode will start the Rx process. */
if (yp->chip_id == 0) {
}
set_rx_mode(dev);
- dev->start = 1;
-
/* Enable interrupts by setting the interrupt mask. */
outw(0x81ff, ioaddr + IntrEnb); /* See enum intr_status_bits */
outw(0x0000, ioaddr + EventStatus); /* Clear non-interrupting events */
struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
unsigned entry;
- /* 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, (void*)&dev->tbusy) != 0) {
- if (jiffies - dev->trans_start < TX_TIMEOUT)
- return 1;
- yellowfin_tx_timeout(dev);
- return 1;
- }
-
/* Caution: the write order is important here, set the base address
with the "ownership" bits last. */
outl(0x10001000, dev->base_addr + TxCtrl);
if (yp->cur_tx - yp->dirty_tx < TX_RING_SIZE - 1)
- clear_bit(0, (void*)&dev->tbusy); /* Typical path */
+ netif_start_queue(dev); /* Typical path */
else
yp->tx_full = 1;
dev->trans_start = jiffies;
ioaddr = dev->base_addr;
yp = (struct yellowfin_private *)dev->priv;
- if (test_and_set_bit(0, (void*)&yp->in_interrupt)) {
- dev->interrupt = 1;
- printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
- return;
- }
+
+ spin_lock (&yp->lock);
do {
u16 intr_status = inw(ioaddr + IntrClear);
yp->tx_skbuff[entry] = 0;
yp->stats.tx_packets++;
}
- if (yp->tx_full && dev->tbusy
- && yp->cur_tx - yp->dirty_tx < TX_RING_SIZE - 4) {
+ if (yp->tx_full &&
+ test_bit(LINK_STATE_XOFF, &dev->flags) &&
+ yp->cur_tx - yp->dirty_tx < TX_RING_SIZE - 4) {
/* The ring is no longer full, clear tbusy. */
yp->tx_full = 0;
- clear_bit(0, (void*)&dev->tbusy);
- mark_bh(NET_BH);
+ netif_wake_queue (dev);
}
#else
if (intr_status & IntrTxDone
}
#endif
- if (yp->tx_full && dev->tbusy
- && yp->cur_tx - dirty_tx < TX_RING_SIZE - 2) {
+ if (yp->tx_full &&
+ test_bit(LINK_STATE_XOFF, &dev->flags) &&
+ yp->cur_tx - dirty_tx < TX_RING_SIZE - 2) {
/* The ring is no longer full, clear tbusy. */
yp->tx_full = 0;
- clear_bit(0, (void*)&dev->tbusy);
- mark_bh(NET_BH);
+ netif_wake_queue (dev);
}
yp->dirty_tx = dirty_tx;
/* Code that should never be run! Perhaps remove after testing.. */
{
static int stopit = 10;
- if (dev->start == 0 && --stopit < 0) {
+ if ((!test_bit(LINK_STATE_START, &dev->state)) && --stopit < 0) {
printk(KERN_ERR "%s: Emergency stop, looping startup interrupt.\n",
dev->name);
free_irq(irq, dev);
}
}
- dev->interrupt = 0;
- clear_bit(0, (void*)&yp->in_interrupt);
+ spin_lock (&yp->lock);
return;
}
struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
int i;
- dev->start = 0;
- dev->tbusy = 1;
+ netif_stop_queue(dev);
if (yellowfin_debug > 1) {
printk(KERN_DEBUG "%s: Shutting down ethercard, status was Tx %4.4x Rx %4.4x Int %2.2x.\n",
yp->rx_ring[i].cmd = CMD_STOP;
yp->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */
if (yp->rx_skbuff[i]) {
-#if LINUX_VERSION_CODE < 0x20100
- yp->rx_skbuff[i]->free = 1;
-#endif
DEV_FREE_SKB(yp->rx_skbuff[i]);
}
yp->rx_skbuff[i] = 0;
}
#endif /* HAVE_PRIVATE_IOCTL */
-\f
-#ifdef MODULE
/* An additional parameter that may be passed in... */
static int debug = -1;
-int init_module(void)
+static int __init yellowfin_init_module(void)
{
if (debug >= 0)
yellowfin_debug = debug;
return yellowfin_probe();
}
-void cleanup_module(void)
+static void __exit yellowfin_cleanup_module (void)
{
struct net_device *next_dev;
}
}
-#endif /* MODULE */
-\f
+module_init(yellowfin_init_module);
+module_exit(yellowfin_cleanup_module);
+
+
/*
* Local variables:
* compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c yellowfin.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
* Translate the low bits of the PCI base
* to the resource type
*/
-static inline unsigned int pci_resource_flags(unsigned int flags)
+static inline unsigned int pci_calc_resource_flags(unsigned int flags)
{
if (flags & PCI_BASE_ADDRESS_SPACE_IO)
return IORESOURCE_IO;
sz = ~(sz & PCI_BASE_ADDRESS_IO_MASK) & 0xffff;
}
res->end = res->start + (unsigned long) sz;
- res->flags |= (l & 0xf) | pci_resource_flags(l);
+ res->flags |= (l & 0xf) | pci_calc_resource_flags(l);
if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
== (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) {
pci_read_config_dword(dev, reg+4, &l);
-/* $Id: flash.c,v 1.16 2000/02/09 22:33:24 davem Exp $
+/* $Id: flash.c,v 1.17 2000/02/10 02:51:35 davem Exp $
* flash.c: Allow mmap access to the OBP Flash, for OBP updates.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
*/
llseek: flash_llseek,
read: flash_read,
- ioctl: flash_mmap,
- mmap: flash_open,
- flush: flash_release,
+ mmap: flash_mmap,
+ open: flash_open,
+ release: flash_release,
};
static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops };
$Header: /vger/u4/cvs/linux/drivers/scsi/hosts.h,v 1.6 1997/01/19 23:07:13 davem Exp $
*/
+#include <linux/config.h>
#include <linux/proc_fs.h>
/* It is senseless to set SG_ALL any higher than this - the performance
* # cat /proc/scsi/sg/debug
*
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/fs.h>
};
extern int ac97_probe_codec(struct ac97_codec *);
-#endif
+
+#endif /* _AC97_CODEC_H_ */
*/
#include <linux/config.h>
+#include <linux/init.h>
#define _DEV_TABLE_C_
return 0;
}
-void sound_setup(char *str, int *ints)
+static int __init sound_setup(char *str)
{
int i, n = num_sound_cards;
+ int ints[32];
+
+ str = get_options(str, ARRAY_SIZE(ints), ints);
/*
* First disable all drivers
snd_installed_cards[i].enabled = 0;
if (ints[0] == 0 || ints[1] == 0)
- return;
+ return 1;
/*
* Then enable them one by time
*/
/*
* Add any future extensions here
*/
- return;
+ return 1;
}
ioaddr = (val & 0x000fff00) >> 8;
irq = (val & 0x000000f0) >> 4;
snd_installed_cards[ptr].config.card_subtype = 0;
}
}
+
+ return 1;
}
+__setup("sound=", sound_setup);
+
struct address_info * sound_getconf(int card_type)
{
void sound_unload_drivers(void);
void sound_unload_driver(int type);
int sndtable_identify_card(char *name);
+
+#if FIXED_FOR_2_4_0
void sound_setup (char *str, int *ints);
+#endif
extern int sound_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc *info);
int sndtable_probe (int unit, struct address_info *hw_config);
}
-#define MAXARGS 8 /* Should be sufficient for now */
-
-void __init dmasound_setup(char *str, int *ints)
+static int __init dmasound_setup(char *str)
{
+ int ints[6];
+
+ str = get_options(str, ARRAY_SIZE(ints), ints);
+
/* check the bootstrap parameter for "dmasound=" */
switch (ints[0]) {
break;
default:
printk("dmasound_setup: illegal number of arguments\n");
+ return 0;
}
+
+ return 1;
}
+__setup("dmasound=", dmasound_setup);
+
#ifdef MODULE
int init_module(void)
{
int err;
+#if FIXED_FOR_2_4_0
int ints[21];
int i;
+#endif
trace_init=traceinit;
printk(KERN_ERR "sound: rebuild with PCI_QUIRKS enabled to configure this.\n");
#endif
+#if FIXED_FOR_2_4_0
/*
* "sound=" command line handling by Harald Milz.
*/
if (i)
sound_setup("sound=", ints);
+#endif
err = create_special_devices();
if (err)
#error "Cannot generate rawmode keyboard for your architecture yet."
#endif
- mark_bh(KEYBOARD_BH);
+ tasklet_schedule(&keyboard_tasklet);
}
static int keybdev_connect(struct input_handler *handler, struct input_dev *dev)
-/* $Id: atyfb.c,v 1.137 2000/01/09 03:11:49 davem Exp $
+/* $Id: atyfb.c,v 1.138 2000/02/10 02:52:12 davem Exp $
* linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
*
* Copyright (C) 1997-1998 Geert Uytterhoeven
&adfs_dir_operations, /* default directory file-ops */
NULL, /* create */
adfs_lookup, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* read link */
- NULL, /* follow link */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
- NULL, /* bmap */
- NULL, /* read page */
- NULL, /* write page */
-#else
- NULL, /* read page */
- NULL, /* write page */
- NULL, /* bmap */
-#endif
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
#include "adfs.h"
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-/*
- * Write to a file (through the page cache).
- */
-static ssize_t
-adfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
- ssize_t retval;
-
- retval = generic_file_write(file, buf, count, ppos,
- block_write_partial_page);
-
- if (retval > 0) {
- struct inode *inode = file->f_dentry->d_inode;
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
- mark_inode_dirty(inode);
- }
-
- return retval;
-}
-#endif
-
/*
* We have mostly NULLs here: the current defaults are OK for
* the adfs filesystem.
mmap: generic_file_mmap,
fsync: file_fsync,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
- write: adfs_file_write,
+ write: generic_file_write,
#endif
};
struct inode_operations adfs_file_inode_operations = {
&adfs_file_operations, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
- adfs_get_block, /* bmap */
- block_read_full_page, /* readpage */
- block_write_full_page, /* writepage */
-#else
- generic_readpage, /* readpage */
- NULL, /* writepage */
- adfs_bmap, /* bmap */
-#endif
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* revalidate */
};
abort_toobig:
return 0;
}
+static int adfs_writepage(struct dentry *dentry, struct page *page)
+{
+ return block_write_full_page(page,adfs_get_block);
+}
+static int adfs_readpage(struct dentry *dentry, struct page *page)
+{
+ return block_read_full_page(page,adfs_get_block);
+}
+static int adfs_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+ return cont_prepare_write(page,from,to,adfs_get_block,
+ &((struct inode*)page->mapping->host)->u.adfs_i.mmu_private);
+}
+static int _adfs_bmap(struct address_space *mapping, long block)
+{
+ return generic_block_bmap(mapping,block,adfs_get_block);
+}
+struct address_space_operations adfs_aops = {
+ readpage: adfs_readpage,
+ writepage: adfs_writepage,
+ prepare_write: adfs_prepare_write,
+ commit_write: generic_commit_write,
+ bmap: _adfs_bmap
+};
#else
int adfs_bmap(struct inode *inode, int block)
{
if (S_ISDIR(inode->i_mode))
inode->i_op = &adfs_dir_inode_operations;
- else if (S_ISREG(inode->i_mode))
- inode->i_op = &adfs_file_inode_operations;
+ else if (S_ISREG(inode->i_mode)) {
+ inode->i_op = &adfs_file_inode_operations;
+ inode->i_mapping->a_ops = &adfs_aops;
+ inode->u.adfs_i.mmu_private = inode->i_size;
+ }
insert_inode_hash(inode);
affs_rmdir, /* rmdir */
NULL, /* mknod */
affs_rename, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permissions */
- NULL /* revalidate */
};
static ssize_t
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- affs_bmap, /* get_block */
- block_read_full_page, /* readpage */
- NULL, /* writepage */
affs_truncate, /* truncate */
NULL, /* permission */
NULL /* revalidate */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
affs_truncate, /* truncate */
NULL, /* permission */
NULL /* revalidate */
return key;
}
+/* AFFS is currently broken */
+static int affs_get_block(struct inode *inode, long block, struct buffer_head *bh, int create)
+{
+ BUG();
+ return -1;
+}
+static int affs_writepage(struct dentry *dentry, struct page *page)
+{
+ return block_write_full_page(page,affs_get_block);
+}
+static int affs_readpage(struct dentry *dentry, struct page *page)
+{
+ return block_read_full_page(page,affs_get_block);
+}
+static int affs_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+ return cont_prepare_write(page,from,to,affs_get_block,
+ &((struct inode*)page->mapping->host)->u.affs_i.mmu_private);
+}
+static int _affs_bmap(struct address_space *mapping, long block)
+{
+ return generic_block_bmap(mapping,block,affs_get_block);
+}
+struct address_space_operations affs_aops = {
+ readpage: affs_readpage,
+ writepage: affs_writepage,
+ prepare_write: affs_prepare_write,
+ commit_write: generic_commit_write,
+ bmap: _affs_bmap
+};
+
/* With the affs, getting a random block from a file is not
* a simple business. Since this fs does not allow holes,
* it may be necessary to allocate all the missing blocks
if (S_ISREG(inode->i_mode)) {
if (inode->i_sb->u.affs_sb.s_flags & SF_OFS) {
inode->i_op = &affs_file_inode_operations_ofs;
- } else {
- inode->i_op = &affs_file_inode_operations;
+ return;
}
+ inode->i_op = &affs_file_inode_operations;
+ inode->i_mapping->a_ops = &affs_aops;
+ inode->u.affs_i.mmu_private = inode->i_size;
} else if (S_ISDIR(inode->i_mode)) {
/* Maybe it should be controlled by mount parameter? */
inode->i_mode |= S_ISVTX;
inode->i_op = &affs_dir_inode_operations;
}
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = &affs_symlink_inode_operations;
+ else if (S_ISLNK(inode->i_mode)) {
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_data.a_ops = &affs_symlink_aops;
+ }
}
void
pr_debug("AFFS: ino=%lu\n",inode->i_ino);
if (dir->i_sb->u.affs_sb.s_flags & SF_OFS)
inode->i_op = &affs_file_inode_operations_ofs;
- else
+ else {
inode->i_op = &affs_file_inode_operations;
-
+ inode->i_mapping->a_ops = &affs_aops;
+ inode->u.affs_i.mmu_private = inode->i_size;
+ }
error = affs_add_entry(dir,NULL,inode,dentry,ST_FILE);
if (error)
goto out_iput;
if (!inode)
goto out;
- inode->i_op = &affs_symlink_inode_operations;
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_data.a_ops = &affs_symlink_aops;
inode->i_mode = S_IFLNK | 0777;
inode->u.affs_i.i_protect = mode_to_prot(inode->i_mode);
error = -EIO;
return err;
}
-struct inode_operations affs_symlink_inode_operations = {
- readlink: page_readlink,
- follow_link: page_follow_link,
+struct address_space_operations affs_symlink_aops = {
readpage: affs_symlink_readpage,
};
&autofs_dir_operations, /* file operations */
NULL, /* create */
autofs_dir_lookup, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
unregister_filesystem(&autofs_fs_type);
}
-module_init(init_autofs_fs)
-module_exit(exit_autofs_fs)
+module_init(init_autofs_fs);
+module_exit(exit_autofs_fs);
#ifdef DEBUG
void autofs_say(const char *name, int len)
autofs_root_symlink, /* symlink */
autofs_root_mkdir, /* mkdir */
autofs_root_rmdir, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
static int autofs_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
EIO_ERROR, /* rename */
EIO_ERROR, /* readlink */
bad_follow_link, /* follow_link */
- EIO_ERROR, /* get_block */
- EIO_ERROR, /* readpage */
- EIO_ERROR, /* writepage */
EIO_ERROR, /* truncate */
EIO_ERROR, /* permission */
EIO_ERROR /* revalidate */
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_blocks = inode->i_blksize = 0;
inode->i_op = &bfs_file_inops;
+ inode->i_mapping->a_ops = &bfs_aops;
inode->i_mode = mode;
inode->i_ino = inode->iu_dsk_ino = ino;
inode->iu_sblock = inode->iu_eblock = 0;
rmdir: NULL,
mknod: NULL,
rename: bfs_rename,
- readlink: NULL,
- follow_link: NULL,
- get_block: NULL,
- readpage: NULL,
- writepage: NULL,
- truncate: NULL,
- permission: NULL,
- revalidate: NULL
};
static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int ino)
#define dprintf(x...)
#endif
-static ssize_t bfs_file_write(struct file * f, const char * buf, size_t count, loff_t *ppos)
-{
- return generic_file_write(f, buf, count, ppos, block_write_partial_page);
-}
-
static struct file_operations bfs_file_operations = {
read: generic_file_read,
- write: bfs_file_write,
+ write: generic_file_write,
mmap: generic_file_mmap,
};
return err;
}
+static int bfs_writepage(struct dentry *dentry, struct page *page)
+{
+ return block_write_full_page(page,bfs_get_block);
+}
+static int bfs_readpage(struct dentry *dentry, struct page *page)
+{
+ return block_read_full_page(page,bfs_get_block);
+}
+static int bfs_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+ return block_prepare_write(page,from,to,bfs_get_block);
+}
+static int bfs_bmap(struct address_space *mapping, long block)
+{
+ return generic_block_bmap(mapping,block,bfs_get_block);
+}
+struct address_space_operations bfs_aops = {
+ readpage: bfs_readpage,
+ writepage: bfs_writepage,
+ prepare_write: bfs_prepare_write,
+ commit_write: generic_commit_write,
+ bmap: bfs_bmap
+};
+
struct inode_operations bfs_file_inops = {
default_file_ops: &bfs_file_operations,
- create: NULL,
- lookup: NULL,
- link: NULL,
- unlink: NULL,
- symlink: NULL,
- mkdir: NULL,
- rmdir: NULL,
- mknod: NULL,
- rename: NULL,
- readlink: NULL,
- follow_link: NULL,
- get_block: bfs_get_block,
- readpage: block_read_full_page,
- writepage: block_write_full_page,
- truncate: NULL,
- permission: NULL,
- revalidate: NULL
};
} else if (di->i_vtype == BFS_VREG) {
inode->i_mode |= S_IFREG;
inode->i_op = &bfs_file_inops;
+ inode->i_mapping->a_ops = &bfs_aops;
} else
inode->i_op = NULL;
* block_write_full_page() is SMP-safe - currently it's still
* being called with the kernel lock held, but the code is ready.
*/
-int block_write_full_page(struct dentry *dentry, struct page *page)
+static int __block_write_full_page(struct inode *inode, struct page *page, get_block_t *get_block)
{
- struct inode *inode = dentry->d_inode;
int err, i, need_balance_dirty = 0;
unsigned long block;
struct buffer_head *bh, *head;
create_empty_buffers(page, inode, inode->i_sb->s_blocksize);
head = page->buffers;
- /* The page cache is now PAGE_CACHE_SIZE aligned, period. We handle old a.out
- * and others via unaligned private mappings.
- */
block = page->index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
bh = head;
i = 0;
do {
- if (!bh)
- BUG();
-
/*
* If the buffer isn't up-to-date, we can't be sure
* that the buffer has been initialized with the proper
*/
bh->b_end_io = end_buffer_io_sync;
if (!buffer_mapped(bh)) {
- err = inode->i_op->get_block(inode, block, bh, 1);
+ err = get_block(inode, block, bh, 1);
if (err)
goto out;
if (buffer_new(bh))
return err;
}
-int block_write_zero_range(struct inode *inode, struct page *page,
- unsigned zerofrom, unsigned from, unsigned to,
- const char * buf)
+static int __block_prepare_write(struct inode *inode, struct page *page,
+ unsigned from, unsigned to, get_block_t *get_block)
{
- unsigned zeroto = 0, block_start, block_end;
+ unsigned block_start, block_end;
unsigned long block;
- int err = 0, partial = 0, need_balance_dirty = 0;
+ int err = 0;
unsigned blocksize, bbits;
struct buffer_head *bh, *head, *wait[2], **wait_bh=wait;
char *kaddr = (char *)kmap(page);
bbits = inode->i_sb->s_blocksize_bits;
block = page->index << (PAGE_CACHE_SHIFT - bbits);
- /*
- * First pass - map what needs to be mapped, initiate reads
- * on the boundaries if needed (i.e. if block is partially covered
- * _and_ is not up-to-date _and_ is not new).
- */
for(bh = head, block_start = 0; bh != head || !block_start;
block++, block_start=block_end, bh = bh->b_this_page) {
if (!bh)
BUG();
block_end = block_start+blocksize;
- if (block_end <= zerofrom)
+ if (block_end <= from)
continue;
if (block_start >= to)
break;
bh->b_end_io = end_buffer_io_sync;
if (!buffer_mapped(bh)) {
- err = inode->i_op->get_block(inode, block, bh, 1);
+ err = get_block(inode, block, bh, 1);
if (err)
goto out;
if (buffer_new(bh)) {
unmap_underlying_metadata(bh);
- zeroto = block_end;
- if (block_start < zerofrom)
- zerofrom = block_start;
+ if (block_end > to)
+ memset(kaddr+to, 0, block_end-to);
+ if (block_start < from)
+ memset(kaddr+block_start, 0, from-block_start);
continue;
}
}
if (!buffer_uptodate(bh) &&
- (block_start < zerofrom || block_end > to)) {
+ (block_start < from || block_end > to)) {
ll_rw_block(READ, 1, &bh);
*wait_bh++=bh;
}
if (!buffer_uptodate(*wait_bh))
goto out;
}
- /*
- * Now we can copy the data.
- */
- if (zerofrom < from)
- memset(kaddr+zerofrom, 0, from-zerofrom);
- if (from < to)
- err = copy_from_user(kaddr+from, buf, to-from);
- if (to < zeroto)
- memset(kaddr+to, 0, zeroto-to);
- else
- zeroto = to;
- if (err < 0)
- goto out;
- /*
- * Second pass: check if all out-of-range blocks are up-to-date
- * and mark the rest up-to-date and dirty.
- *
- * NOTE! This also does a direct dirty balace check,
- * rather than relying on bdflush just waking up every
- * once in a while. This is to catch (and slow down)
- * the processes that write tons of buffer..
- *
- * Note how we do NOT want to do this in the full block
- * case: full pages are flushed not by the people who
- * dirtied them, but by people who need memory. And we
- * should not penalize them for somebody else writing
- * lots of dirty pages.
- */
- for(bh = head, block_start = 0;
+ return 0;
+out:
+ return err;
+}
+
+static int __block_commit_write(struct inode *inode, struct page *page,
+ unsigned from, unsigned to)
+{
+ unsigned block_start, block_end;
+ int partial = 0, need_balance_dirty = 0;
+ unsigned blocksize;
+ struct buffer_head *bh, *head;
+
+ blocksize = inode->i_sb->s_blocksize;
+
+ for(bh = head = page->buffers, block_start = 0;
bh != head || !block_start;
block_start=block_end, bh = bh->b_this_page) {
block_end = block_start + blocksize;
- if (block_end <= zerofrom || block_start >= zeroto) {
+ if (block_end <= from || block_start >= to) {
if (!buffer_uptodate(bh))
partial = 1;
} else {
*/
if (!partial)
SetPageUptodate(page);
- kunmap(page);
return 0;
-out:
- ClearPageUptodate(page);
- kunmap(page);
- return err;
}
-int block_write_partial_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+/*
+ * Generic "read page" function for block devices that have the normal
+ * get_block functionality. This is most of the block device filesystems.
+ * Reads the page asynchronously --- the unlock_buffer() and
+ * mark_buffer_uptodate() functions propagate buffer state into the
+ * page struct once IO has completed.
+ */
+static inline int __block_read_full_page(struct inode *inode, struct page *page,
+ get_block_t *get_block)
{
- struct inode *inode = file->f_dentry->d_inode;
- int err;
+ unsigned long iblock;
+ struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
+ unsigned int blocksize, blocks;
+ unsigned long kaddr = 0;
+ int nr, i;
if (!PageLocked(page))
- BUG();
- if (offset < 0 || offset >= PAGE_SIZE)
- BUG();
- if (bytes+offset < 0 || bytes+offset > PAGE_SIZE)
- BUG();
+ PAGE_BUG(page);
+ blocksize = inode->i_sb->s_blocksize;
+ if (!page->buffers)
+ create_empty_buffers(page, inode, blocksize);
+ head = page->buffers;
+
+ blocks = PAGE_CACHE_SIZE >> inode->i_sb->s_blocksize_bits;
+ iblock = page->index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
+ bh = head;
+ nr = 0;
+ i = 0;
+
+ do {
+ if (buffer_uptodate(bh))
+ continue;
+
+ if (!buffer_mapped(bh)) {
+ get_block(inode, iblock, bh, 0);
+ if (!buffer_mapped(bh)) {
+ if (!kaddr)
+ kaddr = kmap(page);
+ memset((char *)(kaddr + i*blocksize), 0, blocksize);
+ set_bit(BH_Uptodate, &bh->b_state);
+ continue;
+ }
+ }
+
+ init_buffer(bh, end_buffer_io_async, NULL);
+ atomic_inc(&bh->b_count);
+ arr[nr] = bh;
+ nr++;
+ } while (i++, iblock++, (bh = bh->b_this_page) != head);
- err = block_write_range(inode, page, offset, bytes, buf);
- return err ? err : bytes;
+ ++current->maj_flt;
+ if (nr) {
+ if (Page_Uptodate(page))
+ BUG();
+ ll_rw_block(READ, nr, arr);
+ } else {
+ /*
+ * all buffers are uptodate - we can set the page
+ * uptodate as well.
+ */
+ SetPageUptodate(page);
+ UnlockPage(page);
+ }
+ if (kaddr)
+ kunmap(page);
+ return 0;
}
/*
* For moronic filesystems that do not allow holes in file.
- * we allow offset==PAGE_SIZE, bytes==0
+ * We may have to extend the file.
*/
-int block_write_cont_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+int cont_prepare_write(struct page *page, unsigned offset, unsigned to, get_block_t *get_block, unsigned long *bytes)
+{
+ struct address_space *mapping = page->mapping;
+ struct inode *inode = (struct inode*)mapping->host;
+ struct page *new_page;
+ unsigned long pgpos;
+ long status;
+ unsigned zerofrom;
+ unsigned blocksize = inode->i_sb->s_blocksize;
+ char *kaddr;
+
+ while(page->index > (pgpos = *bytes>>PAGE_CACHE_SHIFT)) {
+ status = -ENOMEM;
+ new_page = grab_cache_page(mapping, pgpos);
+ if (!new_page)
+ goto out;
+ /* we might sleep */
+ if (*bytes>>PAGE_CACHE_SHIFT != pgpos) {
+ UnlockPage(new_page);
+ page_cache_release(new_page);
+ continue;
+ }
+ zerofrom = *bytes & ~PAGE_CACHE_MASK;
+ if (zerofrom & (blocksize-1)) {
+ *bytes |= (blocksize-1);
+ (*bytes)++;
+ }
+ status = __block_prepare_write(inode, new_page, zerofrom,
+ PAGE_CACHE_SIZE, get_block);
+ if (status)
+ goto out_unmap;
+ kaddr = (char*)page_address(page);
+ memset(kaddr+zerofrom, 0, PAGE_CACHE_SIZE-zerofrom);
+ __block_commit_write(inode, new_page, zerofrom, to);
+ kunmap(new_page);
+ UnlockPage(new_page);
+ page_cache_release(new_page);
+ }
+
+ if (page->index < pgpos) {
+ /* completely inside the area */
+ zerofrom = offset;
+ } else {
+ /* page covers the boundary, find the boundary offset */
+ zerofrom = *bytes & ~PAGE_CACHE_MASK;
+
+ /* if we will expand the thing last block will be filled */
+ if (to > zerofrom && (zerofrom & (blocksize-1))) {
+ *bytes |= (blocksize-1);
+ (*bytes)++;
+ }
+
+ /* starting below the boundary? Nothing to zero out */
+ if (offset <= zerofrom)
+ zerofrom = offset;
+ }
+ status = __block_prepare_write(inode, page, zerofrom, to, get_block);
+ if (status)
+ goto out1;
+ kaddr = (char*)page_address(page);
+ if (zerofrom < offset) {
+ memset(kaddr+zerofrom, 0, offset-zerofrom);
+ __block_commit_write(inode, page, zerofrom, offset);
+ }
+ return 0;
+out1:
+ ClearPageUptodate(page);
+ kunmap(page);
+ return status;
+
+out_unmap:
+ ClearPageUptodate(new_page);
+ kunmap(new_page);
+ UnlockPage(new_page);
+ page_cache_release(new_page);
+out:
+ return status;
+}
+
+int block_prepare_write(struct page *page, unsigned from, unsigned to,
+ get_block_t *get_block)
{
- struct inode *inode = file->f_dentry->d_inode;
- int err;
- unsigned zerofrom = offset;
+ struct inode *inode = (struct inode*)page->mapping->host;
+ int err = __block_prepare_write(inode, page, from, to, get_block);
+ if (err) {
+ ClearPageUptodate(page);
+ kunmap(page);
+ }
+ return err;
+}
+
+int generic_commit_write(struct file *file, struct page *page,
+ unsigned from, unsigned to)
+{
+ __block_commit_write((struct inode*)page->mapping->host,page,from,to);
+ kunmap(page);
+ return 0;
+}
+
+int block_write_full_page(struct page *page, get_block_t *get_block)
+{
+ struct inode *inode = (struct inode*)page->mapping->host;
+ return __block_write_full_page(inode, page, get_block);
+}
- if (page->index > (inode->i_size >> PAGE_CACHE_SHIFT))
- zerofrom = 0;
- else if (page->index == (inode->i_size >> PAGE_CACHE_SHIFT) &&
- offset > (inode->i_size & ~PAGE_CACHE_MASK))
- zerofrom = inode->i_size & ~PAGE_CACHE_MASK;
- err = block_write_zero_range(inode, page, zerofrom,offset,offset+bytes,
- buf);
- return err ? err : bytes;
+int block_read_full_page(struct page *page, get_block_t *get_block)
+{
+ struct inode *inode = (struct inode*)page->mapping->host;
+ return __block_read_full_page(inode, page, get_block);
}
+int generic_block_bmap(struct address_space *mapping, long block, get_block_t *get_block)
+{
+ struct buffer_head tmp;
+ struct inode *inode = (struct inode*)mapping->host;
+ tmp.b_state = 0;
+ tmp.b_blocknr = 0;
+ get_block(inode, block, &tmp, 0);
+ return tmp.b_blocknr;
+}
/*
* IO completion routine for a buffer_head being used for kiobuf IO: we
return 0;
}
-/*
- * Generic "read page" function for block devices that have the normal
- * get_block functionality. This is most of the block device filesystems.
- * Reads the page asynchronously --- the unlock_buffer() and
- * mark_buffer_uptodate() functions propagate buffer state into the
- * page struct once IO has completed.
- */
-static inline int __block_read_full_page(struct inode *inode, struct page *page)
-{
- unsigned long iblock;
- struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
- unsigned int blocksize, blocks;
- unsigned long kaddr = 0;
- int nr, i;
-
- if (!PageLocked(page))
- PAGE_BUG(page);
- blocksize = inode->i_sb->s_blocksize;
- if (!page->buffers)
- create_empty_buffers(page, inode, blocksize);
- head = page->buffers;
-
- blocks = PAGE_CACHE_SIZE >> inode->i_sb->s_blocksize_bits;
- iblock = page->index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
- bh = head;
- nr = 0;
- i = 0;
-
- do {
- if (buffer_uptodate(bh))
- continue;
-
- if (!buffer_mapped(bh)) {
- inode->i_op->get_block(inode, iblock, bh, 0);
- if (!buffer_mapped(bh)) {
- if (!kaddr)
- kaddr = kmap(page);
- memset((char *)(kaddr + i*blocksize), 0, blocksize);
- set_bit(BH_Uptodate, &bh->b_state);
- continue;
- }
- }
-
- init_buffer(bh, end_buffer_io_async, NULL);
- atomic_inc(&bh->b_count);
- arr[nr] = bh;
- nr++;
- } while (i++, iblock++, (bh = bh->b_this_page) != head);
-
- ++current->maj_flt;
- if (nr) {
- if (Page_Uptodate(page))
- BUG();
- ll_rw_block(READ, nr, arr);
- } else {
- /*
- * all buffers are uptodate - we can set the page
- * uptodate as well.
- */
- SetPageUptodate(page);
- UnlockPage(page);
- }
- if (kaddr)
- kunmap(page);
- return 0;
-}
-
-int block_read_full_page(struct dentry *dentry, struct page *page)
-{
- return __block_read_full_page(dentry->d_inode, page);
-}
-
int block_symlink(struct inode *inode, const char *symname, int len)
{
- struct page *page = grab_cache_page(&inode->i_data, 0);
- mm_segment_t fs;
+ struct address_space *mapping = inode->i_mapping;
+ struct page *page = grab_cache_page(mapping, 0);
int err = -ENOMEM;
+ char *kaddr;
if (!page)
goto fail;
- fs = get_fs();
- set_fs(KERNEL_DS);
- err = block_write_range(inode, page, 0, len-1, symname);
- set_fs(fs);
- inode->i_size = len-1;
+ err = mapping->a_ops->prepare_write(page, 0, len-1);
if (err)
- goto fail_write;
+ goto fail_map;
+ kaddr = (char*)page_address(page);
+ memcpy(kaddr, symname, len-1);
+ mapping->a_ops->commit_write(NULL, page, 0, len-1);
+ inode->i_size = len-1;
/*
* Notice that we are _not_ going to block here - end of page is
* unmapped, so this will only try to map the rest of page, see
* ->i_size will be enough for everything) and zero it out.
* OTOH it's obviously correct and should make the page up-to-date.
*/
- err = __block_read_full_page(inode, page);
+ err = mapping->a_ops->readpage(NULL, page);
wait_on_page(page);
page_cache_release(page);
if (err < 0)
goto fail;
mark_inode_dirty(inode);
return 0;
-fail_write:
+fail_map:
+ inode->i_size = len-1;
UnlockPage(page);
page_cache_release(page);
fail:
inode->i_op = &coda_file_inode_operations;
else if (S_ISDIR(inode->i_mode))
inode->i_op = &coda_dir_inode_operations;
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = &coda_symlink_inode_operations;
- else
+ else if (S_ISLNK(inode->i_mode)) {
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_data.a_ops = &coda_symlink_aops;
+ } else
init_special_inode(inode, inode->i_mode, attr->va_rdev);
}
+struct inode * coda_iget(struct super_block * sb, ViceFid * fid,
+ struct coda_vattr * attr)
+{
+ struct inode *inode;
+ struct coda_sb_info *sbi= coda_sbp(sb);
+ struct coda_inode_info *cii;
+ ino_t ino = attr->va_fileid;
+
+ inode = iget(sb, ino);
+ if ( !inode ) {
+ CDEBUG(D_CNODE, "coda_iget: no inode\n");
+ return NULL;
+ }
+
+ /* check if the inode is already initialized */
+ cii = ITOC(inode);
+ if (cii->c_magic == CODA_CNODE_MAGIC)
+ goto out;
+
+ /* Initialize the Coda inode info structure */
+ memset(cii, 0, (int) sizeof(struct coda_inode_info));
+ cii->c_magic = CODA_CNODE_MAGIC;
+ cii->c_fid = *fid;
+ cii->c_flags = 0;
+ cii->c_vnode = inode;
+ INIT_LIST_HEAD(&(cii->c_cnhead));
+ INIT_LIST_HEAD(&(cii->c_volrootlist));
+
+ coda_fill_inode(inode, attr);
+
+ /* check if it is a weird fid (hashed fid != ino), f.i mountpoints
+ repair object, expanded local-global conflict trees, etc.
+ */
+ if ( coda_f2i(fid) == ino )
+ goto out;
+
+ /* check if we expect this weird fid */
+ if ( !coda_fid_is_weird(fid) )
+ printk("Coda: unknown weird fid: ino %ld, fid %s."
+ "Tell Peter.\n", (long)ino, coda_f2s(&cii->c_fid));
+
+ /* add the inode to a global list so we can find it back later */
+ list_add(&cii->c_volrootlist, &sbi->sbi_volroothead);
+ CDEBUG(D_CNODE, "Added %ld, %s to volroothead\n",
+ (long)ino, coda_f2s(&cii->c_fid));
+out:
+ return inode;
+}
+
/* this is effectively coda_iget:
- get attributes (might be cached)
- get the inode for the fid using vfs iget
int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb)
{
struct coda_inode_info *cnp;
- struct coda_sb_info *sbi= coda_sbp(sb);
struct coda_vattr attr;
int error;
- ino_t ino;
ENTRY;
- /*
- * We get inode numbers from Venus -- see venus source
- */
+ /* We get inode numbers from Venus -- see venus source */
error = venus_getattr(sb, fid, &attr);
if ( error ) {
return error;
}
- ino = attr.va_fileid;
- *inode = iget(sb, ino);
- if ( !*inode ) {
- printk("coda_cnode_make: iget failed\n");
+ *inode = coda_iget(sb, fid, &attr);
+ if ( !(*inode) ) {
+ printk("coda_cnode_make: coda_iget failed\n");
return -ENOMEM;
}
cnp = ITOC(*inode);
- /* see if we've got it already */
- if ( cnp->c_magic != 0 && coda_fideq(fid, &cnp->c_fid)) {
+ /* see if it is the right one (we might have an inode collision) */
+ if ( coda_fideq(fid, &cnp->c_fid) ) {
+ CDEBUG(D_DOWNCALL,
+ "Done making inode: ino %ld, count %d with %s\n",
+ (*inode)->i_ino, (*inode)->i_count,
+ coda_f2s(&cnp->c_fid));
+ EXIT;
return 0;
}
- /* not fresh: collision */
- if ( cnp->c_magic != 0 ) {
- printk("coda_cnode_make on initialized inode %ld, old %s new
-%s!\n",
+ /* collision */
+ printk("coda_cnode_make on initialized inode %ld, old %s new %s!\n",
(*inode)->i_ino, coda_f2s(&cnp->c_fid), coda_f2s2(fid));
iput(*inode);
- return -ENOENT;
- }
-
- memset(cnp, 0, (int) sizeof(struct coda_inode_info));
- cnp->c_fid = *fid;
- cnp->c_magic = CODA_CNODE_MAGIC;
- cnp->c_flags = 0;
- cnp->c_vnode = *inode;
- INIT_LIST_HEAD(&(cnp->c_cnhead));
- INIT_LIST_HEAD(&(cnp->c_volrootlist));
-
- /* fill in the inode attributes */
- if ( coda_f2i(fid) != ino ) {
- if ( !coda_fid_is_weird(fid) )
- printk("Coda: unknown weird fid: ino %ld, fid %s."
- "Tell Peter.\n", (long)ino, coda_f2s(&cnp->c_fid));
- list_add(&cnp->c_volrootlist, &sbi->sbi_volroothead);
- CDEBUG(D_UPCALL, "Added %ld ,%s to volroothead\n",
- (long)ino, coda_f2s(&cnp->c_fid));
- }
-
- coda_fill_inode(*inode, &attr);
- CDEBUG(D_DOWNCALL, "Done making inode: ino %ld, count %d with %s\n",
- (*inode)->i_ino, (*inode)->i_count,
- coda_f2s(&cnp->c_fid));
-
EXIT;
- return 0;
+ return -ENOENT;
}
coda_f2s(&cii->c_fid), cii->c_vnode->i_ino);
if ( coda_fideq(&cii->c_fid, fid) ) {
inode = cii->c_vnode;
- CDEBUG(D_INODE, "volume root, found %ld\n", cii->c_vnode->i_ino);
+ CDEBUG(D_INODE, "volume root, found %ld\n", inode->i_ino);
if ( cii->c_magic != CODA_CNODE_MAGIC )
printk("%s: Bad magic in inode, tell Peter.\n",
__FUNCTION__);
- return cii->c_vnode;
+
+ iget(sb, inode->i_ino);
+ return inode;
}
}
}
CDEBUG(D_INODE, "found %ld\n", inode->i_ino);
- iput(inode);
return inode;
}
return 1;
return 0;
-
}
vattr->va_ctime.tv_sec = iattr->ia_ctime;
vattr->va_ctime.tv_nsec = 0;
}
-
}
void print_vattr(struct coda_vattr *attr)
coda_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
NULL, /* truncate */
coda_permission, /* permission */
coda_revalidate_inode /* revalidate */
}
-
/* creation routines: create, mknod, mkdir, link, symlink */
static int coda_create(struct inode *dir, struct dentry *de, int mode)
coda_vfs_stat.create++;
- CDEBUG(D_INODE, "name: %s, length %d, mode %o, rdev %x\n",name, length, mode, rdev);
+ CDEBUG(D_INODE, "name: %s, length %d, mode %o, rdev %x\n",
+ name, length, mode, rdev);
if (coda_isroot(dir) && coda_iscontrol(name, length))
return -EPERM;
}
-
/* file operations for directories */
int coda_readdir(struct file *file, void *dirent, filldir_t filldir)
{
coda_load_creds(cred);
f->private_data = cred;
- if ( cnp->c_ovp ) {
+ if ( cnp->c_ovp )
iput(cnp->c_ovp);
- cnp->c_ovp = NULL;
- }
+
cnp->c_ovp = cont_inode;
+ i->i_mapping = cont_inode->i_mapping;
cnp->c_ocount++;
CDEBUG(D_FILE, "result %d, coda i->i_count is %d for ino %ld\n",
int coda_release(struct inode *i, struct file *f)
{
struct coda_inode_info *cnp;
- int error;
+ int error = 0;
unsigned short flags = (f->f_flags) & (~O_EXCL);
unsigned short cflags = coda_flags_to_cflags(flags);
struct coda_cred *cred;
--cnp->c_ocount;
- if (flags & (O_WRONLY | O_RDWR)) {
+ if ( flags & (O_WRONLY | O_RDWR) )
--cnp->c_owrite;
- }
+ /* Venus closing a container file? don't bother making the upcall. */
+ if ( current->pid != coda_upc_comm.vc_pid ) {
error = venus_release(i->i_sb, &(cnp->c_fid), cflags, cred);
+ }
- CODA_FREE(cred, sizeof(*cred));
f->private_data = NULL;
+ if (cred)
+ CODA_FREE(cred, sizeof(*cred));
CDEBUG(D_FILE, "coda_release: result: %d\n", error);
return error;
if ( cii->c_flags == 0 )
return 0;
- /* Venus closed the device .... */
- if ( cii->c_flags & C_DYING ) {
- make_bad_inode(inode);
- return -EIO;
- }
+ /* Venus accessing a container file, don't try to revalidate */
+ if ( current->pid == coda_upc_comm.vc_pid )
+ return 0;
+ /* Venus closed the device .... */
+ if ( cii->c_flags & C_DYING )
+ goto return_bad_inode;
if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
- if ( error ) {
- make_bad_inode(inode);
- return -EIO;
- }
+ if ( error )
+ goto return_bad_inode;
/* this inode may be lost if:
- it's ino changed
}
/* the following can happen when a local fid is replaced
- with a global one, here we lose and declar the inode bad */
- if (inode->i_ino != old_ino) {
- make_bad_inode(inode);
- inode->i_mode = old_mode;
- return -EIO;
- }
+ with a global one, here we lose and declare the inode bad */
+ if (inode->i_ino != old_ino)
+ goto return_bad_inode;
if ( cii->c_flags )
coda_flag_inode_children(inode, C_FLUSH);
}
return 0;
+
+return_bad_inode:
+ if ( cii->c_ovp ) {
+ iput(cii->c_ovp);
+ inode->i_mapping = &inode->i_data;
+ cii->c_ovp = NULL;
+ }
+ make_bad_inode(inode);
+ return -EIO;
}
#include <linux/coda_proc.h>
/* file operations */
-static int coda_readpage(struct dentry *dentry, struct page * page);
-static ssize_t coda_file_read(struct file *f, char *buf, size_t count, loff_t *off);
-static ssize_t coda_file_write(struct file *f, const char *buf, size_t count, loff_t *off);
static int coda_file_mmap(struct file * file, struct vm_area_struct * vma);
/* also exported from this file (used for dirs) */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block */
- coda_readpage, /* readpage */
- NULL, /* writepage */
NULL, /* truncate */
coda_permission, /* permission */
coda_revalidate_inode /* revalidate */
};
struct file_operations coda_file_operations = {
- read: coda_file_read,
- write: coda_file_write,
+ read: generic_file_read,
+ write: generic_file_write,
mmap: coda_file_mmap,
open: coda_open,
release: coda_release,
fsync: coda_fsync,
};
-
-/* File file operations */
-static int coda_readpage(struct dentry * dentry, struct page * page)
-{
- struct inode *coda_inode = dentry->d_inode;
- struct dentry cont_dentry;
- struct coda_inode_info *cii;
-
- ENTRY;
- coda_vfs_stat.readpage++;
-
- cii = ITOC(coda_inode);
-
- if ( ! cii->c_ovp ) {
- printk("coda_readpage: no open inode for ino %ld, %s\n",
- coda_inode->i_ino, dentry->d_name.name);
- return -ENXIO;
- }
-
- cont_dentry.d_inode = cii->c_ovp;
-
- CDEBUG(D_INODE, "coda ino: %ld, cached ino %ld, page offset: %lx\n",
- coda_inode->i_ino, cii->c_ovp->i_ino, page->index);
-
- block_read_full_page(&cont_dentry, page);
- EXIT;
- return 0;
-}
+
+/* File operations */
static int coda_file_mmap(struct file * file, struct vm_area_struct * vma)
{
return res;
}
-static ssize_t coda_file_read(struct file *coda_file, char *buff,
- size_t count, loff_t *ppos)
-{
- struct coda_inode_info *cnp;
- struct inode *coda_inode = coda_file->f_dentry->d_inode;
- struct inode *cont_inode = NULL;
- struct file cont_file;
- struct dentry cont_dentry;
- int result = 0;
-
- ENTRY;
- coda_vfs_stat.file_read++;
-
- cnp = ITOC(coda_inode);
- CHECK_CNODE(cnp);
-
- cont_inode = cnp->c_ovp;
- if ( cont_inode == NULL ) {
- printk("coda_file_read: cached inode is 0!\n");
- return -1;
- }
-
- coda_prepare_openfile(coda_inode, coda_file, cont_inode,
- &cont_file, &cont_dentry);
-
- if (!cont_file.f_op || ! cont_file.f_op->read) {
- printk( "container file has no read in file operations.\n");
- return -1;
- }
-
- result = cont_file.f_op->read(&cont_file , buff, count,
- &(cont_file.f_pos));
-
- CDEBUG(D_FILE, "ops at %p result %d, count %ld, position: %d\n",
- cont_file.f_op, result, (long)count, (int)cont_file.f_pos);
-
- coda_restore_codafile(coda_inode, coda_file, cont_inode, &cont_file);
- return result;
-}
-
-
-static ssize_t coda_file_write(struct file *coda_file, const char *buff,
- size_t count, loff_t *ppos)
-{
- struct coda_inode_info *cnp;
- struct inode *coda_inode = coda_file->f_dentry->d_inode;
- struct inode *cont_inode = NULL;
- struct file cont_file;
- struct dentry cont_dentry;
- int result = 0;
-
- ENTRY;
- coda_vfs_stat.file_write++;
-
- cnp = ITOC(coda_inode);
- CHECK_CNODE(cnp);
-
- cont_inode = cnp->c_ovp;
- if ( cont_inode == NULL ) {
- printk("coda_file_write: cached inode is 0!\n");
- return -1;
- }
-
- coda_prepare_openfile(coda_inode, coda_file, cont_inode,
- &cont_file, &cont_dentry);
-
- if (!cont_file.f_op || !cont_file.f_op->write) {
- printk("coda_file_write: container file has no file ops.\n");
- return -1;
- }
-
- down(&cont_inode->i_sem);
- result = cont_file.f_op->write(&cont_file , buff, count,
- &(cont_file.f_pos));
- up(&cont_inode->i_sem);
- coda_restore_codafile(coda_inode, coda_file, cont_inode, &cont_file);
-
- if (result)
- cnp->c_flags |= C_VATTR;
-
- return result;
-}
-
int coda_fsync(struct file *coda_file, struct dentry *coda_dentry)
{
struct coda_inode_info *cnp;
*ind = iget(sbptr, ino);
if ( *ind == NULL ) {
- printk("coda_inode_grab: iget(dev: %d, ino: %ld)
- returns NULL.\n", dev, (long)ino);
+ printk("coda_inode_grab: iget(dev: %d, ino: %ld) "
+ "returns NULL.\n", dev, (long)ino);
return -ENOENT;
}
CDEBUG(D_FILE, "ino: %ld, ops at %p\n", (long)ino, (*ind)->i_op);
coda_put_super, /* put_super */
NULL, /* write_super */
coda_statfs, /* statfs */
- NULL /* remount_fs */
+ NULL, /* remount_fs */
+ NULL, /* no clear inode */
+ NULL /* umount attempt begin */
};
static struct super_block * coda_read_super(struct super_block *sb,
return;
}
-static void coda_put_inode(struct inode *in)
+static void coda_put_inode(struct inode *inode)
{
ENTRY;
- CDEBUG(D_INODE,"ino: %ld, count %d\n", in->i_ino, in->i_count);
-
- if ( in->i_count == 1 )
- in->i_nlink = 0;
+ CDEBUG(D_INODE,"ino: %ld, count %d\n", inode->i_ino, inode->i_count);
+ if ( inode->i_count == 1 ) {
+ write_inode_now(inode);
+ inode->i_nlink = 0;
+ }
}
static void coda_delete_inode(struct inode *inode)
return;
}
-
- if ( ! list_empty(&cii->c_volrootlist) )
+ if ( ! list_empty(&cii->c_volrootlist) ) {
list_del(&cii->c_volrootlist);
+ INIT_LIST_HEAD(&cii->c_volrootlist);
+ }
open_inode = cii->c_ovp;
if ( open_inode ) {
CDEBUG(D_SUPER, "DELINO cached file: ino %ld count %d.\n",
open_inode->i_ino, open_inode->i_count);
cii->c_ovp = NULL;
+ inode->i_mapping = &inode->i_data;
iput(open_inode);
}
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
NULL, /* truncate */
coda_ioctl_permission, /* permission */
NULL /* revalidate */
/* The pioctl file ops*/
int coda_ioctl_open(struct inode *i, struct file *f)
{
-
ENTRY;
CDEBUG(D_PIOCTL, "File inode number: %ld\n",
return mask;
}
+static int coda_psdev_ioctl(struct inode * inode, struct file * filp,
+ unsigned int cmd, unsigned long arg)
+{
+ unsigned int data;
+
+ switch(cmd) {
+ case CIOC_KERNEL_VERSION:
+ data = CODA_KERNEL_VERSION;
+ return put_user(data, (int *) arg);
+ default:
+ return -ENOTTY;
+ }
+
+ return 0;
+}
/*
* Receive a message written by Venus to the psdev
vcp->vc_inuse++;
MOD_INC_USE_COUNT;
-
if ( file->f_flags == O_RDWR ) {
vcp->vc_pid = current->pid;
vcp->vc_seq = 0;
}
-
static int coda_psdev_release(struct inode * inode, struct file * file)
{
struct venus_comm *vcp = &coda_upc_comm;
CODA_FREE(req, (u_int)sizeof(struct upc_req));
continue;
}
+ req->uc_flags |= REQ_ABORT;
wake_up(&req->uc_sleep);
}
CDEBUG(D_PSDEV, "wake up processing clients\n");
while ( (lh = lh->next) != &vcp->vc_processing) {
req = list_entry(lh, struct upc_req, uc_chain);
+ req->uc_flags |= REQ_ABORT;
wake_up(&req->uc_sleep);
}
CDEBUG(D_PSDEV, "Done.\n");
read: coda_psdev_read,
write: coda_psdev_write,
poll: coda_psdev_poll,
+ ioctl: coda_psdev_ioctl,
open: coda_psdev_open,
release: coda_psdev_release,
};
return error;
}
-struct inode_operations coda_symlink_inode_operations = {
- readlink: page_readlink,
- follow_link: page_follow_link,
+struct address_space_operations coda_symlink_aops = {
readpage: coda_symlink_filler
};
"open_by_path", /* 31 */
"resolve ", /* 32 */
"reintegrate ", /* 33 */
- "statfs " /* 34 */
+ "statfs ", /* 34 */
+ "make_cinode " /* 35 */
};
return 0;
time_avg = get_time_average( pentry );
- return
- sqr_root( (pentry->time_squared_sum / pentry->count) -
+
+ return sqr_root( (pentry->time_squared_sum / pentry->count) -
time_avg * time_avg );
}
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/fs.h>
+#include <linux/file.h>
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/locks.h>
set_current_state(TASK_UNINTERRUPTIBLE);
/* got a reply */
- if ( vmp->uc_flags & REQ_WRITE )
+ if ( vmp->uc_flags & ( REQ_WRITE | REQ_ABORT ) )
break;
if ( !coda_hard && signal_pending(current) ) {
int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
{
-
/* Handle invalidation requests. */
if ( !sb || !sb->s_root || !sb->s_root->d_inode) {
printk("coda_downcall: opcode %d, no sb!\n", opcode);
case CODA_ZAPDIR : {
struct inode *inode;
ViceFid *fid = &out->coda_zapdir.CodaFid;
- CDEBUG(D_DOWNCALL, "zapdir: fid = %s...\n", coda_f2s(fid));
+ CDEBUG(D_DOWNCALL, "zapdir: fid = %s...\n",
+ coda_f2s(fid));
clstats(CODA_ZAPDIR);
inode = coda_fid_to_inode(fid, sb);
coda_flag_inode_children(inode, C_PURGE);
CDEBUG(D_DOWNCALL, "zapdir: inode = %ld cache cleared\n", inode->i_ino);
coda_flag_inode(inode, C_VATTR);
+ iput(inode);
} else
CDEBUG(D_DOWNCALL, "zapdir: no inode\n");
struct inode *inode;
struct ViceFid *fid = &out->coda_zapfile.CodaFid;
clstats(CODA_ZAPFILE);
- CDEBUG(D_DOWNCALL, "zapfile: fid = %s\n", coda_f2s(fid));
+ CDEBUG(D_DOWNCALL, "zapfile: fid = %s\n",
+ coda_f2s(fid));
inode = coda_fid_to_inode(fid, sb);
if ( inode ) {
- CDEBUG(D_DOWNCALL, "zapfile: inode = %ld\n", inode->i_ino);
+ CDEBUG(D_DOWNCALL, "zapfile: inode = %ld\n",
+ inode->i_ino);
coda_flag_inode(inode, C_VATTR);
+ iput(inode);
} else
CDEBUG(D_DOWNCALL, "zapfile: no inode\n");
return 0;
case CODA_PURGEFID : {
struct inode *inode;
ViceFid *fid = &out->coda_purgefid.CodaFid;
- CDEBUG(D_DOWNCALL, "purgefid: fid = %s\n", coda_f2s(fid));
+ CDEBUG(D_DOWNCALL, "purgefid: fid = %s\n",
+ coda_f2s(fid));
clstats(CODA_PURGEFID);
inode = coda_fid_to_inode(fid, sb);
if ( inode ) {
- CDEBUG(D_DOWNCALL, "purgefid: inode = %ld\n", inode->i_ino);
+ CDEBUG(D_DOWNCALL, "purgefid: inode = %ld\n",
+ inode->i_ino);
coda_flag_inode_children(inode, C_PURGE);
coda_purge_dentries(inode);
+ iput(inode);
}else
CDEBUG(D_DOWNCALL, "purgefid: no inode\n");
return 0;
}
+ case CODA_MAKE_CINODE : {
+ struct inode *inode;
+ ViceFid *fid = &out->coda_make_cinode.CodaFid;
+ struct coda_vattr *attr = &out->coda_make_cinode.attr;
+ int fd = out->coda_make_cinode.fd;
+ struct file *file;
+ CDEBUG(D_DOWNCALL, "make_cinode: fid = %s, ino = %ld\n",
+ coda_f2s(fid), attr->va_fileid);
+
+ inode = coda_iget(sb, fid, attr);
+ if ( !inode ) {
+ CDEBUG(D_DOWNCALL, "make_cinode: no inode\n");
+ return -EINVAL;
+ }
+
+ file = fget(fd);
+ if ( !file ) {
+ CDEBUG(D_DOWNCALL, "make_cinode: no file\n");
+ iput(inode);
+ return -EINVAL;
+ }
+
+ inode->u.coda_i.c_ovp = file->f_dentry->d_inode;
+ inode->i_mapping = file->f_dentry->d_inode->i_mapping;
+ file->f_dentry->d_inode = inode;
+ file->f_op = &coda_file_operations;
+
+ /*
+ Unhash the dentry of the container file, as it is
+ still owned by the fs that stores the container
+ file. A more reliable solution would be to create
+ an new dentry owned by Coda, but that would require
+ knowledge of the internals of the dcache.
+ */
+ d_drop(file->f_dentry);
+
+ fput(file);
+ return 0;
+ }
+
case CODA_REPLACE : {
struct inode *inode;
ViceFid *oldfid = &out->coda_replace.OldFid;
if ( inode ) {
CDEBUG(D_DOWNCALL, "replacefid: inode = %ld\n", inode->i_ino);
coda_replace_fid(inode, oldfid, newfid);
+ iput(inode);
}else
CDEBUG(D_DOWNCALL, "purgefid: no inode\n");
return 0;
}
-
-
static struct super_operations cramfs_ops;
static struct inode_operations cramfs_file_inode_operations;
static struct inode_operations cramfs_dir_inode_operations;
-static struct inode_operations cramfs_symlink_inode_operations;
+static struct address_space_operations cramfs_aops;
/* These two macros may change in future, to provide better st_ino
semantics. */
result in GNU find, even
without -noleaf option. */
insert_inode_hash(inode);
- if (S_ISREG(inode->i_mode))
+ if (S_ISREG(inode->i_mode)) {
inode->i_op = &cramfs_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
+ inode->i_data.a_ops = &cramfs_aops;
+ } else if (S_ISDIR(inode->i_mode))
inode->i_op = &cramfs_dir_inode_operations;
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = &cramfs_symlink_inode_operations;
- else {
+ else if (S_ISLNK(inode->i_mode)) {
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_data.a_ops = &cramfs_aops;
+ } else {
inode->i_size = 0;
init_special_inode(inode, inode->i_mode, cramfs_inode->size);
}
return 0;
}
-static struct page *get_symlink_page(struct dentry *dentry)
-{
- return read_cache_page(&dentry->d_inode->i_data, 0, (filler_t *)cramfs_readpage, dentry);
-}
-
-static int cramfs_readlink(struct dentry *dentry, char *buffer, int len)
-{
- struct inode *inode = dentry->d_inode;
- int retval;
-
- if (!inode || !S_ISLNK(inode->i_mode))
- return -EBADF;
-
- retval = inode->i_size;
- if (retval) {
- int len;
- struct page *page = get_symlink_page(dentry);
-
- if (IS_ERR(page))
- return PTR_ERR(page);
- wait_on_page(page);
- len = retval;
- retval = -EIO;
- if (Page_Uptodate(page)) {
- retval = -EFAULT;
- if (!copy_to_user(buffer, (void *) page_address(page), len))
- retval = len;
- }
- page_cache_release(page);
- }
- return retval;
-}
-
-static struct dentry *cramfs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow)
-{
- struct page *page = get_symlink_page(dentry);
- struct dentry *result;
-
- if (IS_ERR(page)) {
- dput(base);
- return ERR_PTR(PTR_ERR(page));
- }
-
- result = lookup_dentry((void *) page_address(page), base, follow);
- page_cache_release(page);
- return result;
-}
+static struct address_space_operations cramfs_aops = {
+ readpage: cramfs_readpage
+};
/*
* Our operations:
static struct inode_operations cramfs_file_inode_operations = {
&cramfs_file_operations,
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- cramfs_readpage, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
static struct inode_operations cramfs_dir_inode_operations = {
&cramfs_directory_operations,
NULL, /* create */
cramfs_lookup, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
-};
-
-static struct inode_operations cramfs_symlink_inode_operations = {
- NULL, /* symlinks do not have files */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- cramfs_readlink, /* readlink */
- cramfs_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
static struct super_operations cramfs_ops = {
&devpts_root_operations, /* file operations */
NULL, /* create */
devpts_root_lookup, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
static struct dentry_operations devpts_dentry_operations = {
readdir: efs_readdir,
};
-extern int efs_get_block(struct inode *, long, struct buffer_head *, int);
-
struct inode_operations efs_dir_inode_operations = {
&efs_dir_operations, /* default directory file-ops */
NULL, /* create */
efs_lookup, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- efs_get_block, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) {
struct inode_operations efs_file_inode_operations = {
&efs_file_operations, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- efs_get_block, /* get_block */
- block_read_full_page, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
#include <linux/efs_fs.h>
#include <linux/efs_fs_sb.h>
+extern int efs_get_block(struct inode *, long, struct buffer_head *, int);
+static int efs_readpage(struct dentry *dentry, struct page *page)
+{
+ return block_read_full_page(page,efs_get_block);
+}
+static int _efs_bmap(struct address_space *mapping, long block)
+{
+ return generic_block_bmap(mapping,block,efs_get_block);
+}
+struct address_space_operations efs_aops = {
+ readpage: efs_readpage,
+ bmap: _efs_bmap
+};
+
static inline void extent_copy(efs_extent *src, efs_extent *dst) {
/*
* this is slightly evil. it doesn't just copy
break;
case S_IFREG:
inode->i_op = &efs_file_inode_operations;
+ inode->i_data.a_ops = &efs_aops;
break;
case S_IFLNK:
- inode->i_op = &efs_symlink_inode_operations;
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_data.a_ops = &efs_symlink_aops;
break;
case S_IFCHR:
case S_IFBLK:
return err;
}
-struct inode_operations efs_symlink_inode_operations = {
- readlink: page_readlink,
- follow_link: page_follow_link,
+struct address_space_operations efs_symlink_aops = {
readpage: efs_symlink_readpage
};
ext2_rmdir, /* rmdir */
ext2_mknod, /* mknod */
ext2_rename, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
int ext2_check_dir_entry (const char * function, struct inode * dir,
#include <linux/fs.h>
#include <linux/sched.h>
-
-
-#define NBUF 32
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
static loff_t ext2_file_lseek(struct file *, loff_t, int);
static int ext2_open_file (struct inode *, struct file *);
return offset;
}
-static inline void remove_suid(struct inode *inode)
-{
- unsigned int mode;
-
- /* set S_IGID if S_IXGRP is set, and always set S_ISUID */
- mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID;
-
- /* was any of the uid bits set? */
- mode &= inode->i_mode;
- if (mode && !capable(CAP_FSETID)) {
- inode->i_mode &= ~mode;
- mark_inode_dirty(inode);
- }
-}
-
-/*
- * Write to a file (through the page cache).
- */
-static ssize_t
-ext2_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
- ssize_t retval;
-
- retval = generic_file_write(file, buf, count,
- ppos, block_write_partial_page);
- if (retval > 0) {
- struct inode *inode = file->f_dentry->d_inode;
- remove_suid(inode);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
- mark_inode_dirty(inode);
- }
- return retval;
-}
-
/*
* Called when an inode is released. Note that this is different
* from ext2_file_open: open gets called at every open, but release
static struct file_operations ext2_file_operations = {
llseek: ext2_file_lseek,
read: generic_file_read,
- write: ext2_file_write,
+ write: generic_file_write,
ioctl: ext2_ioctl,
mmap: generic_file_mmap,
open: ext2_open_file,
};
struct inode_operations ext2_file_inode_operations = {
- &ext2_file_operations,/* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- ext2_get_block, /* get_block */
- block_read_full_page, /* readpage */
- block_write_full_page, /* writepage */
- ext2_truncate, /* truncate */
- NULL, /* permission */
- NULL, /* revalidate */
+ &ext2_file_operations,
+ truncate: ext2_truncate,
};
return result;
}
-int ext2_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
+static int ext2_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
{
int ret, err, new;
struct buffer_head *bh;
return NULL;
}
+static int ext2_writepage(struct dentry *dentry, struct page *page)
+{
+ return block_write_full_page(page,ext2_get_block);
+}
+static int ext2_readpage(struct dentry *dentry, struct page *page)
+{
+ return block_read_full_page(page,ext2_get_block);
+}
+static int ext2_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+ return block_prepare_write(page,from,to,ext2_get_block);
+}
+static int ext2_bmap(struct address_space *mapping, long block)
+{
+ return generic_block_bmap(mapping,block,ext2_get_block);
+}
+struct address_space_operations ext2_aops = {
+ readpage: ext2_readpage,
+ writepage: ext2_writepage,
+ prepare_write: ext2_prepare_write,
+ commit_write: generic_commit_write,
+ bmap: ext2_bmap
+};
+
void ext2_read_inode (struct inode * inode)
{
struct buffer_head * bh;
if (inode->i_ino == EXT2_ACL_IDX_INO ||
inode->i_ino == EXT2_ACL_DATA_INO)
/* Nothing to do */ ;
- else if (S_ISREG(inode->i_mode))
+ else if (S_ISREG(inode->i_mode)) {
inode->i_op = &ext2_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
+ inode->i_mapping->a_ops = &ext2_aops;
+ } else if (S_ISDIR(inode->i_mode))
inode->i_op = &ext2_dir_inode_operations;
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = inode->i_blocks
- ?&ext2_symlink_inode_operations
- :&ext2_fast_symlink_inode_operations;
- else
+ else if (S_ISLNK(inode->i_mode)) {
+ if (!inode->i_blocks)
+ inode->i_op = &ext2_fast_symlink_inode_operations;
+ else {
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_mapping->a_ops = &ext2_aops;
+ }
+ } else
init_special_inode(inode, inode->i_mode,
le32_to_cpu(raw_inode->i_block[0]));
brelse (bh);
return err;
inode->i_op = &ext2_file_inode_operations;
+ inode->i_mapping->a_ops = &ext2_aops;
inode->i_mode = mode;
mark_inode_dirty(inode);
bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
inode->i_mode = S_IFLNK | S_IRWXUGO;
if (l > sizeof (inode->u.ext2_i.i_data)) {
- inode->i_op = &ext2_symlink_inode_operations;
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_mapping->a_ops = &ext2_aops;
err = block_symlink(inode, symname, l);
if (err)
goto out_no_entry;
/*
* linux/fs/ext2/symlink.c
*
+ * Only fast symlinks left here - the rest is done by generic code. AV, 1999
+ *
* Copyright (C) 1992, 1993, 1994, 1995
* Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
*/
#include <linux/fs.h>
-#include <linux/ext2_fs.h>
static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
{
readlink: ext2_readlink,
follow_link: ext2_follow_link,
};
-
-struct inode_operations ext2_symlink_inode_operations = {
- readlink: page_readlink,
- follow_link: page_follow_link,
- get_block: ext2_get_block,
- readpage: block_read_full_page,
-};
return 0;
return sector+sb->dir_start;
}
- if (sector >= (MSDOS_I(inode)->i_realsize>>9))
+ if (sector >= MSDOS_I(inode)->mmu_private>>9)
return 0;
cluster = sector/sb->cluster_size;
offset = sector % sb->cluster_size;
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- fat_get_block, /* get_block */
- block_read_full_page, /* readpage */
- NULL, /* writepage */
fat_truncate, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
ssize_t fat_file_read(
}
if (!create)
return 0;
- if (iblock<<9 != MSDOS_I(inode)->i_realsize) {
+ if (iblock<<9 != MSDOS_I(inode)->mmu_private) {
BUG();
return -EIO;
}
if (fat_add_cluster(inode))
return -ENOSPC;
}
- MSDOS_I(inode)->i_realsize+=SECTOR_SIZE;
+ MSDOS_I(inode)->mmu_private += 512;
phys=fat_bmap(inode, iblock);
if (!phys)
BUG();
return 0;
}
-static int fat_write_partial_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
-{
- struct dentry *dentry = file->f_dentry;
- struct inode *inode = dentry->d_inode;
- struct page *new_page;
- unsigned long pgpos;
- long status;
-
- while((pgpos=MSDOS_I(inode)->i_realsize>>PAGE_CACHE_SHIFT)<page->index){
- status = -ENOMEM;
- new_page = grab_cache_page(&inode->i_data, pgpos);
- if (!new_page)
- goto out;
- status = block_write_cont_page(file, new_page, PAGE_SIZE, 0, NULL);
- UnlockPage(new_page);
- page_cache_release(new_page);
- if (status < 0)
- goto out;
- }
- status = block_write_cont_page(file, page, offset, bytes, buf);
-out:
- return status;
-}
-
ssize_t fat_file_write(
struct file *filp,
const char *buf,
struct inode *inode = filp->f_dentry->d_inode;
int retval;
- retval = generic_file_write(filp, buf, count, ppos,
- fat_write_partial_page);
+ retval = generic_file_write(filp, buf, count, ppos);
if (retval > 0) {
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
if (IS_IMMUTABLE(inode))
return /* -EPERM */;
cluster = SECTOR_SIZE*sbi->cluster_size;
- MSDOS_I(inode)->i_realsize = ((inode->i_size-1) | (SECTOR_SIZE-1)) + 1;
+ MSDOS_I(inode)->mmu_private = inode->i_size;
fat_free(inode,(inode->i_size+(cluster-1))>>sbi->cluster_bits);
MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
inode->i_ctime = inode->i_mtime = CURRENT_TIME;
((inode->i_size+inode->i_blksize-1)>>sbi->cluster_bits) *
sbi->cluster_size;
MSDOS_I(inode)->i_logstart = 0;
- MSDOS_I(inode)->i_realsize = inode->i_size;
+ MSDOS_I(inode)->mmu_private = inode->i_size;
MSDOS_I(inode)->i_attrs = 0;
inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
return 0;
}
+static int fat_writepage(struct dentry *dentry, struct page *page)
+{
+ return block_write_full_page(page,fat_get_block);
+}
+static int fat_readpage(struct dentry *dentry, struct page *page)
+{
+ return block_read_full_page(page,fat_get_block);
+}
+static int fat_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+ return cont_prepare_write(page,from,to,fat_get_block,
+ &MSDOS_I((struct inode*)page->mapping->host)->mmu_private);
+}
+static int _fat_bmap(struct address_space *mapping, long block)
+{
+ return generic_block_bmap(mapping,block,fat_get_block);
+}
+static struct address_space_operations fat_aops = {
+ readpage: fat_readpage,
+ writepage: fat_writepage,
+ prepare_write: fat_prepare_write,
+ commit_write: generic_commit_write,
+ bmap: _fat_bmap
+};
+
/* doesn't deal with root inode */
static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
{
break;
}
}
- MSDOS_I(inode)->i_realsize = inode->i_size;
+ MSDOS_I(inode)->mmu_private = inode->i_size;
} else { /* not a directory */
inode->i_mode = MSDOS_MKMODE(de->attr,
((IS_NOEXEC(inode) ||
!is_exec(de->ext)))
? S_IRUGO|S_IWUGO : S_IRWXUGO)
& ~sbi->options.fs_umask) | S_IFREG;
- inode->i_op = &fat_file_inode_operations;
MSDOS_I(inode)->i_start = CF_LE_W(de->start);
if (sbi->fat_bits == 32) {
MSDOS_I(inode)->i_start |=
MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start;
inode->i_nlink = 1;
inode->i_size = CF_LE_L(de->size);
- MSDOS_I(inode)->i_realsize = ((inode->i_size-1)|(SECTOR_SIZE-1))+1;
+ inode->i_op = &fat_file_inode_operations;
+ inode->i_mapping->a_ops = &fat_aops;
+ MSDOS_I(inode)->mmu_private = inode->i_size;
}
if(de->attr & ATTR_SYS)
if (sbi->options.sys_immutable)
~(SECTOR_SIZE-1);
}
inode->i_size += SECTOR_SIZE*cluster_size;
- MSDOS_I(inode)->i_realsize += SECTOR_SIZE*cluster_size;
+ MSDOS_I(inode)->mmu_private += SECTOR_SIZE*cluster_size;
mark_inode_dirty(inode);
return res;
}
hfs_rmdir, /* rmdir */
NULL, /* mknod */
hfs_rename, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
struct inode_operations hfs_cap_fdir_inode_operations = {
&hfs_cap_dir_operations,/* default directory file-ops */
NULL, /* create */
cap_lookup, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
struct inode_operations hfs_cap_rdir_inode_operations = {
&hfs_cap_dir_operations,/* default directory file-ops */
hfs_create, /* create */
cap_lookup, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
/*================ File-local functions ================*/
dbl_rmdir, /* rmdir */
NULL, /* mknod */
dbl_rename, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
nat_rmdir, /* rmdir */
NULL, /* mknod */
hfs_rename, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
struct inode_operations hfs_nat_hdir_inode_operations = {
NULL, /* rmdir */
NULL, /* mknod */
nat_hdr_rename, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
/*================ File-local functions ================*/
static hfs_rwret_t hfs_file_write(struct file *, const char *, hfs_rwarg_t,
loff_t *);
static void hfs_file_truncate(struct inode *);
-static int hfs_get_block(struct inode *, long, struct buffer_head *, int);
/*================ Global variables ================*/
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- hfs_get_block, /* get_block */
- block_read_full_page, /* readpage */
- NULL, /* writepage */
hfs_file_truncate, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
/*================ Variable-like macros ================*/
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block - none */
- NULL, /* readpage */
- NULL, /* writepage */
cap_info_truncate, /* truncate */
- NULL, /* permission */
- NULL /* revalidata */
};
/*================ File-local functions ================*/
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block - XXX: not available since
- header part has no disk block */
- NULL, /* readpage */
- NULL, /* writepage */
hdr_truncate, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
const struct hfs_hdr_layout hfs_dbl_fil_hdr_layout = {
extern void hfs_extent_adj(struct hfs_fork *);
extern void hfs_extent_free(struct hfs_fork *);
+/* file.c */
+extern int hfs_get_block(struct inode *, long, struct buffer_head *, int);
+
/* mdb.c */
extern struct hfs_mdb *hfs_mdb_get(hfs_sysmdb, int, hfs_s32);
extern void hfs_mdb_commit(struct hfs_mdb *, int);
return 0;
}
+static int hfs_writepage(struct dentry *dentry, struct page *page)
+{
+ return block_write_full_page(page,hfs_get_block);
+}
+static int hfs_readpage(struct dentry *dentry, struct page *page)
+{
+ return block_read_full_page(page,hfs_get_block);
+}
+static int hfs_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+ return cont_prepare_write(page,from,to,hfs_get_block,
+ &((struct inode*)page->mapping->host)->u.hfs_i.mmu_private);
+}
+static int hfs_bmap(struct address_space *mapping, long block)
+{
+ return generic_block_bmap(mapping,block,hfs_get_block);
+}
+struct address_space_operations hfs_aops = {
+ readpage: hfs_readpage,
+ writepage: hfs_writepage,
+ prepare_write: hfs_prepare_write,
+ commit_write: generic_commit_write,
+ bmap: hfs_bmap
+};
+
/*
* __hfs_iget()
*
init_file_inode(inode, (type == HFS_CAP_DATA) ?
HFS_FK_DATA : HFS_FK_RSRC);
inode->i_op = &hfs_file_inode_operations;
+ inode->i_mapping->a_ops = &hfs_aops;
+ inode->u.hfs_i.mmu_private = inode->i_size;
} else { /* Directory */
struct hfs_dir *hdir = &entry->u.dir;
} else if (entry->type == HFS_CDR_FIL) {
init_file_inode(inode, HFS_FK_DATA);
inode->i_op = &hfs_file_inode_operations;
+ inode->i_mapping->a_ops = &hfs_aops;
+ inode->u.hfs_i.mmu_private = inode->i_size;
} else { /* Directory */
struct hfs_dir *hdir = &entry->u.dir;
} else if (entry->type == HFS_CDR_FIL) {
init_file_inode(inode, HFS_FK_DATA);
inode->i_op = &hfs_file_inode_operations;
+ inode->i_mapping->a_ops = &hfs_aops;
+ inode->u.hfs_i.mmu_private = inode->i_size;
} else { /* Directory */
struct hfs_dir *hdir = &entry->u.dir;
if (!de->directory) {
if (result->i_size == -1) {
result->i_size = de->file_size;
+ result->i_data.a_ops = &hpfs_aops;
+ result->u.hpfs_i.mmu_private = result->i_size;
/*
* i_blocks should count the fnode and any anodes.
* We count 1 for the fnode and don't bother about
if (IS_IMMUTABLE(i)) return /*-EPERM*/;
i->i_hpfs_n_secs = 0;
i->i_blocks = 1 + ((i->i_size + 511) >> 9);
+ i->u.hpfs_i.mmu_private = i->i_size;
hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9));
hpfs_write_inode(i);
}
int hpfs_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
{
secno s;
- if (iblock < inode->i_blocks - 1) {
- s = hpfs_bmap(inode, iblock);
+ s = hpfs_bmap(inode, iblock);
+ if (s) {
bh_result->b_dev = inode->i_dev;
bh_result->b_blocknr = s;
bh_result->b_state |= (1UL << BH_Mapped);
return 0;
}
if (!create) return 0;
- if (iblock > inode->i_blocks - 1) {
- //hpfs_error(inode->i_sb, "hpfs_get_block beyond file end (requested %08x, inode size %08x", (int)iblock, (int)inode->i_blocks - 1);
- printk("HPFS: could not write beyond file end. This is known bug.\n");
- return -EFSERROR;
+ if (iblock<<9 != inode->u.hpfs_i.mmu_private) {
+ BUG();
+ return -EIO;
}
if ((s = hpfs_add_sector_to_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1)) == -1) {
hpfs_truncate_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1);
return -ENOSPC;
}
inode->i_blocks++;
+ inode->u.hpfs_i.mmu_private += 512;
bh_result->b_dev = inode->i_dev;
bh_result->b_blocknr = s;
bh_result->b_state |= (1UL << BH_Mapped) | (1UL << BH_New);
return 0;
}
-static int hpfs_write_partial_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+static int hpfs_writepage(struct dentry *dentry, struct page *page)
{
- struct dentry *dentry = file->f_dentry;
- struct inode *inode = dentry->d_inode;
- struct page *new_page;
- unsigned long pgpos;
- long status;
-
- pgpos = ((inode->i_blocks - 1) * 512) >> PAGE_CACHE_SHIFT;
- while (pgpos < page->index) {
- status = -ENOMEM;
- new_page = grab_cache_page(&inode->i_data, pgpos);
- if (!new_page)
- goto out;
- status = block_write_cont_page(file, new_page, PAGE_SIZE, 0, NULL);
- UnlockPage(new_page);
- page_cache_release(new_page);
- if (status < 0)
- goto out;
- pgpos = ((inode->i_blocks - 1) * 512) >> PAGE_CACHE_SHIFT;
- }
- status = block_write_cont_page(file, page, offset, bytes, buf);
-out:
- return status;
+ return block_write_full_page(page,hpfs_get_block);
}
-
+static int hpfs_readpage(struct dentry *dentry, struct page *page)
+{
+ return block_read_full_page(page,hpfs_get_block);
+}
+static int hpfs_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+ return cont_prepare_write(page,from,to,hpfs_get_block,
+ &((struct inode*)page->mapping->host)->u.hpfs_i.mmu_private);
+}
+static int _hpfs_bmap(struct address_space *mapping, long block)
+{
+ return generic_block_bmap(mapping,block,hpfs_get_block);
+}
+struct address_space_operations hpfs_aops = {
+ readpage: hpfs_readpage,
+ writepage: hpfs_writepage,
+ prepare_write: hpfs_prepare_write,
+ commit_write: generic_commit_write,
+ bmap: _hpfs_bmap
+};
ssize_t hpfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
ssize_t retval;
- retval = generic_file_write(file, buf, count,
- ppos, hpfs_write_partial_page);
+ retval = generic_file_write(file, buf, count, ppos);
if (retval > 0) {
struct inode *inode = file->f_dentry->d_inode;
inode->i_mtime = CURRENT_TIME;
unsigned hpfs_count_one_bitmap(struct super_block *, secno);
int hpfs_statfs(struct super_block *, struct statfs *, int);
struct super_block *hpfs_read_super(struct super_block *, void *, int);
+
+extern struct address_space_operations hpfs_aops;
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- &hpfs_get_block, /* get_block */
- block_read_full_page, /* readpage */
- block_write_full_page, /* writepage */
hpfs_truncate, /* truncate */
- NULL, /* permission */
- NULL, /* revalidate */
};
static const struct file_operations hpfs_dir_ops =
hpfs_rmdir, /* rmdir */
hpfs_mknod, /* mknod */
hpfs_rename, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
-const struct inode_operations hpfs_symlink_iops =
-{
- readlink: page_readlink,
- follow_link: page_follow_link,
+struct address_space_operations hpfs_symlink_aops = {
readpage: hpfs_symlink_readpage
};
if ((ea = hpfs_get_ea(i->i_sb, fnode, "SYMLINK", &ea_size))) {
kfree(ea);
i->i_mode = S_IFLNK | 0777;
- i->i_op = (struct inode_operations *) &hpfs_symlink_iops;
+ i->i_op = &page_symlink_inode_operations;
+ i->i_data.a_ops = &hpfs_symlink_aops;
i->i_nlink = 1;
i->i_size = ea_size;
i->i_blocks = 1;
i->i_nlink = 1;
i->i_size = fnode->file_size;
i->i_blocks = ((i->i_size + 511) >> 9) + 1;
+ i->i_data.a_ops = &hpfs_aops;
+ i->u.hpfs_i.mmu_private = i->i_size;
}
brelse(bh);
}
result->i_hpfs_ea_size = 0;
if (dee.read_only) result->i_mode &= ~0222;
if (result->i_blocks == -1) result->i_blocks = 1;
- if (result->i_size == -1) result->i_size = 0;
+ if (result->i_size == -1) {
+ result->i_size = 0;
+ result->i_data.a_ops = &hpfs_aops;
+ result->u.hpfs_i.mmu_private = 0;
+ }
if (result->i_uid != current->fsuid ||
result->i_gid != current->fsgid ||
result->i_mode != (mode | S_IFREG)) {
return -ENOSPC;
}
-extern const struct inode_operations hpfs_symlink_iops;
+extern struct address_space_operations hpfs_symlink_aops;
int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *symlink)
{
result->i_gid = current->fsgid;
result->i_blocks = 1;
result->i_size = strlen(symlink);
- result->i_op = (struct inode_operations *) &hpfs_symlink_iops;
+ result->i_op = &page_symlink_inode_operations;
+ result->i_data.a_ops = &hpfs_symlink_aops;
if ((fnode = hpfs_map_fnode(dir->i_sb, fno, &bh))) {
hpfs_set_ea(result, fnode, "SYMLINK", (char *)symlink, strlen(symlink));
mark_buffer_dirty(bh, 1);
memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
inode->i_pipe = NULL;
inode->i_bdev = NULL;
+ inode->i_mapping = &inode->i_data;
+ inode->i_mapping->host = (void*)inode;
}
/*
int bmap(struct inode * inode, int block)
{
- struct buffer_head tmp;
-
- if (inode->i_op && inode->i_op->get_block) {
- tmp.b_state = 0;
- tmp.b_blocknr = 0;
- inode->i_op->get_block(inode, block, &tmp, 0);
- return tmp.b_blocknr;
- }
- return 0;
+ int res = 0;
+ if (inode->i_mapping->a_ops->bmap)
+ res = inode->i_mapping->a_ops->bmap(inode->i_mapping, block);
+ return res;
}
/*
switch (cmd) {
case FIBMAP:
{
- struct buffer_head tmp;
-
- if (inode->i_op == NULL)
- return -EBADF;
- if (inode->i_op->get_block == NULL)
+ struct address_space *mapping = inode->i_mapping;
+ int res;
+ /* do we support this mess? */
+ if (!mapping->a_ops->bmap)
return -EINVAL;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
if ((error = get_user(block, (int *) arg)) != 0)
return error;
- tmp.b_state = 0;
- tmp.b_blocknr = 0;
- inode->i_op->get_block(inode, block, &tmp, 0);
- return put_user(tmp.b_blocknr, (int *) arg);
+ res = mapping->a_ops->bmap(mapping, block);
+ return put_user(res, (int *) arg);
}
case FIGETBSZ:
if (inode->i_sb == NULL)
# Note 2! The CFLAGS definitions are now in the main makefile.
O_TARGET := isofs.o
-O_OBJS := namei.o inode.o file.o dir.o util.o rock.o symlink.o
+O_OBJS := namei.o inode.o file.o dir.o util.o rock.o
ifdef CONFIG_JOLIET
O_OBJS += joliet.o
&isofs_dir_operations, /* default directory file-ops */
NULL, /* create */
isofs_lookup, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
static int isofs_name_translate(char * old, int len, char * new)
struct inode_operations isofs_file_inode_operations = {
&isofs_file_operations, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- isofs_get_block, /* get_block */
- block_read_full_page, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
return 0;
}
+static int isofs_readpage(struct dentry *dentry, struct page *page)
+{
+ return block_read_full_page(page,isofs_get_block);
+}
+static int _isofs_bmap(struct address_space *mapping, long block)
+{
+ return generic_block_bmap(mapping,block,isofs_get_block);
+}
+static struct address_space_operations isofs_aops = {
+ readpage: isofs_readpage,
+ bmap: _isofs_bmap
+};
+
static void test_and_set_uid(uid_t *p, uid_t value)
{
if(value) {
} else
#endif IGNORE_WRONG_MULTI_VOLUME_SPECS
{
- if (S_ISREG(inode->i_mode))
+ if (S_ISREG(inode->i_mode)) {
inode->i_op = &isofs_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
+ inode->i_data.a_ops = &isofs_aops;
+ } else if (S_ISDIR(inode->i_mode))
inode->i_op = &isofs_dir_inode_operations;
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = &isofs_symlink_inode_operations;
- else
+ else if (S_ISLNK(inode->i_mode)) {
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_data.a_ops = &isofs_symlink_aops;
+ } else
/* XXX - parse_rock_ridge_inode() had already set i_rdev. */
init_special_inode(inode, inode->i_mode, kdev_t_to_nr(inode->i_rdev));
}
/* readpage() for symlinks: reads symlink contents into the page and either
makes it uptodate and returns 0 or returns error (-EIO) */
-int rock_ridge_symlink_readpage(struct dentry *dentry, struct page *page)
+static int rock_ridge_symlink_readpage(struct dentry *dentry, struct page *page)
{
struct inode *inode = dentry->d_inode;
char *link = (char*)kmap(page);
UnlockPage(page);
return -EIO;
}
+
+struct address_space_operations isofs_symlink_aops = {
+ readpage: rock_ridge_symlink_readpage
+};
+++ /dev/null
-/*
- * linux/fs/isofs/symlink.c
- *
- * (C) 1992 Eric Youngdale Modified for ISO 9660 filesystem.
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * isofs symlink handling code. This is only used with the Rock Ridge
- * extensions to iso9660
- */
-
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/iso_fs.h>
-#include <linux/stat.h>
-#include <linux/malloc.h>
-
-/*
- * symlinks can't do much...
- */
-struct inode_operations isofs_symlink_inode_operations = {
- readlink: page_readlink,
- follow_link: page_follow_link,
- readpage: rock_ridge_symlink_readpage
-};
#ifdef MODULE
/* New module support in 2.1.18 */
-#if LINUX_VERSION_CODE >= 0x020112
- EXPORT_NO_SYMBOLS;
- MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
- MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION ".");
- MODULE_PARM(nlm_grace_period, "10-240l");
- MODULE_PARM(nlm_timeout, "3-20l");
-#endif
+
+EXPORT_NO_SYMBOLS;
+MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
+MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION ".");
+MODULE_PARM(nlm_grace_period, "10-240l");
+MODULE_PARM(nlm_timeout, "3-20l");
+
int
init_module(void)
{
# Note 2! The CFLAGS definitions are now in the main makefile.
O_TARGET := minix.o
-O_OBJS := bitmap.o truncate.o namei.o inode.o file.o dir.o symlink.o fsync.o
+O_OBJS := bitmap.o truncate.o namei.o inode.o file.o dir.o fsync.o
M_OBJS := $(O_TARGET)
include $(TOPDIR)/Rules.make
minix_rmdir, /* rmdir */
minix_mknod, /* mknod */
minix_rename, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
static int minix_readdir(struct file * filp,
#include <asm/uaccess.h>
#include <asm/system.h>
-#define NBUF 32
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
#include <linux/fs.h>
#include <linux/minix_fs.h>
-/*
- * Write to a file (through the page cache).
- */
-static ssize_t
-minix_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
- return generic_file_write(file, buf, count,
- ppos, block_write_partial_page);
-}
-
/*
* We have mostly NULLs here: the current defaults are OK for
* the minix filesystem.
*/
static struct file_operations minix_file_operations = {
read: generic_file_read,
- write: minix_file_write,
+ write: generic_file_write,
mmap: generic_file_mmap,
fsync: minix_sync_file,
};
struct inode_operations minix_file_inode_operations = {
- &minix_file_operations, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- minix_get_block, /* get_block */
- block_read_full_page, /* readpage */
- block_write_full_page, /* writepage */
- minix_truncate, /* truncate */
- NULL, /* permission */
- NULL, /* revalidate */
+ &minix_file_operations,
+ truncate: minix_truncate,
};
goto abort;
}
-int minix_get_block(struct inode *inode, long block,
+static int minix_get_block(struct inode *inode, long block,
struct buffer_head *bh_result, int create)
{
if (INODE_VERSION(inode) == MINIX_V1)
return NULL;
}
+static int minix_writepage(struct dentry *dentry, struct page *page)
+{
+ return block_write_full_page(page,minix_get_block);
+}
+static int minix_readpage(struct dentry *dentry, struct page *page)
+{
+ return block_read_full_page(page,minix_get_block);
+}
+static int minix_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+ return block_prepare_write(page,from,to,minix_get_block);
+}
+static int minix_bmap(struct address_space *mapping, long block)
+{
+ return generic_block_bmap(mapping,block,minix_get_block);
+}
+struct address_space_operations minix_aops = {
+ readpage: minix_readpage,
+ writepage: minix_writepage,
+ prepare_write: minix_prepare_write,
+ commit_write: generic_commit_write,
+ bmap: minix_bmap
+};
+
/*
* The minix V1 function to read an inode.
*/
inode->i_blocks = inode->i_blksize = 0;
for (block = 0; block < 9; block++)
inode->u.minix_i.u.i1_data[block] = raw_inode->i_zone[block];
- if (S_ISREG(inode->i_mode))
+ if (S_ISREG(inode->i_mode)) {
inode->i_op = &minix_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
+ inode->i_mapping->a_ops = &minix_aops;
+ } else if (S_ISDIR(inode->i_mode))
inode->i_op = &minix_dir_inode_operations;
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = &minix_symlink_inode_operations;
- else
+ else if (S_ISLNK(inode->i_mode)) {
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_mapping->a_ops = &minix_aops;
+ } else
init_special_inode(inode, inode->i_mode, raw_inode->i_zone[0]);
brelse(bh);
}
inode->i_blocks = inode->i_blksize = 0;
for (block = 0; block < 10; block++)
inode->u.minix_i.u.i2_data[block] = raw_inode->i_zone[block];
- if (S_ISREG(inode->i_mode))
+ if (S_ISREG(inode->i_mode)) {
inode->i_op = &minix_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
+ inode->i_mapping->a_ops = &minix_aops;
+ } else if (S_ISDIR(inode->i_mode))
inode->i_op = &minix_dir_inode_operations;
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = &minix_symlink_inode_operations;
- else
+ else if (S_ISLNK(inode->i_mode)) {
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_mapping->a_ops = &minix_aops;
+ } else
init_special_inode(inode, inode->i_mode, raw_inode->i_zone[0]);
brelse(bh);
}
if (!inode)
return -ENOSPC;
inode->i_op = &minix_file_inode_operations;
+ inode->i_mapping->a_ops = &minix_aops;
inode->i_mode = mode;
mark_inode_dirty(inode);
error = minix_add_entry(dir, dentry->d_name.name,
goto out;
inode->i_mode = S_IFLNK | 0777;
- inode->i_op = &minix_symlink_inode_operations;
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_mapping->a_ops = &minix_aops;
err = block_symlink(inode, symname, i);
if (err)
goto fail;
+++ /dev/null
-/*
- * linux/fs/minix/symlink.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * minix symlink handling code
- *
- * Code removed. 1999, AV ;-)
- */
-
-#include <linux/fs.h>
-#include <linux/minix_fs.h>
-
-/*
- * symlinks can't do much...
- */
-struct inode_operations minix_symlink_inode_operations = {
- readlink: page_readlink,
- follow_link: page_follow_link,
- get_block: minix_get_block,
- readpage: block_read_full_page
-};
msdos_rmdir, /* rmdir */
NULL, /* mknod */
msdos_rename, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* revalidate */
};
static void msdos_put_super_callback(struct super_block *sb)
static char *page_getlink(struct dentry * dentry, struct page **ppage)
{
struct page * page;
- page = read_cache_page(&dentry->d_inode->i_data, 0,
- (filler_t *)dentry->d_inode->i_op->readpage,
+ struct address_space *mapping = dentry->d_inode->i_mapping;
+ page = read_cache_page(mapping, 0, (filler_t *)mapping->a_ops->readpage,
dentry);
if (IS_ERR(page))
goto sync_fail;
}
return res;
}
+
+struct inode_operations page_symlink_inode_operations = {
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+};
ncp_rename, /* rename */
NULL, /* readlink */
NULL, /* follow link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
NULL, /* truncate */
NULL, /* permission */
NULL, /* revalidate */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
NULL, /* truncate */
NULL, /* permission */
NULL /* revalidate */
extern struct dentry_operations ncp_dentry_operations;
#ifdef CONFIG_NCPFS_EXTRAS
-extern struct inode_operations ncp_symlink_inode_operations;
+extern struct address_space_operations ncp_symlink_aops;
extern int ncp_symlink(struct inode*, struct dentry*, const char*);
#endif
inode->i_op = &ncp_dir_inode_operations;
#ifdef CONFIG_NCPFS_EXTRAS
} else if (S_ISLNK(inode->i_mode)) {
- inode->i_op = &ncp_symlink_inode_operations;
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_data.a_ops = &ncp_symlink_aops;
#endif
}
insert_inode_hash(inode);
/*
* symlinks can't do much...
*/
-struct inode_operations ncp_symlink_inode_operations={
- readlink: page_readlink,
- follow_link: page_follow_link,
+struct address_space_operations ncp_symlink_aops = {
readpage: ncp_symlink_readpage,
};
nfs_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
NULL, /* truncate */
NULL, /* permission */
nfs_revalidate, /* revalidate */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block */
- nfs_readpage, /* readpage */
- nfs_writepage, /* writepage */
NULL, /* truncate */
NULL, /* permission */
nfs_revalidate, /* revalidate */
* If the writer ends up delaying the write, the writer needs to
* increment the page use counts until he is done with the page.
*/
-static int nfs_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+static int nfs_prepare_write(struct page *page, unsigned offset, unsigned to)
+{
+ kmap(page);
+ return 0;
+}
+static int nfs_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
{
long status;
- bytes -= copy_from_user((u8*)kmap(page) + offset, buf, bytes);
kunmap(page);
- status = -EFAULT;
- if (bytes) {
- lock_kernel();
- status = nfs_updatepage(file, page, offset, bytes);
- unlock_kernel();
- }
+ lock_kernel();
+ status = nfs_updatepage(file, page, offset, to-offset);
+ unlock_kernel();
return status;
}
+struct address_space_operations nfs_file_aops = {
+ readpage: nfs_readpage,
+ writepage: nfs_writepage,
+ prepare_write: nfs_prepare_write,
+ commit_write: nfs_commit_write
+};
+
/*
* Write to a file (through the page cache).
*/
if (!count)
goto out;
- result = generic_file_write(file, buf, count, ppos, nfs_write_one_page);
+ result = generic_file_write(file, buf, count, ppos);
out:
return result;
NFS_FILEID(inode) = fattr->fileid;
NFS_FSID(inode) = fattr->fsid;
inode->i_mode = fattr->mode;
- if (S_ISREG(inode->i_mode))
+ if (S_ISREG(inode->i_mode)) {
inode->i_op = &nfs_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
+ inode->i_data.a_ops = &nfs_file_aops;
+ } else if (S_ISDIR(inode->i_mode))
inode->i_op = &nfs_dir_inode_operations;
else if (S_ISLNK(inode->i_mode))
inode->i_op = &nfs_symlink_inode_operations;
if (req->wb_bytes == PAGE_SIZE)
SetPageUptodate(page);
- retval = count;
+ retval = 0;
if (synchronous) {
int status = wait_on_write_request(req);
if (status) {
#include <linux/nfsd/xdr.h>
#include <linux/nfsd/syscall.h>
-#if LINUX_VERSION_CODE >= 0x020100
#include <asm/uaccess.h>
-#else
-# define copy_from_user memcpy_fromfs
-# define copy_to_user memcpy_tofs
-# define access_ok !verify_area
-#endif
#include <linux/smp.h>
#include <linux/smp_lock.h>
#ifdef MODULE
/* New-style module support since 2.1.18 */
-#if LINUX_VERSION_CODE >= 131346
EXPORT_NO_SYMBOLS;
MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
-#endif
extern int (*do_nfsservctl)(int, void *, void *);
#include <linux/nfsd/nfsfh.h>
#include <linux/quotaops.h>
-#if LINUX_VERSION_CODE >= 0x020100
#include <asm/uaccess.h>
-#endif
#define NFSDDBG_FACILITY NFSDDBG_FILEOP
#define NFSD_PARANOIA
static struct inode_operations ntfs_inode_operations_nobmap = {
&ntfs_file_operations_nommap,
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* revalidate */
};
#ifdef CONFIG_NTFS_RW
return (ret==-1) ? 0:ret;
}
+/* It's fscking broken. */
+
+static int ntfs_get_block(struct inode *inode, long block, struct buffer_head *bh, int create)
+{
+ BUG();
+ return -1;
+}
+
static struct file_operations ntfs_file_operations = {
read: ntfs_read,
mmap: generic_file_mmap,
static struct inode_operations ntfs_inode_operations = {
&ntfs_file_operations,
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- ntfs_bmap, /* get_block */
- block_read_full_page, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* revalidate */
};
static struct file_operations ntfs_dir_operations = {
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* revalidate */
};
+static int ntfs_writepage(struct dentry *dentry, struct page *page)
+{
+ return block_write_full_page(page,ntfs_get_block);
+}
+static int ntfs_readpage(struct dentry *dentry, struct page *page)
+{
+ return block_read_full_page(page,ntfs_get_block);
+}
+static int ntfs_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+ return cont_prepare_write(page,from,to,ntfs_get_block,
+ &((struct inode*)page->mapping->host)->u.ntfs_i.mmu_private);
+}
+static int _ntfs_bmap(struct address_space *mapping, long block)
+{
+ return generic_block_bmap(mapping,block,ntfs_get_block);
+}
+struct address_space_operations ntfs_aops = {
+ readpage: ntfs_readpage,
+ writepage: ntfs_writepage,
+ prepare_write: ntfs_prepare_write,
+ commit_write: generic_commit_write,
+ bmap: _ntfs_bmap
+};
/* ntfs_read_inode is called by the Virtual File System (the kernel layer that
* deals with filesystems) when iget is called requesting an inode not already
* present in the inode table. Typically filesystems have separate
}
else
{
- inode->i_op=can_mmap ? &ntfs_inode_operations :
- &ntfs_inode_operations_nobmap;
+ if (can_mmap) {
+ inode->i_op = &ntfs_inode_operations;
+ inode->i_mapping->a_ops = &ntfs_aops;
+ inode->u.ntfs_i.mmu_private = inode->i_size;
+ } else {
+ inode->i_op=&ntfs_inode_operations_nobmap;
+ }
inode->i_mode=S_IFREG|S_IRUGO;
}
#ifdef CONFIG_NTFS_RW
*/
asmlinkage long sys_vhangup(void)
{
- int ret = -EPERM;
-
- if (!capable(CAP_SYS_TTY_CONFIG))
- goto out;
- /* If there is a controlling tty, hang it up */
- lock_kernel();
- if (current->tty)
+ if (capable(CAP_SYS_TTY_CONFIG)) {
tty_vhangup(current->tty);
- unlock_kernel();
- ret = 0;
-out:
- return ret;
+ return 0;
+ }
+ return -EPERM;
}
openpromfs_lookup, /* lookup */
NULL, /* link */
openpromfs_unlink, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
extern struct inode_operations openprom_inode_operations;
TASK_INTERRUPTIBLE |
TASK_UNINTERRUPTIBLE |
TASK_ZOMBIE |
- TASK_STOPPED |
- TASK_SWAPPING);
+ TASK_STOPPED);
const char **p = &task_state_array[0];
while (state) {
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
NULL, /* truncate */
proc_permission, /* permission */
NULL /* revalidate */
}
static struct inode_operations proc_pid_link_inode_operations = {
- NULL, /* file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- proc_pid_readlink, /* readlink */
- proc_pid_follow_link, /* follow_link */
+ readlink: proc_pid_readlink,
+ follow_link: proc_pid_follow_link
};
/* reading from directory - bad */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
NULL, /* truncate */
proc_permission, /* permission */
};
# Note 2! The CFLAGS definitions are now in the main makefile...
O_TARGET := qnx4.o
-O_OBJS := inode.o dir.o namei.o file.o bitmap.o symlinks.o truncate.o \
-fsync.o
+O_OBJS := inode.o dir.o namei.o file.o bitmap.o truncate.o fsync.o
M_OBJS := $(O_TARGET)
include $(TOPDIR)/Rules.make
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/qnx4_fs.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/malloc.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
-
-#ifdef CONFIG_QNX4FS_RW
-static ssize_t qnx4_file_write(struct file *filp, const char *buf,
- size_t count, loff_t * ppos)
-{
- struct dentry *dentry = filp->f_dentry;
- struct inode *inode = dentry->d_inode;
- struct qnx4_inode_info *qnx4_ino;
- struct buffer_head *bh;
- ssize_t result = -EBUSY, c;
- off_t pos;
- unsigned long start, block, extent_end;
- char *p;
-
- QNX4DEBUG(("qnx4: file_write(%s/%s (%d), %lu@%lu)\n",
- dentry->d_parent->d_name.name, dentry->d_name.name,
- inode->i_count, (unsigned long) count, (unsigned long) *ppos));
- if (inode == NULL) {
- printk("qnx4: NULL inode for file_write\n");
- return -EINVAL;
- }
- qnx4_ino = &inode->u.qnx4_i;
- if (S_ISREG(inode->i_mode) == 0) {
- printk("qnx4: write to non-file, mode %07o\n", inode->i_mode);
- return -EINVAL;
- }
- if (count == 0) {
- goto out;
- }
- if (filp->f_flags & O_APPEND) {
- pos = inode->i_size;
- } else {
- pos = *ppos;
- }
- start = qnx4_ino->i_first_xtnt.xtnt_blk + ((pos >> 9) * 0) - 1;
- result = 0;
- extent_end = start + qnx4_ino->i_first_xtnt.xtnt_size - 1;
- QNX4DEBUG(("qnx4: extent length : [%lu] bytes\n",
- qnx4_ino->i_first_xtnt.xtnt_size));
- while (result < count) {
- block = start + pos / QNX4_BLOCK_SIZE;
- if (block > extent_end) {
- if (qnx4_is_free(inode->i_sb, block) <= 0) {
- printk("qnx4: next inode is busy -> write aborted.\n");
- result = -ENOSPC;
- break;
- }
- }
- if ((bh = bread(inode->i_dev, block,
- QNX4_BLOCK_SIZE)) == NULL) {
- printk("qnx4: I/O error on write.\n");
- result = -EIO;
- goto out;
- }
- if (bh == NULL) {
- if (result != 0) {
- result = -ENOSPC;
- }
- break;
- }
- if (block > extent_end) {
- qnx4_set_bitmap(inode->i_sb, block, 1);
- extent_end++;
- qnx4_ino->i_first_xtnt.xtnt_size = extent_end - start + 1;
- }
- c = QNX4_BLOCK_SIZE - (pos % QNX4_BLOCK_SIZE);
- if (c > count - result) {
- c = count - result;
- }
- if (c != QNX4_BLOCK_SIZE && buffer_uptodate(bh) == 0) {
- ll_rw_block(WRITE, 1, &bh);
- wait_on_buffer(bh);
- if (buffer_uptodate(bh) == 0) {
- brelse(bh);
- if (result != 0) {
- result = -EIO;
- }
- break;
- }
- }
- p = bh->b_data + (pos % QNX4_BLOCK_SIZE);
- c -= copy_from_user(p, buf, c);
- if (c == 0) {
- brelse(bh);
- if (result == 0) {
- result = -EFAULT;
- }
- break;
- }
-// update_vm_cache(inode, pos, p, c);
- mark_buffer_uptodate(bh, 1);
- mark_buffer_dirty(bh, 0);
- brelse(bh);
- pos += c;
- buf += c;
- result += c;
- }
- if (pos > inode->i_size) {
- inode->i_size = pos;
- }
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- *ppos = pos;
- mark_inode_dirty(inode);
-
- out:
- return result;
-}
-#endif
/*
* We have mostly NULL's here: the current defaults are ok for
{
read: generic_file_read,
#ifdef CONFIG_QNX4FS_RW
- write: qnx4_file_write,
+ write: generic_file_write,
#endif
mmap: generic_file_mmap,
#ifdef CONFIG_QNX4FS_RW
struct inode_operations qnx4_file_inode_operations =
{
default_file_ops: &qnx4_file_operations,
- get_block: qnx4_get_block,
- readpage: block_read_full_page,
#ifdef CONFIG_QNX4FS_RW
- writepage: block_write_full_page,
truncate: qnx4_truncate,
#endif
};
return;
}
+static int qnx4_writepage(struct dentry *dentry, struct page *page)
+{
+ return block_write_full_page(page,qnx4_get_block);
+}
+static int qnx4_readpage(struct dentry *dentry, struct page *page)
+{
+ return block_read_full_page(page,qnx4_get_block);
+}
+static int qnx4_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+ return cont_prepare_write(page,from,to,qnx4_get_block,
+ &((struct inode*)page->mapping->host)->u.qnx4_i.mmu_private);
+}
+static int qnx4_bmap(struct address_space *mapping, long block)
+{
+ return generic_block_bmap(mapping,block,qnx4_get_block);
+}
+struct address_space_operations qnx4_aops = {
+ readpage: qnx4_readpage,
+ writepage: qnx4_writepage,
+ prepare_write: qnx4_prepare_write,
+ commit_write: generic_commit_write,
+ bmap: qnx4_bmap
+};
+
static void qnx4_read_inode(struct inode *inode)
{
struct buffer_head *bh;
inode->i_blksize = QNX4_DIR_ENTRY_SIZE;
memcpy(&inode->u.qnx4_i, (struct qnx4_inode_info *) raw_inode, QNX4_DIR_ENTRY_SIZE);
- inode->i_op = &qnx4_file_inode_operations;
- if (S_ISREG(inode->i_mode))
+ if (S_ISREG(inode->i_mode)) {
inode->i_op = &qnx4_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
+ inode->i_mapping->a_ops = &qnx4_aops;
+ inode->u.qnx4_i.mmu_private = inode->i_size;
+ } else if (S_ISDIR(inode->i_mode))
inode->i_op = &qnx4_dir_inode_operations;
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = &qnx4_symlink_inode_operations;
- else
+ else if (S_ISLNK(inode->i_mode)) {
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_mapping->a_ops = &qnx4_aops;
+ inode->u.qnx4_i.mmu_private = inode->i_size;
+ } else
/* HUH??? Where is device number? Oh, well... */
init_special_inode(inode, inode->i_mode, 0);
+++ /dev/null
-/*
- * QNX4 file system, Linux implementation.
- *
- * Version : 0.2.1
- *
- * Using parts of the xiafs filesystem.
- *
- * History :
- *
- * 28-05-1998 by Richard Frowijn : first release.
- * 21-06-1998 by Frank Denis : ugly changes to make it compile on Linux 2.1.99+
- */
-
-#include <linux/fs.h>
-#include <linux/qnx4_fs.h>
-
-/*
- * symlinks can't do much...
- */
-struct inode_operations qnx4_symlink_inode_operations =
-{
- readlink: page_readlink,
- follow_link: page_follow_link,
- get_block: qnx4_get_block,
- readpage: block_read_full_page,
-};
/* Mapping from our types to the kernel */
+static struct address_space_operations romfs_aops = {
+ readpage: romfs_readpage
+};
+
static struct file_operations romfs_file_operations = {
read: generic_file_read,
mmap: generic_file_mmap,
static struct inode_operations romfs_file_inode_operations = {
&romfs_file_operations,
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block -- not really */
- romfs_readpage, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
static struct file_operations romfs_dir_operations = {
&romfs_dir_operations,
NULL, /* create */
romfs_lookup, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
-};
-
-static struct inode_operations romfs_link_inode_operations = {
- readlink: page_readlink,
- follow_link: page_follow_link,
- readpage: romfs_readpage
};
static mode_t romfs_modemap[] =
NULL, /* hardlink, handled elsewhere */
&romfs_dir_inode_operations,
&romfs_file_inode_operations,
- &romfs_link_inode_operations,
+ &page_symlink_inode_operations,
NULL, /* device/fifo/socket nodes, */
NULL, /* set by init_special_inode */
NULL,
i->i_mode = ino;
if (S_ISDIR(ino))
i->i_size = i->u.romfs_i.i_metasize;
+ else
+ i->i_data.a_ops = &romfs_aops;
} else {
/* depending on MBZ for sock/fifos */
nextfh = ntohl(ri.spec);
smb_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
NULL, /* truncate */
NULL, /* permission */
smb_revalidate_inode, /* revalidate */
* If the writer ends up delaying the write, the writer needs to
* increment the page use counts until he is done with the page.
*/
-static int smb_write_one_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+static int smb_prepare_write(struct page *page, unsigned offset, unsigned to)
+{
+ kmap(page);
+ return 0;
+}
+
+static int smb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
{
int status;
- bytes -= copy_from_user((u8*)page_address(page) + offset, buf, bytes);
status = -EFAULT;
- if (bytes) {
- lock_kernel();
- status = smb_updatepage(file, page, offset, bytes);
- unlock_kernel();
- }
+ lock_kernel();
+ status = smb_updatepage(file, page, offset, to-offset);
+ unlock_kernel();
+ kunmap(page);
return status;
}
+struct address_space_operations smb_file_aops = {
+ readpage: smb_readpage,
+ writepage: smb_writepage,
+ prepare_write: smb_prepare_write,
+ commit_write: smb_commit_write
+};
+
/*
* Write to a file (through the page cache).
*/
if (count > 0)
{
- result = generic_file_write(file, buf, count, ppos, smb_write_one_page);
+ result = generic_file_write(file, buf, count, ppos);
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_file_write: pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
(long) file->f_pos, dentry->d_inode->i_size, dentry->d_inode->i_mtime,
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block */
- smb_readpage, /* readpage */
- smb_writepage, /* writepage */
NULL, /* truncate */
smb_file_permission, /* permission */
smb_revalidate_inode, /* revalidate */
result->i_ino = fattr->f_ino;
memset(&(result->u.smbfs_i), 0, sizeof(result->u.smbfs_i));
smb_set_inode_attr(result, fattr);
- if (S_ISREG(result->i_mode))
+ if (S_ISREG(result->i_mode)) {
result->i_op = &smb_file_inode_operations;
- else if (S_ISDIR(result->i_mode))
+ result->i_data.a_ops = &smb_file_aops;
+ } else if (S_ISDIR(result->i_mode))
result->i_op = &smb_dir_inode_operations;
else
result->i_op = NULL;
# Note 2! The CFLAGS definitions are now in the main makefile.
O_TARGET := sysv.o
-O_OBJS := ialloc.o balloc.o inode.o file.o dir.o symlink.o namei.o \
- fsync.o truncate.o
+O_OBJS := ialloc.o balloc.o inode.o file.o dir.o namei.o fsync.o truncate.o
M_OBJS := $(O_TARGET)
include $(TOPDIR)/Rules.make
sysv_rmdir, /* rmdir */
sysv_mknod, /* mknod */
sysv_rename, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
#include <linux/locks.h>
#include <linux/pagemap.h>
-#include <asm/uaccess.h>
-
-#define NBUF 32
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
-/*
- * Write to a file (through the page cache).
- */
-static ssize_t
-sysv_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
- return generic_file_write(file, buf, count,
- ppos, block_write_partial_page);
-}
-
/*
* We have mostly NULLs here: the current defaults are OK for
* the coh filesystem.
*/
static struct file_operations sysv_file_operations = {
read: generic_file_read,
- write: sysv_file_write,
+ write: generic_file_write,
mmap: generic_file_mmap,
fsync: sysv_sync_file,
};
struct inode_operations sysv_file_inode_operations = {
- &sysv_file_operations, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- sysv_get_block, /* get_block */
- block_read_full_page, /* readpage */
- block_write_full_page, /* writepage */
- sysv_truncate, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
+ &sysv_file_operations,
+ truncate: sysv_truncate,
};
#include <linux/errno.h>
#include <linux/stat.h>
-#include <linux/smp_lock.h>
-
#include <linux/fs.h>
#include <linux/sysv_fs.h>
+#include <linux/smp_lock.h>
/* return values: 0 means OK/done, 1 means redo, -1 means I/O error. */
return result;
}
-int sysv_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
+static int sysv_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
{
struct super_block *sb;
int ret, err, new;
return NULL;
}
+static int sysv_writepage(struct dentry *dentry, struct page *page)
+{
+ return block_write_full_page(page,sysv_get_block);
+}
+static int sysv_readpage(struct dentry *dentry, struct page *page)
+{
+ return block_read_full_page(page,sysv_get_block);
+}
+static int sysv_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+ return block_prepare_write(page,from,to,sysv_get_block);
+}
+static int sysv_bmap(struct address_space *mapping, long block)
+{
+ return generic_block_bmap(mapping,block,sysv_get_block);
+}
+struct address_space_operations sysv_aops = {
+ readpage: sysv_readpage,
+ writepage: sysv_writepage,
+ prepare_write: sysv_prepare_write,
+ commit_write: generic_commit_write,
+ bmap: sysv_bmap
+};
+
#ifdef __BIG_ENDIAN
static inline unsigned long read3byte (unsigned char * p)
for (block = 0; block < 10+1+1+1; block++)
inode->u.sysv_i.i_data[block] =
read3byte(&raw_inode->i_a.i_addb[3*block]);
- if (S_ISREG(inode->i_mode))
+ if (S_ISREG(inode->i_mode)) {
inode->i_op = &sysv_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
+ inode->i_mapping->a_ops = &sysv_aops;
+ } else if (S_ISDIR(inode->i_mode))
inode->i_op = &sysv_dir_inode_operations;
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = &sysv_symlink_inode_operations;
- else
+ else if (S_ISLNK(inode->i_mode)) {
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_mapping->a_ops = &sysv_aops;
+ } else
init_special_inode(inode, inode->i_mode,raw_inode->i_a.i_rdev);
brelse(bh);
}
if (!inode)
return -ENOSPC;
inode->i_op = &sysv_file_inode_operations;
+ inode->i_mapping->a_ops = &sysv_aops;
inode->i_mode = mode;
mark_inode_dirty(inode);
error = sysv_add_entry(dir, dentry->d_name.name,
goto out;
inode->i_mode = S_IFLNK | 0777;
- inode->i_op = &sysv_symlink_inode_operations;
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_mapping->a_ops = &sysv_aops;
err = block_symlink(inode, symname, l);
if (err)
goto out_no_entry;
+++ /dev/null
-/*
- * linux/fs/sysv/symlink.c
- *
- * minix/symlink.c
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * coh/symlink.c
- * Copyright (C) 1993 Pascal Haible, Bruno Haible
- *
- * sysv/symlink.c
- * Copyright (C) 1993 Bruno Haible
- *
- * SystemV/Coherent symlink handling code
- */
-
-#include <linux/sysv_fs.h>
-
-/*
- * symlinks can't do much...
- */
-struct inode_operations sysv_symlink_inode_operations = {
- readlink: page_readlink,
- follow_link: page_follow_link,
- get_block: sysv_get_block,
- readpage: block_read_full_page
-};
NULL, /* mknod */
NULL, /* rename */
#endif
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
/*
return offset;
}
-static inline void remove_suid(struct inode * inode)
+static int udf_adinicb_readpage(struct dentry *dentry, struct page * page)
{
- unsigned int mode;
+ struct inode *inode = dentry->d_inode;
- /* set S_IGID if S_IXGRP is set, and always set S_ISUID */
- mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID;
-
- /* was any of the uid bits set? */
- mode &= inode->i_mode;
- if (mode && !capable(CAP_FSETID))
- {
- inode->i_mode &= ~mode;
- mark_inode_dirty(inode);
- }
-}
-
-static ssize_t udf_file_write(struct file * file, const char * buf,
- size_t count, loff_t *ppos)
-{
- ssize_t retval;
- struct inode *inode = file->f_dentry->d_inode;
+ struct buffer_head *bh;
+ unsigned long kaddr = 0;
- retval = generic_file_write(file, buf, count, ppos, block_write_partial_page);
+ if (!PageLocked(page))
+ PAGE_BUG(page);
- if (retval > 0)
- {
- remove_suid(inode);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
- UDF_I_UCTIME(inode) = UDF_I_UMTIME(inode) = CURRENT_UTIME;
- mark_inode_dirty(inode);
- }
- return retval;
+ kaddr = kmap(page);
+ memset((char *)kaddr, 0, PAGE_CACHE_SIZE);
+ bh = getblk (inode->i_dev, inode->i_ino, inode->i_sb->s_blocksize);
+ ll_rw_block (READ, 1, &bh);
+ wait_on_buffer(bh);
+ memcpy((char *)kaddr, bh->b_data + udf_ext0_offset(inode),
+ inode->i_size);
+ brelse(bh);
+ SetPageUptodate(page);
+ kunmap(page);
+ UnlockPage(page);
+ return 0;
}
-int udf_write_partial_page_adinicb(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+static int udf_adinicb_writepage(struct dentry *dentry, struct page *page)
{
- struct inode *inode = file->f_dentry->d_inode;
- int err = 0, block;
+ struct inode *inode = dentry->d_inode;
+
struct buffer_head *bh;
unsigned long kaddr = 0;
if (!PageLocked(page))
BUG();
- if (offset < 0 || offset >= (inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode)))
- BUG();
- if (bytes+offset < 0 || bytes+offset > (inode->i_sb->s_blocksize - udf_file_entry_alloc_offset(inode)))
- BUG();
kaddr = kmap(page);
- block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
- bh = getblk (inode->i_dev, block, inode->i_sb->s_blocksize);
+ bh = getblk (inode->i_dev, inode->i_ino, inode->i_sb->s_blocksize);
if (!buffer_uptodate(bh))
{
ll_rw_block (READ, 1, &bh);
wait_on_buffer(bh);
}
- err = copy_from_user((char *)kaddr + offset, buf, bytes);
+ memcpy(bh->b_data + udf_ext0_offset(inode), (char *)kaddr,
+ inode->i_size);
+ ll_rw_block (WRITE, 1, &bh);
+ wait_on_buffer(bh);
+ brelse(bh);
+ SetPageUptodate(page);
+ kunmap(page);
+ return 0;
+}
+
+static int udf_adinicb_prepare_write(struct page *page, unsigned offset, unsigned to)
+{
+ kmap(page);
+ return 0;
+}
+
+static int udf_adinicb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ struct buffer_head *bh;
+ char *kaddr = (char*)page_address(page);
+ bh = bread (inode->i_dev, inode->i_ino, inode->i_sb->s_blocksize);
+ if (!buffer_uptodate(bh)) {
+ ll_rw_block (READ, 1, &bh);
+ wait_on_buffer(bh);
+ }
memcpy(bh->b_data + udf_file_entry_alloc_offset(inode) + offset,
- (char *)kaddr + offset, bytes);
+ kaddr + offset, to-offset);
mark_buffer_dirty(bh, 0);
brelse(bh);
kunmap(page);
SetPageUptodate(page);
- return bytes;
+ return 0;
}
-static ssize_t udf_file_write_adinicb(struct file * file, const char * buf,
+struct address_space_operations udf_adinicb_aops = {
+ readpage: udf_adinicb_readpage,
+ writepage: udf_adinicb_writepage,
+ prepare_write: udf_adinicb_prepare_write,
+ commit_write: udf_adinicb_commit_write
+};
+
+static ssize_t udf_file_write(struct file * file, const char * buf,
size_t count, loff_t *ppos)
{
ssize_t retval;
struct inode *inode = file->f_dentry->d_inode;
int err, pos;
- if (file->f_flags & O_APPEND)
- pos = inode->i_size;
- else
- pos = *ppos;
-
- if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
- pos + count))
- {
- udf_expand_file_adinicb(file, pos + count, &err);
- if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
- {
- udf_debug("udf_expand_adinicb: err=%d\n", err);
- return err;
- }
+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) {
+ if (file->f_flags & O_APPEND)
+ pos = inode->i_size;
else
- return udf_file_write(file, buf, count, ppos);
- }
- else
- {
- if (pos + count > inode->i_size)
- UDF_I_LENALLOC(inode) = pos + count;
- else
- UDF_I_LENALLOC(inode) = inode->i_size;
+ pos = *ppos;
+
+ if (inode->i_sb->s_blocksize <
+ (udf_file_entry_alloc_offset(inode) + pos + count)) {
+ udf_expand_file_adinicb(file, pos + count, &err);
+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) {
+ udf_debug("udf_expand_adinicb: err=%d\n", err);
+ return err;
+ }
+ } else {
+ if (pos + count > inode->i_size)
+ UDF_I_LENALLOC(inode) = pos + count;
+ else
+ UDF_I_LENALLOC(inode) = inode->i_size;
+ }
}
- retval = generic_file_write(file, buf, count, ppos, udf_write_partial_page_adinicb);
-
- if (retval > 0)
- {
- remove_suid(inode);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+ retval = generic_file_write(file, buf, count, ppos);
+ if (retval > 0) {
UDF_I_UCTIME(inode) = UDF_I_UMTIME(inode) = CURRENT_UTIME;
mark_inode_dirty(inode);
}
struct inode_operations udf_file_inode_operations = {
&udf_file_operations,
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- udf_get_block, /* get_block */
- block_read_full_page, /* readpage */
- block_write_full_page, /* writepage */
-#if CONFIG_UDF_RW == 1
- udf_truncate, /* truncate */
-#else
- NULL, /* truncate */
-#endif
- NULL, /* permission */
- NULL /* revalidate */
-};
-
-static struct file_operations udf_file_operations_adinicb = {
- llseek: udf_file_llseek,
- read: generic_file_read,
- write: udf_file_write_adinicb,
- ioctl: udf_ioctl,
- release: udf_release_file,
- fsync: udf_sync_file_adinicb,
-};
-
-struct inode_operations udf_file_inode_operations_adinicb = {
- &udf_file_operations_adinicb,
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- udf_get_block, /* get_block */
- udf_readpage_adinicb, /* readpage */
- udf_writepage_adinicb, /* writepage */
#if CONFIG_UDF_RW == 1
- udf_truncate_adinicb, /* truncate */
-#else
- NULL, /* truncate */
+ truncate: udf_truncate,
#endif
- NULL, /* permission */
- NULL /* revalidate */
};
unlock_kernel();
return err ? -EIO : 0;
}
-
-int udf_sync_file_adinicb(struct file * file, struct dentry *dentry)
-{
- int ret;
-
- lock_kernel();
- ret = udf_sync_inode(dentry->d_inode) ? -EIO : 0;
- unlock_kernel();
- return ret;
-}
static void udf_update_extents(struct inode *,
long_ad [EXTENT_MERGE_SIZE], int, int,
lb_addr, Uint32, struct buffer_head **);
+static int udf_get_block(struct inode *, long, struct buffer_head *, int);
/*
* udf_put_inode
{
inode->i_size = 0;
if (inode->i_blocks)
- inode->i_op->truncate(inode);
+ udf_truncate(inode);
udf_free_inode(inode);
}
return result;
}
+static int udf_writepage(struct dentry *dentry, struct page *page)
+{
+ return block_write_full_page(page,udf_get_block);
+}
+static int udf_readpage(struct dentry *dentry, struct page *page)
+{
+ return block_read_full_page(page,udf_get_block);
+}
+static int udf_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+ return block_prepare_write(page,from,to,udf_get_block);
+}
+static int udf_bmap(struct address_space *mapping, long block)
+{
+ return generic_block_bmap(mapping,block,udf_get_block);
+}
+static struct address_space_operations udf_aops = {
+ readpage: udf_readpage,
+ writepage: udf_writepage,
+ prepare_write: udf_prepare_write,
+ commit_write: generic_commit_write,
+ bmap: udf_bmap
+};
+
void udf_expand_file_adinicb(struct file * filp, int newsize, int * err)
{
struct inode * inode = filp->f_dentry->d_inode;
struct page *page;
unsigned long kaddr = 0;
+ /* from now on we have normal address_space methods */
+ inode->i_data.a_ops = &udf_aops;
+
if (!UDF_I_LENALLOC(inode))
{
UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
mark_inode_dirty(inode);
- inode->i_op = &udf_file_inode_operations;
- filp->f_op = inode->i_op->default_file_ops;
return;
}
mark_buffer_dirty(bh, 1);
udf_release_data(bh);
- block_write_full_page(filp->f_dentry, page);
+ inode->i_data.a_ops->writepage(filp->f_dentry, page);
UnlockPage(page);
page_cache_release(page);
mark_inode_dirty(inode);
inode->i_version ++;
- inode->i_op = &udf_file_inode_operations;
- filp->f_op = inode->i_op->default_file_ops;
}
struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int *err)
return dbh;
}
-struct buffer_head * udf_getblk(struct inode * inode, long block,
- int create, int * err)
-{
- struct buffer_head dummy;
- int error;
-
- dummy.b_state = 0;
- dummy.b_blocknr = -1000;
- error = udf_get_block(inode, block, &dummy, create);
- *err = error;
- if (!error & buffer_mapped(&dummy))
- {
- struct buffer_head *bh;
- bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize);
- if (buffer_new(&dummy))
- {
- if (!buffer_uptodate(bh))
- wait_on_buffer(bh);
- memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
- mark_buffer_uptodate(bh, 1);
- mark_buffer_dirty(bh, 1);
- }
- return bh;
- }
- return NULL;
-}
-
-int udf_get_block(struct inode *inode, long block, struct buffer_head *bh_result, int create)
+static int udf_get_block(struct inode *inode, long block, struct buffer_head *bh_result, int create)
{
int err, new;
struct buffer_head *bh;
goto abort;
}
+struct buffer_head * udf_getblk(struct inode * inode, long block,
+ int create, int * err)
+{
+ struct buffer_head dummy;
+ int error;
+
+ dummy.b_state = 0;
+ dummy.b_blocknr = -1000;
+ error = udf_get_block(inode, block, &dummy, create);
+ *err = error;
+ if (!error & buffer_mapped(&dummy))
+ {
+ struct buffer_head *bh;
+ bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize);
+ if (buffer_new(&dummy))
+ {
+ if (!buffer_uptodate(bh))
+ wait_on_buffer(bh);
+ memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
+ mark_buffer_uptodate(bh, 1);
+ mark_buffer_dirty(bh, 1);
+ }
+ return bh;
+ }
+ return NULL;
+}
+
static struct buffer_head * inode_getblk(struct inode * inode, long block,
int *err, long *phys, int *new)
{
case FILE_TYPE_NONE:
{
if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
- inode->i_op = &udf_file_inode_operations_adinicb;
+ inode->i_data.a_ops = &udf_adinicb_aops;
else
- inode->i_op = &udf_file_inode_operations;
+ inode->i_data.a_ops = &udf_aops;
+ inode->i_op = &udf_file_inode_operations;
inode->i_mode |= S_IFREG;
break;
}
}
case FILE_TYPE_SYMLINK:
{
- inode->i_op = &udf_symlink_inode_operations;
+ inode->i_data.a_ops = &udf_symlink_aops;
+ inode->i_op = &page_symlink_inode_operations;
inode->i_mode = S_IFLNK|S_IRWXUGO;
break;
}
unlock_kernel();
return ret;
}
-
-int udf_readpage_adinicb (struct dentry *dentry, struct page * page)
-{
- struct inode *inode = dentry->d_inode;
-
- struct buffer_head *bh;
- int block;
- unsigned long kaddr = 0;
-
- if (!PageLocked(page))
- PAGE_BUG(page);
-
- kaddr = kmap(page);
- memset((char *)kaddr, 0, PAGE_CACHE_SIZE);
- block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
- bh = getblk (inode->i_dev, block, inode->i_sb->s_blocksize);
- ll_rw_block (READ, 1, &bh);
- wait_on_buffer(bh);
- memcpy((char *)kaddr, bh->b_data + udf_ext0_offset(inode),
- inode->i_size);
- brelse(bh);
- SetPageUptodate(page);
- kunmap(page);
- UnlockPage(page);
- return 0;
-}
-
-int udf_writepage_adinicb (struct dentry *dentry, struct page *page)
-{
- struct inode *inode = dentry->d_inode;
-
- struct buffer_head *bh;
- int block;
- unsigned long kaddr = 0;
-
- if (!PageLocked(page))
- BUG();
-
- kaddr = kmap(page);
- block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
- bh = getblk (inode->i_dev, block, inode->i_sb->s_blocksize);
- if (!buffer_uptodate(bh))
- {
- ll_rw_block (READ, 1, &bh);
- wait_on_buffer(bh);
- }
- memcpy(bh->b_data + udf_ext0_offset(inode), (char *)kaddr,
- inode->i_size);
- ll_rw_block (WRITE, 1, &bh);
- wait_on_buffer(bh);
- brelse(bh);
- SetPageUptodate(page);
- kunmap(page);
- return 0;
-}
if (!inode)
return err;
- inode->i_op = &udf_file_inode_operations_adinicb;
+ inode->i_data.a_ops = &udf_adinicb_aops;
+ inode->i_op = &udf_file_inode_operations;
inode->i_mode = mode;
mark_inode_dirty(inode);
goto out;
inode->i_mode = S_IFLNK | S_IRWXUGO;
- inode->i_op = &udf_symlink_inode_operations;
+ inode->i_data.a_ops = &udf_symlink_aops;
+ inode->i_op = &page_symlink_inode_operations;
bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
ea = bh->b_data + udf_file_entry_alloc_offset(inode);
/*
* symlinks can't do much...
*/
-struct inode_operations udf_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- page_readlink, /* readlink */
- page_follow_link, /* follow_link */
- NULL, /* get_block */
- udf_symlink_filler, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
+struct address_space_operations udf_symlink_aops = {
+ readpage: udf_symlink_filler,
};
if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
return;
- udf_trunc(inode);
-
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- mark_inode_dirty(inode);
-}
-
-void udf_truncate_adinicb(struct inode * inode)
-{
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- return;
-
- UDF_I_LENALLOC(inode) = inode->i_size;
+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
+ UDF_I_LENALLOC(inode) = inode->i_size;
+ else
+ udf_trunc(inode);
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
mark_inode_dirty(inode);
extern struct inode_operations udf_dir_inode_operations;
extern struct inode_operations udf_file_inode_operations;
-extern struct inode_operations udf_file_inode_operations_adinicb;
-extern struct inode_operations udf_symlink_inode_operations;
+extern struct address_space_operations udf_adinicb_aops;
+extern struct address_space_operations udf_symlink_aops;
struct udf_fileident_bh
{
extern void udf_expand_file_adinicb(struct file *, int, int *);
extern struct buffer_head * udf_expand_dir_adinicb(struct inode *, int *, int *);
extern struct buffer_head * udf_getblk(struct inode *, long, int, int *);
-extern int udf_get_block(struct inode *, long, struct buffer_head *, int);
-extern int udf_readpage_adinicb (struct dentry *, struct page *);
-extern int udf_writepage_adinicb (struct dentry *, struct page *);
extern struct buffer_head * udf_bread(struct inode *, int, int, int *);
extern void udf_read_inode(struct inode *);
extern void udf_put_inode(struct inode *);
/* truncate.c */
extern void udf_trunc(struct inode *);
extern void udf_truncate(struct inode *);
-extern void udf_truncate_adinicb(struct inode *);
/* balloc.c */
extern void udf_free_blocks(const struct inode *, lb_addr, Uint32, Uint32);
extern int udf_alloc_blocks(const struct inode *, Uint16, Uint32, Uint32);
extern int udf_new_block(const struct inode *, Uint16, Uint32, int *);
extern int udf_sync_file(struct file *, struct dentry *);
-extern int udf_sync_file_adinicb(struct file *, struct dentry *);
/* directory.c */
extern Uint8 * udf_filead_read(struct inode *, Uint8 *, Uint8, lb_addr, int *, int *, struct buffer_head **, int *);
ufs_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
NULL, /* truncate */
ufs_permission, /* permission */
NULL /* revalidate */
#include <linux/mm.h>
#include <linux/pagemap.h>
-#define NBUF 32
-
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
/*
* Make sure the offset never goes beyond the 32-bit mark..
*/
return retval;
}
-static inline void remove_suid(struct inode *inode)
-{
- unsigned int mode;
-
- /* set S_IGID if S_IXGRP is set, and always set S_ISUID */
- mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID;
-
- /* was any of the uid bits set? */
- mode &= inode->i_mode;
- if (mode && !suser()) {
- inode->i_mode &= ~mode;
- mark_inode_dirty(inode);
- }
-}
-
-/*
- * Write to a file (through the page cache).
- */
-static ssize_t
-ufs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
- ssize_t retval;
-
- retval = generic_file_write(file, buf, count,
- ppos, block_write_partial_page);
- if (retval > 0) {
- struct inode *inode = file->f_dentry->d_inode;
- remove_suid(inode);
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
- mark_inode_dirty(inode);
- }
- return retval;
-}
-
-/*
- * Called when an inode is released. Note that this is different
- * from ufs_open: open gets called at every open, but release
- * gets called only when /all/ the files are closed.
- */
-static int ufs_release_file (struct inode * inode, struct file * filp)
-{
- return 0;
-}
-
/*
* We have mostly NULL's here: the current defaults are ok for
* the ufs filesystem.
static struct file_operations ufs_file_operations = {
llseek: ufs_file_lseek,
read: generic_file_read,
- write: ufs_file_write,
+ write: generic_file_write,
mmap: generic_file_mmap,
- release: ufs_release_file,
};
struct inode_operations ufs_file_inode_operations = {
- &ufs_file_operations,/* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- ufs_getfrag_block, /* get_block */
- block_read_full_page, /* readpage */
- block_write_full_page, /* writepage */
- ufs_truncate, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
+ &ufs_file_operations,
+ truncate: ufs_truncate,
};
return result;
}
-int ufs_getfrag_block (struct inode *inode, long fragment, struct buffer_head *bh_result, int create)
+static int ufs_getfrag_block (struct inode *inode, long fragment, struct buffer_head *bh_result, int create)
{
struct super_block * sb;
struct ufs_sb_private_info * uspi;
return NULL;
}
+static int ufs_writepage(struct dentry *dentry, struct page *page)
+{
+ return block_write_full_page(page,ufs_getfrag_block);
+}
+static int ufs_readpage(struct dentry *dentry, struct page *page)
+{
+ return block_read_full_page(page,ufs_getfrag_block);
+}
+static int ufs_prepare_write(struct page *page, unsigned from, unsigned to)
+{
+ return block_prepare_write(page,from,to,ufs_getfrag_block);
+}
+static int ufs_bmap(struct address_space *mapping, long block)
+{
+ return generic_block_bmap(mapping,block,ufs_getfrag_block);
+}
+struct address_space_operations ufs_aops = {
+ readpage: ufs_readpage,
+ writepage: ufs_writepage,
+ prepare_write: ufs_prepare_write,
+ commit_write: generic_commit_write,
+ bmap: ufs_bmap
+};
+
void ufs_read_inode (struct inode * inode)
{
struct super_block * sb;
inode->i_op = NULL;
- if (S_ISREG(inode->i_mode))
+ if (S_ISREG(inode->i_mode)) {
inode->i_op = &ufs_file_inode_operations;
- else if (S_ISDIR(inode->i_mode))
+ inode->i_mapping->a_ops = &ufs_aops;
+ } else if (S_ISDIR(inode->i_mode))
inode->i_op = &ufs_dir_inode_operations;
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = inode->i_blocks
- ?&ufs_symlink_inode_operations
- :&ufs_fast_symlink_inode_operations;
- else
+ else if (S_ISLNK(inode->i_mode)) {
+ if (!inode->i_blocks)
+ inode->i_op = &ufs_fast_symlink_inode_operations;
+ else {
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_mapping->a_ops = &ufs_aops;
+ }
+ } else
init_special_inode(inode, inode->i_mode,
SWAB32(ufs_inode->ui_u2.ui_addr.ui_db[0]));
if (!inode)
return err;
inode->i_op = &ufs_file_inode_operations;
+ inode->i_mapping->a_ops = &ufs_aops;
inode->i_mode = mode;
mark_inode_dirty(inode);
bh = ufs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
if (l > sb->u.ufs_sb.s_uspi->s_maxsymlinklen) {
/* slow symlink */
- inode->i_op = &ufs_symlink_inode_operations;
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_mapping->a_ops = &ufs_aops;
err = block_symlink(inode, symname, l);
if (err)
goto out_no_entry;
/*
* linux/fs/ufs/symlink.c
*
+ * Only fast symlinks left here - the rest is done by generic code. AV, 1999
+ *
* Copyright (C) 1998
* Daniel Pirkl <daniel.pirkl@emai.cz>
* Charles University, Faculty of Mathematics and Physics
*/
#include <linux/fs.h>
-#include <linux/ufs_fs.h>
static int ufs_readlink(struct dentry *dentry, char *buffer, int buflen)
{
readlink: ufs_readlink,
follow_link: ufs_follow_link,
};
-
-struct inode_operations ufs_symlink_inode_operations = {
- readlink: page_readlink,
- follow_link: page_follow_link,
- get_block: ufs_getfrag_block,
- readpage: block_read_full_page
-};
# Note 2: the CFLAGS definitions are now in the main makefile.
O_TARGET := umsdos.o
-O_OBJS := dir.o inode.o ioctl.o mangle.o namei.o \
- rdir.o symlink.o emd.o check.o
+O_OBJS := dir.o inode.o ioctl.o mangle.o namei.o rdir.o emd.o check.o
M_OBJS := $(O_TARGET)
UMSDOS_rmdir, /* rmdir */
UMSDOS_mknod, /* mknod */
UMSDOS_rename, /* rename */
- NULL, /* readlink */
- NULL, /* followlink */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
} else if (S_ISDIR (inode->i_mode)) {
umsdos_setup_dir(dentry);
} else if (S_ISLNK (inode->i_mode)) {
- inode->i_op = &umsdos_symlink_inode_operations;
+ /* address_space operations already set */
+ inode->i_op = &page_symlink_inode_operations;
} else
init_special_inode(inode, inode->i_mode,
kdev_t_to_nr(inode->i_rdev));
UMSDOS_rrmdir, /* rmdir */
NULL, /* mknod */
msdos_rename, /* rename */
- NULL, /* readlink */
- NULL, /* followlink */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* get_block */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
+++ /dev/null
-/*
- * linux/fs/umsdos/file.c
- *
- * Written 1992 by Jacques Gelinas
- * inspired from linux/fs/msdos/file.c Werner Almesberger
- *
- * Extended MS-DOS regular file handling primitives
- *
- * Wow. It looks like we could support them on FAT with little (if any)
- * problems. Oh, well...
- */
-
-#include <linux/fs.h>
-#include <linux/msdos_fs.h>
-
-struct inode_operations umsdos_symlink_inode_operations =
-{
- readlink: page_readlink,
- follow_link: page_follow_link,
- get_block: fat_get_block,
- readpage: block_read_full_page
-};
vfat_rmdir, /* rmdir */
NULL, /* mknod */
vfat_rename, /* rename */
- NULL, /* readlink */
- NULL, /* followlink */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
struct super_block *vfat_read_super(struct super_block *sb,void *data,
*/
#define __ISA_IO_base ((char *)(PAGE_OFFSET))
-#define isa_readb(a) readb(__ISA_IO_base + (a))
-#define isa_readw(a) readw(__ISA_IO_base + (a))
-#define isa_readl(a) readl(__ISA_IO_base + (a))
-#define isa_writeb(b,a) writeb(b,__ISA_IO_base + (a))
-#define isa_writew(w,a) writew(w,__ISA_IO_base + (a))
-#define isa_writel(l,a) writel(l,__ISA_IO_base + (a))
-#define isa_memset_io(a,b,c) memset_io(__ISA_IO_base + (a),(b),(c))
-#define isa_memcpy_fromio(a,b,c) memcpy_fromio((a),__ISA_IO_base + (b),(c))
-#define isa_memcpy_toio(a,b,c) memcpy_toio(__ISA_IO_base + (a),(b),(c))
+#define isa_readb(a) readb(__ISA_IO_base + (unsigned long)(a))
+#define isa_readw(a) readw(__ISA_IO_base + (unsigned long)(a))
+#define isa_readl(a) readl(__ISA_IO_base + (unsigned long)(a))
+#define isa_writeb(b,a) writeb(b,__ISA_IO_base + (unsigned long)(a))
+#define isa_writew(w,a) writew(w,__ISA_IO_base + (unsigned long)(a))
+#define isa_writel(l,a) writel(l,__ISA_IO_base + (unsigned long)(a))
+#define isa_memset_io(a,b,c) memset_io(__ISA_IO_base + (unsigned long)(a),(b),(c))
+#define isa_memcpy_fromio(a,b,c) memcpy_fromio((a),__ISA_IO_base + (unsigned long)(b),(c))
+#define isa_memcpy_toio(a,b,c) memcpy_toio(__ISA_IO_base + (unsigned long)(a),(b),(c))
/*
*/
#define eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),__io_virt(b),(c),(d))
-#define isa_eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),__io_virt(__ISA_IO_base + (b)),(c),(d))
+#define isa_eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),__io_virt(__ISA_IO_base + (unsigned long)(b)),(c),(d))
static inline int check_signature(unsigned long io_addr,
const unsigned char *signature, int length)
* Copyright (C) 1998, 1999 Hewlett-Packard Co
* Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
*/
-#include <linux/config.h>
#include <linux/types.h>
#include <asm/system.h>
* adfs file system inode data in memory
*/
struct adfs_inode_info {
+ unsigned long mmu_private;
unsigned long parent_id; /* object id of parent */
__u32 loadaddr; /* RISC OS load address */
__u32 execaddr; /* RISC OS exec address */
extern struct inode_operations affs_file_inode_operations;
extern struct inode_operations affs_file_inode_operations_ofs;
extern struct inode_operations affs_dir_inode_operations;
-extern struct inode_operations affs_symlink_inode_operations;
-extern struct inode_operations affs_chrdev_inode_operations;
-extern struct inode_operations affs_blkdev_inode_operations;
+extern struct address_space_operations affs_symlink_aops;
+extern struct address_space_operations affs_aops;
extern struct dentry_operations affs_dentry_operations;
extern struct dentry_operations affs_dentry_operations_intl;
+extern int affs_bmap(struct inode *, int);
#endif
* affs fs inode data in memory
*/
struct affs_inode_info {
+ unsigned long mmu_private;
u32 i_protect; /* unused attribute bits */
s32 i_parent; /* parent ino */
s32 i_original; /* if != 0, this is the key of the original */
VIA_GENERIC,
VIA_VP3,
VIA_MVP3,
+ VIA_MVP4,
VIA_APOLLO_PRO,
SIS_GENERIC,
AMD_GENERIC,
/* file.c */
extern struct inode_operations bfs_file_inops;
+extern struct address_space_operations bfs_aops;
/* dir.c */
extern struct inode_operations bfs_dir_inops;
#define CODA_INACTIVE 21
#define CODA_VGET 22
#define CODA_SIGNAL 23
-#define CODA_REPLACE 24
-#define CODA_FLUSH 25
-#define CODA_PURGEUSER 26
-#define CODA_ZAPFILE 27
-#define CODA_ZAPDIR 28
-#define CODA_PURGEFID 30
+#define CODA_REPLACE 24 /* DOWNCALL */
+#define CODA_FLUSH 25 /* DOWNCALL */
+#define CODA_PURGEUSER 26 /* DOWNCALL */
+#define CODA_ZAPFILE 27 /* DOWNCALL */
+#define CODA_ZAPDIR 28 /* DOWNCALL */
+#define CODA_PURGEFID 30 /* DOWNCALL */
#define CODA_OPEN_BY_PATH 31
#define CODA_RESOLVE 32
#define CODA_REINTEGRATE 33
#define CODA_STATFS 34
-#define CODA_NCALLS 35
+#define CODA_MAKE_CINODE 35 /* DOWNCALL */
+#define CODA_NCALLS 36
-#define DOWNCALL(opcode) (opcode >= CODA_REPLACE && opcode <= CODA_PURGEFID)
+#define DOWNCALL(opcode) \
+ ((opcode >= CODA_REPLACE && opcode <= CODA_PURGEFID) || \
+ opcode == CODA_MAKE_CINODE)
#define VC_MAXDATASIZE 8192
#define VC_MAXMSGSIZE sizeof(union inputArgs)+sizeof(union outputArgs) +\
VC_MAXDATASIZE
#define CIOC_KERNEL_VERSION _IOWR('c', 10, sizeof (int))
+
#if 0
- /* don't care about kernel version number */
-#define CODA_KERNEL_VERSION 0
- /* The old venus 4.6 compatible interface */
-#define CODA_KERNEL_VERSION 1
+#define CODA_KERNEL_VERSION 0 /* don't care about kernel version number */
+#define CODA_KERNEL_VERSION 1 /* The old venus 4.6 compatible interface */
+#define CODA_KERNEL_VERSION 2 /* venus_lookup gets an extra parameter */
#endif
- /* venus_lookup gets an extra parameter to aid windows.*/
-#define CODA_KERNEL_VERSION 2
+#define CODA_KERNEL_VERSION 3 /* added CODA_MAKE_CINODE downcall */
/*
* Venus <-> Coda RPC arguments
ViceFid CodaFid;
};
+struct coda_make_cinode_out {
+ struct coda_out_hdr oh;
+ ViceFid CodaFid;
+ struct coda_vattr attr;
+ int fd;
+};
+
/* coda_rdwr: */
struct coda_rdwr_in {
struct coda_in_hdr ih;
struct coda_purgefid_out coda_purgefid;
struct coda_rdwr_out coda_rdwr;
struct coda_replace_out coda_replace;
+ struct coda_make_cinode_out coda_make_cinode;
struct coda_open_by_path_out coda_open_by_path;
struct coda_statfs_out coda_statfs;
};
#define C_INITED 0x20
#define C_FLUSH 0x2 /* used after a flush */
+struct inode *coda_iget(struct super_block * sb, ViceFid * fid,
+ struct coda_vattr * attr);
int coda_cnode_make(struct inode **, struct ViceFid *, struct super_block *);
int coda_cnode_makectl(struct inode **inode, struct super_block *sb);
struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb);
extern struct inode_operations coda_dir_inode_operations;
extern struct inode_operations coda_file_inode_operations;
extern struct inode_operations coda_ioctl_inode_operations;
-extern struct inode_operations coda_symlink_inode_operations;
+
+extern struct address_space_operations coda_file_aops;
+extern struct address_space_operations coda_symlink_aops;
extern struct file_operations coda_dir_operations;
extern struct file_operations coda_file_operations;
#define REQ_ASYNC 0x1
#define REQ_READ 0x2
#define REQ_WRITE 0x4
+#define REQ_ABORT 0x8
/*
extern struct inode_operations efs_dir_inode_operations;
extern struct inode_operations efs_file_inode_operations;
-extern struct inode_operations efs_symlink_inode_operations;
+extern struct address_space_operations efs_symlink_aops;
extern int init_module(void);
extern void cleanup_module(void);
extern void ext2_check_inodes_bitmap (struct super_block *);
/* inode.c */
-extern long ext2_bmap (struct inode *, long);
-extern int ext2_get_block (struct inode *, long, struct buffer_head *, int);
extern struct buffer_head * ext2_getblk (struct inode *, long, int, int *);
-extern int ext2_getblk_block (struct inode *, long, int, int *, int *);
extern struct buffer_head * ext2_bread (struct inode *, int, int, int *);
-extern int ext2_getcluster (struct inode * inode, long block);
extern void ext2_read_inode (struct inode *);
extern void ext2_write_inode (struct inode *);
extern void ext2_put_inode (struct inode *);
extern struct inode_operations ext2_file_inode_operations;
/* symlink.c */
-extern struct inode_operations ext2_symlink_inode_operations;
extern struct inode_operations ext2_fast_symlink_inode_operations;
+extern struct address_space_operations ext2_aops;
+
#endif /* __KERNEL__ */
#endif /* _LINUX_EXT2_FS_H */
#define touch_buffer(bh) set_bit(PG_referenced, &bh->b_page->flags)
+
#include <linux/pipe_fs_i.h>
#include <linux/minix_fs_i.h>
#include <linux/ext2_fs_i.h>
* oh the beauties of C type declarations.
*/
struct page;
+struct address_space;
+
+struct address_space_operations {
+ int (*writepage) (struct dentry *, struct page *);
+ int (*readpage)(struct dentry *, struct page *);
+ int (*prepare_write)(struct page *, unsigned, unsigned);
+ int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
+ /* Unfortunately this kludge is needed for FIBMAP. Don't use it */
+ int (*bmap)(struct address_space *, long);
+};
struct address_space {
- struct list_head pages;
- unsigned long nrpages;
+ struct list_head pages; /* list of pages */
+ unsigned long nrpages; /* number of pages */
+ struct address_space_operations *a_ops; /* methods */
+ void *host; /* owner: inode, block_device */
+ void *private; /* private data */
};
struct block_device {
wait_queue_head_t i_wait;
struct file_lock *i_flock;
struct vm_area_struct *i_mmap;
+ struct address_space *i_mapping;
struct address_space i_data;
spinlock_t i_shared_lock;
struct dquot *i_dquot[MAXQUOTAS];
struct inode *, struct dentry *);
int (*readlink) (struct dentry *, char *,int);
struct dentry * (*follow_link) (struct dentry *, struct dentry *, unsigned int);
- /*
- * the order of these functions within the VFS template has been
- * changed because SMP locking has changed: from now on all get_block,
- * readpage and writepage functions are supposed to do
- * whatever locking they need to get proper SMP operation - for
- * now in most cases this means a lock/unlock_kernel at entry/exit.
- * [The new order is also slightly more logical :)]
- */
- /*
- * Generic block allocator exported by the lowlevel fs. All metadata
- * details are handled by the lowlevel fs, all 'logical data content'
- * details are handled by the highlevel block layer.
- */
- int (*get_block) (struct inode *, long, struct buffer_head *, int);
-
- int (*readpage) (struct dentry *, struct page *);
- int (*writepage) (struct dentry *, struct page *);
-
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int);
int (*revalidate) (struct dentry *);
extern int register_chrdev(unsigned int, const char *, struct file_operations *);
extern int unregister_chrdev(unsigned int, const char *);
extern int chrdev_open(struct inode *, struct file *);
-extern struct file_operations def_chr_fops;
extern const char * bdevname(kdev_t);
extern const char * cdevname(kdev_t);
extern const char * kdevname(kdev_t);
extern int brw_page(int, struct page *, kdev_t, int [], int);
typedef int (*writepage_t)(struct file *, struct page *, unsigned long, unsigned long, const char *);
+typedef int (get_block_t)(struct inode*,long,struct buffer_head*,int);
/* Generic buffer handling for block filesystems.. */
-extern int block_read_full_page(struct dentry *, struct page *);
-extern int block_write_full_page (struct dentry *, struct page *);
-extern int block_write_partial_page (struct file *, struct page *, unsigned long, unsigned long, const char *);
-extern int block_write_cont_page (struct file *, struct page *, unsigned long, unsigned long, const char *);
-extern int block_write_zero_range(struct inode *, struct page *, unsigned, unsigned, unsigned, const char *);
-extern inline int block_write_range(struct inode *inode, struct page *page,
- unsigned from, unsigned len,const char *buf)
-{
- return block_write_zero_range(inode, page, from, from, from+len, buf);
-}
extern int block_flushpage(struct page *, unsigned long);
extern int block_symlink(struct inode *, const char *, int);
+extern int block_write_full_page(struct page*, get_block_t*);
+extern int block_read_full_page(struct page*, get_block_t*);
+extern int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*);
+extern int cont_prepare_write(struct page*, unsigned, unsigned, get_block_t*,
+ unsigned long *);
+int generic_block_bmap(struct address_space *, long, get_block_t *);
+int generic_commit_write(struct file *, struct page *, unsigned, unsigned);
extern int generic_file_mmap(struct file *, struct vm_area_struct *);
extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
-extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *, writepage_t);
+extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *);
extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t);
extern int vfs_readlink(struct dentry *, char *, int, const char *);
extern struct dentry *vfs_follow_link(struct dentry *, struct dentry *, unsigned, const char *);
extern int page_readlink(struct dentry *, char *, int);
extern struct dentry *page_follow_link(struct dentry *, struct dentry *, unsigned);
+struct inode_operations page_symlink_inode_operations;
extern struct super_block *get_super(kdev_t);
struct super_block *get_empty_super(void);
struct hfs_inode_info {
int magic; /* A magic number */
+ unsigned long mmu_private;
struct hfs_cat_entry *entry;
/* For a regular or header file */
#define _HPFS_FS_I
struct hpfs_inode_info {
+ unsigned long mmu_private;
ino_t i_parent_dir; /* (directories) gives fnode of parent dir */
unsigned i_dno; /* (directories) root dnode */
unsigned i_dpos; /* (directories) temp for readdir */
extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *);
extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *);
-extern int rock_ridge_symlink_readpage(struct dentry *, struct page *);
extern int find_rock_ridge_relocation(struct iso_directory_record *, struct inode *);
int get_joliet_filename(struct iso_directory_record *, struct inode *, unsigned char *);
extern struct inode_operations isofs_file_inode_operations;
extern struct inode_operations isofs_dir_inode_operations;
-extern struct inode_operations isofs_symlink_inode_operations;
-extern struct inode_operations isofs_chrdev_inode_operations;
-extern struct inode_operations isofs_blkdev_inode_operations;
-extern struct inode_operations isofs_fifo_inode_operations;
+extern struct address_space_operations isofs_symlink_aops;
/* The following macros are used to check for memory leaks. */
#ifdef LEAK_CHECK
extern void minix_free_block(struct inode * inode, int block);
extern unsigned long minix_count_free_blocks(struct super_block *sb);
-extern int minix_bmap(struct inode *,int);
-
extern struct buffer_head * minix_getblk(struct inode *, int, int);
-extern int minix_get_block(struct inode *, long, struct buffer_head *, int);
extern struct buffer_head * minix_bread(struct inode *, int, int);
extern void minix_truncate(struct inode *);
extern int minix_sync_inode(struct inode *);
extern int minix_sync_file(struct file *, struct dentry *);
+extern struct address_space_operations minix_aops;
extern struct inode_operations minix_file_inode_operations;
extern struct inode_operations minix_dir_inode_operations;
-extern struct inode_operations minix_symlink_inode_operations;
extern struct dentry_operations minix_dentry_operations;
#endif /* __KERNEL__ */
extern ssize_t fat_file_write(struct file *, const char *, size_t, loff_t *);
extern void fat_truncate(struct inode *inode);
-/* mmap.c */
-extern int fat_mmap(struct file *, struct vm_area_struct *);
-extern int fat_readpage(struct file *, struct page *);
-
-
/* vfat.c */
extern int init_vfat_fs(void);
*/
struct msdos_inode_info {
+ unsigned long mmu_private;
int i_start; /* first cluster or 0 */
int i_logstart; /* logical first cluster */
int i_attrs; /* unused attribute bits */
int i_location; /* on-disk position of directory entry or 0 */
struct inode *i_fat_inode; /* struct inode of this one */
struct list_head i_fat_hash; /* hash by i_location */
- int i_realsize;
};
#endif
* linux/fs/nfs/file.c
*/
extern struct inode_operations nfs_file_inode_operations;
+extern struct address_space_operations nfs_file_aops;
/*
* linux/fs/nfs/dir.c
/* Definition of NTFS in-memory inode structure */
struct ntfs_inode_info{
+ unsigned long mmu_private;
struct ntfs_sb_info *vol;
int i_number; /* should be really 48 bits */
unsigned sequence_number;
extern inline void add_page_to_hash_queue(struct page * page, struct inode * inode, unsigned long index)
{
- __add_page_to_hash_queue(page, page_hash(&inode->i_data,index));
+ __add_page_to_hash_queue(page, page_hash(inode->i_mapping,index));
}
extern inline void add_page_to_inode_queue(struct address_space *mapping, struct page * page)
#endif /* !CONFIG_PCI */
+/* these helpers provide future and backwards compatibility
+ * for accessing popular PCI BAR info */
+#define pci_resource_start(dev,bar) ((dev)->resource[(bar)].start)
+#define pci_resource_end(dev,bar) ((dev)->resource[(bar)].end)
+#define pci_resource_flags(dev,bar) ((dev)->resource[(bar)].flags)
+#define pci_resource_len(dev,bar) \
+ ((pci_resource_start((dev),(bar)) == 0 && \
+ pci_resource_end((dev),(bar)) == \
+ pci_resource_start((dev),(bar))) ? 0 : \
+ \
+ (pci_resource_end((dev),(bar)) - \
+ pci_resource_start((dev),(bar)) + 1))
+
/*
* The world is not perfect and supplies us with broken PCI devices.
* For at least a part of these bugs we need a work-around, so both
extern int qnx4_create(struct inode *dir, struct dentry *dentry, int mode);
extern struct inode_operations qnx4_file_inode_operations;
extern struct inode_operations qnx4_dir_inode_operations;
-extern struct inode_operations qnx4_symlink_inode_operations;
extern int qnx4_is_free(struct super_block *sb, long block);
extern int qnx4_set_bitmap(struct super_block *sb, long block, int busy);
extern int qnx4_create(struct inode *inode, struct dentry *dentry, int mode);
__u8 i_zero[4]; /* 4 */
qnx4_ftype_t i_type; /* 1 */
__u8 i_status; /* 1 */
+ unsigned long mmu_private;
};
#endif
#define TASK_UNINTERRUPTIBLE 2
#define TASK_ZOMBIE 4
#define TASK_STOPPED 8
-#define TASK_SWAPPING 16
#define TASK_EXCLUSIVE 32
#define __set_task_state(tsk, state_value) \
/* linux/fs/smbfs/file.c */
extern struct inode_operations smb_file_inode_operations;
+extern struct address_space_operations smb_file_aops;
/* linux/fs/smbfs/dir.c */
extern struct inode_operations smb_dir_inode_operations;
extern void sysv_free_block(struct super_block * sb, unsigned int block);
extern unsigned long sysv_count_free_blocks(struct super_block *sb);
-extern int sysv_get_block(struct inode *, long, struct buffer_head *, int);
extern struct buffer_head * sysv_file_bread(struct inode *, int, int);
extern void sysv_truncate(struct inode *);
extern int sysv_sync_file(struct file *, struct dentry *);
extern struct inode_operations sysv_file_inode_operations;
-extern struct inode_operations sysv_file_inode_operations_with_bmap;
extern struct inode_operations sysv_dir_inode_operations;
-extern struct inode_operations sysv_symlink_inode_operations;
+extern struct address_space_operations sysv_aops;
#endif /* __KERNEL__ */
extern struct inode_operations ufs_file_inode_operations;
extern struct file_operations ufs_file_operations;
+extern struct address_space_operations ufs_aops;
+
/* ialloc.c */
extern void ufs_free_inode (struct inode *inode);
extern struct inode * ufs_new_inode (const struct inode *, int, int *);
extern void ufs_write_inode (struct inode *);
extern void ufs_delete_inode (struct inode *);
extern struct buffer_head * ufs_getfrag (struct inode *, unsigned, int, int *);
-extern int ufs_getfrag_block (struct inode *, long, struct buffer_head *, int);
extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *);
/* namei.c */
extern void ufs_write_super (struct super_block *);
/* symlink.c */
-extern struct inode_operations ufs_symlink_inode_operations;
extern struct inode_operations ufs_fast_symlink_inode_operations;
/* truncate.c */
#endif
extern struct inode_operations umsdos_dir_inode_operations;
-extern struct inode_operations umsdos_symlink_inode_operations;
extern int init_umsdos_fs (void);
#include <linux/umsdos_fs.p>
OX_OBJS += ksyms.o
endif
+ifdef CONFIG_ACPI
+OX_OBJS += pm.o
+else
+ ifdef CONFIG_APM
+ OX_OBJS += pm.o
+ endif
+endif
+
CFLAGS_sched.o := $(PROFILING) -fno-omit-frame-pointer
include $(TOPDIR)/Rules.make
unsigned long old_personality;
int ret;
- lock_kernel();
- ret = current->personality;
if (personality == 0xffffffff)
- goto out;
+ return current->personality;
ret = -EINVAL;
+ lock_kernel();
it = lookup_exec_domain(personality);
if (!it)
goto out;
EXPORT_SYMBOL(ll_rw_block);
EXPORT_SYMBOL(__wait_on_buffer);
EXPORT_SYMBOL(___wait_on_page);
-EXPORT_SYMBOL(block_read_full_page);
EXPORT_SYMBOL(block_write_full_page);
-EXPORT_SYMBOL(block_write_partial_page);
-EXPORT_SYMBOL(block_write_cont_page);
-EXPORT_SYMBOL(block_write_zero_range);
+EXPORT_SYMBOL(block_read_full_page);
+EXPORT_SYMBOL(block_prepare_write);
+EXPORT_SYMBOL(cont_prepare_write);
+EXPORT_SYMBOL(generic_commit_write);
+EXPORT_SYMBOL(generic_block_bmap);
EXPORT_SYMBOL(generic_file_read);
EXPORT_SYMBOL(do_generic_file_read);
EXPORT_SYMBOL(generic_file_write);
EXPORT_SYMBOL(vfs_follow_link);
EXPORT_SYMBOL(page_readlink);
EXPORT_SYMBOL(page_follow_link);
+EXPORT_SYMBOL(page_symlink_inode_operations);
EXPORT_SYMBOL(block_symlink);
/* for stackable file systems (lofs, wrapfs, etc.) */
--- /dev/null
+/*
+ * pm.c - Power management interface
+ *
+ * Copyright (C) 2000 Andrew Henroid
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+
+int pm_active = 0;
+
+static spinlock_t pm_devs_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(pm_devs);
+
+/*
+ * Register a device with power management
+ */
+struct pm_dev *pm_register(pm_dev_t type,
+ unsigned long id,
+ pm_callback callback)
+{
+ struct pm_dev *dev = kmalloc(sizeof(struct pm_dev), GFP_KERNEL);
+ if (dev) {
+ unsigned long flags;
+
+ memset(dev, 0, sizeof(*dev));
+ dev->type = type;
+ dev->id = id;
+ dev->callback = callback;
+
+ spin_lock_irqsave(&pm_devs_lock, flags);
+ list_add(&dev->entry, &pm_devs);
+ spin_unlock_irqrestore(&pm_devs_lock, flags);
+ }
+ return dev;
+}
+
+/*
+ * Unregister a device with power management
+ */
+void pm_unregister(struct pm_dev *dev)
+{
+ if (dev) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&pm_devs_lock, flags);
+ list_del(&dev->entry);
+ spin_unlock_irqrestore(&pm_devs_lock, flags);
+
+ kfree(dev);
+ }
+}
+
+/*
+ * Unregister all devices with matching callback
+ */
+void pm_unregister_all(pm_callback callback)
+{
+ struct list_head *entry;
+
+ if (!callback)
+ return;
+
+ entry = pm_devs.next;
+ while (entry != &pm_devs) {
+ struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
+ entry = entry->next;
+ if (dev->callback == callback)
+ pm_unregister(dev);
+ }
+}
+
+/*
+ * Send request to an individual device
+ */
+static int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data)
+{
+ int status = 0;
+ int next_state;
+ switch (rqst) {
+ case PM_SUSPEND:
+ case PM_RESUME:
+ next_state = (int) data;
+ if (dev->state != next_state) {
+ if (dev->callback)
+ status = (*dev->callback)(dev, rqst, data);
+ if (!status)
+ dev->state = next_state;
+ }
+ break;
+ default:
+ if (dev->callback)
+ status = (*dev->callback)(dev, rqst, data);
+ break;
+ }
+ return status;
+}
+
+/*
+ * Undo incomplete request
+ */
+static void pm_undo_request(struct pm_dev *last, pm_request_t undo, void *data)
+{
+ struct list_head *entry = last->entry.prev;
+ while (entry != &pm_devs) {
+ struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
+ if (dev->callback)
+ pm_send(dev, undo, data);
+ entry = entry->prev;
+ }
+}
+
+/*
+ * Send a request to all devices
+ */
+int pm_send_request(pm_request_t rqst, void *data)
+{
+ struct list_head *entry = pm_devs.next;
+ while (entry != &pm_devs) {
+ struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
+ if (dev->callback) {
+ int status = pm_send(dev, rqst, data);
+ if (status) {
+ /* resume devices on failed suspend request */
+ if (rqst == PM_SUSPEND)
+ pm_undo_request(dev, PM_RESUME, 0);
+ return status;
+ }
+ }
+ entry = entry->next;
+ }
+ return 0;
+}
+
+/*
+ * Find a device
+ */
+struct pm_dev *pm_find(pm_dev_t type, struct pm_dev *from)
+{
+ struct list_head *entry = from ? from->entry.next:pm_devs.next;
+ while (entry != &pm_devs) {
+ struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
+ if (type == PM_UNKNOWN_DEV || dev->type == type)
+ return dev;
+ entry = entry->next;
+ }
+ return 0;
+}
+
+EXPORT_SYMBOL(pm_register);
+EXPORT_SYMBOL(pm_unregister);
+EXPORT_SYMBOL(pm_unregister_all);
+EXPORT_SYMBOL(pm_send_request);
+EXPORT_SYMBOL(pm_find);
void __init init_idle(void)
{
- cycles_t t;
struct schedule_data * sched_data;
sched_data = &aligned_data[smp_processor_id()].schedule_data;
smp_processor_id(), current->pid);
del_from_runqueue(current);
}
- t = get_cycles();
sched_data->curr = current;
- sched_data->last_schedule = t;
+ sched_data->last_schedule = get_cycles();
}
void __init sched_init(void)
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
NULL, /* truncate */
proc_sys_permission, /* permission */
NULL /* revalidate */
read_lock(&tasklist_lock);
for_each_task(p) {
if ((p->state == TASK_RUNNING ||
- (p->state & TASK_UNINTERRUPTIBLE) ||
- (p->state & TASK_SWAPPING)))
+ (p->state & TASK_UNINTERRUPTIBLE)))
nr += FIXED_1;
}
read_unlock(&tasklist_lock);
struct list_head *head, *curr;
struct page * page;
- head = &inode->i_data.pages;
+ head = &inode->i_mapping->pages;
spin_lock(&pagecache_lock);
curr = head->next;
start = (lstart + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
repeat:
- head = &inode->i_data.pages;
+ head = &inode->i_mapping->pages;
spin_lock(&pagecache_lock);
curr = head->next;
while (curr != head) {
struct page *page;
int retval = 0;
- head = &inode->i_data.pages;
+ head = &inode->i_mapping->pages;
spin_lock(&pagecache_lock);
curr = head->next;
static inline int page_cache_read(struct file * file, unsigned long offset)
{
struct inode *inode = file->f_dentry->d_inode;
- struct page **hash = page_hash(&inode->i_data, offset);
+ struct address_space *mapping = inode->i_mapping;
+ struct page **hash = page_hash(mapping, offset);
struct page *page;
spin_lock(&pagecache_lock);
- page = __find_page_nolock(&inode->i_data, offset, *hash);
+ page = __find_page_nolock(mapping, offset, *hash);
spin_unlock(&pagecache_lock);
if (page)
return 0;
if (!page)
return -ENOMEM;
- if (!add_to_page_cache_unique(page, &inode->i_data, offset, hash)) {
- int error = inode->i_op->readpage(file->f_dentry, page);
+ if (!add_to_page_cache_unique(page, mapping, offset, hash)) {
+ int error = mapping->a_ops->readpage(file->f_dentry, page);
page_cache_release(page);
return error;
}
{
struct dentry *dentry = filp->f_dentry;
struct inode *inode = dentry->d_inode;
+ struct address_space *mapping = inode->i_mapping;
unsigned long index, offset;
struct page *cached_page;
int reada_ok;
/*
* Try to find the data in the page cache..
*/
- hash = page_hash(&inode->i_data, index);
+ hash = page_hash(mapping, index);
spin_lock(&pagecache_lock);
- page = __find_page_nolock(&inode->i_data, index, *hash);
+ page = __find_page_nolock(mapping, index, *hash);
if (!page)
goto no_cached_page;
found_page:
readpage:
/* ... and start the actual read. The read will unlock the page. */
- error = inode->i_op->readpage(filp->f_dentry, page);
+ error = mapping->a_ops->readpage(filp->f_dentry, page);
if (!error) {
if (Page_Uptodate(page))
* dropped the page cache lock. Check for that.
*/
spin_lock(&pagecache_lock);
- page = __find_page_nolock(&inode->i_data, index, *hash);
+ page = __find_page_nolock(mapping, index, *hash);
if (page)
goto found_page;
}
* Ok, add the new page to the hash-queues...
*/
page = cached_page;
- __add_to_page_cache(page, &inode->i_data, index, hash);
+ __add_to_page_cache(page, mapping, index, hash);
spin_unlock(&pagecache_lock);
cached_page = NULL;
in_inode = in_file->f_dentry->d_inode;
if (!in_inode)
goto fput_in;
- if (!in_inode->i_op || !in_inode->i_op->readpage)
+ if (!in_inode->i_mapping->a_ops->readpage)
goto fput_in;
retval = locks_verify_area(FLOCK_VERIFY_READ, in_inode, in_file, in_file->f_pos, count);
if (retval)
struct file *file = area->vm_file;
struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode;
+ struct address_space *mapping = inode->i_mapping;
struct page *page, **hash, *old_page;
unsigned long size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
/*
* Do we have something in the page cache already?
*/
- hash = page_hash(&inode->i_data, pgoff);
+ hash = page_hash(mapping, pgoff);
retry_find:
- page = __find_get_page(&inode->i_data, pgoff, hash);
+ page = __find_get_page(mapping, pgoff, hash);
if (!page)
goto no_cached_page;
goto success;
}
- if (!inode->i_op->readpage(file->f_dentry, page)) {
+ if (!mapping->a_ops->readpage(file->f_dentry, page)) {
wait_on_page(page);
if (Page_Uptodate(page))
goto success;
goto success;
}
ClearPageError(page);
- if (!inode->i_op->readpage(file->f_dentry, page)) {
+ if (!mapping->a_ops->readpage(file->f_dentry, page)) {
wait_on_page(page);
if (Page_Uptodate(page))
goto success;
if (size_idx <= index)
return -EIO;
}
- writepage = inode->i_op->writepage;
+ writepage = inode->i_mapping->a_ops->writepage;
lock_page(page);
retval = writepage(file->f_dentry, page);
ops = &file_private_mmap;
if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) {
- if (!inode->i_op || !inode->i_op->writepage)
+ if (!inode->i_mapping->a_ops->writepage)
return -EINVAL;
ops = &file_shared_mmap;
}
if (!inode->i_sb || !S_ISREG(inode->i_mode))
return -EACCES;
- if (!inode->i_op || !inode->i_op->readpage)
+ if (!inode->i_mapping->a_ops->readpage)
return -ENOEXEC;
UPDATE_ATIME(inode);
vma->vm_ops = ops;
return page;
}
+static inline void remove_suid(struct inode *inode)
+{
+ unsigned int mode;
+
+ /* set S_IGID if S_IXGRP is set, and always set S_ISUID */
+ mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID;
+
+ /* was any of the uid bits set? */
+ mode &= inode->i_mode;
+ if (mode && !capable(CAP_FSETID)) {
+ inode->i_mode &= ~mode;
+ mark_inode_dirty(inode);
+ }
+}
+
/*
* Write to a file through the page cache. This is mainly for the
* benefit of NFS and possibly other network-based file systems.
* okir@monad.swb.de
*/
ssize_t
-generic_file_write(struct file *file, const char *buf,
- size_t count, loff_t *ppos,
- writepage_t write_one_page)
+generic_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos)
{
struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode;
+ struct address_space *mapping = inode->i_mapping;
unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
loff_t pos;
struct page *page, *cached_page;
}
status = 0;
+ if (count) {
+ remove_suid(inode);
+ inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+ mark_inode_dirty(inode);
+ }
while (count) {
unsigned long bytes, index, offset;
+ char *kaddr;
/*
* Try to find the page in the cache. If it isn't there,
bytes = count;
status = -ENOMEM; /* we'll assign it later anyway */
- page = __grab_cache_page(&inode->i_data, index, &cached_page);
+ page = __grab_cache_page(mapping, index, &cached_page);
if (!page)
break;
PAGE_BUG(page);
}
- status = write_one_page(file, page, offset, bytes, buf);
+ status = mapping->a_ops->prepare_write(page, offset, offset+bytes);
+ if (status)
+ goto unlock;
+ kaddr = (char*)page_address(page);
+ status = copy_from_user(kaddr+offset, buf, bytes);
+ if (status)
+ goto fail_write;
+ status = mapping->a_ops->commit_write(file, page, offset, offset+bytes);
+ if (!status)
+ status = bytes;
if (status >= 0) {
written += status;
if (pos > inode->i_size)
inode->i_size = pos;
}
+unlock:
/* Mark it unlocked again and drop the page.. */
UnlockPage(page);
page_cache_release(page);
out:
up(&inode->i_sem);
return err;
+fail_write:
+ status = -EFAULT;
+ ClearPageUptodate(page);
+ kunmap(page);
+ goto unlock;
}
void __init page_cache_init(unsigned long mempages)
inode = CurrentRequest->filp->f_dentry->d_inode;
- if ( (inode!=NULL)&&(inode->i_op!=NULL)&&(inode->i_op->readpage!=NULL))
- {
+ if (inode && inode->i_mapping->a_ops->readpage) {
/* This does the actual transfer using sendfile */
read_descriptor_t desc;
loff_t *ppos;
#include <linux/skbuff.h>
#include <net/sock.h>
#include <net/ip.h>
-#if LINUX_VERSION_CODE >= 0x020100
#include <asm/uaccess.h>
-#endif
#include <linux/sunrpc/types.h>
#include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/sunrpc/stats.h>
+/* SMP locking strategy:
+ *
+ * svc_sock->sk_lock and svc_serv->sv_lock protect their
+ * respective structures.
+ *
+ * Antideadlock ordering is sk_lock --> sv_lock.
+ */
#define RPCDBG_FACILITY RPCDBG_SVCSOCK
/*
- * Queue up an idle server thread.
+ * Queue up an idle server thread. Must have serv->sv_lock held.
*/
static inline void
svc_serv_enqueue(struct svc_serv *serv, struct svc_rqst *rqstp)
{
+ BUG_TRAP(spin_is_locked(&serv->sv_lock));
rpc_append_list(&serv->sv_threads, rqstp);
}
/*
- * Dequeue an nfsd thread.
+ * Dequeue an nfsd thread. Must have serv->sv_lock held.
*/
static inline void
svc_serv_dequeue(struct svc_serv *serv, struct svc_rqst *rqstp)
{
+ BUG_TRAP(spin_is_locked(&serv->sv_lock));
rpc_remove_list(&serv->sv_threads, rqstp);
}
/*
* Queue up a socket with data pending. If there are idle nfsd
* processes, wake 'em up.
- * When calling this function, you should make sure it can't be interrupted
- * by the network bottom half.
+ *
+ * This must be called with svsk->sk_lock held.
*/
static void
svc_sock_enqueue(struct svc_sock *svsk)
BUG_TRAP(spin_is_locked(&svsk->sk_lock));
+ /* NOTE: Local BH is already disabled by our caller. */
+ spin_lock(&serv->sv_lock);
+
if (serv->sv_threads && serv->sv_sockets)
printk(KERN_ERR
"svc_sock_enqueue: threads and sockets both waiting??\n");
if (svsk->sk_busy) {
/* Don't enqueue socket while daemon is receiving */
dprintk("svc: socket %p busy, not enqueued\n", svsk->sk_sk);
- return;
+ goto out_unlock;
}
/* Mark socket as busy. It will remain in this state until the
rpc_append_list(&serv->sv_sockets, svsk);
svsk->sk_qued = 1;
}
+
+out_unlock:
+ spin_unlock(&serv->sv_lock);
}
/*
- * Dequeue the first socket.
+ * Dequeue the first socket. Must be called with the serv->sv_lock held.
*/
static inline struct svc_sock *
svc_sock_dequeue(struct svc_serv *serv)
{
struct svc_sock *svsk;
- spin_lock_bh(&serv->sv_lock);
+ BUG_TRAP(spin_is_locked(&serv->sv_lock));
+
if ((svsk = serv->sv_sockets) != NULL)
rpc_remove_list(&serv->sv_sockets, svsk);
- spin_unlock_bh(&serv->sv_lock);
if (svsk) {
dprintk("svc: socket %p dequeued, inuse=%d\n",
{
struct svc_rqst *rqstp;
+ spin_lock_bh(&serv->sv_lock);
if ((rqstp = serv->sv_threads) != NULL) {
dprintk("svc: daemon %p woken up.\n", rqstp);
/*
*/
wake_up(&rqstp->rq_wait);
}
+ spin_unlock_bh(&serv->sv_lock);
}
/*
msg.msg_control = NULL;
msg.msg_controllen = 0;
-#if LINUX_VERSION_CODE >= 0x020100
msg.msg_flags = MSG_DONTWAIT;
oldfs = get_fs(); set_fs(KERNEL_DS);
len = sock_sendmsg(sock, &msg, buflen);
set_fs(oldfs);
-#else
- msg.msg_flags = 0;
-
- oldfs = get_fs(); set_fs(KERNEL_DS);
- len = sock->ops->sendmsg(sock, &msg, buflen, 1, 0);
- set_fs(oldfs);
-#endif
dprintk("svc: socket %p sendto([%p %Zu... ], %d, %d) = %d\n",
rqstp->rq_sock, iov[0].iov_base, iov[0].iov_len, nr, buflen, len);
msg.msg_control = NULL;
msg.msg_controllen = 0;
-#if LINUX_VERSION_CODE >= 0x020100
msg.msg_flags = MSG_DONTWAIT;
oldfs = get_fs(); set_fs(KERNEL_DS);
len = sock_recvmsg(sock, &msg, buflen, MSG_DONTWAIT);
set_fs(oldfs);
-#else
- msg.msg_flags = 0;
-
- oldfs = get_fs(); set_fs(KERNEL_DS);
- len = sock->ops->recvmsg(sock, &msg, buflen, 0, 1, &rqstp->rq_addrlen);
- set_fs(oldfs);
-#endif
dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
rqstp->rq_sock, iov[0].iov_base, iov[0].iov_len, len);
/* Get sender address */
rqstp->rq_addr.sin_family = AF_INET;
rqstp->rq_addr.sin_port = skb->h.uh->source;
-#if LINUX_VERSION_CODE >= 0x020100
rqstp->rq_addr.sin_addr.s_addr = skb->nh.iph->saddr;
-#else
- rqstp->rq_addr.sin_addr.s_addr = skb->saddr;
-#endif
if (serv->sv_stats)
serv->sv_stats->netudpcnt++;
}
memset(svsk, 0, sizeof(*svsk));
-#if LINUX_VERSION_CODE >= 0x020100
inet = sock->sk;
-#else
- inet = (struct sock *) sock->data;
-#endif
inet->user_data = svsk;
svsk->sk_sock = sock;
svsk->sk_sk = inet;
return NULL;
}
+ spin_lock_bh(&serv->sv_lock);
svsk->sk_list = serv->sv_allsocks;
serv->sv_allsocks = svsk;
+ spin_unlock_bh(&serv->sv_lock);
dprintk("svc: svc_setup_socket created %p (inet %p)\n",
svsk, svsk->sk_sk);
sk->state_change = svsk->sk_ostate;
sk->data_ready = svsk->sk_odata;
+ spin_lock_bh(&serv->sv_lock);
+
for (rsk = &serv->sv_allsocks; *rsk; rsk = &(*rsk)->sk_list) {
if (*rsk == svsk)
break;
}
- if (!*rsk)
+ if (!*rsk) {
+ spin_unlock_bh(&serv->sv_lock);
return;
+ }
*rsk = svsk->sk_list;
-
if (svsk->sk_qued)
rpc_remove_list(&serv->sv_sockets, svsk);
+
+ spin_unlock_bh(&serv->sv_lock);
+
svsk->sk_dead = 1;
if (!svsk->sk_inuse) {
if (!access_ok(VERIFY_READ, buffer, left))
return -EFAULT;
p = (char *) buffer;
-#if LINUX_VERSION_CODE >= 0x020100
while (left && __get_user(c, p) >= 0 && isspace(c))
left--, p++;
-#else
- while (left && (c = get_fs_byte(p)) >= 0 && isspace(c))
- left--, p++;
-#endif
if (!left)
goto done;
#include <asm/uaccess.h>
-#define SOCK_HAS_USER_DATA
/* Following value should be > 32k + RPC overhead */
#define XPRT_MIN_WRITE_SPACE 35000
-/*
- * Local variables
- */
-#ifndef SOCK_HAS_USER_DATA
-static struct rpc_xprt * sock_list = NULL;
-#endif
-
/* Spinlock for critical sections in the code. */
spinlock_t xprt_lock = SPIN_LOCK_UNLOCKED;
static inline struct rpc_xprt *
xprt_from_sock(struct sock *sk)
{
-#ifndef SOCK_HAS_USER_DATA
- struct rpc_xprt *xprt;
-
- for (xprt = sock_list; xprt && sk != xprt->inet; xprt = xprt->link)
- ;
- return xprt;
-#else
return (struct rpc_xprt *) sk->user_data;
-#endif
}
/*
xprt_disconnect(xprt);
-#ifdef SOCK_HAS_USER_DATA
sk->user_data = NULL;
-#endif
sk->data_ready = xprt->old_data_ready;
sk->state_change = xprt->old_state_change;
sk->write_space = xprt->old_write_space;
inet->data_ready = xprt->inet->data_ready;
inet->state_change = xprt->inet->state_change;
inet->write_space = xprt->inet->write_space;
-#ifdef SOCK_HAS_USER_DATA
inet->user_data = xprt;
-#endif
dprintk("RPC: %4d closing old socket\n", task->tk_pid);
xprt_close(xprt);
xprt->stream = (proto == IPPROTO_TCP)? 1 : 0;
xprt->congtime = jiffies;
init_waitqueue_head(&xprt->cong_wait);
-#ifdef SOCK_HAS_USER_DATA
inet->user_data = xprt;
-#else
- xprt->link = sock_list;
- sock_list = xprt;
-#endif
xprt->old_data_ready = inet->data_ready;
xprt->old_state_change = inet->state_change;
xprt->old_write_space = inet->write_space;
int
xprt_destroy(struct rpc_xprt *xprt)
{
-#ifndef SOCK_HAS_USER_DATA
- struct rpc_xprt **q;
-
- for (q = &sock_list; *q && *q != xprt; q = &((*q)->link))
- ;
- if (!*q) {
- printk(KERN_WARNING "xprt_destroy: unknown socket!\n");
- return -EIO; /* why is there no EBUGGYSOFTWARE */
- }
- *q = xprt->link;
-#endif
-
dprintk("RPC: destroying transport %p\n", xprt);
xprt_close(xprt);
kfree(xprt);
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
NULL, /* truncate */
router_proc_perms, /* permission */
NULL /* revalidate */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
NULL, /* truncate */
router_proc_perms, /* permission */
NULL /* revalidate */