From 53022f15f8c0381a9b55bbe2893a5f9f6abda6f3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:28:35 -0500 Subject: [PATCH] Import 2.3.27 --- Documentation/Configure.help | 58 +- Documentation/acpi.txt | 18 +- Makefile | 6 + arch/arm/mm/small_page.c | 4 +- arch/i386/boot/compressed/misc.c | 1 + arch/i386/defconfig | 13 + arch/i386/kernel/Makefile | 3 - arch/i386/kernel/head.S | 1 + arch/i386/kernel/mtrr.c | 2 +- arch/i386/mm/init.c | 93 +- arch/ppc/amiga/config.c | 2 +- arch/ppc/kernel/chrp_setup.c | 2 +- arch/ppc/kernel/pmac_setup.c | 2 +- arch/ppc/kernel/prep_setup.c | 2 +- arch/ppc/mm/extable.c | 7 +- arch/ppc/mm/init.c | 4 +- drivers/acorn/scsi/acornscsi.c | 6 +- drivers/acorn/scsi/acornscsi.h | 3 - drivers/acorn/scsi/arxescsi.c | 7 +- drivers/acorn/scsi/cumana_1.c | 6 +- drivers/acorn/scsi/cumana_2.c | 7 +- drivers/acorn/scsi/ecoscsi.c | 6 +- drivers/acorn/scsi/eesox.c | 7 +- drivers/acorn/scsi/oak.c | 6 +- drivers/acorn/scsi/powertec.c | 7 +- drivers/block/ide.c | 1 + drivers/block/ll_rw_blk.c | 10 + drivers/cdrom/cdrom.c | 19 +- drivers/char/Config.in | 4 + drivers/char/Makefile | 11 +- drivers/char/console.c | 29 + drivers/char/keyboard.c | 3 +- drivers/char/pcmcia/Config.in | 31 + drivers/char/pcmcia/Makefile | 27 + drivers/char/pcmcia/serial_cb.c | 150 ++ drivers/char/pcmcia/serial_cs.c | 667 ++++++ drivers/char/stradis.c | 1 - drivers/i2o/i2o_scsi.c | 4 - drivers/i2o/i2o_scsi.h | 4 +- drivers/misc/acpi.c | 136 +- drivers/net/8390.c | 3 + drivers/net/fc/iph5526.c | 7 +- drivers/net/mace.c | 1 + drivers/net/pcmcia/3c574_cs.c | 4 +- drivers/net/pcmcia/3c575_cb.c | 2215 +++++++++++++++++++ drivers/net/pcmcia/3c589_cs.c | 8 +- drivers/net/pcmcia/Config.in | 10 +- drivers/net/pcmcia/Makefile | 142 +- drivers/net/pcmcia/netwave_cs.c | 2 +- drivers/net/pcmcia/nmclan_cs.c | 2 +- drivers/net/pcmcia/pcnet_cs.c | 64 +- drivers/net/pcmcia/smc91c92_cs.c | 22 +- drivers/net/pcmcia/tulip_cb.c | 3383 ++++++++++++++++++++++++++++++ drivers/net/pcmcia/wavelan_cs.h | 4 +- drivers/net/pcmcia/xirc2ps_cs.c | 961 ++++----- drivers/net/ppp_async.c | 10 + drivers/net/seeq8005.c | 3 +- drivers/net/setup.c | 4 +- drivers/pcmcia/bulkmem.c | 4 +- drivers/pcmcia/cardbus.c | 17 +- drivers/pcmcia/cb_enabler.c | 6 +- drivers/pcmcia/cirrus.h | 4 +- drivers/pcmcia/cistpl.c | 6 +- drivers/pcmcia/cs.c | 52 +- drivers/pcmcia/cs_internal.h | 20 +- drivers/pcmcia/ds.c | 44 +- drivers/pcmcia/i82365.c | 40 +- drivers/pcmcia/i82365.h | 4 +- drivers/pcmcia/o2micro.h | 4 +- drivers/pcmcia/ricoh.h | 4 +- drivers/pcmcia/rsrc_mgr.c | 86 +- drivers/pcmcia/rsrc_mgr.h | 4 +- drivers/pcmcia/smc34c90.h | 4 +- drivers/pcmcia/tcic.c | 6 +- drivers/pcmcia/tcic.h | 4 +- drivers/pcmcia/ti113x.h | 4 +- drivers/pcmcia/vg468.h | 4 +- drivers/pcmcia/yenta.h | 4 +- drivers/scsi/53c7,8xx.c | 11 +- drivers/scsi/AM53C974.c | 8 +- drivers/scsi/AM53C974.h | 4 +- drivers/scsi/BusLogic.c | 10 - drivers/scsi/BusLogic.h | 3 +- drivers/scsi/NCR53C9x.c | 5 - drivers/scsi/NCR53C9x.h | 2 - drivers/scsi/NCR53c406a.c | 6 +- drivers/scsi/NCR53c406a.h | 4 +- drivers/scsi/a2091.c | 7 +- drivers/scsi/a2091.h | 4 +- drivers/scsi/a3000.c | 7 +- drivers/scsi/a3000.h | 4 +- drivers/scsi/advansys.c | 17 +- drivers/scsi/advansys.h | 96 +- drivers/scsi/aha152x.c | 17 +- drivers/scsi/aha152x.h | 4 +- drivers/scsi/aha1542.c | 7 +- drivers/scsi/aha1542.h | 4 +- drivers/scsi/aha1740.c | 5 - drivers/scsi/aha1740.h | 4 +- drivers/scsi/aic7xxx.c | 8 +- drivers/scsi/aic7xxx.h | 27 - drivers/scsi/amiga7xx.c | 7 +- drivers/scsi/amiga7xx.h | 2 - drivers/scsi/atari_scsi.c | 7 +- drivers/scsi/atp870u.c | 8 +- drivers/scsi/atp870u.h | 6 +- drivers/scsi/blz1230.h | 2 +- drivers/scsi/blz2060.h | 2 +- drivers/scsi/bvme6000.c | 7 +- drivers/scsi/bvme6000.h | 2 - drivers/scsi/cyberstorm.h | 2 +- drivers/scsi/cyberstormII.h | 2 +- drivers/scsi/dc390.h | 3 +- drivers/scsi/dec_esp.h | 2 +- drivers/scsi/dtc.c | 9 +- drivers/scsi/eata.c | 7 +- drivers/scsi/eata_dma.c | 7 +- drivers/scsi/eata_pio.c | 7 +- drivers/scsi/esp.c | 5 - drivers/scsi/esp.h | 4 +- drivers/scsi/fastlane.h | 2 +- drivers/scsi/fcal.c | 7 +- drivers/scsi/fd_mcs.c | 5 - drivers/scsi/fd_mcs.h | 4 +- drivers/scsi/fdomain.c | 9 +- drivers/scsi/fdomain.h | 2 - drivers/scsi/g_NCR5380.c | 7 +- drivers/scsi/gdth.c | 265 --- drivers/scsi/gdth.h | 58 +- drivers/scsi/gvp11.c | 7 +- drivers/scsi/gvp11.h | 4 +- drivers/scsi/hosts.c | 2 + drivers/scsi/hosts.h | 6 + drivers/scsi/ibmmca.c | 9 - drivers/scsi/ibmmca.h | 35 +- drivers/scsi/ide-scsi.c | 4 +- drivers/scsi/imm.h | 5 +- drivers/scsi/in2000.c | 9 +- drivers/scsi/in2000.h | 42 +- drivers/scsi/ini9100u.c | 276 +-- drivers/scsi/ini9100u.h | 59 +- drivers/scsi/inia100.c | 155 +- drivers/scsi/inia100.h | 63 +- drivers/scsi/ips.c | 16 +- drivers/scsi/ips.h | 1 - drivers/scsi/jazz_esp.h | 2 +- drivers/scsi/mac53c94.c | 5 - drivers/scsi/mac53c94.h | 4 +- drivers/scsi/mac_esp.h | 2 +- drivers/scsi/mac_scsi.c | 6 +- drivers/scsi/mca_53c9x.h | 2 +- drivers/scsi/megaraid.c | 54 +- drivers/scsi/megaraid.h | 2 - drivers/scsi/mesh.c | 5 - drivers/scsi/mesh.h | 4 +- drivers/scsi/mvme16x.c | 7 +- drivers/scsi/mvme16x.h | 2 - drivers/scsi/ncr53c8xx.c | 6 +- drivers/scsi/oktagon_esp.h | 2 +- drivers/scsi/pas16.c | 6 +- drivers/scsi/pci2000.c | 46 - drivers/scsi/pci2000.h | 28 +- drivers/scsi/pci2220i.c | 87 - drivers/scsi/pci2220i.h | 28 +- drivers/scsi/pluto.c | 7 +- drivers/scsi/ppa.h | 5 +- drivers/scsi/psi240i.c | 3 - drivers/scsi/psi240i.h | 4 +- drivers/scsi/qlogicfas.c | 7 +- drivers/scsi/qlogicfc.c | 9 +- drivers/scsi/qlogicisp.c | 8 +- drivers/scsi/qlogicpti.c | 7 +- drivers/scsi/scsi.c | 51 +- drivers/scsi/scsi.h | 43 - drivers/scsi/scsi_debug.c | 9 +- drivers/scsi/scsi_ioctl.c | 2 +- drivers/scsi/scsi_proc.c | 242 +-- drivers/scsi/scsi_syms.c | 1 - drivers/scsi/sd.c | 149 +- drivers/scsi/seagate.c | 8 +- drivers/scsi/sgiwd93.c | 7 +- drivers/scsi/sgiwd93.h | 4 +- drivers/scsi/sim710.c | 8 +- drivers/scsi/sim710.h | 4 +- drivers/scsi/sun3_scsi.c | 6 +- drivers/scsi/sun3x_esp.h | 4 +- drivers/scsi/sym53c416.c | 6 +- drivers/scsi/sym53c416.h | 35 +- drivers/scsi/sym53c8xx.c | 12 +- drivers/scsi/t128.c | 8 +- drivers/scsi/tmscsim.c | 8 +- drivers/scsi/u14-34f.c | 7 +- drivers/scsi/ultrastor.c | 7 +- drivers/scsi/wd7000.c | 13 +- drivers/scsi/wd7000.h | 5 +- drivers/sound/sb_card.c | 87 +- drivers/usb/proc_usb.c | 1 + drivers/usb/usb_scsi.c | 2 +- fs/binfmt_misc.c | 22 +- fs/buffer.c | 89 +- fs/coda/sysctl.c | 11 +- fs/exec.c | 22 +- fs/ncpfs/mmap.c | 2 +- fs/nfsd/nfsctl.c | 15 - fs/nfsd/stats.c | 5 +- fs/proc/inode-alloc.txt | 9 +- fs/proc/inode.c | 16 +- fs/proc/kcore.c | 231 +- fs/proc/proc_misc.c | 30 +- fs/proc/procfs_syms.c | 2 - fs/proc/root.c | 3 - fs/udf/udfdecl.h | 3 +- fs/ufs/balloc.c | 2 +- fs/ufs/dir.c | 2 +- fs/ufs/inode.c | 2 +- fs/ufs/super.c | 4 +- fs/ufs/truncate.c | 10 +- fs/ufs/util.h | 1 - include/asm-i386/highmem.h | 96 +- include/asm-i386/io.h | 3 +- include/asm-i386/kmap_types.h | 6 +- include/asm-ppc/fcntl.h | 32 +- include/linux/acpi.h | 101 +- include/linux/bootmem.h | 1 - include/linux/fs.h | 11 +- include/linux/highmem.h | 25 +- include/linux/mm.h | 10 +- include/linux/module.h | 1 - include/linux/pagemap.h | 2 +- include/linux/proc_fs.h | 75 +- include/linux/swap.h | 6 +- include/linux/videodev.h | 74 +- include/linux/vmalloc.h | 1 + include/pcmcia/bulkmem.h | 4 +- include/pcmcia/bus_ops.h | 4 +- include/pcmcia/ciscode.h | 4 +- include/pcmcia/cisreg.h | 4 +- include/pcmcia/cistpl.h | 4 +- include/pcmcia/cs.h | 4 +- include/pcmcia/cs_types.h | 4 +- include/pcmcia/driver_ops.h | 4 +- include/pcmcia/ds.h | 4 +- include/pcmcia/ftl.h | 4 +- include/pcmcia/mem_op.h | 4 +- include/pcmcia/memory.h | 4 +- include/pcmcia/ss.h | 4 +- include/pcmcia/version.h | 6 +- ipc/shm.c | 46 +- kernel/module.c | 26 - kernel/ptrace.c | 8 +- mm/filemap.c | 26 +- mm/highmem.c | 288 ++- mm/memory.c | 4 +- mm/page_alloc.c | 56 +- mm/swapfile.c | 24 +- mm/vmalloc.c | 4 +- net/ipv4/tcp_input.c | 11 +- net/irda/irmod.c | 18 - net/irda/irproc.c | 5 +- net/sunrpc/stats.c | 19 +- net/sunrpc/sysctl.c | 5 +- scripts/usb/procusb | 44 + scripts/usb/usbtree | 90 + 263 files changed, 8861 insertions(+), 3816 deletions(-) create mode 100644 drivers/char/pcmcia/Config.in create mode 100644 drivers/char/pcmcia/Makefile create mode 100644 drivers/char/pcmcia/serial_cb.c create mode 100644 drivers/char/pcmcia/serial_cs.c create mode 100644 drivers/net/pcmcia/3c575_cb.c create mode 100644 drivers/net/pcmcia/tulip_cb.c create mode 100644 scripts/usb/procusb create mode 100644 scripts/usb/usbtree diff --git a/Documentation/Configure.help b/Documentation/Configure.help index e2cda118fafe..b56f5eba5b6b 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -1680,6 +1680,29 @@ CONFIG_HUB6 Say Y here to enable support in the dumb serial driver to support the HUB6 card. +PCMCIA serial device support +CONFIG_PCMCIA_SERIAL_CS + Say Y here to enable support for 16-bit PCMCIA serial devices, + including serial port cards, modems, and the modem functions of + multifunction ethernet/modem cards. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called serial_cs.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. If unsure, + say N. + +CardBus serial device support +CONFIG_PCMCIA_SERIAL_CB + Say Y here to enable support for CardBus serial devices, including + the modem functions of multifunction ethernet/modem devices. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called serial_cb.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. If unsure, + say N. + PCI support CONFIG_PCI Find out whether you have a PCI motherboard. PCI is the name of a @@ -5607,6 +5630,36 @@ CONFIG_PCMCIA_XIRC2PS module, say M here and read Documentation/modules.txt. If unsure, say N. +3Com 3c575 CardBus support +CONFIG_PCMCIA_3C575 + This driver supports the 3Com 3c575 series of CardBus Fast Ethernet + adapters. + + This driver can only be compiled as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called 3c575_cb.o. If you want to do that, say M + here and read Documentation/modules.txt. If unsure, say N. + +DEC Tulip CardBus support +CONFIG_PCMCIA_TULIP + This driver supports CardBus Fast Ethernet adapters based on DEC + Tulip and compatible chipsets. + + This driver can only be compiled as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called tulip_cb.o. If you want to do that, say M + here and read Documentation/modules.txt. If unsure, say N. + +SMC EPIC CardBus support +CONFIG_PCMCIA_EPIC100 + This driver supports CardBus Fast Ethernet adapters based on the SMC + EPIC chipset. + + This driver can only be compiled as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called epic100_cb.o. If you want to do that, say + M here and read Documentation/modules.txt. If unsure, say N. + Aviator/Raytheon 2.4MHz wireless support CONFIG_PCMCIA_RAYCS Say Y here if you intend to attach an Aviator/Raytheon PCMCIA @@ -7925,11 +7978,6 @@ CONFIG_ACPI specification to support power management of peripherals. If your system supports it, say Y here. - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called acpi.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. - Minix fs support CONFIG_MINIX_FS Minix is a simple operating system used in many classes about OS's. diff --git a/Documentation/acpi.txt b/Documentation/acpi.txt index 6f86ab592508..9629eb29e709 100644 --- a/Documentation/acpi.txt +++ b/Documentation/acpi.txt @@ -15,10 +15,11 @@ Overview: * Description: Register a device with the ACPI subsystem * * Parameters: - * type - device type + * info - static device information + * type - device type + * hid - PnP identifier (or 0 if unknown) + * trans - device state transition callback * adr - bus number and address or unique id - * hid - PnP identifier (or 0 if unknown) - * trans - device state transition callback * * Returns: Registered ACPI device or NULL on error * @@ -27,15 +28,14 @@ Overview: * identify device dependencies * * Examples: - * dev = acpi_register(ACPI_SYS_DEV, 0, ACPI_VGA_HID, vga_trans); + * struct acpi_dev_info info = {ACPI_SYS_DEV, ACPI_VGA_HID, vga_trans}; + * dev = acpi_register(&info, 0); * * struct pci_dev *pci_dev = pci_find_dev(...); - * dev = acpi_register(ACPI_PCI_DEV, ACPI_PCI_ADR(pci_dev), 0, trans); + * struct acpi_dev_info info = {ACPI_PCI_DEV, 0, trans}; + * dev = acpi_register(&info, ACPI_PCI_ADR(pci_dev)); */ -struct acpi_dev *acpi_register(acpi_dev_t type, - unsigned long adr, - acpi_hid_t hid, - acpi_transition trans); +struct acpi_dev *acpi_register(struct acpi_dev_info *info, unsigned long adr); /* * Description: Unregister a device with ACPI diff --git a/Makefile b/Makefile index df4352ca18cd..7eb9122fff97 100644 --- a/Makefile +++ b/Makefile @@ -166,6 +166,10 @@ ifeq ($(CONFIG_PCMCIA_NETCARD),y) DRIVERS := $(DRIVERS) drivers/net/pcmcia/pcmcia_net.o endif +ifeq ($(CONFIG_PCMCIA_CHRDEV),y) +DRIVERS := $(DRIVERS) drivers/char/pcmcia/pcmcia_char.o +endif + ifdef CONFIG_DIO DRIVERS := $(DRIVERS) drivers/dio/dio.a endif @@ -362,6 +366,8 @@ modules_install: if [ -f IRDA_MODULES ]; then inst_mod IRDA_MODULES net; fi; \ if [ -f USB_MODULES ]; then inst_mod USB_MODULES usb; fi; \ if [ -f PCMCIA_MODULES ]; then inst_mod PCMCIA_MODULES pcmcia; fi; \ + if [ -f PCMCIA_NET_MODULES ]; then inst_mod PCMCIA_NET_MODULES pcmcia; fi; \ + if [ -f PCMCIA_CHAR_MODULES ]; then inst_mod PCMCIA_CHAR_MODULES pcmcia; fi; \ \ ls *.o > $$MODLIB/.allmods; \ echo $$MODULES | tr ' ' '\n' | sort | comm -23 $$MODLIB/.allmods - > $$MODLIB/.misc; \ diff --git a/arch/arm/mm/small_page.c b/arch/arm/mm/small_page.c index f82089800334..ac303d45ec15 100644 --- a/arch/arm/mm/small_page.c +++ b/arch/arm/mm/small_page.c @@ -33,7 +33,7 @@ * second level page tables on 32-bit ARMs. * * Theory: - * We "misuse" the Linux memory management system. We use __get_pages + * We "misuse" the Linux memory management system. We use alloc_page * to allocate a page and then mark it as reserved. The Linux memory * management system will then ignore the "offset", "next_hash" and * "pprev_hash" entries in the mem_map for this page. @@ -119,7 +119,7 @@ again: return page_address(page) + (offset << order->shift); need_new_page: - page = __get_pages(priority, 0); + page = alloc_page(priority); if (!order->queue) { if (!page) goto no_page; diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c index 128b534276b9..92ae6af45670 100644 --- a/arch/i386/boot/compressed/misc.c +++ b/arch/i386/boot/compressed/misc.c @@ -9,6 +9,7 @@ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 */ +#include #include #include diff --git a/arch/i386/defconfig b/arch/i386/defconfig index e3bb17a89bf6..6aa8412c121b 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -299,6 +299,9 @@ CONFIG_PCMCIA_PCNET=y # CONFIG_PCMCIA_NMCLAN is not set # CONFIG_PCMCIA_SMC91C92 is not set # CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_3C575 is not set +# CONFIG_PCMCIA_TULIP is not set +# CONFIG_PCMCIA_EPIC100 is not set CONFIG_PCMCIA_RAYCS=y # CONFIG_PCMCIA_NETWAVE is not set # CONFIG_PCMCIA_WAVELAN is not set @@ -345,6 +348,10 @@ CONFIG_PSMOUSE=y # CONFIG_82C710_MOUSE is not set # CONFIG_PC110_PAD is not set # CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set @@ -367,6 +374,12 @@ CONFIG_PSMOUSE=y # # CONFIG_FTAPE is not set +# +# PCMCIA character device support +# +# CONFIG_PCMCIA_SERIAL_CS is not set +# CONFIG_PCMCIA_SERIAL_CB is not set + # # USB drivers - not for the faint of heart # diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index 29afabd7abbf..55790ac25e5b 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -59,7 +59,4 @@ ifdef CONFIG_X86_VISWS_APIC O_OBJS += visws_apic.o endif -head.o: head.S - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o - include $(TOPDIR)/Rules.make diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index 423308aae0b6..b3f1335d0913 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -8,6 +8,7 @@ */ .text +#include #include #include #include diff --git a/arch/i386/kernel/mtrr.c b/arch/i386/kernel/mtrr.c index a5a4b447f58e..9e612451cd86 100644 --- a/arch/i386/kernel/mtrr.c +++ b/arch/i386/kernel/mtrr.c @@ -1204,7 +1204,7 @@ int mtrr_add (unsigned long base, unsigned long size, unsigned int type, i = (*get_free_region) (base, size); if (i < 0) { - spin_unlock (&main_lock); + up(&main_lock); printk ("mtrr: no more MTRRs available\n"); return i; } diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 099696197020..7a05654d87d4 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -171,9 +171,11 @@ int do_check_pgt_cache(int low, int high) return freed; } -/* NOTE: fixmap_init alloc all the fixmap pagetables contigous on the - physical space so we can cache the place of the first one and move - around without checking the pgd every time. */ +/* + * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the + * physical space so we can cache the place of the first one and move + * around without checking the pgd every time. + */ #if CONFIG_HIGHMEM pte_t *kmap_pte; @@ -268,6 +270,44 @@ void set_fixmap (enum fixed_addresses idx, unsigned long phys) set_pte_phys (address,phys); } +static void __init fixrange_init (unsigned long start, unsigned long end, pgd_t *pgd_base) +{ + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + int i, j; + + i = __pgd_offset(start); + j = __pmd_offset(start); + pgd = pgd_base + i; + + for ( ; (i < PTRS_PER_PGD) && (start != end); pgd++, i++) { +#if CONFIG_X86_PAE + if (pgd_none(*pgd)) { + pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); + memset((void*)pmd, 0, PAGE_SIZE); + pgd_val(*pgd) = __pa(pmd) + 0x1; + if (pmd != pmd_offset(pgd, start)) + BUG(); + } + pmd = pmd_offset(pgd, start); +#else + pmd = (pmd_t *)pgd; +#endif + for (; (j < PTRS_PER_PMD) && start; pmd++, j++) { + if (pmd_none(*pmd)) { + pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); + memset((void*)pte, 0, PAGE_SIZE); + pmd_val(*pmd) = _KERNPG_TABLE + __pa(pte); + if (pte != pte_offset(pmd, 0)) + BUG(); + } + start += PMD_SIZE; + } + j = 0; + } +} + static void __init pagetable_init(void) { pgd_t *pgd, *pgd_base; @@ -331,37 +371,21 @@ static void __init pagetable_init(void) * Fixed mappings, only the page table structure has to be * created - mappings will be set by set_fixmap(): */ - vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; - i = __pgd_offset(vaddr); - j = __pmd_offset(vaddr); - pgd = pgd_base + i; + fixrange_init(vaddr, 0, pgd_base); - for ( ; (i < PTRS_PER_PGD) && vaddr; pgd++, i++) { -#if CONFIG_X86_PAE - if (pgd_none(*pgd)) { - pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); - memset((void*)pmd, 0, PAGE_SIZE); - pgd_val(*pgd) = __pa(pmd) + 0x1; - if (pmd != pmd_offset(pgd, vaddr)) - BUG(); - } - pmd = pmd_offset(pgd, vaddr); -#else - pmd = (pmd_t *)pgd; +#if CONFIG_HIGHMEM + /* + * Permanent kmaps: + */ + vaddr = PKMAP_BASE; + fixrange_init(vaddr, vaddr + 4*1024*1024, pgd_base); + + pgd = swapper_pg_dir + __pgd_offset(vaddr); + pmd = pmd_offset(pgd, vaddr); + pte = pte_offset(pmd, vaddr); + pkmap_page_table = pte; #endif - for (; (j < PTRS_PER_PMD) && vaddr; pmd++, j++) { - if (pmd_none(*pmd)) { - pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); - memset((void*)pte, 0, PAGE_SIZE); - pmd_val(*pmd) = _KERNPG_TABLE + __pa(pte); - if (pte != pte_offset(pmd, 0)) - BUG(); - } - vaddr += PMD_SIZE; - } - j = 0; - } #if CONFIG_X86_PAE /* @@ -389,6 +413,7 @@ void __init zap_low_mappings (void) */ for (i = 0; i < USER_PTRS_PER_PGD; i++) pgd_val(swapper_pg_dir[i]) = 0; + flush_tlb_all(); } /* @@ -420,7 +445,7 @@ void __init paging_init(void) #endif #ifdef CONFIG_HIGHMEM - kmap_init(); /* run after fixmap_init */ + kmap_init(); #endif { unsigned int zones_size[3]; @@ -446,7 +471,6 @@ void __init test_wp_bit(void) /* * Ok, all PAE-capable CPUs are definitely handling the WP bit right. */ -//#ifndef CONFIG_X86_PAE const unsigned long vaddr = PAGE_OFFSET; pgd_t *pgd; pmd_t *pmd; @@ -483,7 +507,6 @@ void __init test_wp_bit(void) #endif } else printk(".\n"); -//#endif } static inline int page_is_ram (unsigned long pagenr) @@ -577,7 +600,7 @@ void __init mem_init(void) void free_initmem(void) { unsigned long addr; - + addr = (unsigned long)(&__init_begin); for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { ClearPageReserved(mem_map + MAP_NR(addr)); diff --git a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c index 29b738eec055..652eb1582f3e 100644 --- a/arch/ppc/amiga/config.c +++ b/arch/ppc/amiga/config.c @@ -6,7 +6,6 @@ void (*mach_kbd_reset_setup) (char *, int) __initdata = 0; #include -#include /* * linux/arch/m68k/amiga/config.c @@ -32,6 +31,7 @@ void (*mach_kbd_reset_setup) (char *, int) __initdata = 0; #include #include +#include #include #include #include diff --git a/arch/ppc/kernel/chrp_setup.c b/arch/ppc/kernel/chrp_setup.c index d0825ce8bddf..938cea36dc5d 100644 --- a/arch/ppc/kernel/chrp_setup.c +++ b/arch/ppc/kernel/chrp_setup.c @@ -11,7 +11,6 @@ */ #include -#include #include #include #include @@ -34,6 +33,7 @@ #include #include #include +#include #include #include diff --git a/arch/ppc/kernel/pmac_setup.c b/arch/ppc/kernel/pmac_setup.c index f494b04c7e84..4c3e9a790a3f 100644 --- a/arch/ppc/kernel/pmac_setup.c +++ b/arch/ppc/kernel/pmac_setup.c @@ -39,9 +39,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/arch/ppc/kernel/prep_setup.c b/arch/ppc/kernel/prep_setup.c index fe7043206541..1bfc63c63a8c 100644 --- a/arch/ppc/kernel/prep_setup.c +++ b/arch/ppc/kernel/prep_setup.c @@ -210,7 +210,7 @@ no_l2: } void __init -prep_setup_arch() +prep_setup_arch(void) { extern char cmd_line[]; unsigned char reg; diff --git a/arch/ppc/mm/extable.c b/arch/ppc/mm/extable.c index afcf705e14a6..dc57bf86845b 100644 --- a/arch/ppc/mm/extable.c +++ b/arch/ppc/mm/extable.c @@ -43,13 +43,18 @@ search_exception_table(unsigned long addr) #else /* The kernel is the last "module" -- no need to treat it special. */ struct module *mp; + read_lock(&modlist_lock); for (mp = module_list; mp != NULL; mp = mp->next) { if (mp->ex_table_start == NULL) continue; ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, addr); - if (ret) return ret; + if (ret) { + read_unlock(&modlist_lock); + return ret; + } } + read_unlock(&modlist_lock); #endif return 0; diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index f3efef24ac43..025145d71aad 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -348,7 +348,7 @@ void si_meminfo(struct sysinfo *val) i = max_mapnr; val->totalram = 0; val->sharedram = 0; - val->freeram = nr_free_pages << PAGE_SHIFT; + val->freeram = nr_free_pages(); val->bufferram = atomic_read(&buffermem_pages); while (i-- > 0) { if (PageReserved(mem_map+i)) @@ -1215,8 +1215,6 @@ void __init paging_init(void) */ empty_bad_page = alloc_bootmem_pages(PAGE_SIZE); empty_bad_page_table = alloc_bootmem_pages(PAGE_SIZE); - - free_area_init(max_low_pfn); } void __init mem_init(void) diff --git a/drivers/acorn/scsi/acornscsi.c b/drivers/acorn/scsi/acornscsi.c index e8a136753d03..cf4c1b3619ba 100644 --- a/drivers/acorn/scsi/acornscsi.c +++ b/drivers/acorn/scsi/acornscsi.c @@ -190,10 +190,6 @@ unsigned int sdtr_period = SDTR_PERIOD; unsigned int sdtr_size = SDTR_SIZE; -static struct proc_dir_entry proc_scsi_acornscsi = { - PROC_SCSI_EATA, 9, "acornscsi", S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - static void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result); static int acornscsi_reconnect_finish(AS_Host *host); static void acornscsi_dma_cleanup(AS_Host *host); @@ -2875,7 +2871,7 @@ int acornscsi_detect(Scsi_Host_Template * tpnt) struct Scsi_Host *instance; AS_Host *host; - tpnt->proc_dir = &proc_scsi_acornscsi; + tpnt->proc_name = "acornscsi"; for (i = 0; i < MAX_ECARDS; i++) ecs[i] = NULL; diff --git a/drivers/acorn/scsi/acornscsi.h b/drivers/acorn/scsi/acornscsi.h index 5470c6b6cdca..b6a7f3148951 100644 --- a/drivers/acorn/scsi/acornscsi.h +++ b/drivers/acorn/scsi/acornscsi.h @@ -23,10 +23,7 @@ extern int acornscsi_biosparam (Disk *, kdev_t, int []); #define CAN_QUEUE 16 #endif -#ifndef PROC_SCSI_AKA30 #include "linux/proc_fs.h" -#define PROC_SCSI_AKA30 PROC_SCSI_EATA -#endif #include diff --git a/drivers/acorn/scsi/arxescsi.c b/drivers/acorn/scsi/arxescsi.c index 4afebe35900b..2a0ee9d1cfe6 100644 --- a/drivers/acorn/scsi/arxescsi.c +++ b/drivers/acorn/scsi/arxescsi.c @@ -58,11 +58,6 @@ static struct expansion_card *ecs[MAX_ECARDS]; -static struct proc_dir_entry proc_scsi_arxescsi = { - PROC_SCSI_QLOGICFAS, 6, "arxescsi", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - /* * Function: int arxescsi_dma_setup(host, SCpnt, direction, min_type) * Purpose : initialises DMA/PIO @@ -223,7 +218,7 @@ int arxescsi_detect(Scsi_Host_Template *tpnt) int count = 0; struct Scsi_Host *host; - tpnt->proc_dir = &proc_scsi_arxescsi; + tpnt->proc_name = "arxescsi"; memset(ecs, 0, sizeof (ecs)); ecard_startfind(); diff --git a/drivers/acorn/scsi/cumana_1.c b/drivers/acorn/scsi/cumana_1.c index df00d6bff21a..1f0609b45087 100644 --- a/drivers/acorn/scsi/cumana_1.c +++ b/drivers/acorn/scsi/cumana_1.c @@ -69,10 +69,6 @@ static const card_ids cumanascsi_cids[] = { { 0xffff, 0xffff } }; -static struct proc_dir_entry proc_scsi_cumana1 = { - PROC_SCSI_T128, 12, "CumanaSCSI-1", S_IFDIR | S_IRUGO, S_IXUGO, 2 -}; - /* * Function : cumanascsi_setup(char *str, int *ints) * @@ -106,7 +102,7 @@ int cumanascsi_detect(Scsi_Host_Template * tpnt) int count = 0; struct Scsi_Host *instance; - tpnt->proc_dir = &proc_scsi_cumana1; + tpnt->proc_name = "CumanaSCSI-1"; memset (ecs, 0, sizeof (ecs)); diff --git a/drivers/acorn/scsi/cumana_2.c b/drivers/acorn/scsi/cumana_2.c index c0edf3b645d5..2307ae3972f7 100644 --- a/drivers/acorn/scsi/cumana_2.c +++ b/drivers/acorn/scsi/cumana_2.c @@ -84,11 +84,6 @@ MODULE_PARM_DESC(term, "SCSI bus termination"); */ int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 }; -static struct proc_dir_entry proc_scsi_cumanascsi_2 = { - PROC_SCSI_QLOGICFAS, 6, "cumanascs2", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - /* Prototype: void cumanascsi_2_irqenable(ec, irqnr) * Purpose : Enable interrupts on Cumana SCSI 2 card * Params : ec - expansion card structure @@ -329,7 +324,7 @@ cumanascsi_2_detect(Scsi_Host_Template *tpnt) int count = 0; struct Scsi_Host *host; - tpnt->proc_dir = &proc_scsi_cumanascsi_2; + tpnt->proc_name = "cumanascs2"; memset(ecs, 0, sizeof (ecs)); ecard_startfind(); diff --git a/drivers/acorn/scsi/ecoscsi.c b/drivers/acorn/scsi/ecoscsi.c index 1d1d0628cd4a..6a204326ed59 100644 --- a/drivers/acorn/scsi/ecoscsi.c +++ b/drivers/acorn/scsi/ecoscsi.c @@ -57,10 +57,6 @@ #include "../../scsi/NCR5380.h" #include "../../scsi/constants.h" -static struct proc_dir_entry proc_scsi_ecoscsi = { - PROC_SCSI_GENERIC_NCR5380, 7, "ecoscsi", S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - static char ecoscsi_read(struct Scsi_Host *instance, int reg) { int iobase = instance->io_port; @@ -104,7 +100,7 @@ int ecoscsi_detect(Scsi_Host_Template * tpnt) { struct Scsi_Host *instance; - tpnt->proc_dir = &proc_scsi_ecoscsi; + tpnt->proc_name = "ecoscsi"; instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); instance->io_port = 0x80ce8000; diff --git a/drivers/acorn/scsi/eesox.c b/drivers/acorn/scsi/eesox.c index 8ed77e157911..e6a6a40050c8 100644 --- a/drivers/acorn/scsi/eesox.c +++ b/drivers/acorn/scsi/eesox.c @@ -81,11 +81,6 @@ MODULE_PARM_DESC(term, "SCSI bus termination"); */ int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 }; -static struct proc_dir_entry proc_scsi_eesox = { - PROC_SCSI_QLOGICISP, 5, "eesox", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - /* Prototype: void eesoxscsi_irqenable(ec, irqnr) * Purpose : Enable interrupts on EESOX SCSI card * Params : ec - expansion card structure @@ -334,7 +329,7 @@ eesoxscsi_detect(Scsi_Host_Template *tpnt) int count = 0; struct Scsi_Host *host; - tpnt->proc_dir = &proc_scsi_eesox; + tpnt->proc_name = "eesox"; memset(ecs, 0, sizeof (ecs)); ecard_startfind(); diff --git a/drivers/acorn/scsi/oak.c b/drivers/acorn/scsi/oak.c index 44fc86eaf610..d6a658c75c3e 100644 --- a/drivers/acorn/scsi/oak.c +++ b/drivers/acorn/scsi/oak.c @@ -71,10 +71,6 @@ static const card_ids oakscsi_cids[] = { { 0xffff, 0xffff } }; -static struct proc_dir_entry proc_scsi_oakscsi = { - PROC_SCSI_PAS16, 7, "oakscsi", S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - #define OAK_ADDRESS(card) (ecard_address((card), ECARD_MEMC, 0)) #define OAK_IRQ(card) (IRQ_NONE) /* @@ -95,7 +91,7 @@ int oakscsi_detect(Scsi_Host_Template * tpnt) int count = 0; struct Scsi_Host *instance; - tpnt->proc_dir = &proc_scsi_oakscsi; + tpnt->proc_name = "oakscsi"; memset (ecs, 0, sizeof (ecs)); diff --git a/drivers/acorn/scsi/powertec.c b/drivers/acorn/scsi/powertec.c index 95dbc3050153..f65ea120aec0 100644 --- a/drivers/acorn/scsi/powertec.c +++ b/drivers/acorn/scsi/powertec.c @@ -81,11 +81,6 @@ static struct expansion_card *ecs[MAX_ECARDS]; */ int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 }; -static struct proc_dir_entry proc_scsi_powertec = { - PROC_SCSI_QLOGICISP, 8, "powertec", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - /* Prototype: void powertecscsi_irqenable(ec, irqnr) * Purpose : Enable interrupts on Powertec SCSI card * Params : ec - expansion card structure @@ -236,7 +231,7 @@ powertecscsi_detect(Scsi_Host_Template *tpnt) int count = 0; struct Scsi_Host *host; - tpnt->proc_dir = &proc_scsi_powertec; + tpnt->proc_name = "powertec"; memset(ecs, 0, sizeof (ecs)); ecard_startfind(); diff --git a/drivers/block/ide.c b/drivers/block/ide.c index 82f9a330370e..0f3e41fed945 100644 --- a/drivers/block/ide.c +++ b/drivers/block/ide.c @@ -307,6 +307,7 @@ int drive_is_flashcard (ide_drive_t *drive) struct hd_driveid *id = drive->id; if (drive->removable && id != NULL) { + if (id->config == 0x848a) return 1; /* CompactFlash */ if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */ || !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */ || !strncmp(id->model, "SunDisk SDCFB", 13) /* SunDisk */ diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 47704a6746da..1da3702b0b21 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -492,6 +493,15 @@ void make_request(int major,int rw, struct buffer_head * bh) if (!buffer_mapped(bh)) BUG(); + /* + * Temporary solution - in 2.5 this will be done by the lowlevel + * driver. Create a bounce buffer if the buffer data points into + * high memory - keep the original buffer otherwise. + */ +#if CONFIG_HIGHMEM + bh = create_bounce(rw, bh); +#endif + /* look for a free request. */ /* Loop uses two requests, 1 for loop and 1 for the real device. * Cut max_req in half to avoid running out and deadlocking. */ diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 03cdb4470cc0..536c94a44bf9 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -2531,23 +2531,6 @@ ctl_table cdrom_root_table[] = { static struct ctl_table_header *cdrom_sysctl_header; -/* - * This is called as the fill_inode function when an inode - * is going into (fill = 1) or out of service (fill = 0). - * We use it here to manage the module use counts. - * - * Note: only the top-level directory needs to do this; if - * a lower level is referenced, the parent will be as well. - */ -static void cdrom_procfs_modcount(struct inode *inode, int fill) -{ - if (fill) { - MOD_INC_USE_COUNT; - } else { - MOD_DEC_USE_COUNT; - } -} - static void cdrom_sysctl_register(void) { static int initialized = 0; @@ -2556,7 +2539,7 @@ static void cdrom_sysctl_register(void) return; cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 1); - cdrom_root_table->child->de->fill_inode = &cdrom_procfs_modcount; + cdrom_root_table->child->de->owner = THIS_MODULE; /* set the defaults */ cdrom_sysctl_settings.autoclose = autoclose; diff --git a/drivers/char/Config.in b/drivers/char/Config.in index 52b4bbd17c65..04d20eb977c8 100644 --- a/drivers/char/Config.in +++ b/drivers/char/Config.in @@ -227,4 +227,8 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then fi fi +if [ "$CONFIG_PCMCIA" != "n" ]; then + source drivers/char/pcmcia/Config.in +fi + endmenu diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 5b29bcafbe91..4c3ed132ffea 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -11,7 +11,7 @@ SUB_DIRS := MOD_SUB_DIRS := $(SUB_DIRS) -ALL_SUB_DIRS := $(SUB_DIRS) ftape joystick +ALL_SUB_DIRS := $(SUB_DIRS) ftape joystick pcmcia # # This file contains the font map for the default (hardware) font @@ -591,6 +591,15 @@ ifeq ($(CONFIG_DRM),y) MOD_SUB_DIRS += drm endif +ifeq ($(CONFIG_PCMCIA),y) + SUB_DIRS += pcmcia + MOD_IN_SUB_DIRS += pcmcia +else + ifeq ($(CONFIG_PCMCIA),m) + MOD_IN_SUB_DIRS += pcmcia + endif +endif + include $(TOPDIR)/Rules.make fastdep: diff --git a/drivers/char/console.c b/drivers/char/console.c index 49512fe42e21..2a58a72ec638 100644 --- a/drivers/char/console.c +++ b/drivers/char/console.c @@ -95,6 +95,7 @@ #include #endif #include +#include #include #include @@ -201,6 +202,11 @@ static int scrollback_delta = 0; #define DO_UPDATE IS_VISIBLE #endif +static int acpi_con_transition(struct acpi_dev *dev, acpi_dstate_t state); +static struct acpi_dev_info acpi_con_info + = {ACPI_SYS_DEV, ACPI_VGA_HID, acpi_con_transition}; +static struct acpi_dev *acpi_con = NULL; + static inline unsigned short *screenpos(int currcons, int offset, int viewed) { unsigned short *p; @@ -654,6 +660,9 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ screenbuf = (unsigned short *) q; kmalloced = 1; vc_init(currcons, video_num_lines, video_num_columns, 1); + + if (!acpi_con) + acpi_con = acpi_register(&acpi_con_info, 0); } return 0; } @@ -1991,6 +2000,8 @@ void vt_console_print(struct console *co, const char * b, unsigned count) if (!printable || test_and_set_bit(0, &printing)) return; + acpi_access(acpi_con); + if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1)) currcons = kmsg_redirect - 1; @@ -2148,6 +2159,7 @@ static int con_write(struct tty_struct * tty, int from_user, { int retval; + acpi_access(acpi_con); retval = do_con_write(tty, from_user, buf, count); con_flush_chars(tty); @@ -2156,6 +2168,7 @@ static int con_write(struct tty_struct * tty, int from_user, static void con_put_char(struct tty_struct *tty, unsigned char ch) { + acpi_access(acpi_con); do_con_write(tty, 0, &ch, 1); } @@ -2221,6 +2234,7 @@ static void con_flush_chars(struct tty_struct *tty) { struct vt_struct *vt = (struct vt_struct *)tty->driver_data; + acpi_access(acpi_con); set_cursor(vt->vc_num); } @@ -2806,6 +2820,21 @@ void vcs_scr_writew(int currcons, u16 val, u16 *org) } } +static int acpi_con_transition(struct acpi_dev *dev, acpi_dstate_t state) +{ + switch (state) + { + case ACPI_D0: + unblank_screen(); + break; + case ACPI_D1: + case ACPI_D2: + case ACPI_D3: + do_blank_screen(0); + break; + } + return 0; +} /* * Visible symbols for modules diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 995f817eb711..616bbafdce21 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -159,6 +159,7 @@ static int sysrq_pressed; int sysrq_enabled = 1; #endif +static struct acpi_dev_info acpi_kbd_info = {ACPI_SYS_DEV, ACPI_KBC_HID, NULL}; static struct acpi_dev *acpi_kbd = NULL; /* @@ -928,7 +929,7 @@ int __init kbd_init(void) init_bh(KEYBOARD_BH, kbd_bh); mark_bh(KEYBOARD_BH); - acpi_kbd = acpi_register(ACPI_SYS_DEV, 0, ACPI_KBC_HID, NULL); + acpi_kbd = acpi_register(&acpi_kbd_info, 0); return 0; } diff --git a/drivers/char/pcmcia/Config.in b/drivers/char/pcmcia/Config.in new file mode 100644 index 000000000000..88545b788a7d --- /dev/null +++ b/drivers/char/pcmcia/Config.in @@ -0,0 +1,31 @@ +# +# PCMCIA character device configuration +# + +mainmenu_option next_comment +comment 'PCMCIA character device support' + +if [ "$CONFIG_SERIAL" = "y" ]; then + dep_tristate ' PCMCIA serial device support' \ + CONFIG_PCMCIA_SERIAL_CS $CONFIG_PCMCIA + if [ "$CONFIG_CARDBUS" = "y" ]; then + dep_tristate ' CardBus serial device support' \ + CONFIG_PCMCIA_SERIAL_CB $CONFIG_PCMCIA + fi +fi + +if [ "$CONFIG_SERIAL" = "m" ]; then + dep_tristate ' PCMCIA serial device support' \ + CONFIG_PCMCIA_SERIAL_CS m + if [ "$CONFIG_CARDBUS" = "y" ]; then + dep_tristate ' CardBus serial device support' \ + CONFIG_PCMCIA_SERIAL_CB m + fi +fi + +if [ "$CONFIG_PCMCIA_SERIAL_CS" = "y" -o \ + "$CONFIG_PCMCIA_SERIAL_CB" = "y" ]; then + define_bool CONFIG_PCMCIA_CHRDEV y +fi + +endmenu diff --git a/drivers/char/pcmcia/Makefile b/drivers/char/pcmcia/Makefile new file mode 100644 index 000000000000..198500763867 --- /dev/null +++ b/drivers/char/pcmcia/Makefile @@ -0,0 +1,27 @@ +# +# drivers/char/pcmcia/Makefile +# +# Makefile for the Linux PCMCIA char device drivers. +# + +SUB_DIRS := +MOD_SUB_DIRS := $(SUB_DIRS) +ALL_SUB_DIRS := $(SUB_DIRS) + +O_TARGET := pcmcia_char.o +MOD_LIST_NAME := PCMCIA_CHAR_MODULES + +obj-y := +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_PCMCIA_SERIAL_CS) += serial_cs.o +obj-$(CONFIG_PCMCIA_SERIAL_CB) += serial_cb.o + +O_OBJS := $(obj-y) +OX_OBJS := +M_OBJS := $(obj-m) +MX_OBJS := + +include $(TOPDIR)/Rules.make diff --git a/drivers/char/pcmcia/serial_cb.c b/drivers/char/pcmcia/serial_cb.c new file mode 100644 index 000000000000..8a2dede8552a --- /dev/null +++ b/drivers/char/pcmcia/serial_cb.c @@ -0,0 +1,150 @@ +/*====================================================================== + + A driver for CardBus serial devices + + serial_cb.c 1.14 1999/11/11 02:18:08 + + Copyright 1998, 1999 by Donald Becker and David Hinds + + This software may be used and distributed according to the terms + of the GNU Public License, incorporated herein by reference. + All other rights reserved. + + This driver is an activator for CardBus serial cards, as + found on multifunction (e.g. Ethernet and Modem) CardBus cards. + + Donald Becker may be reached as becker@CESDIS.edu, or C/O + USRA Center of Excellence in Space Data and Information Sciences + Code 930.5, NASA Goddard Space Flight Center, Greenbelt MD 20771 + David Hinds may be reached at dhinds@pcmcia.sourceforge.org + +======================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +MODULE_PARM(pc_debug, "i"); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) +static char *version = +"serial_cb.c 1.14 1999/11/11 02:18:08 (David Hinds)"; +#else +#define DEBUG(n, args...) +#endif + +/*====================================================================== + + Card-specific configuration hacks + +======================================================================*/ + +static void device_setup(u_char bus, u_char devfn, u_int ioaddr) +{ + u_short a, b; + + pcibios_read_config_word(bus, devfn, PCI_SUBSYSTEM_VENDOR_ID, &a); + pcibios_read_config_word(bus, devfn, PCI_SUBSYSTEM_ID, &b); + if ((a == 0x13a2) && (b == 0x8007)) { + /* Ositech Jack of Spades */ + DEBUG(0, " 83c175 NVCTL_m = 0x%4.4x.\n", inl(ioaddr+0x80)); + outl(0x4C00, ioaddr + 0x80); + outl(0x4C80, ioaddr + 0x80); + } + DEBUG(0, " modem registers are %2.2x %2.2x %2.2x " + "%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x.\n", + inb(ioaddr + 0), inb(ioaddr + 1), inb(ioaddr + 2), + inb(ioaddr + 3), inb(ioaddr + 4), inb(ioaddr + 5), + inb(ioaddr + 6), inb(ioaddr + 7), inb(ioaddr + 8)); +} + +/*====================================================================== + + serial_attach() creates a serial device "instance" and registers + it with the kernel serial driver, and serial_detach() unregisters + an instance. + +======================================================================*/ + +static dev_node_t *serial_attach(dev_locator_t *loc) +{ + u_int io; + u_char bus, devfn, irq; + int line; + struct serial_struct serial; + + if (loc->bus != LOC_PCI) return NULL; + bus = loc->b.pci.bus; devfn = loc->b.pci.devfn; + printk(KERN_INFO "serial_attach(bus %d, fn %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); + if (io & PCI_BASE_ADDRESS_SPACE_IO) { + io &= PCI_BASE_ADDRESS_IO_MASK; + } else { + printk(KERN_NOTICE "serial_cb: PCI base address 0 is not IO\n"); + return NULL; + } + device_setup(bus, devfn, io); + memset(&serial, 0, sizeof(serial)); + serial.port = io; serial.irq = irq; + serial.flags = ASYNC_SKIP_TEST | ASYNC_SHARE_IRQ; + + /* Some devices seem to need extra time */ + __set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/50); + + line = register_serial(&serial); + if (line < 0) { + printk(KERN_NOTICE "serial_cb: register_serial() at 0x%04x, " + "irq %d failed\n", serial.port, serial.irq); + return NULL; + } else { + dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL); + sprintf(node->dev_name, "ttyS%d", line); + node->major = TTY_MAJOR; node->minor = 0x40 + line; + node->next = NULL; + MOD_INC_USE_COUNT; + return node; + } +} + +static void serial_detach(dev_node_t *node) +{ + DEBUG(0, "serial_detach(tty%02d)\n", node->minor - 0x40); + unregister_serial(node->minor - 0x40); + kfree(node); + MOD_DEC_USE_COUNT; +} + +/*====================================================================*/ + +struct driver_operations serial_ops = { + "serial_cb", serial_attach, NULL, NULL, serial_detach +}; + +static int __init init_serial_cb(void) +{ + DEBUG(0, "%s\n", version); + register_driver(&serial_ops); + return 0; +} + +static void __exit exit_serial_cb(void) +{ + DEBUG(0, "serial_cb: unloading\n"); + unregister_driver(&serial_ops); +} + +module_init(init_serial_cb); +module_exit(exit_serial_cb); diff --git a/drivers/char/pcmcia/serial_cs.c b/drivers/char/pcmcia/serial_cs.c new file mode 100644 index 000000000000..38345b1b5331 --- /dev/null +++ b/drivers/char/pcmcia/serial_cs.c @@ -0,0 +1,667 @@ +/*====================================================================== + + A driver for PCMCIA serial devices + + serial_cs.c 1.114 1999/11/11 00:54:46 + + The contents of this file are subject to the Mozilla Public + License Version 1.1 (the "License"); you may not use this file + except in compliance with the License. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS + IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + implied. See the License for the specific language governing + rights and limitations under the License. + + The initial developer of the original code is David A. Hinds + . Portions created by David A. Hinds + are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + + Alternatively, the contents of this file may be used under the + terms of the GNU Public License version 2 (the "GPL"), in which + case the provisions of the GPL are applicable instead of the + above. If you wish to allow the use of your version of this file + only under the terms of the GPL and not to allow others to use + your version of this file under the MPL, indicate your decision + by deleting the provisions above and replace them with the notice + and other provisions required by the GPL. If you do not delete + the provisions above, a recipient may use your version of this + file under either the MPL or the GPL. + +======================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +MODULE_PARM(pc_debug, "i"); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) +static char *version = +"serial_cs.c 1.114 1999/11/11 00:54:46 (David Hinds)"; +#else +#define DEBUG(n, args...) +#endif + +/*====================================================================*/ + +/* Parameters that can be set with 'insmod' */ + +/* Bit map of interrupts to choose from */ +static u_int irq_mask = 0xdeb8; +static int irq_list[4] = { -1 }; + +/* Enable the speaker? */ +static int do_sound = 1; + +MODULE_PARM(irq_mask, "i"); +MODULE_PARM(irq_list, "1-4i"); +MODULE_PARM(do_sound, "i"); + +/*====================================================================*/ + +/* Table of multi-port card ID's */ + +typedef struct { + u_short manfid; + u_short prodid; + int multi; /* 1 = multifunction, > 1 = # ports */ +} multi_id_t; + +static multi_id_t multi_id[] = { + { MANFID_OMEGA, PRODID_OMEGA_QSP_100, 4 }, + { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232, 2 }, + { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232_D1, 2 }, + { MANFID_QUATECH, PRODID_QUATECH_QUAD_RS232, 4 }, + { MANFID_SOCKET, PRODID_SOCKET_DUAL_RS232, 2 }, + { MANFID_INTEL, PRODID_INTEL_DUAL_RS232, 2 }, + { MANFID_NATINST, PRODID_NATINST_QUAD_RS232, 4 } +}; +#define MULTI_COUNT (sizeof(multi_id)/sizeof(multi_id_t)) + +typedef struct serial_info_t { + int ndev; + int multi; + int slave; + int manfid; + dev_node_t node[4]; + int line[4]; +} serial_info_t; + +static void serial_config(dev_link_t *link); +static void serial_release(u_long arg); +static int serial_event(event_t event, int priority, + event_callback_args_t *args); + +static dev_info_t dev_info = "serial_cs"; + +static dev_link_t *serial_attach(void); +static void serial_detach(dev_link_t *); + +static dev_link_t *dev_list = NULL; + +/*====================================================================*/ + +static void cs_error(client_handle_t handle, int func, int ret) +{ + error_info_t err = { func, ret }; + CardServices(ReportError, handle, &err); +} + +/*====================================================================== + + serial_attach() creates an "instance" of the driver, allocating + local data structures for one device. The device is registered + with Card Services. + +======================================================================*/ + +static dev_link_t *serial_attach(void) +{ + client_reg_t client_reg; + dev_link_t *link; + int i, ret; + + DEBUG(0, "serial_attach()\n"); + + /* Create new serial device */ + link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); + memset(link, 0, sizeof(struct dev_link_t)); + link->release.function = &serial_release; + link->release.data = (u_long)link; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.NumPorts1 = 8; + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; + if (irq_list[0] == -1) + link->irq.IRQInfo2 = irq_mask; + else + for (i = 0; i < 4; i++) + link->irq.IRQInfo2 |= 1 << irq_list[i]; + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + if (do_sound) { + link->conf.Attributes |= CONF_ENABLE_SPKR; + link->conf.Status = CCSR_AUDIO_ENA; + } + link->conf.IntType = INT_MEMORY_AND_IO; + link->priv = kmalloc(sizeof(struct serial_info_t), GFP_KERNEL); + memset(link->priv, 0, sizeof(struct serial_info_t)); + + /* Register with Card Services */ + link->next = dev_list; + dev_list = link; + client_reg.dev_info = &dev_info; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &serial_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != CS_SUCCESS) { + cs_error(link->handle, RegisterClient, ret); + serial_detach(link); + return NULL; + } + + return link; +} /* serial_attach */ + +/*====================================================================== + + This deletes a driver "instance". The device is de-registered + with Card Services. If it has been released, all local data + structures are freed. Otherwise, the structures will be freed + when the device is released. + +======================================================================*/ + +static void serial_detach(dev_link_t *link) +{ + dev_link_t **linkp; + long flags; + int ret; + + DEBUG(0, "serial_detach(0x%p)\n", link); + + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) break; + if (*linkp == NULL) + return; + + save_flags(flags); + cli(); + if (link->state & DEV_RELEASE_PENDING) { + del_timer(&link->release); + link->state &= ~DEV_RELEASE_PENDING; + } + restore_flags(flags); + + if (link->state & DEV_CONFIG) + serial_release((u_long)link); + + if (link->handle) { + ret = CardServices(DeregisterClient, link->handle); + if (ret != CS_SUCCESS) + cs_error(link->handle, DeregisterClient, ret); + } + + /* Unlink device structure, free bits */ + *linkp = link->next; + kfree_s(link->priv, sizeof(serial_info_t)); + kfree_s(link, sizeof(struct dev_link_t)); + +} /* serial_detach */ + +/*====================================================================*/ + +static int setup_serial(serial_info_t *info, ioaddr_t port, int irq) +{ + struct serial_struct serial; + int line; + + memset(&serial, 0, sizeof(serial)); + serial.port = port; + serial.irq = irq; + serial.flags = ASYNC_SKIP_TEST; + serial.flags |= (info->multi || info->slave) ? ASYNC_SHARE_IRQ : 0; + line = register_serial(&serial); + if (line < 0) { + printk(KERN_NOTICE "serial_cs: register_serial() at 0x%04x, " + "irq %d failed\n", serial.port, serial.irq); + return -1; + } + + info->line[info->ndev] = line; + sprintf(info->node[info->ndev].dev_name, "ttyS%d", line); + info->node[info->ndev].major = TTY_MAJOR; + info->node[info->ndev].minor = 0x40+line; + if (info->ndev > 0) + info->node[info->ndev-1].next = &info->node[info->ndev]; + info->ndev++; + + return 0; +} + +/*====================================================================*/ + +static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, + cisparse_t *parse) +{ + int i; + i = CardServices(fn, handle, tuple); + if (i != CS_SUCCESS) return CS_NO_MORE_ITEMS; + i = CardServices(GetTupleData, handle, tuple); + if (i != CS_SUCCESS) return i; + return CardServices(ParseTuple, handle, tuple, parse); +} + +#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c) +#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c) + +/*====================================================================*/ + +static int simple_config(dev_link_t *link) +{ + static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; + client_handle_t handle = link->handle; + serial_info_t *info = link->priv; + tuple_t tuple; + u_char buf[256]; + cisparse_t parse; + cistpl_cftable_entry_t *cf = &parse.cftable_entry; + config_info_t config; + int i, j; + + /* If the card is already configured, look up the port and irq */ + i = CardServices(GetConfigurationInfo, handle, &config); + if ((i == CS_SUCCESS) && + (config.Attributes & CONF_VALID_CLIENT)) { + ioaddr_t port = 0; + if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) { + port = config.BasePort2; + info->slave = 1; + } else if ((info->manfid == MANFID_OSITECH) && + (config.NumPorts1 == 0x40)) { + port = config.BasePort1 + 0x28; + info->slave = 1; + } + if (info->slave) + return setup_serial(info, port, config.AssignedIRQ); + } + link->conf.Vcc = config.Vcc; + + /* First pass: look for a config entry that looks normal. */ + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; tuple.TupleDataMax = 255; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if (i != CS_SUCCESS) goto next_entry; + if (cf->vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 = + cf->vpp1.param[CISTPL_POWER_VNOM]/10000; + if ((cf->io.nwin > 0) && ((cf->io.win[0].base & 0xf) == 8)) { + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; + i = CardServices(RequestIO, link->handle, &link->io); + if (i == CS_SUCCESS) goto found_port; + } + next_entry: + i = next_tuple(handle, &tuple, &parse); + } + + /* Second pass: try to find an entry that isn't picky about + its base address, then try to grab any standard serial port + address, and finally try to get any free port. */ + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && + ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { + link->conf.ConfigIndex = cf->index; + for (j = 0; j < 5; j++) { + link->io.BasePort1 = base[j]; + i = CardServices(RequestIO, link->handle, + &link->io); + if (i == CS_SUCCESS) goto found_port; + } + } + i = next_tuple(handle, &tuple, &parse); + } + +found_port: + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIO, i); + return -1; + } + + i = CardServices(RequestIRQ, link->handle, &link->irq); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIRQ, i); + link->irq.AssignedIRQ = 0; + } + if (info->multi && (info->manfid == MANFID_3COM)) + link->conf.ConfigIndex &= ~(0x08); + i = CardServices(RequestConfiguration, link->handle, &link->conf); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestConfiguration, i); + return -1; + } + + return setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); +} + +static int multi_config(dev_link_t *link) +{ + client_handle_t handle = link->handle; + serial_info_t *info = link->priv; + tuple_t tuple; + u_char buf[256]; + cisparse_t parse; + cistpl_cftable_entry_t *cf = &parse.cftable_entry; + int i, base2 = 0; + + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; tuple.TupleDataMax = 255; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + + /* First, look for a generic full-sized window */ + link->io.NumPorts1 = info->multi * 8; + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + /* The quad port cards have bad CIS's, so just look for a + window larger than 8 ports and assume it will be right */ + if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && + (cf->io.win[0].len > 8)) { + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; + i = CardServices(RequestIO, link->handle, &link->io); + base2 = link->io.BasePort1 + 8; + if (i == CS_SUCCESS) break; + } + i = next_tuple(handle, &tuple, &parse); + } + + /* If that didn't work, look for two windows */ + if (i != CS_SUCCESS) { + link->io.NumPorts1 = link->io.NumPorts2 = 8; + info->multi = 2; + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) { + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + link->io.BasePort2 = cf->io.win[1].base; + link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; + i = CardServices(RequestIO, link->handle, &link->io); + base2 = link->io.BasePort2; + if (i == CS_SUCCESS) break; + } + i = next_tuple(handle, &tuple, &parse); + } + } + + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIO, i); + return -1; + } + + i = CardServices(RequestIRQ, link->handle, &link->irq); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIRQ, i); + link->irq.AssignedIRQ = 0; + } + /* Socket Dual IO: this enables irq's for second port */ + if (info->multi && (info->manfid == MANFID_SOCKET)) { + link->conf.Present |= PRESENT_EXT_STATUS; + link->conf.ExtStatus = ESR_REQ_ATTN_ENA; + } + i = CardServices(RequestConfiguration, link->handle, &link->conf); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestConfiguration, i); + return -1; + } + + setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); + for (i = 0; i < info->multi-1; i++) + setup_serial(info, base2+(8*i), link->irq.AssignedIRQ); + + return 0; +} + +/*====================================================================== + + serial_config() is scheduled to run after a CARD_INSERTION event + is received, to configure the PCMCIA socket, and to make the + serial device available to the system. + +======================================================================*/ + +#define CS_CHECK(fn, args...) \ +while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed + +void serial_config(dev_link_t *link) +{ + client_handle_t handle; + serial_info_t *info; + tuple_t tuple; + u_short buf[128]; + cisparse_t parse; + cistpl_cftable_entry_t *cf = &parse.cftable_entry; + int i, last_ret, last_fn; + + sti(); + handle = link->handle; + info = link->priv; + + DEBUG(0, "serial_config(0x%p)\n", link); + + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; tuple.TupleDataMax = 255; + tuple.Attributes = 0; + /* Get configuration register information */ + tuple.DesiredTuple = CISTPL_CONFIG; + last_ret = first_tuple(handle, &tuple, &parse); + if (last_ret != CS_SUCCESS) { + last_fn = ParseTuple; + goto cs_failed; + } + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* Configure card */ + link->state |= DEV_CONFIG; + + /* Is this a compliant multifunction card? */ + tuple.DesiredTuple = CISTPL_LONGLINK_MFC; + tuple.Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; + info->multi = (first_tuple(handle, &tuple, &parse) == CS_SUCCESS); + + /* Is this a multiport card? */ + tuple.DesiredTuple = CISTPL_MANFID; + if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { + info->manfid = le16_to_cpu(buf[0]); + for (i = 0; i < MULTI_COUNT; i++) + if ((info->manfid == multi_id[i].manfid) && + (le16_to_cpu(buf[1]) == multi_id[i].prodid)) + break; + if (i < MULTI_COUNT) + info->multi = multi_id[i].multi; + } + + /* Another check for dual-serial cards: look for either serial or + multifunction cards that ask for appropriate IO port ranges */ + tuple.DesiredTuple = CISTPL_FUNCID; + if ((info->multi == 0) && + ((first_tuple(handle, &tuple, &parse) != CS_SUCCESS) || + (parse.funcid.func == CISTPL_FUNCID_MULTI) || + (parse.funcid.func == CISTPL_FUNCID_SERIAL))) { + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + if ((first_tuple(handle, &tuple, &parse) == CS_SUCCESS) && + (((cf->io.nwin == 1) && (cf->io.win[0].len == 16)) || + ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && + (cf->io.win[1].len == 8)))) + info->multi = 2; + } + + if (info->multi > 1) + multi_config(link); + else + simple_config(link); + + if (info->ndev == 0) + goto failed; + + if (info->manfid == MANFID_IBM) { + conf_reg_t reg = { 0, CS_READ, 0x800, 0 }; + CS_CHECK(AccessConfigurationRegister, link->handle, ®); + reg.Action = CS_WRITE; + reg.Value = reg.Value | 1; + CS_CHECK(AccessConfigurationRegister, link->handle, ®); + } + + link->dev = &info->node[0]; + link->state &= ~DEV_CONFIG_PENDING; + return; + +cs_failed: + cs_error(link->handle, last_fn, last_ret); +failed: + serial_release((u_long)link); + +} /* serial_config */ + +/*====================================================================== + + After a card is removed, serial_release() will unregister the net + device, and release the PCMCIA configuration. + +======================================================================*/ + +void serial_release(u_long arg) +{ + dev_link_t *link = (dev_link_t *)arg; + serial_info_t *info = link->priv; + int i; + + sti(); + + DEBUG(0, "serial_release(0x%p)\n", link); + + for (i = 0; i < info->ndev; i++) { + unregister_serial(info->line[i]); + } + link->dev = NULL; + + if (!info->slave) { + CardServices(ReleaseConfiguration, link->handle); + CardServices(ReleaseIO, link->handle, &link->io); + CardServices(ReleaseIRQ, link->handle, &link->irq); + } + + link->state &= ~DEV_CONFIG; + +} /* serial_release */ + +/*====================================================================== + + The card status event handler. Mostly, this schedules other + stuff to run after an event is received. A CARD_REMOVAL event + also sets some flags to discourage the serial drivers from + talking to the ports. + +======================================================================*/ + +static int serial_event(event_t event, int priority, + event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + serial_info_t *info = link->priv; + + DEBUG(1, "serial_event(0x%06x)\n", event); + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) { + link->release.expires = jiffies + HZ/20; + link->state |= DEV_RELEASE_PENDING; + add_timer(&link->release); + } + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + serial_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if ((link->state & DEV_CONFIG) && !info->slave) + CardServices(ReleaseConfiguration, link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (DEV_OK(link) && !info->slave) + CardServices(RequestConfiguration, link->handle, &link->conf); + break; + } + return 0; +} /* serial_event */ + +/*====================================================================*/ + +static int __init init_serial_cs(void) +{ + servinfo_t serv; + DEBUG(0, "%s\n", version); + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "serial_cs: Card Services release " + "does not match!\n"); + return -1; + } + register_pccard_driver(&dev_info, &serial_attach, &serial_detach); + return 0; +} + +static void __exit exit_serial_cs(void) +{ + DEBUG(0, "serial_cs: unloading\n"); + unregister_pccard_driver(&dev_info); + while (dev_list != NULL) + serial_detach(dev_list); +} + +module_init(init_serial_cs); +module_exit(exit_serial_cs); diff --git a/drivers/char/stradis.c b/drivers/char/stradis.c index d0675a09ce23..6edbf218cb3e 100644 --- a/drivers/char/stradis.c +++ b/drivers/char/stradis.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/i2o/i2o_scsi.c b/drivers/i2o/i2o_scsi.c index e383dbb4d3b5..7e5342181047 100644 --- a/drivers/i2o/i2o_scsi.c +++ b/drivers/i2o/i2o_scsi.c @@ -59,10 +59,6 @@ #define MAXHOSTS 32 -struct proc_dir_entry proc_scsi_i2o_scsi = { - PROC_SCSI_I2O, 8, "i2o_scsi", S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - struct i2o_scsi_host { struct i2o_controller *controller; diff --git a/drivers/i2o/i2o_scsi.h b/drivers/i2o/i2o_scsi.h index 71f71c762158..c059c05f42e0 100644 --- a/drivers/i2o/i2o_scsi.h +++ b/drivers/i2o/i2o_scsi.h @@ -14,8 +14,6 @@ #define I2O_SCSI_CAN_QUEUE 4 #define I2O_SCSI_CMD_PER_LUN 6 -extern struct proc_dir_entry proc_scsi_i2o_scsi; - extern int i2o_scsi_detect(Scsi_Host_Template *); extern const char *i2o_scsi_info(struct Scsi_Host *); extern int i2o_scsi_command(Scsi_Cmnd *); @@ -27,7 +25,7 @@ extern void i2o_scsi_setup(char *str, int *ints); #define I2OSCSI { \ next: NULL, \ - proc_dir: &proc_scsi_i2o_scsi, \ + proc_name: "i2o_scsi", \ name: "I2O SCSI Layer", \ detect: i2o_scsi_detect, \ release: i2o_scsi_release, \ diff --git a/drivers/misc/acpi.c b/drivers/misc/acpi.c index 2b379dd7014d..fb7654f7e4b8 100644 --- a/drivers/misc/acpi.c +++ b/drivers/misc/acpi.c @@ -70,6 +70,11 @@ static int acpi_do_event(ctl_table *ctl, struct file *file, void *buffer, size_t *len); +static int acpi_do_sleep_wake(ctl_table *ctl, + int write, + struct file *file, + void *buffer, + size_t *len); DECLARE_WAIT_QUEUE_HEAD(acpi_idle_wait); @@ -153,6 +158,11 @@ static struct ctl_table acpi_table[] = &acpi_slp_typ[5], sizeof(acpi_slp_typ[5]), 0600, NULL, &acpi_do_ulong}, +#if 0 + {123, "sleep", (void*) 1, 0, 0600, NULL, &acpi_do_sleep_wake}, + {124, "wake", NULL, 0, 0600, NULL, &acpi_do_sleep_wake}, +#endif + {0} }; @@ -325,15 +335,23 @@ static struct acpi_table *__init acpi_map_table(u32 addr) if (addr) { // map table header to determine size table = (struct acpi_table *) - ioremap_nocache((unsigned long) addr, - sizeof(struct acpi_table)); + ioremap((unsigned long) addr, + sizeof(struct acpi_table)); if (table) { unsigned long table_size = table->length; iounmap(table); // remap entire table table = (struct acpi_table *) - ioremap_nocache((unsigned long) addr, - table_size); + ioremap((unsigned long) addr, table_size); + } + + if (!table) { + /* ioremap is a pain, it returns NULL if the + * table starts within mapped physical memory. + * Hopefully, no table straddles a mapped/unmapped + * physical memory boundary, ugh + */ + table = (struct acpi_table*) phys_to_virt(addr); } } return table; @@ -344,6 +362,7 @@ static struct acpi_table *__init acpi_map_table(u32 addr) */ static void acpi_unmap_table(struct acpi_table *table) { + // iounmap ignores addresses within physical memory if (table) iounmap(table); } @@ -386,8 +405,14 @@ static int __init acpi_find_tables(void) // fetch RSDT from RSDP rsdt = acpi_map_table(rsdp->rsdt); - if (!rsdt || rsdt->signature != ACPI_RSDT_SIG) { - printk(KERN_ERR "ACPI: missing RSDT\n"); + if (!rsdt) { + printk(KERN_ERR "ACPI: missing RSDT at 0x%p\n", + (void*) rsdp->rsdt); + return -ENODEV; + } + else if (rsdt->signature != ACPI_RSDT_SIG) { + printk(KERN_ERR "ACPI: bad RSDT at 0x%p (%08x)\n", + (void*) rsdp->rsdt, (unsigned) rsdt->signature); acpi_unmap_table(rsdt); return -ENODEV; } @@ -402,9 +427,15 @@ static int __init acpi_find_tables(void) acpi_facp_addr = *rsdt_entry; acpi_dsdt_addr = acpi_facp->dsdt; + // map FACS if it exists if (acpi_facp->facs) { - acpi_facs = (struct acpi_facs*) - acpi_map_table(acpi_facp->facs); + dt = acpi_map_table(acpi_facp->facs); + if (dt && dt->signature == ACPI_FACS_SIG) { + acpi_facs = (struct acpi_facs*) dt; + } + else { + acpi_unmap_table(dt); + } } } else { @@ -629,6 +660,34 @@ static void acpi_idle_handler(void) sleep_level = 1; } +/* + * Put all devices into specified D-state + */ +static int acpi_enter_dx(acpi_dstate_t state) +{ + int status = 0; + struct list_head *i = acpi_devs.next; + + while (i != &acpi_devs) { + struct acpi_dev *dev = list_entry(i, struct acpi_dev, entry); + if (dev->state != state) { + int dev_status = 0; + if (dev->info.transition) + dev_status = dev->info.transition(dev, state); + if (!dev_status) { + // put hardware into D-state + dev->state = state; + } + if (dev_status) + status = dev_status; + } + + i = i->next; + } + + return status; +} + /* * Enter system sleep state */ @@ -908,6 +967,35 @@ static int acpi_do_event(ctl_table *ctl, return 0; } +/* + * Sleep or wake system + */ +static int acpi_do_sleep_wake(ctl_table *ctl, + int write, + struct file *file, + void *buffer, + size_t *len) +{ + if (!write) { + if (file->f_pos) { + *len = 0; + return 0; + } + } + else + { + // just shutdown some devices for now + if (ctl->data) { + acpi_enter_dx(ACPI_D3); + } + else { + acpi_enter_dx(ACPI_D0); + } + } + file->f_pos += *len; + return 0; +} + /* * Initialize and enable ACPI */ @@ -976,24 +1064,22 @@ static void __exit acpi_exit(void) /* * Register a device with the ACPI subsystem */ -struct acpi_dev* acpi_register(acpi_dev_t type, - unsigned long adr, - acpi_hid_t hid, - acpi_transition trans) +struct acpi_dev* acpi_register(struct acpi_dev_info *info, unsigned long adr) { - struct acpi_dev *dev = kmalloc(sizeof(struct acpi_dev), GFP_KERNEL); - if (dev) { - unsigned long flags; - - memset(dev, 0, sizeof(*dev)); - dev->type = type; - dev->adr = adr; - dev->hid = hid; - dev->transition = trans; - - spin_lock_irqsave(&acpi_devs_lock, flags); - list_add(&dev->entry, &acpi_devs); - spin_unlock_irqrestore(&acpi_devs_lock, flags); + struct acpi_dev *dev = NULL; + if (info) { + dev = kmalloc(sizeof(struct acpi_dev), GFP_KERNEL); + if (dev) { + unsigned long flags; + + memset(dev, 0, sizeof(*dev)); + memcpy(&dev->info, info, sizeof(dev->info)); + dev->adr = adr; + + spin_lock_irqsave(&acpi_devs_lock, flags); + list_add(&dev->entry, &acpi_devs); + spin_unlock_irqrestore(&acpi_devs_lock, flags); + } } return dev; } diff --git a/drivers/net/8390.c b/drivers/net/8390.c index 4b4cc6466ef6..f935249b9daa 100644 --- a/drivers/net/8390.c +++ b/drivers/net/8390.c @@ -1089,7 +1089,10 @@ static void NS8390_trigger_send(struct net_device *dev, unsigned int length, int start_page) { long e8390_base = dev->base_addr; +#if defined(CONFIG_MAC) || defined(CONFIG_AMIGA_PCMCIA) || \ + defined(CONFIG_ARIADNE2) || defined(CONFIG_ARIADNE2_MODULE) struct ei_device *ei_local = (struct ei_device *) dev->priv; +#endif outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD); diff --git a/drivers/net/fc/iph5526.c b/drivers/net/fc/iph5526.c index 9cad49031d4a..c1c9fde27587 100644 --- a/drivers/net/fc/iph5526.c +++ b/drivers/net/fc/iph5526.c @@ -3752,11 +3752,6 @@ struct fc_info *fi = (struct fc_info*)dev->priv; /* SCSI stuff starts here */ -static struct proc_dir_entry proc_scsi_iph5526 = { - PROC_SCSI_IPH5526_FC, 7, "iph5526", S_IFDIR, S_IRUGO | S_IXUGO, 2 -}; - - int iph5526_detect(Scsi_Host_Template *tmpt) { struct Scsi_Host *host = NULL; @@ -3766,7 +3761,7 @@ int no_of_hosts = 0, timeout, i, j, count = 0; u_int pci_maddr = 0; struct pci_dev *pdev = NULL; - tmpt->proc_dir = &proc_scsi_iph5526; + tmpt->proc_name = "iph5526"; if (pci_present() == 0) { printk("iph5526: PCI not present\n"); return 0; diff --git a/drivers/net/mace.c b/drivers/net/mace.c index 684f9bcd01b1..7ad7007b9691 100644 --- a/drivers/net/mace.c +++ b/drivers/net/mace.c @@ -104,6 +104,7 @@ bitrev(int b) int mace_probe(void) { int j, rev; + struct net_device *dev; struct mace_data *mp; struct device_node *mace; unsigned char *addr; diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 40c53a2cf8d7..0e9110a8bd3d 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -2,7 +2,7 @@ Written 1993-1998 by Donald Becker, becker@cesdis.gsfc.nasa.gov, (driver core) and - David Hinds, dhinds@allegro.stanford.edu (derived from his PC card code). + David Hinds, dhinds@pcmcia.sourceforge.org (from his PC card code). This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference. @@ -322,7 +322,6 @@ static dev_link_t *tc574_attach(void) link->release.data = (u_long)link; link->io.NumPorts1 = 32; link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - link->io.IOAddrLines = 5; link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; if (irq_list[0] == -1) @@ -483,6 +482,7 @@ static void tc574_config(dev_link_t *link) /* Configure card */ link->state |= DEV_CONFIG; + link->io.IOAddrLines = 16; for (i = j = 0; j < 0x400; j += 0x20) { link->io.BasePort1 = j ^ 0x300; i = CardServices(RequestIO, link->handle, &link->io); diff --git a/drivers/net/pcmcia/3c575_cb.c b/drivers/net/pcmcia/3c575_cb.c new file mode 100644 index 000000000000..f9fd76d01281 --- /dev/null +++ b/drivers/net/pcmcia/3c575_cb.c @@ -0,0 +1,2215 @@ +/* EtherLinkXL.c: A 3Com EtherLink PCI III/XL ethernet driver for linux. */ +/* + Written 1996-1999 by Donald Becker. + + This software may be used and distributed according to the terms + of the GNU Public License, incorporated herein by reference. + + This driver is for the 3Com "Vortex" and "Boomerang" series ethercards. + Members of the series include Fast EtherLink 3c590/3c592/3c595/3c597 + and the EtherLink XL 3c900 and 3c905 cards. + + 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 +*/ + +static char *version = +"3c59x.c:v0.99L 5/28/99 Donald Becker 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. + Setting to > 1512 effectively disables this feature. */ +static const int rx_copybreak = 200; +/* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */ +static const int mtu = 1500; +/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ +static int max_interrupt_work = 20; + +/* Put out somewhat more debugging messages. (0: no msg, 1 minimal .. 6). */ +#define vortex_debug debug +#ifdef VORTEX_DEBUG +static int vortex_debug = VORTEX_DEBUG; +#else +static int vortex_debug = 1; +#endif + +/* Some values here only for performance evaluation and path-coverage + debugging. */ +static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits; + +/* A few values that may be tweaked. */ +/* Time in jiffies before concluding the transmitter is hung. */ +#define TX_TIMEOUT (2*HZ) + +/* Keep the ring sizes a power of two for efficiency. */ +#define TX_RING_SIZE 16 +#define RX_RING_SIZE 32 +#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ + +#ifndef __OPTIMIZE__ +#warning You must compile this file with the correct options! +#warning See the last lines of the source file. +#error You must compile this driver with "-O". +#endif + +#include +#include +#ifdef MODULE +#ifdef MODVERSIONS +#include +#endif +#include +#else +#define MOD_INC_USE_COUNT +#define MOD_DEC_USE_COUNT +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* For NR_IRQS only. */ +#include +#include + +/* Kernel compatibility defines, some common to David Hinds' PCMCIA package. + This is only in the support-all-kernels source code. */ + +#define RUN_AT(x) (jiffies + (x)) + +#include + +#define PCI_SUPPORT_VER2 +#define DEV_FREE_SKB(skb) dev_kfree_skb(skb); +#if ! defined(CAP_NET_ADMIN) +#define capable(CAP_XXX) (suser()) +#endif + +#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115 +MODULE_AUTHOR("Donald Becker "); +MODULE_DESCRIPTION("3Com 3c590/3c900 series Vortex/Boomerang driver"); +MODULE_PARM(debug, "i"); +MODULE_PARM(options, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(rx_copybreak, "i"); +MODULE_PARM(max_interrupt_work, "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. */ + +/* The Vortex size is twice that of the original EtherLinkIII series: the + runtime register window, window 1, is now always mapped in. + The Boomerang size is twice as large as the Vortex -- it has additional + bus master control registers. */ +#define VORTEX_TOTAL_SIZE 0x20 +#define BOOMERANG_TOTAL_SIZE 0x40 + +/* Set iff a MII transceiver on any interface requires mdio preamble. + This only set with the original DP83840 on older 3c905 boards, so the extra + code size of a per-interface flag is not worthwhile. */ +static char mii_preamble_required = 0; + +/* + Theory of Operation + +I. Board Compatibility + +This device driver is designed for the 3Com FastEtherLink and FastEtherLink +XL, 3Com's PCI to 10/100baseT adapters. It also works with the 10Mbs +versions of the FastEtherLink cards. The supported product IDs are + 3c590, 3c592, 3c595, 3c597, 3c900, 3c905 + +The related ISA 3c515 is supported with a separate driver, 3c515.c, included +with the kernel source or available from + cesdis.gsfc.nasa.gov:/pub/linux/drivers/3c515.html + +II. Board-specific settings + +PCI bus devices are configured by the system at boot time, so no jumpers +need to be set on the board. The system BIOS should be set to assign the +PCI INTA signal to an otherwise unused system IRQ line. + +The EEPROM settings for media type and forced-full-duplex are observed. +The EEPROM media type should be left at the default "autoselect" unless using +10base2 or AUI connections which cannot be reliably detected. + +III. Driver operation + +The 3c59x series use an interface that's very similar to the previous 3c5x9 +series. The primary interface is two programmed-I/O FIFOs, with an +alternate single-contiguous-region bus-master transfer (see next). + +The 3c900 "Boomerang" series uses a full-bus-master interface with separate +lists of transmit and receive descriptors, similar to the AMD LANCE/PCnet, +DEC Tulip and Intel Speedo3. The first chip version retains a compatible +programmed-I/O interface that has been removed in 'B' and subsequent board +revisions. + +One extension that is advertised in a very large font is that the adapters +are capable of being bus masters. On the Vortex chip this capability was +only for a single contiguous region making it far less useful than the full +bus master capability. There is a significant performance impact of taking +an extra interrupt or polling for the completion of each transfer, as well +as difficulty sharing the single transfer engine between the transmit and +receive threads. Using DMA transfers is a win only with large blocks or +with the flawed versions of the Intel Orion motherboard PCI controller. + +The Boomerang chip's full-bus-master interface is useful, and has the +currently-unused advantages over other similar chips that queued transmit +packets may be reordered and receive buffer groups are associated with a +single frame. + +With full-bus-master support, this driver uses a "RX_COPYBREAK" scheme. +Rather than a fixed intermediate receive buffer, this scheme allocates +full-sized skbuffs as receive buffers. The value RX_COPYBREAK is used as +the copying breakpoint: it is chosen to trade-off the memory wasted by +passing the full-sized skbuff to the queue layer for all frames vs. the +copying cost of copying a frame to a correctly-sized skbuff. + +IIIC. Synchronization +The driver runs as two independent, single-threaded flows of control. One +is the send-packet routine, which enforces single-threaded use by the +dev->tbusy flag. The other thread is the interrupt handler, which is single +threaded by the hardware and other software. + +IV. Notes + +Thanks to Cameron Spitzer and Terry Murphy of 3Com for providing development +3c590, 3c595, and 3c900 boards. +The name "Vortex" is the internal 3Com project name for the PCI ASIC, and +the EISA version is called "Demon". According to Terry these names come +from rides at the local amusement park. + +The new chips support both ethernet (1.5K) and FDDI (4.5K) packet sizes! +This driver only supports ethernet packets because of the skbuff allocation +limit of 4K. +*/ + +/* This table drives the PCI probe routines. It's mostly boilerplate in all + of the drivers, and will likely be provided by some future kernel. +*/ +enum pci_flags_bit { + PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, + PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, +}; +struct pci_id_info { + 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, struct net_device *dev, + 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, + struct net_device *dev, long ioaddr, + int irq, int dev_id, int card_idx); +static struct pci_id_info pci_tbl[] = { + {"3c590 Vortex 10Mbps", 0x10B7, 0x5900, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1}, + {"3c595 Vortex 100baseTx", 0x10B7, 0x5950, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1}, + {"3c595 Vortex 100baseT4", 0x10B7, 0x5951, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1}, + {"3c595 Vortex 100base-MII", 0x10B7, 0x5952, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1}, + {"3Com Vortex", 0x10B7, 0x5900, 0xff00, + PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1}, + {"3c900 Boomerang 10baseT", 0x10B7, 0x9000, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1}, + {"3c900 Boomerang 10Mbps Combo", 0x10B7, 0x9001, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1}, + {"3c900 Cyclone 10Mbps Combo", 0x10B7, 0x9005, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1}, + {"3c900B-FL Cyclone 10base-FL", 0x10B7, 0x900A, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1}, + {"3c905 Boomerang 100baseTx", 0x10B7, 0x9050, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1}, + {"3c905 Boomerang 100baseT4", 0x10B7, 0x9051, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1}, + {"3c905B Cyclone 100baseTx", 0x10B7, 0x9055, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, vortex_probe1}, + {"3c905B Cyclone 10/100/BNC", 0x10B7, 0x9058, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, vortex_probe1}, + {"3c905B-FX Cyclone 100baseFx", 0x10B7, 0x905A, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1}, + {"3c905C Tornado", 0x10B7, 0x9200, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1}, + {"3c980 Cyclone", 0x10B7, 0x9800, 0xfff0, + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1}, + {"3cSOHO100-TX Hurricane", 0x10B7, 0x7646, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1}, + {"3c555 Laptop Hurricane", 0x10B7, 0x5055, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1}, + {"3c575 Boomerang CardBus", 0x10B7, 0x5057, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1}, + {"3CCFE575 Cyclone CardBus", 0x10B7, 0x5157, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS, + 128, vortex_probe1}, + {"3CCFE575CT Cyclone CardBus", 0x10B7, 0x5257, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS, + 128, vortex_probe1}, + {"3CCFE656 Cyclone CardBus", 0x10B7, 0x6560, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS, + 128, vortex_probe1}, + {"3CCFEM656 Cyclone CardBus", 0x10B7, 0x6562, 0xffff, + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS, + 128, vortex_probe1}, + {"3c575 series CardBus (unknown version)", 0x10B7, 0x5057, 0xf0ff, + PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1}, + {"3Com Boomerang (unknown version)", 0x10B7, 0x9000, 0xff00, + PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1}, + {0,}, /* 0 terminated list. */ +}; + +/* Operational definitions. + These are not used by other compilation units and thus are not + exported in a ".h" file. + + First the windows. There are eight register windows, with the command + and status registers available in each. + */ +#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD) +#define EL3_CMD 0x0e +#define EL3_STATUS 0x0e + +/* The top five bits written to EL3_CMD are a command, the lower + 11 bits are the parameter, if applicable. + Note that 11 parameters bits was fine for ethernet, but the new chip + can handle FDDI length frames (~4500 octets) and now parameters count + 32-bit 'Dwords' rather than octets. */ + +enum vortex_cmd { + TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11, + RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, + UpStall = 6<<11, UpUnstall = (6<<11)+1, + DownStall = (6<<11)+2, DownUnstall = (6<<11)+3, + RxDiscard = 8<<11, TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11, + FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11, + SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11, + SetTxThreshold = 18<<11, SetTxStart = 19<<11, + StartDMAUp = 20<<11, StartDMADown = (20<<11)+1, StatsEnable = 21<<11, + StatsDisable = 22<<11, StopCoax = 23<<11, SetFilterBit = 25<<11,}; + +/* The SetRxFilter command accepts the following classes: */ +enum RxFilter { + RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 }; + +/* Bits in the general status register. */ +enum vortex_status { + IntLatch = 0x0001, HostError = 0x0002, TxComplete = 0x0004, + TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020, + IntReq = 0x0040, StatsFull = 0x0080, + DMADone = 1<<8, DownComplete = 1<<9, UpComplete = 1<<10, + DMAInProgress = 1<<11, /* DMA controller is still busy.*/ + CmdInProgress = 1<<12, /* EL3_CMD is still busy.*/ +}; + +/* Register window 1 offsets, the window used in normal operation. + On the Vortex this window is always mapped at offsets 0x10-0x1f. */ +enum Window1 { + TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14, + RxStatus = 0x18, Timer=0x1A, TxStatus = 0x1B, + TxFree = 0x1C, /* Remaining free bytes in Tx buffer. */ +}; +enum Window0 { + Wn0EepromCmd = 10, /* Window 0: EEPROM command register. */ + Wn0EepromData = 12, /* Window 0: EEPROM results register. */ + IntrStatus=0x0E, /* Valid in all windows. */ +}; +enum Win0_EEPROM_bits { + EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0, + EEPROM_EWENB = 0x30, /* Enable erasing/writing for 10 msec. */ + EEPROM_EWDIS = 0x00, /* Disable EWENB before 10 msec timeout. */ +}; +/* EEPROM locations. */ +enum eeprom_offset { + PhysAddr01=0, PhysAddr23=1, PhysAddr45=2, ModelID=3, + EtherLink3ID=7, IFXcvrIO=8, IRQLine=9, + NodeAddr01=10, NodeAddr23=11, NodeAddr45=12, + DriverTune=13, Checksum=15}; + +enum Window2 { /* Window 2. */ + Wn2_ResetOptions=12, +}; +enum Window3 { /* Window 3: MAC/config bits. */ + Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8, +}; +union wn3_config { + int i; + struct w3_config_fields { + unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2; + int pad8:8; + unsigned int ram_split:2, pad18:2, xcvr:4, autoselect:1; + int pad24:7; + } u; +}; + +enum Window4 { /* Window 4: Xcvr/media bits. */ + Wn4_FIFODiag = 4, Wn4_NetDiag = 6, Wn4_PhysicalMgmt=8, Wn4_Media = 10, +}; +enum Win4_Media_bits { + Media_SQE = 0x0008, /* Enable SQE error counting for AUI. */ + Media_10TP = 0x00C0, /* Enable link beat and jabber for 10baseT. */ + Media_Lnk = 0x0080, /* Enable just link beat for 100TX/100FX. */ + Media_LnkBeat = 0x0800, +}; +enum Window7 { /* Window 7: Bus Master control. */ + Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12, +}; +/* Boomerang bus master control registers. */ +enum MasterCtrl { + PktStatus = 0x20, DownListPtr = 0x24, FragAddr = 0x28, FragLen = 0x2c, + TxFreeThreshold = 0x2f, UpPktStatus = 0x30, UpListPtr = 0x38, +}; + +/* The Rx and Tx descriptor lists. + Caution Alpha hackers: these types are 32 bits! Note also the 8 byte + alignment contraint on tx_ring[] and rx_ring[]. */ +#define LAST_FRAG 0x80000000 /* Last Addr/Len pair in descriptor. */ +struct boom_rx_desc { + u32 next; /* Last entry points to 0. */ + s32 status; + u32 addr; /* Up to 63 addr/len pairs possible. */ + s32 length; /* Set LAST_FRAG to indicate last pair. */ +}; +/* Values for the Rx status entry. */ +enum rx_desc_status { + RxDComplete=0x00008000, RxDError=0x4000, + /* See boomerang_rx() for actual error bits */ + IPChksumErr=1<<25, TCPChksumErr=1<<26, UDPChksumErr=1<<27, + IPChksumValid=1<<29, TCPChksumValid=1<<30, UDPChksumValid=1<<31, +}; + +struct boom_tx_desc { + u32 next; /* Last entry points to 0. */ + s32 status; /* bits 0:12 length, others see below. */ + u32 addr; + s32 length; +}; + +/* Values for the Tx status entry. */ +enum tx_desc_status { + CRCDisable=0x2000, TxDComplete=0x8000, + AddIPChksum=0x02000000, AddTCPChksum=0x04000000, AddUDPChksum=0x08000000, + TxIntrUploaded=0x80000000, /* IRQ when in FIFO, but maybe not sent. */ +}; + +/* Chip features we care about in vp->capabilities, read from the EEPROM. */ +enum ChipCaps { CapBusMaster=0x20, CapPwrMgmt=0x2000 }; + +struct vortex_private { + /* The Rx and Tx rings should be quad-word-aligned. */ + struct boom_rx_desc rx_ring[RX_RING_SIZE]; + struct boom_tx_desc tx_ring[TX_RING_SIZE]; + /* The addresses of transmit- and receive-in-place skbuffs. */ + struct sk_buff* rx_skbuff[RX_RING_SIZE]; + struct sk_buff* tx_skbuff[TX_RING_SIZE]; + struct net_device *next_module; + void *priv_addr; + unsigned int cur_rx, cur_tx; /* The next free ring entry */ + unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ + struct net_device_stats stats; + struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */ + + /* PCI configuration space information. */ + u8 pci_bus, pci_devfn; /* PCI bus location, for power management. */ + char *cb_fn_base; /* CardBus function status addr space. */ + int chip_id; + + /* The remainder are related to chip state, mostly media selection. */ + unsigned long in_interrupt; + struct timer_list timer; /* Media selection timer. */ + int options; /* User-settable misc. driver options. */ + unsigned int media_override:4, /* Passed-in media type. */ + default_media:4, /* Read from the EEPROM/Wn3_Config. */ + full_duplex:1, force_fd:1, autoselect:1, + bus_master:1, /* Vortex can only do a fragment bus-m. */ + full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang */ + hw_csums:1, /* Has hardware checksums. */ + tx_full:1, + open:1; + u16 status_enable; + u16 intr_enable; + u16 available_media; /* From Wn3_Options. */ + u16 capabilities, info1, info2; /* Various, from EEPROM. */ + u16 advertising; /* NWay media advertisement */ + unsigned char phys[2]; /* MII device addresses. */ +}; + +/* The action to take with a media selection timer tick. + Note that we deviate from the 3Com order by checking 10base2 before AUI. + */ +enum xcvr_types { + XCVR_10baseT=0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx, + XCVR_100baseFx, XCVR_MII=6, XCVR_NWAY=8, XCVR_ExtMII=9, XCVR_Default=10, +}; + +static struct media_table { + char *name; + unsigned int media_bits:16, /* Bits to set in Wn4_Media register. */ + mask:8, /* The transceiver-present bit in Wn3_Config.*/ + next:8; /* The media type to try next. */ + int wait; /* Time before we check media status. */ +} media_tbl[] = { + { "10baseT", Media_10TP,0x08, XCVR_10base2, (14*HZ)/10}, + { "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1*HZ)/10}, + { "undefined", 0, 0x80, XCVR_10baseT, 10000}, + { "10base2", 0, 0x10, XCVR_AUI, (1*HZ)/10}, + { "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14*HZ)/10}, + { "100baseFX", Media_Lnk, 0x04, XCVR_MII, (14*HZ)/10}, + { "MII", 0, 0x41, XCVR_10baseT, 3*HZ }, + { "undefined", 0, 0x01, XCVR_10baseT, 10000}, + { "Autonegotiate", 0, 0x41, XCVR_10baseT, 3*HZ}, + { "MII-External", 0, 0x41, XCVR_10baseT, 3*HZ }, + { "Default", 0, 0xFF, XCVR_10baseT, 10000}, +}; + +#ifndef CARDBUS +static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[]); +#endif +static void vortex_up(struct net_device *dev); +static void vortex_down(struct net_device *dev); +static int vortex_open(struct net_device *dev); +static void mdio_sync(long ioaddr, int bits); +static int mdio_read(long ioaddr, int phy_id, int location); +static void mdio_write(long ioaddr, int phy_id, int location, int value); +static void vortex_timer(unsigned long arg); +static int vortex_start_xmit(struct sk_buff *skb, struct net_device *dev); +static int boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev); +static int vortex_rx(struct net_device *dev); +static int boomerang_rx(struct net_device *dev); +static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static int vortex_close(struct net_device *dev); +static void update_stats(long ioaddr, struct net_device *dev); +static struct net_device_stats *vortex_get_stats(struct net_device *dev); +static void set_rx_mode(struct net_device *dev); +static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static void acpi_wake(int pci_bus, int pci_devfn); +static void acpi_set_WOL(struct net_device *dev); + +/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */ +/* Option count limit only -- unlimited interfaces are supported. */ +#define MAX_UNITS 8 +static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1,}; +static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; +/* 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; +#endif + +#ifdef CARDBUS + +#include + +static dev_node_t *vortex_attach(dev_locator_t *loc) +{ + u16 dev_id, vendor_id; + u32 io; + u8 bus, devfn, irq; + struct net_device *dev; + 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); + printk(KERN_INFO "vortex_attach(bus %d, function %d, device %4.4x)\n", + bus, devfn, dev_id); + io &= ~3; + if (io == 0 || irq == 0) { + printk(KERN_ERR "The 3Com CardBus Ethernet interface was not " + "assigned an %s.\n" KERN_ERR " It will not be activated.\n", + io == 0 ? "I/O address" : "IRQ"); + return NULL; + } + for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++) + if (vendor_id == pci_tbl[chip_idx].vendor_id + && (dev_id & pci_tbl[chip_idx].device_id_mask) == + pci_tbl[chip_idx].device_id) + break; + if (pci_tbl[chip_idx].vendor_id == 0) { /* Compiled out! */ + printk(KERN_INFO "Unable to match chip type %4.4x %4.4x in " + "vortex_attach().\n", vendor_id, dev_id); + return NULL; + } + dev = vortex_probe1(bus, devfn, NULL, 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); + node->major = node->minor = 0; + node->next = NULL; + MOD_INC_USE_COUNT; + return node; + } + return NULL; +} + +static void vortex_detach(dev_node_t *node) +{ + struct net_device **devp, **next; + printk(KERN_INFO "vortex_detach(%s)\n", node->dev_name); + for (devp = &root_vortex_dev; *devp; devp = next) { + next = &((struct vortex_private *)(*devp)->priv)->next_module; + if (strcmp((*devp)->name, node->dev_name) == 0) break; + } + if (*devp) { + struct net_device *dev = *devp; + struct vortex_private *vp = dev->priv; + if (dev->flags & IFF_UP) + vortex_close(dev); + dev->flags &= ~(IFF_UP|IFF_RUNNING); + unregister_netdev(dev); + if (vp->cb_fn_base) iounmap(vp->cb_fn_base); + kfree(dev); + *devp = *next; + kfree(vp->priv_addr); + kfree(node); + MOD_DEC_USE_COUNT; + } +} + +static void vortex_suspend(dev_node_t *node) +{ + struct net_device *dev, *next; + printk(KERN_INFO "vortex_suspend(%s)\n", node->dev_name); + for (dev = root_vortex_dev; dev; dev = next) { + next = ((struct vortex_private *)dev->priv)->next_module; + if (strcmp(dev->name, node->dev_name) == 0) break; + } + if (dev && dev->priv) { + struct vortex_private *vp = (struct vortex_private *)dev->priv; + if (vp->open) vortex_down(dev); + } +} + +static void vortex_resume(dev_node_t *node) +{ + struct net_device *dev, *next; + printk(KERN_INFO "vortex_resume(%s)\n", node->dev_name); + for (dev = root_vortex_dev; dev; dev = next) { + next = ((struct vortex_private *)dev->priv)->next_module; + if (strcmp(dev->name, node->dev_name) == 0) break; + } + if (dev && dev->priv) { + struct vortex_private *vp = (struct vortex_private *)dev->priv; + if (vp->open) vortex_up(dev); + } +} + +struct driver_operations vortex_ops = { + "3c575_cb", vortex_attach, vortex_suspend, vortex_resume, vortex_detach +}; + +#endif /* Cardbus support */ + +int init_module(void) +{ + if (vortex_debug) + printk(KERN_INFO "%s", version); +#ifdef CARDBUS + register_driver(&vortex_ops); + return 0; +#else + return vortex_scan(0, pci_tbl); +#endif +} + +#else +int tc59x_probe(struct net_device *dev) +{ + static int did_version = -1; + if (++did_version <= 0) + printk(KERN_INFO "%s", version); + return vortex_scan(dev, pci_tbl); +} +#endif /* not MODULE */ + +#ifndef CARDBUS +static int vortex_scan(struct net_device *dev, struct pci_id_info pci_tbl[]) +{ + int cards_found = 0; + + /* Allow an EISA-only driver. */ +#if defined(CONFIG_PCI) || (defined(MODULE) && !defined(NO_PCI)) + /* Ideally we would detect all cards in slot order. That would + be best done a central PCI probe dispatch, which wouldn't work + well with the current structure. So instead we detect 3Com cards + in slot order. */ + if (pcibios_present()) { + static int pci_index = 0; + unsigned char pci_bus, pci_device_fn; + + for (;pci_index < 0xff; pci_index++) { + u16 vendor, device, pci_command, new_command; + int chip_idx, irq; + long 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; 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! */ + continue; + + /* The Cyclone requires config space re-write if powered down. */ + acpi_wake(pci_bus, pci_device_fn); + + { + struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); + ioaddr = pdev->resource[0].start; + irq = pdev->irq; +#elif LINUX_VERSION_CODE >= 0x20155 + struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); + ioaddr = pdev->base_address[0] & ~3; + irq = pdev->irq; + } + + if (ioaddr == 0) { + printk(KERN_WARNING " A 3Com network adapter has been found, " + "however it has not been assigned an I/O address.\n" + " You may need to power-cycle the machine for this " + "device to work!\n"); + continue; + } + + /* Activate the card. */ + pcibios_read_config_word(pci_bus, pci_device_fn, + PCI_COMMAND, &pci_command); + new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO; + if (pci_command != new_command) { + printk(KERN_INFO " The PCI BIOS has not enabled 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); + } + + dev = vortex_probe1(pci_bus, pci_device_fn, dev, ioaddr, irq, + chip_idx, cards_found); + + if (dev) { + /* Get and check the latency values. On the 3c590 series + the latency timer must be set to the maximum value to avoid + data corruption that occurs when the timer expires during + a transfer -- a bug in the Vortex chip only. */ + 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); + 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); + } + dev = 0; + cards_found++; + } + } + } +#endif /* NO_PCI */ + + /* Now check all slots of the EISA bus. */ + if (EISA_bus) { + static long ioaddr = 0x1000; + for ( ; ioaddr < 0x9000; ioaddr += 0x1000) { + int device_id; + if (check_region(ioaddr, VORTEX_TOTAL_SIZE)) + continue; + /* Check the standard EISA ID register for an encoded '3Com'. */ + if (inw(ioaddr + 0xC80) != 0x6d50) + continue; + /* Check for a product that we support, 3c59{2,7} any rev. */ + device_id = (inb(ioaddr + 0xC82)<<8) + inb(ioaddr + 0xC83); + if ((device_id & 0xFF00) != 0x5900) + continue; + vortex_probe1(0, 0, dev, ioaddr, inw(ioaddr + 0xC88) >> 12, + 4, cards_found); + dev = 0; + cards_found++; + } + } + +#ifdef MODULE + /* Special code to work-around the Compaq PCI BIOS32 problem. */ + if (compaq_ioaddr) { + vortex_probe1(0, 0, dev, 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, + struct net_device *dev, long ioaddr, + int irq, int chip_idx, int card_idx) +{ + struct vortex_private *vp; + int option; + unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */ + int i; + + dev = init_etherdev(dev, 0); + + printk(KERN_INFO "%s: 3Com %s at 0x%lx, ", + dev->name, pci_tbl[chip_idx].name, ioaddr); + + dev->base_addr = ioaddr; + dev->irq = irq; + dev->mtu = mtu; + + /* Make certain the descriptor lists are aligned. */ + { + void *mem = kmalloc(sizeof(*vp) + 15, GFP_KERNEL); + vp = (void *)(((long)mem + 15) & ~15); + vp->priv_addr = mem; + } + memset(vp, 0, sizeof(*vp)); + dev->priv = vp; + + vp->next_module = root_vortex_dev; + root_vortex_dev = dev; + + vp->chip_id = chip_idx; + vp->pci_bus = pci_bus; + vp->pci_devfn = pci_devfn; + + /* The lower four bits are the media type. */ + if (dev->mem_start) + option = dev->mem_start; + else if (card_idx < MAX_UNITS) + option = options[card_idx]; + else + option = -1; + + if (option >= 0) { + vp->media_override = ((option & 7) == 2) ? 0 : option & 15; + vp->full_duplex = (option & 0x200) ? 1 : 0; + vp->bus_master = (option & 16) ? 1 : 0; + } else { + vp->media_override = 7; + vp->full_duplex = 0; + vp->bus_master = 0; + } + if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0) + vp->full_duplex = 1; + + vp->force_fd = vp->full_duplex; + vp->options = option; + + /* Read the station address from the EEPROM. */ + EL3WINDOW(0); + for (i = 0; i < 0x40; i++) { + int timer; +#ifdef CARDBUS + outw(0x230 + i, ioaddr + Wn0EepromCmd); +#else + outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd); +#endif + /* Pause for at least 162 us. for the read to take place. */ + for (timer = 10; timer >= 0; timer--) { + udelay(162); + if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0) + break; + } + eeprom[i] = inw(ioaddr + Wn0EepromData); + } + for (i = 0; i < 0x18; i++) + checksum ^= eeprom[i]; + checksum = (checksum ^ (checksum >> 8)) & 0xff; + if (checksum != 0x00) { /* Grrr, needless incompatible change 3Com. */ + while (i < 0x21) + checksum ^= eeprom[i++]; + checksum = (checksum ^ (checksum >> 8)) & 0xff; + } + if (checksum != 0x00) + printk(" ***INVALID CHECKSUM %4.4x*** ", checksum); + + for (i = 0; i < 3; i++) + ((u16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]); + for (i = 0; i < 6; i++) + printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]); + EL3WINDOW(2); + for (i = 0; i < 6; i++) + outb(dev->dev_addr[i], ioaddr + i); + +#ifdef __sparc__ + printk(", IRQ %s\n", __irq_itoa(dev->irq)); +#else + printk(", IRQ %d\n", dev->irq); + /* Tell them about an invalid IRQ. */ + if (vortex_debug && (dev->irq <= 0 || dev->irq >= NR_IRQS)) + printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n", + dev->irq); +#endif + + 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); + if (fn_st_addr) + vp->cb_fn_base = ioremap(fn_st_addr & ~3, 128); + printk(KERN_INFO "%s: CardBus functions mapped %8.8x->%p\n", + dev->name, fn_st_addr, vp->cb_fn_base); + } + + /* Extract our information from the EEPROM data. */ + vp->info1 = eeprom[13]; + vp->info2 = eeprom[15]; + vp->capabilities = eeprom[16]; + + if (vp->info1 & 0x8000) + vp->full_duplex = 1; + + { + char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; + union wn3_config config; + EL3WINDOW(3); + vp->available_media = inw(ioaddr + Wn3_Options); + if ((vp->available_media & 0xff) == 0) /* Broken 3c916 */ + vp->available_media = 0x40; + config.i = inl(ioaddr + Wn3_Config); + if (vortex_debug > 1) + printk(KERN_DEBUG " Internal config register is %4.4x, " + "transceivers %#x.\n", config.i, inw(ioaddr + Wn3_Options)); + printk(KERN_INFO " %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n", + 8 << config.u.ram_size, + config.u.ram_width ? "word" : "byte", + ram_split[config.u.ram_split], + config.u.autoselect ? "autoselect/" : "", + config.u.xcvr > XCVR_ExtMII ? "" : + media_tbl[config.u.xcvr].name); + vp->default_media = config.u.xcvr; + vp->autoselect = config.u.autoselect; + } + + if (vp->media_override != 7) { + printk(KERN_INFO " Media override to transceiver type %d (%s).\n", + vp->media_override, media_tbl[vp->media_override].name); + dev->if_port = vp->media_override; + } else + dev->if_port = vp->default_media; + + if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) { + int phy, phy_idx = 0; + EL3WINDOW(4); + mii_preamble_required++; + mii_preamble_required++; + mdio_read(ioaddr, 24, 1); + for (phy = 1; phy <= 32 && phy_idx < sizeof(vp->phys); phy++) { + int mii_status, phyx = phy & 0x1f; + mii_status = mdio_read(ioaddr, phyx, 1); + if (mii_status && mii_status != 0xffff) { + vp->phys[phy_idx++] = phyx; + printk(KERN_INFO " MII transceiver found at address %d," + " status %4x.\n", phyx, mii_status); + if ((mii_status & 0x0040) == 0) + mii_preamble_required++; + } + } + mii_preamble_required--; + if (phy_idx == 0) { + printk(KERN_WARNING" ***WARNING*** No MII transceivers found!\n"); + vp->phys[0] = 24; + } else { + vp->advertising = mdio_read(ioaddr, vp->phys[0], 4); + if (vp->full_duplex) { + /* Only advertise the FD media types. */ + vp->advertising &= ~0x02A0; + mdio_write(ioaddr, vp->phys[0], 4, vp->advertising); + } + } + } + + if (vp->capabilities & CapPwrMgmt) + acpi_set_WOL(dev); + + if (vp->capabilities & CapBusMaster) { + vp->full_bus_master_tx = 1; + printk(KERN_INFO" Enabling bus-master transmits and %s receives.\n", + (vp->info2 & 1) ? "early" : "whole-frame" ); + vp->full_bus_master_rx = (vp->info2 & 1) ? 1 : 2; + } + + /* We do a request_region() to register /proc/ioports info. */ + request_region(ioaddr, pci_tbl[chip_idx].io_size, dev->name); + + /* The 3c59x-specific entries in the device structure. */ + dev->open = &vortex_open; + dev->hard_start_xmit = &vortex_start_xmit; + dev->stop = &vortex_close; + dev->get_stats = &vortex_get_stats; + dev->do_ioctl = &vortex_ioctl; + dev->set_multicast_list = &set_rx_mode; + + return dev; +} + +static void wait_for_completion(struct net_device *dev, int cmd) +{ + int i = 2000; + outw(cmd, dev->base_addr + EL3_CMD); + while (--i > 0) + if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress)) + break; + if (i == 0) + printk(KERN_NOTICE "%s: command 0x%04x did not complete!\n", + dev->name, cmd); +} + +static void +vortex_up(struct net_device *dev) +{ + long ioaddr = dev->base_addr; + struct vortex_private *vp = (struct vortex_private *)dev->priv; + union wn3_config config; + int i; + + /* Should be if(HAS_ACPI) */ + acpi_wake(vp->pci_bus, vp->pci_devfn); + + /* Before initializing select the active media port. */ + EL3WINDOW(3); + config.i = inl(ioaddr + Wn3_Config); + + if (vp->media_override != 7) { + if (vortex_debug > 1) + printk(KERN_INFO "%s: Media override to transceiver %d (%s).\n", + dev->name, vp->media_override, + media_tbl[vp->media_override].name); + dev->if_port = vp->media_override; + } else if (vp->autoselect) { + if (pci_tbl[vp->chip_id].drv_flags & HAS_NWAY) + dev->if_port = XCVR_NWAY; + else { + /* Find first available media type, starting with 100baseTx. */ + dev->if_port = XCVR_100baseTx; + while (! (vp->available_media & media_tbl[dev->if_port].mask)) + dev->if_port = media_tbl[dev->if_port].next; + } + } else + dev->if_port = vp->default_media; + + init_timer(&vp->timer); + vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait); + vp->timer.data = (unsigned long)dev; + vp->timer.function = &vortex_timer; /* timer handler */ + add_timer(&vp->timer); + + if (vortex_debug > 1) + printk(KERN_DEBUG "%s: Initial media type %s.\n", + dev->name, media_tbl[dev->if_port].name); + + vp->full_duplex = vp->force_fd; + config.u.xcvr = dev->if_port; + if ( ! (pci_tbl[vp->chip_id].drv_flags & HAS_NWAY)) + outl(config.i, ioaddr + Wn3_Config); + + if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) { + int mii_reg1, mii_reg5; + EL3WINDOW(4); + /* Read BMSR (reg1) only to clear old status. */ + mii_reg1 = mdio_read(ioaddr, vp->phys[0], 1); + mii_reg5 = mdio_read(ioaddr, vp->phys[0], 5); + if (mii_reg5 == 0xffff || mii_reg5 == 0x0000) + ; /* No MII device or no link partner report */ + else if ((mii_reg5 & 0x0100) != 0 /* 100baseTx-FD */ + || (mii_reg5 & 0x00C0) == 0x0040) /* 10T-FD, but not 100-HD */ + vp->full_duplex = 1; + if (vortex_debug > 1) + printk(KERN_INFO "%s: MII #%d status %4.4x, link partner capability %4.4x," + " setting %s-duplex.\n", dev->name, vp->phys[0], + mii_reg1, mii_reg5, vp->full_duplex ? "full" : "half"); + EL3WINDOW(3); + } + + /* Set the full-duplex bit. */ + outb(((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) | + (dev->mtu > 1500 ? 0x40 : 0), ioaddr + Wn3_MAC_Ctrl); + + if (vortex_debug > 1) { + printk(KERN_DEBUG "%s: vortex_open() InternalConfig %8.8x.\n", + dev->name, config.i); + } + + wait_for_completion(dev, TxReset); + wait_for_completion(dev, RxReset); + + outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD); + + if (vortex_debug > 1) { + EL3WINDOW(4); + printk(KERN_DEBUG "%s: vortex_open() irq %d media status %4.4x.\n", + dev->name, dev->irq, inw(ioaddr + Wn4_Media)); + } + + /* Set the station address and mask in window 2 each time opened. */ + EL3WINDOW(2); + for (i = 0; i < 6; i++) + outb(dev->dev_addr[i], ioaddr + i); + for (; i < 12; i+=2) + outw(0, ioaddr + i); + if (vp->cb_fn_base) { + u_short n = inw(ioaddr + Wn2_ResetOptions); + /* Inverted LED polarity */ + if (pci_tbl[vp->chip_id].device_id != 0x5257) + n |= 0x0010; + /* Inverted polarity of MII power bit */ + if ((pci_tbl[vp->chip_id].device_id == 0x6560) || + (pci_tbl[vp->chip_id].device_id == 0x6562) || + (pci_tbl[vp->chip_id].device_id == 0x5257)) + n |= 0x4000; + outw(n, ioaddr + Wn2_ResetOptions); + } + + if (dev->if_port == XCVR_10base2) + /* Start the thinnet transceiver. We should really wait 50ms...*/ + outw(StartCoax, ioaddr + EL3_CMD); + if (dev->if_port != XCVR_NWAY) { + EL3WINDOW(4); + outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) | + media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media); + } + + /* Switch to the stats window, and clear all stats by reading. */ + outw(StatsDisable, ioaddr + EL3_CMD); + EL3WINDOW(6); + for (i = 0; i < 10; i++) + inb(ioaddr + i); + inw(ioaddr + 10); + inw(ioaddr + 12); + /* New: On the Vortex we must also clear the BadSSD counter. */ + EL3WINDOW(4); + inb(ioaddr + 12); + /* ..and on the Boomerang we enable the extra statistics bits. */ + outw(0x0040, ioaddr + Wn4_NetDiag); + + /* Switch to register set 7 for normal use. */ + EL3WINDOW(7); + + if (vp->full_bus_master_rx) { /* Boomerang bus master. */ + vp->cur_rx = vp->dirty_rx = 0; + /* Initialize the RxEarly register as recommended. */ + outw(SetRxThreshold + (1536>>2), ioaddr + EL3_CMD); + outl(0x0020, ioaddr + PktStatus); + outl(virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr); + } + if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */ + dev->hard_start_xmit = &boomerang_start_xmit; + vp->cur_tx = vp->dirty_tx = 0; + outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */ + /* Clear the Tx ring. */ + for (i = 0; i < TX_RING_SIZE; i++) + vp->tx_skbuff[i] = 0; + outl(0, ioaddr + DownListPtr); + } + /* Set receiver mode: presumably accept b-case and phys addr only. */ + set_rx_mode(dev); + outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ + + vp->in_interrupt = 0; + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ + outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ + /* Allow status bits to be seen. */ + vp->status_enable = SetStatusEnb | HostError|IntReq|StatsFull|TxComplete| + (vp->full_bus_master_tx ? DownComplete : TxAvailable) | + (vp->full_bus_master_rx ? UpComplete : RxComplete) | + (vp->bus_master ? DMADone : 0); + vp->intr_enable = SetIntrEnb | IntLatch | TxAvailable | RxComplete | + StatsFull | HostError | TxComplete | IntReq + | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete; + outw(vp->status_enable, ioaddr + EL3_CMD); + /* Ack all pending events, and set active indicator mask. */ + outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, + ioaddr + EL3_CMD); + outw(vp->intr_enable, ioaddr + EL3_CMD); + if (vp->cb_fn_base) /* The PCMCIA people are idiots. */ + writel(0x8000, vp->cb_fn_base + 4); +} + +static int +vortex_open(struct net_device *dev) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + int i; + + /* Use the now-standard shared IRQ implementation. */ + if (request_irq(dev->irq, &vortex_interrupt, SA_SHIRQ, dev->name, dev)) { + return -EAGAIN; + } + + if (vp->full_bus_master_rx) { /* Boomerang bus master. */ + if (vortex_debug > 2) + printk(KERN_DEBUG "%s: Filling in the Rx ring.\n", dev->name); + for (i = 0; i < RX_RING_SIZE; i++) { + struct sk_buff *skb; + vp->rx_ring[i].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[i+1])); + vp->rx_ring[i].status = 0; /* Clear complete bit. */ + vp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LAST_FRAG); + skb = dev_alloc_skb(PKT_BUF_SZ); + vp->rx_skbuff[i] = skb; + if (skb == NULL) + break; /* Bad news! */ + skb->dev = dev; /* Mark as being used by this device. */ + skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ + vp->rx_ring[i].addr = cpu_to_le32(virt_to_bus(skb->tail)); + } + /* Wrap the ring. */ + vp->rx_ring[i-1].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[0])); + } + if (vp->full_bus_master_tx) + dev->hard_start_xmit = &boomerang_start_xmit; + + vortex_up(dev); + vp->open = 1; + MOD_INC_USE_COUNT; + + return 0; +} + +static void vortex_timer(unsigned long data) +{ + struct net_device *dev = (struct net_device *)data; + struct vortex_private *vp = (struct vortex_private *)dev->priv; + long ioaddr = dev->base_addr; + int next_tick = 60*HZ; + int ok = 0; + int media_status, mii_status, old_window; + + if (vortex_debug > 1) + printk(KERN_DEBUG "%s: Media selection timer tick happened, %s.\n", + dev->name, media_tbl[dev->if_port].name); + + disable_irq(dev->irq); + old_window = inw(ioaddr + EL3_CMD) >> 13; + EL3WINDOW(4); + media_status = inw(ioaddr + Wn4_Media); + switch (dev->if_port) { + case XCVR_10baseT: case XCVR_100baseTx: case XCVR_100baseFx: + if (media_status & Media_LnkBeat) { + ok = 1; + if (vortex_debug > 1) + printk(KERN_DEBUG "%s: Media %s has link beat, %x.\n", + dev->name, media_tbl[dev->if_port].name, media_status); + } else if (vortex_debug > 1) + printk(KERN_DEBUG "%s: Media %s is has no link beat, %x.\n", + dev->name, media_tbl[dev->if_port].name, media_status); + break; + case XCVR_MII: case XCVR_NWAY: + mii_status = mdio_read(ioaddr, vp->phys[0], 1); + ok = 1; + if (debug > 1) + printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n", + dev->name, mii_status); + if (mii_status & 0x0004) { + int mii_reg5 = mdio_read(ioaddr, vp->phys[0], 5); + if (! vp->force_fd && mii_reg5 != 0xffff) { + int duplex = (mii_reg5&0x0100) || + (mii_reg5 & 0x01C0) == 0x0040; + if (vp->full_duplex != duplex) { + vp->full_duplex = duplex; + printk(KERN_INFO "%s: Setting %s-duplex based on MII " + "#%d link partner capability of %4.4x.\n", + dev->name, vp->full_duplex ? "full" : "half", + vp->phys[0], mii_reg5); + /* Set the full-duplex bit. */ + EL3WINDOW(3); + outb((vp->full_duplex ? 0x20 : 0) | + (dev->mtu > 1500 ? 0x40 : 0), + ioaddr + Wn3_MAC_Ctrl); + } + next_tick = 60*HZ; + } + } + break; + default: /* Other media types handled by Tx timeouts. */ + if (vortex_debug > 1) + printk(KERN_DEBUG "%s: Media %s is has no indication, %x.\n", + dev->name, media_tbl[dev->if_port].name, media_status); + ok = 1; + } + if ( ! ok) { + union wn3_config config; + + do { + dev->if_port = media_tbl[dev->if_port].next; + } while ( ! (vp->available_media & media_tbl[dev->if_port].mask)); + if (dev->if_port == XCVR_Default) { /* Go back to default. */ + dev->if_port = vp->default_media; + if (vortex_debug > 1) + printk(KERN_DEBUG "%s: Media selection failing, using default " + "%s port.\n", + dev->name, media_tbl[dev->if_port].name); + } else { + if (vortex_debug > 1) + printk(KERN_DEBUG "%s: Media selection failed, now trying " + "%s port.\n", + dev->name, media_tbl[dev->if_port].name); + next_tick = media_tbl[dev->if_port].wait; + } + outw((media_status & ~(Media_10TP|Media_SQE)) | + media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media); + + EL3WINDOW(3); + config.i = inl(ioaddr + Wn3_Config); + config.u.xcvr = dev->if_port; + outl(config.i, ioaddr + Wn3_Config); + + outw(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax, + ioaddr + EL3_CMD); + } + EL3WINDOW(old_window); + enable_irq(dev->irq); + + if (vortex_debug > 2) + printk(KERN_DEBUG "%s: Media selection timer finished, %s.\n", + dev->name, media_tbl[dev->if_port].name); + + vp->timer.expires = RUN_AT(next_tick); + add_timer(&vp->timer); + return; +} + +static void vortex_tx_timeout(struct net_device *dev) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + long ioaddr = dev->base_addr; + + printk(KERN_ERR "%s: transmit timed out, tx_status %2.2x status %4.4x.\n", + dev->name, inb(ioaddr + TxStatus), + inw(ioaddr + EL3_STATUS)); + /* Slight code bloat to be user friendly. */ + if ((inb(ioaddr + TxStatus) & 0x88) == 0x88) + printk(KERN_ERR "%s: Transmitter encountered 16 collisions --" + " network cable problem?\n", dev->name); + if (inw(ioaddr + EL3_STATUS) & IntLatch) { + printk(KERN_ERR "%s: Interrupt posted but not delivered --" + " IRQ blocked by another device?\n", dev->name); + /* Bad idea here.. but we might as well handle a few events. */ + vortex_interrupt(dev->irq, dev, 0); + } + +#if ! defined(final_version) && LINUX_VERSION_CODE >= 0x10300 + if (vp->full_bus_master_tx) { + int i; + printk(KERN_DEBUG " Flags; bus-master %d, full %d; dirty %d " + "current %d.\n", + vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx, vp->cur_tx); + printk(KERN_DEBUG " Transmit list %8.8x vs. %p.\n", + inl(ioaddr + DownListPtr), + &vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]); + for (i = 0; i < TX_RING_SIZE; i++) { + printk(KERN_DEBUG " %d: @%p length %8.8x status %8.8x\n", i, + &vp->tx_ring[i], + le32_to_cpu(vp->tx_ring[i].length), + le32_to_cpu(vp->tx_ring[i].status)); + } + } +#endif + wait_for_completion(dev, TxReset); + + vp->stats.tx_errors++; + if (vp->full_bus_master_tx) { + if (vortex_debug > 0) + printk(KERN_DEBUG "%s: Resetting the Tx ring pointer.\n", + dev->name); + if (vp->cur_tx - vp->dirty_tx > 0 && inl(ioaddr + DownListPtr) == 0) + outl(virt_to_bus(&vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]), + ioaddr + DownListPtr); + if (vp->tx_full && (vp->cur_tx - vp->dirty_tx <= TX_RING_SIZE - 1)) { + vp->tx_full = 0; + clear_bit(0, (void*)&dev->tbusy); + } + outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); + outw(DownUnstall, ioaddr + EL3_CMD); + } else + vp->stats.tx_dropped++; + + /* Issue Tx Enable */ + outw(TxEnable, ioaddr + EL3_CMD); + dev->trans_start = jiffies; + + /* Switch to register set 7 for normal use. */ + EL3WINDOW(7); +} + +/* + * Handle uncommon interrupt sources. This is a separate routine to minimize + * the cache impact. + */ +static void +vortex_error(struct net_device *dev, int status) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + long ioaddr = dev->base_addr; + int do_tx_reset = 0; + + if (status & TxComplete) { /* Really "TxError" for us. */ + unsigned char tx_status = inb(ioaddr + TxStatus); + /* Presumably a tx-timeout. We must merely re-enable. */ + if (vortex_debug > 2 + || (tx_status != 0x88 && vortex_debug > 0)) + printk(KERN_DEBUG"%s: Transmit error, Tx status register %2.2x.\n", + dev->name, tx_status); + if (tx_status & 0x14) vp->stats.tx_fifo_errors++; + if (tx_status & 0x38) vp->stats.tx_aborted_errors++; + outb(0, ioaddr + TxStatus); + if (tx_status & 0x30) + do_tx_reset = 1; + else /* Merely re-enable the transmitter. */ + outw(TxEnable, ioaddr + EL3_CMD); + } + if (status & RxEarly) { /* Rx early is unused. */ + vortex_rx(dev); + outw(AckIntr | RxEarly, ioaddr + EL3_CMD); + } + if (status & StatsFull) { /* Empty statistics. */ + static int DoneDidThat = 0; + if (vortex_debug > 4) + printk(KERN_DEBUG "%s: Updating stats.\n", dev->name); + update_stats(ioaddr, dev); + /* HACK: Disable statistics as an interrupt source. */ + /* This occurs when we have the wrong media type! */ + if (DoneDidThat == 0 && + inw(ioaddr + EL3_STATUS) & StatsFull) { + printk(KERN_WARNING "%s: Updating statistics failed, disabling " + "stats as an interrupt source.\n", dev->name); + EL3WINDOW(5); + outw(SetIntrEnb | (inw(ioaddr + 10) & ~StatsFull), ioaddr + EL3_CMD); + EL3WINDOW(7); + DoneDidThat++; + } + } + if (status & IntReq) { /* Restore all interrupt sources. */ + outw(vp->status_enable, ioaddr + EL3_CMD); + outw(vp->intr_enable, ioaddr + EL3_CMD); + } + if (status & HostError) { + u16 fifo_diag; + EL3WINDOW(4); + fifo_diag = inw(ioaddr + Wn4_FIFODiag); + printk(KERN_ERR "%s: Host error, FIFO diagnostic register %4.4x.\n", + dev->name, fifo_diag); + /* Adapter failure requires Tx/Rx reset and reinit. */ + if (vp->full_bus_master_tx) { + wait_for_completion(dev, TotalReset | 0xff); + /* Re-enable the receiver. */ + outw(RxEnable, ioaddr + EL3_CMD); + outw(TxEnable, ioaddr + EL3_CMD); + } else if (fifo_diag & 0x0400) + do_tx_reset = 1; + if (fifo_diag & 0x3000) { + wait_for_completion(dev, RxReset); + /* Set the Rx filter to the current state. */ + set_rx_mode(dev); + outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */ + outw(AckIntr | HostError, ioaddr + EL3_CMD); + } + } + if (do_tx_reset) { + wait_for_completion(dev, TxReset); + outw(TxEnable, ioaddr + EL3_CMD); + } + +} + +static int +vortex_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + long ioaddr = dev->base_addr; + + if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { + if (jiffies - dev->trans_start >= TX_TIMEOUT) + vortex_tx_timeout(dev); + return 1; + } + + /* Put out the doubleword header... */ + outl(skb->len, ioaddr + TX_FIFO); + if (vp->bus_master) { + /* Set the bus-master controller to transfer the packet. */ + outl(virt_to_bus(skb->data), ioaddr + Wn7_MasterAddr); + outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen); + vp->tx_skb = skb; + outw(StartDMADown, ioaddr + EL3_CMD); + /* dev->tbusy will be cleared at the DMADone interrupt. */ + } else { + /* ... and the packet rounded to a doubleword. */ + outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); + DEV_FREE_SKB(skb); + if (inw(ioaddr + TxFree) > 1536) { + clear_bit(0, (void*)&dev->tbusy); + } else + /* Interrupt us when the FIFO has room for max-sized packet. */ + outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD); + } + + dev->trans_start = jiffies; + + /* Clear the Tx status stack. */ + { + int tx_status; + int i = 32; + + while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) { + if (tx_status & 0x3C) { /* A Tx-disabling error occurred. */ + if (vortex_debug > 2) + printk(KERN_DEBUG "%s: Tx error, status %2.2x.\n", + dev->name, tx_status); + if (tx_status & 0x04) vp->stats.tx_fifo_errors++; + if (tx_status & 0x38) vp->stats.tx_aborted_errors++; + if (tx_status & 0x30) { + wait_for_completion(dev, TxReset); + } + outw(TxEnable, ioaddr + EL3_CMD); + } + outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */ + } + } + return 0; +} + +static int +boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + long ioaddr = dev->base_addr; + + if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { + if (jiffies - dev->trans_start >= TX_TIMEOUT) + vortex_tx_timeout(dev); + return 1; + } else { + /* Calculate the next Tx descriptor entry. */ + int entry = vp->cur_tx % TX_RING_SIZE; + struct boom_tx_desc *prev_entry = + &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE]; + unsigned long flags; + + if (vortex_debug > 3) + printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n", + dev->name, vp->cur_tx); + if (vp->tx_full) { + if (vortex_debug >0) + printk(KERN_WARNING "%s: Tx Ring full, refusing to send buffer.\n", + dev->name); + return 1; + } + vp->tx_skbuff[entry] = skb; + vp->tx_ring[entry].next = 0; + vp->tx_ring[entry].addr = cpu_to_le32(virt_to_bus(skb->data)); + vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG); + vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded); + + save_flags(flags); + cli(); + /* Wait for the stall to complete. */ + wait_for_completion(dev, DownStall); + prev_entry->next = cpu_to_le32(virt_to_bus(&vp->tx_ring[entry])); + if (inl(ioaddr + DownListPtr) == 0) { + outl(virt_to_bus(&vp->tx_ring[entry]), ioaddr + DownListPtr); + queued_packet++; + } + outw(DownUnstall, ioaddr + EL3_CMD); + restore_flags(flags); + + vp->cur_tx++; + if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1) + vp->tx_full = 1; + else { /* Clear previous interrupt enable. */ +#if defined(tx_interrupt_mitigation) + prev_entry->status &= cpu_to_le32(~TxIntrUploaded); +#endif + clear_bit(0, (void*)&dev->tbusy); + } + dev->trans_start = jiffies; + return 0; + } +} + +/* The interrupt handler does all of the Rx thread work and cleans up + after the Tx thread. */ +static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = dev_id; + struct vortex_private *vp = (struct vortex_private *)dev->priv; + long ioaddr; + int latency, status; + int work_done = 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 + + dev->interrupt = 1; + ioaddr = dev->base_addr; + latency = inb(ioaddr + Timer); + status = inw(ioaddr + EL3_STATUS); + + if (status == 0xffff) + goto handler_exit; + if (vortex_debug > 4) + printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n", + dev->name, status, latency); + do { + if (vortex_debug > 5) + printk(KERN_DEBUG "%s: In interrupt loop, status %4.4x.\n", + dev->name, status); + if (status & RxComplete) + vortex_rx(dev); + if (status & UpComplete) { + outw(AckIntr | UpComplete, ioaddr + EL3_CMD); + boomerang_rx(dev); + } + + if (status & TxAvailable) { + if (vortex_debug > 5) + printk(KERN_DEBUG " TX room bit was handled.\n"); + /* There's room in the FIFO for a full-sized packet. */ + outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); + clear_bit(0, (void*)&dev->tbusy); + mark_bh(NET_BH); + } + + if (status & DownComplete) { + unsigned int dirty_tx = vp->dirty_tx; + + outw(AckIntr | DownComplete, ioaddr + EL3_CMD); + while (vp->cur_tx - dirty_tx > 0) { + int entry = dirty_tx % TX_RING_SIZE; + if (inl(ioaddr + DownListPtr) == + virt_to_bus(&vp->tx_ring[entry])) + break; /* It still hasn't been processed. */ + if (vp->tx_skbuff[entry]) { + DEV_FREE_SKB(vp->tx_skbuff[entry]); + vp->tx_skbuff[entry] = 0; + } + /* vp->stats.tx_packets++; Counted below. */ + dirty_tx++; + } + vp->dirty_tx = dirty_tx; + if (vp->tx_full && (vp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) { + vp->tx_full = 0; + clear_bit(0, (void*)&dev->tbusy); + mark_bh(NET_BH); + } + } + if (status & DMADone) { + if (inw(ioaddr + Wn7_MasterStatus) & 0x1000) { + outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */ + DEV_FREE_SKB(vp->tx_skb); /* Release the transfered buffer */ + if (inw(ioaddr + TxFree) > 1536) { + clear_bit(0, (void*)&dev->tbusy); + mark_bh(NET_BH); + } else /* Interrupt when FIFO has room for max-sized packet. */ + outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD); + } + } + /* Check for all uncommon interrupts at once. */ + if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) { + if (status == 0xffff) + break; + vortex_error(dev, status); + } + + if (--work_done < 0) { + if ((status & (0x7fe - (UpComplete | DownComplete))) == 0) { + /* Just ack these and return. */ + outw(AckIntr | UpComplete | DownComplete, ioaddr + EL3_CMD); + } else { + printk(KERN_WARNING "%s: Too much work in interrupt, status " + "%4.4x. Temporarily disabling functions (%4.4x).\n", + dev->name, status, SetStatusEnb | ((~status) & 0x7FE)); + /* Disable all pending interrupts. */ + outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD); + outw(AckIntr | 0x7FF, ioaddr + EL3_CMD); + /* The timer will reenable interrupts. */ + break; + } + } + /* Acknowledge the IRQ. */ + outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); + if (vp->cb_fn_base) /* The PCMCIA people are idiots. */ + writel(0x8000, vp->cb_fn_base + 4); + + } while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete)); + + if (vortex_debug > 4) + printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n", + dev->name, status); +handler_exit: +#if defined(__i386__) + clear_bit(0, (void*)&dev->interrupt); +#else + dev->interrupt = 0; +#endif + return; +} + +static int vortex_rx(struct net_device *dev) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + long ioaddr = dev->base_addr; + int i; + short rx_status; + + if (vortex_debug > 5) + printk(KERN_DEBUG" In rx_packet(), status %4.4x, rx_status %4.4x.\n", + inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus)); + while ((rx_status = inw(ioaddr + RxStatus)) > 0) { + if (rx_status & 0x4000) { /* Error, update stats. */ + unsigned char rx_error = inb(ioaddr + RxErrors); + if (vortex_debug > 2) + printk(KERN_DEBUG " Rx error: status %2.2x.\n", rx_error); + vp->stats.rx_errors++; + if (rx_error & 0x01) vp->stats.rx_over_errors++; + if (rx_error & 0x02) vp->stats.rx_length_errors++; + if (rx_error & 0x04) vp->stats.rx_frame_errors++; + if (rx_error & 0x08) vp->stats.rx_crc_errors++; + if (rx_error & 0x10) vp->stats.rx_length_errors++; + } else { + /* The packet length: up to 4.5K!. */ + int pkt_len = rx_status & 0x1fff; + struct sk_buff *skb; + + skb = dev_alloc_skb(pkt_len + 5); + if (vortex_debug > 4) + printk(KERN_DEBUG "Receiving packet size %d status %4.4x.\n", + pkt_len, rx_status); + if (skb != NULL) { + skb->dev = dev; + skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ + /* 'skb_put()' points to the start of sk_buff data area. */ + if (vp->bus_master && + ! (inw(ioaddr + Wn7_MasterStatus) & 0x8000)) { + outl(virt_to_bus(skb_put(skb, pkt_len)), + ioaddr + Wn7_MasterAddr); + outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen); + outw(StartDMAUp, ioaddr + EL3_CMD); + while (inw(ioaddr + Wn7_MasterStatus) & 0x8000) + ; + } else { + insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len), + (pkt_len + 3) >> 2); + } + outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */ + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + dev->last_rx = jiffies; + vp->stats.rx_packets++; + /* Wait a limited time to go to next packet. */ + for (i = 200; i >= 0; i--) + if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) + break; + continue; + } else if (vortex_debug) + printk(KERN_NOTICE "%s: No memory to allocate a sk_buff of " + "size %d.\n", dev->name, pkt_len); + } + outw(RxDiscard, ioaddr + EL3_CMD); + vp->stats.rx_dropped++; + /* Wait a limited time to skip this packet. */ + for (i = 200; i >= 0; i--) + if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) + break; + } + + return 0; +} + +static int +boomerang_rx(struct net_device *dev) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + int entry = vp->cur_rx % RX_RING_SIZE; + long ioaddr = dev->base_addr; + int rx_status; + int rx_work_limit = vp->dirty_rx + RX_RING_SIZE - vp->cur_rx; + + if (vortex_debug > 5) + printk(KERN_DEBUG " In boomerang_rx(), status %4.4x, rx_status " + "%4.4x.\n", + inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus)); + while ((rx_status = le32_to_cpu(vp->rx_ring[entry].status)) & RxDComplete){ + if (--rx_work_limit < 0) + break; + if (rx_status & RxDError) { /* Error, update stats. */ + unsigned char rx_error = rx_status >> 16; + if (vortex_debug > 2) + printk(KERN_DEBUG " Rx error: status %2.2x.\n", rx_error); + vp->stats.rx_errors++; + if (rx_error & 0x01) vp->stats.rx_over_errors++; + if (rx_error & 0x02) vp->stats.rx_length_errors++; + if (rx_error & 0x04) vp->stats.rx_frame_errors++; + if (rx_error & 0x08) vp->stats.rx_crc_errors++; + if (rx_error & 0x10) vp->stats.rx_length_errors++; + } else { + /* The packet length: up to 4.5K!. */ + int pkt_len = rx_status & 0x1fff; + struct sk_buff *skb; + + if (vortex_debug > 4) + printk(KERN_DEBUG "Receiving packet size %d status %4.4x.\n", + pkt_len, rx_status); + + /* Check if the packet is long enough to just accept without + copying to a properly sized skbuff. */ + if (pkt_len < rx_copybreak + && (skb = dev_alloc_skb(pkt_len + 2)) != 0) { + skb->dev = dev; + skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ + /* 'skb_put()' points to the start of sk_buff data area. */ + memcpy(skb_put(skb, pkt_len), + bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)), + pkt_len); + rx_copy++; + } else { + void *temp; + /* Pass up the skbuff already on the Rx ring. */ + skb = vp->rx_skbuff[entry]; + vp->rx_skbuff[entry] = NULL; + temp = skb_put(skb, pkt_len); + /* Remove this checking code for final release. */ + if (bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)) != temp) + printk(KERN_ERR "%s: Warning -- the skbuff addresses do not match" + " in boomerang_rx: %p vs. %p.\n", dev->name, + bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)), + temp); + rx_nocopy++; + } + skb->protocol = eth_type_trans(skb, dev); + { /* Use hardware checksum info. */ + int csum_bits = rx_status & 0xee000000; + if (csum_bits && + (csum_bits == (IPChksumValid | TCPChksumValid) || + csum_bits == (IPChksumValid | UDPChksumValid))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + rx_csumhits++; + } + } + netif_rx(skb); + dev->last_rx = jiffies; + vp->stats.rx_packets++; + } + entry = (++vp->cur_rx) % RX_RING_SIZE; + } + /* Refill the Rx ring buffers. */ + for (; vp->dirty_rx < vp->cur_rx; vp->dirty_rx++) { + struct sk_buff *skb; + entry = vp->dirty_rx % RX_RING_SIZE; + if (vp->rx_skbuff[entry] == NULL) { + skb = dev_alloc_skb(PKT_BUF_SZ); + if (skb == NULL) + break; /* Bad news! */ + skb->dev = dev; /* Mark as being used by this device. */ + skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ + vp->rx_ring[entry].addr = cpu_to_le32(virt_to_bus(skb->tail)); + vp->rx_skbuff[entry] = skb; + } + vp->rx_ring[entry].status = 0; /* Clear complete bit. */ + outw(UpUnstall, ioaddr + EL3_CMD); + } + return 0; +} + +static void +vortex_down(struct net_device *dev) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + long ioaddr = dev->base_addr; + + dev->start = 0; + dev->tbusy = 1; + + del_timer(&vp->timer); + + /* Turn off statistics ASAP. We update vp->stats below. */ + outw(StatsDisable, ioaddr + EL3_CMD); + + /* Disable the receiver and transmitter. */ + outw(RxDisable, ioaddr + EL3_CMD); + outw(TxDisable, ioaddr + EL3_CMD); + + if (dev->if_port == XCVR_10base2) + /* Turn off thinnet power. Green! */ + outw(StopCoax, ioaddr + EL3_CMD); + + outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD); + + update_stats(ioaddr, dev); + if (vp->full_bus_master_rx) + outl(0, ioaddr + UpListPtr); + if (vp->full_bus_master_tx) + outl(0, ioaddr + DownListPtr); + + if (vp->capabilities & CapPwrMgmt) + acpi_set_WOL(dev); +} + +static int +vortex_close(struct net_device *dev) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + long ioaddr = dev->base_addr; + int i; + + if (dev->start) + vortex_down(dev); + + if (vortex_debug > 1) { + printk(KERN_DEBUG"%s: vortex_close() status %4.4x, Tx status %2.2x.\n", + dev->name, inw(ioaddr + EL3_STATUS), inb(ioaddr + TxStatus)); + printk(KERN_DEBUG "%s: vortex close stats: rx_nocopy %d rx_copy %d" + " tx_queued %d Rx pre-checksummed %d.\n", + dev->name, rx_nocopy, rx_copy, queued_packet, rx_csumhits); + } + + free_irq(dev->irq, dev); + + if (vp->full_bus_master_rx) { /* Free Boomerang bus master Rx buffers. */ + for (i = 0; i < RX_RING_SIZE; i++) + if (vp->rx_skbuff[i]) { + DEV_FREE_SKB(vp->rx_skbuff[i]); + vp->rx_skbuff[i] = 0; + } + } + if (vp->full_bus_master_tx) { /* Free Boomerang bus master Tx buffers. */ + for (i = 0; i < TX_RING_SIZE; i++) + if (vp->tx_skbuff[i]) { + DEV_FREE_SKB(vp->tx_skbuff[i]); + vp->tx_skbuff[i] = 0; + } + } + + MOD_DEC_USE_COUNT; + vp->open = 0; + return 0; +} + +static struct net_device_stats *vortex_get_stats(struct net_device *dev) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + unsigned long flags; + + if (dev->start) { + save_flags(flags); + cli(); + update_stats(dev->base_addr, dev); + restore_flags(flags); + } + return &vp->stats; +} + +/* Update statistics. + Unlike with the EL3 we need not worry about interrupts changing + the window setting from underneath us, but we must still guard + against a race condition with a StatsUpdate interrupt updating the + table. This is done by checking that the ASM (!) code generated uses + atomic updates with '+='. + */ +static void update_stats(long ioaddr, struct net_device *dev) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + int old_window = inw(ioaddr + EL3_CMD); + + if (old_window == 0xffff) /* Chip suspended or ejected. */ + return; + /* Unlike the 3c5x9 we need not turn off stats updates while reading. */ + /* Switch to the stats window, and read everything. */ + EL3WINDOW(6); + vp->stats.tx_carrier_errors += inb(ioaddr + 0); + vp->stats.tx_heartbeat_errors += inb(ioaddr + 1); + /* Multiple collisions. */ inb(ioaddr + 2); + vp->stats.collisions += inb(ioaddr + 3); + vp->stats.tx_window_errors += inb(ioaddr + 4); + vp->stats.rx_fifo_errors += inb(ioaddr + 5); + vp->stats.tx_packets += inb(ioaddr + 6); + vp->stats.tx_packets += (inb(ioaddr + 9)&0x30) << 4; + /* Rx packets */ inb(ioaddr + 7); /* Must read to clear */ + /* Tx deferrals */ inb(ioaddr + 8); + /* Don't bother with register 9, an extension of registers 6&7. + If we do use the 6&7 values the atomic update assumption above + is invalid. */ + vp->stats.rx_bytes += inw(ioaddr + 10); + vp->stats.tx_bytes += inw(ioaddr + 12); + /* New: On the Vortex we must also clear the BadSSD counter. */ + EL3WINDOW(4); + inb(ioaddr + 12); + + { + u8 up = inb(ioaddr + 13); + vp->stats.rx_bytes += (up & 0x0f) << 16; + vp->stats.tx_bytes += (up & 0xf0) << 12; + } + + /* We change back to window 7 (not 1) with the Vortex. */ + EL3WINDOW(old_window >> 13); + return; +} + +static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + long ioaddr = dev->base_addr; + u16 *data = (u16 *)&rq->ifr_data; + int phy = vp->phys[0] & 0x1f; + + switch(cmd) { + case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ + data[0] = phy; + case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ + EL3WINDOW(4); + data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f); + return 0; + case SIOCDEVPRIVATE+2: /* Write the specified MII register */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + EL3WINDOW(4); + mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]); + return 0; + default: + return -EOPNOTSUPP; + } +} + +/* Pre-Cyclone chips have no documented multicast filter, so the only + multicast setting is to receive all multicast frames. At least + the chip has a very clean way to set the mode, unlike many others. */ +static void set_rx_mode(struct net_device *dev) +{ + long ioaddr = dev->base_addr; + int new_mode; + + if (dev->flags & IFF_PROMISC) { + if (vortex_debug > 0) + printk(KERN_NOTICE "%s: Setting promiscuous mode.\n", dev->name); + new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast|RxProm; + } else if ((dev->mc_list) || (dev->flags & IFF_ALLMULTI)) { + new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast; + } else + new_mode = SetRxFilter | RxStation | RxBroadcast; + + outw(new_mode, ioaddr + EL3_CMD); +} + +/* MII transceiver control section. + Read and write the MII registers using software-generated serial + MDIO protocol. See the MII specifications or DP83840A data sheet + for details. */ + +/* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually + met by back-to-back PCI I/O cycles, but we insert a delay to avoid + "overclocking" issues. */ +#define mdio_delay() inl(mdio_addr) + +#define MDIO_SHIFT_CLK 0x01 +#define MDIO_DIR_WRITE 0x04 +#define MDIO_DATA_WRITE0 (0x00 | MDIO_DIR_WRITE) +#define MDIO_DATA_WRITE1 (0x02 | MDIO_DIR_WRITE) +#define MDIO_DATA_READ 0x02 +#define MDIO_ENB_IN 0x00 + +/* Generate the preamble required for initial synchronization and + a few older transceivers. */ +static void mdio_sync(long ioaddr, int bits) +{ + long mdio_addr = ioaddr + Wn4_PhysicalMgmt; + + /* Establish sync by sending at least 32 logic ones. */ + while (-- bits >= 0) { + outw(MDIO_DATA_WRITE1, mdio_addr); + mdio_delay(); + outw(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } +} + +static int mdio_read(long ioaddr, int phy_id, int location) +{ + int i; + int read_cmd = (0xf6 << 10) | (phy_id << 5) | location; + unsigned int retval = 0; + long mdio_addr = ioaddr + Wn4_PhysicalMgmt; + + if (mii_preamble_required) + mdio_sync(ioaddr, 32); + + /* Shift the read command bits out. */ + for (i = 14; i >= 0; i--) { + int dataval = (read_cmd&(1< 0; i--) { + outw(MDIO_ENB_IN, mdio_addr); + mdio_delay(); + retval = (retval << 1) | ((inw(mdio_addr) & MDIO_DATA_READ) ? 1 : 0); + outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff; +} + +static void mdio_write(long ioaddr, int phy_id, int location, int value) +{ + int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value; + long mdio_addr = ioaddr + Wn4_PhysicalMgmt; + int i; + + if (mii_preamble_required) + mdio_sync(ioaddr, 32); + + /* Shift the command bits out. */ + for (i = 31; i >= 0; i--) { + int dataval = (write_cmd&(1<= 0; i--) { + outw(MDIO_ENB_IN, mdio_addr); + mdio_delay(); + outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + + return; +} + +/* ACPI: Advanced Configuration and Power Interface. */ +/* Set Wake-On-LAN mode and put the board into D3 (power-down) state. */ +static void acpi_set_WOL(struct net_device *dev) +{ + struct vortex_private *vp = (struct vortex_private *)dev->priv; + long ioaddr = dev->base_addr; + + /* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */ + EL3WINDOW(7); + outw(2, ioaddr + 0x0c); + /* The RxFilter must accept the WOL frames. */ + outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD); + outw(RxEnable, ioaddr + EL3_CMD); + /* Change the power state to D3; RxEnable doesn't take effect. */ + pcibios_write_config_word(vp->pci_bus, vp->pci_devfn, 0xe0, 0x8103); +} +/* Change from D3 (sleep) to D0 (active). + Problem: The Cyclone forgets all PCI config info during the transition! */ +static void acpi_wake(int bus, int devfn) +{ + u32 base0, base1, romaddr; + u16 pci_command, pwr_command; + u8 pci_latency, pci_cacheline, irq; + + pcibios_read_config_word(bus, devfn, 0xe0, &pwr_command); + if ((pwr_command & 3) == 0) + return; + pcibios_read_config_word( bus, devfn, PCI_COMMAND, &pci_command); + pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &base0); + pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_1, &base1); + pcibios_read_config_dword(bus, devfn, PCI_ROM_ADDRESS, &romaddr); + pcibios_read_config_byte( bus, devfn, PCI_LATENCY_TIMER, &pci_latency); + pcibios_read_config_byte( bus, devfn, PCI_CACHE_LINE_SIZE, &pci_cacheline); + pcibios_read_config_byte( bus, devfn, PCI_INTERRUPT_LINE, &irq); + + pcibios_write_config_word( bus, devfn, 0xe0, 0x0000); + pcibios_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, base0); + pcibios_write_config_dword(bus, devfn, PCI_BASE_ADDRESS_1, base1); + pcibios_write_config_dword(bus, devfn, PCI_ROM_ADDRESS, romaddr); + pcibios_write_config_byte( bus, devfn, PCI_INTERRUPT_LINE, irq); + pcibios_write_config_byte( bus, devfn, PCI_LATENCY_TIMER, pci_latency); + pcibios_write_config_byte( bus, devfn, PCI_CACHE_LINE_SIZE, pci_cacheline); + pcibios_write_config_word( bus, devfn, PCI_COMMAND, pci_command | 5); +} + +#ifdef MODULE +void cleanup_module(void) +{ + struct net_device *next_dev; + +#ifdef CARDBUS + unregister_driver(&vortex_ops); +#endif + + /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ + while (root_vortex_dev) { + struct vortex_private *vp=(void *)(root_vortex_dev->priv); + next_dev = vp->next_module; + unregister_netdev(root_vortex_dev); + outw(TotalReset, root_vortex_dev->base_addr + EL3_CMD); + release_region(root_vortex_dev->base_addr, + pci_tbl[vp->chip_id].io_size); + kfree(root_vortex_dev); + kfree(vp->priv_addr); + root_vortex_dev = next_dev; + } +} + +#endif /* MODULE */ + +/* + * Local variables: + * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" + * SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c" + * cardbus-compile-command: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c -o 3c575_cb.o -I/usr/src/linux/pcmcia-cs-3.0.9/include/" + * c-indent-level: 4 + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index dea14d53a2cb..40e5a643fa9b 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -2,9 +2,9 @@ A PCMCIA ethernet driver for the 3com 3c589 card. - Copyright (C) 1999 David A. Hinds -- dhinds@hyper.stanford.edu + Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org - 3c589_cs.c 1.135 1999/10/07 20:14:54 + 3c589_cs.c 1.137 1999/11/08 20:46:17 The network driver code is based on Donald Becker's 3c589 code: @@ -115,7 +115,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = -"3c589_cs.c 1.135 1999/10/07 20:14:54 (David Hinds)"; +"3c589_cs.c 1.137 1999/11/08 20:46:17 (David Hinds)"; #else #define DEBUG(n, args...) #endif @@ -226,7 +226,6 @@ static dev_link_t *tc589_attach(void) link->release.data = (u_long)link; link->io.NumPorts1 = 16; link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - link->io.IOAddrLines = 4; link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; if (irq_list[0] == -1) @@ -392,6 +391,7 @@ static void tc589_config(dev_link_t *link) link->state |= DEV_CONFIG; /* For the 3c562, the base address must be xx00-xx7f */ + link->io.IOAddrLines = 16; for (i = j = 0; j < 0x400; j += 0x10) { if (multi && (j & 0x80)) continue; link->io.BasePort1 = j ^ 0x300; diff --git a/drivers/net/pcmcia/Config.in b/drivers/net/pcmcia/Config.in index cca2ff57aa0d..5cb25eb8853f 100644 --- a/drivers/net/pcmcia/Config.in +++ b/drivers/net/pcmcia/Config.in @@ -15,11 +15,11 @@ if [ "$CONFIG_NET_PCMCIA" = "y" ]; then dep_tristate ' SMC 91Cxx PCMCIA support' CONFIG_PCMCIA_SMC91C92 $CONFIG_PCMCIA dep_tristate ' Xircom 16-bit PCMCIA support' CONFIG_PCMCIA_XIRC2PS $CONFIG_PCMCIA - # if [ "$CONFIG_CARDBUS" = "y" ]; then - # dep_tristate ' 3Com 3c575 CardBus support' CONFIG_PCMCIA_3C575 $CONFIG_PCMCIA - # dep_tristate ' DEC Tulip CardBus support' CONFIG_PCMCIA_TULIP $CONFIG_PCMCIA - # dep_tristate ' SMC EPIC CardBus support' CONFIG_PCMCIA_EPIC100 $CONFIG_PCMCIA - # fi + if [ "$CONFIG_CARDBUS" = "y" ]; then + dep_tristate ' 3Com 3c575 CardBus support' CONFIG_PCMCIA_3C575 m + dep_tristate ' DEC Tulip CardBus support' CONFIG_PCMCIA_TULIP m + dep_tristate ' SMC EPIC CardBus support' CONFIG_PCMCIA_EPIC100 m + fi dep_tristate ' Aviator/Raytheon 2.4MHz wireless support' CONFIG_PCMCIA_RAYCS $CONFIG_PCMCIA dep_tristate ' Xircom Netwave AirSurfer wireless support' CONFIG_PCMCIA_NETWAVE $CONFIG_PCMCIA diff --git a/drivers/net/pcmcia/Makefile b/drivers/net/pcmcia/Makefile index 779abb20ce47..91c284adaac8 100644 --- a/drivers/net/pcmcia/Makefile +++ b/drivers/net/pcmcia/Makefile @@ -9,110 +9,44 @@ MOD_SUB_DIRS := $(SUB_DIRS) ALL_SUB_DIRS := $(SUB_DIRS) O_TARGET := pcmcia_net.o -O_OBJS := -M_OBJS := -MOD_LIST_NAME := PCMCIA_MODULES - -#CFLAGS_3c575_cb.o = -DCARDBUS -#CFLAGS_tulip_cb.o = -DCARDBUS - -ifeq ($(CONFIG_PCMCIA_3C589),y) - O_OBJS += 3c589_cs.o -else - ifeq ($(CONFIG_PCMCIA_3C589),m) - M_OBJS += 3c589_cs.o - endif -endif - -ifeq ($(CONFIG_PCMCIA_3C574),y) - O_OBJS += 3c574_cs.o -else - ifeq ($(CONFIG_PCMCIA_3C574),m) - M_OBJS += 3c574_cs.o - endif -endif - -ifeq ($(CONFIG_PCMCIA_FMVJ18X),y) - O_OBJS += fmvj18x_cs.o -else - ifeq ($(CONFIG_PCMCIA_FMVJ18X),m) - M_OBJS += fmvj18x_cs.o - endif -endif - -ifeq ($(CONFIG_PCMCIA_NMCLAN),y) - O_OBJS += nmclan_cs.o -else - ifeq ($(CONFIG_PCMCIA_NMCLAN),m) - M_OBJS += nmclan_cs.o - endif -endif - -ifeq ($(CONFIG_PCMCIA_PCNET),y) - O_OBJS += pcnet_cs.o -else - ifeq ($(CONFIG_PCMCIA_PCNET),m) - M_OBJS += pcnet_cs.o - endif -endif - -ifeq ($(CONFIG_PCMCIA_SMC91C92),y) - O_OBJS += smc91c92_cs.o -else - ifeq ($(CONFIG_PCMCIA_SMC91C92),m) - M_OBJS += smc91c92_cs.o - endif -endif - -#ifeq ($(CONFIG_PCMCIA_3C575),y) -# O_OBJS += 3c575_cb.o -#else -# ifeq ($(CONFIG_PCMCIA_3C575),m) -# M_OBJS += 3c575_cb.o -# endif -#endif - -#ifeq ($(CONFIG_PCMCIA_TULIP),y) -# O_OBJS += tulip_cb.o -#else -# ifeq ($(CONFIG_PCMCIA_TULIP),m) -# M_OBJS += tulip_cb.o -# endif -#endif - -#ifeq ($(CONFIG_PCMCIA_EPIC100),y) -# O_OBJS += epic100_cb.o -#else -# ifeq ($(CONFIG_PCMCIA_EPIC100),m) -# M_OBJS += epic100_cb.o -# endif -#endif - -ifeq ($(CONFIG_PCMCIA_RAYCS),y) - OX_OBJS += ray_cs.o -else - ifeq ($(CONFIG_PCMCIA_RAYCS),m) - MX_OBJS += ray_cs.o - endif -endif - -ifeq ($(CONFIG_PCMCIA_NETWAVE),y) - OX_OBJS += netwave_cs.o -else - ifeq ($(CONFIG_PCMCIA_NETWAVE),m) - M_OBJS += netwave_cs.o - endif -endif - -ifeq ($(CONFIG_PCMCIA_WAVELAN),y) - OX_OBJS += wavelan_cs.o -else - ifeq ($(CONFIG_PCMCIA_WAVELAN),m) - M_OBJS += wavelan_cs.o - endif -endif +MOD_LIST_NAME := PCMCIA_NET_MODULES + +obj-y := +obj-m := +obj-n := +obj- := + +# Things that need to export symbols +export-objs := ray_cs.o + +CFLAGS_3c575_cb.o = -DCARDBUS -DMODULE +CFLAGS_tulip_cb.o = -DCARDBUS -DMODULE + +# 16-bit client drivers +obj-$(CONFIG_PCMCIA_3C589) += 3c589_cs.o +obj-$(CONFIG_PCMCIA_3C574) += 3c574_cs.o +obj-$(CONFIG_PCMCIA_FMVJ18X) += fmvj18x_cs.o +obj-$(CONFIG_PCMCIA_NMCLAN) += nmclan_cs.o +obj-$(CONFIG_PCMCIA_PCNET) += pcnet_cs.o +obj-$(CONFIG_PCMCIA_SMC91C92) += smc91c92_cs.o +obj-$(CONFIG_PCMCIA_XIRC2PS) += xirc2ps_cs.o + +# 16-bit wireless client drivers +obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o +obj-$(CONFIG_PCMCIA_NETWAVE) += netwave_cs.o +obj-$(CONFIG_PCMCIA_WAVELAN) += wavelan_cs.o + +# Cardbus client drivers +obj-$(CONFIG_PCMCIA_3C575) += 3c575_cb.o +obj-$(CONFIG_PCMCIA_TULIP) += tulip_cb.o +obj-$(CONFIG_PCMCIA_EPIC100) += epic100_cb.o + +O_OBJS := $(filter-out $(export-objs), $(obj-y)) +OX_OBJS := $(filter $(export-objs), $(obj-y)) +M_OBJS := $(filter-out $(export-objs), $(obj-m)) +MX_OBJS := $(filter $(export-objs), $(obj-m)) include $(TOPDIR)/Rules.make -#epic100_cb.o: ../epic100.c -# $(CC) $(CFLAGS) -DCARDBUS -c -o $@ ../epic100.c +epic100_cb.o: ../epic100.c + $(CC) $(CFLAGS) -DMODULE -DCARDBUS -c -o $@ ../epic100.c diff --git a/drivers/net/pcmcia/netwave_cs.c b/drivers/net/pcmcia/netwave_cs.c index 0e9a1045f84e..25b29847bd69 100644 --- a/drivers/net/pcmcia/netwave_cs.c +++ b/drivers/net/pcmcia/netwave_cs.c @@ -6,7 +6,7 @@ * Status: Experimental. * Authors: John Markus Bjørndalen * Dag Brattli - * David Hinds + * David Hinds * Created at: A long time ago! * Modified at: Mon Nov 10 11:54:37 1997 * Modified by: Dag Brattli diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 45aab6d625d7..2dd6a369b437 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -28,7 +28,7 @@ References Dean Siasoyco, New Media Corporation Ken Lesniak, Silicon Graphics, Inc. Donald Becker - David Hinds + David Hinds The Linux client driver is based on the 3c589_cs.c client driver by David Hinds. diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 26fa47ee96bc..cefdf91be461 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -9,9 +9,9 @@ Conrad ethernet card, and the Kingston KNE-PCM/x in shared-memory mode. It will also handle the Socket EA card in either mode. - Copyright (C) 1999 David A. Hinds -- dhinds@hyper.stanford.edu + Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org - pcnet_cs.c 1.101 1999/10/21 00:56:19 + pcnet_cs.c 1.106 1999/11/09 21:53:13 The network driver code is based on Donald Becker's NE2000 code: @@ -72,7 +72,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = -"pcnet_cs.c 1.101 1999/10/21 00:56:19 (David Hinds)"; +"pcnet_cs.c 1.106 1999/11/09 21:53:13 (David Hinds)"; #else #define DEBUG(n, args...) #endif @@ -187,6 +187,8 @@ static hw_info_t hw_info[] = { HAS_MISC_REG | HAS_IBM_MISC }, { /* Kansai KLA-PCM/T */ 0x0ff0, 0x00, 0x60, 0x87, HAS_MISC_REG | HAS_IBM_MISC }, + { /* NSC DP83903 */ 0x0374, 0x08, 0x00, 0x17, + HAS_MISC_REG | HAS_IBM_MISC }, { /* NSC DP83903 */ 0x0374, 0x00, 0xc0, 0xa8, HAS_MISC_REG | HAS_IBM_MISC }, { /* NSC DP83903 */ 0x0374, 0x00, 0xa0, 0xb0, @@ -229,7 +231,7 @@ typedef struct pcnet_dev_t { u_long flags; caddr_t base; struct timer_list watchdog; - int stale; + int stale, link; u_short fast_poll; } pcnet_dev_t; @@ -578,6 +580,7 @@ static int try_io_port(dev_link_t *link) link->io.Attributes2 = IO_DATA_PATH_WIDTH_16; } if (link->io.BasePort1 == 0) { + link->io.IOAddrLines = 16; for (j = 0; j < 0x400; j += 0x20) { link->io.BasePort1 = j ^ 0x300; link->io.BasePort2 = (j ^ 0x300) + 0x10; @@ -656,6 +659,7 @@ static void pcnet_config(dev_link_t *link) (cfg->mem.win[0].len >= 0x4000)); link->io.BasePort1 = io->win[i].base; link->io.NumPorts1 = io->win[i].len; + link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; if (link->io.NumPorts1 + link->io.NumPorts2 >= 32) { last_ret = try_io_port(link); if (last_ret == CS_SUCCESS) break; @@ -681,10 +685,14 @@ static void pcnet_config(dev_link_t *link) CS_CHECK(RequestConfiguration, handle, &link->conf); dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; - if ((if_port == 1) || (if_port == 2)) - dev->if_port = if_port; - else - printk(KERN_NOTICE "pcnet_cs: invalid if_port requested\n"); + if (info->flags & HAS_MISC_REG) { + if ((if_port == 1) || (if_port == 2)) + dev->if_port = if_port; + else + printk(KERN_NOTICE "pcnet_cs: invalid if_port requested\n"); + } else { + dev->if_port = 0; + } dev->tbusy = 0; if (register_netdev(dev) != 0) { printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n"); @@ -885,19 +893,11 @@ static int pcnet_open(struct net_device *dev) link->open++; MOD_INC_USE_COUNT; - /* For D-Link EtherFast, wait for something(?) to happen */ - if (info->flags & IS_DL10019A) { - int i; - for (i = 0; i < 20; i++) { - if ((inb(dev->base_addr+0x1c) & 0x01) == 0) break; - __set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); - } - } - set_misc_reg(dev); request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, dev_info, dev); + /* Start by assuming the link is bad */ + info->link = 1; info->watchdog.function = &ei_watchdog; info->watchdog.data = (u_long)info; info->watchdog.expires = jiffies + HZ; @@ -969,17 +969,14 @@ static int set_config(struct net_device *dev, struct ifmap *map) { pcnet_dev_t *info = (pcnet_dev_t *)dev; if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) { - if ((map->port != 0) && !(info->flags & HAS_MISC_REG)) { - printk(KERN_NOTICE "%s: transceiver selection not " - "implemented\n", dev->name); - return -EINVAL; - } - if ((map->port == 1) || (map->port == 2)) { - dev->if_port = map->port; - printk(KERN_INFO "%s: switched to %s port\n", - dev->name, if_names[dev->if_port]); - } else + if (!(info->flags & HAS_MISC_REG)) + return -EOPNOTSUPP; + else if ((map->port < 1) || (map->port > 2)) return -EINVAL; + dev->if_port = map->port; + printk(KERN_INFO "%s: switched to %s port\n", + dev->name, if_names[dev->if_port]); + NS8390_init(dev, 1); } return 0; } @@ -1017,6 +1014,17 @@ static void ei_watchdog(u_long arg) return; } + if (info->flags & IS_DL10019A) { + int state = inb(dev->base_addr+0x1c) & 0x01; + if (state != info->link) { + printk(KERN_INFO "%s: %s link beat\n", dev->name, + (state) ? "lost" : "found"); + if (!state) + NS8390_init(dev, 1); + info->link = state; + } + } + reschedule: info->watchdog.expires = jiffies + HZ; add_timer(&info->watchdog); diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 3abdf7d9d009..5c7c5e4df6cd 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -6,13 +6,13 @@ Megahertz, Motorola, Ositech, and Psion Dacom ethernet/modem multifunction cards. - Copyright (C) 1999 David A. Hinds -- dhinds@hyper.stanford.edu + Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org - smc91c92_cs.c 1.79 1999/10/19 00:38:29 + smc91c92_cs.c 1.82 1999/11/08 20:46:17 This driver contains code written by Donald Becker (becker@cesdis.gsfc.nasa.gov), Rowan Hughes (x-csrdh@jcu.edu.au), - David Hinds (dhinds@hyper.stanford.edu), and Erik Stahlman + David Hinds (dhinds@pcmcia.sourceforge.org), and Erik Stahlman (erik@vt.edu). Donald wrote the SMC 91c92 code using parts of Erik's SMC 91c94 driver. Rowan wrote a similar driver, and I've incorporated some parts of his driver here. I (Dave) wrote most @@ -717,6 +717,7 @@ static int smc_config(dev_link_t *link) if (i == CS_SUCCESS) { link->conf.ConfigIndex = cf->index; link->io.BasePort1 = cf->io.win[0].base; + link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; i = CardServices(RequestIO, link->handle, &link->io); if (i == CS_SUCCESS) break; } @@ -784,6 +785,7 @@ static int osi_config(dev_link_t *link) link->io.NumPorts1 = 64; link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; link->io.NumPorts2 = 8; + link->io.IOAddrLines = 16; /* Enable Hard Decode, LAN, Modem */ link->conf.ConfigIndex = 0x23; @@ -1799,15 +1801,17 @@ static void set_rx_mode(struct net_device *dev) static int s9k_config(struct net_device *dev, struct ifmap *map) { + struct smc_private *lp = dev->priv; if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) { - if (map->port <= 2) { - dev->if_port = map->port; - printk(KERN_INFO "%s: switched to %s port\n", - dev->name, if_names[dev->if_port]); - } else + if (lp->cfg & CFG_MII_SELECT) + return -EOPNOTSUPP; + else if (map->port > 2) return -EINVAL; + dev->if_port = map->port; + printk(KERN_INFO "%s: switched to %s port\n", + dev->name, if_names[dev->if_port]); + smc_reset(dev); } - smc_reset(dev); return 0; } diff --git a/drivers/net/pcmcia/tulip_cb.c b/drivers/net/pcmcia/tulip_cb.c new file mode 100644 index 000000000000..a48c661451df --- /dev/null +++ b/drivers/net/pcmcia/tulip_cb.c @@ -0,0 +1,3383 @@ +/* tulip.c: A DEC 21040-family ethernet driver for Linux. */ +/* + Written/copyright 1994-1999 by Donald Becker. + + This software may be used and distributed according to the terms + of the GNU Public License, incorporated herein by reference. + + This driver is for the Digital "Tulip" Ethernet adapter interface. + It should work with most DEC 21*4*-based chips/ethercards, as well as + with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and ASIX. + + 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 + + Support and updates available at + http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html +*/ + +#define SMP_CHECK +static const char version[] = "tulip.c:v0.91 4/14/99 becker@cesdis.gsfc.nasa.gov (modified by danilo@cs.uni-magdeburg.de for XIRCOM CBE, fixed by Doug Ledford)\n"; + +/* A few user-configurable values. */ + +/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ +static int max_interrupt_work = 25; + +#define MAX_UNITS 8 +/* Used to pass the full-duplex flag, etc. */ +static int full_duplex[MAX_UNITS] = {0, }; +static int options[MAX_UNITS] = {0, }; +static int mtu[MAX_UNITS] = {0, }; /* Jumbo MTU for interfaces. */ + +/* The possible media types that can be set in options[] are: */ +static const char * const medianame[] = { + "10baseT", "10base2", "AUI", "100baseTx", + "10baseT-FD", "100baseTx-FD", "100baseT4", "100baseFx", + "100baseFx-FD", "MII 10baseT", "MII 10baseT-FD", "MII", + "10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FD", "MII 100baseT4", +}; + +/* Set if the PCI BIOS detects the chips on a multiport board backwards. */ +#ifdef REVERSE_PROBE_ORDER +static int reverse_probe = 1; +#else +static int reverse_probe = 0; +#endif + +/* Keep the ring sizes a power of two for efficiency. + Making the Tx ring too large decreases the effectiveness of channel + bonding and packet priority. + There are no ill effects from too-large receive rings. */ +#define TX_RING_SIZE 16 +#define RX_RING_SIZE 32 + +/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */ +#ifdef __alpha__ +static int rx_copybreak = 1518; +#else +static int rx_copybreak = 100; +#endif + +/* + Set the bus performance register. + Typical: Set 16 longword cache alignment, no burst limit. + Cache alignment bits 15:14 Burst length 13:8 + 0000 No alignment 0x00000000 unlimited 0800 8 longwords + 4000 8 longwords 0100 1 longword 1000 16 longwords + 8000 16 longwords 0200 2 longwords 2000 32 longwords + C000 32 longwords 0400 4 longwords + Warning: many older 486 systems are broken and require setting 0x00A04800 + 8 longword cache alignment, 8 longword burst. + ToDo: Non-Intel setting could be better. +*/ + +#if defined(__alpha__) +static int csr0 = 0x01A00000 | 0xE000; +#elif defined(__powerpc__) +static int csr0 = 0x01B00000 | 0x8000; +#elif defined(__sparc__) +static int csr0 = 0x01B00080 | 0x8000; +#elif defined(__i386__) +static int csr0 = 0x01A00000 | 0x8000; +#else +#warning Processor architecture undefined! +static int csr0 = 0x00A00000 | 0x4800; +#endif + +/* Operational parameters that usually are not changed. */ +/* Time in jiffies before concluding the transmitter is hung. */ +#define TX_TIMEOUT (4*HZ) +#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ +/* This is a mysterious value that can be written to CSR11 in the 21040 (only) + to support a pre-NWay full-duplex signaling mechanism using short frames. + No one knows what it should be, but if left at its default value some + 10base2(!) packets trigger a full-duplex-request interrupt. */ +#define FULL_DUPLEX_MAGIC 0x6969 + +#if !defined(__OPTIMIZE__) || !defined(__KERNEL__) +#warning You must compile this file with the correct options! +#warning See the last lines of the source file. +#error You must compile this driver with "-O". +#endif + +#include +#include +#ifdef MODULE +#ifdef MODVERSIONS +#include +#endif +#include +#else +#define MOD_INC_USE_COUNT +#define MOD_DEC_USE_COUNT +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* Processor type for cache alignment. */ +#include +#include +#include + +/* Kernel compatibility defines, some common to David Hinds' PCMCIA package. + This is only in the support-all-kernels source code. */ + +#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115 +MODULE_AUTHOR("Donald Becker "); +MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver"); +MODULE_PARM(debug, "i"); +MODULE_PARM(max_interrupt_work, "i"); +MODULE_PARM(reverse_probe, "i"); +MODULE_PARM(rx_copybreak, "i"); +MODULE_PARM(csr0, "i"); +MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); +#endif + +#define RUN_AT(x) (jiffies + (x)) + +#define NETSTATS_VER2 +#define PCI_SUPPORT_VER3 +#define dev_free_skb(skb) dev_kfree_skb(skb); + +#define tulip_debug debug +#ifdef TULIP_DEBUG +static int tulip_debug = TULIP_DEBUG; +#else +static int tulip_debug = 1; +#endif + +/* + Theory of Operation + +I. Board Compatibility + +This device driver is designed for the DECchip "Tulip", Digital's +single-chip ethernet controllers for PCI. Supported members of the family +are the 21040, 21041, 21140, 21140A, 21142, and 21143. Similar work-alike +chips from Lite-On, Macronics, ASIX, Compex and other listed below are also +supported. + +These chips are used on at least 140 unique PCI board designs. The great +number of chips and board designs supported is the reason for the +driver size and complexity. Almost of the increasing complexity is in the +board configuration and media selection code. There is very little +increasing in the operational critical path length. + +II. Board-specific settings + +PCI bus devices are configured by the system at boot time, so no jumpers +need to be set on the board. The system BIOS preferably should assign the +PCI INTA signal to an otherwise unused system IRQ line. + +Some boards have EEPROMs tables with default media entry. The factory default +is usually "autoselect". This should only be overridden when using +transceiver connections without link beat e.g. 10base2 or AUI, or (rarely!) +for forcing full-duplex when used with old link partners that do not do +autonegotiation. + +III. Driver operation + +IIIa. Ring buffers + +The Tulip can use either ring buffers or lists of Tx and Rx descriptors. +This driver uses statically allocated rings of Rx and Tx descriptors, set at +compile time by RX/TX_RING_SIZE. This version of the driver allocates skbuffs +for the Rx ring buffers at open() time and passes the skb->data field to the +Tulip as receive data buffers. When an incoming frame is less than +RX_COPYBREAK bytes long, a fresh skbuff is allocated and the frame is +copied to the new skbuff. When the incoming frame is larger, the skbuff is +passed directly up the protocol stack and replaced by a newly allocated +skbuff. + +The RX_COPYBREAK value is chosen to trade-off the memory wasted by +using a full-sized skbuff for small frames vs. the copying costs of larger +frames. For small frames the copying cost is negligible (esp. considering +that we are pre-loading the cache with immediately useful header +information). For large frames the copying cost is non-trivial, and the +larger copy might flush the cache of useful data. A subtle aspect of this +choice is that the Tulip only receives into longword aligned buffers, thus +the IP header at offset 14 isn't longword aligned for further processing. +Copied frames are put into the new skbuff at an offset of "+2", thus copying +has the beneficial effect of aligning the IP header and preloading the +cache. + +IIIC. Synchronization +The driver runs as two independent, single-threaded flows of control. One +is the send-packet routine, which enforces single-threaded use by the +dev->tbusy flag. The other thread is the interrupt handler, which is single +threaded by the hardware and other software. + +The send packet thread has partial control over the Tx ring and 'dev->tbusy' +flag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next +queue slot is empty, it clears the tbusy flag when finished otherwise it sets +the 'tp->tx_full' flag. + +The interrupt handler has exclusive control over the Rx ring and records stats +from the Tx ring. (The Tx-done interrupt can't be selectively turned off, so +we can't avoid the interrupt overhead by having the Tx routine reap the Tx +stats.) After reaping the stats, it marks the queue entry as empty by setting +the 'base' to zero. Iff the 'tp->tx_full' flag is set, it clears both the +tx_full and tbusy flags. + +IV. Notes + +Thanks to Duke Kamstra of SMC for long ago providing an EtherPower board. +Greg LaPolla at Linksys provided PNIC and other Linksys boards. +Znyx provided a four-port card for testing. + +IVb. References + +http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html +http://www.digital.com (search for current 21*4* datasheets and "21X4 SROM") +http://www.national.com/pf/DP/DP83840A.html +http://www.asix.com.tw/pmac.htm +http://www.admtek.com.tw/ + +IVc. Errata + +The old DEC databooks were light on details. +The 21040 databook claims that CSR13, CSR14, and CSR15 should each be the last +register of the set CSR12-15 written. Hmmm, now how is that possible? + +The DEC SROM format is very badly designed not precisely defined, leading to +part of the media selection junkheap below. Some boards do not have EEPROM +media tables and need to be patched up. Worse, other boards use the DEC +design kit media table when it isn't correct for their board. + +We cannot use MII interrupts because there is no defined GPIO pin to attach +them. The MII transceiver status is polled using an kernel timer. + +*/ + +static struct net_device * +tulip_probe1(int pci_bus, int pci_devfn, struct net_device *dev, long ioaddr, + int irq, int chip_idx, int board_idx); + +/* This table drives the PCI probe routines. It's mostly boilerplate in all + of the drivers, and will likely be provided by some future kernel. + Note the matching code -- the first table entry matchs all 56** cards but + second only the 1234 card. +*/ +enum pci_flags_bit { + PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, + PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, +}; +#define PCI_ADDR0_IO (PCI_USES_IO|PCI_ADDR0) + +struct pci_id_info { + const char *name; + u16 vendor_id, device_id, device_id_mask, flags; + int io_size, min_latency; + struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev, + long ioaddr, int irq, int chip_idx, int fnd_cnt); +}; +#ifndef CARDBUS +static struct pci_id_info pci_tbl[] = { + { "Digital DC21040 Tulip", + 0x1011, 0x0002, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 }, + { "Digital DC21041 Tulip", + 0x1011, 0x0014, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 }, + { "Digital DS21140 Tulip", + 0x1011, 0x0009, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 }, + { "Digital DS21143 Tulip", + 0x1011, 0x0019, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 }, + { "Lite-On 82c168 PNIC", + 0x11AD, 0x0002, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 }, + { "Macronix 98713 PMAC", + 0x10d9, 0x0512, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 }, + { "Macronix 98715 PMAC", + 0x10d9, 0x0531, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 }, + { "Macronix 98725 PMAC", + 0x10d9, 0x0531, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 }, + { "ASIX AX88140", + 0x125B, 0x1400, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 }, + { "Lite-On LC82C115 PNIC-II", + 0x11AD, 0xc115, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 }, + { "ADMtek AN981 Comet", + 0x1317, 0x0981, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 }, + { "Compex RL100-TX", + 0x11F6, 0x9881, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 }, + {0}, +}; +#endif /* !CARD_BUS */ + +/* This table use during operation for capabilities and media timer. */ + +static void tulip_timer(unsigned long data); +static void t21142_timer(unsigned long data); +static void mxic_timer(unsigned long data); +static void pnic_timer(unsigned long data); +static void comet_timer(unsigned long data); + +enum tbl_flag { + HAS_MII=1, HAS_MEDIA_TABLE=2, CSR12_IN_SROM=4, ALWAYS_CHECK_MII=8, + HAS_ACPI=0x10, MC_HASH_ONLY=0x20, /* Hash-only multicast filter. */ + HAS_NWAY143=0x40, /* Uses 21143-like internal NWay. */ +}; +static struct tulip_chip_table { + char *chip_name; + int io_size; + int valid_intrs; /* CSR7 interrupt enable settings */ + int flags; + void (*media_timer)(unsigned long data); +} tulip_tbl[] = { + { "Digital DC21040 Tulip", 128, 0x0001ebef, 0, tulip_timer }, + { "Digital DC21041 Tulip", 128, 0x0001ebef, HAS_MEDIA_TABLE, tulip_timer }, + { "Digital DS21140 Tulip", 128, 0x0001ebef, + HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, tulip_timer }, + { "Digital DS21143 Tulip", 128, 0x0801fbff, + HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | HAS_NWAY143, t21142_timer }, + { "Lite-On 82c168 PNIC", 256, 0x0001ebef, + HAS_MII, pnic_timer }, + { "Macronix 98713 PMAC", 128, 0x0001ebef, + HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer }, + { "Macronix 98715 PMAC", 256, 0x0001ebef, + HAS_MEDIA_TABLE, mxic_timer }, + { "Macronix 98725 PMAC", 256, 0x0001ebef, + HAS_MEDIA_TABLE, mxic_timer }, + { "ASIX AX88140", 128, 0x0001fbff, + HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY, tulip_timer }, + { "Lite-On PNIC-II", 256, 0x0001ebef, + HAS_MII | HAS_NWAY143, pnic_timer }, + { "ADMtek Comet", 256, 0x0001abef, + MC_HASH_ONLY, comet_timer }, + { "Compex 9881 PMAC", 128, 0x0001ebef, + HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer }, + { "Xircom Cardbus Adapter (DEC 21143 compatible mode)", 128, 0x0801fbff, + HAS_MII | HAS_ACPI, tulip_timer }, + {0}, +}; +/* This matches the table above. Note 21142 == 21143. */ +enum chips { + DC21040=0, DC21041=1, DC21140=2, DC21142=3, DC21143=3, + LC82C168, MX98713, MX98715, MX98725, AX88140, PNIC2, COMET, COMPEX9881, + X3201_3, +}; + +/* A full-duplex map for media types. */ +enum MediaIs { + MediaIsFD = 1, MediaAlwaysFD=2, MediaIsMII=4, MediaIsFx=8, + MediaIs100=16}; +static const char media_cap[] = +{0,0,0,16, 3,19,16,24, 27,4,7,5, 0,20,23,20 }; +static u8 t21040_csr13[] = {2,0x0C,8,4, 4,0,0,0, 0,0,0,0, 4,0,0,0}; +/* 21041 transceiver register settings: 10-T, 10-2, AUI, 10-T, 10T-FD*/ +static u16 t21041_csr13[] = { 0xEF05, 0xEF09, 0xEF09, 0xEF01, 0xEF09, }; +static u16 t21041_csr14[] = { 0x7F3F, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, }; +static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; + +static u16 t21142_csr13[] = { 0x0001, 0x0009, 0x0009, 0x0000, 0x0001, }; +static u16 t21142_csr14[] = { 0xFFFF, 0x0705, 0x0705, 0x0000, 0x7F3D, }; +static u16 t21142_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; + +/* Offsets to the Command and Status Registers, "CSRs". All accesses + must be longword instructions and quadword aligned. */ +enum tulip_offsets { + CSR0=0, CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28, + CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58, + CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78 }; + +/* The bits in the CSR5 status registers, mostly interrupt sources. */ +enum status_bits { + TimerInt=0x800, TPLnkFail=0x1000, TPLnkPass=0x10, + NormalIntr=0x10000, AbnormalIntr=0x8000, + RxJabber=0x200, RxDied=0x100, RxNoBuf=0x80, RxIntr=0x40, + TxFIFOUnderflow=0x20, TxJabber=0x08, TxNoBuf=0x04, TxDied=0x02, TxIntr=0x01, +}; + +/* The Tulip Rx and Tx buffer descriptors. */ +struct tulip_rx_desc { + s32 status; + s32 length; + u32 buffer1, buffer2; +}; + +struct tulip_tx_desc { + s32 status; + s32 length; + u32 buffer1, buffer2; /* We use only buffer 1. */ +}; + +enum desc_status_bits { + DescOwned=0x80000000, RxDescFatalErr=0x8000, RxWholePkt=0x0300, +}; + +/* Ring-wrap flag in length field, use for last ring entry. + 0x01000000 means chain on buffer2 address, + 0x02000000 means use the ring start address in CSR2/3. + Note: Some work-alike chips do not function correctly in chained mode. + The ASIX chip works only in chained mode. + Thus we indicates ring mode, but always write the 'next' field for + chained mode as well. +*/ +#define DESC_RING_WRAP 0x02000000 + +#ifdef CARDBUS +#define EEPROM_ADDRLEN (chip_rev == 65 ? 8 : 6) +#else +#define EEPROM_ADDRLEN 6 +#endif +#define EEPROM_SIZE 128 /* 2 << EEPROM_ADDRLEN */ + +struct medialeaf { + u8 type; + u8 media; + unsigned char *leafdata; +}; + +struct mediatable { + u16 defaultmedia; + u8 leafcount, csr12dir; /* General purpose pin directions. */ + unsigned has_mii:1, has_nonmii:1, has_reset:6; + u32 csr15dir, csr15val; /* 21143 NWay setting. */ + struct medialeaf mleaf[0]; +}; + +struct mediainfo { + struct mediainfo *next; + int info_type; + int index; + unsigned char *info; +}; + +struct tulip_private { + char devname[8]; /* Used only for kernel debugging. */ + const char *product_name; + struct net_device *next_module; + struct tulip_rx_desc rx_ring[RX_RING_SIZE]; + struct tulip_tx_desc tx_ring[TX_RING_SIZE]; + /* The saved address of a sent-in-place packet/buffer, for skfree(). */ + struct sk_buff* tx_skbuff[TX_RING_SIZE]; +#ifdef CARDBUS + /* The X3201-3 requires double word aligned tx bufs */ + struct sk_buff* tx_aligned_skbuff[TX_RING_SIZE]; +#endif + /* The addresses of receive-in-place skbuffs. */ + struct sk_buff* rx_skbuff[RX_RING_SIZE]; + char *rx_buffs; /* Address of temporary Rx buffers. */ + u8 setup_buf[96*sizeof(u16) + 7]; + u16 *setup_frame; /* Pseudo-Tx frame to init address table. */ + int chip_id; + int revision; + struct net_device_stats stats; + struct timer_list timer; /* Media selection timer. */ + int interrupt; /* In-interrupt flag. */ + unsigned int cur_rx, cur_tx; /* The next free ring entry */ + unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ + unsigned int tx_full:1; /* The Tx queue is full. */ + unsigned int full_duplex:1; /* Full-duplex operation requested. */ + unsigned int full_duplex_lock:1; + unsigned int fake_addr:1; /* Multiport board faked address. */ + unsigned int default_port:4; /* Last dev->if_port value. */ + unsigned int media2:4; /* Secondary monitored media port. */ + unsigned int medialock:1; /* Don't sense media type. */ + unsigned int mediasense:1; /* Media sensing in progress. */ + unsigned int nway:1, nwayset:1; /* 21143 internal NWay. */ + unsigned int open:1; + unsigned int csr0; /* CSR0 setting. */ + unsigned int csr6; /* Current CSR6 control settings. */ + unsigned char eeprom[EEPROM_SIZE]; /* Serial EEPROM contents. */ + u16 to_advertise; /* NWay capabilities advertised. */ + u16 lpar; /* 21143 Link partner ability. */ + u16 advertising[4]; + signed char phys[4], mii_cnt; /* MII device addresses. */ + struct mediatable *mtable; + int cur_index; /* Current media index. */ + int saved_if_port; + unsigned char pci_bus, pci_devfn; + int pad0, pad1; /* Used for 8-byte alignment */ +}; + +static void parse_eeprom(struct net_device *dev); +static int read_eeprom(long ioaddr, int location, int addr_len); +static int mdio_read(struct net_device *dev, int phy_id, int location); +static void mdio_write(struct net_device *dev, int phy_id, int location, int value); +static void select_media(struct net_device *dev, int startup); +static void tulip_up(struct net_device *dev); +static void tulip_down(struct net_device *dev); +static int tulip_open(struct net_device *dev); +static void tulip_timer(unsigned long data); +static void t21142_start_nway(struct net_device *dev); +static void tulip_tx_timeout(struct net_device *dev); +static void tulip_init_ring(struct net_device *dev); +static int tulip_start_xmit(struct sk_buff *skb, struct net_device *dev); +static int tulip_rx(struct net_device *dev); +static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +static int tulip_close(struct net_device *dev); +static struct net_device_stats *tulip_get_stats(struct net_device *dev); +#ifdef HAVE_PRIVATE_IOCTL +static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +#endif +static void set_rx_mode(struct net_device *dev); + +/* The Xircom cards are picky about when certain bits in CSR6 can be + manipulated. Keith Owens . */ + +static void outl_CSR6 (u32 newcsr6, long ioaddr, int chip_idx) +{ + const int strict_bits = 0x0060e202; + int csr5, csr5_22_20, csr5_19_17, currcsr6, attempts = 200; + long flags; + save_flags(flags); + cli(); + if (chip_idx != X3201_3) { + outl(newcsr6, ioaddr + CSR6); + restore_flags(flags); + return; + } + newcsr6 &= 0x726cfeca; /* mask out the reserved CSR6 bits that always */ + /* read 0 on the Xircom cards */ + newcsr6 |= 0x320c0000; /* or in the reserved bits that always read 1 */ + currcsr6 = inl(ioaddr + CSR6); + if (((newcsr6 & strict_bits) == (currcsr6 & strict_bits)) || + ((currcsr6 & ~0x2002) == 0)) { + outl(newcsr6, ioaddr + CSR6); /* safe */ + restore_flags(flags); + return; + } + /* make sure the transmitter and receiver are stopped first */ + currcsr6 &= ~0x2002; + while (1) { + csr5 = inl(ioaddr + CSR5); + if (csr5 == 0xffffffff) + break; /* cannot read csr5, card removed? */ + csr5_22_20 = csr5 & 0x700000; + csr5_19_17 = csr5 & 0x0e0000; + if ((csr5_22_20 == 0 || csr5_22_20 == 0x600000) && + (csr5_19_17 == 0 || csr5_19_17 == 0x80000 || csr5_19_17 == 0xc0000)) + break; /* both are stopped or suspended */ + if (!--attempts) { + printk(KERN_INFO "tulip.c: outl_CSR6 too many attempts," + "csr5=0x%08x\n", csr5); + outl(newcsr6, ioaddr + CSR6); /* unsafe but do it anyway */ + restore_flags(flags); + return; + } + outl(currcsr6, ioaddr + CSR6); + udelay(1); + } + /* now it is safe to change csr6 */ + outl(newcsr6, ioaddr + CSR6); + restore_flags(flags); +} + +/* A list of all installed Tulip devices. */ +static struct net_device *root_tulip_dev = NULL; + +#ifndef CARDBUS +int tulip_probe(struct net_device *dev) +{ + int cards_found = 0; + int pci_index = 0; + unsigned char pci_bus, pci_device_fn; + + if ( ! pcibios_present()) + return -ENODEV; + + for (;pci_index < 0xff; pci_index++) { + u16 vendor, device, pci_command, new_command; + int chip_idx; + int irq; + long ioaddr; + + if (pcibios_find_class + (PCI_CLASS_NETWORK_ETHERNET << 8, + reverse_probe ? 0xfe - pci_index : pci_index, + &pci_bus, &pci_device_fn) != PCIBIOS_SUCCESSFUL) { + if (reverse_probe) + continue; + 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); + + 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) + continue; + + { +#if defined(PCI_SUPPORT_VER2) + struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); + ioaddr = pdev->base_address[0] & ~3; + irq = pdev->irq; +#elif defined(PCI_SUPPORT_VER3) + struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); + ioaddr = pdev->resource[0].start; + irq = pdev->irq; +#else + u32 pci_ioaddr; + u8 pci_irq_line; + 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); + ioaddr = pci_ioaddr & ~3; + irq = pci_irq_line; +#endif + } + + if (debug > 2) + printk(KERN_INFO "Found %s at PCI I/O address %#lx.\n", + pci_tbl[chip_idx].name, ioaddr); + + pcibios_read_config_word(pci_bus, pci_device_fn, + PCI_COMMAND, &pci_command); + new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO; + if (pci_command != new_command) { + printk(KERN_INFO " The PCI BIOS has not enabled 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); + } + + dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, ioaddr, + irq, chip_idx, cards_found); + + /* Get and check the bus-master and latency values. */ + if (dev) { + u8 pci_latency; + pcibios_read_config_byte(pci_bus, pci_device_fn, + 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); + } + } + dev = 0; + cards_found++; + } + + return cards_found ? 0 : -ENODEV; +} +#endif /* not CARDBUS */ + +static struct net_device *tulip_probe1(int pci_bus, int pci_devfn, + struct net_device *dev, long ioaddr, int irq, + int chip_idx, int board_idx) +{ + static int did_version = 0; /* Already printed version info. */ + struct tulip_private *tp; + /* See note below on the multiport cards. */ + static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'}; + static int last_irq = 0; + static int multiport_cnt = 0; /* For four-port boards w/one EEPROM */ + u8 chip_rev; + int i; + unsigned short sum; + + if (tulip_debug > 0 && did_version++ == 0) + printk(KERN_INFO "%s", version); + + dev = init_etherdev(dev, 0); + + pcibios_read_config_byte(pci_bus, pci_devfn, PCI_REVISION_ID, &chip_rev); + /* Bring the 21143 out of sleep mode. + Caution: Snooze mode does not work with some boards! */ + if (tulip_tbl[chip_idx].flags & HAS_ACPI) + pcibios_write_config_dword(pci_bus, pci_devfn, 0x40, 0x00000000); + + printk(KERN_INFO "%s: %s rev %d at %#3lx,", + dev->name, tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr); + + /* Stop the chip's Tx and Rx processes. */ + outl_CSR6(inl(ioaddr + CSR6) & ~0x2002, ioaddr, chip_idx); + /* Clear the missed-packet counter. */ + (volatile int)inl(ioaddr + CSR8); + + if (chip_idx == DC21041) { + if (inl(ioaddr + CSR9) & 0x8000) { + printk(" 21040 compatible mode,"); + chip_idx = DC21040; + } else { + printk(" 21041 mode,"); + } + } + + /* The station address ROM is read byte serially. The register must + be polled, waiting for the value to be read bit serially from the + EEPROM. + */ + sum = 0; + if (chip_idx == DC21040) { + outl(0, ioaddr + CSR9); /* Reset the pointer with a dummy write. */ + for (i = 0; i < 6; i++) { + int value, boguscnt = 100000; + do + value = inl(ioaddr + CSR9); + while (value < 0 && --boguscnt > 0); + dev->dev_addr[i] = value; + sum += value & 0xff; + } + } else if (chip_idx == LC82C168) { + for (i = 0; i < 3; i++) { + int value, boguscnt = 100000; + outl(0x600 | i, ioaddr + 0x98); + do + value = inl(ioaddr + CSR9); + while (value < 0 && --boguscnt > 0); + put_unaligned(le16_to_cpu(value), ((u16*)dev->dev_addr) + i); + sum += value & 0xffff; + } + } else if (chip_idx == COMET) { + /* No need to read the EEPROM. */ + put_unaligned(inl(ioaddr + 0xA4), (u32 *)dev->dev_addr); + put_unaligned(inl(ioaddr + 0xA8), (u16 *)(dev->dev_addr + 4)); + for (i = 0; i < 6; i ++) + sum += dev->dev_addr[i]; + } else if (chip_idx == X3201_3) { + /* Xircom has its address stored in the CIS + * we access it through the boot rom interface for now + * this might not work, as the CIS is not parsed but I + * (danilo) use the offset I found on my card's CIS !!! + * + * Doug Ledford: I changed this routine around so that it + * walks the CIS memory space, parsing the config items, and + * finds the proper lan_node_id tuple and uses the data + * stored there. + */ + unsigned char j, tuple, link, data_id, data_count; + outl(1<<12, ioaddr + CSR9); /* enable boot rom access */ + for (i = 0x100; i < 0x1f7; i += link+2) { + outl(i, ioaddr + CSR10); + tuple = inl(ioaddr + CSR9) & 0xff; + outl(i + 1, ioaddr + CSR10); + link = inl(ioaddr + CSR9) & 0xff; + outl(i + 2, ioaddr + CSR10); + data_id = inl(ioaddr + CSR9) & 0xff; + outl(i + 3, ioaddr + CSR10); + data_count = inl(ioaddr + CSR9) & 0xff; + if ( (tuple == 0x22) && + (data_id == 0x04) && (data_count == 0x06) ) { + /* + * This is it. We have the data we want. + */ + for (j = 0; j < 6; j++) { + outl(i + j + 4, ioaddr + CSR10); + dev->dev_addr[j] = inl(ioaddr + CSR9) & 0xff; + } + break; + } else if (link == 0) { + break; + } + } + sum = 1; // to make check below fail! + } else { /* Must be a new chip, with a serial EEPROM interface. */ + /* We read the whole EEPROM, and sort it out later. DEC has a + specification _Digital Semiconductor 21X4 Serial ROM Format_ + but early vendor boards just put the address in the first six + EEPROM locations. */ + unsigned char ee_data[EEPROM_SIZE]; + int sa_offset = 0; + + for (i = 0; i < sizeof(ee_data)/2; i++) + ((u16 *)ee_data)[i] = + le16_to_cpu(read_eeprom(ioaddr, i, EEPROM_ADDRLEN)); + + /* Detect the simple EEPROM format by the duplicated station addr. */ + for (i = 0; i < 8; i ++) + if (ee_data[i] != ee_data[16+i]) + sa_offset = 20; + if (ee_data[0] == 0xff && ee_data[1] == 0xff && ee_data[2] == 0) { + sa_offset = 2; /* Grrr, damn Matrox boards. */ + multiport_cnt = 4; + } + for (i = 0; i < 6; i ++) { + dev->dev_addr[i] = ee_data[i + sa_offset]; + sum += ee_data[i + sa_offset]; + } + } + /* Lite-On boards have the address byte-swapped. */ + if ((dev->dev_addr[0] == 0xA0 || dev->dev_addr[0] == 0xC0) + && dev->dev_addr[1] == 0x00) + for (i = 0; i < 6; i+=2) { + char tmp = dev->dev_addr[i]; + dev->dev_addr[i] = dev->dev_addr[i+1]; + dev->dev_addr[i+1] = tmp; + } + /* On the Zynx 315 Etherarray and other multiport boards only the + first Tulip has an EEPROM. + The addresses of the subsequent ports are derived from the first. + Many PCI BIOSes also incorrectly report the IRQ line, so we correct + that here as well. */ + if (sum == 0 || sum == 6*0xff) { + printk(" EEPROM not present,"); + for (i = 0; i < 5; i++) + dev->dev_addr[i] = last_phys_addr[i]; + dev->dev_addr[i] = last_phys_addr[i] + 1; +#if defined(__i386__) /* Patch up x86 BIOS bug. */ + if (last_irq) + irq = last_irq; +#endif + } + + for (i = 0; i < 6; i++) + printk("%c%2.2X", i ? ':' : ' ', last_phys_addr[i] = dev->dev_addr[i]); + printk(", IRQ %d.\n", irq); + last_irq = irq; + + /* We do a request_region() only to register /proc/ioports info. */ + /* Note that proper size is tulip_tbl[chip_idx].chip_name, but... */ + request_region(ioaddr, tulip_tbl[chip_idx].io_size, dev->name); + + dev->base_addr = ioaddr; + dev->irq = irq; + + /* Make certain the data structures are quadword aligned. */ + tp = (void *)(((long)kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA) + 7) & ~7); + memset(tp, 0, sizeof(*tp)); + dev->priv = tp; + + tp->next_module = root_tulip_dev; + root_tulip_dev = dev; + + tp->pci_bus = pci_bus; + tp->pci_devfn = pci_devfn; + tp->chip_id = chip_idx; + tp->revision = chip_rev; + tp->csr0 = csr0; + tp->setup_frame = (u16 *)(((unsigned long)tp->setup_buf + 7) & ~7); + + /* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles. + And the ASIX must have a burst limit or horrible things happen. */ + if ( (chip_idx == DC21143 && chip_rev == 65) || + (chip_idx == X3201_3) ) + tp->csr0 &= ~0x01000000; + else if (chip_idx == AX88140) + tp->csr0 |= 0x2000; + +#ifdef TULIP_FULL_DUPLEX + tp->full_duplex = 1; + tp->full_duplex_lock = 1; +#endif +#ifdef TULIP_DEFAULT_MEDIA + tp->default_port = TULIP_DEFAULT_MEDIA; +#endif +#ifdef TULIP_NO_MEDIA_SWITCH + tp->medialock = 1; +#endif + + /* The lower four bits are the media type. */ + if (board_idx >= 0 && board_idx < MAX_UNITS) { + tp->default_port = options[board_idx] & 15; + if ((options[board_idx] & 0x90) || full_duplex[board_idx] > 0) + tp->full_duplex = 1; + if (mtu[board_idx] > 0) + dev->mtu = mtu[board_idx]; + } + if (dev->mem_start) + tp->default_port = dev->mem_start; + if (tp->default_port) { + tp->medialock = 1; + if (media_cap[tp->default_port] & MediaAlwaysFD) + tp->full_duplex = 1; + } + if (tp->full_duplex) + tp->full_duplex_lock = 1; + + /* This is logically part of probe1(), but too complex to write inline. */ + if (tulip_tbl[chip_idx].flags & HAS_MEDIA_TABLE) + parse_eeprom(dev); + + if (media_cap[tp->default_port] & MediaIsMII) { + u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 }; + tp->to_advertise = media2advert[tp->default_port - 9]; + } else + tp->to_advertise = 0x03e1; + + if ((tulip_tbl[chip_idx].flags & ALWAYS_CHECK_MII) || + (tp->mtable && tp->mtable->has_mii) || + ( ! tp->mtable && (tulip_tbl[chip_idx].flags & HAS_MII))) { + int phy, phy_idx; + if (tp->mtable && tp->mtable->has_mii) { + for (i = 0; i < tp->mtable->leafcount; i++) + if (tp->mtable->mleaf[i].media == 11) { + tp->cur_index = i; + tp->saved_if_port = dev->if_port; + select_media(dev, 1); + dev->if_port = tp->saved_if_port; + break; + } + } + /* Find the connected MII xcvrs. + Doing this in open() would allow detecting external xcvrs later, + but takes much time. */ + for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys); + phy++) { + int mii_status = mdio_read(dev, phy, 1); + if ((mii_status & 0x8301) == 0x8001 || + ((mii_status & 0x8000) == 0 && (mii_status & 0x7800) != 0)) { + int mii_reg0 = mdio_read(dev, phy, 0); + int mii_advert = mdio_read(dev, phy, 4); + int reg4 = ((mii_status>>6) & tp->to_advertise) | 1; + tp->phys[phy_idx] = phy; + tp->advertising[phy_idx++] = reg4; + printk(KERN_INFO "%s: MII transceiver #%d " + "config %4.4x status %4.4x advertising %4.4x.\n", + dev->name, phy, mii_reg0, mii_status, mii_advert); + /* Fixup for DLink with miswired PHY. */ + if (mii_advert != reg4) { + printk(KERN_DEBUG "%s: Advertising %4.4x on PHY %d," + " previously advertising %4.4x.\n", + dev->name, reg4, phy, mii_advert); + mdio_write(dev, phy, 4, reg4); + } + /* Enable autonegotiation: some boards default to off. */ + mdio_write(dev, phy, 0, mii_reg0 | + (tp->full_duplex ? 0x1100 : 0x1000) | + (media_cap[tp->default_port]&MediaIs100 ? 0x2000:0)); + } + } + tp->mii_cnt = phy_idx; + if (tp->mtable && tp->mtable->has_mii && phy_idx == 0) { + printk(KERN_INFO "%s: ***WARNING***: No MII transceiver found!\n", + dev->name); + tp->phys[0] = 1; + } + } + + /* The Tulip-specific entries in the device structure. */ + dev->open = &tulip_open; + dev->hard_start_xmit = &tulip_start_xmit; + dev->stop = &tulip_close; + dev->get_stats = &tulip_get_stats; +#ifdef HAVE_PRIVATE_IOCTL + dev->do_ioctl = &private_ioctl; +#endif +#ifdef HAVE_MULTICAST + dev->set_multicast_list = &set_rx_mode; +#endif + + /* Reset the xcvr interface and turn on heartbeat. */ + switch (chip_idx) { + case DC21041: + outl(0x00000000, ioaddr + CSR13); + outl(0xFFFFFFFF, ioaddr + CSR14); + outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */ + outl_CSR6(inl(ioaddr + CSR6) | 0x0200, ioaddr, chip_idx); + outl(0x0000EF05, ioaddr + CSR13); + break; + case DC21040: + outl(0x00000000, ioaddr + CSR13); + outl(0x00000004, ioaddr + CSR13); + break; + case DC21140: default: + if (tp->mtable) + outl(tp->mtable->csr12dir | 0x100, ioaddr + CSR12); + break; + case DC21142: + case PNIC2: + if (tp->mii_cnt || media_cap[dev->if_port] & MediaIsMII) { + outl_CSR6(0x82020000, ioaddr, chip_idx); + outl(0x0000, ioaddr + CSR13); + outl(0x0000, ioaddr + CSR14); + outl_CSR6(0x820E0000, ioaddr, chip_idx); + } else { + outl_CSR6(0x82420200, ioaddr, chip_idx); + outl(0x0001, ioaddr + CSR13); + outl(0x0003FFFF, ioaddr + CSR14); + outl(0x0008, ioaddr + CSR15); + outl(0x0001, ioaddr + CSR13); + outl(0x1301, ioaddr + CSR12); /* Start NWay. */ + } + break; + case X3201_3: + outl(0x0008, ioaddr + CSR15); + udelay(5); /* The delays are Xircom recommended to give the + * chipset time to reset the actual hardware + * on the PCMCIA card + */ + outl(0xa8050000, ioaddr + CSR15); + udelay(5); + outl(0xa00f0000, ioaddr + CSR15); + udelay(5); + outl_CSR6(0x32000200, ioaddr, chip_idx); + break; + case LC82C168: + if ( ! tp->mii_cnt) { + outl_CSR6(0x00420000, ioaddr, chip_idx); + outl(0x30, ioaddr + CSR12); + outl(0x0001F078, ioaddr + 0xB8); + outl(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */ + } + break; + case MX98713: case COMPEX9881: + outl_CSR6(0x00000000, ioaddr, chip_idx); + outl(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */ + outl(0x00000001, ioaddr + CSR13); + break; + case MX98715: case MX98725: + outl_CSR6(0x01a80000, ioaddr, chip_idx); + outl(0xFFFFFFFF, ioaddr + CSR14); + outl(0x00001000, ioaddr + CSR12); + break; + case COMET: + /* No initialization necessary. */ + break; + } + + return dev; +} + +/* Serial EEPROM section. */ +/* The main routine to parse the very complicated SROM structure. + Search www.digital.com for "21X4 SROM" to get details. + This code is very complex, and will require changes to support + additional cards, so I'll be verbose about what is going on. + */ + +/* Known cards that have old-style EEPROMs. */ +static struct fixups { + char *name; + unsigned char addr0, addr1, addr2; + u16 newtable[32]; /* Max length below. */ +} eeprom_fixups[] = { + {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c, + 0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }}, + {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x021f, + 0x0000, 0x009E, /* 10baseT */ + 0x0903, 0x006D, /* 100baseTx */ }}, + {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x033f, + 0x0107, 0x8021, /* 100baseFx */ + 0x0108, 0x8021, /* 100baseFx-FD */ + 0x0103, 0x006D, /* 100baseTx */ }}, + {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0313, + 0x1001, 0x009E, /* 10base2, CSR12 0x10*/ + 0x0000, 0x009E, /* 10baseT */ + 0x0303, 0x006D, /* 100baseTx, CSR12 0x03 */ }}, + {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x031F, + 0x1B01, 0x0000, /* 10base2, CSR12 0x1B */ + 0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */ + 0x0B00, 0x009E, /* 10baseT, CSR12 0x0B */ + }}, + {0, 0, 0, 0, {}}}; + +static const char * block_name[] = {"21140 non-MII", "21140 MII PHY", + "21142 Serial PHY", "21142 MII PHY", "21143 SYM PHY", "21143 reset method"}; + +#if defined(__i386__) /* AKA get_unaligned() */ +#define get_u16(ptr) (*(u16 *)(ptr)) +#else +#define get_u16(ptr) (((u8*)(ptr))[0] + (((u8*)(ptr))[1]<<8)) +#endif + +static void parse_eeprom(struct net_device *dev) +{ + /* The last media info list parsed, for multiport boards. */ + static struct mediatable *last_mediatable = NULL; + static unsigned char *last_ee_data = NULL; + static int controller_index = 0; + struct tulip_private *tp = (struct tulip_private *)dev->priv; + long ioaddr = dev->base_addr; + unsigned char *ee_data = tp->eeprom; + int i; +#ifdef CARDBUS + int chip_rev = tp->revision; +#endif + + tp->mtable = 0; + for (i = 0; i < EEPROM_SIZE/2; i++) + ((u16 *)ee_data)[i] = + le16_to_cpu(read_eeprom(ioaddr, i, EEPROM_ADDRLEN)); + + /* Detect an old-style (SA only) EEPROM layout: + memcmp(eedata, eedata+16, 8). */ + for (i = 0; i < 8; i ++) + if (ee_data[i] != ee_data[16+i]) + break; + if (i >= 8) { + if (ee_data[0] == 0xff) { + if (last_mediatable) { + controller_index++; + printk(KERN_INFO "%s: Controller %d of multiport board.\n", + dev->name, controller_index); + tp->mtable = last_mediatable; + ee_data = last_ee_data; + goto subsequent_board; + } else + printk(KERN_INFO "%s: Missing EEPROM, this interface may " + "not work correctly!\n", + dev->name); + return; + } + /* Do a fix-up based on the vendor half of the station address prefix. */ + for (i = 0; eeprom_fixups[i].name; i++) { + if (dev->dev_addr[0] == eeprom_fixups[i].addr0 + && dev->dev_addr[1] == eeprom_fixups[i].addr1 + && dev->dev_addr[2] == eeprom_fixups[i].addr2) { + if (dev->dev_addr[2] == 0xE8 && ee_data[0x1a] == 0x55) + i++; /* An Accton EN1207, not an outlaw Maxtech. */ + memcpy(ee_data + 26, eeprom_fixups[i].newtable, + sizeof(eeprom_fixups[i].newtable)); + printk(KERN_INFO "%s: Old format EEPROM on '%s' board. Using" + " substitute media control info.\n", + dev->name, eeprom_fixups[i].name); + break; + } + } + if (eeprom_fixups[i].name == NULL) { /* No fixup found. */ + printk(KERN_INFO "%s: Old style EEPROM with no media selection " + "information.\n", + dev->name); + return; + } + } + + controller_index = 0; + if (ee_data[19] > 1) { /* Multiport board. */ + last_ee_data = ee_data; + } +subsequent_board: + + if (ee_data[27] == 0) { /* No valid media table. */ + } else if (tp->chip_id == DC21041) { + unsigned char *p = (void *)ee_data + ee_data[27 + controller_index*3]; + short media; + int count; + + media = get_u16(p); + p += 2; + count = *p++; + + printk(KERN_INFO "%s:21041 Media information at %d, default media " + "%4.4x (%s).\n", dev->name, ee_data[27], media, + media & 0x0800 ? "Autosense" : medianame[media & 15]); + for (i = 0; i < count; i++) { + unsigned char media_code = *p++; + u16 csrvals[3]; + int idx; + for (idx = 0; idx < 3; idx++) { + csrvals[idx] = get_u16(p); + p += 2; + } + if (media_code & 0x40) { + printk(KERN_INFO "%s: 21041 media %2.2x (%s)," + " csr13 %4.4x csr14 %4.4x csr15 %4.4x.\n", + dev->name, media_code & 15, medianame[media_code & 15], + csrvals[0], csrvals[1], csrvals[2]); + } else + printk(KERN_INFO "%s: 21041 media #%d, %s.\n", + dev->name, media_code & 15, medianame[media_code & 15]); + } + } else { + unsigned char *p = (void *)ee_data + ee_data[27]; + unsigned char csr12dir = 0; + int count; + struct mediatable *mtable; + u16 media = get_u16(p); + + p += 2; + if (tulip_tbl[tp->chip_id].flags & CSR12_IN_SROM) + csr12dir = *p++; + count = *p++; + mtable = (struct mediatable *) + kmalloc(sizeof(struct mediatable) + count*sizeof(struct medialeaf), + GFP_KERNEL); + if (mtable == NULL) + return; /* Horrible, impossible failure. */ + last_mediatable = tp->mtable = mtable; + mtable->defaultmedia = media; + mtable->leafcount = count; + mtable->csr12dir = csr12dir; + mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0; + mtable->csr15dir = mtable->csr15val = 0; + + printk(KERN_INFO "%s: EEPROM default media type %s.\n", dev->name, + media & 0x0800 ? "Autosense" : medianame[media & 15]); + for (i = 0; i < count; i++) { + struct medialeaf *leaf = &mtable->mleaf[i]; + + if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */ + leaf->type = 0; + leaf->media = p[0] & 0x3f; + leaf->leafdata = p; + if ((p[2] & 0x61) == 0x01) /* Bogus, but Znyx boards do it. */ + mtable->has_mii = 1; + p += 4; + } else { + leaf->type = p[1]; + if (p[1] == 0x05) { + mtable->has_reset = i; + leaf->media = p[2] & 0x0f; + } else if (p[1] & 1) { + mtable->has_mii = 1; + leaf->media = 11; + } else { + mtable->has_nonmii = 1; + leaf->media = p[2] & 0x0f; + if (p[1] == 2) { + if (leaf->media == 0) { + mtable->csr15dir = get_unaligned((u16*)&p[3])<<16; + mtable->csr15val = get_unaligned((u16*)&p[5])<<16; + } else if (leaf->media == 0x40) { + u32 base15 = get_unaligned((u16*)&p[7]); + mtable->csr15dir = + (get_unaligned((u16*)&p[9])<<16) + base15; + mtable->csr15val = + (get_unaligned((u16*)&p[11])<<16) + base15; + } + } + } + leaf->leafdata = p + 2; + p += (p[0] & 0x3f) + 1; + } + if (tulip_debug > 1 && leaf->media == 11) { + unsigned char *bp = leaf->leafdata; + printk(KERN_INFO "%s: MII interface PHY %d, setup/reset " + "sequences %d/%d long, capabilities %2.2x %2.2x.\n", + dev->name, bp[0], bp[1], bp[1 + bp[1]*2], + bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]); + } + printk(KERN_INFO "%s: Index #%d - Media %s (#%d) described " + "by a %s (%d) block.\n", + dev->name, i, medianame[leaf->media], leaf->media, + block_name[leaf->type], leaf->type); + } + } +} +/* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/ + +/* EEPROM_Ctrl bits. */ +#define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */ +#define EE_CS 0x01 /* EEPROM chip select. */ +#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ +#define EE_WRITE_0 0x01 +#define EE_WRITE_1 0x05 +#define EE_DATA_READ 0x08 /* EEPROM chip data out. */ +#define EE_ENB (0x4800 | EE_CS) + +/* Delay between EEPROM clock transitions. + Even at 33Mhz current PCI implementations don't overrun the EEPROM clock. + We add a bus turn-around to insure that this remains true. */ +#define eeprom_delay() inl(ee_addr) + +/* The EEPROM commands include the alway-set leading bit. */ +#define EE_WRITE_CMD (5 << addr_len) +#define EE_READ_CMD (6 << addr_len) +#define EE_ERASE_CMD (7 << addr_len) + +static int read_eeprom(long ioaddr, int location, int addr_len) +{ + int i; + unsigned short retval = 0; + long ee_addr = ioaddr + CSR9; + int read_cmd = location | EE_READ_CMD; + + outl(EE_ENB & ~EE_CS, ee_addr); + outl(EE_ENB, ee_addr); + + /* Shift the read command bits out. */ + for (i = 4 + addr_len; i >= 0; i--) { + short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + outl(EE_ENB | dataval, ee_addr); + eeprom_delay(); + outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); + eeprom_delay(); + } + outl(EE_ENB, ee_addr); + + for (i = 16; i > 0; i--) { + outl(EE_ENB | EE_SHIFT_CLK, ee_addr); + eeprom_delay(); + retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0); + outl(EE_ENB, ee_addr); + eeprom_delay(); + } + + /* Terminate the EEPROM access. */ + outl(EE_ENB & ~EE_CS, ee_addr); + return retval; +} + +/* MII transceiver control section. + Read and write the MII registers using software-generated serial + MDIO protocol. See the MII specifications or DP83840A data sheet + for details. */ + +/* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually + met by back-to-back PCI I/O cycles, but we insert a delay to avoid + "overclocking" issues or future 66Mhz PCI. */ +#define mdio_delay() inl(mdio_addr) + +/* Read and write the MII registers using software-generated serial + MDIO protocol. It is just different enough from the EEPROM protocol + to not share code. The maxium data clock rate is 2.5 Mhz. */ +#define MDIO_SHIFT_CLK 0x10000 +#define MDIO_DATA_WRITE0 0x00000 +#define MDIO_DATA_WRITE1 0x20000 +#define MDIO_ENB 0x00000 /* Ignore the 0x02000 databook setting. */ +#define MDIO_ENB_IN 0x40000 +#define MDIO_DATA_READ 0x80000 + +static int mdio_read(struct net_device *dev, int phy_id, int location) +{ + struct tulip_private *tp = (struct tulip_private *)dev->priv; + int i; + int read_cmd = (0xf6 << 10) | (phy_id << 5) | location; + int retval = 0; + long ioaddr = dev->base_addr; + long mdio_addr = ioaddr + CSR9; + + if (tp->chip_id == LC82C168) { + int i = 1000; + outl(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0); + inl(ioaddr + 0xA0); + inl(ioaddr + 0xA0); + while (--i > 0) + if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000)) + return retval & 0xffff; + return 0xffff; + } + + if (tp->chip_id == COMET) { + if (phy_id == 1) { + if (location < 7) + return inl(ioaddr + 0xB4 + (location<<2)); + else if (location == 17) + return inl(ioaddr + 0xD0); + else if (location >= 29 && location <= 31) + return inl(ioaddr + 0xD4 + ((location-29)<<2)); + } + return 0xffff; + } + + /* Establish sync by sending at least 32 logic ones. */ + for (i = 32; i >= 0; i--) { + outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr); + mdio_delay(); + outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + /* Shift the read command bits out. */ + for (i = 15; i >= 0; i--) { + int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; + + outl(MDIO_ENB | dataval, mdio_addr); + mdio_delay(); + outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + /* Read the two transition, 16 data, and wire-idle bits. */ + for (i = 19; i > 0; i--) { + outl(MDIO_ENB_IN, mdio_addr); + mdio_delay(); + retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0); + outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + return (retval>>1) & 0xffff; +} + +static void mdio_write(struct net_device *dev, int phy_id, int location, int value) +{ + struct tulip_private *tp = (struct tulip_private *)dev->priv; + int i; + int cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value; + long ioaddr = dev->base_addr; + long mdio_addr = ioaddr + CSR9; + + if (tp->chip_id == LC82C168) { + int i = 1000; + outl(cmd, ioaddr + 0xA0); + do + if ( ! (inl(ioaddr + 0xA0) & 0x80000000)) + break; + while (--i > 0); + return; + } + + if (tp->chip_id == COMET) { + if (phy_id != 1) + return; + if (location < 7) + outl(value, ioaddr + 0xB4 + (location<<2)); + else if (location == 17) + outl(value, ioaddr + 0xD0); + else if (location >= 29 && location <= 31) + outl(value, ioaddr + 0xD4 + ((location-29)<<2)); + return; + } + + /* Establish sync by sending 32 logic ones. */ + for (i = 32; i >= 0; i--) { + outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr); + mdio_delay(); + outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + /* Shift the command bits out. */ + for (i = 31; i >= 0; i--) { + int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0; + outl(MDIO_ENB | dataval, mdio_addr); + mdio_delay(); + outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + /* Clear out extra bits. */ + for (i = 2; i > 0; i--) { + outl(MDIO_ENB_IN, mdio_addr); + mdio_delay(); + outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); + mdio_delay(); + } + return; +} + +static void +tulip_up(struct net_device *dev) +{ + struct tulip_private *tp = (struct tulip_private *)dev->priv; + long ioaddr = dev->base_addr; + int i; + + /* On some chip revs we must set the MII/SYM port before the reset!? */ + if (tp->mii_cnt || (tp->mtable && tp->mtable->has_mii)) + outl_CSR6(0x00040000, ioaddr, tp->chip_id); + + /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */ + outl(0x00000001, ioaddr + CSR0); + + /* Deassert reset. */ + outl(tp->csr0, ioaddr + CSR0); + udelay(2); + + /* Clear the tx ring */ + for (i = 0; i < TX_RING_SIZE; i++) { + tp->tx_skbuff[i] = 0; + tp->tx_ring[i].status = 0x00000000; + } + + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: tulip_open() irq %d.\n", dev->name, dev->irq); + + if (tulip_tbl[tp->chip_id].flags & MC_HASH_ONLY) { + u32 addr_low = cpu_to_le32(get_unaligned((u32 *)dev->dev_addr)); + u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(dev->dev_addr+4))); + if (tp->chip_id == AX88140) { + outl(0, ioaddr + CSR13); + outl(addr_low, ioaddr + CSR14); + outl(1, ioaddr + CSR13); + outl(addr_high, ioaddr + CSR14); + } else if (tp->chip_id == COMET) { + outl(addr_low, ioaddr + 0xA4); + outl(addr_high, ioaddr + 0xA8); + outl(0, ioaddr + 0xAC); + outl(0, ioaddr + 0xB0); + } + } else if (tp->chip_id != X3201_3) { + /* This is set_rx_mode(), but without starting the transmitter. */ + u16 *eaddrs = (u16 *)dev->dev_addr; + u16 *setup_frm = &tp->setup_frame[15*6]; + + /* 21140 bug: you must add the broadcast address. */ + memset(tp->setup_frame, 0xff, 96*sizeof(u16)); + /* Fill the final entry of the table with our physical address. */ + *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; + *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; + *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; + /* Put the setup frame on the Tx list. */ + tp->tx_ring[0].length = 0x08000000 | 192; + tp->tx_ring[0].buffer1 = virt_to_bus(tp->setup_frame); + tp->tx_ring[0].status = DescOwned; + + tp->cur_tx++; + } else { /* X3201_3 */ + u16 *eaddrs = (u16 *)dev->dev_addr; + u16 *setup_frm = &tp->setup_frame[0*6]; + + /* fill the table with the broadcast address */ + memset(tp->setup_frame, 0xff, 96*sizeof(u16)); + /* re-fill the first 14 table entries with our address */ + for(i=0; i<14; i++) { + *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; + *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; + *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; + } + + /* Put the setup frame on the Tx list. */ + tp->tx_ring[0].length = 0x08000000 | 192; + /* Lie about the address of our setup frame to make the */ + /* chip happy */ + tp->tx_ring[0].buffer1 = (virt_to_bus(tp->setup_frame) + 4); + tp->tx_ring[0].status = DescOwned; + + tp->cur_tx++; + } + outl(virt_to_bus(tp->rx_ring), ioaddr + CSR3); + outl(virt_to_bus(tp->tx_ring), ioaddr + CSR4); + + tp->saved_if_port = dev->if_port; + if (dev->if_port == 0) + dev->if_port = tp->default_port; + if (tp->chip_id == DC21041 && dev->if_port > 4) + /* Invalid: Select initial TP, autosense, autonegotiate. */ + dev->if_port = 4; + + /* Allow selecting a default media. */ + i = 0; + if (tp->mtable == NULL) + goto media_picked; + if (dev->if_port) { + int looking_for = media_cap[dev->if_port] & MediaIsMII ? 11 : + (dev->if_port == 12 ? 0 : dev->if_port); + for (i = 0; i < tp->mtable->leafcount; i++) + if (tp->mtable->mleaf[i].media == looking_for) { + printk(KERN_INFO "%s: Using user-specified media %s.\n", + dev->name, medianame[dev->if_port]); + goto media_picked; + } + } + if ((tp->mtable->defaultmedia & 0x0800) == 0) { + int looking_for = tp->mtable->defaultmedia & 15; + for (i = 0; i < tp->mtable->leafcount; i++) + if (tp->mtable->mleaf[i].media == looking_for) { + printk(KERN_INFO "%s: Using EEPROM-set media %s.\n", + dev->name, medianame[looking_for]); + goto media_picked; + } + } + /* Start sensing first non-full-duplex media. */ + for (i = tp->mtable->leafcount - 1; + (media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--) + ; +media_picked: + + tp->csr6 = 0; + tp->cur_index = i; + if (dev->if_port == 0 && tp->chip_id == DC21142) { + if (tp->mii_cnt) { + select_media(dev, 1); + if (tulip_debug > 1) + printk(KERN_INFO "%s: Using MII transceiver %d, status " + "%4.4x.\n", + dev->name, tp->phys[0], mdio_read(dev, tp->phys[0], 1)); + outl_CSR6(0x82020000, ioaddr, tp->chip_id); + tp->csr6 = 0x820E0000; + dev->if_port = 11; + outl(0x0000, ioaddr + CSR13); + outl(0x0000, ioaddr + CSR14); + } else + t21142_start_nway(dev); + } else if ((tp->chip_id == LC82C168 || tp->chip_id == PNIC2) + && tp->mii_cnt && ! tp->medialock) { + dev->if_port = 11; + tp->csr6 = 0x814C0000 | (tp->full_duplex ? 0x0200 : 0); + outl(0x0001, ioaddr + CSR15); + } else if ((tp->chip_id == MX98713 || tp->chip_id == COMPEX9881) + && ! tp->medialock) { + dev->if_port = 0; + tp->csr6 = 0x01880000 | (tp->full_duplex ? 0x0200 : 0); + outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80); + } else if (tp->chip_id == MX98715 || tp->chip_id == MX98725) { + /* Provided by BOLO, Macronix - 12/10/1998. */ + dev->if_port = 0; + tp->csr6 = 0x01880200; + outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80); + outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0); + } else if (tp->chip_id == DC21143 && + media_cap[dev->if_port] & MediaIsMII) { + /* We must reset the media CSRs when we force-select MII mode. */ + outl(0x0000, ioaddr + CSR13); + outl(0x0000, ioaddr + CSR14); + outl(0x0008, ioaddr + CSR15); + } else if (tp->chip_id == X3201_3) { + outl(0x0008, ioaddr + CSR15); + udelay(5); + outl(0xa8050000, ioaddr + CSR15); + udelay(5); + outl(0xa00f0000, ioaddr + CSR15); + udelay(5); + tp->csr6 = 0x32400000; + } else if (tp->chip_id == COMET) { + dev->if_port = 0; + tp->csr6 = 0x00040000; + } else + select_media(dev, 1); + + /* Start the chip's Tx to process setup frame. */ + outl_CSR6(tp->csr6, ioaddr, tp->chip_id); + outl_CSR6(tp->csr6 | 0x2000, ioaddr, tp->chip_id); + + dev->tbusy = 0; + tp->interrupt = 0; + dev->start = 1; + + /* Enable interrupts by setting the interrupt mask. */ + outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5); + outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); + outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id); + outl(0, ioaddr + CSR2); /* Rx poll demand */ + + if (tulip_debug > 2) { + printk(KERN_DEBUG "%s: Done tulip_open(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n", + dev->name, inl(ioaddr + CSR0), inl(ioaddr + CSR5), + inl(ioaddr + CSR6)); + } + /* Set the timer to switch to check for link beat and perhaps switch + to an alternate media type. */ + init_timer(&tp->timer); + tp->timer.expires = RUN_AT(5*HZ); + tp->timer.data = (unsigned long)dev; + tp->timer.function = tulip_tbl[tp->chip_id].media_timer; + add_timer(&tp->timer); +} + +static int +tulip_open(struct net_device *dev) +{ + struct tulip_private *tp = (struct tulip_private *)dev->priv; + + if (request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev)) + return -EAGAIN; + + tulip_init_ring(dev); + + tulip_up(dev); + tp->open = 1; + MOD_INC_USE_COUNT; + + return 0; +} + +/* Set up the transceiver control registers for the selected media type. */ +static void select_media(struct net_device *dev, int startup) +{ + long ioaddr = dev->base_addr; + struct tulip_private *tp = (struct tulip_private *)dev->priv; + struct mediatable *mtable = tp->mtable; + u32 new_csr6; + int i; + + if (mtable) { + struct medialeaf *mleaf = &mtable->mleaf[tp->cur_index]; + unsigned char *p = mleaf->leafdata; + switch (mleaf->type) { + case 0: /* 21140 non-MII xcvr. */ + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: Using a 21140 non-MII transceiver" + " with control setting %2.2x.\n", + dev->name, p[1]); + dev->if_port = p[0]; + if (startup) + outl(mtable->csr12dir | 0x100, ioaddr + CSR12); + outl(p[1], ioaddr + CSR12); + new_csr6 = 0x02000000 | ((p[2] & 0x71) << 18); + break; + case 2: case 4: { + u16 setup[5]; + u32 csr13val, csr14val, csr15dir, csr15val; + for (i = 0; i < 5; i++) + setup[i] = get_u16(&p[i*2 + 1]); + + dev->if_port = p[0] & 15; + if (media_cap[dev->if_port] & MediaAlwaysFD) + tp->full_duplex = 1; + + if (startup && mtable->has_reset) { + struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset]; + unsigned char *rst = rleaf->leafdata; + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: Resetting the transceiver.\n", + dev->name); + for (i = 0; i < rst[0]; i++) + outl(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15); + } + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: 21143 non-MII %s transceiver control " + "%4.4x/%4.4x.\n", + dev->name, medianame[dev->if_port], setup[0], setup[1]); + if (p[0] & 0x40) { /* SIA (CSR13-15) setup values are provided. */ + csr13val = setup[0]; + csr14val = setup[1]; + csr15dir = (setup[3]<<16) | setup[2]; + csr15val = (setup[4]<<16) | setup[2]; + outl(0, ioaddr + CSR13); + outl(csr14val, ioaddr + CSR14); + outl(csr15dir, ioaddr + CSR15); /* Direction */ + outl(csr15val, ioaddr + CSR15); /* Data */ + outl(csr13val, ioaddr + CSR13); + } else { + csr13val = 1; + csr14val = 0x0003FF7F; + csr15dir = (setup[0]<<16) | 0x0008; + csr15val = (setup[1]<<16) | 0x0008; + if (dev->if_port <= 4) + csr14val = t21142_csr14[dev->if_port]; + if (startup) { + outl(0, ioaddr + CSR13); + outl(csr14val, ioaddr + CSR14); + } + outl(csr15dir, ioaddr + CSR15); /* Direction */ + outl(csr15val, ioaddr + CSR15); /* Data */ + if (startup) outl(csr13val, ioaddr + CSR13); + } + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: Setting CSR15 to %8.8x/%8.8x.\n", + dev->name, csr15dir, csr15val); + if (mleaf->type == 4) + new_csr6 = 0x82020000 | ((setup[2] & 0x71) << 18); + else + new_csr6 = 0x82420000; + break; + } + case 1: case 3: { + int phy_num = p[0]; + int init_length = p[1]; + u16 *misc_info; + u16 to_advertise; + + dev->if_port = 11; + new_csr6 = 0x020E0000; + if (mleaf->type == 3) { /* 21142 */ + u16 *init_sequence = (u16*)(p+2); + u16 *reset_sequence = &((u16*)(p+3))[init_length]; + int reset_length = p[2 + init_length*2]; + misc_info = reset_sequence + reset_length; + if (startup) + for (i = 0; i < reset_length; i++) + outl(get_u16(&reset_sequence[i]) << 16, ioaddr + CSR15); + for (i = 0; i < init_length; i++) + outl(get_u16(&init_sequence[i]) << 16, ioaddr + CSR15); + } else { + u8 *init_sequence = p + 2; + u8 *reset_sequence = p + 3 + init_length; + int reset_length = p[2 + init_length]; + misc_info = (u16*)(reset_sequence + reset_length); + if (startup) { + outl(mtable->csr12dir | 0x100, ioaddr + CSR12); + for (i = 0; i < reset_length; i++) + outl(reset_sequence[i], ioaddr + CSR12); + } + for (i = 0; i < init_length; i++) + outl(init_sequence[i], ioaddr + CSR12); + } + to_advertise = (get_u16(&misc_info[1]) & tp->to_advertise) | 1; + tp->advertising[phy_num] = to_advertise; + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: Advertising %4.4x on PHY %d (%d).\n", + dev->name, to_advertise, phy_num, tp->phys[phy_num]); + /* Bogus: put in by a committee? */ + mdio_write(dev, tp->phys[phy_num], 4, to_advertise); + break; + } + default: + printk(KERN_DEBUG "%s: Invalid media table selection %d.\n", + dev->name, mleaf->type); + new_csr6 = 0x020E0000; + } + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: Using media type %s, CSR12 is %2.2x.\n", + dev->name, medianame[dev->if_port], + inl(ioaddr + CSR12) & 0xff); + } else if (tp->chip_id == DC21041) { + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: 21041 using media %s, CSR12 is %4.4x.\n", + dev->name, medianame[dev->if_port & 15], + inl(ioaddr + CSR12) & 0xffff); + outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */ + outl(t21041_csr14[dev->if_port], ioaddr + CSR14); + outl(t21041_csr15[dev->if_port], ioaddr + CSR15); + outl(t21041_csr13[dev->if_port], ioaddr + CSR13); + new_csr6 = 0x80020000; + } else if (tp->chip_id == LC82C168 || tp->chip_id == PNIC2) { + if (startup && ! tp->medialock) + dev->if_port = tp->mii_cnt ? 11 : 0; + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: PNIC PHY status is %3.3x, CSR12 %4.4x," + " media %s.\n", + dev->name, inl(ioaddr + 0xB8), inl(ioaddr + CSR12), + medianame[dev->if_port]); + if (tp->mii_cnt) { + new_csr6 = 0x810C0000; + outl(0x0001, ioaddr + CSR15); + outl(0x0201B07A, ioaddr + 0xB8); + } else if (startup) { + /* Start with 10mbps to do autonegotiation. */ + outl(0x32, ioaddr + CSR12); + new_csr6 = 0x00420000; + outl(0x0001B078, ioaddr + 0xB8); + outl(0x0201B078, ioaddr + 0xB8); + } else if (dev->if_port == 3 || dev->if_port == 5) { + outl(0x33, ioaddr + CSR12); + new_csr6 = 0x01860000; + if (startup) + outl(0x0201F868, ioaddr + 0xB8); /* Trigger autonegotiation. */ + else + outl(0x1F868, ioaddr + 0xB8); + } else { + outl(0x32, ioaddr + CSR12); + new_csr6 = 0x00420000; + outl(0x1F078, ioaddr + 0xB8); + } + } else if (tp->chip_id == DC21040) { /* 21040 */ + /* Turn on the xcvr interface. */ + int csr12 = inl(ioaddr + CSR12); + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: 21040 media type is %s, CSR12 is %2.2x.\n", + dev->name, medianame[dev->if_port], csr12); + if (media_cap[dev->if_port] & MediaAlwaysFD) + tp->full_duplex = 1; + new_csr6 = 0x20000; + /* Set the full duplux match frame. */ + outl(FULL_DUPLEX_MAGIC, ioaddr + CSR11); + outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */ + if (t21040_csr13[dev->if_port] & 8) { + outl(0x0705, ioaddr + CSR14); + outl(0x0006, ioaddr + CSR15); + } else { + outl(0xffff, ioaddr + CSR14); + outl(0x0000, ioaddr + CSR15); + } + outl(0x8f01 | t21040_csr13[dev->if_port], ioaddr + CSR13); + } else if (tp->chip_id == X3201_3) { /* Xircom */ + if (tp->default_port == 0) + dev->if_port = tp->mii_cnt ? 11 : 3; +/* Someone is on crack, the Xircom only does MII, no Fx */ +/* if (media_cap[dev->if_port] & MediaIsMII) { + new_csr6 = 0x020E0000; + } else if (media_cap[dev->if_port] & MediaIsFx) { + new_csr6 = 0x028600000; + } else + new_csr6 = 0x038600000;*/ + new_csr6 = 0x324c0000; + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: Xircom CardBus Adapter: " + "%s transceiver, CSR12 %2.2x.\n", + dev->name, medianame[dev->if_port], + inl(ioaddr + CSR12)); + } else { /* Unknown chip type with no media table. */ + if (tp->default_port == 0) + dev->if_port = tp->mii_cnt ? 11 : 3; + if (media_cap[dev->if_port] & MediaIsMII) { + new_csr6 = 0x020E0000; + } else if (media_cap[dev->if_port] & MediaIsFx) { + new_csr6 = 0x028600000; + } else + new_csr6 = 0x038600000; + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: No media description table, assuming " + "%s transceiver, CSR12 %2.2x.\n", + dev->name, medianame[dev->if_port], + inl(ioaddr + CSR12)); + } + + tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0); + return; +} + +/* + Check the MII negotiated duplex, and change the CSR6 setting if + required. + Return 0 if everything is OK. + Return < 0 if the transceiver is missing or has no link beat. + */ +static int check_duplex(struct net_device *dev) +{ + long ioaddr = dev->base_addr; + struct tulip_private *tp = (struct tulip_private *)dev->priv; + int mii_reg1, mii_reg5, negotiated, duplex; + + if (tp->full_duplex_lock) + return 0; + mii_reg1 = mdio_read(dev, tp->phys[0], 1); + mii_reg5 = mdio_read(dev, tp->phys[0], 5); + if (tulip_debug > 1) + printk(KERN_INFO "%s: MII status %4.4x, Link partner report " + "%4.4x.\n", dev->name, mii_reg1, mii_reg5); + if (mii_reg1 == 0xffff) + return -2; + if ((mii_reg1 & 0x0004) == 0) { + int new_reg1 = mdio_read(dev, tp->phys[0], 1); + if ((new_reg1 & 0x0004) == 0) { + if (tulip_debug > 1) + printk(KERN_INFO "%s: No link beat on the MII interface," + " status %4.4x.\n", dev->name, new_reg1); + return -1; + } + } + negotiated = mii_reg5 & tp->advertising[0]; + duplex = ((negotiated & 0x0300) == 0x0100 + || (negotiated & 0x00C0) == 0x0040); + /* 100baseTx-FD or 10T-FD, but not 100-HD */ + if (tp->full_duplex != duplex) { + tp->full_duplex = duplex; + if (tp->full_duplex) tp->csr6 |= 0x0200; + else tp->csr6 &= ~0x0200; + outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id); + outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id); + if (tulip_debug > 0) + printk(KERN_INFO "%s: Setting %s-duplex based on MII" + "#%d link partner capability of %4.4x.\n", + dev->name, tp->full_duplex ? "full" : "half", + tp->phys[0], mii_reg5); + } + return 0; +} + +static void tulip_timer(unsigned long data) +{ + struct net_device *dev = (struct net_device *)data; + struct tulip_private *tp = (struct tulip_private *)dev->priv; + long ioaddr = dev->base_addr; + u32 csr12 = inl(ioaddr + CSR12); + int next_tick = 2*HZ; + + if (tulip_debug > 2) { + printk(KERN_DEBUG "%s: Media selection tick, status %8.8x mode %8.8x " + "SIA %8.8x %8.8x %8.8x %8.8x.\n", + dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR6), + csr12, inl(ioaddr + CSR13), + inl(ioaddr + CSR14), inl(ioaddr + CSR15)); + } + switch (tp->chip_id) { + case DC21040: + if (!tp->medialock && csr12 & 0x0002) { /* Network error */ + printk(KERN_INFO "%s: No link beat found.\n", + dev->name); + dev->if_port = (dev->if_port == 2 ? 0 : 2); + select_media(dev, 0); + dev->trans_start = jiffies; + } + break; + case DC21041: + if (tulip_debug > 2) + printk(KERN_DEBUG "%s: 21041 media tick CSR12 %8.8x.\n", + dev->name, csr12); + switch (dev->if_port) { + case 0: case 3: case 4: + if (csr12 & 0x0004) { /*LnkFail */ + /* 10baseT is dead. Check for activity on alternate port. */ + tp->mediasense = 1; + if (csr12 & 0x0200) + dev->if_port = 2; + else + dev->if_port = 1; + printk(KERN_INFO "%s: No 21041 10baseT link beat, Media switched to %s.\n", + dev->name, medianame[dev->if_port]); + outl(0, ioaddr + CSR13); /* Reset */ + outl(t21041_csr14[dev->if_port], ioaddr + CSR14); + outl(t21041_csr15[dev->if_port], ioaddr + CSR15); + outl(t21041_csr13[dev->if_port], ioaddr + CSR13); + next_tick = 10*HZ; /* 2.4 sec. */ + } else + next_tick = 30*HZ; + break; + case 1: /* 10base2 */ + case 2: /* AUI */ + if (csr12 & 0x0100) { + next_tick = (30*HZ); /* 30 sec. */ + tp->mediasense = 0; + } else if ((csr12 & 0x0004) == 0) { + printk(KERN_INFO "%s: 21041 media switched to 10baseT.\n", + dev->name); + dev->if_port = 0; + select_media(dev, 0); + next_tick = (24*HZ)/10; /* 2.4 sec. */ + } else if (tp->mediasense || (csr12 & 0x0002)) { + dev->if_port = 3 - dev->if_port; /* Swap ports. */ + select_media(dev, 0); + next_tick = 20*HZ; + } else { + next_tick = 20*HZ; + } + break; + } + break; + case DC21140: case DC21142: case MX98713: case COMPEX9881: default: { + struct medialeaf *mleaf; + unsigned char *p; + if (tp->mtable == NULL) { /* No EEPROM info, use generic code. */ + /* Not much that can be done. + Assume this a generic MII or SYM transceiver. */ + next_tick = 60*HZ; + if (tulip_debug > 2) + printk(KERN_DEBUG "%s: network media monitor CSR6 %8.8x " + "CSR12 0x%2.2x.\n", + dev->name, inl(ioaddr + CSR6), csr12 & 0xff); + break; + } + mleaf = &tp->mtable->mleaf[tp->cur_index]; + p = mleaf->leafdata; + switch (mleaf->type) { + case 0: case 4: { + /* Type 0 serial or 4 SYM transceiver. Check the link beat bit. */ + int offset = mleaf->type == 4 ? 5 : 2; + s8 bitnum = p[offset]; + if (p[offset+1] & 0x80) { + if (tulip_debug > 1) + printk(KERN_DEBUG"%s: Transceiver monitor tick " + "CSR12=%#2.2x, no media sense.\n", + dev->name, csr12); + if (mleaf->type == 4) { + if (mleaf->media == 3 && (csr12 & 0x02)) + goto select_next_media; + } + break; + } + if (tulip_debug > 2) + printk(KERN_DEBUG "%s: Transceiver monitor tick: CSR12=%#2.2x" + " bit %d is %d, expecting %d.\n", + dev->name, csr12, (bitnum >> 1) & 7, + (csr12 & (1 << ((bitnum >> 1) & 7))) != 0, + (bitnum >= 0)); + /* Check that the specified bit has the proper value. */ + if ((bitnum < 0) != + ((csr12 & (1 << ((bitnum >> 1) & 7))) != 0)) { + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: Link beat detected for %s.\n", dev->name, + medianame[mleaf->media]); + if ((p[2] & 0x61) == 0x01) /* Bogus Znyx board. */ + goto actually_mii; + break; + } + if (tp->medialock) + break; + select_next_media: + if (--tp->cur_index < 0) { + /* We start again, but should instead look for default. */ + tp->cur_index = tp->mtable->leafcount - 1; + } + dev->if_port = tp->mtable->mleaf[tp->cur_index].media; + if (media_cap[dev->if_port] & MediaIsFD) + goto select_next_media; /* Skip FD entries. */ + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: No link beat on media %s," + " trying transceiver type %s.\n", + dev->name, medianame[mleaf->media & 15], + medianame[tp->mtable->mleaf[tp->cur_index].media]); + select_media(dev, 0); + /* Restart the transmit process. */ + outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id); + outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id); + next_tick = (24*HZ)/10; + break; + } + case 1: case 3: /* 21140, 21142 MII */ + actually_mii: + check_duplex(dev); + next_tick = 60*HZ; + break; + case 2: /* 21142 serial block has no link beat. */ + default: + break; + } + } + break; + } + tp->timer.expires = RUN_AT(next_tick); + add_timer(&tp->timer); +} + +/* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list + of available transceivers. */ +static void t21142_timer(unsigned long data) +{ + struct net_device *dev = (struct net_device *)data; + struct tulip_private *tp = (struct tulip_private *)dev->priv; + long ioaddr = dev->base_addr; + int csr12 = inl(ioaddr + CSR12); + int next_tick = 60*HZ; + int new_csr6 = 0; + + if ((tulip_debug > 2) && !(media_cap[dev->if_port] & MediaIsMII)) + printk(KERN_INFO"%s: 21143 negotiation status %8.8x, %s.\n", + dev->name, csr12, medianame[dev->if_port]); + if (media_cap[dev->if_port] & MediaIsMII) { + check_duplex(dev); + next_tick = 60*HZ; + } else if (tp->nwayset) { + /* Don't screw up a negotiated session! */ + if (tulip_debug > 1) + printk(KERN_INFO"%s: Using NWay-set %s media, csr12 %8.8x.\n", + dev->name, medianame[dev->if_port], csr12); + } else if (tp->medialock) { + ; + } else if (dev->if_port == 3) { + if (csr12 & 2) { /* No 100mbps link beat, revert to 10mbps. */ + if (tulip_debug > 1) + printk(KERN_INFO"%s: No 21143 100baseTx link beat, %8.8x, " + "trying NWay.\n", dev->name, csr12); + t21142_start_nway(dev); + next_tick = 3*HZ; + } + } else if (((csr12 & 0x7000) != 0x5000) + && tp->chip_id != X3201_3) { + /* Negotiation failed. Search media types. */ + if (tulip_debug > 1) + printk(KERN_INFO"%s: 21143 negotiation failed, status %8.8x.\n", + dev->name, csr12); + if (!(csr12 & 4)) { /* 10mbps link beat good. */ + new_csr6 = 0x82420000; + dev->if_port = 0; + outl(0, ioaddr + CSR13); + outl(0x0003FFFF, ioaddr + CSR14); + outw(t21142_csr15[dev->if_port], ioaddr + CSR15); + outl(t21142_csr13[dev->if_port], ioaddr + CSR13); + } else { + /* Select 100mbps port to check for link beat. */ + new_csr6 = 0x83860000; + dev->if_port = 3; + outl(0, ioaddr + CSR13); + outl(0x0003FF7F, ioaddr + CSR14); + outw(8, ioaddr + CSR15); + outl(1, ioaddr + CSR13); + } + if (tulip_debug > 1) + printk(KERN_INFO"%s: Testing new 21143 media %s.\n", + dev->name, medianame[dev->if_port]); + if (new_csr6 != (tp->csr6 & ~0x00D5)) { + tp->csr6 &= 0x00D5; + tp->csr6 |= new_csr6; + outl(0x0301, ioaddr + CSR12); + outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id); + outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id); + } + next_tick = 3*HZ; + } + if (tp->cur_tx - tp->dirty_tx > 0 && + jiffies - dev->trans_start > TX_TIMEOUT) { + printk(KERN_WARNING "%s: Tx hung, %d vs. %d.\n", + dev->name, tp->cur_tx, tp->dirty_tx); + tulip_tx_timeout(dev); + } + + tp->timer.expires = RUN_AT(next_tick); + add_timer(&tp->timer); +} + +static void t21142_start_nway(struct net_device *dev) +{ + struct tulip_private *tp = (struct tulip_private *)dev->priv; + long ioaddr = dev->base_addr; + int csr14 = ((tp->to_advertise & 0x0180) << 9) | + ((tp->to_advertise&0x0020)<<1) | 0xffbf; + + dev->if_port = 0; + tp->nway = tp->mediasense = 1; + tp->nwayset = tp->lpar = 0; + if (debug > 1) + printk(KERN_DEBUG "%s: Restarting 21143 autonegotiation, %8.8x.\n", + dev->name, csr14); + outl(0x0001, ioaddr + CSR13); + outl(csr14, ioaddr + CSR14); + tp->csr6 = 0x82420000 | (tp->to_advertise & 0x0040 ? 0x0200 : 0); + outl_CSR6(tp->csr6, ioaddr, tp->chip_id); + if (tp->mtable && tp->mtable->csr15dir) { + outl(tp->mtable->csr15dir, ioaddr + CSR15); + outl(tp->mtable->csr15val, ioaddr + CSR15); + } else + outw(0x0008, ioaddr + CSR15); + outl(0x1301, ioaddr + CSR12); /* Trigger NWAY. */ +} + +static void t21142_lnk_change(struct net_device *dev, int csr5) +{ + struct tulip_private *tp = (struct tulip_private *)dev->priv; + long ioaddr = dev->base_addr; + int csr12 = inl(ioaddr + CSR12); + + if (tulip_debug > 1) + printk(KERN_INFO"%s: 21143 link status interrupt %8.8x, CSR5 %x, " + "%8.8x.\n", dev->name, csr12, csr5, inl(ioaddr + CSR14)); + + /* If NWay finished and we have a negotiated partner capability. */ + if (tp->nway && !tp->nwayset && (csr12 & 0x7000) == 0x5000) { + int setup_done = 0; + tp->lpar = csr12 >> 16; + tp->nwayset = 1; + if (csr12 & 0x01000000) dev->if_port = 5; + else if (csr12 & 0x00800000) dev->if_port = 3; + else if (csr12 & 0x00400000) dev->if_port = 4; + else if (csr12 & 0x00200000) dev->if_port = 0; + else { + tp->nwayset = 0; + if ( ! (csr12 & 2)) dev->if_port = 3; + else if ( ! (csr12 & 4)) dev->if_port = 0; + } + tp->full_duplex = (media_cap[tp->default_port] & MediaAlwaysFD) ? 1:0; + + if (tulip_debug > 1) { + if (tp->nwayset) + printk(KERN_INFO "%s: Switching to %s based on link partner " + "advertisement %4.4x.\n", + dev->name, medianame[dev->if_port], tp->lpar); + else + printk(KERN_INFO "%s: Switching to %s based on link beat " + "status of %4.4x.\n", + dev->name, medianame[dev->if_port], csr12); + } + + if (tp->mtable) { + int i; + for (i = 0; i < tp->mtable->leafcount; i++) + if (tp->mtable->mleaf[i].media == dev->if_port) { + tp->cur_index = i; + select_media(dev, 0); + setup_done = 1; + break; + } + } + if ( ! setup_done) { + tp->csr6 = dev->if_port & 1 ? 0x83860000 : 0x82420000; + if (tp->full_duplex) + tp->csr6 |= 0x0200; + outw(0x0000, ioaddr + CSR13); + outw(0x0000, ioaddr + CSR14); + } + outl_CSR6(tp->csr6 | 0x0000, ioaddr, tp->chip_id); + if (debug > 2) + printk(KERN_DEBUG "%s: Restarting Tx and Rx, CSR5 is %8.8x.\n", + dev->name, inl(ioaddr + CSR5)); + outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id); + } else if ((tp->nwayset && (csr5 & 0x08000000) + && (dev->if_port == 3 || dev->if_port == 5) + && (csr12 & 2) == 2) || + (tp->nway && (csr5 & (TPLnkFail)))) { + /* Link blew? Maybe restart NWay. */ + del_timer(&tp->timer); + t21142_start_nway(dev); + tp->timer.expires = RUN_AT(3*HZ); + add_timer(&tp->timer); + } else if (dev->if_port == 3 || dev->if_port == 5) { + if (tulip_debug > 1) + printk(KERN_INFO"%s: 21143 %s link beat %s.\n", + dev->name, medianame[dev->if_port], + (csr12 & 2) ? "failed" : "good"); + if ((csr12 & 2) && ! tp->medialock) { + del_timer(&tp->timer); + t21142_start_nway(dev); + tp->timer.expires = RUN_AT(3*HZ); + add_timer(&tp->timer); + } + } else if (dev->if_port == 0 || dev->if_port == 4) { + if ((csr12 & 4) == 0) + printk(KERN_INFO"%s: 21143 10baseT link beat good.\n", + dev->name); + } else if (!(csr12 & 4)) { /* 10mbps link beat good. */ + if (tulip_debug) + printk(KERN_INFO"%s: 21143 10mbps sensed media.\n", + dev->name); + dev->if_port = 0; + } else if (tp->nwayset) { + if (tulip_debug) + printk(KERN_INFO"%s: 21143 using NWay-set %s, csr6 %8.8x.\n", + dev->name, medianame[dev->if_port], tp->csr6); + } else { /* 100mbps link beat good. */ + if (tulip_debug) + printk(KERN_INFO"%s: 21143 100baseTx sensed media.\n", + dev->name); + dev->if_port = 3; + tp->csr6 = 0x83860000; + outl(0x0003FF7F, ioaddr + CSR14); + outl(0x0301, ioaddr + CSR12); + outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id); + outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id); + } +} + +static void mxic_timer(unsigned long data) +{ + struct net_device *dev = (struct net_device *)data; + struct tulip_private *tp = (struct tulip_private *)dev->priv; + long ioaddr = dev->base_addr; + int next_tick = 60*HZ; + + if (tulip_debug > 3) { + printk(KERN_INFO"%s: MXIC negotiation status %8.8x.\n", dev->name, + inl(ioaddr + CSR12)); + } + if (next_tick) { + tp->timer.expires = RUN_AT(next_tick); + add_timer(&tp->timer); + } +} + +static void pnic_timer(unsigned long data) +{ + struct net_device *dev = (struct net_device *)data; + struct tulip_private *tp = (struct tulip_private *)dev->priv; + long ioaddr = dev->base_addr; + int csr12 = inl(ioaddr + CSR12); + int next_tick = 60*HZ; + int new_csr6 = tp->csr6 & ~0x40C40200; + + if (media_cap[dev->if_port] & MediaIsMII) { + int negotiated = mdio_read(dev, tp->phys[0], 5) & tp->advertising[0]; + + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: PNIC negotiated capability %8.8x, " + "CSR5 %8.8x.\n", + dev->name, negotiated, inl(ioaddr + CSR5)); + + if (negotiated & 0x0380) /* 10 vs 100mbps */ + new_csr6 |= 0x810E0000; + else + new_csr6 |= 0x814E0000; + if (((negotiated & 0x0300) == 0x0100) /* Duplex */ + || (negotiated & 0x00C0) == 0x0040 + || tp->full_duplex_lock) { + tp->full_duplex = 1; + new_csr6 |= 0x0200; + } + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: PNIC MII PHY status %4.4x, Link " + "partner report %4.4x, csr6 %8.8x/%8.8x.\n", + dev->name, mdio_read(dev, tp->phys[0], 1), negotiated, + tp->csr6, inl(ioaddr + CSR6)); + } else { + int phy_reg = inl(ioaddr + 0xB8); + int csr5 = inl(ioaddr + CSR5); + + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: PNIC PHY status %8.8x, CSR5 %8.8x.\n", + dev->name, phy_reg, csr5); + + if (phy_reg & 0x04000000) { /* Remote link fault */ + /*outl(0x0201F078, ioaddr + 0xB8);*/ + next_tick = 3*HZ; + } + if (inl(ioaddr + CSR5) & TPLnkFail) { /* 100baseTx link beat */ + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: %s link beat failed, CSR12 %4.4x, " + "CSR5 %8.8x, PHY %3.3x.\n", + dev->name, medianame[dev->if_port], csr12, + inl(ioaddr + CSR5), inl(ioaddr + 0xB8)); + if (tp->medialock) { + } else if (dev->if_port == 0) { + dev->if_port = 3; + outl(0x33, ioaddr + CSR12); + new_csr6 = 0x01860000; + outl(0x1F868, ioaddr + 0xB8); + } else { + dev->if_port = 0; + outl(0x32, ioaddr + CSR12); + new_csr6 = 0x00420000; + outl(0x1F078, ioaddr + 0xB8); + } + new_csr6 |= (tp->csr6 & 0xfdff); + next_tick = 3*HZ; + } else + new_csr6 = tp->csr6; + if (tp->full_duplex_lock || (phy_reg & 0x30000000) != 0) { + tp->full_duplex = 1; + new_csr6 |= 0x00000200; + } + } + if (tp->csr6 != new_csr6) { + tp->csr6 = new_csr6; + outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id); /* Restart Tx */ + outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id); + dev->trans_start = jiffies; + if (tulip_debug > 1) + printk(KERN_INFO "%s: Changing PNIC configuration to %s-duplex, " + "CSR6 %8.8x.\n", + dev->name, tp->full_duplex ? "full" : "half", new_csr6); + } + tp->timer.expires = RUN_AT(next_tick); + add_timer(&tp->timer); +} + +static void comet_timer(unsigned long data) +{ + struct net_device *dev = (struct net_device *)data; + struct tulip_private *tp = (struct tulip_private *)dev->priv; + long ioaddr = dev->base_addr; + int next_tick = 60*HZ; + + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: Comet link status %4.4x partner capability " + "%4.4x.\n", + dev->name, inl(ioaddr + 0xB8), inl(ioaddr + 0xC8)); + tp->timer.expires = RUN_AT(next_tick); + add_timer(&tp->timer); +} + +static void tulip_tx_timeout(struct net_device *dev) +{ + struct tulip_private *tp = (struct tulip_private *)dev->priv; + long ioaddr = dev->base_addr; + + if (media_cap[dev->if_port] & MediaIsMII) { + /* Do nothing -- the media monitor should handle this. */ + if (tulip_debug > 1) + printk(KERN_WARNING "%s: Transmit timeout using MII device.\n", + dev->name); + } else if (tp->chip_id == DC21040) { + if ( !tp->medialock && inl(ioaddr + CSR12) & 0x0002) { + dev->if_port = (dev->if_port == 2 ? 0 : 2); + printk(KERN_INFO "%s: transmit timed out, switching to " + "%s.\n", + dev->name, medianame[dev->if_port]); + select_media(dev, 0); + } + dev->trans_start = jiffies; + return; + } else if (tp->chip_id == DC21041) { + int csr12 = inl(ioaddr + CSR12); + + printk(KERN_WARNING "%s: 21041 transmit timed out, status %8.8x, " + "CSR12 %8.8x, CSR13 %8.8x, CSR14 %8.8x, resetting...\n", + dev->name, inl(ioaddr + CSR5), csr12, + inl(ioaddr + CSR13), inl(ioaddr + CSR14)); + tp->mediasense = 1; + if ( ! tp->medialock) { + if (dev->if_port == 1 || dev->if_port == 2) + if (csr12 & 0x0004) { + dev->if_port = 2 - dev->if_port; + } else + dev->if_port = 0; + else + dev->if_port = 1; + select_media(dev, 0); + } + } else if (tp->chip_id == DC21140 || tp->chip_id == DC21142 + || tp->chip_id == MX98713 || tp->chip_id == COMPEX9881) { + printk(KERN_WARNING "%s: 21140 transmit timed out, status %8.8x, " + "SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n", + dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12), + inl(ioaddr + CSR13), inl(ioaddr + CSR14), inl(ioaddr + CSR15)); + if ( ! tp->medialock && tp->mtable) { + do + --tp->cur_index; + while (tp->cur_index >= 0 + && (media_cap[tp->mtable->mleaf[tp->cur_index].media] + & MediaIsFD)); + if (--tp->cur_index < 0) { + /* We start again, but should instead look for default. */ + tp->cur_index = tp->mtable->leafcount - 1; + } + select_media(dev, 0); + printk(KERN_WARNING "%s: transmit timed out, switching to %s " + "media.\n", dev->name, medianame[dev->if_port]); + } + } else { + printk(KERN_WARNING "%s: Transmit timed out, status %8.8x, CSR12 " + "%8.8x, resetting...\n", + dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12)); + dev->if_port = 0; + } + +#if defined(way_too_many_messages) + if (tulip_debug > 3) { + int i; + for (i = 0; i < RX_RING_SIZE; i++) { + u8 *buf = (u8 *)(tp->rx_ring[i].buffer1); + int j; + printk(KERN_DEBUG "%2d: %8.8x %8.8x %8.8x %8.8x " + "%2.2x %2.2x %2.2x.\n", + i, (unsigned int)tp->rx_ring[i].status, + (unsigned int)tp->rx_ring[i].length, + (unsigned int)tp->rx_ring[i].buffer1, + (unsigned int)tp->rx_ring[i].buffer2, + buf[0], buf[1], buf[2]); + for (j = 0; buf[j] != 0xee && j < 1600; j++) + if (j < 100) printk(" %2.2x", buf[j]); + printk(" j=%d.\n", j); + } + printk(KERN_DEBUG " Rx ring %8.8x: ", (int)tp->rx_ring); + for (i = 0; i < RX_RING_SIZE; i++) + printk(" %8.8x", (unsigned int)tp->rx_ring[i].status); + printk("\n" KERN_DEBUG " Tx ring %8.8x: ", (int)tp->tx_ring); + for (i = 0; i < TX_RING_SIZE; i++) + printk(" %8.8x", (unsigned int)tp->tx_ring[i].status); + printk("\n"); + } +#endif + + /* Stop and restart the chip's Tx processes . */ + outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id); + outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id); + /* Trigger an immediate transmit demand. */ + outl(0, ioaddr + CSR1); + + dev->trans_start = jiffies; + tp->stats.tx_errors++; + return; +} + +/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ +static void tulip_init_ring(struct net_device *dev) +{ + struct tulip_private *tp = (struct tulip_private *)dev->priv; + int i; + + tp->tx_full = 0; + tp->cur_rx = tp->cur_tx = 0; + tp->dirty_rx = tp->dirty_tx = 0; + + for (i = 0; i < RX_RING_SIZE; i++) { + tp->rx_ring[i].status = 0x00000000; + tp->rx_ring[i].length = PKT_BUF_SZ; + tp->rx_ring[i].buffer2 = virt_to_bus(&tp->rx_ring[i+1]); + tp->rx_skbuff[i] = NULL; + } + /* Mark the last entry as wrapping the ring. */ + tp->rx_ring[i-1].length = PKT_BUF_SZ | DESC_RING_WRAP; + tp->rx_ring[i-1].buffer2 = virt_to_bus(&tp->rx_ring[0]); + + for (i = 0; i < RX_RING_SIZE; i++) { + /* Note the receive buffer must be longword aligned. + dev_alloc_skb() provides 16 byte alignment. But do *not* + use skb_reserve() to align the IP header! */ + struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ); + tp->rx_skbuff[i] = skb; + if (skb == NULL) + break; + skb->dev = dev; /* Mark as being used by this device. */ + tp->rx_ring[i].status = DescOwned; /* Owned by Tulip chip */ + tp->rx_ring[i].buffer1 = virt_to_bus(skb->tail); + } + tp->dirty_rx = (unsigned int)(i - RX_RING_SIZE); + + /* The Tx buffer descriptor is filled in as needed, but we + do need to clear the ownership bit. */ + for (i = 0; i < TX_RING_SIZE; i++) { + tp->tx_skbuff[i] = 0; + tp->tx_ring[i].status = 0x00000000; + tp->tx_ring[i].buffer2 = virt_to_bus(&tp->tx_ring[i+1]); +#ifdef CARDBUS + if (tp->chip_id == X3201_3) + tp->tx_aligned_skbuff[i] = dev_alloc_skb(PKT_BUF_SZ); +#endif CARDBUS + } + tp->tx_ring[i-1].buffer2 = virt_to_bus(&tp->tx_ring[0]); +} + +static int +tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct tulip_private *tp = (struct tulip_private *)dev->priv; + 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; + tulip_tx_timeout(dev); + return 1; + } + + /* Caution: the write order is important here, set the base address + with the "ownership" bits last. */ + + /* Calculate the next Tx descriptor entry. */ + entry = tp->cur_tx % TX_RING_SIZE; + + tp->tx_skbuff[entry] = skb; +#ifdef CARDBUS + if (tp->chip_id == X3201_3) { + memcpy(tp->tx_aligned_skbuff[entry]->data,skb->data,skb->len); + tp->tx_ring[entry].buffer1 = virt_to_bus(tp->tx_aligned_skbuff[entry]->data); + } else +#endif + tp->tx_ring[entry].buffer1 = virt_to_bus(skb->data); + + if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */ + flag = 0x60000000; /* No interrupt */ + } else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) { + flag = 0xe0000000; /* Tx-done intr. */ + } else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) { + flag = 0x60000000; /* No Tx-done intr. */ + } else { + /* Leave room for set_rx_mode() to fill entries. */ + flag = 0xe0000000; /* Tx-done intr. */ + tp->tx_full = 1; + } + if (entry == TX_RING_SIZE-1) + flag |= 0xe0000000 | DESC_RING_WRAP; + + tp->tx_ring[entry].length = skb->len | flag; + tp->tx_ring[entry].status = DescOwned; /* Pass ownership to the chip. */ + tp->cur_tx++; + if ( ! tp->tx_full) + clear_bit(0, (void*)&dev->tbusy); + + /* Trigger an immediate transmit demand. */ + outl(0, dev->base_addr + CSR1); + + dev->trans_start = jiffies; + + return 0; +} + +/* The interrupt handler does all of the Rx thread work and cleans up + after the Tx thread. */ +static void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *)dev_instance; + struct tulip_private *tp = (struct tulip_private *)dev->priv; + long ioaddr = dev->base_addr; + int csr5, work_budget = max_interrupt_work; + +#if defined(__i386__) && defined(SMP_CHECK) + if (test_and_set_bit(0, (void*)&dev->interrupt)) { + printk(KERN_ERR "%s: Duplicate entry of the interrupt handler by " + "processor %d.\n", + dev->name, hard_smp_processor_id()); + dev->interrupt = 0; + return; + } +#else + if (dev->interrupt) { + printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name); + return; + } + dev->interrupt = 1; +#endif + + do { + csr5 = inl(ioaddr + CSR5); + /* Acknowledge all of the current interrupt sources ASAP. */ + outl(csr5 & 0x0001ffff, ioaddr + CSR5); + + if (tulip_debug > 4) + printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", + dev->name, csr5, inl(dev->base_addr + CSR5)); + + if (csr5 == 0xffffffff) + break; /* all bits set, assume PCMCIA card removed */ + + if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) + break; + + if (csr5 & (RxIntr | RxNoBuf)) + work_budget -= tulip_rx(dev); + + if (csr5 & (TxNoBuf | TxDied | TxIntr)) { + unsigned int dirty_tx; + + for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; + dirty_tx++) { + int entry = dirty_tx % TX_RING_SIZE; + int status = tp->tx_ring[entry].status; + + if (status < 0) + break; /* It still hasn't been Txed */ + /* Check for Rx filter setup frames. */ + if (tp->tx_skbuff[entry] == NULL) + continue; + + if (status & 0x8000) { + /* There was an major error, log it. */ +#ifndef final_version + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", + dev->name, status); +#endif + tp->stats.tx_errors++; + if (status & 0x4104) tp->stats.tx_aborted_errors++; + if (status & 0x0C00) tp->stats.tx_carrier_errors++; + if (status & 0x0200) tp->stats.tx_window_errors++; + if (status & 0x0002) tp->stats.tx_fifo_errors++; + if ((status & 0x0080) && tp->full_duplex == 0) + tp->stats.tx_heartbeat_errors++; +#ifdef ETHER_STATS + if (status & 0x0100) tp->stats.collisions16++; +#endif + } else { +#ifdef ETHER_STATS + if (status & 0x0001) tp->stats.tx_deferred++; +#endif + tp->stats.tx_bytes += tp->tx_ring[entry].length & 0x7ff; + tp->stats.collisions += (status >> 3) & 15; + tp->stats.tx_packets++; + } + + /* Free the original skb. */ + dev_free_skb(tp->tx_skbuff[entry]); + tp->tx_skbuff[entry] = 0; + } + +#ifndef final_version + if (tp->cur_tx - dirty_tx > TX_RING_SIZE) { + printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", + dev->name, dirty_tx, tp->cur_tx, tp->tx_full); + dirty_tx += TX_RING_SIZE; + } +#endif + + if (tp->tx_full && dev->tbusy + && tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) { + /* The ring is no longer full, clear tbusy. */ + tp->tx_full = 0; + dev->tbusy = 0; + mark_bh(NET_BH); + } + + tp->dirty_tx = dirty_tx; + if (csr5 & TxDied) { + if (tulip_debug > 2) + printk(KERN_WARNING "%s: The transmitter stopped." + " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", + dev->name, csr5, inl(ioaddr + CSR6), tp->csr6); + outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id); + outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id); + } + } + + /* Log errors. */ + if (csr5 & AbnormalIntr) { /* Abnormal error summary bit. */ + if (csr5 == 0xffffffff) + break; + if (csr5 & TxJabber) tp->stats.tx_errors++; + if (csr5 & TxFIFOUnderflow) { + if ((tp->csr6 & 0xC000) != 0xC000) + tp->csr6 += 0x4000; /* Bump up the Tx threshold */ + else + tp->csr6 |= 0x00200000; /* Store-n-forward. */ + /* Restart the transmit process. */ + outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id); + outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id); + } + if (csr5 & RxDied) { /* Missed a Rx frame. */ + tp->stats.rx_errors++; + tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; + outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id); + } + if (csr5 & TimerInt) { + if (tulip_debug > 2) + printk(KERN_ERR "%s: Re-enabling interrupts, %8.8x.\n", + dev->name, csr5); + outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); + } + if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) { + if ( tp->chip_id == DC21142) + t21142_lnk_change(dev, csr5); + } + /* Clear all error sources, included undocumented ones! */ + outl(0x0800f7ba, ioaddr + CSR5); + } + if (--work_budget < 0) { + if (tulip_debug > 1) + printk(KERN_WARNING "%s: Too much work during an interrupt, " + "csr5=0x%8.8x.\n", dev->name, csr5); + /* Acknowledge all interrupt sources. */ + outl(0x8001ffff, ioaddr + CSR5); +#ifdef notdef + /* Clear all but standard interrupt sources. */ + outl((~csr5) & 0x0001ebef, ioaddr + CSR7); +#endif + break; + } + } while (1); + + if (tulip_debug > 3) + printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n", + dev->name, inl(ioaddr + CSR5)); + +#if defined(__i386__) + clear_bit(0, (void*)&dev->interrupt); +#else + dev->interrupt = 0; +#endif + return; +} + +static int +tulip_rx(struct net_device *dev) +{ + struct tulip_private *tp = (struct tulip_private *)dev->priv; + int entry = tp->cur_rx % RX_RING_SIZE; + int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx; + int work_done = 0; + + if (tulip_debug > 4) + printk(KERN_DEBUG " In tulip_rx(), entry %d %8.8x.\n", entry, + tp->rx_ring[entry].status); + /* If we own the next entry, it's a new packet. Send it up. */ + while (tp->rx_ring[entry].status >= 0) { + s32 status = tp->rx_ring[entry].status; + + if (tulip_debug > 5) + printk(KERN_DEBUG " In tulip_rx(), entry %d %8.8x.\n", entry, + tp->rx_ring[entry].status); + if (--rx_work_limit < 0) + break; + if ((status & 0x38008300) != 0x0300) { + if ((status & 0x38000300) != 0x0300) { + /* Ingore earlier buffers. */ + if ((status & 0xffff) != 0x7fff) { + if (tulip_debug > 1) + printk(KERN_WARNING "%s: Oversized Ethernet frame " + "spanned multiple buffers, status %8.8x!\n", + dev->name, status); + tp->stats.rx_length_errors++; + } + } else if (status & RxDescFatalErr) { + /* There was a fatal error. */ + if (tulip_debug > 2) + printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", + dev->name, status); + tp->stats.rx_errors++; /* end of a packet.*/ + if (status & 0x0890) tp->stats.rx_length_errors++; + if (status & 0x0004) tp->stats.rx_frame_errors++; + if (status & 0x0002) tp->stats.rx_crc_errors++; + if (status & 0x0001) tp->stats.rx_fifo_errors++; + } + } else { + /* Omit the four octet CRC from the length. */ + short pkt_len = ((status >> 16) & 0x7ff) - 4; + struct sk_buff *skb; + +#ifndef final_version + if (pkt_len > 1518) { + printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n", + dev->name, pkt_len, pkt_len); + pkt_len = 1518; + tp->stats.rx_length_errors++; + } +#endif + /* Check if the packet is long enough to accept without copying + to a minimally-sized skbuff. */ + if (pkt_len < rx_copybreak + && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { + skb->dev = dev; + skb_reserve(skb, 2); /* 16 byte align the IP header */ +#if ! defined(__alpha__) + eth_copy_and_sum(skb, bus_to_virt(tp->rx_ring[entry].buffer1), + pkt_len, 0); + skb_put(skb, pkt_len); +#else + memcpy(skb_put(skb, pkt_len), + bus_to_virt(tp->rx_ring[entry].buffer1), pkt_len); +#endif + work_done++; + } else { /* Pass up the skb already on the Rx ring. */ + char *temp = skb_put(skb = tp->rx_skbuff[entry], pkt_len); + tp->rx_skbuff[entry] = NULL; +#ifndef final_version + if (bus_to_virt(tp->rx_ring[entry].buffer1) != temp) + printk(KERN_ERR "%s: Internal fault: The skbuff addresses " + "do not match in tulip_rx: %p vs. %p / %p.\n", + dev->name, bus_to_virt(tp->rx_ring[entry].buffer1), + skb->head, temp); +#endif + } + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + dev->last_rx = jiffies; + tp->stats.rx_packets++; + tp->stats.rx_bytes += pkt_len; + } + entry = (++tp->cur_rx) % RX_RING_SIZE; + } + + /* Refill the Rx ring buffers. */ + for (; tp->cur_rx - tp->dirty_rx > 0; tp->dirty_rx++) { + entry = tp->dirty_rx % RX_RING_SIZE; + if (tp->rx_skbuff[entry] == NULL) { + struct sk_buff *skb; + skb = tp->rx_skbuff[entry] = dev_alloc_skb(PKT_BUF_SZ); + if (skb == NULL) + break; + skb->dev = dev; /* Mark as being used by this device. */ + tp->rx_ring[entry].buffer1 = virt_to_bus(skb->tail); + work_done++; + } + tp->rx_ring[entry].status = DescOwned; + } + + return work_done; +} + +static void +tulip_down(struct net_device *dev) +{ + long ioaddr = dev->base_addr; + struct tulip_private *tp = (struct tulip_private *)dev->priv; + + dev->start = 0; + dev->tbusy = 1; + + /* Disable interrupts by clearing the interrupt mask. */ + outl(0x00000000, ioaddr + CSR7); + /* Stop the chip's Tx and Rx processes. */ + outl_CSR6(inl(ioaddr + CSR6) & ~0x2002, ioaddr, tp->chip_id); + /* 21040 -- Leave the card in 10baseT state. */ + if (tp->chip_id == DC21040) + outl(0x00000004, ioaddr + CSR13); + + if (inl(ioaddr + CSR6) != 0xffffffff) + tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; + + del_timer(&tp->timer); + + dev->if_port = tp->saved_if_port; +} + +static int +tulip_close(struct net_device *dev) +{ + long ioaddr = dev->base_addr; + struct tulip_private *tp = (struct tulip_private *)dev->priv; + int i; + + if (tulip_debug > 1) + printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", + dev->name, inl(ioaddr + CSR5)); + + if (dev->start) + tulip_down(dev); + + free_irq(dev->irq, dev); + + /* Free all the skbuffs in the Rx queue. */ + for (i = 0; i < RX_RING_SIZE; i++) { + struct sk_buff *skb = tp->rx_skbuff[i]; + tp->rx_skbuff[i] = 0; + tp->rx_ring[i].status = 0; /* Not owned by Tulip chip. */ + tp->rx_ring[i].length = 0; + tp->rx_ring[i].buffer1 = 0xBADF00D0; /* An invalid address. */ + if (skb) { + dev_free_skb(skb); + } + } + for (i = 0; i < TX_RING_SIZE; i++) { + if (tp->tx_skbuff[i]) + dev_free_skb(tp->tx_skbuff[i]); + tp->tx_skbuff[i] = 0; + } + + MOD_DEC_USE_COUNT; + tp->open = 0; + return 0; +} + +static struct net_device_stats *tulip_get_stats(struct net_device *dev) +{ + struct tulip_private *tp = (struct tulip_private *)dev->priv; + long ioaddr = dev->base_addr; + + if (dev->start) + tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; + + return &tp->stats; +} + +#ifdef HAVE_PRIVATE_IOCTL +/* Provide ioctl() calls to examine the MII xcvr state. */ +static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct tulip_private *tp = (struct tulip_private *)dev->priv; + long ioaddr = dev->base_addr; + u16 *data = (u16 *)&rq->ifr_data; + int phy = tp->phys[0] & 0x1f; + long flags; + + switch(cmd) { + case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ + if (tp->mii_cnt) + data[0] = phy; + else if (tp->chip_id == DC21142) /* 21142 pseudo-MII */ + data[0] = 32; + else if (tp->chip_id == PNIC2) + data[0] = 32; + else if (tp->chip_id == COMET) + data[0] = 1; + else + return -ENODEV; + return 0; + case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ + if (data[0] == 32 && + (tp->chip_id == DC21142 || tp->chip_id == PNIC2)) { + int csr12 = inl(ioaddr + CSR12); + int csr14 = inl(ioaddr + CSR14); + switch (data[1]) { + case 0: { + data[3] = (csr14<<5) & 0x1000; + break; } + case 1: + data[3] = 0x7848 + ((csr12&0x7000) == 0x5000 ? 0x20 : 0) + + (csr12&0x06 ? 0x04 : 0); + break; + case 4: { + data[3] = ((csr14>>9)&0x0380) + + ((inl(ioaddr + CSR6)>>3)&0x0040) +((csr14>>1)&0x20) + 1; + break; + } + case 5: data[3] = csr12 >> 16; break; + default: data[3] = 0; break; + } + } else { + save_flags(flags); + cli(); + data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f); + restore_flags(flags); + } + return 0; + case SIOCDEVPRIVATE+2: /* Write the specified MII register */ +#if defined(CAP_NET_ADMIN) + if (!capable(CAP_NET_ADMIN)) + return -EPERM; +#else + if (!suser()) + return -EPERM; +#endif + if (data[0] == 32 && tp->chip_id == DC21142) { + if (data[1] == 5) + tp->to_advertise = data[2]; + } else { + save_flags(flags); + cli(); + mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]); + restore_flags(flags); + } + return 0; + default: + return -EOPNOTSUPP; + } + + return -EOPNOTSUPP; +} +#endif /* HAVE_PRIVATE_IOCTL */ + +/* Set or clear the multicast filter for this adaptor. + Note that we only use exclusion around actually queueing the + new frame, not around filling tp->setup_frame. This is non-deterministic + when re-entered but still correct. */ + +/* The little-endian AUTODIN32 ethernet CRC calculation. + N.B. Do not use for bulk data, use a table-based routine instead. + This is common code and should be moved to net/core/crc.c */ +static unsigned const ethernet_polynomial_le = 0xedb88320U; +static inline u32 ether_crc_le(int length, unsigned char *data) +{ + u32 crc = 0xffffffff; /* Initial value. */ + while(--length >= 0) { + unsigned char current_octet = *data++; + int bit; + for (bit = 8; --bit >= 0; current_octet >>= 1) { + if ((crc ^ current_octet) & 1) { + crc >>= 1; + crc ^= ethernet_polynomial_le; + } else + crc >>= 1; + } + } + return crc; +} +static unsigned const ethernet_polynomial = 0x04c11db7U; +static inline u32 ether_crc(int length, unsigned char *data) +{ + int crc = -1; + + while(--length >= 0) { + unsigned char current_octet = *data++; + int bit; + for (bit = 0; bit < 8; bit++, current_octet >>= 1) + crc = (crc << 1) ^ + ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); + } + return crc; +} + +static void set_rx_mode(struct net_device *dev) +{ + long ioaddr = dev->base_addr; + int csr6 = inl(ioaddr + CSR6) & ~0x00D5; + struct tulip_private *tp = (struct tulip_private *)dev->priv; + + tp->csr6 &= ~0x00D5; + if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ + tp->csr6 |= 0x00C0; + csr6 |= 0x00C0; + /* Unconditionally log net taps. */ + printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name); + } else if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) { + /* Too many to filter well -- accept all multicasts. */ + tp->csr6 |= 0x0080; + csr6 |= 0x0080; + } else if (tulip_tbl[tp->chip_id].flags & MC_HASH_ONLY) { + /* Some work-alikes have only a 64-entry hash filter table. */ + /* Should verify correctness on big-endian/__powerpc__ */ + struct dev_mc_list *mclist; + int i; + u32 mc_filter[2]; /* Multicast hash filter */ + if (dev->mc_count > 64) { /* Arbitrary non-effective limit. */ + tp->csr6 |= 0x0080; + csr6 |= 0x0080; + } else { + mc_filter[1] = mc_filter[0] = 0; + for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + i++, mclist = mclist->next) + set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr)>>26, mc_filter); + if (tp->chip_id == AX88140) { + outl(2, ioaddr + CSR13); + outl(mc_filter[0], ioaddr + CSR14); + outl(3, ioaddr + CSR13); + outl(mc_filter[1], ioaddr + CSR14); + } else if (tp->chip_id == COMET) { /* Has a simple hash filter. */ + outl(mc_filter[0], ioaddr + 0xAC); + outl(mc_filter[1], ioaddr + 0xB0); + } + } + } else { + u16 *eaddrs, *setup_frm = tp->setup_frame; + struct dev_mc_list *mclist; + u32 tx_flags = 0x08000000 | 192; + int i; + + /* Note that only the low-address shortword of setup_frame is valid! + The values are doubled for big-endian architectures. */ + if ((dev->mc_count > 14) || ((dev->mc_count > 6) && (tp->chip_id == X3201_3))) { /* Must use a multicast hash table. */ + u16 hash_table[32]; + tx_flags = 0x08400000 | 192; /* Use hash filter. */ + memset(hash_table, 0, sizeof(hash_table)); + set_bit(255, hash_table); /* Broadcast entry */ + /* This should work on big-endian machines as well. */ + for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + i++, mclist = mclist->next) + set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff, + hash_table); + for (i = 0; i < 32; i++) { + *setup_frm++ = hash_table[i]; + *setup_frm++ = hash_table[i]; + } + setup_frm = &tp->setup_frame[13*6]; + } else if(tp->chip_id != X3201_3) { + /* We have <= 14 addresses so we can use the wonderful + 16 address perfect filtering of the Tulip. */ + for (i = 0, mclist = dev->mc_list; i < dev->mc_count; + i++, mclist = mclist->next) { + eaddrs = (u16 *)mclist->dmi_addr; + *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; + *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; + *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; + } + /* Fill the unused entries with the broadcast address. */ + memset(setup_frm, 0xff, (15-i)*12); + setup_frm = &tp->setup_frame[15*6]; + } else { + /* fill the first two table entries with our address */ + eaddrs = (u16 *)dev->dev_addr; + for(i=0; i<2; i++) { + *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; + *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; + *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; + } + /* Double fill each entry to accomodate chips that */ + /* don't like to parse these correctly */ + for (i=0, mclist=dev->mc_list; imc_count; + i++, mclist=mclist->next) { + eaddrs = (u16 *)mclist->dmi_addr; + *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; + *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; + *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; + *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; + *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; + *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; + } + i=((i+1)*2); + /* Fill the unused entries with the broadcast address. */ + memset(setup_frm, 0xff, (15-i)*12); + setup_frm = &tp->setup_frame[15*6]; + } + + /* Fill the final entry with our physical address. */ + eaddrs = (u16 *)dev->dev_addr; + *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; + *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; + *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; + /* Now add this frame to the Tx list. */ + if (tp->cur_tx - tp->dirty_tx > TX_RING_SIZE - 2) { + /* Same setup recently queued, we need not add it. */ + } else { + unsigned long flags; + unsigned int entry, dummy = -1; + + save_flags(flags); cli(); + entry = tp->cur_tx++ % TX_RING_SIZE; + + if (entry != 0) { + /* Avoid a chip errata by prefixing a dummy entry. */ + tp->tx_skbuff[entry] = 0; + tp->tx_ring[entry].length = + (entry == TX_RING_SIZE-1) ? DESC_RING_WRAP : 0; + tp->tx_ring[entry].buffer1 = 0; + /* race with chip, set DescOwned later */ + dummy = entry; + entry = tp->cur_tx++ % TX_RING_SIZE; + } + + tp->tx_skbuff[entry] = 0; + /* Put the setup frame on the Tx list. */ + if (entry == TX_RING_SIZE-1) + tx_flags |= DESC_RING_WRAP; /* Wrap ring. */ + tp->tx_ring[entry].length = tx_flags; + if(tp->chip_id == X3201_3) + tp->tx_ring[entry].buffer1 = (virt_to_bus(tp->setup_frame) + 4); + else + tp->tx_ring[entry].buffer1 = virt_to_bus(tp->setup_frame); + tp->tx_ring[entry].status = DescOwned; + if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) { + set_bit(0, (void*)&dev->tbusy); + tp->tx_full = 1; + } + if (dummy >= 0) + tp->tx_ring[dummy].status = DescOwned; + restore_flags(flags); + /* Trigger an immediate transmit demand. */ + outl(0, ioaddr + CSR1); + } + } + outl_CSR6(csr6 | 0x0000, ioaddr, tp->chip_id); +} + +#ifdef CARDBUS + +#include + +static dev_node_t *tulip_attach(dev_locator_t *loc) +{ + struct net_device *dev; + u16 dev_id; + u16 vendor_id; + u32 io; + u8 bus, devfn, irq; + + if (loc->bus != LOC_PCI) return NULL; + bus = loc->b.pci.bus; devfn = loc->b.pci.devfn; + 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); + pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq); + pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor_id); + if (dev_id == 0x0003 && vendor_id == 0x115d) + dev = tulip_probe1(bus, devfn, NULL, io & ~3, irq, X3201_3, 0); + else + dev = tulip_probe1(bus, devfn, NULL, io & ~3, irq, DC21142, 0); + if (dev) { + dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL); + strcpy(node->dev_name, dev->name); + node->major = node->minor = 0; + node->next = NULL; + MOD_INC_USE_COUNT; + return node; + } + return NULL; +} + +static void tulip_suspend(dev_node_t *node) +{ + struct net_device *dev, *next; + printk(KERN_INFO "tulip_suspend(%s)\n", node->dev_name); + for (dev = root_tulip_dev; dev; dev = next) { + next = ((struct tulip_private *)dev->priv)->next_module; + if (strcmp(dev->name, node->dev_name) == 0) break; + } + if (dev) { + struct tulip_private *tp = (struct tulip_private *)dev->priv; + if (tp->open) tulip_down(dev); + } +} + +static void tulip_resume(dev_node_t *node) +{ + struct net_device *dev, *next; + printk(KERN_INFO "tulip_resume(%s)\n", node->dev_name); + for (dev = root_tulip_dev; dev; dev = next) { + next = ((struct tulip_private *)dev->priv)->next_module; + if (strcmp(dev->name, node->dev_name) == 0) break; + } + if (dev) { + struct tulip_private *tp = (struct tulip_private *)dev->priv; + if (tp->open) tulip_up(dev); + } +} + +static void tulip_detach(dev_node_t *node) +{ + struct net_device **devp, **next; + printk(KERN_INFO "tulip_detach(%s)\n", node->dev_name); + for (devp = &root_tulip_dev; *devp; devp = next) { + next = &((struct tulip_private *)(*devp)->priv)->next_module; + if (strcmp((*devp)->name, node->dev_name) == 0) break; + } + if (*devp) { + struct net_device *dev = *devp; + struct tulip_private *tp = dev->priv; + unregister_netdev(dev); + kfree(dev); + kfree(tp); + *devp = *next; + kfree(node); + MOD_DEC_USE_COUNT; + } +} + +struct driver_operations tulip_ops = { + "tulip_cb", tulip_attach, tulip_suspend, tulip_resume, tulip_detach +}; + +#endif /* Cardbus support */ + +#ifdef MODULE +int init_module(void) +{ +#ifdef CARDBUS + reverse_probe = 0; /* Not used. */ + register_driver(&tulip_ops); + return 0; +#else + return tulip_probe(NULL); +#endif +} + +void cleanup_module(void) +{ + struct net_device *next_dev; + +#ifdef CARDBUS + unregister_driver(&tulip_ops); +#endif + + /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ + while (root_tulip_dev) { + struct tulip_private *tp = (struct tulip_private *)root_tulip_dev->priv; + next_dev = tp->next_module; + unregister_netdev(root_tulip_dev); + release_region(root_tulip_dev->base_addr, + tulip_tbl[tp->chip_id].io_size); + kfree(root_tulip_dev); + root_tulip_dev = next_dev; + } +} + +#endif /* MODULE */ + +/* + * Local variables: + * SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c tulip.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" + * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c tulip.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`" + * cardbus-compile-command: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c tulip.c -o tulip_cb.o -I/usr/src/pcmcia-cs-3.0.9/include/" + * c-indent-level: 4 + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff --git a/drivers/net/pcmcia/wavelan_cs.h b/drivers/net/pcmcia/wavelan_cs.h index 84dc2114d0cd..efc10cc91099 100644 --- a/drivers/net/pcmcia/wavelan_cs.h +++ b/drivers/net/pcmcia/wavelan_cs.h @@ -122,7 +122,7 @@ * Yunzhou Li finished is work. * Joe Finney patched the driver to start * correctly 2.00 cards (2.4 GHz with frequency selection). - * David Hinds integrated the whole in his + * David Hinds integrated the whole in his * Pcmcia package (+ bug corrections). * * I (Jean Tourrilhes - jt@hplb.hpl.hp.com) then started to make some @@ -174,7 +174,7 @@ * Matthew Geier (matthew@cs.su.oz.au), * Remo di Giovanni (remo@cs.su.oz.au), * Mark Hagan (mhagan@wtcpost.daytonoh.NCR.COM), - * David Hinds , + * David Hinds , * Jan Hoogendoorn (c/o marteijn@lucent.com), * Bruce Janson , * Anthony D. Joseph , diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index d09230655989..0b9c4bd3a816 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -83,10 +83,6 @@ /* Enable the bug fix for CEM56 to use modem and ethernet simultaneously */ #define CEM56_FIX -#if !defined(PCMCIA_DEBUG) && 0 - #define PCMCIA_DEBUG 4 -#endif - #include #include #include @@ -250,6 +246,9 @@ static char *if_names[] = { "Auto", "10BaseT", "10Base2", "AUI", "100BaseT" }; #ifdef PCMCIA_DEBUG static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KDBG_XIRC args) +#else +#define DEBUG(n, args...) #endif static char *version = "xirc2ps_cs.c 1.31 1998/12/09 19:32:55 (dd9jn+kvh)"; @@ -313,11 +312,11 @@ static unsigned maxrx_bytes = 22000; /* MII management prototypes */ static void mii_idle(ioaddr_t ioaddr); static void mii_putbit(ioaddr_t ioaddr, unsigned data); -static int mii_getbit( ioaddr_t ioaddr ); +static int mii_getbit(ioaddr_t ioaddr); static void mii_wbits(ioaddr_t ioaddr, unsigned data, int len); static unsigned mii_rd(ioaddr_t ioaddr, u_char phyaddr, u_char phyreg); static void mii_wr(ioaddr_t ioaddr, u_char phyaddr, u_char phyreg, - unsigned data, int len); + unsigned data, int len); /* * The event() function is this driver's Card Services event handler. @@ -396,6 +395,7 @@ typedef struct local_info_t { int silicon; /* silicon revision. 0=old CE2, 1=Scipper, 4=Mohawk */ int mohawk; /* a CE3 type card */ int dingo; /* a CEM56 type card */ + int new_mii; /* has full 10baseT/100baseT MII */ int modem; /* is a multi function card (i.e with a modem) */ caddr_t dingo_ccr; /* only used for CEM56 cards */ int suspended; @@ -411,7 +411,7 @@ static struct enet_statistics *do_get_stats(struct net_device *dev); static void set_addresses(struct net_device *dev); static void set_multicast_list(struct net_device *dev); static int do_init(struct net_device *dev); -static int set_card_type( dev_link_t *link, const void *s ); +static int set_card_type(dev_link_t *link, const void *s); static int do_config(struct net_device *dev, struct ifmap *map); static int do_open(struct net_device *dev); static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); @@ -441,11 +441,11 @@ cs_error(client_handle_t handle, int func, int ret) } static int -get_tuple_data(int fn, client_handle_t handle, tuple_t *tuple ) +get_tuple_data(int fn, client_handle_t handle, tuple_t *tuple) { int err; - if( (err=CardServices(fn, handle, tuple)) ) + if ((err=CardServices(fn, handle, tuple))) return err; return CardServices(GetTupleData, handle, tuple); } @@ -455,7 +455,7 @@ get_tuple(int fn, client_handle_t handle, tuple_t *tuple, cisparse_t *parse) { int err; - if( (err=get_tuple_data(fn, handle, tuple)) ) + if ((err=get_tuple_data(fn, handle, tuple))) return err; return CardServices(ParseTuple, handle, tuple, parse); } @@ -477,7 +477,7 @@ busy_loop(u_long len) save_flags(flags); sti(); - while(timeout >= jiffies) + while (timeout >= jiffies) ; restore_flags(flags); } @@ -489,27 +489,27 @@ PrintRegisters(struct net_device *dev) { ioaddr_t ioaddr = dev->base_addr; - if(pc_debug > 1) { + if (pc_debug > 1) { int i, page; printk(KDBG_XIRC "Register common: "); - for(i = 0; i < 8; i++ ) - printk(" %2.2x", GetByte(i) ); + for (i = 0; i < 8; i++) + printk(" %2.2x", GetByte(i)); printk("\n"); - for(page = 0; page <= 8; page++) { + for (page = 0; page <= 8; page++) { printk(KDBG_XIRC "Register page %2x: ", page); SelectPage(page); - for(i = 8; i < 16; i++) + for (i = 8; i < 16; i++) printk(" %2.2x", GetByte(i)); printk("\n"); } - for(page=0x40 ; page <= 0x5f; page++) { - if( page == 0x43 || (page >= 0x46 && page <= 0x4f) - || (page >= 0x51 && page <=0x5e) ) + for (page=0x40 ; page <= 0x5f; page++) { + if (page == 0x43 || (page >= 0x46 && page <= 0x4f) + || (page >= 0x51 && page <=0x5e)) continue; printk(KDBG_XIRC "Register page %2x: ", page); SelectPage(page); - for(i = 8; i < 16; i++) + for (i = 8; i < 16; i++) printk(" %2.2x", GetByte(i)); printk("\n"); } @@ -525,9 +525,9 @@ PrintRegisters(struct net_device *dev) static void mii_idle(ioaddr_t ioaddr) { - PutByte(XIRCREG2_GPR2, 0x04|0 ); /* drive MDCK low */ + PutByte(XIRCREG2_GPR2, 0x04|0); /* drive MDCK low */ udelay(1); - PutByte(XIRCREG2_GPR2, 0x04|1 ); /* and drive MDCK high */ + PutByte(XIRCREG2_GPR2, 0x04|1); /* and drive MDCK high */ udelay(1); } @@ -538,29 +538,27 @@ static void mii_putbit(ioaddr_t ioaddr, unsigned data) { #if 1 - if( data ) { - PutByte(XIRCREG2_GPR2, 0x0c|2|0 ); /* set MDIO */ + if (data) { + PutByte(XIRCREG2_GPR2, 0x0c|2|0); /* set MDIO */ udelay(1); - PutByte(XIRCREG2_GPR2, 0x0c|2|1 ); /* and drive MDCK high */ + PutByte(XIRCREG2_GPR2, 0x0c|2|1); /* and drive MDCK high */ udelay(1); - } - else { - PutByte(XIRCREG2_GPR2, 0x0c|0|0 ); /* clear MDIO */ + } else { + PutByte(XIRCREG2_GPR2, 0x0c|0|0); /* clear MDIO */ udelay(1); - PutByte(XIRCREG2_GPR2, 0x0c|0|1 ); /* and drive MDCK high */ + PutByte(XIRCREG2_GPR2, 0x0c|0|1); /* and drive MDCK high */ udelay(1); } #else - if( data ) { - PutWord(XIRCREG2_GPR2-1, 0x0e0e ); + if (data) { + PutWord(XIRCREG2_GPR2-1, 0x0e0e); udelay(1); - PutWord(XIRCREG2_GPR2-1, 0x0f0f ); + PutWord(XIRCREG2_GPR2-1, 0x0f0f); udelay(1); - } - else { - PutWord(XIRCREG2_GPR2-1, 0x0c0c ); + } else { + PutWord(XIRCREG2_GPR2-1, 0x0c0c); udelay(1); - PutWord(XIRCREG2_GPR2-1, 0x0d0d ); + PutWord(XIRCREG2_GPR2-1, 0x0d0d); udelay(1); } #endif @@ -570,14 +568,14 @@ mii_putbit(ioaddr_t ioaddr, unsigned data) * Get a bit from MDI/O */ static int -mii_getbit( ioaddr_t ioaddr ) +mii_getbit(ioaddr_t ioaddr) { unsigned d; - PutByte(XIRCREG2_GPR2, 4|0 ); /* drive MDCK low */ + PutByte(XIRCREG2_GPR2, 4|0); /* drive MDCK low */ udelay(1); d = GetByte(XIRCREG2_GPR2); /* read MDIO */ - PutByte(XIRCREG2_GPR2, 4|1 ); /* drive MDCK high again */ + PutByte(XIRCREG2_GPR2, 4|1); /* drive MDCK high again */ udelay(1); return d & 0x20; /* read MDIO */ } @@ -586,8 +584,8 @@ static void mii_wbits(ioaddr_t ioaddr, unsigned data, int len) { unsigned m = 1 << (len-1); - for( ; m; m >>= 1) - mii_putbit( ioaddr, data & m ); + for (; m; m >>= 1) + mii_putbit(ioaddr, data & m); } static unsigned @@ -597,16 +595,16 @@ mii_rd(ioaddr_t ioaddr, u_char phyaddr, u_char phyreg) unsigned data=0, m; SelectPage(2); - for( i=0; i < 32; i++ ) /* 32 bit preamble */ + for (i=0; i < 32; i++) /* 32 bit preamble */ mii_putbit(ioaddr, 1); mii_wbits(ioaddr, 0x06, 4); /* Start and opcode for read */ mii_wbits(ioaddr, phyaddr, 5); /* PHY address to be accessed */ mii_wbits(ioaddr, phyreg, 5); /* PHY register to read */ mii_idle(ioaddr); /* turn around */ - mii_getbit( ioaddr); + mii_getbit(ioaddr); - for( m = 1<<15; m; m >>= 1 ) - if( mii_getbit( ioaddr ) ) + for (m = 1<<15; m; m >>= 1) + if (mii_getbit(ioaddr)) data |= m; mii_idle(ioaddr); return data; @@ -618,7 +616,7 @@ mii_wr(ioaddr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len) int i; SelectPage(2); - for( i=0; i < 32; i++ ) /* 32 bit preamble */ + for (i=0; i < 32; i++) /* 32 bit preamble */ mii_putbit(ioaddr, 1); mii_wbits(ioaddr, 0x05, 4); /* Start and opcode for write */ mii_wbits(ioaddr, phyaddr, 5); /* PHY address to be accessed */ @@ -640,13 +638,13 @@ mii_dump(struct net_device *dev) * not be read according to the DP83840A specs. */ printk(KERN_DEBUG "%s: MII register dump:\n", dev->name); - for(i=0; i < 32; i++ ) { - if( !(i % 8) ) { - if( i ) + for (i=0; i < 32; i++) { + if (!(i % 8)) { + if (i) printk("\n"); - printk(KERN_DEBUG "%s:", dev->name ); + printk(KERN_DEBUG "%s:", dev->name); } - printk(" %04x", mii_rd(ioaddr, 0, i) ); + printk(" %04x", mii_rd(ioaddr, 0, i)); } printk("\n"); } @@ -673,10 +671,7 @@ xirc2ps_attach(void) local_info_t *local; int err; - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "attach()\n"); - #endif + DEBUG(0, "attach()\n"); flush_stale_links(); /* Initialize the dev_link_t structure */ @@ -725,7 +720,7 @@ xirc2ps_attach(void) client_reg.event_handler = &xirc2ps_event; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; - if( (err = CardServices(RegisterClient, &link->handle, &client_reg)) ) { + if ((err = CardServices(RegisterClient, &link->handle, &client_reg))) { cs_error(link->handle, RegisterClient, err); xirc2ps_detach(link); return NULL; @@ -747,25 +742,20 @@ xirc2ps_detach(dev_link_t * link) dev_link_t **linkp; long flags; - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "detach(0x%p)\n", link); - #endif + DEBUG(0, "detach(0x%p)\n", link); /* Locate device structure */ - for( linkp = &dev_list; *linkp; linkp = &(*linkp)->next ) - if( *linkp == link) + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) break; - if( !*linkp ) { - #ifdef PCMCIA_DEBUG - printk(KDBG_XIRC "detach(0x%p): dev_link lost\n", link ); - #endif + if (!*linkp) { + DEBUG(0, "detach(0x%p): dev_link lost\n", link); return; } save_flags(flags); cli(); - if( link->state & DEV_RELEASE_PENDING ) { + if (link->state & DEV_RELEASE_PENDING) { del_timer(&link->release); link->state &= ~DEV_RELEASE_PENDING; } @@ -777,26 +767,24 @@ xirc2ps_detach(dev_link_t * link) * the release() function is called, that will trigger a proper * detach(). */ - if(link->state & DEV_CONFIG) { - #ifdef PCMCIA_DEBUG - printk(KDBG_XIRC "detach postponed, '%s' " - "still locked\n", link->dev->dev_name); - #endif + if (link->state & DEV_CONFIG) { + DEBUG(0, "detach postponed, '%s' still locked\n", + link->dev->dev_name); link->state |= DEV_STALE_LINK; return; } /* Break the link with Card Services */ - if(link->handle) + if (link->handle) CardServices(DeregisterClient, link->handle); /* Unlink device structure, free pieces */ *linkp = link->next; - if(link->priv) { + if (link->priv) { struct net_device *dev = link->priv; if (link->dev != NULL) unregister_netdev(dev); - if( dev->priv ) + if (dev->priv) kfree(dev->priv); kfree(link->priv); } @@ -823,7 +811,7 @@ xirc2ps_detach(dev_link_t * link) * */ static int -set_card_type( dev_link_t *link, const void *s ) +set_card_type(dev_link_t *link, const void *s) { struct net_device *dev = link->priv; local_info_t *local = dev->priv; @@ -833,27 +821,24 @@ set_card_type( dev_link_t *link, const void *s ) unsigned mediaid= ((const unsigned char *)s)[3]; unsigned prodid = ((const unsigned char *)s)[4]; - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "cisrev=%02x mediaid=%02x prodid=%02x\n", - cisrev, mediaid, prodid ); - #endif + DEBUG(0, "cisrev=%02x mediaid=%02x prodid=%02x\n", + cisrev, mediaid, prodid); local->mohawk = 0; local->dingo = 0; local->modem = 0; local->card_type = XIR_UNKNOWN; - if( !(prodid & 0x40) ) { + if (!(prodid & 0x40)) { printk(KNOT_XIRC "Ooops: Not a creditcard\n"); return 0; } - if( !(mediaid & 0x01) ) { + if (!(mediaid & 0x01)) { printk(KNOT_XIRC "Not an Ethernet card\n"); return 0; } - if( mediaid & 0x10 ) { + if (mediaid & 0x10) { local->modem = 1; - switch( prodid & 15 ) { + switch(prodid & 15) { case 1: local->card_type = XIR_CEM ; break; case 2: local->card_type = XIR_CEM2 ; break; case 3: local->card_type = XIR_CEM3 ; break; @@ -868,9 +853,8 @@ set_card_type( dev_link_t *link, const void *s ) local->dingo = 1; break; } - } - else { - switch( prodid & 15 ) { + } else { + switch(prodid & 15) { case 1: local->card_type = has_ce2_string(link)? XIR_CE2 : XIR_CE ; break; case 2: local->card_type = XIR_CE2; break; @@ -879,13 +863,13 @@ set_card_type( dev_link_t *link, const void *s ) break; } } - if( local->card_type == XIR_CE || local->card_type == XIR_CEM ) { + if (local->card_type == XIR_CE || local->card_type == XIR_CEM) { printk(KNOT_XIRC "Sorry, this is an old CE card\n"); return 0; } - if( local->card_type == XIR_UNKNOWN ) - printk(KNOT_XIRC "Warning: Unknown card (mediaid=%02x prodid=%02x)\n", - mediaid, prodid ); + if (local->card_type == XIR_UNKNOWN) + printk(KNOT_XIRC "unknown card (mediaid=%02x prodid=%02x)\n", + mediaid, prodid); return 1; } @@ -908,8 +892,8 @@ has_ce2_string(dev_link_t * link) tuple.TupleDataMax = 254; tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_VERS_1; - if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 2 ) { - if( strstr(parse.version_1.str + parse.version_1.ofs[2], "CE2") ) + if (!first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 2) { + if (strstr(parse.version_1.str + parse.version_1.ofs[2], "CE2")) return 1; } return 0; @@ -939,10 +923,7 @@ xirc2ps_config(dev_link_t * link) local = dev->priv; local->dingo_ccr = 0; - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "config(0x%p)\n", link); - #endif + DEBUG(0, "config(0x%p)\n", link); /* * This reads the card's CONFIG tuple to find its configuration @@ -955,101 +936,89 @@ xirc2ps_config(dev_link_t * link) /* Is this a valid card */ tuple.DesiredTuple = CISTPL_MANFID; - if( (err=first_tuple(handle, &tuple, &parse))) { + if ((err=first_tuple(handle, &tuple, &parse))) { printk(KNOT_XIRC "manfid not found in CIS\n"); goto failure; } - switch( parse.manfid.manf ) { + switch(parse.manfid.manf) { case MANFID_XIRCOM: local->manf_str = "Xircom"; - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "found xircom card\n"); - #endif + DEBUG(0, "found xircom card\n"); break; case MANFID_ACCTON: local->manf_str = "Accton"; - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "found Accton card\n"); - #endif + DEBUG(0, "found Accton card\n"); break; case MANFID_COMPAQ: case MANFID_COMPAQ2: local->manf_str = "Compaq"; - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "found Compaq card\n"); - #endif + DEBUG(0, "found Compaq card\n"); break; case MANFID_INTEL: local->manf_str = "Intel"; - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "found Intel card\n"); - #endif + DEBUG(0, "found Intel card\n"); break; default: printk(KNOT_XIRC "Unknown Card Manufacturer ID: 0x%04x\n", - (unsigned)parse.manfid.manf); + (unsigned)parse.manfid.manf); goto failure; } - if( !set_card_type(link, buf ) ) { + if (!set_card_type(link, buf)) { printk(KNOT_XIRC "this card is not supported\n"); goto failure; } /* get configuration stuff */ tuple.DesiredTuple = CISTPL_CONFIG; - if( (err=first_tuple(handle, &tuple, &parse))) + if ((err=first_tuple(handle, &tuple, &parse))) goto cis_error; link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; /* get the ethernet address from the CIS */ tuple.DesiredTuple = CISTPL_FUNCE; - for( err = first_tuple(handle, &tuple, &parse); !err; - err = next_tuple(handle, &tuple, &parse) ) { + for (err = first_tuple(handle, &tuple, &parse); !err; + err = next_tuple(handle, &tuple, &parse)) { /* Once I saw two CISTPL_FUNCE_LAN_NODE_ID entries: * the first one with a length of zero the second correct - * so I skip all entries with length 0 */ - if( parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID - && ((cistpl_lan_node_id_t *)parse.funce.data)->nb ) + if (parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID + && ((cistpl_lan_node_id_t *)parse.funce.data)->nb) break; } - if( err ) { /* not found: try to get the node-id from tuple 0x89 */ + if (err) { /* not found: try to get the node-id from tuple 0x89 */ tuple.DesiredTuple = 0x89; /* data layout looks like tuple 0x22 */ - if( !(err = get_tuple_data(GetFirstTuple, handle, &tuple )) ) { - if( tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID ) - memcpy( &parse, buf, 8 ); + if (!(err = get_tuple_data(GetFirstTuple, handle, &tuple))) { + if (tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID) + memcpy(&parse, buf, 8); else err = -1; } } - if( err ) { /* another try (James Lehmer's CE2 version 4.1)*/ + if (err) { /* another try (James Lehmer's CE2 version 4.1)*/ tuple.DesiredTuple = CISTPL_FUNCE; - for( err = first_tuple(handle, &tuple, &parse); !err; - err = next_tuple(handle, &tuple, &parse) ) { - if( parse.funce.type == 0x02 && parse.funce.data[0] == 1 - && parse.funce.data[1] == 6 && tuple.TupleDataLen == 13 ) { + for (err = first_tuple(handle, &tuple, &parse); !err; + err = next_tuple(handle, &tuple, &parse)) { + if (parse.funce.type == 0x02 && parse.funce.data[0] == 1 + && parse.funce.data[1] == 6 && tuple.TupleDataLen == 13) { buf[1] = 4; - memcpy( &parse, buf+1, 8 ); + memcpy(&parse, buf+1, 8); break; } } } - if( err ) { + if (err) { printk(KNOT_XIRC "node-id not found in CIS\n"); goto failure; } node_id = (cistpl_lan_node_id_t *)parse.funce.data; - if( node_id->nb != 6 ) { + if (node_id->nb != 6) { printk(KNOT_XIRC "malformed node-id in CIS\n"); goto failure; } - for( i=0; i < 6; i++ ) + for (i=0; i < 6; i++) dev->dev_addr[i] = node_id->id[i]; /* Configure card */ @@ -1059,61 +1028,60 @@ xirc2ps_config(dev_link_t * link) link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; link->irq.Attributes = IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; - if( irq_list[0] == -1 ) + if (irq_list[0] == -1) link->irq.IRQInfo2 = irq_mask; else { - for( i = 0; i < 4; i++) + for (i = 0; i < 4; i++) link->irq.IRQInfo2 |= 1 << irq_list[i]; } link->irq.Handler = xirc2ps_interrupt; link->irq.Instance = dev; - if( local->modem ) { + if (local->modem) { int pass; - if( do_sound ) { + if (do_sound) { link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status |= CCSR_AUDIO_ENA; } link->irq.Attributes |= IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED ; link->io.NumPorts2 = 8; link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; - if( local->dingo ) { + if (local->dingo) { /* Take the Modem IO port from the CIS and scan for a free * Ethernet port */ link->io.NumPorts1 = 16; /* no Mako stuff anymore */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - for( err = first_tuple(handle, &tuple, &parse); !err; - err = next_tuple(handle, &tuple, &parse) ) { - if( cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8 ) { - for(ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { + for (err = first_tuple(handle, &tuple, &parse); !err; + err = next_tuple(handle, &tuple, &parse)) { + if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) { + for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { link->conf.ConfigIndex = cf->index ; link->io.BasePort2 = cf->io.win[0].base; link->io.BasePort1 = ioaddr; - if( !(err=CardServices(RequestIO, link->handle, - &link->io)) ) + if (!(err=CardServices(RequestIO, link->handle, + &link->io))) goto port_found; } } } - } - else { + } else { link->io.NumPorts1 = 18; /* We do 2 passes here: The first one uses the regular mapping and * the second tries again, thereby considering that the 32 ports are * mirrored every 32 bytes. Actually we use a mirrored port for * the Mako if (on the first pass) the COR bit 5 is set. */ - for( pass=0; pass < 2; pass++ ) { + for (pass=0; pass < 2; pass++) { tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - for( err = first_tuple(handle, &tuple, &parse); !err; - err = next_tuple(handle, &tuple, &parse) ){ - if( cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8 ){ + for (err = first_tuple(handle, &tuple, &parse); !err; + err = next_tuple(handle, &tuple, &parse)){ + if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8){ link->conf.ConfigIndex = cf->index ; link->io.BasePort2 = cf->io.win[0].base; link->io.BasePort1 = link->io.BasePort2 - + (pass ? ( cf->index & 0x20 ? -24:8 ) - : ( cf->index & 0x20 ? 8:-24) ); - if( !(err=CardServices(RequestIO, link->handle, + + (pass ? (cf->index & 0x20 ? -24:8) + : (cf->index & 0x20 ? 8:-24)); + if (!(err=CardServices(RequestIO, link->handle, &link->io))) goto port_found; } @@ -1124,30 +1092,29 @@ xirc2ps_config(dev_link_t * link) * .... */ } printk(KNOT_XIRC "no ports available\n"); - } - else { + } else { link->irq.Attributes |= IRQ_TYPE_EXCLUSIVE; link->io.NumPorts1 = 16; - for(ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { + for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { link->io.BasePort1 = ioaddr; - if( !(err=CardServices(RequestIO, link->handle, &link->io)) ) + if (!(err=CardServices(RequestIO, link->handle, &link->io))) goto port_found; } link->io.BasePort1 = 0; /* let CS decide */ - if( (err=CardServices(RequestIO, link->handle, &link->io)) ) { + if ((err=CardServices(RequestIO, link->handle, &link->io))) { cs_error(link->handle, RequestIO, err); goto config_error; } } port_found: - if( err ) + if (err) goto config_error; /**************** * Now allocate an interrupt line. Note that this does not * actually assign a handler to the interrupt. */ - if( (err=CardServices(RequestIRQ, link->handle, &link->irq))) { + if ((err=CardServices(RequestIRQ, link->handle, &link->irq))) { cs_error(link->handle, RequestIRQ, err); goto config_error; } @@ -1156,13 +1123,13 @@ xirc2ps_config(dev_link_t * link) * This actually configures the PCMCIA socket -- setting up * the I/O windows and the interrupt mapping. */ - if( (err=CardServices(RequestConfiguration, - link->handle, &link->conf)) ) { + if ((err=CardServices(RequestConfiguration, + link->handle, &link->conf))) { cs_error(link->handle, RequestConfiguration, err); goto config_error; } - if( local->dingo ) { + if (local->dingo) { #ifdef CEM56_FIX conf_reg_t reg; #endif @@ -1178,16 +1145,16 @@ xirc2ps_config(dev_link_t * link) reg.Action = CS_WRITE; reg.Offset = CISREG_IOBASE_0; reg.Value = link->io.BasePort2 & 0xff; - if( (err = CardServices(AccessConfigurationRegister, link->handle, - ® )) ) { + if ((err = CardServices(AccessConfigurationRegister, link->handle, + ®))) { cs_error(link->handle, AccessConfigurationRegister, err); goto config_error; } reg.Action = CS_WRITE; reg.Offset = CISREG_IOBASE_1; reg.Value = (link->io.BasePort2 >> 8) & 0xff; - if( (err = CardServices(AccessConfigurationRegister, link->handle, - ® )) ) { + if ((err = CardServices(AccessConfigurationRegister, link->handle, + ®))) { cs_error(link->handle, AccessConfigurationRegister, err); goto config_error; } @@ -1202,14 +1169,14 @@ xirc2ps_config(dev_link_t * link) req.Size = 0x1000; /* 4k window */ req.AccessSpeed = 0; link->win = (window_handle_t)link->handle; - if( (err = CardServices(RequestWindow, &link->win, &req )) ) { + if ((err = CardServices(RequestWindow, &link->win, &req))) { cs_error(link->handle, RequestWindow, err); goto config_error; } local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800; mem.CardOffset = 0x0; mem.Page = 0; - if( (err = CardServices(MapMemPage, link->win, &mem) ) ) { + if ((err = CardServices(MapMemPage, link->win, &mem))) { cs_error(link->handle, MapMemPage, err); goto config_error; } @@ -1217,72 +1184,72 @@ xirc2ps_config(dev_link_t * link) /* Setup the CCRs; there are no infos in the CIS about the Ethernet * part. */ - writeb(0x47, local->dingo_ccr + CISREG_COR ); + writeb(0x47, local->dingo_ccr + CISREG_COR); ioaddr = link->io.BasePort1; - writeb( ioaddr & 0xff , local->dingo_ccr + CISREG_IOBASE_0 ); - writeb((ioaddr >> 8)&0xff , local->dingo_ccr + CISREG_IOBASE_1 ); + writeb(ioaddr & 0xff , local->dingo_ccr + CISREG_IOBASE_0); + writeb((ioaddr >> 8)&0xff , local->dingo_ccr + CISREG_IOBASE_1); #if 0 { u_char tmp; - printk(KERN_INFO "ECOR:" ); - for(i=0; i < 7; i++ ) { - tmp = readb(local->dingo_ccr + i*2 ); - printk(" %02x", tmp ); + printk(KERN_INFO "ECOR:"); + for (i=0; i < 7; i++) { + tmp = readb(local->dingo_ccr + i*2); + printk(" %02x", tmp); } - printk("\n" ); - printk(KERN_INFO "DCOR:" ); - for(i=0; i < 4; i++ ) { - tmp = readb(local->dingo_ccr + 0x20 + i*2 ); - printk(" %02x", tmp ); + printk("\n"); + printk(KERN_INFO "DCOR:"); + for (i=0; i < 4; i++) { + tmp = readb(local->dingo_ccr + 0x20 + i*2); + printk(" %02x", tmp); } - printk("\n" ); - printk(KERN_INFO "SCOR:" ); - for(i=0; i < 10; i++ ) { - tmp = readb(local->dingo_ccr + 0x40 + i*2 ); - printk(" %02x", tmp ); + printk("\n"); + printk(KERN_INFO "SCOR:"); + for (i=0; i < 10; i++) { + tmp = readb(local->dingo_ccr + 0x40 + i*2); + printk(" %02x", tmp); } - printk("\n" ); + printk("\n"); } #endif - writeb( 0x01 , local->dingo_ccr + 0x20 ); - writeb( 0x0c , local->dingo_ccr + 0x22 ); - writeb( 0x00 , local->dingo_ccr + 0x24 ); - writeb( 0x00 , local->dingo_ccr + 0x26 ); - writeb( 0x00 , local->dingo_ccr + 0x28 ); + writeb(0x01 , local->dingo_ccr + 0x20); + writeb(0x0c , local->dingo_ccr + 0x22); + writeb(0x00 , local->dingo_ccr + 0x24); + writeb(0x00 , local->dingo_ccr + 0x26); + writeb(0x00 , local->dingo_ccr + 0x28); } /* The if_port symbol can be set when the module is loaded */ local->probe_port=0; - if( !if_port ) { + if (!if_port) { local->probe_port=1; dev->if_port = 1; } - else if( (if_port >= 1 && if_port <= 2) || (local->mohawk && if_port==4) ) + else if ((if_port >= 1 && if_port <= 2) || (local->mohawk && if_port==4)) dev->if_port = if_port; else - printk(KERN_NOTICE "xirc2ps_cs: invalid if_port requested\n"); + printk(KNOT_XIRC "invalid if_port requested\n"); /* we can now register the device with the net subsystem */ dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; dev->tbusy = 0; - if( (err=register_netdev(dev)) ) { - printk(KERN_NOTICE "xirc2ps_cs: register_netdev() failed\n"); + if ((err=register_netdev(dev))) { + printk(KNOT_XIRC "register_netdev() failed\n"); goto config_error; } link->state &= ~DEV_CONFIG_PENDING; link->dev = &local->node; - if( local->dingo ) + if (local->dingo) do_reset(dev, 1); /* a kludge to make the cem56 work */ /* give some infos about the hardware */ printk(KERN_INFO "%s: %s: port %#3lx, irq %d, hwaddr", - dev->name, local->manf_str,(u_long)dev->base_addr, (int)dev->irq ); - for(i = 0; i < 6; i++) + dev->name, local->manf_str,(u_long)dev->base_addr, (int)dev->irq); + for (i = 0; i < 6; i++) printk("%c%02X", i?':':' ', dev->dev_addr[i]); printk("\n"); @@ -1294,7 +1261,7 @@ xirc2ps_config(dev_link_t * link) return; cis_error: - printk(KERN_NOTICE "xirc2ps_cs: unable to parse CIS\n"); + printk(KNOT_XIRC "unable to parse CIS\n"); failure: link->state &= ~DEV_CONFIG_PENDING; } /* xirc2ps_config */ @@ -1305,35 +1272,29 @@ xirc2ps_config(dev_link_t * link) * still open, this will be postponed until it is closed. */ static void -xirc2ps_release( u_long arg) +xirc2ps_release(u_long arg) { dev_link_t *link = (dev_link_t *) arg; struct net_device *dev = link->priv; - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "release(0x%p)\n", link); - #endif + DEBUG(0, "release(0x%p)\n", link); /* * If the device is currently in use, we won't release until it * is actually closed. */ - if(link->open) { - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "release postponed, '%s' " - "still open\n", link->dev->dev_name); - #endif + if (link->open) { + DEBUG(0, "release postponed, '%s' " + "still open\n", link->dev->dev_name); link->state |= DEV_STALE_CONFIG; return; } - if( link->win ) { + if (link->win) { local_info_t *local = dev->priv; - if( local->dingo ) - iounmap( local->dingo_ccr - 0x0800 ); - CardServices(ReleaseWindow, link->win ); + if (local->dingo) + iounmap(local->dingo_ccr - 0x0800); + CardServices(ReleaseWindow, link->win); } CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseIO, link->handle, &link->io); @@ -1364,21 +1325,15 @@ xirc2ps_event(event_t event, int priority, struct net_device *dev = link->priv; local_info_t *lp = dev? dev->priv : NULL; - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "event(%d)\n", (int)event ); - #endif + DEBUG(0, "event(%d)\n", (int)event); switch (event) { case CS_EVENT_REGISTRATION_COMPLETE: - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "registration complete\n"); - #endif + DEBUG(0, "registration complete\n"); break; case CS_EVENT_CARD_REMOVAL: link->state &= ~DEV_PRESENT; - if(link->state & DEV_CONFIG) { + if (link->state & DEV_CONFIG) { dev->tbusy = 1; dev->start = 0; link->release.expires = jiffies + HZ / 20; add_timer(&link->release); @@ -1392,8 +1347,8 @@ xirc2ps_event(event_t event, int priority, link->state |= DEV_SUSPEND; /* Fall through... */ case CS_EVENT_RESET_PHYSICAL: - if(link->state & DEV_CONFIG) { - if(link->open) { + if (link->state & DEV_CONFIG) { + if (link->open) { dev->tbusy = 1; dev->start = 0; lp->suspended=1; do_powerdown(dev); @@ -1405,9 +1360,9 @@ xirc2ps_event(event_t event, int priority, link->state &= ~DEV_SUSPEND; /* Fall through... */ case CS_EVENT_CARD_RESET: - if(link->state & DEV_CONFIG) { + if (link->state & DEV_CONFIG) { CardServices(RequestConfiguration, link->handle, &link->conf); - if( link->open) { + if (link->open) { do_reset(dev,1); lp->suspended=0; dev->tbusy = 0; dev->start = 1; @@ -1438,24 +1393,21 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs) * -- on a laptop? */ - if( !dev->start ) + if (!dev->start) return; - if( dev->interrupt ) { + if (dev->interrupt) { printk(KERR_XIRC "re-entering isr on irq %d (dev=%p)\n", irq, dev); return; } dev->interrupt = 1; lp = dev->priv; ioaddr = dev->base_addr; - if( lp->mohawk ) { /* must disable the interrupt */ - PutByte(XIRCREG_CR, 0 ); + if (lp->mohawk) { /* must disable the interrupt */ + PutByte(XIRCREG_CR, 0); } - #ifdef PCMCIA_DEBUG - if(pc_debug > 6 ) - printk(KERN_DEBUG "%s: interrupt %d at %#x.\n", dev->name, irq, ioaddr); - #endif + DEBUG(6, "%s: interrupt %d at %#x.\n", dev->name, irq, ioaddr); saved_page = GetByte(XIRCREG_PR); /* Read the ISR to see whats the cause for the interrupt. @@ -1464,91 +1416,74 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs) int_status = GetByte(XIRCREG_ISR); bytes_rcvd = 0; loop_entry: - if( int_status == 0xff ) { /* card may be ejected */ - #ifdef PCMCIA_DEBUG - if( pc_debug > 3 ) - printk(KERN_DEBUG "%s: interrupt %d for dead card\n", dev->name, irq ); - #endif + if (int_status == 0xff) { /* card may be ejected */ + DEBUG(3, "%s: interrupt %d for dead card\n", dev->name, irq); goto leave; } eth_status = GetByte(XIRCREG_ESR); SelectPage(0x40); rx_status = GetByte(XIRCREG40_RXST0); - PutByte(XIRCREG40_RXST0, (~rx_status & 0xff) ); + PutByte(XIRCREG40_RXST0, (~rx_status & 0xff)); tx_status = GetByte(XIRCREG40_TXST0); tx_status |= GetByte(XIRCREG40_TXST1) << 8; - PutByte(XIRCREG40_TXST0, 0 ); - PutByte(XIRCREG40_TXST1, 0 ); + PutByte(XIRCREG40_TXST0, 0); + PutByte(XIRCREG40_TXST1, 0); - #ifdef PCMCIA_DEBUG - if( pc_debug > 3 ) - printk(KERN_DEBUG "%s: ISR=%#2.2x ESR=%#2.2x RSR=%#2.2x TSR=%#4.4x\n", - dev->name, int_status, eth_status, rx_status, tx_status ); - #endif + DEBUG(3, "%s: ISR=%#2.2x ESR=%#2.2x RSR=%#2.2x TSR=%#4.4x\n", + dev->name, int_status, eth_status, rx_status, tx_status); /***** receive section ******/ SelectPage(0); - while( eth_status & FullPktRcvd ) { + while (eth_status & FullPktRcvd) { rsr = GetByte(XIRCREG0_RSR); - if( bytes_rcvd > maxrx_bytes && (rsr & PktRxOk) ) { + if (bytes_rcvd > maxrx_bytes && (rsr & PktRxOk)) { /* too many bytes received during this int, drop the rest of the * packets */ lp->stats.rx_dropped++; - #ifdef PCMCIA_DEBUG - if( pc_debug > 3 ) - printk(KNOT_XIRC "%s: RX drop, too much done\n", dev->name); - #endif - PutWord(XIRCREG0_DO, 0x8000 ); /* issue cmd: skip_rx_packet */ - } - else if( rsr & PktRxOk ) { + printk(KINF_XIRC "%s: RX drop, too much done\n", dev->name); + PutWord(XIRCREG0_DO, 0x8000); /* issue cmd: skip_rx_packet */ + } else if (rsr & PktRxOk) { struct sk_buff *skb; pktlen = GetWord(XIRCREG0_RBC); bytes_rcvd += pktlen; - #ifdef PCMCIA_DEBUG - if( pc_debug > 5 ) - printk(KDBG_XIRC "rsr=%#02x packet_length=%u\n", rsr, pktlen ); - #endif + DEBUG(5, "rsr=%#02x packet_length=%u\n", rsr, pktlen); skb = dev_alloc_skb(pktlen+3); /* 1 extra so we can use insw */ - if( !skb ) { - #ifdef PCMCIA_DEBUG - if( pc_debug ) - printk(KNOT_XIRC "low memory, packet dropped (size=%u)\n", - pktlen ); - #endif + if (!skb) { + printk(KNOT_XIRC "low memory, packet dropped (size=%u)\n", + pktlen); lp->stats.rx_dropped++; - } - else { /* okay get the packet */ + } else { /* okay get the packet */ skb_reserve(skb, 2); - if( lp->silicon == 0 ) { /* work around a hardware bug */ + if (lp->silicon == 0 ) { /* work around a hardware bug */ unsigned rhsa; /* receive start address */ SelectPage(5); rhsa = GetWord(XIRCREG5_RHSA0); SelectPage(0); rhsa += 3; /* skip control infos */ - if( rhsa >= 0x8000 ) + if (rhsa >= 0x8000) rhsa = 0; - if( rhsa + pktlen > 0x8000 ) { + if (rhsa + pktlen > 0x8000) { unsigned i; u_char *buf = skb_put(skb, pktlen); - for(i=0; i < pktlen ; i++, rhsa++ ) { + for (i=0; i < pktlen ; i++, rhsa++) { buf[i] = GetByte(XIRCREG_EDP); - if( rhsa == 0x8000 ) { + if (rhsa == 0x8000) { rhsa = 0; i--; } } } else { insw(ioaddr+XIRCREG_EDP, - skb_put(skb, pktlen), (pktlen+1)>>1 ); + skb_put(skb, pktlen), (pktlen+1)>>1); } } #if 0 - else if( lp->mohawk ) { + else if (lp->mohawk) { /* To use this 32 bit access we should use * a manual optimized loop * Also the words are swapped, we can get more @@ -1561,7 +1496,7 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs) u_long *p = skb_put(skb, pktlen); register u_long a; ioaddr_t edpreg = ioaddr+XIRCREG_EDP-2; - for(i=0; i < len ; i += 4, p++ ) { + for (i=0; i < len ; i += 4, p++) { a = inl(edpreg); __asm__("rorl $16,%0\n\t" :"=q" (a) @@ -1572,129 +1507,100 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs) #endif else { insw(ioaddr+XIRCREG_EDP, skb_put(skb, pktlen), - (pktlen+1)>>1 ); + (pktlen+1)>>1); } skb->protocol = eth_type_trans(skb, dev); skb->dev = dev; netif_rx(skb); lp->stats.rx_packets++; lp->stats.rx_bytes += pktlen; - if( !(rsr & PhyPkt) ) + if (!(rsr & PhyPkt)) lp->stats.multicast++; } - PutWord(XIRCREG0_DO, 0x8000 ); /* issue cmd: skip_rx_packet */ + PutWord(XIRCREG0_DO, 0x8000); /* issue cmd: skip_rx_packet */ + } else { + DEBUG(5, "rsr=%#02x\n", rsr); } - else { - #ifdef PCMCIA_DEBUG - if( pc_debug > 5 ) - printk("rsr=%#02x\n", rsr ); - #endif - } - if( rsr & PktTooLong ) { + if (rsr & PktTooLong) { lp->stats.rx_frame_errors++; - #ifdef PCMCIA_DEBUG - if( pc_debug > 3 ) - printk(KNOT_XIRC "%s: Packet too long\n", dev->name); - #endif + DEBUG(3, "%s: Packet too long\n", dev->name); } - if( rsr & CRCErr ) { + if (rsr & CRCErr) { lp->stats.rx_crc_errors++; - #ifdef PCMCIA_DEBUG - if( pc_debug > 3 ) - printk(KNOT_XIRC "%s: CRC error\n", dev->name); - #endif + DEBUG(3, "%s: CRC error\n", dev->name); } - if( rsr & AlignErr ) { + if (rsr & AlignErr) { lp->stats.rx_fifo_errors++; /* okay ? */ - #ifdef PCMCIA_DEBUG - if( pc_debug > 3 ) - printk(KNOT_XIRC "%s: Alignment error\n", dev->name); - #endif + DEBUG(3, "%s: Alignment error\n", dev->name); } /* get the new ethernet status */ eth_status = GetByte(XIRCREG_ESR); } - if( rx_status & 0x10 ) { /* Receive overrun */ + if (rx_status & 0x10) { /* Receive overrun */ lp->stats.rx_over_errors++; PutByte(XIRCREG_CR, ClearRxOvrun); - #ifdef PCMCIA_DEBUG - if( pc_debug > 3 ) - printk(KDBG_XIRC "receive overrun cleared\n" ); - #endif + DEBUG(3, "receive overrun cleared\n"); } /***** transmit section ******/ - if( int_status & PktTxed ) { + if (int_status & PktTxed) { unsigned n, nn; n = lp->last_ptr_value; nn = GetByte(XIRCREG0_PTR); lp->last_ptr_value = nn; - if( nn < n ) /* rollover */ + if (nn < n) /* rollover */ lp->stats.tx_packets += 256 - n; - else if( n == nn ) { /* happens sometimes - don't know why */ - #ifdef PCMCIA_DEBUG - if( pc_debug ) - printk(KDBG_XIRC "PTR not changed?\n" ); - #endif - } - else + else if (n == nn) { /* happens sometimes - don't know why */ + DEBUG(0, "PTR not changed?\n"); + } else lp->stats.tx_packets += lp->last_ptr_value - n; dev->tbusy = 0; mark_bh(NET_BH); /* Inform upper layers. */ } - if( tx_status & 0x0002 ) { /* Execessive collissions */ - #ifdef PCMCIA_DEBUG - if( pc_debug ) - printk(KDBG_XIRC "tx restarted due to execssive collissions\n" ); - #endif - PutByte(XIRCREG_CR, RestartTx ); /* restart transmitter process */ + if (tx_status & 0x0002) { /* Execessive collissions */ + DEBUG(0, "tx restarted due to execssive collissions\n"); + PutByte(XIRCREG_CR, RestartTx); /* restart transmitter process */ } - if( tx_status & 0x0040 ) + if (tx_status & 0x0040) lp->stats.tx_aborted_errors++; /* recalculate our work chunk so that we limit the duration of this * ISR to about 1/10 of a second. * Calculate only if we received a reasonable amount of bytes. */ - if( bytes_rcvd > 1000 ) { + if (bytes_rcvd > 1000) { u_long duration = jiffies - start_ticks; - if( duration >= HZ/10 ) { /* if more than about 1/10 second */ + if (duration >= HZ/10) { /* if more than about 1/10 second */ maxrx_bytes = (bytes_rcvd * (HZ/10)) / duration; - if( maxrx_bytes < 2000 ) + if (maxrx_bytes < 2000) maxrx_bytes = 2000; - else if( maxrx_bytes > 22000 ) + else if (maxrx_bytes > 22000) maxrx_bytes = 22000; - #ifdef PCMCIA_DEBUG - if( pc_debug > 1) - printk(KDBG_XIRC "set maxrx=%u (rcvd=%u ticks=%lu)\n", - maxrx_bytes, bytes_rcvd, duration ); - #endif - } - else if( !duration && maxrx_bytes < 22000 ) { /* now much faster*/ + DEBUG(1, "set maxrx=%u (rcvd=%u ticks=%lu)\n", + maxrx_bytes, bytes_rcvd, duration); + } else if (!duration && maxrx_bytes < 22000) { + /* now much faster */ maxrx_bytes += 2000; - if( maxrx_bytes > 22000 ) + if (maxrx_bytes > 22000) maxrx_bytes = 22000; - #ifdef PCMCIA_DEBUG - if( pc_debug > 1 ) - printk(KDBG_XIRC "set maxrx=%u\n", maxrx_bytes ); - #endif + DEBUG(1, "set maxrx=%u\n", maxrx_bytes); } } leave: - if( lockup_hack ) { - if( int_status != 0xff && (int_status = GetByte(XIRCREG_ISR)) != 0 ) + if (lockup_hack) { + if (int_status != 0xff && (int_status = GetByte(XIRCREG_ISR)) != 0) goto loop_entry; } SelectPage(saved_page); dev->interrupt = 0; - PutByte(XIRCREG_CR, EnableIntr ); /* re-enable interrupts */ + PutByte(XIRCREG_CR, EnableIntr); /* re-enable interrupts */ /* Instead of dropping packets during a receive, we could * force an interrupt with this command: - * PutByte(XIRCREG_CR, EnableIntr|ForceIntr ); + * PutByte(XIRCREG_CR, EnableIntr|ForceIntr); */ } /* xirc2ps_interrupt */ @@ -1709,26 +1615,23 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev) unsigned freespace; unsigned pktlen = skb? skb->len : 0; - #ifdef PCMCIA_DEBUG - if(pc_debug>1 ) - printk(KDBG_XIRC "do_start_xmit(skb=%p, dev=%p) len=%u\n", - skb, dev, pktlen ); - #endif + DEBUG(1, "do_start_xmit(skb=%p, dev=%p) len=%u\n", + skb, dev, pktlen); /* Transmitter timeout, serious problems */ - if( dev->tbusy ) { + if (dev->tbusy) { int tickssofar = jiffies - dev->trans_start; - if( lp->suspended ) { + if (lp->suspended) { dev_kfree_skb (skb); dev->trans_start = jiffies; lp->stats.tx_dropped++; return 0; } - if( tickssofar < TX_TIMEOUT ) + if (tickssofar < TX_TIMEOUT) return 1; - printk(KERN_NOTICE "%s: transmit timed out\n", dev->name ); + printk(KERN_NOTICE "%s: transmit timed out\n", dev->name); lp->stats.tx_errors++; /* reset the card */ do_reset(dev,1); @@ -1736,7 +1639,7 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->tbusy = 0; } - if( test_and_set_bit(0, (void*)&dev->tbusy ) ) { + if (test_and_set_bit(0, (void*)&dev->tbusy)) { printk(KWRN_XIRC "transmitter access conflict\n"); dev_kfree_skb (skb); return 0; @@ -1749,33 +1652,30 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev) * a larger packetlen than we actually have; the chip will * pad this in his buffer with random bytes */ - if( pktlen < ETH_ZLEN ) + if (pktlen < ETH_ZLEN) pktlen = ETH_ZLEN; SelectPage(0); - PutWord(XIRCREG0_TRS, (u_short)pktlen+2 ); + PutWord(XIRCREG0_TRS, (u_short)pktlen+2); freespace = GetWord(XIRCREG0_TSO); okay = freespace & 0x8000; freespace &= 0x7fff; /* TRS doesn't work - (indeed it is eliminated with sil-rev 1) */ okay = pktlen +2 < freespace; - #ifdef PCMCIA_DEBUG - if(pc_debug > 2 + ( okay ? 2 : 0) ) - printk(KERN_DEBUG "%s: avail. tx space=%u%s\n", dev->name, freespace, - okay? " (okay)":" (not enough)" ); - #endif - if( !okay ) { /* not enough space */ + DEBUG(2 + (okay ? 2 : 0), "%s: avail. tx space=%u%s\n", + dev->name, freespace, okay ? " (okay)":" (not enough)"); + if (!okay) { /* not enough space */ dev->tbusy = 1; return 1; /* upper layer may decide to requeue this packet */ } /* send the packet */ - PutWord(XIRCREG_EDP, (u_short)pktlen ); - outsw(ioaddr+XIRCREG_EDP, skb->data, pktlen>>1 ); - if( pktlen & 1 ) - PutByte(XIRCREG_EDP, skb->data[pktlen-1] ); + PutWord(XIRCREG_EDP, (u_short)pktlen); + outsw(ioaddr+XIRCREG_EDP, skb->data, pktlen>>1); + if (pktlen & 1) + PutByte(XIRCREG_EDP, skb->data[pktlen-1]); - if( lp->mohawk ) - PutByte(XIRCREG_CR, TransmitPacket|EnableIntr ); + if (lp->mohawk) + PutByte(XIRCREG_CR, TransmitPacket|EnableIntr); dev_kfree_skb (skb); dev->trans_start = jiffies; @@ -1808,29 +1708,28 @@ set_addresses(struct net_device *dev) int i,j,k,n; SelectPage(k=0x50); - for(i=0,j=8,n=0; ; i++, j++) { - if( i > 5 ) { - if( ++n > 9 ) + for (i=0,j=8,n=0; ; i++, j++) { + if (i > 5) { + if (++n > 9) break; i = 0; } - if( j > 15 ) { + if (j > 15) { j = 8; k++; SelectPage(k); } - if( n && n <= dev->mc_count && dmi ) { + if (n && n <= dev->mc_count && dmi) { addr = dmi->dmi_addr; dmi = dmi->next; - } - else + } else addr = dev->dev_addr; - if( lp->mohawk ) - PutByte( j, addr[5-i] ); + if (lp->mohawk) + PutByte(j, addr[5-i]); else - PutByte( j, addr[i] ); + PutByte(j, addr[i]); } SelectPage(0); } @@ -1847,21 +1746,19 @@ set_multicast_list(struct net_device *dev) ioaddr_t ioaddr = dev->base_addr; SelectPage(0x42); - if( dev->flags & IFF_PROMISC ) { /* snoop */ + if (dev->flags & IFF_PROMISC) { /* snoop */ PutByte(XIRCREG42_SWC1, 0x06); /* set MPE and PME */ - } - else if( dev->mc_count > 9 || (dev->flags & IFF_ALLMULTI) ) { + } else if (dev->mc_count > 9 || (dev->flags & IFF_ALLMULTI)) { PutByte(XIRCREG42_SWC1, 0x06); /* set MPE */ - } - else if( dev->mc_count ) { /* the chip can filter 9 addresses perfectly */ + } else if (dev->mc_count) { + /* the chip can filter 9 addresses perfectly */ PutByte(XIRCREG42_SWC1, 0x00); SelectPage(0x40); - PutByte(XIRCREG40_CMD0, Offline ); + PutByte(XIRCREG40_CMD0, Offline); set_addresses(dev); SelectPage(0x40); - PutByte(XIRCREG40_CMD0, EnableRecv | Online ); - } - else { /* standard usage */ + PutByte(XIRCREG40_CMD0, EnableRecv | Online); + } else { /* standard usage */ PutByte(XIRCREG42_SWC1, 0x00); } SelectPage(0); @@ -1874,10 +1771,7 @@ set_multicast_list(struct net_device *dev) static int do_init(struct net_device *dev) { - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "do_init(%p)\n", dev ); - #endif + DEBUG(0, "do_init(%p)\n", dev); return 0; } @@ -1886,30 +1780,25 @@ do_config(struct net_device *dev, struct ifmap *map) { local_info_t *local = dev->priv; - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "do_config(%p)\n", dev ); - #endif - - if( map->port != 255 && map->port != dev->if_port ) { - if( map->port <= 4 ) { - if( !map->port ) { - local->probe_port = 1; - dev->if_port = 1; - } - else { - local->probe_port = 0; - dev->if_port = map->port; - } - printk(KERN_INFO "%s: switching to %s port\n", - dev->name, if_names[dev->if_port]); - do_reset(dev,1); /* not the fine way :-) */ - } - else + DEBUG(0, "do_config(%p)\n", dev); + if (map->port != 255 && map->port != dev->if_port) { + if (local->new_mii) + return -EOPNOTSUPP; + if (map->port > 4) return -EINVAL; + if (!map->port) { + local->probe_port = 1; + dev->if_port = 1; + } else { + local->probe_port = 0; + dev->if_port = map->port; + } + printk(KERN_INFO "%s: switching to %s port\n", + dev->name, if_names[dev->if_port]); + do_reset(dev,1); /* not the fine way :-) */ } #ifdef PCMCIA_DEBUG - else if( map->port == dev->if_port && local->mohawk ) { + else if (local->mohawk) { /* kludge to print the mii regsiters */ mii_dump(dev); } @@ -1926,17 +1815,14 @@ do_open(struct net_device *dev) local_info_t *lp = dev->priv; dev_link_t *link; - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "do_open(%p)\n", dev ); - #endif + DEBUG(0, "do_open(%p)\n", dev); /* Check that the PCMCIA card is still here. */ - for( link = dev_list; link; link = link->next ) - if( link->priv == dev ) + for (link = dev_list; link; link = link->next) + if (link->priv == dev) break; /* Physical device present signature. */ - if( !DEV_OK(link) ) + if (!DEV_OK(link)) return -ENODEV; /* okay */ @@ -1957,25 +1843,22 @@ do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ioaddr_t ioaddr = dev->base_addr; u16 *data = (u16 *)&rq->ifr_data; - #ifdef PCMCIA_DEBUG - if(pc_debug > 1) - printk(KERN_DEBUG "%s: ioctl(%-.6s, %#04x) %04x %04x %04x %04x\n", - dev->name, rq->ifr_ifrn.ifrn_name, cmd, - data[0], data[1], data[2], data[3] ); - #endif + DEBUG(1, "%s: ioctl(%-.6s, %#04x) %04x %04x %04x %04x\n", + dev->name, rq->ifr_ifrn.ifrn_name, cmd, + data[0], data[1], data[2], data[3]); - if( !local->mohawk ) + if (!local->mohawk) return -EOPNOTSUPP; - switch( cmd ) { + switch(cmd) { case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ data[0] = 0; /* we have only this address */ /* fall trough */ case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ - data[3] = mii_rd( ioaddr, data[0] & 0x1f, data[1] & 0x1f); + data[3] = mii_rd(ioaddr, data[0] & 0x1f, data[1] & 0x1f); break; case SIOCDEVPRIVATE+2: /* Write the specified MII register */ - if( !suser() ) + if (!suser()) return -EPERM; mii_wr(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2], 16); break; @@ -1995,7 +1878,7 @@ hardreset(struct net_device *dev) udelay(1); PutByte(XIRCREG4_GPR1, 0); /* clear bit 0: power down */ busy_loop(HZ/25); /* wait 40 msec */ - if( local->mohawk ) + if (local->mohawk) PutByte(XIRCREG4_GPR1, 1); /* set bit 0: power up */ else PutByte(XIRCREG4_GPR1, 1 | 4); /* set bit 0: power up, bit 2: AIC */ @@ -2009,18 +1892,14 @@ do_reset(struct net_device *dev, int full) ioaddr_t ioaddr = dev->base_addr; unsigned value; - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KERN_DEBUG "%s: do_reset(%p,%d)\n", - dev? dev->name:"eth?", dev, full ); - #endif + DEBUG(0, "%s: do_reset(%p,%d)\n", dev? dev->name:"eth?", dev, full); hardreset(dev); - PutByte(XIRCREG_CR, SoftReset ); /* set */ + PutByte(XIRCREG_CR, SoftReset); /* set */ busy_loop(HZ/50); /* wait 20 msec */ - PutByte(XIRCREG_CR, 0 ); /* clear */ + PutByte(XIRCREG_CR, 0); /* clear */ busy_loop(HZ/25); /* wait 40 msec */ - if( local->mohawk ) { + if (local->mohawk) { SelectPage(4); /* set pin GP1 and GP2 to output (0x0c) * set GP1 to low to power up the ML6692 (0x00) @@ -2036,25 +1915,23 @@ do_reset(struct net_device *dev, int full) local->silicon = local->mohawk ? (GetByte(XIRCREG4_BOV) & 0x70) >> 4 : (GetByte(XIRCREG4_BOV) & 0x30) >> 4; - if( local->probe_port ) { - if( !local->mohawk ) { + if (local->probe_port) { + if (!local->mohawk) { SelectPage(4); PutByte(XIRCREG4_GPR0, 4); local->probe_port = 0; } - } - else if( dev->if_port == 2 ) { /* enable 10Base2 */ + } else if (dev->if_port == 2) { /* enable 10Base2 */ SelectPage(0x42); PutByte(XIRCREG42_SWC1, 0xC0); - } - else { /* enable 10BaseT */ + } else { /* enable 10BaseT */ SelectPage(0x42); PutByte(XIRCREG42_SWC1, 0x80); } busy_loop(HZ/25); /* wait 40 msec to let it complete */ #ifdef PCMCIA_DEBUG - if(pc_debug) { + if (pc_debug) { SelectPage(0); value = GetByte(XIRCREG_ESR); /* read the ESR */ printk(KERN_DEBUG "%s: ESR is: %#02x\n", dev->name, value); @@ -2063,33 +1940,30 @@ do_reset(struct net_device *dev, int full) /* setup the ECR */ SelectPage(1); - PutByte(XIRCREG1_IMR0, 0xff ); /* allow all ints */ + PutByte(XIRCREG1_IMR0, 0xff); /* allow all ints */ PutByte(XIRCREG1_IMR1, 1 ); /* and Set TxUnderrunDetect */ value = GetByte(XIRCREG1_ECR); #if 0 - if( local->mohawk ) + if (local->mohawk) value |= DisableLinkPulse; PutByte(XIRCREG1_ECR, value); #endif - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KERN_DEBUG "%s: ECR is: %#02x\n", dev->name, value); - #endif + DEBUG(0, "%s: ECR is: %#02x\n", dev->name, value); SelectPage(0x42); PutByte(XIRCREG42_SWC0, 0x20); /* disable source insertion */ - if( local->silicon != 1 ) { + if (local->silicon != 1) { /* set the local memory dividing line. * The comments in the sample code say that this is only * settable with the scipper version 2 which is revision 0. * Always for CE3 cards */ SelectPage(2); - PutWord(XIRCREG2_RBS, 0x2000 ); + PutWord(XIRCREG2_RBS, 0x2000); } - if( full ) + if (full) set_addresses(dev); /* Hardware workaround: @@ -2097,7 +1971,7 @@ do_reset(struct net_device *dev, int full) * to move the offset pointer back to 0. */ SelectPage(0); - PutWord(XIRCREG0_DO, 0x2000 ); /* change offset command, off=0 */ + PutWord(XIRCREG0_DO, 0x2000); /* change offset command, off=0 */ /* setup MAC IMRs and clear status registers */ SelectPage(0x40); /* Bit 7 ... bit 0 */ @@ -2108,36 +1982,23 @@ do_reset(struct net_device *dev, int full) PutByte(XIRCREG40_TXST0, 0x00); /* TOK, TAB, SQE, LL, TU, JAB, EXC, CRS */ PutByte(XIRCREG40_TXST1, 0x00); /* TEN, rsv, PTD, EXT, retry_counter:4 */ - if( full && local->mohawk && init_mii(dev) ) { - if( dev->if_port == 4 || local->dingo ) { /* and use it */ - SelectPage(2); - value = GetByte(XIRCREG2_MSR); - value |= 0x08; /* Select MII */ - PutByte(XIRCREG2_MSR, value); - busy_loop(HZ/50); /* wait 20 msec */ - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KERN_DEBUG "%s: MII selected\n", dev->name); - #endif - } - else { + if (full && local->mohawk && init_mii(dev)) { + if (dev->if_port == 4 || local->dingo || local->new_mii) { + printk(KERN_INFO "%s: MII selected\n", dev->name); SelectPage(2); PutByte(XIRCREG2_MSR, GetByte(XIRCREG2_MSR) | 0x08); busy_loop(HZ/50); - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KERN_DEBUG "%s: MII detected; using 10mbs\n", - dev->name); - #endif + } else { + printk(KERN_INFO "%s: MII detected; using 10mbs\n", + dev->name); SelectPage(0x42); - if( dev->if_port == 2 ) /* enable 10Base2 */ + if (dev->if_port == 2) /* enable 10Base2 */ PutByte(XIRCREG42_SWC1, 0xC0); else /* enable 10BaseT */ PutByte(XIRCREG42_SWC1, 0x80); busy_loop(HZ/25); /* wait 40 msec to let it complete */ } - } - else { /* No MII */ + } else { /* No MII */ SelectPage(0); value = GetByte(XIRCREG_ESR); /* read the ESR */ dev->if_port = (value & MediaSelect) ? 1 : 2; @@ -2145,34 +2006,34 @@ do_reset(struct net_device *dev, int full) /* configure the LEDs */ SelectPage(2); - if( dev->if_port == 1 || dev->if_port == 4 ) /* TP: Link and Activity */ - PutByte(XIRCREG2_LED, 0x3b ); + if (dev->if_port == 1 || dev->if_port == 4) /* TP: Link and Activity */ + PutByte(XIRCREG2_LED, 0x3b); else /* Coax: Not-Collision and Activity */ - PutByte(XIRCREG2_LED, 0x3a ); + PutByte(XIRCREG2_LED, 0x3a); if (local->dingo) - PutByte( 0x0b, 0x04 ); /* 100 Mbit LED */ + PutByte(0x0b, 0x04); /* 100 Mbit LED */ /* enable receiver and put the mac online */ - if( full ) { + if (full) { SelectPage(0x40); - PutByte(XIRCREG40_CMD0, EnableRecv | Online ); + PutByte(XIRCREG40_CMD0, EnableRecv | Online); } /* setup Ethernet IMR and enable interrupts */ SelectPage(1); - PutByte(XIRCREG1_IMR0, 0xff ); + PutByte(XIRCREG1_IMR0, 0xff); udelay(1); SelectPage(0); - PutByte(XIRCREG_CR, EnableIntr ); - if( local->modem && !local->dingo ) { /* do some magic */ - if( !(GetByte( 0x10 ) & 0x01 ) ) - PutByte( 0x10, 0x11 ); /* unmask master-int bit */ + PutByte(XIRCREG_CR, EnableIntr); + if (local->modem && !local->dingo) { /* do some magic */ + if (!(GetByte(0x10) & 0x01)) + PutByte(0x10, 0x11); /* unmask master-int bit */ } - if( full ) - printk(KERN_INFO "%s: media %s, silicon revision %d\n", dev->name, - if_names[dev->if_port], local->silicon); + if (full) + printk(KERN_INFO "%s: media %s, silicon revision %d\n", + dev->name, if_names[dev->if_port], local->silicon); /* We should switch back to page 0 to avoid a bug in revision 0 * where regs with offset below 8 can't be read after an access * to the MAC registers */ @@ -2192,68 +2053,70 @@ init_mii(struct net_device *dev) int i; #ifdef PCMCIA_DEBUG - if(pc_debug>1) { + if (pc_debug>1) { mii_dump(dev); } #endif - status = mii_rd(ioaddr, 0, 1 ); - if( (status & 0xff00) != 0x7800 ) + status = mii_rd(ioaddr, 0, 1); + if ((status & 0xff00) != 0x7800) return 0; /* No MII */ - if( local->probe_port ) + local->new_mii = (mii_rd(ioaddr, 0, 2) != 0xffff); + + if (local->new_mii || local->probe_port) control = 0x1000; /* auto neg */ - else if( dev->if_port == 4 ) + else if (dev->if_port == 4) control = 0x2000; /* no auto neg, 100mbs mode */ else control = 0x0000; /* no auto neg, 10mbs mode */ - mii_wr(ioaddr, 0, 0, control, 16 ); + mii_wr(ioaddr, 0, 0, control, 16); udelay(100); - control = mii_rd(ioaddr, 0, 0 ); + control = mii_rd(ioaddr, 0, 0); - if( control & 0x0400 ) { + if (control & 0x0400) { printk(KERN_NOTICE "%s can't take PHY out of isolation mode\n", - dev->name); + dev->name); local->probe_port = 0; return 0; } - if( local->probe_port ) { + if (local->new_mii || local->probe_port) { /* according to the DP83840A specs the auto negotation process * may take up to 3.5 sec, so we use this also for our ML6692 * Fixme: Better to use a timer here! */ - for(i=0; i < 35; i++ ) { + for (i=0; i < 35; i++) { busy_loop(HZ/10); /* wait 100 msec */ - status = mii_rd(ioaddr, 0, 1 ); - if( (status & 0x0020) && (status & 0x0004) ) + status = mii_rd(ioaddr, 0, 1); + if ((status & 0x0020) && (status & 0x0004)) break; } - if( !(status & 0x0020) ) { - printk(KERN_NOTICE "%s: auto negotation failed;" - " using 10mbs\n", dev->name ); - control = 0x0000; - mii_wr(ioaddr, 0, 0, control, 16 ); - udelay(100); - SelectPage(0); - dev->if_port = (GetByte(XIRCREG_ESR) & MediaSelect) ? 1 : 2; - } - else { - linkpartner = mii_rd(ioaddr, 0, 5 ); - printk(KERN_INFO "%s: MII link partner: %04x\n", dev->name, - linkpartner ); - if( linkpartner & 0x0080 ) { /* 100BaseTx capability */ - dev->if_port = 4; + if (!(status & 0x0020)) { + printk(KERN_INFO "%s: auto negotation failed;" + " using 10mbs\n", dev->name); + if (!local->new_mii) { + control = 0x0000; + mii_wr(ioaddr, 0, 0, control, 16); + udelay(100); + SelectPage(0); + dev->if_port = (GetByte(XIRCREG_ESR) & MediaSelect) ? 1 : 2; } - else + } else { + linkpartner = mii_rd(ioaddr, 0, 5); + printk(KERN_INFO "%s: MII link partner: %04x\n", + dev->name, linkpartner); + if (linkpartner & 0x0080) { + dev->if_port = 4; + } else dev->if_port = 1; } local->probe_port = 0; } #ifdef PCMCIA_DEBUG - if( pc_debug ) + if (pc_debug) mii_dump(dev); #endif @@ -2266,10 +2129,7 @@ do_powerdown(struct net_device *dev) ioaddr_t ioaddr = dev->base_addr; - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "do_powerdown(%p)\n", dev ); - #endif + DEBUG(0, "do_powerdown(%p)\n", dev); SelectPage(4); PutByte(XIRCREG4_GPR1, 0); /* clear bit 0: power down */ @@ -2277,33 +2137,26 @@ do_powerdown(struct net_device *dev) } static int -do_stop( struct net_device *dev) +do_stop(struct net_device *dev) { ioaddr_t ioaddr = dev->base_addr; dev_link_t *link; - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "do_stop(%p)\n", dev ); - #endif + DEBUG(0, "do_stop(%p)\n", dev); - for(link = dev_list; link; link = link->next) - if(link->priv == dev) + for (link = dev_list; link; link = link->next) + if (link->priv == dev) break; - if( !link ) + if (!link) return -ENODEV; - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "shutting down\n"); - #endif dev->tbusy = 1; dev->start = 0; SelectPage(0); - PutByte(XIRCREG_CR, 0 ); /* disable interrupts */ + PutByte(XIRCREG_CR, 0); /* disable interrupts */ SelectPage(0x01); - PutByte(XIRCREG1_IMR0, 0x00 ); /* forbid all ints */ + PutByte(XIRCREG1_IMR0, 0x00); /* forbid all ints */ SelectPage(4); PutByte(XIRCREG4_GPR1, 0); /* clear bit 0: power down */ SelectPage(0); @@ -2326,19 +2179,16 @@ init_xirc2ps_cs(void) servinfo_t serv; printk(KERN_INFO "%s\n", version); - if( card_type ) + if (card_type) printk(KINF_XIRC "option card_type is obsolete\n"); - if( lockup_hack ) + if (lockup_hack) printk(KINF_XIRC "lockup hack is enabled\n"); CardServices(GetCardServicesInfo, &serv); - if( serv.Revision != CS_RELEASE_CODE ) { + if (serv.Revision != CS_RELEASE_CODE) { printk(KNOT_XIRC "Card Services release does not match!\n"); return -1; } - #ifdef PCMCIA_DEBUG - if( pc_debug ) - printk(KDBG_XIRC "pc_debug=%d\n", pc_debug); - #endif + DEBUG(0, "pc_debug=%d\n", pc_debug); register_pccard_driver(&dev_info, &xirc2ps_attach, &xirc2ps_detach); return 0; } @@ -2346,16 +2196,13 @@ init_xirc2ps_cs(void) static void __exit exit_xirc2ps_cs(void) { - #ifdef PCMCIA_DEBUG - if(pc_debug) - printk(KDBG_XIRC "unloading\n"); - #endif + DEBUG(0, "unloading\n"); unregister_pccard_driver(&dev_info); - while( dev_list ) { - if( dev_list->state & DEV_CONFIG ) - xirc2ps_release( (u_long)dev_list ); - if( dev_list ) /* xirc2ps_release() might already have detached... */ - xirc2ps_detach( dev_list ); + while (dev_list) { + if (dev_list->state & DEV_CONFIG) + xirc2ps_release((u_long)dev_list); + if (dev_list) /* xirc2ps_release() might already have detached... */ + xirc2ps_detach(dev_list); } } diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index 552061da11d0..43b5508ae5ef 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -64,6 +64,7 @@ struct asyncppp { struct ppp_channel chan; /* interface to generic ppp layer */ int connected; + int index; unsigned char obuf[OBUFSIZE]; }; @@ -387,6 +388,7 @@ ppp_async_ioctl(struct tty_struct *tty, struct file *file, if (err != 0) break; ap->connected = 1; + ap->index = val; break; case PPPIOCDETACH: err = -ENXIO; @@ -396,6 +398,14 @@ ppp_async_ioctl(struct tty_struct *tty, struct file *file, ap->connected = 0; err = 0; break; + case PPPIOCGUNIT: + err = -ENXIO; + if (!ap->connected) + break; + if (put_user(ap->index, (int *) arg)) + break; + err = 0; + break; case TCGETS: case TCGETA: diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c index 9d9b9d633902..d2756c92fda5 100644 --- a/drivers/net/seeq8005.c +++ b/drivers/net/seeq8005.c @@ -30,6 +30,7 @@ static const char *version = 0.48 Receive working */ +#include #include #include #include @@ -780,7 +781,7 @@ void cleanup_module(void) /* * If we don't do this, we can't re-insmod it later. */ - release_region(dev_seeq.base_addr, EL1_IO_EXTENT); + release_region(dev_seeq.base_addr, SEEQ8005_IO_EXTENT); } #endif /* MODULE */ diff --git a/drivers/net/setup.c b/drivers/net/setup.c index 63e311d56972..184d34613c43 100644 --- a/drivers/net/setup.c +++ b/drivers/net/setup.c @@ -260,7 +260,7 @@ static void __init network_ldisc_init(void) strip_init_ctrl_dev(); #endif #if defined(CONFIG_PPP) - ppp_init(): + ppp_init(); #endif } @@ -368,4 +368,4 @@ void __init net_device_init(void) /* That kicks off the legacy init functions */ } - \ No newline at end of file + diff --git a/drivers/pcmcia/bulkmem.c b/drivers/pcmcia/bulkmem.c index 7eaad9626ed8..60d227494789 100644 --- a/drivers/pcmcia/bulkmem.c +++ b/drivers/pcmcia/bulkmem.c @@ -2,7 +2,7 @@ PCMCIA Bulk Memory Services - bulkmem.c 1.32 1999/09/15 15:32:19 + bulkmem.c 1.33 1999/10/25 20:03:33 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -15,7 +15,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index 490182e0093d..440fd39c5355 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -2,7 +2,7 @@ Cardbus device configuration - cardbus.c 1.61 1999/10/20 22:36:57 + cardbus.c 1.63 1999/11/08 20:47:02 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -15,7 +15,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -190,7 +190,7 @@ int cb_setup_cis_mem(socket_info_t *s, int space) sz &= PCI_BASE_ADDRESS_MEM_MASK; sz = FIND_FIRST_BIT(sz); if (sz < PAGE_SIZE) sz = PAGE_SIZE; - if (find_mem_region(&base, sz, "cb_enabler", sz, 0) != 0) { + if (find_mem_region(&base, sz, sz, 0, "cb_enabler") != 0) { printk(KERN_NOTICE "cs: could not allocate %dK memory for" " CardBus socket %d\n", sz/1024, s->sock); return CS_OUT_OF_RESOURCE; @@ -413,7 +413,8 @@ int cb_config(socket_info_t *s) s->io[0].NumPorts = num[B_IO]; s->io[0].BasePort = 0; if (num[B_IO]) { - if (find_io_region(&s->io[0].BasePort, num[B_IO], name) != 0) { + if (find_io_region(&s->io[0].BasePort, num[B_IO], + num[B_IO], name) != 0) { printk(KERN_NOTICE "cs: could not allocate %d IO ports for" " CardBus socket %d\n", num[B_IO], s->sock); goto failed; @@ -423,8 +424,8 @@ int cb_config(socket_info_t *s) s->win[0].size = num[B_M1]; s->win[0].base = 0; if (num[B_M1]) { - if (find_mem_region(&s->win[0].base, num[B_M1], - name, num[B_M1], 0) != 0) { + if (find_mem_region(&s->win[0].base, num[B_M1], num[B_M1], + 0, name) != 0) { printk(KERN_NOTICE "cs: could not allocate %dK memory for" " CardBus socket %d\n", num[B_M1]/1024, s->sock); goto failed; @@ -434,8 +435,8 @@ int cb_config(socket_info_t *s) s->win[1].size = num[B_M2]; s->win[1].base = 0; if (num[B_M2]) { - if (find_mem_region(&s->win[1].base, num[B_M2], - name, num[B_M2], 0) != 0) { + if (find_mem_region(&s->win[1].base, num[B_M2], num[B_M2], + 0, name) != 0) { printk(KERN_NOTICE "cs: could not allocate %dK memory for" " CardBus socket %d\n", num[B_M2]/1024, s->sock); goto failed; diff --git a/drivers/pcmcia/cb_enabler.c b/drivers/pcmcia/cb_enabler.c index 00cf824b31ba..f8fef22ed963 100644 --- a/drivers/pcmcia/cb_enabler.c +++ b/drivers/pcmcia/cb_enabler.c @@ -2,7 +2,7 @@ Cardbus device enabler - cb_enabler.c 1.24 1999/10/20 00:19:09 + cb_enabler.c 1.25 1999/10/25 20:03:33 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -15,7 +15,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -58,7 +58,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = -"cb_enabler.c 1.24 1999/10/20 00:19:09 (David Hinds)"; +"cb_enabler.c 1.25 1999/10/25 20:03:33 (David Hinds)"; #else #define DEBUG(n, args...) do { } while (0) #endif diff --git a/drivers/pcmcia/cirrus.h b/drivers/pcmcia/cirrus.h index 43527010ac2d..34a3086cb479 100644 --- a/drivers/pcmcia/cirrus.h +++ b/drivers/pcmcia/cirrus.h @@ -1,5 +1,5 @@ /* - * cirrus.h 1.3 1999/08/28 04:01:46 + * cirrus.h 1.4 1999/10/25 20:03:34 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 690ea894f307..45c08258c8d2 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -2,7 +2,7 @@ PCMCIA Card Information Structure parser - cistpl.c 1.72 1999/09/15 15:32:19 + cistpl.c 1.74 1999/11/08 20:47:02 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -15,7 +15,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -206,7 +206,7 @@ int setup_cis_mem(socket_info_t *s) s->cis_mem.sys_start = 0; vs = NULL; if (find_mem_region(&s->cis_mem.sys_start, s->cap.map_size, - "card services", s->cap.map_size, low)) { + s->cap.map_size, low, "card services")) { printk(KERN_NOTICE "cs: unable to map card memory!\n"); return CS_OUT_OF_RESOURCE; } diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index f7fda7d8da19..0b3bbd77d578 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -2,7 +2,7 @@ PCMCIA Card Services -- core services - cs.c 1.232 1999/10/20 22:17:24 + cs.c 1.235 1999/11/11 17:52:05 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -15,7 +15,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -70,7 +70,7 @@ static int handle_apm_event(apm_event_t event); int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); static const char *version = -"cs.c 1.232 1999/10/20 22:17:24 (David Hinds)"; +"cs.c 1.235 1999/11/11 17:52:05 (David Hinds)"; #endif static const char *release = "Linux PCMCIA Card Services " CS_RELEASE; @@ -100,7 +100,7 @@ static const char *options = "options: " static int setup_delay = HZ/20; /* ticks */ static int resume_delay = HZ/5; /* ticks */ static int shutdown_delay = HZ/40; /* ticks */ -static int vcc_settle = HZ*3/10; /* ticks */ +static int vcc_settle = HZ*4/10; /* ticks */ static int reset_time = 10; /* usecs */ static int unreset_delay = HZ/10; /* ticks */ static int unreset_check = HZ/10; /* ticks */ @@ -268,8 +268,8 @@ static void init_socket(socket_info_t *s) /*====================================================================*/ #if defined(CONFIG_PROC_FS) && defined(PCMCIA_DEBUG) -int proc_read_clients(char *buf, char **start, off_t pos, - int count, int *eof, void *data) +static int proc_read_clients(char *buf, char **start, off_t pos, + int count, int *eof, void *data) { socket_info_t *s = data; client_handle_t c; @@ -708,14 +708,28 @@ static int handle_apm_event(apm_event_t event) ======================================================================*/ static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base, - ioaddr_t num, char *name) + ioaddr_t num, u_int lines, char *name) { int i; - ioaddr_t try; - + ioaddr_t try, align; + + align = (*base) ? (1<io[i].NumPorts == 0) { - if (find_io_region(base, num, name) == 0) { + if (find_io_region(base, num, align, name) == 0) { s->io[i].Attributes = attr; s->io[i].BasePort = *base; s->io[i].NumPorts = s->io[i].InUse = num; @@ -727,7 +741,7 @@ static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base, /* Try to extend top of window */ try = s->io[i].BasePort + s->io[i].NumPorts; if ((*base == 0) || (*base == try)) - if (find_io_region(&try, num, name) == 0) { + if (find_io_region(&try, num, 0, name) == 0) { *base = try; s->io[i].NumPorts += num; s->io[i].InUse += num; @@ -736,7 +750,7 @@ static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base, /* Try to extend bottom of window */ try = s->io[i].BasePort - num; if ((*base == 0) || (*base == try)) - if (find_io_region(&try, num, name) == 0) { + if (find_io_region(&try, num, 0, name) == 0) { s->io[i].BasePort = *base = try; s->io[i].NumPorts += num; s->io[i].InUse += num; @@ -1699,12 +1713,14 @@ static int request_io(client_handle_t handle, io_req_t *req) return CS_BAD_ATTRIBUTE; if (alloc_io_space(s, req->Attributes1, &req->BasePort1, - req->NumPorts1, handle->dev_info)) + req->NumPorts1, req->IOAddrLines, + handle->dev_info)) return CS_IN_USE; if (req->NumPorts2) { if (alloc_io_space(s, req->Attributes2, &req->BasePort2, - req->NumPorts2, handle->dev_info)) { + req->NumPorts2, req->IOAddrLines, + handle->dev_info)) { release_io_space(s, req->BasePort1, req->NumPorts1); return CS_IN_USE; } @@ -1836,10 +1852,11 @@ static int request_window(client_handle_t *handle, win_req_t *req) win->size = req->Size; align = ((s->cap.features & SS_CAP_MEM_ALIGN) || (req->Attributes & WIN_STRICT_ALIGN)); - if (find_mem_region(&win->base, win->size, (*handle)->dev_info, + if (find_mem_region(&win->base, win->size, (align ? req->Size : s->cap.map_size), (req->Attributes & WIN_MAP_BELOW_1MB) || - !(s->cap.features & SS_CAP_PAGE_REGS))) + !(s->cap.features & SS_CAP_PAGE_REGS), + (*handle)->dev_info)) return CS_IN_USE; req->Base = win->base; (*handle)->state |= CLIENT_WIN_REQ(w); @@ -2202,6 +2219,9 @@ EXPORT_SYMBOL(register_ss_entry); EXPORT_SYMBOL(unregister_ss_entry); EXPORT_SYMBOL(CardServices); EXPORT_SYMBOL(MTDHelperEntry); +#ifdef CONFIG_PROC_FS +EXPORT_SYMBOL(proc_pccard); +#endif static int __init init_pcmcia_cs(void) { diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index aca0a0d0cac5..a49d4e0b5f2e 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -1,5 +1,5 @@ /* - * cs_internal.h 1.43 1999/09/07 15:19:04 + * cs_internal.h 1.46 1999/11/08 20:46:49 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. */ @@ -241,9 +241,10 @@ int copy_memory(memory_handle_t handle, copy_op_t *req); /* In rsrc_mgr */ void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long), int force_low); -int find_io_region(ioaddr_t *base, ioaddr_t num, char *name); -int find_mem_region(u_long *base, u_long num, char *name, - u_long align, int force_low); +int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align, + char *name); +int find_mem_region(u_long *base, u_long num, u_long align, + int force_low, char *name); int try_irq(u_int Attributes, int irq, int specific); void undo_irq(u_int Attributes, int irq); int adjust_resource_info(client_handle_t handle, adjust_t *adj); @@ -253,15 +254,6 @@ int proc_read_io(char *buf, char **start, off_t pos, int proc_read_mem(char *buf, char **start, off_t pos, int count, int *eof, void *data); -/* in pnp components */ -int proc_read_irq(char *buf, char **start, off_t pos, - int count, int *eof, void *data); -void pnp_bios_init(void); -void pnp_proc_init(void); -void pnp_proc_done(void); -void pnp_rsrc_init(void); -void pnp_rsrc_done(void); - #define MAX_SOCK 8 extern socket_t sockets; extern socket_info_t *socket_table[MAX_SOCK]; diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 71550228ba21..7713002a5277 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -2,7 +2,7 @@ PC Card Driver Services - ds.c 1.98 1999/09/15 15:32:19 + ds.c 1.100 1999/11/08 20:47:02 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -15,7 +15,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -57,7 +58,7 @@ int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static const char *version = -"ds.c 1.98 1999/09/15 15:32:19 (David Hinds)"; +"ds.c 1.100 1999/11/08 20:47:02 (David Hinds)"; #else #define DEBUG(n, args...) #endif @@ -66,7 +67,7 @@ static const char *version = typedef struct driver_info_t { dev_info_t dev_info; - int use_count; + int use_count, status; dev_link_t *(*attach)(void); void (*detach)(dev_link_t *); struct driver_info_t *next; @@ -116,6 +117,11 @@ static driver_info_t *root_driver = NULL; static int sockets = 0, major_dev = -1; static socket_info_t *socket_table = NULL; +extern struct proc_dir_entry *proc_pccard; + +/* We use this to distinguish in-kernel from modular drivers */ +static int init_status = 1; + /*====================================================================*/ static void cs_error(client_handle_t handle, int func, int ret) @@ -149,6 +155,7 @@ int register_pccard_driver(dev_info_t *dev_info, driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL); strncpy(driver->dev_info, (char *)dev_info, DEV_NAME_LEN); driver->use_count = 0; + driver->status = init_status; driver->next = root_driver; root_driver = driver; } @@ -200,6 +207,21 @@ int unregister_pccard_driver(dev_info_t *dev_info) return 0; } /* unregister_pccard_driver */ +/*====================================================================*/ + +#ifdef CONFIG_PROC_FS +static int proc_read_drivers(char *buf, char **start, off_t pos, + int count, int *eof, void *data) +{ + driver_info_t *d; + char *p = buf; + for (d = root_driver; d; d = d->next) + p += sprintf(p, "%-24.24s %d %d\n", d->dev_info, + d->status, d->use_count); + return (p - buf); +} +#endif + /*====================================================================== These manage a ring buffer of events pending for one user process @@ -874,7 +896,15 @@ int __init init_pcmcia_ds(void) "Driver Services\n"); else major_dev = i; - + +#ifdef CONFIG_PROC_FS + if (proc_pccard) { + struct proc_dir_entry *ent; + ent = create_proc_entry("drivers", 0, proc_pccard); + ent->read_proc = proc_read_drivers; + } + init_status = 0; +#endif return 0; } @@ -888,6 +918,10 @@ int __init init_module(void) void __exit cleanup_module(void) { int i; +#ifdef CONFIG_PROC_FS + if (proc_pccard) + remove_proc_entry("drivers", proc_pccard); +#endif if (major_dev != -1) unregister_chrdev(major_dev, "pcmcia"); for (i = 0; i < sockets; i++) diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index ed7bd3c30e88..685e65fe9caa 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c @@ -3,7 +3,7 @@ Device driver for Intel 82365 and compatible PC Card controllers, and Yenta-compatible PCI-to-CardBus controllers. - i82365.c 1.260 1999/10/21 00:56:07 + i82365.c 1.265 1999/11/10 18:36:21 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -16,7 +16,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -76,7 +76,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static const char *version = -"i82365.c 1.260 1999/10/21 00:56:07 (David Hinds)"; +"i82365.c 1.265 1999/11/10 18:36:21 (David Hinds)"; #else #define DEBUG(n, args...) do { } while (0) #endif @@ -189,7 +189,7 @@ MODULE_PARM(cb_write_post, "i"); #ifdef CONFIG_ISA #ifdef CONFIG_PCI /* PCI card status change interrupts? */ -static int pci_csc = 1; +static int pci_csc = 0; /* PCI IO card functional interrupts? */ static int pci_int = 0; MODULE_PARM(pci_csc, "i"); @@ -903,7 +903,8 @@ static void o2micro_get_state(u_short s) { socket_info_t *t = &socket[s]; o2micro_state_t *p = &socket[s].state.o2micro; - if ((t->revision == 0x34) || (t->revision == 0x62)) { + if ((t->revision == 0x34) || (t->revision == 0x62) || + (t->type == IS_OZ6812)) { p->mode_a = i365_get(s, O2_MODE_A_2); p->mode_b = i365_get(s, O2_MODE_B_2); } else { @@ -923,7 +924,8 @@ static void o2micro_set_state(u_short s) { socket_info_t *t = &socket[s]; o2micro_state_t *p = &socket[s].state.o2micro; - if ((t->revision == 0x34) || (t->revision == 0x62)) { + if ((t->revision == 0x34) || (t->revision == 0x62) || + (t->type == IS_OZ6812)) { i365_set(s, O2_MODE_A_2, p->mode_a); i365_set(s, O2_MODE_B_2, p->mode_b); } else { @@ -1007,6 +1009,7 @@ static int topic_set_irq_mode(u_short s, int pcsc, int pint) flip(p->ccr, TOPIC97_ICR_IRQSEL, pcsc); return 0; } else { + /* no ISA card status change irq */ return !pcsc; } } @@ -1541,7 +1544,8 @@ static void __init add_pcic(int ns, int type) #ifdef CONFIG_ISA /* Poll if only two interrupts available */ if (!use_pci && !poll_interval) { - u_int tmp = (mask & (mask-1)); + u_int tmp = (mask & 0xff20); + tmp = tmp & (tmp-1); if ((tmp & (tmp-1)) == 0) poll_interval = HZ; } @@ -1627,7 +1631,7 @@ static void __init add_cb_bridge(int type, u_char bus, u_char devfn, u_short v, u_short d0) { socket_info_t *s = &socket[sockets]; - u_short d, ns; + u_short d, ns, i; u_char a, b, r, max; /* PCI bus enumeration is broken on some systems */ @@ -1666,7 +1670,6 @@ static void __init add_cb_bridge(int type, u_char bus, u_char devfn, pci_writel(bus, devfn, CB_LEGACY_MODE_BASE, 0); pci_readl(bus, devfn, PCI_BASE_ADDRESS_0, &s->cb_phys); if (s->cb_phys == 0) { - int i; pci_writew(bus, devfn, PCI_COMMAND, CMD_DFLT); for (i = 0; i < sizeof(cb_mem_base)/sizeof(u_int); i++) { s->cb_phys = cb_mem_base[i]; @@ -1710,10 +1713,21 @@ static void __init add_cb_bridge(int type, u_char bus, u_char devfn, } add_pcic(ns, type); - /* Re-do card type & voltage detection */ - cb_writel(sockets-ns, CB_SOCKET_FORCE, CB_SF_CVSTEST); - __set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/5); + /* Re-do card voltage detection, if needed: this checks for + card presence with no voltage detect bits set */ + for (a = sockets-ns; a < sockets; a++) + if (!(cb_readl(a, CB_SOCKET_STATE) & 0x3c86)) + cb_writel(a, CB_SOCKET_FORCE, CB_SF_CVSTEST); + for (i = 0; i < 200; i++) { + for (a = sockets-ns; a < sockets; a++) + if (!(cb_readl(a, CB_SOCKET_STATE) & 0x3c86)) break; + if (a == sockets) break; + __set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/20); + } + if (i == 200) + printk(KERN_NOTICE "i82365: card voltage interrogation" + " timed out!\n"); /* Set up PCI bus bridge structures if needed */ for (a = 0; a < ns; a++) { diff --git a/drivers/pcmcia/i82365.h b/drivers/pcmcia/i82365.h index ac3ba4e878cf..085f6bd4f5d8 100644 --- a/drivers/pcmcia/i82365.h +++ b/drivers/pcmcia/i82365.h @@ -1,5 +1,5 @@ /* - * i82365.h 1.14 1999/08/28 04:01:47 + * i82365.h 1.15 1999/10/25 20:03:34 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/drivers/pcmcia/o2micro.h b/drivers/pcmcia/o2micro.h index a3f922239c02..f303aba4a116 100644 --- a/drivers/pcmcia/o2micro.h +++ b/drivers/pcmcia/o2micro.h @@ -1,5 +1,5 @@ /* - * o2micro.h 1.12 1999/10/16 01:43:24 + * o2micro.h 1.13 1999/10/25 20:03:34 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/drivers/pcmcia/ricoh.h b/drivers/pcmcia/ricoh.h index c6fceac2eb08..8cfd30dac086 100644 --- a/drivers/pcmcia/ricoh.h +++ b/drivers/pcmcia/ricoh.h @@ -1,5 +1,5 @@ /* - * ricoh.h 1.8 1999/08/28 04:01:47 + * ricoh.h 1.9 1999/10/25 20:03:34 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index 736ac0c05d53..e8a14d16f02e 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -2,7 +2,7 @@ Resource management routines - rsrc_mgr.c 1.73 1999/10/19 00:54:04 + rsrc_mgr.c 1.76 1999/11/08 20:47:02 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -15,7 +15,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -98,6 +98,14 @@ static irq_info_t irq_table[NR_IRQS] = { { 0, 0, 0 }, /* etc */ }; #endif +/*====================================================================== + + Linux resource management extensions + +======================================================================*/ + +#define check_io_region(b,n) (0) + /*====================================================================== These manage the internal databases of available resources. @@ -180,7 +188,7 @@ static void do_io_probe(ioaddr_t base, ioaddr_t num) b = kmalloc(256, GFP_KERNEL); memset(b, 0, 256); for (i = base, most = 0; i < base+num; i += 8) { - if (check_region(i, 8)) + if (check_region(i, 8) || check_io_region(i, 8)) continue; hole = inb(i); for (j = 1; j < 8; j++) @@ -193,7 +201,7 @@ static void do_io_probe(ioaddr_t base, ioaddr_t num) bad = any = 0; for (i = base; i < base+num; i += 8) { - if (check_region(i, 8)) + if (check_region(i, 8) || check_io_region(i, 8)) continue; for (j = 0; j < 8; j++) if (inb(i+j) != most) break; @@ -344,67 +352,59 @@ void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long), These find ranges of I/O ports or memory addresses that are not currently allocated by other devices. + + The 'align' field should reflect the number of bits of address + that need to be preserved from the initial value of *base. It + should be a power of two, greater than or equal to 'num'. A value + of 0 means that all bits of *base are significant. *base should + also be strictly less than 'align'. ======================================================================*/ -int find_io_region(ioaddr_t *base, ioaddr_t num, char *name) +int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align, + char *name) { - ioaddr_t align; + ioaddr_t try; resource_map_t *m; - if (*base != 0) { - for (m = io_db.next; m != &io_db; m = m->next) { - if ((*base >= m->base) && (*base+num <= m->base+m->num)) { - if (check_region(*base, num)) { - return -1; - } else { - request_region(*base, num, name); - return 0; - } - } - } - return -1; - } - - for (align = 1; align < num; align *= 2) ; for (m = io_db.next; m != &io_db; m = m->next) { - for (*base = (m->base + align - 1) & (~(align-1)); - *base+align <= m->base + m->num; - *base += align) - if (check_region(*base, num) == 0) { - request_region(*base, num, name); + try = (m->base & ~(align-1)) + *base; + for (try = (try >= m->base) ? try : try+align; + (try >= m->base) && (try+num <= m->base+m->num); + try += align) { + if ((check_region(try, num) == 0) && + (check_io_region(try, num) == 0)) { + *base = try; + request_region(try, num, name); return 0; } + if (!align) break; + } } return -1; } /* find_io_region */ -int find_mem_region(u_long *base, u_long num, char *name, - u_long align, int force_low) +int find_mem_region(u_long *base, u_long num, u_long align, + int force_low, char *name) { + u_long try; resource_map_t *m; - if (*base != 0) { - for (m = mem_db.next; m != &mem_db; m = m->next) { - if ((*base >= m->base) && (*base+num <= m->base+m->num)) - if (check_mem_region(*base, num) == 0) { - request_mem_region(*base, num, name); - return 0; - } - } - return -1; - } - while (1) { for (m = mem_db.next; m != &mem_db; m = m->next) { /* first pass >1MB, second pass <1MB */ if ((force_low != 0) ^ (m->base < 0x100000)) continue; - for (*base = (m->base + align - 1) & (~(align-1)); - *base+num <= m->base+m->num; *base += align) - if (check_mem_region(*base, num) == 0) { - request_mem_region(*base, num, name); + try = (m->base & ~(align-1)) + *base; + for (try = (try >= m->base) ? try : try+align; + (try >= m->base) && (try+num <= m->base+m->num); + try += align) { + if (check_mem_region(try, num) == 0) { + request_mem_region(try, num, name); + *base = try; return 0; } + if (!align) break; + } } if (force_low) break; force_low++; diff --git a/drivers/pcmcia/rsrc_mgr.h b/drivers/pcmcia/rsrc_mgr.h index 37faa3b26c67..739e03b2f936 100644 --- a/drivers/pcmcia/rsrc_mgr.h +++ b/drivers/pcmcia/rsrc_mgr.h @@ -1,5 +1,5 @@ /* - * rsrc_mgr.h 1.18 1999/08/28 04:01:47 + * rsrc_mgr.h 1.19 1999/10/25 20:03:34 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/drivers/pcmcia/smc34c90.h b/drivers/pcmcia/smc34c90.h index 8ac3854a4d6e..79893e9c798b 100644 --- a/drivers/pcmcia/smc34c90.h +++ b/drivers/pcmcia/smc34c90.h @@ -1,5 +1,5 @@ /* - * smc34c90.h 1.6 1999/08/28 04:01:47 + * smc34c90.h 1.7 1999/10/25 20:03:34 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c index ca2818d7c9ef..2fba49434341 100644 --- a/drivers/pcmcia/tcic.c +++ b/drivers/pcmcia/tcic.c @@ -2,7 +2,7 @@ Device driver for Databook TCIC-2 PCMCIA controller - tcic.c 1.106 1999/09/15 15:32:19 + tcic.c 1.107 1999/10/25 20:03:34 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -15,7 +15,7 @@ rights and limitations under the License. The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds + . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Alternatively, the contents of this file may be used under the @@ -60,7 +60,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); static const char *version = -"tcic.c 1.106 1999/09/15 15:32:19 (David Hinds)"; +"tcic.c 1.107 1999/10/25 20:03:34 (David Hinds)"; #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) #else #define DEBUG(n, args...) diff --git a/drivers/pcmcia/tcic.h b/drivers/pcmcia/tcic.h index e33f79531891..222341d3cda8 100644 --- a/drivers/pcmcia/tcic.h +++ b/drivers/pcmcia/tcic.h @@ -1,5 +1,5 @@ /* - * tcic.h 1.12 1999/08/28 04:01:47 + * tcic.h 1.13 1999/10/25 20:03:34 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h index 758757d995d4..f37faeba5f38 100644 --- a/drivers/pcmcia/ti113x.h +++ b/drivers/pcmcia/ti113x.h @@ -1,5 +1,5 @@ /* - * ti113x.h 1.15 1999/09/03 16:43:35 + * ti113x.h 1.16 1999/10/25 20:03:34 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/drivers/pcmcia/vg468.h b/drivers/pcmcia/vg468.h index c19d53d15c20..af0a941ed335 100644 --- a/drivers/pcmcia/vg468.h +++ b/drivers/pcmcia/vg468.h @@ -1,5 +1,5 @@ /* - * vg468.h 1.10 1999/08/28 04:01:47 + * vg468.h 1.11 1999/10/25 20:03:34 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/drivers/pcmcia/yenta.h b/drivers/pcmcia/yenta.h index 5c09f297830f..fbba0b1a3b61 100644 --- a/drivers/pcmcia/yenta.h +++ b/drivers/pcmcia/yenta.h @@ -1,5 +1,5 @@ /* - * yenta.h 1.15 1999/08/28 04:01:47 + * yenta.h 1.16 1999/10/25 20:03:34 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/drivers/scsi/53c7,8xx.c b/drivers/scsi/53c7,8xx.c index 18c87cec9a35..8991d84d414c 100644 --- a/drivers/scsi/53c7,8xx.c +++ b/drivers/scsi/53c7,8xx.c @@ -263,13 +263,6 @@ typedef unsigned int u32; #include #include -#ifndef LINUX_1_2 -struct proc_dir_entry proc_scsi_ncr53c7xx = { - PROC_SCSI_NCR53C7xx, 9, "ncr53c7xx", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; -#endif - static int check_address (unsigned long addr, int size); static void dump_events (struct Scsi_Host *host, int count); static Scsi_Cmnd * return_outstanding_commands (struct Scsi_Host *host, @@ -1568,9 +1561,7 @@ NCR53c7xx_detect(Scsi_Host_Template *tpnt){ unsigned char pci_bus, pci_device_fn; static short pci_index=0; /* Device index to PCI BIOS calls */ -#ifndef LINUX_1_2 - tpnt->proc_dir = &proc_scsi_ncr53c7xx; -#endif + tpnt->proc_name = "ncr53c7xx"; for (current_override = count = 0; current_override < OVERRIDE_LIMIT; ++current_override) { diff --git a/drivers/scsi/AM53C974.c b/drivers/scsi/AM53C974.c index e4e289775d65..25fc2aea74d3 100644 --- a/drivers/scsi/AM53C974.c +++ b/drivers/scsi/AM53C974.c @@ -390,12 +390,6 @@ override_t overrides[7] = { {-1, 0, 0, 0},}; /* LILO overrides */ -struct proc_dir_entry proc_scsi_am53c974 = -{ - PROC_SCSI_AM53C974, 8, "am53c974", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - #ifdef AM53C974_DEBUG static int deb_stop = 1; @@ -664,7 +658,7 @@ int __init AM53C974_detect(Scsi_Host_Template * tpnt) { int count = 0; /* number of boards detected */ - tpnt->proc_dir = &proc_scsi_am53c974; + tpnt->proc_name = "am53c974"; #if defined (CONFIG_PCI) if (pci_present()) diff --git a/drivers/scsi/AM53C974.h b/drivers/scsi/AM53C974.h index 41aa5e7a17b0..78c6d21f8e10 100644 --- a/drivers/scsi/AM53C974.h +++ b/drivers/scsi/AM53C974.h @@ -50,10 +50,8 @@ struct AM53C974_hostdata { unsigned char max_offset[8]; /* max. sync. offset (setup), only valid if corresponding sync_en is nonzero */ }; -extern struct proc_dir_entry proc_scsi_am53c974; - #define AM53C974 { \ - proc_dir: &proc_scsi_am53c974, \ + proc_name: "am53c974", \ name: "AM53C974", \ detect: AM53C974_detect, \ release: AM53C974_release, \ diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index aa1943891212..d7850fb463ac 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -140,16 +140,6 @@ static BusLogic_ProbeInfo_T static char *BusLogic_CommandFailureReason; - -/* - BusLogic_ProcDirectoryEntry is the BusLogic /proc/scsi directory entry. -*/ - -PROC_DirectoryEntry_T - BusLogic_ProcDirectoryEntry = - { PROC_SCSI_BUSLOGIC, 8, "BusLogic", S_IFDIR | S_IRUGO | S_IXUGO, 2 }; - - /* BusLogic_AnnounceDriver announces the Driver Version and Date, Author's Name, Copyright Notice, and Electronic Mail Address. diff --git a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h index 97c1a412f3c6..9b1150e8a23c 100644 --- a/drivers/scsi/BusLogic.h +++ b/drivers/scsi/BusLogic.h @@ -52,7 +52,6 @@ typedef struct scatterlist SCSI_ScatterList_T; Define prototypes for the BusLogic Driver Interface Functions. */ -extern PROC_DirectoryEntry_T BusLogic_ProcDirectoryEntry; extern const char *BusLogic_DriverInfo(SCSI_Host_T *); extern int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *); extern int BusLogic_ReleaseHostAdapter(SCSI_Host_T *); @@ -69,7 +68,7 @@ extern int BusLogic_ProcDirectoryInfo(char *, char **, off_t, int, int, int); */ #define BUSLOGIC \ - { proc_dir: &BusLogic_ProcDirectoryEntry, /* ProcFS Directory Entry */ \ + { proc_name: "BusLogic", /* ProcFS Directory Entry */ \ proc_info: BusLogic_ProcDirectoryInfo, /* ProcFS Info Function */ \ name: "BusLogic", /* Driver Name */ \ detect: BusLogic_DetectHostAdapter, /* Detect Host Adapter */ \ diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c index 03da4ba48ea1..d5158e5b973c 100644 --- a/drivers/scsi/NCR53C9x.c +++ b/drivers/scsi/NCR53C9x.c @@ -94,11 +94,6 @@ enum { /*5*/ do_intr_end }; -struct proc_dir_entry proc_scsi_esp = { - PROC_SCSI_ESP, 3, "esp", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - /* The master ring of all esp hosts we are managing in this driver. */ struct NCR_ESP *espchain = 0; int nesps = 0, esps_in_use = 0, esps_running = 0; diff --git a/drivers/scsi/NCR53C9x.h b/drivers/scsi/NCR53C9x.h index f6724ee2c5fa..a899d7f58c16 100644 --- a/drivers/scsi/NCR53C9x.h +++ b/drivers/scsi/NCR53C9x.h @@ -625,8 +625,6 @@ struct NCR_ESP { #define ESP_TICK(ccf, cycle) ((7682 * (ccf) * (cycle) / 1000)) -extern struct proc_dir_entry proc_scsi_esp; - /* UGLY, UGLY, UGLY! */ extern int nesps, esps_in_use, esps_running; diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c index 52a9196c6b47..1ee14b6e3cff 100644 --- a/drivers/scsi/NCR53c406a.c +++ b/drivers/scsi/NCR53c406a.c @@ -212,10 +212,6 @@ static volatile int internal_done_flag = 0; static volatile int internal_done_errcode = 0; static char info_msg[256]; -struct proc_dir_entry proc_scsi_NCR53c406a = { - PROC_SCSI_NCR53C406A, 7, "NCR53c406a", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; /* ================================================================= */ /* possible BIOS locations */ @@ -571,7 +567,7 @@ NCR53c406a_detect(Scsi_Host_Template * tpnt){ #endif USE_DMA tpnt->present = 1; - tpnt->proc_dir = &proc_scsi_NCR53c406a; + tpnt->proc_name = "NCR53c406a"; shpnt = scsi_register(tpnt, 0); shpnt->irq = irq_level; diff --git a/drivers/scsi/NCR53c406a.h b/drivers/scsi/NCR53c406a.h index 4ec3abbd5365..0ef6c67ba6a7 100644 --- a/drivers/scsi/NCR53c406a.h +++ b/drivers/scsi/NCR53c406a.h @@ -26,7 +26,7 @@ * Use SG_NONE if DMA mode is enabled! */ #define NCR53c406a { \ - proc_dir: &proc_scsi_NCR53c406a /* proc_dir */, \ + proc_name: "NCR53c406a" /* proc_name */, \ name: "NCR53c406a" /* name */, \ detect: NCR53c406a_detect /* detect */, \ info: NCR53c406a_info /* info */, \ @@ -43,8 +43,6 @@ use_clustering: ENABLE_CLUSTERING \ } -extern struct proc_dir_entry proc_scsi_NCR53c406a; - int NCR53c406a_detect(Scsi_Host_Template *); const char* NCR53c406a_info(struct Scsi_Host *); diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c index 95b07bdad9e0..2302d39a8e2f 100644 --- a/drivers/scsi/a2091.c +++ b/drivers/scsi/a2091.c @@ -21,11 +21,6 @@ #include -struct proc_dir_entry proc_scsi_a2091 = { - PROC_SCSI_A2091, 5, "A2091", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - #define DMA(ptr) ((a2091_scsiregs *)((ptr)->base)) #define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata)) @@ -201,7 +196,7 @@ int __init a2091_detect(Scsi_Host_Template *tpnt) return 0; called = 1; - tpnt->proc_dir = &proc_scsi_a2091; + tpnt->proc_name = "A2091"; tpnt->proc_info = &wd33c93_proc_info; while ((key = zorro_find(ZORRO_PROD_CBM_A590_A2091_1, 0, 0)) || diff --git a/drivers/scsi/a2091.h b/drivers/scsi/a2091.h index b04ef6c25852..5a42b9300086 100644 --- a/drivers/scsi/a2091.h +++ b/drivers/scsi/a2091.h @@ -31,9 +31,7 @@ int wd33c93_reset(Scsi_Cmnd *, unsigned int); #ifdef HOSTS_C -extern struct proc_dir_entry proc_scsi_a2091; - -#define A2091_SCSI { proc_dir: &proc_scsi_a2091, \ +#define A2091_SCSI { proc_name: "A2901", \ name: "Commodore A2091/A590 SCSI", \ detect: a2091_detect, \ release: a2091_release, \ diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c index ef4b010a6470..1bc8f05fafc1 100644 --- a/drivers/scsi/a3000.c +++ b/drivers/scsi/a3000.c @@ -20,11 +20,6 @@ #include -struct proc_dir_entry proc_scsi_a3000 = { - PROC_SCSI_A3000, 5, "A3000", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - #define DMA(ptr) ((a3000_scsiregs *)((ptr)->base)) #define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata)) @@ -176,7 +171,7 @@ int __init a3000_detect(Scsi_Host_Template *tpnt) if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(A3000_SCSI)) return 0; - tpnt->proc_dir = &proc_scsi_a3000; + tpnt->proc_name = "A3000"; tpnt->proc_info = &wd33c93_proc_info; a3000_host = scsi_register (tpnt, sizeof(struct WD33C93_hostdata)); diff --git a/drivers/scsi/a3000.h b/drivers/scsi/a3000.h index c088f1d9890a..b6b6827d09d9 100644 --- a/drivers/scsi/a3000.h +++ b/drivers/scsi/a3000.h @@ -31,9 +31,7 @@ int wd33c93_reset(Scsi_Cmnd *, unsigned int); #ifdef HOSTS_C -extern struct proc_dir_entry proc_scsi_a3000; - -#define A3000_SCSI { proc_dir: &proc_scsi_a3000, \ +#define A3000_SCSI { proc_name: "A3000", \ proc_info: NULL, \ name: "Amiga 3000 built-in SCSI", \ detect: a3000_detect, \ diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 60b7b037ea65..d032e6dd072d 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -4011,19 +4011,6 @@ typedef struct _PCI_CONFIG_SPACE_ * --- Driver Data */ -/* Note: All driver global data should be initialized. */ - -#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) -struct proc_dir_entry proc_scsi_advansys = -{ - PROC_SCSI_ADVANSYS, /* unsigned short low_ino */ - 8, /* unsigned short namelen */ - "advansys", /* const char *name */ - S_IFDIR | S_IRUGO | S_IXUGO, /* mode_t mode */ - 2 /* nlink_t nlink */ -}; -#endif /* version >= v1.3.0 */ - /* Number of boards detected in system. */ STATIC int asc_board_count = 0; STATIC struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED] = { 0 }; @@ -4481,9 +4468,7 @@ advansys_detect(Scsi_Host_Template *tpnt) ASC_DBG(1, "advansys_detect: begin\n"); -#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) - tpnt->proc_dir = &proc_scsi_advansys; -#endif /* version >= v1.3.0 */ + tpnt->proc_name = "advansys"; asc_board_count = 0; diff --git a/drivers/scsi/advansys.h b/drivers/scsi/advansys.h index 010cd6153cd3..7db30e068bd3 100644 --- a/drivers/scsi/advansys.h +++ b/drivers/scsi/advansys.h @@ -40,18 +40,9 @@ const char *advansys_info(struct Scsi_Host *); int advansys_command(Scsi_Cmnd *); int advansys_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); int advansys_abort(Scsi_Cmnd *); -#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89) -int advansys_reset(Scsi_Cmnd *); -#else /* version >= v1.3.89 */ int advansys_reset(Scsi_Cmnd *, unsigned int); -#endif /* version >= v1.3.89 */ -#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0) -int advansys_biosparam(Disk *, int, int[]); -#else /* version >= v1.3.0 */ int advansys_biosparam(Disk *, kdev_t, int[]); -extern struct proc_dir_entry proc_scsi_advansys; int advansys_proc_info(char *, char **, off_t, int, int, int); -#endif /* version >= v1.3.0 */ /* init/main.c setup function */ void advansys_setup(char *, int *); @@ -59,92 +50,8 @@ void advansys_setup(char *, int *); /* * AdvanSys Host Driver Scsi_Host_Template (struct SHT) from hosts.h. */ -#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0) #define ADVANSYS { \ - NULL, /* struct SHT *next */ \ - NULL, /* int *usage_count */ \ - "advansys", /* char *name */ \ - advansys_detect, /* int (*detect)(struct SHT *) */ \ - advansys_release, /* int (*release)(struct Scsi_Host *) */ \ - advansys_info, /* const char *(*info)(struct Scsi_Host *) */ \ - advansys_command, /* int (*command)(Scsi_Cmnd *) */ \ - advansys_queuecommand, \ - /* int (*queuecommand)(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ \ - advansys_abort, /* int (*abort)(Scsi_Cmnd *) */ \ - advansys_reset, /* int (*reset)(Scsi_Cmnd *) */ \ - NULL, /* int (*slave_attach)(int, int) */ \ - advansys_biosparam, /* int (* bios_param)(Disk *, int, int []) */ \ - /* \ - * The following fields are set per adapter in advansys_detect(). \ - */ \ - 0, /* int can_queue */ \ - 0, /* int this_id */ \ - 0, /* short unsigned int sg_tablesize */ \ - 0, /* short cmd_per_lun */ \ - 0, /* unsigned char present */ \ - /* \ - * Because the driver may control an ISA adapter 'unchecked_isa_dma' \ - * must be set. The flag will be cleared in advansys_detect for non-ISA \ - * adapters. Refer to the comment in scsi_module.c for more information. \ - */ \ - 1, /* unsigned unchecked_isa_dma:1 */ \ - /* \ - * All adapters controlled by this driver are capable of large \ - * scatter-gather lists. According to the mid-level SCSI documentation \ - * this obviates any performance gain provided by setting \ - * 'use_clustering'. But empirically while CPU utilization is increased \ - * by enabling clustering, I/O throughput increases as well. \ - */ \ - ENABLE_CLUSTERING, /* unsigned use_clustering:1 */ \ -} -#elif LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,75) -#define ADVANSYS { \ - NULL, /* struct SHT *next */ \ - NULL, \ - /* version < v2.1.23 long *usage_count */ \ - /* version >= v2.1.23 struct module * */ \ - &proc_scsi_advansys, /* struct proc_dir_entry *proc_dir */ \ - advansys_proc_info, \ - /* int (*proc_info)(char *, char **, off_t, int, int, int) */ \ - "advansys", /* const char *name */ \ - advansys_detect, /* int (*detect)(struct SHT *) */ \ - advansys_release, /* int (*release)(struct Scsi_Host *) */ \ - advansys_info, /* const char *(*info)(struct Scsi_Host *) */ \ - advansys_command, /* int (*command)(Scsi_Cmnd *) */ \ - advansys_queuecommand, \ - /* int (*queuecommand)(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ \ - advansys_abort, /* int (*abort)(Scsi_Cmnd *) */ \ - advansys_reset, \ - /* version < v1.3.89 int (*reset)(Scsi_Cmnd *) */ \ - /* version >= v1.3.89 int (*reset)(Scsi_Cmnd *, unsigned int) */ \ - NULL, /* int (*slave_attach)(int, int) */ \ - advansys_biosparam, /* int (* bios_param)(Disk *, kdev_t, int []) */ \ - /* \ - * The following fields are set per adapter in advansys_detect(). \ - */ \ - 0, /* int can_queue */ \ - 0, /* int this_id */ \ - 0, /* short unsigned int sg_tablesize */ \ - 0, /* short cmd_per_lun */ \ - 0, /* unsigned char present */ \ - /* \ - * Because the driver may control an ISA adapter 'unchecked_isa_dma' \ - * must be set. The flag will be cleared in advansys_detect for non-ISA \ - * adapters. Refer to the comment in scsi_module.c for more information. \ - */ \ - 1, /* unsigned unchecked_isa_dma:1 */ \ - /* \ - * All adapters controlled by this driver are capable of large \ - * scatter-gather lists. According to the mid-level SCSI documentation \ - * this obviates any performance gain provided by setting \ - * 'use_clustering'. But empirically while CPU utilization is increased \ - * by enabling clustering, I/O throughput increases as well. \ - */ \ - ENABLE_CLUSTERING, /* unsigned use_clustering:1 */ \ -} -#else /* version >= v2.1.75 */ -#define ADVANSYS { \ - proc_dir: &proc_scsi_advansys, \ + proc_name: "advansys", \ proc_info: advansys_proc_info, \ name: "advansys", \ detect: advansys_detect, \ @@ -170,5 +77,4 @@ void advansys_setup(char *, int *); */ \ use_clustering: ENABLE_CLUSTERING, \ } -#endif /* version >= v2.1.75 */ #endif /* _ADVANSYS_H */ diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index 5c011500a239..243b0b96f8d7 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -352,12 +352,6 @@ #include -struct proc_dir_entry proc_scsi_aha152x = -{ - PROC_SCSI_AHA152X, 7, "aha152x", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - /* DEFINES */ /* For PCMCIA cards, always use AUTOCONF */ @@ -716,8 +710,7 @@ static int getphase(struct Scsi_Host *shpnt) } } -#if 0 -/* called from init/main.c */ +#ifdef PCMCIA void aha152x_setup(char *str, int *ints) { if (setup_count > 2) @@ -745,8 +738,9 @@ void aha152x_setup(char *str, int *ints) } else setup_count++; } -#endif +#endif /* PCMCIA */ +#ifndef MODULE static int __init do_aha152x_setup (char * str) { if (setup_count > 2) { @@ -765,10 +759,9 @@ controllers\n"); return 1; } -#ifndef MODULE __setup("aha152x=",do_aha152x_setup); #endif - + /* * Test, if port_base is valid. */ @@ -843,7 +836,7 @@ int aha152x_detect(Scsi_Host_Template * tpnt) aha152x_config conf; #endif - tpnt->proc_dir = &proc_scsi_aha152x; + tpnt->proc_name = "aha152x"; for (i = 0; i < IRQS; i++) aha152x_host[i] = (struct Scsi_Host *) NULL; diff --git a/drivers/scsi/aha152x.h b/drivers/scsi/aha152x.h index 95b7487bc001..8bac1ddf9cc2 100644 --- a/drivers/scsi/aha152x.h +++ b/drivers/scsi/aha152x.h @@ -26,10 +26,8 @@ int aha152x_proc_info(char *buffer, char **start, off_t offset, int length, int #define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 1.7 $" -extern struct proc_dir_entry proc_scsi_aha152x; - /* Initial value of Scsi_Host entry */ -#define AHA152X { proc_dir: &proc_scsi_aha152x, \ +#define AHA152X { proc_name: "a152x", \ proc_info: aha152x_proc_info, \ name: AHA152X_REVID, \ detect: aha152x_detect, \ diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c index ebd8cbe05afd..6f9b2e480e7a 100644 --- a/drivers/scsi/aha1542.c +++ b/drivers/scsi/aha1542.c @@ -54,11 +54,6 @@ #include -struct proc_dir_entry proc_scsi_aha1542 = { - PROC_SCSI_AHA1542, 7, "aha1542", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - #ifdef DEBUG #define DEB(x) x #else @@ -967,7 +962,7 @@ int aha1542_detect(Scsi_Host_Template * tpnt) DEB(printk("aha1542_detect: \n")); - tpnt->proc_dir = &proc_scsi_aha1542; + tpnt->proc_name = "aha1542"; #ifdef MODULE bases[0] = aha1542[0]; diff --git a/drivers/scsi/aha1542.h b/drivers/scsi/aha1542.h index 820cc4b1ce3b..d29ac0c08957 100644 --- a/drivers/scsi/aha1542.h +++ b/drivers/scsi/aha1542.h @@ -149,9 +149,7 @@ int aha1542_biosparam(Disk *, kdev_t, int*); #define NULL 0 #endif -extern struct proc_dir_entry proc_scsi_aha1542; - -#define AHA1542 { proc_dir: &proc_scsi_aha1542, \ +#define AHA1542 { proc_name: "aha1542", \ name: "Adaptec 1542", \ detect: aha1542_detect, \ command: aha1542_command, \ diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c index 96812a0ec9f0..592301e76993 100644 --- a/drivers/scsi/aha1740.c +++ b/drivers/scsi/aha1740.c @@ -44,11 +44,6 @@ #include "aha1740.h" #include -struct proc_dir_entry proc_scsi_aha1740 = { - PROC_SCSI_AHA1740, 7, "aha1740", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - /* IF YOU ARE HAVING PROBLEMS WITH THIS DRIVER, AND WANT TO WATCH IT WORK, THEN: #define DEBUG diff --git a/drivers/scsi/aha1740.h b/drivers/scsi/aha1740.h index 597ec8be34c6..036effaa4e17 100644 --- a/drivers/scsi/aha1740.h +++ b/drivers/scsi/aha1740.h @@ -170,9 +170,7 @@ int aha1740_proc_info(char *buffer, char **start, off_t offset, #define NULL 0 #endif -extern struct proc_dir_entry proc_scsi_aha1740; - -#define AHA1740 { proc_dir: &proc_scsi_aha1740, \ +#define AHA1740 { proc_name: "aha1740", \ proc_info: aha1740_proc_info, \ name: "Adaptec 174x (EISA)", \ detect: aha1740_detect, \ diff --git a/drivers/scsi/aic7xxx.c b/drivers/scsi/aic7xxx.c index 760dcc75ba8c..21e252eb441c 100644 --- a/drivers/scsi/aic7xxx.c +++ b/drivers/scsi/aic7xxx.c @@ -263,12 +263,6 @@ */ #define VIRT_TO_BUS(a) (unsigned int)virt_to_bus((void *)(a)) -struct proc_dir_entry proc_scsi_aic7xxx = { - PROC_SCSI_AIC7XXX, 7, "aic7xxx", - S_IFDIR | S_IRUGO | S_IXUGO, 2, - 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - #define AIC7XXX_C_VERSION "5.1.20" #define NUMBER(arr) (sizeof(arr) / sizeof(arr[0])) @@ -9076,7 +9070,7 @@ aic7xxx_detect(Scsi_Host_Template *template) "aic7xxx: insmod or else it might trash certain memory areas.\n"); #endif - template->proc_dir = &proc_scsi_aic7xxx; + template->proc_name = "aic7xxx"; template->sg_tablesize = AIC7XXX_MAX_SG; diff --git a/drivers/scsi/aic7xxx.h b/drivers/scsi/aic7xxx.h index 2a7f34c0a475..ffcedd96d0c9 100644 --- a/drivers/scsi/aic7xxx.h +++ b/drivers/scsi/aic7xxx.h @@ -43,11 +43,9 @@ * Scsi_Host_Template (see hosts.h) for AIC-7xxx - some fields * to do with card config are filled in after the card is detected. */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,65) #define AIC7XXX { \ next: NULL, \ module: NULL, \ - proc_dir: NULL, \ proc_info: aic7xxx_proc_info, \ name: NULL, \ detect: aic7xxx_detect, \ @@ -73,31 +71,6 @@ use_clustering: ENABLE_CLUSTERING, \ use_new_eh_code: 0 \ } -#else -#define AIC7XXX { \ - next: NULL, \ - usage_count: NULL, \ - proc_dir: NULL, \ - proc_info: aic7xxx_proc_info, \ - name: NULL, \ - detect: aic7xxx_detect, \ - release: aic7xxx_release, \ - info: aic7xxx_info, \ - command: NULL, \ - queuecommand: aic7xxx_queue, \ - abort: aic7xxx_abort, \ - reset: aic7xxx_reset, \ - slave_attach: NULL, \ - bios_param: AIC7XXX_BIOSPARAM, \ - can_queue: 255, /* max simultaneous cmds */\ - this_id: -1, /* scsi id of host adapter */\ - sg_tablesize: 0, /* max scatter-gather cmds */\ - cmd_per_lun: 3, /* cmds per lun (linked cmds) */\ - present: 0, /* number of 7xxx's present */\ - unchecked_isa_dma: 0, /* no memory DMA restrictions */\ - use_clustering: ENABLE_CLUSTERING \ -} -#endif extern int aic7xxx_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *)); extern int aic7xxx_biosparam(Disk *, kdev_t, int[]); diff --git a/drivers/scsi/amiga7xx.c b/drivers/scsi/amiga7xx.c index 96c4602be05f..f35eac3ade70 100644 --- a/drivers/scsi/amiga7xx.c +++ b/drivers/scsi/amiga7xx.c @@ -31,11 +31,6 @@ #include -struct proc_dir_entry proc_scsi_amiga7xx = { - PROC_SCSI_AMIGA7XX, 8, "Amiga7xx", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - extern int ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip, u32 base, int io_port, int irq, int dma, long long options, int clock); @@ -51,7 +46,7 @@ int __init amiga7xx_detect(Scsi_Host_Template *tpnt) if (called || !MACH_IS_AMIGA) return 0; - tpnt->proc_dir = &proc_scsi_amiga7xx; + tpnt->proc_name = "Amiga7xx"; #ifdef CONFIG_BLZ603EPLUS_SCSI if ((key = zorro_find(ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS, 0, 0))) diff --git a/drivers/scsi/amiga7xx.h b/drivers/scsi/amiga7xx.h index dbae07dbaa04..06b5ba91faaf 100644 --- a/drivers/scsi/amiga7xx.h +++ b/drivers/scsi/amiga7xx.h @@ -25,8 +25,6 @@ void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs); #if defined(HOSTS_C) || defined(MODULE) #include -extern struct proc_dir_entry proc_scsi_amiga7xx; - #define AMIGA7XX_SCSI {name: "Amiga NCR53c710 SCSI", \ detect: amiga7xx_detect, \ queuecommand: NCR53c7xx_queue_command, \ diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index a5963ad3d903..a06cd8b7ce89 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -112,11 +112,6 @@ #include -struct proc_dir_entry proc_scsi_atari = { - PROC_SCSI_ATARI, 5, "Atari", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - #define IS_A_TT() ATARIHW_PRESENT(TT_SCSI) #define SCSI_DMA_WRITE_P(elt,val) \ @@ -616,7 +611,7 @@ int atari_scsi_detect (Scsi_Host_Template *host) called) return( 0 ); - host->proc_dir = &proc_scsi_atari; + host->proc_name = "Atari"; atari_scsi_reg_read = IS_A_TT() ? atari_scsi_tt_reg_read : atari_scsi_falcon_reg_read; diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index 5d0e54153436..a8ff8703ac97 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -30,12 +30,6 @@ #include -struct proc_dir_entry proc_scsi_atp870u = -{ - PROC_SCSI_ATP870U, 7, "atp870u", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - void mydlyu(unsigned int); /* @@ -1457,7 +1451,7 @@ int atp870u_detect(Scsi_Host_Template * tpnt) printk(" NO BIOS32 SUPPORT.\n"); return count; } - tpnt->proc_dir = &proc_scsi_atp870u; + tpnt->proc_name = "atp870u"; for (h = 0; h < 2; h++) { active_idu[h] = 0; diff --git a/drivers/scsi/atp870u.h b/drivers/scsi/atp870u.h index 83698d4c7b24..13639945a2a9 100644 --- a/drivers/scsi/atp870u.h +++ b/drivers/scsi/atp870u.h @@ -34,16 +34,12 @@ void send_s870(unsigned char); #define NULL 0 #endif -extern struct proc_dir_entry proc_scsi_atp870u; - extern const char *atp870u_info(struct Scsi_Host *); extern int atp870u_proc_info(char *, char **, off_t, int, int, int); #define ATP870U { \ - next: NULL, \ - module: NULL, \ - proc_dir: &proc_scsi_atp870u, \ + proc_name: "atp870u", \ proc_info: atp870u_proc_info, \ name: NULL, \ detect: atp870u_detect, \ diff --git a/drivers/scsi/blz1230.h b/drivers/scsi/blz1230.h index 4355dd382fd6..c6503eecb2f7 100644 --- a/drivers/scsi/blz1230.h +++ b/drivers/scsi/blz1230.h @@ -57,7 +57,7 @@ extern int esp_reset(Scsi_Cmnd *, unsigned int); extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); -#define SCSI_BLZ1230 { proc_dir: &proc_scsi_esp, \ +#define SCSI_BLZ1230 { proc_name: "esp-blz1230", \ proc_info: esp_proc_info, \ name: "Blizzard1230 SCSI IV", \ detect: blz1230_esp_detect, \ diff --git a/drivers/scsi/blz2060.h b/drivers/scsi/blz2060.h index 10ec2f5a1ad5..8fc95c1f5485 100644 --- a/drivers/scsi/blz2060.h +++ b/drivers/scsi/blz2060.h @@ -53,7 +53,7 @@ extern int esp_reset(Scsi_Cmnd *, unsigned int); extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); -#define SCSI_BLZ2060 { proc_dir: &proc_scsi_esp, \ +#define SCSI_BLZ2060 { proc_name: "esp-blz2060", \ proc_info: esp_proc_info, \ name: "Blizzard2060 SCSI", \ detect: blz2060_esp_detect, \ diff --git a/drivers/scsi/bvme6000.c b/drivers/scsi/bvme6000.c index c8712e92bde5..d8d887902ac5 100644 --- a/drivers/scsi/bvme6000.c +++ b/drivers/scsi/bvme6000.c @@ -23,11 +23,6 @@ #include -struct proc_dir_entry proc_scsi_bvme6000 = { - PROC_SCSI_BVME6000, 8, "BVME6000", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - extern ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip, u32 base, int io_port, int irq, int dma, long long options, int clock); @@ -43,7 +38,7 @@ int bvme6000_scsi_detect(Scsi_Host_Template *tpnt) if (!MACH_IS_BVME6000) return 0; - tpnt->proc_dir = &proc_scsi_bvme6000; + tpnt->proc_name = "BVME6000"; options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT; diff --git a/drivers/scsi/bvme6000.h b/drivers/scsi/bvme6000.h index 06ad193ee700..55736862516f 100644 --- a/drivers/scsi/bvme6000.h +++ b/drivers/scsi/bvme6000.h @@ -26,8 +26,6 @@ void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs); #if defined(HOSTS_C) || defined(MODULE) #include -extern struct proc_dir_entry proc_scsi_mvme16x; - #define BVME6000_SCSI {name: "BVME6000 NCR53c710 SCSI", \ detect: bvme6000_scsi_detect, \ queuecommand: NCR53c7xx_queue_command, \ diff --git a/drivers/scsi/cyberstorm.h b/drivers/scsi/cyberstorm.h index 0dd156389675..00624cd3fb7f 100644 --- a/drivers/scsi/cyberstorm.h +++ b/drivers/scsi/cyberstorm.h @@ -56,7 +56,7 @@ extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); -#define SCSI_CYBERSTORM { proc_dir: &proc_scsi_esp, \ +#define SCSI_CYBERSTORM { proc_name: "esp-cyberstorm", \ proc_info: esp_proc_info, \ name: "CyberStorm SCSI", \ detect: cyber_esp_detect, \ diff --git a/drivers/scsi/cyberstormII.h b/drivers/scsi/cyberstormII.h index f97d2fcaacd1..c328b8bbb8b0 100644 --- a/drivers/scsi/cyberstormII.h +++ b/drivers/scsi/cyberstormII.h @@ -43,7 +43,7 @@ extern int esp_reset(Scsi_Cmnd *, unsigned int); extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); -#define SCSI_CYBERSTORMII { proc_dir: &proc_scsi_esp, \ +#define SCSI_CYBERSTORMII { proc_name: "esp-cyberstormII", \ proc_info: esp_proc_info, \ name: "CyberStorm Mk II SCSI", \ detect: cyberII_esp_detect, \ diff --git a/drivers/scsi/dc390.h b/drivers/scsi/dc390.h index 719df770a060..727fa4c233e1 100644 --- a/drivers/scsi/dc390.h +++ b/drivers/scsi/dc390.h @@ -34,11 +34,10 @@ static int DC390_release(struct Scsi_Host *); # define DC390_release NULL #endif -extern struct proc_dir_entry DC390_proc_scsi_tmscsim; extern int DC390_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); #define DC390_T { \ - proc_dir: &DC390_proc_scsi_tmscsim, \ + proc_name: "tmscsim", \ proc_info: DC390_proc_info, \ name: DC390_BANNER " V" DC390_VERSION, \ detect: DC390_detect, \ diff --git a/drivers/scsi/dec_esp.h b/drivers/scsi/dec_esp.h index 15a7bc14bda8..1c623ca6f7f7 100644 --- a/drivers/scsi/dec_esp.h +++ b/drivers/scsi/dec_esp.h @@ -24,7 +24,7 @@ extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); #define SCSI_DEC_ESP { \ - proc_dir: &proc_scsi_esp, \ + proc_name: "esp", \ proc_info: &esp_proc_info, \ name: "PMAZ-AA", \ detect: dec_esp_detect, \ diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 112ff9b72f46..0a2e943003b2 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -134,13 +134,6 @@ /*!!!! for dtc, it's a 128 byte buffer at 3900 !!! */ #define DTC_DATA_BUF 0x3900 /* rw 128 bytes long */ - -struct proc_dir_entry proc_scsi_dtc = { - PROC_SCSI_T128, 7, "dtc3x80", - S_IFDIR | S_IRUGO | S_IXUGO, 2 - }; - - static struct override { unsigned int address; int irq; @@ -214,7 +207,7 @@ int __init dtc_detect(Scsi_Host_Template * tpnt){ unsigned int base; int sig, count; - tpnt->proc_dir = &proc_scsi_dtc; + tpnt->proc_name = "dtc3x80"; tpnt->proc_info = &dtc_proc_info; for (count = 0; current_override < NO_OVERRIDES; ++current_override) { diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index bce089b6ad2f..4abd2241186a 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c @@ -424,11 +424,6 @@ MODULE_AUTHOR("Dario Ballabio"); #define SPIN_UNLOCK_RESTORE \ spin_unlock_irqrestore(&io_request_lock, spin_flags); -struct proc_dir_entry proc_scsi_eata2x = { - PROC_SCSI_EATA2X, 6, "eata2x", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - /* Subversion values */ #define ISA 0 #define ESA 1 @@ -1257,7 +1252,7 @@ static void add_pci_ports(void) { int eata2x_detect(Scsi_Host_Template *tpnt) { unsigned int j = 0, k; - tpnt->proc_dir = &proc_scsi_eata2x; + tpnt->proc_name = "eata2x"; if(boot_options) option_setup(boot_options); diff --git a/drivers/scsi/eata_dma.c b/drivers/scsi/eata_dma.c index 6c55199503a3..dd90d073d932 100644 --- a/drivers/scsi/eata_dma.c +++ b/drivers/scsi/eata_dma.c @@ -92,11 +92,6 @@ #include #include /* for CONFIG_PCI */ -struct proc_dir_entry proc_scsi_eata_dma = { - PROC_SCSI_EATA, 8, "eata_dma", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - static u32 ISAbases[] = {0x1F0, 0x170, 0x330, 0x230}; static unchar EISAbases[] = @@ -1472,7 +1467,7 @@ int eata_detect(Scsi_Host_Template * tpnt) DBG((DBG_PROBE && DBG_DELAY) || DPT_DEBUG, printk("Using lots of delays to let you read the debugging output\n")); - tpnt->proc_dir = &proc_scsi_eata_dma; + tpnt->proc_name = "eata_dma"; status = scsi_init_malloc(512, GFP_ATOMIC | GFP_DMA); dma_scratch = scsi_init_malloc(1024, GFP_ATOMIC | GFP_DMA); diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c index 5ad320c682bd..4c08f5922f20 100644 --- a/drivers/scsi/eata_pio.c +++ b/drivers/scsi/eata_pio.c @@ -58,11 +58,6 @@ #include #include -struct proc_dir_entry proc_scsi_eata_pio = { - PROC_SCSI_EATA_PIO, 9, "eata_pio", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - static uint ISAbases[MAXISA] = {0x1F0, 0x170, 0x330, 0x230}; static uint ISAirqs[MAXISA] = @@ -946,7 +941,7 @@ int eata_pio_detect(Scsi_Host_Template * tpnt) DBG((DBG_PROBE && DBG_DELAY) || DPT_DEBUG, printk("Using lots of delays to let you read the debugging output\n")); - tpnt->proc_dir = &proc_scsi_eata_pio; + tpnt->proc_name = "eata_pio"; find_pio_PCI(&gc, tpnt); diff --git a/drivers/scsi/esp.c b/drivers/scsi/esp.c index 1a6b8606a07d..4b6e6fba33d9 100644 --- a/drivers/scsi/esp.c +++ b/drivers/scsi/esp.c @@ -173,11 +173,6 @@ enum { /*5*/ do_intr_end }; -struct proc_dir_entry proc_scsi_esp = { - PROC_SCSI_ESP, 3, "esp", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - /* The master ring of all esp hosts we are managing in this driver. */ static struct Sparc_ESP *espchain; static int esps_running = 0; diff --git a/drivers/scsi/esp.h b/drivers/scsi/esp.h index 50a45a58337f..f05df73e7824 100644 --- a/drivers/scsi/esp.h +++ b/drivers/scsi/esp.h @@ -414,10 +414,8 @@ extern int esp_reset(Scsi_Cmnd *, unsigned int); extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); -extern struct proc_dir_entry proc_scsi_esp; - #define SCSI_SPARC_ESP { \ - proc_dir: &proc_scsi_esp, \ + proc_name: "esp", \ proc_info: &esp_proc_info, \ name: "Sun ESP 100/100a/200", \ detect: esp_detect, \ diff --git a/drivers/scsi/fastlane.h b/drivers/scsi/fastlane.h index 6acf6f0d1b55..e5e0002a8bc5 100644 --- a/drivers/scsi/fastlane.h +++ b/drivers/scsi/fastlane.h @@ -48,7 +48,7 @@ extern int esp_reset(Scsi_Cmnd *, unsigned int); extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); -#define SCSI_FASTLANE { proc_dir: &proc_scsi_esp, \ +#define SCSI_FASTLANE { proc_name: "esp-fastlane", \ proc_info: esp_proc_info, \ name: "Fastlane SCSI", \ detect: fastlane_esp_detect, \ diff --git a/drivers/scsi/fcal.c b/drivers/scsi/fcal.c index 0b6de466dc21..16c39d136d27 100644 --- a/drivers/scsi/fcal.c +++ b/drivers/scsi/fcal.c @@ -68,11 +68,6 @@ static unsigned char target2alpa[] = { 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17, 0x10, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x00 }; -struct proc_dir_entry proc_scsi_fcal = { - PROC_SCSI_FCAL, 4, "fcal", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - static int fcal_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd); static void fcal_select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) @@ -97,7 +92,7 @@ int __init fcal_detect(Scsi_Host_Template *tpnt) int fcalcount; int i; - tpnt->proc_dir = &proc_scsi_fcal; + tpnt->proc_name = "fcal"; fcalcount = 0; for_each_online_fc_channel(fc) if (fc->posmap) diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c index 69c97f5881a4..b9aac12daa15 100644 --- a/drivers/scsi/fd_mcs.c +++ b/drivers/scsi/fd_mcs.c @@ -98,11 +98,6 @@ #include "fd_mcs.h" #define DRIVER_VERSION "v0.2 by ZP Gu" - -struct proc_dir_entry proc_scsi_fd_mcs = { - PROC_SCSI_FD_MCS, 6, "fd_mcs", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; /* START OF USER DEFINABLE OPTIONS */ diff --git a/drivers/scsi/fd_mcs.h b/drivers/scsi/fd_mcs.h index e96cc21cde36..1841d5c28661 100644 --- a/drivers/scsi/fd_mcs.h +++ b/drivers/scsi/fd_mcs.h @@ -32,10 +32,8 @@ extern int fd_mcs_biosparam( Disk *, kdev_t, int * ); extern int fd_mcs_proc_info( char *, char **, off_t, int, int, int ); extern const char *fd_mcs_info(struct Scsi_Host *); -extern struct proc_dir_entry proc_scsi_fd_mcs; - #define FD_MCS {\ - proc_dir: &proc_scsi_fd_mcs, \ + proc_name: "fd_mcs", \ proc_info: fd_mcs_proc_info, \ detect: fd_mcs_detect, \ release: fd_mcs_release, \ diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index 1805e9e975be..6bed707e94c5 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -274,9 +274,7 @@ #define MODULE #endif -#ifdef MODULE #include -#endif #ifdef PCMCIA #undef MODULE @@ -299,11 +297,6 @@ #include #include /* for CONFIG_PCI */ - -struct proc_dir_entry proc_scsi_fdomain = { - PROC_SCSI_FDOMAIN, 7, "fdomain", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; #define VERSION "$Revision: 5.50 $" @@ -884,7 +877,7 @@ int fdomain_16x0_detect( Scsi_Host_Template *tpnt ) unsigned char buf[buflen]; #endif - tpnt->proc_dir = &proc_scsi_fdomain; + tpnt->proc_name = "fdomain"; #ifdef MODULE if (fdomain[0] || fdomain[1] || fdomain[2]) { diff --git a/drivers/scsi/fdomain.h b/drivers/scsi/fdomain.h index 3ac53365f9b0..1769d24c70e3 100644 --- a/drivers/scsi/fdomain.h +++ b/drivers/scsi/fdomain.h @@ -35,8 +35,6 @@ int fdomain_16x0_biosparam( Disk *, kdev_t, int * ); int fdomain_16x0_proc_info( char *buffer, char **start, off_t offset, int length, int hostno, int inout ); -extern struct proc_dir_entry proc_scsi_fdomain; - #define FDOMAIN_16X0 { proc_info: fdomain_16x0_proc_info, \ detect: fdomain_16x0_detect, \ info: fdomain_16x0_info, \ diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 875da3846e8b..a2dcf462e56e 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -119,11 +119,6 @@ #include #include -struct proc_dir_entry proc_scsi_g_ncr5380 = { - PROC_SCSI_GENERIC_NCR5380, 9, "g_NCR5380", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - #define NCR_NOT_SET 0 static int ncr_irq=NCR_NOT_SET; static int ncr_dma=NCR_NOT_SET; @@ -285,7 +280,7 @@ int __init generic_NCR5380_detect(Scsi_Host_Template * tpnt){ else if (dtc_3181e != NCR_NOT_SET) overrides[0].board=BOARD_DTC3181E; - tpnt->proc_dir = &proc_scsi_g_ncr5380; + tpnt->proc_name = "g_NCR5380"; for (count = 0; current_override < NO_OVERRIDES; ++current_override) { if (!(overrides[current_override].NCR5380_map_name)) diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 79cd0111c33e..e318395b24f7 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -181,24 +181,13 @@ #include #include #include -#if LINUX_VERSION_CODE >= 0x020100 #include -#else -#include -#endif #include #include #include -#if LINUX_VERSION_CODE >= 0x02015F #include -#endif - -#if LINUX_VERSION_CODE >= 0x010300 #include -#else -#include "../block/blk.h" -#endif #include "scsi.h" #include "hosts.h" #include "sd.h" @@ -207,11 +196,7 @@ static void gdth_delay(int milliseconds); static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs); -#if LINUX_VERSION_CODE >= 0x010346 static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs); -#else -static void gdth_interrupt(int irq,struct pt_regs *regs); -#endif static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp); static int gdth_async_event(int hanum,int service); static void gdth_log_event(gdth_evt_data *dvr, char *buffer); @@ -254,15 +239,8 @@ static void gdth_munmap(void *addr); static const char *gdth_ctr_name(int hanum); -#if LINUX_VERSION_CODE >= 0x010300 static void gdth_flush(int hanum); -#if LINUX_VERSION_CODE >= 0x020100 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf); -#else -static int halt_called = FALSE; -void gdth_halt(void); -#endif -#endif #ifdef DEBUG_GDTH static unchar DebugState = DEBUG_GDTH; @@ -363,64 +341,6 @@ static struct timer_list gdth_timer; #define BUS_L2P(a,b) ((b)>(a)->virt_bus ? (b-1):(b)) -#if LINUX_VERSION_CODE < 0x010300 -static void *gdth_mmap(ulong paddr, ulong size) -{ - if (paddr >= high_memory) - return NULL; - else - return (void *)paddr; -} -static void gdth_munmap(void *addr) -{ -} -inline ulong32 virt_to_phys(volatile void *addr) -{ - return (ulong32)addr; -} -inline void *phys_to_virt(ulong32 addr) -{ - return (void *)addr; -} -#define virt_to_bus virt_to_phys -#define bus_to_virt phys_to_virt -#define gdth_readb(addr) (*(volatile unchar *)(addr)) -#define gdth_readw(addr) (*(volatile ushort *)(addr)) -#define gdth_readl(addr) (*(volatile ulong32 *)(addr)) -#define gdth_writeb(b,addr) (*(volatile unchar *)(addr) = (b)) -#define gdth_writew(b,addr) (*(volatile ushort *)(addr) = (b)) -#define gdth_writel(b,addr) (*(volatile ulong32 *)(addr) = (b)) -#define memset_io(a,b,c) memset((void *)(a),(b),(c)) -#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) -#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) - -#define PCI_SLOT(devfn) ((devfn >> 3) & 0x1f) - -#elif LINUX_VERSION_CODE < 0x020100 -static int remapped = FALSE; -static void *gdth_mmap(ulong paddr, ulong size) -{ - if ( paddr >= high_memory) { - remapped = TRUE; - return vremap(paddr, size); - } else { - return (void *)paddr; - } -} -static void gdth_munmap(void *addr) -{ - if (remapped) - vfree(addr); - remapped = FALSE; -} -#define gdth_readb(addr) readb((ulong)(addr)) -#define gdth_readw(addr) readw((ulong)(addr)) -#define gdth_readl(addr) (ulong32)readl((ulong)(addr)) -#define gdth_writeb(b,addr) writeb((b),(ulong)(addr)) -#define gdth_writew(b,addr) writew((b),(ulong)(addr)) -#define gdth_writel(b,addr) writel((b),(ulong)(addr)) - -#else static void *gdth_mmap(ulong paddr, ulong size) { return ioremap(paddr, size); @@ -435,8 +355,6 @@ static void gdth_munmap(void *addr) #define gdth_writeb(b,addr) writeb((b),(ulong)(addr)) #define gdth_writew(b,addr) writew((b),(ulong)(addr)) #define gdth_writel(b,addr) writel((b),(ulong)(addr)) -#endif - static unchar gdth_drq_tab[4] = {5,6,7,7}; /* DRQ table */ static unchar gdth_irq_tab[6] = {0,10,11,12,14,0}; /* IRQ table */ @@ -477,15 +395,8 @@ static unchar gdth_direction_tab[0x100] = { }; /* __initfunc, __initdata macros */ -#if LINUX_VERSION_CODE >= 0x020126 #include -#else -#define __initfunc(A) A -#define __initdata -#define __init -#endif -#if LINUX_VERSION_CODE >= 0x02015F #define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock) #define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags) #define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags) @@ -494,16 +405,6 @@ static unchar gdth_direction_tab[0x100] = { #define GDTH_UNLOCK_SCSI_DONE(flags) spin_unlock_irqrestore(&io_request_lock,flags) #define GDTH_LOCK_SCSI_DOCMD() spin_lock_irq(&io_request_lock) #define GDTH_UNLOCK_SCSI_DOCMD() spin_unlock_irq(&io_request_lock) -#else -#define GDTH_INIT_LOCK_HA(ha) do {} while (0) -#define GDTH_LOCK_HA(ha,flags) do {save_flags(flags); cli();} while (0) -#define GDTH_UNLOCK_HA(ha,flags) do {restore_flags(flags);} while (0) - -#define GDTH_LOCK_SCSI_DONE(flags) do {} while (0) -#define GDTH_UNLOCK_SCSI_DONE(flags) do {} while (0) -#define GDTH_LOCK_SCSI_DOCMD() do {} while (0) -#define GDTH_UNLOCK_SCSI_DOCMD() do {} while (0) -#endif /* LILO and modprobe/insmod parameters */ /* IRQ list for GDT3000/3020 EISA controllers */ @@ -529,7 +430,6 @@ static int max_ids = MAXID; static int rescan = 0; #ifdef MODULE -#if LINUX_VERSION_CODE >= 0x02011A /* parameters for modprobe/insmod */ MODULE_PARM(irq, "i"); MODULE_PARM(disable, "i"); @@ -541,39 +441,23 @@ MODULE_PARM(max_ids, "i"); MODULE_PARM(rescan, "i"); MODULE_AUTHOR("Achim Leubner"); #endif -#endif /* /proc support */ -#if LINUX_VERSION_CODE >= 0x010300 #include -struct proc_dir_entry proc_scsi_gdth = { - PROC_SCSI_GDTH, 4, "gdth", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; #include "gdth_proc.h" #include "gdth_proc.c" -#endif -#if LINUX_VERSION_CODE >= 0x020100 /* notifier block to get a notify on system shutdown/halt/reboot */ static struct notifier_block gdth_notifier = { gdth_halt, NULL, 0 }; -#endif - static void gdth_delay(int milliseconds) { if (milliseconds == 0) { udelay(1); } else { -#if LINUX_VERSION_CODE >= 0x020168 mdelay(milliseconds); -#else - int i; - for (i = 0; i < milliseconds; ++i) - udelay(1000); -#endif } } @@ -636,12 +520,7 @@ static int __init gdth_search_pci(gdth_pci_str *pcistr) { ulong32 base0, base1, base2; ushort device_id, cnt; -#if LINUX_VERSION_CODE >= 0x2015C struct pci_dev *pdev; -#else - int error; - ushort idx; -#endif TRACE(("gdth_search_pci()\n")); @@ -1099,13 +978,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) continue; } gdth_munmap(ha->brd); -#if LINUX_VERSION_CODE >= 0x2015C pci_write_config_dword(pcistr->pdev, PCI_BASE_ADDRESS_0, i); -#else - pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, - PCI_BASE_ADDRESS_0, i); -#endif ha->brd = gdth_mmap(i, sizeof(gdt6m_dpram_str)); if (ha->brd == NULL) { printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); @@ -1436,11 +1310,7 @@ static int gdth_wait(int hanum,int index,ulong32 time) gdth_from_wait = TRUE; do { -#if LINUX_VERSION_CODE >= 0x010346 gdth_interrupt((int)ha->irq,ha,NULL); -#else - gdth_interrupt((int)ha->irq,NULL); -#endif if (wait_hanum==hanum && wait_index==index) { answer_found = TRUE; break; @@ -1821,13 +1691,8 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority) GDTH_LOCK_HA(ha, flags); scp->SCp.this_residual = (int)priority; -#if LINUX_VERSION_CODE >= 0x020000 b = scp->channel; -#else - b = NUMDATA(nscp->host)->busnum; -#endif t = scp->target; -#if LINUX_VERSION_CODE >= 0x010300 if (priority >= DEFAULT_PRI) { if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) { @@ -1835,7 +1700,6 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority) scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); } } -#endif if (ha->req_first==NULL) { ha->req_first = scp; /* queue was empty */ @@ -1886,11 +1750,7 @@ static void gdth_next(int hanum) for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) { if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr) pscp = (Scsi_Cmnd *)pscp->SCp.ptr; -#if LINUX_VERSION_CODE >= 0x020000 b = nscp->channel; -#else - b = NUMDATA(nscp->host)->busnum; -#endif t = nscp->target; if (nscp->SCp.this_residual >= DEFAULT_PRI) { if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || @@ -1911,9 +1771,7 @@ static void gdth_next(int hanum) firsttime = FALSE; } -#if LINUX_VERSION_CODE >= 0x010300 if (nscp->done != gdth_scsi_done) -#endif { if (nscp->SCp.phase == -1) { nscp->SCp.phase = SCSIRAWSERVICE; /* default: raw svc. */ @@ -1958,13 +1816,11 @@ static void gdth_next(int hanum) } } else -#if LINUX_VERSION_CODE >= 0x010300 if (nscp->done == gdth_scsi_done) { if (!(cmd_index=gdth_special_cmd(hanum,nscp))) this_cmd = FALSE; next_cmd = FALSE; } else -#endif if (b != ha->virt_bus) { if (ha->raw[BUS_L2P(ha,b)].io_cnt[t] >= GDTH_MAX_RAW || !(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b)))) @@ -2591,11 +2447,7 @@ static void gdth_clear_events() /* SCSI interface functions */ -#if LINUX_VERSION_CODE >= 0x010346 static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs) -#else -static void gdth_interrupt(int irq,struct pt_regs *regs) -#endif { register gdth_ha_str *ha; gdt6m_dpram_str *dp6m_ptr; @@ -2913,9 +2765,7 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) scp->sense_buffer[2] = NOT_READY; scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); -#if LINUX_VERSION_CODE >= 0x010300 if (scp->done != gdth_scsi_done) -#endif { dvr.size = sizeof(dvr.eu.sync); dvr.eu.sync.ionode = hanum; @@ -3282,11 +3132,7 @@ int __init gdth_detect(Scsi_Host_Template *shtp) printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n", isa_bios,ha->irq,ha->drq); -#if LINUX_VERSION_CODE >= 0x010346 if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) -#else - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) -#endif { printk("GDT-ISA: Unable to allocate IRQ\n"); scsi_unregister(shp); @@ -3294,11 +3140,7 @@ int __init gdth_detect(Scsi_Host_Template *shtp) } if (request_dma(ha->drq,"gdth")) { printk("GDT-ISA: Unable to allocate DMA channel\n"); -#if LINUX_VERSION_CODE >= 0x010346 free_irq(ha->irq,NULL); -#else - free_irq(ha->irq); -#endif scsi_unregister(shp); continue; } @@ -3331,11 +3173,7 @@ int __init gdth_detect(Scsi_Host_Template *shtp) --gdth_ctr_vcount; if (ha->pscratch != NULL) scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); -#if LINUX_VERSION_CODE >= 0x010346 free_irq(ha->irq,NULL); -#else - free_irq(ha->irq); -#endif scsi_unregister(shp); continue; } @@ -3343,22 +3181,9 @@ int __init gdth_detect(Scsi_Host_Template *shtp) hdr_channel = ha->bus_cnt; ha->virt_bus = hdr_channel; -#if LINUX_VERSION_CODE >= 0x020000 shp->max_id = ha->tid_cnt; shp->max_lun = MAXLUN; shp->max_channel = ha->bus_cnt; -#else - /* register addit. SCSI channels as virtual controllers */ - for (b=1; bbus_cnt+1; ++b) { - shp = scsi_register(shtp,sizeof(gdth_num_str)); - shp->unchecked_isa_dma = 1; - shp->irq = ha->irq; - shp->dma_channel = ha->drq; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum = b; - } -#endif GDTH_INIT_LOCK_HA(ha); gdth_enable_int(hanum); } @@ -3379,11 +3204,7 @@ int __init gdth_detect(Scsi_Host_Template *shtp) printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n", eisa_slot>>12,ha->irq); -#if LINUX_VERSION_CODE >= 0x010346 if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) -#else - if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) -#endif { printk("GDT-EISA: Unable to allocate IRQ\n"); scsi_unregister(shp); @@ -3418,11 +3239,7 @@ int __init gdth_detect(Scsi_Host_Template *shtp) --gdth_ctr_vcount; if (ha->pscratch != NULL) scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); -#if LINUX_VERSION_CODE >= 0x010346 free_irq(ha->irq,NULL); -#else - free_irq(ha->irq); -#endif scsi_unregister(shp); continue; } @@ -3430,36 +3247,16 @@ int __init gdth_detect(Scsi_Host_Template *shtp) hdr_channel = ha->bus_cnt; ha->virt_bus = hdr_channel; -#if LINUX_VERSION_CODE >= 0x020000 shp->max_id = ha->tid_cnt; shp->max_lun = MAXLUN; shp->max_channel = ha->bus_cnt; -#else - /* register addit. SCSI channels as virtual controllers */ - for (b=1; bbus_cnt+1; ++b) { - shp = scsi_register(shtp,sizeof(gdth_num_str)); - shp->unchecked_isa_dma = 0; - shp->irq = ha->irq; - shp->dma_channel = 0xff; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum = b; - TRACE2(("EISA detect Bus %d: shp %x hanum %d\n", - NUMDATA(shp)->busnum,(ulong32)shp, - NUMDATA(shp)->hanum)); - } -#endif GDTH_INIT_LOCK_HA(ha); gdth_enable_int(hanum); } } /* scanning for PCI controllers */ -#if LINUX_VERSION_CODE >= 0x2015C if (pci_present()) -#else - if (pcibios_present()) -#endif { gdth_pci_str pcistr[MAXHA]; @@ -3478,13 +3275,8 @@ int __init gdth_detect(Scsi_Host_Template *shtp) printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n", pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq); -#if LINUX_VERSION_CODE >= 0x010346 if (request_irq(ha->irq, gdth_interrupt, SA_INTERRUPT|SA_SHIRQ, "gdth", ha)) -#else - if (request_irq(ha->irq, gdth_interrupt, - SA_INTERRUPT|SA_SHIRQ, "gdth")) -#endif { printk("GDT-PCI: Unable to allocate IRQ\n"); scsi_unregister(shp); @@ -3517,11 +3309,7 @@ int __init gdth_detect(Scsi_Host_Template *shtp) --gdth_ctr_vcount; if (ha->pscratch != NULL) scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); -#if LINUX_VERSION_CODE >= 0x010346 free_irq(ha->irq,NULL); -#else - free_irq(ha->irq); -#endif scsi_unregister(shp); continue; } @@ -3529,22 +3317,9 @@ int __init gdth_detect(Scsi_Host_Template *shtp) hdr_channel = ha->bus_cnt; ha->virt_bus = hdr_channel; -#if LINUX_VERSION_CODE >= 0x020000 shp->max_id = ha->tid_cnt; shp->max_lun = MAXLUN; shp->max_channel = ha->bus_cnt; -#else - /* register addit. SCSI channels as virtual controllers */ - for (b=1; bbus_cnt+1; ++b) { - shp = scsi_register(shtp,sizeof(gdth_num_str)); - shp->unchecked_isa_dma = 0; - shp->irq = ha->irq; - shp->dma_channel = 0xff; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum = b; - } -#endif GDTH_INIT_LOCK_HA(ha); gdth_enable_int(hanum); } @@ -3560,9 +3335,7 @@ int __init gdth_detect(Scsi_Host_Template *shtp) gdth_timer.function = gdth_timeout; add_timer(&gdth_timer); #endif -#if LINUX_VERSION_CODE >= 0x020100 register_reboot_notifier(&gdth_notifier); -#endif } gdth_polling = FALSE; return gdth_ctr_vcount; @@ -3578,16 +3351,10 @@ int gdth_release(struct Scsi_Host *shp) if (NUMDATA(shp)->busnum == 0) { hanum = NUMDATA(shp)->hanum; ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x010300 gdth_flush(hanum); -#endif if (shp->irq) { -#if LINUX_VERSION_CODE >= 0x010346 free_irq(shp->irq,NULL); -#else - free_irq(shp->irq); -#endif } if (shp->dma_channel != 0xff) { free_dma(shp->dma_channel); @@ -3601,9 +3368,7 @@ int gdth_release(struct Scsi_Host *shp) #ifdef GDTH_STATISTICS del_timer(&gdth_timer); #endif -#if LINUX_VERSION_CODE >= 0x020100 unregister_reboot_notifier(&gdth_notifier); -#endif } } @@ -3663,17 +3428,12 @@ int gdth_abort(Scsi_Cmnd *scp) return SCSI_ABORT_SNOOZE; } -#if LINUX_VERSION_CODE >= 0x010346 int gdth_reset(Scsi_Cmnd *scp, unsigned int reset_flags) -#else -int gdth_reset(Scsi_Cmnd *scp) -#endif { TRACE2(("gdth_reset()\n")); return SCSI_RESET_PUNT; } -#if LINUX_VERSION_CODE >= 0x02015F /* new error handling */ int gdth_eh_abort(Scsi_Cmnd *scp) { @@ -3723,13 +3483,8 @@ int gdth_eh_host_reset(Scsi_Cmnd *scp) TRACE2(("gdth_eh_host_reset()\n")); return FAILED; } -#endif -#if LINUX_VERSION_CODE >= 0x010300 int gdth_bios_param(Disk *disk,kdev_t dev,int *ip) -#else -int gdth_bios_param(Disk *disk,int dev,int *ip) -#endif { unchar t; int hanum; @@ -3793,17 +3548,14 @@ int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *)) #endif priority = DEFAULT_PRI; -#if LINUX_VERSION_CODE >= 0x010300 if (scp->done == gdth_scsi_done) priority = scp->SCp.this_residual; -#endif gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6); gdth_putq( hanum, scp, priority ); gdth_next( hanum ); return 0; } -#if LINUX_VERSION_CODE >= 0x010300 /* flush routine */ static void gdth_flush(int hanum) { @@ -3840,11 +3592,7 @@ static void gdth_flush(int hanum) } /* shutdown routine */ -#if LINUX_VERSION_CODE >= 0x020100 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) -#else -void gdth_halt(void) -#endif { int hanum; #ifndef __alpha__ @@ -3853,18 +3601,9 @@ void gdth_halt(void) gdth_cmd_str gdtcmd; #endif -#if LINUX_VERSION_CODE >= 0x020100 TRACE2(("gdth_halt() event %d\n",event)); if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF) return NOTIFY_DONE; -#else - TRACE2(("gdth_halt()\n")); - if (halt_called) { - TRACE2(("already called\n")); - return; - } - halt_called = TRUE; -#endif printk("GDT: Flushing all host drives .. "); for (hanum = 0; hanum < gdth_ctr_count; ++hanum) { gdth_flush(hanum); @@ -3893,13 +3632,9 @@ void gdth_halt(void) #ifdef GDTH_STATISTICS del_timer(&gdth_timer); #endif -#if LINUX_VERSION_CODE >= 0x020100 unregister_reboot_notifier(&gdth_notifier); return NOTIFY_OK; -#endif } -#endif - /* called from init/main.c */ void __init gdth_setup(char *str,int *ints) diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h index 340adf5aeaf5..2fa420b25fd9 100644 --- a/drivers/scsi/gdth.h +++ b/drivers/scsi/gdth.h @@ -814,9 +814,7 @@ typedef struct { /* PCI resources */ typedef struct { -#if LINUX_VERSION_CODE >= 0x02015C struct pci_dev *pdev; -#endif ushort device_id; /* device ID (0,..,9) */ unchar bus; /* PCI bus */ unchar device_fn; /* PCI device/function no. */ @@ -888,9 +886,7 @@ typedef struct { gdth_cpar_str cpar; /* controller cache par. */ gdth_bfeat_str bfeat; /* controller features */ gdth_binfo_str binfo; /* controller info */ -#if LINUX_VERSION_CODE >= 0x02015F spinlock_t smp_lock; -#endif } gdth_ha_str; /* structure for scsi_register(), SCSI bus != 0 */ @@ -971,22 +967,16 @@ int gdth_release(struct Scsi_Host *); int gdth_command(Scsi_Cmnd *); int gdth_queuecommand(Scsi_Cmnd *,void (*done)(Scsi_Cmnd *)); int gdth_abort(Scsi_Cmnd *); -#if LINUX_VERSION_CODE >= 0x010346 int gdth_reset(Scsi_Cmnd *, unsigned int reset_flags); -#else -int gdth_reset(Scsi_Cmnd *); -#endif const char *gdth_info(struct Scsi_Host *); -#if LINUX_VERSION_CODE >= 0x02015F int gdth_bios_param(Disk *,kdev_t,int *); -extern struct proc_dir_entry proc_scsi_gdth; int gdth_proc_info(char *,char **,off_t,int,int,int); int gdth_eh_abort(Scsi_Cmnd *scp); int gdth_eh_device_reset(Scsi_Cmnd *scp); int gdth_eh_bus_reset(Scsi_Cmnd *scp); int gdth_eh_host_reset(Scsi_Cmnd *scp); -#define GDTH { proc_dir: &proc_scsi_gdth, \ +#define GDTH { proc_name: "gdth", \ proc_info: gdth_proc_info, \ name: "GDT SCSI Disk Array Controller",\ detect: gdth_detect, \ @@ -1009,51 +999,5 @@ int gdth_eh_host_reset(Scsi_Cmnd *scp); unchecked_isa_dma: 1, \ use_clustering: ENABLE_CLUSTERING, \ use_new_eh_code: 1 /* use new error code */ } -#elif LINUX_VERSION_CODE >= 0x010300 -int gdth_bios_param(Disk *,kdev_t,int *); -extern struct proc_dir_entry proc_scsi_gdth; -int gdth_proc_info(char *,char **,off_t,int,int,int); -#define GDTH { NULL, NULL, \ - &proc_scsi_gdth, \ - gdth_proc_info, \ - "GDT SCSI Disk Array Controller", \ - gdth_detect, \ - gdth_release, \ - gdth_info, \ - gdth_command, \ - gdth_queuecommand, \ - gdth_abort, \ - gdth_reset, \ - NULL, \ - gdth_bios_param, \ - GDTH_MAXCMDS, \ - -1, \ - GDTH_MAXSG, \ - GDTH_MAXC_P_L, \ - 0, \ - 1, \ - ENABLE_CLUSTERING} -#else -int gdth_bios_param(Disk *,int,int *); -#define GDTH { NULL, NULL, \ - "GDT SCSI Disk Array Controller", \ - gdth_detect, \ - gdth_release, \ - gdth_info, \ - gdth_command, \ - gdth_queuecommand, \ - gdth_abort, \ - gdth_reset, \ - NULL, \ - gdth_bios_param, \ - GDTH_MAXCMDS, \ - -1, \ - GDTH_MAXSG, \ - GDTH_MAXC_P_L, \ - 0, \ - 1, \ - ENABLE_CLUSTERING} -#endif - #endif diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index 365351cb95e7..d905012ba144 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c @@ -21,11 +21,6 @@ #include -struct proc_dir_entry proc_scsi_gvp11 = { - PROC_SCSI_GVP11, 5, "GVP11", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - #define DMA(ptr) ((gvp11_scsiregs *)((ptr)->base)) #define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata)) @@ -200,7 +195,7 @@ int __init gvp11_detect(Scsi_Host_Template *tpnt) return 0; called = 1; - tpnt->proc_dir = &proc_scsi_gvp11; + tpnt->proc_name = "GVP11"; tpnt->proc_info = &wd33c93_proc_info; while (1) { diff --git a/drivers/scsi/gvp11.h b/drivers/scsi/gvp11.h index d03886baa113..47c6b25eea8c 100644 --- a/drivers/scsi/gvp11.h +++ b/drivers/scsi/gvp11.h @@ -32,9 +32,7 @@ int wd33c93_reset(Scsi_Cmnd *, unsigned int); #ifdef HOSTS_C -extern struct proc_dir_entry proc_scsi_gvp11; - -#define GVP11_SCSI { proc_dir: &proc_scsi_gvp11, \ +#define GVP11_SCSI { proc_name: "GVP11", \ name: "GVP Series II SCSI", \ detect: gvp11_detect, \ release: gvp11_release, \ diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 59a6bee98f9e..4b3a4ddc2060 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -703,6 +703,8 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j){ retval->loaded_as_module = scsi_loadable_module_flag; retval->host_no = max_scsi_hosts++; /* never reuse host_no (DB) */ next_scsi_host++; + /* FIXME: what with overflows? Old code suffered from the same, BTW */ + sprintf(retval->proc_name, "%d", retval->host_no); retval->host_queue = NULL; init_waitqueue_head(&retval->host_wait); retval->resetting = 0; diff --git a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h index 4d25e2e2cfb3..ae3d13c662f8 100644 --- a/drivers/scsi/hosts.h +++ b/drivers/scsi/hosts.h @@ -277,6 +277,11 @@ typedef struct SHT */ unsigned emulated:1; + /* + * Name of proc directory + */ + char *proc_name; + } Scsi_Host_Template; /* @@ -322,6 +327,7 @@ struct Scsi_Host /* public: */ unsigned short extra_bytes; unsigned short host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */ + char proc_name[4]; int resetting; /* if set, it means that last_reset is a valid value */ unsigned long last_reset; diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index d943724c0548..1deec84e4ed2 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c @@ -275,15 +275,6 @@ struct subsys_list_struct subsys_list[] = {0x8efe, "IBM SCSI Adapter"}, /* special = 4 */ }; -/*for /proc filesystem */ -struct proc_dir_entry proc_scsi_ibmmca = -{ - PROC_SCSI_IBMMCA, 6, "ibmmca", - S_IFDIR | S_IRUGO | S_IXUGO, 2, - 0, 0, 0, NULL, NULL, NULL, NULL, - NULL, NULL, NULL -}; - /* Max number of logical devices (can be up from 0 to 14). 15 is the address of the adapter itself. */ #define MAX_LOG_DEV 15 diff --git a/drivers/scsi/ibmmca.h b/drivers/scsi/ibmmca.h index 58b3094b8d7c..99d0fe90f2e4 100644 --- a/drivers/scsi/ibmmca.h +++ b/drivers/scsi/ibmmca.h @@ -27,11 +27,7 @@ extern int ibmmca_reset (Scsi_Cmnd *, unsigned int); extern int ibmmca_biosparam (Disk *, kdev_t, int *); /*structure for /proc filesystem */ -extern struct proc_dir_entry proc_scsi_ibmmca; -#if LINUX_VERSION_CODE >= ibmmca_header_linux_version(2,1,0) -/* Stuff for Linux >= 2.1.0: */ -/*initialization for Scsi_host_template type (Linux >= 2.1.0) */ /* * 2/8/98 * Note to maintainer of IBMMCA. Do not change this initializer back to @@ -39,7 +35,7 @@ extern struct proc_dir_entry proc_scsi_ibmmca; * about this, but it will break things in the future. */ #define IBMMCA { \ - proc_dir: &proc_scsi_ibmmca, /*proc_dir*/ \ + proc_name: "ibmmca", /*proc_name*/ \ proc_info: ibmmca_proc_info, /*proc info fn*/ \ name: "IBM SCSI-Subsystem", /*name*/ \ detect: ibmmca_detect, /*detect fn*/ \ @@ -57,33 +53,4 @@ extern struct proc_dir_entry proc_scsi_ibmmca; use_clustering: ENABLE_CLUSTERING /*use_clustering*/ \ } -#else -/* Stuff for Linux < 2.1.0: */ - -/*initialization for Scsi_host_template type (Linux < 2.1.0) */ -#define IBMMCA { \ - NULL, /*next*/ \ - NULL, /*usage_count*/ \ - &proc_scsi_ibmmca, /*proc_dir*/ \ - ibmmca_proc_info, /*proc info fn*/ \ - "IBM SCSI-Subsystem", /*name*/ \ - ibmmca_detect, /*detect fn*/ \ - ibmmca_release, /*release fn*/ \ - NULL, /*info fn*/ \ - ibmmca_command, /*command fn*/ \ - ibmmca_queuecommand, /*queuecommand fn*/ \ - ibmmca_abort, /*abort fn*/ \ - ibmmca_reset, /*reset fn*/ \ - NULL, /*slave_attach fn*/ \ - ibmmca_biosparam, /*bios fn*/ \ - 16, /*can_queue*/ \ - 7, /*set by detect*/ \ - 16, /*sg_tablesize*/ \ - 1, /*cmd_per_lun*/ \ - 0, /*present*/ \ - 0, /*unchecked_isa_dma*/ \ - ENABLE_CLUSTERING /*use_clustering*/ \ - } -#endif /* kernelversion selection */ - #endif /* _IBMMCA_H */ diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 5ed076b513fe..88756ac660a8 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -558,8 +558,6 @@ static ide_module_t idescsi_module = { NULL }; -static struct proc_dir_entry idescsi_proc_dir = {PROC_SCSI_IDESCSI, 8, "ide-scsi", S_IFDIR | S_IRUGO | S_IXUGO, 2}; - /* * idescsi_init will register the driver for each scsi. */ @@ -603,7 +601,7 @@ int idescsi_detect (Scsi_Host_Template *host_template) struct Scsi_Host *host; int id; - host_template->proc_dir = &idescsi_proc_dir; + host_template->proc_name = "ide-scsi"; host = scsi_register(host_template, 0); for (id = 0; id < MAX_HWIFS * MAX_DRIVES && idescsi_drives[id]; id++); host->max_id = id; diff --git a/drivers/scsi/imm.h b/drivers/scsi/imm.h index feba4c773cb7..8221706dba60 100644 --- a/drivers/scsi/imm.h +++ b/drivers/scsi/imm.h @@ -146,10 +146,7 @@ static int imm_init(int); static void imm_interrupt(void *); static int imm_out(int, char *, int); -struct proc_dir_entry proc_scsi_imm = -{PROC_SCSI_PPA, 3, "imm", S_IFDIR | S_IRUGO | S_IXUGO, 2}; #else -extern struct proc_dir_entry proc_scsi_imm; #define imm_release 0 #endif @@ -162,7 +159,7 @@ int imm_reset(Scsi_Cmnd *); int imm_proc_info(char *, char **, off_t, int, int, int); int imm_biosparam(Disk *, kdev_t, int *); -#define IMM { proc_dir: &proc_scsi_imm, \ +#define IMM { proc_name: "imm", \ proc_info: imm_proc_info, \ name: "Iomega VPI2 (imm) interface",\ detect: imm_detect, \ diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c index 33b2f82d8371..1b1ff4371d74 100644 --- a/drivers/scsi/in2000.c +++ b/drivers/scsi/in2000.c @@ -2023,7 +2023,7 @@ char buf[32]; * initialize it. */ - tpnt->proc_dir = &proc_scsi_in2000; /* done more than once? harmless. */ + tpnt->proc_name = "in2000"; detect_count++; instance = scsi_register(tpnt, sizeof(struct IN2000_hostdata)); if (!instance_list) @@ -2188,13 +2188,6 @@ int size; } - -struct proc_dir_entry proc_scsi_in2000 = { - PROC_SCSI_IN2000, 6, "in2000", - S_IFDIR | S_IRUGO | S_IXUGO, 2 - }; - - int in2000_proc_info(char *buf, char **start, off_t off, int len, int hn, int in) { diff --git a/drivers/scsi/in2000.h b/drivers/scsi/in2000.h index f995b9e32d4c..63bfa6d65049 100644 --- a/drivers/scsi/in2000.h +++ b/drivers/scsi/in2000.h @@ -384,13 +384,6 @@ struct IN2000_hostdata { #include -#if LINUX_VERSION_CODE < 0x020100 /* 2.0.xx */ -# define in2000__INITFUNC(function) function -# define in2000__INIT -# define in2000__INITDATA -# define CLISPIN_LOCK(flags) do { save_flags(flags); cli(); } while(0) -# define CLISPIN_UNLOCK(flags) restore_flags(flags) -#else /* 2.1.xxx */ # include # include # define in2000__INITFUNC(function) __initfunc(function) @@ -398,15 +391,12 @@ struct IN2000_hostdata { # define in2000__INITDATA __initdata # define CLISPIN_LOCK(flags) spin_lock_irqsave(&io_request_lock, flags) # define CLISPIN_UNLOCK(flags) spin_unlock_irqrestore(&io_request_lock, flags) -#endif - int in2000_detect(Scsi_Host_Template *) in2000__INIT; int in2000_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int in2000_abort(Scsi_Cmnd *); void in2000_setup(char *, int *) in2000__INIT; int in2000_proc_info(char *, char **, off_t, int, int, int); -struct proc_dir_entry proc_scsi_in2000; int in2000_biosparam(struct scsi_disk *, kdev_t, int *); int in2000_reset(Scsi_Cmnd *, unsigned int); @@ -416,34 +406,7 @@ int in2000_reset(Scsi_Cmnd *, unsigned int); #define IN2000_CPL 2 #define IN2000_HOST_ID 7 -#if LINUX_VERSION_CODE < 0x020100 /* 2.0.xx */ - -#define IN2000 { NULL, /* link pointer for modules */ \ - NULL, /* usage_count for modules */ \ - &proc_scsi_in2000, /* pointer to /proc/scsi directory entry */ \ - in2000_proc_info, /* pointer to proc info function */ \ - "Always IN2000", /* device name */ \ - in2000_detect, /* returns number of in2000's found */ \ - NULL, /* optional unload function for modules */ \ - NULL, /* optional misc info function */ \ - NULL, /* send scsi command, wait for completion */ \ - in2000_queuecommand, /* queue scsi command, don't wait */ \ - in2000_abort, /* abort current command */ \ - in2000_reset, /* reset scsi bus */ \ - NULL, /* slave_attach - unused */ \ - in2000_biosparam, /* figures out BIOS parameters for lilo, etc */ \ - IN2000_CAN_Q, /* max commands we can queue up */ \ - IN2000_HOST_ID, /* host-adapter scsi id */ \ - IN2000_SG, /* scatter-gather table size */ \ - IN2000_CPL, /* commands per lun */ \ - 0, /* board counter */ \ - 0, /* unchecked dma */ \ - DISABLE_CLUSTERING \ - } - -#else /* 2.1.xxx */ - -#define IN2000 { proc_dir: &proc_scsi_in2000, /* pointer to /proc/scsi directory entry */ \ +#define IN2000 { proc_name: "in2000", /* name of /proc/scsi directory entry */ \ proc_info: in2000_proc_info, /* pointer to proc info function */ \ name: "Always IN2000", /* device name */ \ detect: in2000_detect, /* returns number of in2000's found */ \ @@ -459,7 +422,4 @@ int in2000_reset(Scsi_Cmnd *, unsigned int); use_new_eh_code: 0 /* new error code - not using it yet */ \ } -#endif - - #endif /* IN2000_H */ diff --git a/drivers/scsi/ini9100u.c b/drivers/scsi/ini9100u.c index f37f2ae4d360..db256c53c6b8 100644 --- a/drivers/scsi/ini9100u.c +++ b/drivers/scsi/ini9100u.c @@ -116,33 +116,17 @@ #include #endif -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) #include #include #include -#if LINUX_VERSION_CODE <= CVT_LINUX_VERSION(2,1,92) -#include -#endif #include #include -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,23) #include -#endif #include -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) #include -#endif #include #include -#else - -#include -#include -#include -#include "../block/blk.h" -#endif - #include #include #include @@ -169,15 +153,6 @@ char *i91uInitioName = "by Initio Corporation"; char *i91uProductName = "INI-9X00U/UW"; char *i91uVersion = "v1.03g"; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) -struct proc_dir_entry proc_scsi_ini9100u = -{ - PROC_SCSI_INI9100U, 7, "INI9100U", - S_IFDIR | S_IRUGO | S_IXUGO, 2, - 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; -#endif - #define TULSZ(sz) (sizeof(sz) / sizeof(sz[0])) #define TUL_RDWORD(x,y) (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) )) @@ -195,7 +170,6 @@ static int setup_debug = 0; static char *setup_str = (char *) NULL; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) static void i91u_intr0(int irq, void *dev_id, struct pt_regs *); static void i91u_intr1(int irq, void *dev_id, struct pt_regs *); static void i91u_intr2(int irq, void *dev_id, struct pt_regs *); @@ -204,16 +178,6 @@ static void i91u_intr4(int irq, void *dev_id, struct pt_regs *); static void i91u_intr5(int irq, void *dev_id, struct pt_regs *); static void i91u_intr6(int irq, void *dev_id, struct pt_regs *); static void i91u_intr7(int irq, void *dev_id, struct pt_regs *); -#else -static void i91u_intr0(int irq, struct pt_regs *); -static void i91u_intr1(int irq, struct pt_regs *); -static void i91u_intr2(int irq, struct pt_regs *); -static void i91u_intr3(int irq, struct pt_regs *); -static void i91u_intr4(int irq, struct pt_regs *); -static void i91u_intr5(int irq, struct pt_regs *); -static void i91u_intr6(int irq, struct pt_regs *); -static void i91u_intr7(int irq, struct pt_regs *); -#endif static void i91u_panic(char *msg); @@ -261,12 +225,7 @@ const PCI_ID i91u_pci_devices[] = { static void i91uAppendSRBToQueue(HCS * pHCB, Scsi_Cmnd * pSRB) { ULONG flags; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_lock_irqsave(&(pHCB->pSRB_lock), flags); -#else - save_flags(flags); - cli(); -#endif pSRB->next = NULL; /* Pointer to next */ @@ -276,11 +235,7 @@ static void i91uAppendSRBToQueue(HCS * pHCB, Scsi_Cmnd * pSRB) pHCB->pSRB_tail->next = pSRB; /* Pointer to next */ pHCB->pSRB_tail = pSRB; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags); -#else - restore_flags(flags); -#endif return; } @@ -296,22 +251,13 @@ static Scsi_Cmnd *i91uPopSRBFromQueue(HCS * pHCB) Scsi_Cmnd *pSRB; ULONG flags; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_lock_irqsave(&(pHCB->pSRB_lock), flags); -#else - save_flags(flags); - cli(); -#endif if ((pSRB = pHCB->pSRB_head) != NULL) { pHCB->pSRB_head = pHCB->pSRB_head->next; pSRB->next = NULL; } -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags); -#else - restore_flags(flags); -#endif return (pSRB); } @@ -331,7 +277,6 @@ void i91u_setup(char *str, int *ints) #endif } -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,93) int tul_NewReturnNumberOfAdapters(void) { struct pci_dev *pDev = NULL; /* Start from none */ @@ -363,102 +308,6 @@ int tul_NewReturnNumberOfAdapters(void) return (iAdapters); } -#else /* <01> */ - -/***************************************************************************** - Function name : tul_ReturnNumberOfAdapters - Description : This function will scan PCI bus to get all Orchid card - Input : None. - Output : None. - Return : SUCCESSFUL - Successful scan - ohterwise - No drives founded -*****************************************************************************/ -int tul_ReturnNumberOfAdapters(void) -{ - unsigned int i, iAdapters; - unsigned int dRegValue; - unsigned short command; - WORD wBIOS, wBASE; - BYTE bPCIBusNum, bInterrupt, bPCIDeviceNum; - - iAdapters = 0; - /* - * PCI-bus probe. - */ - if (pcibios_present()) { -#ifdef MMAPIO - unsigned long page_offset, base; -#endif - - int index; - unsigned char pci_bus, pci_devfn; - - bPCIBusNum = 0; - bPCIDeviceNum = 0; - init_i91uAdapter_table(); - for (i = 0; i < TULSZ(i91u_pci_devices); i++) { - index = 0; - while (!(pcibios_find_device(i91u_pci_devices[i].vendor_id, - i91u_pci_devices[i].device_id, - index++, &pci_bus, &pci_devfn))) - { - if (i == 2) { - printk("i91u: The RAID controller is not supported by\n"); - printk("i91u: this driver, we are ignoring it.\n"); - } else { - /* - * Read sundry information from PCI BIOS. - */ - bPCIBusNum = pci_bus; - bPCIDeviceNum = pci_devfn; - pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_0, - &dRegValue); - if (dRegValue == -1) { /* Check return code */ - printk("\n\ri91u: tulip read configuration error.\n"); - return (0); /* Read configuration space error */ - } - /* <02> read from base address + 0x50 offset to get the wBIOS balue. */ - wBASE = (WORD) dRegValue; - - /* Now read the interrupt line */ - pcibios_read_config_dword(pci_bus, pci_devfn, PCI_INTERRUPT_LINE, - &dRegValue); - bInterrupt = dRegValue & 0xFF; /* Assign interrupt line */ - pcibios_read_config_word(pci_bus, pci_devfn, PCI_COMMAND, &command); - pcibios_write_config_word(pci_bus, pci_devfn, PCI_COMMAND, - command | PCI_COMMAND_MASTER | PCI_COMMAND_IO); - wBASE &= PCI_BASE_ADDRESS_IO_MASK; - wBIOS = TUL_RDWORD(wBASE, 0x50); - -#ifdef MMAPIO - base = wBASE & PAGE_MASK; - page_offset = wBASE - base; - - /* - * replace the next line with this one if you are using 2.1.x: - * temp_p->maddr = ioremap(base, page_offset + 256); - */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,0) - wBASE = ioremap(base, page_offset + 256); -#else - wBASE = (WORD) vremap(base, page_offset + 256); -#endif - if (wBASE) { - wBASE += page_offset; - } -#endif - - if (Addi91u_into_Adapter_table(wBIOS, wBASE, bInterrupt, bPCIBusNum, - bPCIDeviceNum) == 0x0) - iAdapters++; - } - } /* while(pdev=....) */ - } /* for PCI_DEVICES */ - } /* PCI BIOS present */ - return (iAdapters); -} -#endif - int i91u_detect(Scsi_Host_Template * tpnt) { SCB *pSCB; @@ -469,9 +318,7 @@ int i91u_detect(Scsi_Host_Template * tpnt) ULONG dBiosAdr; BYTE *pbBiosAdr; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) - tpnt->proc_dir = &proc_scsi_ini9100u; -#endif + tpnt->proc_name = "INI9100U"; if (setup_called) { /* Setup by i91u_setup */ printk("i91u: processing commandline: "); @@ -486,12 +333,8 @@ int i91u_detect(Scsi_Host_Template * tpnt) #endif } /* Get total number of adapters in the motherboard */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,93) #ifdef CONFIG_PCI iAdapters = tul_NewReturnNumberOfAdapters(); -#else - iAdapters = tul_ReturnNumberOfAdapters(); -#endif #else iAdapters = tul_ReturnNumberOfAdapters(); #endif @@ -512,16 +355,11 @@ int i91u_detect(Scsi_Host_Template * tpnt) memset((unsigned char *) &tul_hcs[0], 0, i); /* Initialize tul_hcs 0 */ /* Get total memory needed for SCB */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) for (; tul_num_scb >= MAX_TARGETS + 3; tul_num_scb--) { i = tul_num_ch * tul_num_scb * sizeof(SCB); if ((tul_scb = (SCB *) kmalloc(i, GFP_ATOMIC | GFP_DMA)) != NULL) break; } -#else - i = tul_num_ch * tul_num_scb * sizeof(SCB); - tul_scb = (SCB *) scsi_init_malloc(i, GFP_ATOMIC | GFP_DMA); -#endif if (tul_scb == NULL) { printk("i91u: SCB memory allocation error\n"); return (0); @@ -530,11 +368,7 @@ int i91u_detect(Scsi_Host_Template * tpnt) pSCB = tul_scb; for (i = 0; i < tul_num_ch * tul_num_scb; i++, pSCB++) { -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) pSCB->SCB_SGPAddr = (U32) VIRT_TO_BUS(&pSCB->SCB_SGList[0]); -#else - pSCB->SCB_SGPAddr = (U32) (&pSCB->SCB_SGList[0]); -#endif } for (i = 0, pHCB = &tul_hcs[0]; /* Get pointer for control block */ @@ -542,9 +376,7 @@ int i91u_detect(Scsi_Host_Template * tpnt) i++, pHCB++) { pHCB->pSRB_head = NULL; /* Initial SRB save queue */ pHCB->pSRB_tail = NULL; /* Initial SRB save queue */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) pHCB->pSRB_lock = SPIN_LOCK_UNLOCKED; /* SRB save queue lock */ -#endif request_region(pHCB->HCS_Base, 0x100, "i91u"); /* Register */ get_tulipPCIConfig(pHCB, i); @@ -552,9 +384,7 @@ int i91u_detect(Scsi_Host_Template * tpnt) dBiosAdr = pHCB->HCS_BIOS; dBiosAdr = (dBiosAdr << 4); -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) pbBiosAdr = phys_to_virt(dBiosAdr); -#endif init_tulip(pHCB, tul_scb + (i * tul_num_scb), tul_num_scb, pbBiosAdr, 10); pHCB->HCS_Index = i; /* 7/29/98 */ @@ -562,10 +392,8 @@ int i91u_detect(Scsi_Host_Template * tpnt) hreg->io_port = pHCB->HCS_Base; hreg->n_io_port = 0xff; hreg->can_queue = tul_num_scb; /* 03/05/98 */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) hreg->unique_id = pHCB->HCS_Base; hreg->max_id = pHCB->HCS_MaxTar; -#endif hreg->max_lun = 32; /* 10/21/97 */ hreg->irq = pHCB->HCS_Intr; hreg->this_id = pHCB->HCS_SCSI_ID; /* Assign HCS index */ @@ -574,7 +402,6 @@ int i91u_detect(Scsi_Host_Template * tpnt) /* Initial tulip chip */ switch (i) { -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) case 0: ok = request_irq(pHCB->HCS_Intr, i91u_intr0, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL); break; @@ -617,7 +444,6 @@ int i91u_detect(Scsi_Host_Template * tpnt) } i91u_panic("i91u: driver needs an IRQ.\n"); } -#endif } tpnt->this_id = -1; @@ -642,11 +468,7 @@ static void i91uBuildSCB(HCS * pHCB, SCB * pSCB, Scsi_Cmnd * SCpnt) pSCB->SCB_Ident = SCpnt->lun | DISC_ALLOW; pSCB->SCB_Flags |= SCF_SENSE; /* Turn on auto request sense */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) pSCB->SCB_SensePtr = (U32) VIRT_TO_BUS(SCpnt->sense_buffer); -#else - pSCB->SCB_SensePtr = (U32) (SCpnt->sense_buffer); -#endif pSCB->SCB_SenseLen = SENSE_SIZE; @@ -664,11 +486,7 @@ static void i91uBuildSCB(HCS * pHCB, SCB * pSCB, Scsi_Cmnd * SCpnt) if (SCpnt->use_sg) { pSrbSG = (struct scatterlist *) SCpnt->request_buffer; if (SCpnt->use_sg == 1) { /* If only one entry in the list *//* treat it as regular I/O */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) pSCB->SCB_BufPtr = (U32) VIRT_TO_BUS(pSrbSG->address); -#else - pSCB->SCB_BufPtr = (U32) (pSrbSG->address); -#endif TotalLen = pSrbSG->length; pSCB->SCB_SGLen = 0; } else { /* Assign SG physical address */ @@ -677,11 +495,7 @@ static void i91uBuildSCB(HCS * pHCB, SCB * pSCB, Scsi_Cmnd * SCpnt) for (i = 0, TotalLen = 0, pSG = &pSCB->SCB_SGList[0]; /* 1.01g */ i < SCpnt->use_sg; i++, pSG++, pSrbSG++) { -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) pSG->SG_Ptr = (U32) VIRT_TO_BUS(pSrbSG->address); -#else - pSG->SG_Ptr = (U32) (pSrbSG->address); -#endif TotalLen += pSG->SG_Len = pSrbSG->length; } pSCB->SCB_SGLen = i; @@ -689,11 +503,7 @@ static void i91uBuildSCB(HCS * pHCB, SCB * pSCB, Scsi_Cmnd * SCpnt) pSCB->SCB_BufLen = (SCpnt->request_bufflen > TotalLen) ? TotalLen : SCpnt->request_bufflen; } else { /* Non SG */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) pSCB->SCB_BufPtr = (U32) VIRT_TO_BUS(SCpnt->request_buffer); -#else - pSCB->SCB_BufPtr = (U32) (SCpnt->request_buffer); -#endif pSCB->SCB_BufLen = SCpnt->request_bufflen; pSCB->SCB_SGLen = 0; } @@ -768,11 +578,7 @@ int i91u_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) /* * Return the "logical geometry" */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) int i91u_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array) -#else -int i91u_biosparam(Scsi_Disk * disk, int dev, int *info_array) -#endif { HCS *pHcb; /* Point to Host adapter control block */ TCS *pTcb; @@ -887,196 +693,116 @@ static void i91uSCBPost(BYTE * pHcb, BYTE * pScb) /* * Interrupts handler (main routine of the driver) */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) static void i91u_intr0(int irqno, void *dev_id, struct pt_regs *regs) -#else -static void i91u_intr0(int irqno, struct pt_regs *regs) -#endif { -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) unsigned long flags; -#endif if (tul_hcs[0].HCS_Intr != irqno) return; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_lock_irqsave(&io_request_lock, flags); -#endif tul_isr(&tul_hcs[0]); -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_unlock_irqrestore(&io_request_lock, flags); -#endif } -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) static void i91u_intr1(int irqno, void *dev_id, struct pt_regs *regs) -#else -static void i91u_intr1(int irqno, struct pt_regs *regs) -#endif { -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) unsigned long flags; -#endif if (tul_hcs[1].HCS_Intr != irqno) return; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_lock_irqsave(&io_request_lock, flags); -#endif tul_isr(&tul_hcs[1]); -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_unlock_irqrestore(&io_request_lock, flags); -#endif } -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) static void i91u_intr2(int irqno, void *dev_id, struct pt_regs *regs) -#else -static void i91u_intr2(int irqno, struct pt_regs *regs) -#endif { -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) unsigned long flags; -#endif if (tul_hcs[2].HCS_Intr != irqno) return; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_lock_irqsave(&io_request_lock, flags); -#endif tul_isr(&tul_hcs[2]); -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_unlock_irqrestore(&io_request_lock, flags); -#endif } -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) static void i91u_intr3(int irqno, void *dev_id, struct pt_regs *regs) -#else -static void i91u_intr3(int irqno, struct pt_regs *regs) -#endif { -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) unsigned long flags; -#endif if (tul_hcs[3].HCS_Intr != irqno) return; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_lock_irqsave(&io_request_lock, flags); -#endif tul_isr(&tul_hcs[3]); -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_unlock_irqrestore(&io_request_lock, flags); -#endif } -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) static void i91u_intr4(int irqno, void *dev_id, struct pt_regs *regs) -#else -static void i91u_intr4(int irqno, struct pt_regs *regs) -#endif { -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) unsigned long flags; -#endif if (tul_hcs[4].HCS_Intr != irqno) return; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_lock_irqsave(&io_request_lock, flags); -#endif tul_isr(&tul_hcs[4]); -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_unlock_irqrestore(&io_request_lock, flags); -#endif } -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) static void i91u_intr5(int irqno, void *dev_id, struct pt_regs *regs) -#else -static void i91u_intr5(int irqno, struct pt_regs *regs) -#endif { -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) unsigned long flags; -#endif if (tul_hcs[5].HCS_Intr != irqno) return; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_lock_irqsave(&io_request_lock, flags); -#endif tul_isr(&tul_hcs[5]); -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_unlock_irqrestore(&io_request_lock, flags); -#endif } -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) static void i91u_intr6(int irqno, void *dev_id, struct pt_regs *regs) -#else -static void i91u_intr6(int irqno, struct pt_regs *regs) -#endif { -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) unsigned long flags; -#endif if (tul_hcs[6].HCS_Intr != irqno) return; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_lock_irqsave(&io_request_lock, flags); -#endif tul_isr(&tul_hcs[6]); -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_unlock_irqrestore(&io_request_lock, flags); -#endif } -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) static void i91u_intr7(int irqno, void *dev_id, struct pt_regs *regs) -#else -static void i91u_intr7(int irqno, struct pt_regs *regs) -#endif { -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) unsigned long flags; -#endif if (tul_hcs[7].HCS_Intr != irqno) return; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_lock_irqsave(&io_request_lock, flags); -#endif tul_isr(&tul_hcs[7]); -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_unlock_irqrestore(&io_request_lock, flags); -#endif } /* diff --git a/drivers/scsi/ini9100u.h b/drivers/scsi/ini9100u.h index 14302f256ea6..e3e835085887 100644 --- a/drivers/scsi/ini9100u.h +++ b/drivers/scsi/ini9100u.h @@ -83,68 +83,16 @@ extern int i91u_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); extern int i91u_abort(Scsi_Cmnd *); extern int i91u_reset(Scsi_Cmnd *, unsigned int); -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1, 3, 0) extern int i91u_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */ extern struct proc_dir_entry proc_scsi_ini9100u; -#else -extern int i91u_biosparam(Disk *, int, int *); /*for linux v1.13 */ #endif #define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.03g" -#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(1, 3, 0) -#define INI9100U { \ - NULL, \ - NULL, \ - i91u_REVID, \ - i91u_detect, \ - NULL, \ - NULL, \ - i91u_command, \ - i91u_queue, \ - i91u_abort, \ - i91u_reset, \ - NULL, \ - i91u_biosparam, \ - 1, \ - 7, \ - SG_ALL, \ - 1, \ - 0, \ - 0, \ - ENABLE_CLUSTERING \ -} -#else - -#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2, 1, 75) -#define INI9100U { \ - NULL, \ - NULL, \ - &proc_scsi_ini9100u, \ - NULL, \ - i91u_REVID, \ - i91u_detect, \ - NULL, \ - NULL, \ - i91u_command, \ - i91u_queue, \ - i91u_abort, \ - i91u_reset, \ - NULL, \ - i91u_biosparam, \ - 1, \ - 7, \ - SG_ALL, \ - 1, \ - 0, \ - 0, \ - ENABLE_CLUSTERING \ -} -#else /* Version >= 2.1.75 */ #define INI9100U { \ next: NULL, \ module: NULL, \ - proc_dir: &proc_scsi_ini9100u, \ + proc_name: "INI9100U", \ proc_info: NULL, \ name: i91u_REVID, \ detect: i91u_detect, \ @@ -170,9 +118,6 @@ extern int i91u_biosparam(Disk *, int, int *); /*for linux v1.13 */ use_clustering: ENABLE_CLUSTERING, \ use_new_eh_code: 0 \ } -#endif -#endif - #define VIRT_TO_BUS(i) (unsigned int) virt_to_bus((void *)(i)) #define ULONG unsigned long @@ -330,11 +275,9 @@ typedef struct Ha_Ctrl_Struc { TCS HCS_Tcs[16]; /* 78 -> 16 Targets */ Scsi_Cmnd *pSRB_head; /* SRB save queue header */ Scsi_Cmnd *pSRB_tail; /* SRB save queue tail */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spinlock_t HCS_AvailLock; spinlock_t HCS_SemaphLock; spinlock_t pSRB_lock; -#endif } HCS; /* Bit Definition for HCB_Flags */ diff --git a/drivers/scsi/inia100.c b/drivers/scsi/inia100.c index 5203b6e36923..38b49daeec70 100644 --- a/drivers/scsi/inia100.c +++ b/drivers/scsi/inia100.c @@ -71,33 +71,16 @@ #include #endif -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) #include #include #include #include -#if LINUX_VERSION_CODE <= CVT_LINUX_VERSION(2,1,92) -#include -#endif #include -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,23) #include -#endif #include -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) #include -#endif #include #include - -#else - -#include -#include -#include -#include "../block/blk.h" -#endif - #include #include #include @@ -122,15 +105,6 @@ char *inia100_InitioName = "by Initio Corporation"; char *inia100_ProductName = "INI-A100U2W"; char *inia100_Version = "v1.02c"; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) -struct proc_dir_entry proc_scsi_inia100 = -{ - PROC_SCSI_INIA100, 7, "INIA100", - S_IFDIR | S_IRUGO | S_IXUGO, 2, - 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; -#endif - /* set by inia100_setup according to the command line */ static int setup_called = 0; static int orc_num_ch = MAX_SUPPORTED_ADAPTERS; /* Maximum 4 adapters */ @@ -139,7 +113,6 @@ static int orc_num_ch = MAX_SUPPORTED_ADAPTERS; /* Maximum 4 adapters #define NUMBER(arr) (sizeof(arr) / sizeof(arr[0])) static char *setup_str = (char *) NULL; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) static void inia100_intr0(int irq, void *dev_id, struct pt_regs *); static void inia100_intr1(int irq, void *dev_id, struct pt_regs *); static void inia100_intr2(int irq, void *dev_id, struct pt_regs *); @@ -148,16 +121,6 @@ static void inia100_intr4(int irq, void *dev_id, struct pt_regs *); static void inia100_intr5(int irq, void *dev_id, struct pt_regs *); static void inia100_intr6(int irq, void *dev_id, struct pt_regs *); static void inia100_intr7(int irq, void *dev_id, struct pt_regs *); -#else -static void inia100_intr0(int irq, struct pt_regs *); -static void inia100_intr1(int irq, struct pt_regs *); -static void inia100_intr2(int irq, struct pt_regs *); -static void inia100_intr3(int irq, struct pt_regs *); -static void inia100_intr4(int irq, struct pt_regs *); -static void inia100_intr5(int irq, struct pt_regs *); -static void inia100_intr6(int irq, struct pt_regs *); -static void inia100_intr7(int irq, struct pt_regs *); -#endif static void inia100_panic(char *msg); void inia100SCBPost(BYTE * pHcb, BYTE * pScb); @@ -191,12 +154,7 @@ static void inia100AppendSRBToQueue(ORC_HCS * pHCB, Scsi_Cmnd * pSRB) { ULONG flags; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_lock_irqsave(&(pHCB->pSRB_lock), flags); -#else - save_flags(flags); - cli(); -#endif pSRB->next = NULL; /* Pointer to next */ if (pHCB->pSRB_head == NULL) @@ -204,11 +162,7 @@ static void inia100AppendSRBToQueue(ORC_HCS * pHCB, Scsi_Cmnd * pSRB) else pHCB->pSRB_tail->next = pSRB; /* Pointer to next */ pHCB->pSRB_tail = pSRB; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags); -#else - restore_flags(flags); -#endif return; } @@ -223,22 +177,12 @@ static Scsi_Cmnd *inia100PopSRBFromQueue(ORC_HCS * pHCB) { Scsi_Cmnd *pSRB; ULONG flags; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_lock_irqsave(&(pHCB->pSRB_lock), flags); -#else - save_flags(flags); - cli(); -#endif - if ((pSRB = (Scsi_Cmnd *) pHCB->pSRB_head) != NULL) { pHCB->pSRB_head = pHCB->pSRB_head->next; pSRB->next = NULL; } -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags); -#else - restore_flags(flags); -#endif return (pSRB); } @@ -293,28 +237,16 @@ int orc_ReturnNumberOfAdapters(void) unsigned long page_offset, base; #endif -#if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92) struct pci_dev *pdev = NULL; -#else - int index; - unsigned char pci_bus, pci_devfn; -#endif bPCIBusNum = 0; bPCIDeviceNum = 0; init_inia100Adapter_table(); for (i = 0; i < NUMBER(inia100_pci_devices); i++) { -#if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92) pdev = NULL; while ((pdev = pci_find_device(inia100_pci_devices[i].vendor_id, inia100_pci_devices[i].device_id, pdev))) -#else - index = 0; - while (!(pcibios_find_device(inia100_pci_devices[i].vendor_id, - inia100_pci_devices[i].device_id, - index++, &pci_bus, &pci_devfn))) -#endif { if (iAdapters >= MAX_SUPPORTED_ADAPTERS) break; /* Never greater than maximum */ @@ -328,7 +260,6 @@ int orc_ReturnNumberOfAdapters(void) /* * Read sundry information from PCI BIOS. */ -#if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92) bPCIBusNum = pdev->bus->number; bPCIDeviceNum = pdev->devfn; dRegValue = pdev->resource[0].start; @@ -346,26 +277,6 @@ int orc_ReturnNumberOfAdapters(void) pci_write_config_word(pdev, PCI_COMMAND, command | PCI_COMMAND_MASTER | PCI_COMMAND_IO); -#else - bPCIBusNum = pci_bus; - bPCIDeviceNum = pci_devfn; - pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_0, - &dRegValue); - if (dRegValue == -1) { /* Check return code */ - printk("\n\rinia100: Orchid read configuration error.\n"); - return (0); /* Read configuration space error */ - } - /* <02> read from base address + 0x50 offset to get the wBIOS balue. */ - wBASE = (WORD) dRegValue; - - /* Now read the interrupt line */ - pcibios_read_config_dword(pci_bus, pci_devfn, PCI_INTERRUPT_LINE, - &dRegValue); - bInterrupt = dRegValue & 0xFF; /* Assign interrupt line */ - pcibios_read_config_word(pci_bus, pci_devfn, PCI_COMMAND, &command); - pcibios_write_config_word(pci_bus, pci_devfn, PCI_COMMAND, - command | PCI_COMMAND_MASTER | PCI_COMMAND_IO); -#endif wBASE &= PCI_BASE_ADDRESS_IO_MASK; wBIOS = ORC_RDWORD(wBASE, 0x50); @@ -377,11 +288,7 @@ int orc_ReturnNumberOfAdapters(void) * replace the next line with this one if you are using 2.1.x: * temp_p->maddr = ioremap(base, page_offset + 256); */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,0) wBASE = ioremap(base, page_offset + 256); -#else - wBASE = (WORD) vremap(base, page_offset + 256); -#endif if (wBASE) { wBASE += page_offset; } @@ -414,9 +321,7 @@ int inia100_detect(Scsi_Host_Template * tpnt) ULONG dBiosAdr; BYTE *pbBiosAdr; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) - tpnt->proc_dir = &proc_scsi_inia100; -#endif + tpnt->proc_name = "INIA100"; if (setup_called) { /* Setup by inia100_setup */ printk("inia100: processing commandline: "); @@ -446,9 +351,7 @@ int inia100_detect(Scsi_Host_Template * tpnt) pHCB->pSRB_head = NULL; /* Initial SRB save queue */ pHCB->pSRB_tail = NULL; /* Initial SRB save queue */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) pHCB->pSRB_lock = SPIN_LOCK_UNLOCKED; /* SRB save queue lock */ -#endif /* Get total memory needed for SCB */ sz = orc_num_scb * sizeof(ORC_SCB); if ((pHCB->HCS_virScbArray = (PVOID) kmalloc(sz, GFP_ATOMIC | GFP_DMA)) == NULL) { @@ -473,9 +376,7 @@ int inia100_detect(Scsi_Host_Template * tpnt) dBiosAdr = pHCB->HCS_BIOS; dBiosAdr = (dBiosAdr << 4); -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) pbBiosAdr = phys_to_virt(dBiosAdr); -#endif if (init_orchid(pHCB)) { /* Initial orchid chip */ printk("inia100: initial orchid fail!!\n"); @@ -489,10 +390,8 @@ int inia100_detect(Scsi_Host_Template * tpnt) hreg->n_io_port = 0xff; hreg->can_queue = orc_num_scb; /* 03/05/98 */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) hreg->unique_id = pHCB->HCS_Base; hreg->max_id = pHCB->HCS_MaxTar; -#endif hreg->max_lun = 32; /* 10/21/97 */ /* @@ -511,7 +410,6 @@ int inia100_detect(Scsi_Host_Template * tpnt) /* Initial orc chip */ switch (i) { -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) case 0: ok = request_irq(pHCB->HCS_Intr, inia100_intr0, SA_INTERRUPT | SA_SHIRQ, "inia100", NULL); break; @@ -556,7 +454,6 @@ int inia100_detect(Scsi_Host_Template * tpnt) } inia100_panic("inia100: driver needs an IRQ.\n"); } -#endif } tpnt->this_id = -1; @@ -598,21 +495,13 @@ static void inia100BuildSCB(ORC_HCS * pHCB, ORC_SCB * pSCB, Scsi_Cmnd * SCpnt) pSCB->SCB_SGLen = (U32) (SCpnt->use_sg * 8); pSrbSG = (struct scatterlist *) SCpnt->request_buffer; for (i = 0; i < SCpnt->use_sg; i++, pSG++, pSrbSG++) { -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) pSG->SG_Ptr = (U32) (VIRT_TO_BUS(pSrbSG->address)); -#else - pSG->SG_Ptr = (U32) pSrbSG->address; -#endif pSG->SG_Len = (U32) pSrbSG->length; TotalLen += (U32) pSrbSG->length; } } else { /* Non SG */ pSCB->SCB_SGLen = 0x8; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) pSG->SG_Ptr = (U32) (VIRT_TO_BUS(SCpnt->request_buffer)); -#else - pSG->SG_PTR = (U32) SCpnt->request_buffer; -#endif pSG->SG_Len = (U32) SCpnt->request_bufflen; } } @@ -802,11 +691,7 @@ void inia100SCBPost(BYTE * pHcb, BYTE * pScb) Output : None. Return : pSRB - Pointer to SCSI request block. *****************************************************************************/ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) int inia100_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array) -#else -int inia100_biosparam(Scsi_Disk * disk, int dev, int *info_array) -#endif { ORC_HCS *pHcb; /* Point to Host adapter control block */ ORC_TCS *pTcb; @@ -835,96 +720,58 @@ int inia100_biosparam(Scsi_Disk * disk, int dev, int *info_array) static void subIntr(ORC_HCS * pHCB, int irqno) { -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) unsigned long flags; spin_lock_irqsave(&io_request_lock, flags); -#endif if (pHCB->HCS_Intr != irqno) { -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_unlock_irqrestore(&io_request_lock, flags); -#endif return; } orc_interrupt(pHCB); -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_unlock_irqrestore(&io_request_lock, flags); -#endif } /* * Interrupts handler (main routine of the driver) */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) static void inia100_intr0(int irqno, void *dev_id, struct pt_regs *regs) -#else -static void inia100_intr0(int irqno, struct pt_regs *regs) -#endif { subIntr(&orc_hcs[0], irqno); } -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) static void inia100_intr1(int irqno, void *dev_id, struct pt_regs *regs) -#else -static void inia100_intr1(int irqno, struct pt_regs *regs) -#endif { subIntr(&orc_hcs[1], irqno); } -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) static void inia100_intr2(int irqno, void *dev_id, struct pt_regs *regs) -#else -static void inia100_intr2(int irqno, struct pt_regs *regs) -#endif { subIntr(&orc_hcs[2], irqno); } -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) static void inia100_intr3(int irqno, void *dev_id, struct pt_regs *regs) -#else -static void inia100_intr3(int irqno, struct pt_regs *regs) -#endif { subIntr(&orc_hcs[3], irqno); } -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) static void inia100_intr4(int irqno, void *dev_id, struct pt_regs *regs) -#else -static void inia100_intr4(int irqno, struct pt_regs *regs) -#endif { subIntr(&orc_hcs[4], irqno); } -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) static void inia100_intr5(int irqno, void *dev_id, struct pt_regs *regs) -#else -static void inia100_intr5(int irqno, struct pt_regs *regs) -#endif { subIntr(&orc_hcs[5], irqno); } -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) static void inia100_intr6(int irqno, void *dev_id, struct pt_regs *regs) -#else -static void inia100_intr6(int irqno, struct pt_regs *regs) -#endif { subIntr(&orc_hcs[6], irqno); } -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) static void inia100_intr7(int irqno, void *dev_id, struct pt_regs *regs) -#else -static void inia100_intr7(int irqno, struct pt_regs *regs) -#endif { subIntr(&orc_hcs[7], irqno); } diff --git a/drivers/scsi/inia100.h b/drivers/scsi/inia100.h index 3486897ee13e..509a42b5e166 100644 --- a/drivers/scsi/inia100.h +++ b/drivers/scsi/inia100.h @@ -76,69 +76,14 @@ extern int inia100_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); extern int inia100_abort(Scsi_Cmnd *); extern int inia100_reset(Scsi_Cmnd *, unsigned int); -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1, 3, 0) extern int inia100_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */ -extern struct proc_dir_entry proc_scsi_inia100; -#else -extern int inia100_biosparam(Disk *, int, int *); /*for linux v1.13 */ -#endif #define inia100_REVID "Initio INI-A100U2W SCSI device driver; Revision: 1.02c" -#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(1, 3, 0) -#define INIA100 { \ - NULL, \ - NULL, \ - inia100_REVID, \ - inia100_detect, \ - NULL, \ - NULL, \ - inia100_command, \ - inia100_queue, \ - inia100_abort, \ - inia100_reset, \ - NULL, \ - inia100_biosparam, \ - 1, \ -7, \ -SG_ALL, \ -1, \ -0, \ -0, \ -ENABLE_CLUSTERING \ -} - -#else - -#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2, 1, 75) -#define INIA100 { \ - NULL, \ - NULL, \ - &proc_scsi_inia100, \ - NULL, \ - inia100_REVID, \ - inia100_detect, \ - NULL, \ - NULL, \ - inia100_command, \ - inia100_queue, \ - inia100_abort, \ - inia100_reset, \ - NULL, \ - inia100_biosparam, \ - 1, \ - 7, \ - 0, \ - 1, \ - 0, \ - 0, \ - ENABLE_CLUSTERING \ -} -#else /* Version >= 2.1.75 */ #define INIA100 { \ next: NULL, \ module: NULL, \ - proc_dir: &proc_scsi_inia100, \ + proc_name: "INIA100", \ proc_info: NULL, \ name: inia100_REVID, \ detect: inia100_detect, \ @@ -164,8 +109,6 @@ ENABLE_CLUSTERING \ use_clustering: ENABLE_CLUSTERING, \ use_new_eh_code: 0 \ } -#endif -#endif #define VIRT_TO_BUS(i) (unsigned int) virt_to_bus((void *)(i)) #define ULONG unsigned long @@ -441,14 +384,10 @@ typedef struct ORC_Ha_Ctrl_Struc { UBYTE ActiveTags[16][16]; /* 50 */ ORC_TCS HCS_Tcs[16]; /* 28 */ U32 BitAllocFlag[MAX_CHANNELS][8]; /* Max STB is 256, So 256/32 */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spinlock_t BitAllocFlagLock; -#endif Scsi_Cmnd *pSRB_head; Scsi_Cmnd *pSRB_tail; -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spinlock_t pSRB_lock; -#endif } ORC_HCS; /* Bit Definition for HCS_Flags */ diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 3a422e6bc611..7c0b9e6b9651 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -113,20 +113,6 @@ #define IPS_VERSION_HIGH "1.00" /* MUST be 4 chars */ #define IPS_VERSION_LOW ".00 " /* MUST be 4 chars */ -struct proc_dir_entry proc_scsi_ips = { -#if !defined(PROC_SCSI_IPS) - 0, /* Use dynamic inode allocation */ -#else - PROC_SCSI_IPS, -#endif - 3, "ips", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - -#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,93) - #include -#endif - #if !defined(__i386__) #error "This driver has only been tested on the x86 platform" #endif @@ -262,7 +248,7 @@ ips_detect(Scsi_Host_Template *SHT) { DBG("ips_detect"); SHT->proc_info = ips_proc_info; - SHT->proc_dir = &proc_scsi_ips; + SHT->proc_name = "ips"; #if defined(CONFIG_PCI) diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index 791b144d738c..967b69522bfb 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h @@ -271,7 +271,6 @@ #define IPS { \ next : NULL, \ module : NULL, \ - proc_dir : NULL, \ proc_info : NULL, \ name : NULL, \ detect : ips_detect, \ diff --git a/drivers/scsi/jazz_esp.h b/drivers/scsi/jazz_esp.h index 7fb2c54d3081..443d8505c1ce 100644 --- a/drivers/scsi/jazz_esp.h +++ b/drivers/scsi/jazz_esp.h @@ -21,7 +21,7 @@ extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); #define SCSI_JAZZ_ESP { \ - proc_dir: &proc_scsi_esp, \ + proc_name: "esp", \ proc_info: &esp_proc_info, \ name: "ESP 100/100a/200", \ detect: jazz_esp_detect, \ diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c index 5afba45d56e0..f407740b904b 100644 --- a/drivers/scsi/mac53c94.c +++ b/drivers/scsi/mac53c94.c @@ -26,11 +26,6 @@ #include "hosts.h" #include "mac53c94.h" -struct proc_dir_entry proc_scsi_mac53c94 = { - PROC_SCSI_53C94, 5, "53c94", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - enum fsc_phase { idle, selecting, diff --git a/drivers/scsi/mac53c94.h b/drivers/scsi/mac53c94.h index 3aed6ae0ca9a..320e7f0b38a8 100644 --- a/drivers/scsi/mac53c94.h +++ b/drivers/scsi/mac53c94.h @@ -7,8 +7,6 @@ #ifndef _MAC53C94_H #define _MAC53C94_H -extern struct proc_dir_entry proc_scsi_mac53c94; - int mac53c94_detect(Scsi_Host_Template *); int mac53c94_command(Scsi_Cmnd *); int mac53c94_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); @@ -16,7 +14,7 @@ int mac53c94_abort(Scsi_Cmnd *); int mac53c94_reset(Scsi_Cmnd *, unsigned int); #define SCSI_MAC53C94 { \ - proc_dir: &proc_scsi_mac53c94, \ + proc_name: "53c94", \ name: "53C94", \ detect: mac53c94_detect, \ command: mac53c94_command, \ diff --git a/drivers/scsi/mac_esp.h b/drivers/scsi/mac_esp.h index 9de3186d0f4c..4d17f665c79e 100644 --- a/drivers/scsi/mac_esp.h +++ b/drivers/scsi/mac_esp.h @@ -21,7 +21,7 @@ extern int esp_abort(Scsi_Cmnd *); extern int esp_reset(Scsi_Cmnd *, unsigned int); -#define SCSI_MAC_ESP { proc_dir: &proc_scsi_esp, \ +#define SCSI_MAC_ESP { proc_name: "esp", \ name: "Mac 53C9x SCSI", \ detect: mac_esp_detect, \ release: NULL, \ diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 3832fa266541..9e5bdf2b28ff 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -141,10 +141,6 @@ static int polled_scsi_on = 0; #define AFTER_RESET_DELAY (HZ/2) #endif -static struct proc_dir_entry proc_scsi_mac5380 = { - PROC_SCSI_MAC, 13, "Mac 5380 SCSI", S_IFDIR | S_IRUGO, S_IXUGO, 2 -}; - static volatile unsigned char *mac_scsi_regp = NULL; static volatile unsigned char *mac_scsi_drq = NULL; static volatile unsigned char *mac_scsi_nodrq = NULL; @@ -257,7 +253,7 @@ int macscsi_detect(Scsi_Host_Template * tpnt) if (macintosh_config->scsi_type != MAC_SCSI_OLD) return( 0 ); - tpnt->proc_dir = &proc_scsi_mac5380; + tpnt->proc_name = "Mac 5380 SCSI"; /* setup variables */ tpnt->can_queue = diff --git a/drivers/scsi/mca_53c9x.h b/drivers/scsi/mca_53c9x.h index 57d1d3ff993e..5172d2aa3ed3 100644 --- a/drivers/scsi/mca_53c9x.h +++ b/drivers/scsi/mca_53c9x.h @@ -31,7 +31,7 @@ extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); -#define MCA_53C9X { proc_dir: &proc_scsi_esp, \ +#define MCA_53C9X { proc_name: "esp", \ name: "NCR 53c9x SCSI", \ detect: mca_esp_detect, \ release: mca_esp_release, \ diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 62400530496a..7ea7e6f91fd3 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -133,13 +133,11 @@ #include #include -#if LINUX_VERSION_CODE >= 0x20100 char kernel_version[] = UTS_RELEASE; MODULE_AUTHOR ("American Megatrends Inc."); MODULE_DESCRIPTION ("AMI MegaRAID driver"); #endif -#endif #include #include @@ -157,11 +155,7 @@ MODULE_DESCRIPTION ("AMI MegaRAID driver"); #include #include -#if LINUX_VERSION_CODE < 0x20100 -#include -#else #include -#endif #include #include @@ -180,27 +174,8 @@ MODULE_DESCRIPTION ("AMI MegaRAID driver"); *================================================================ */ -#if LINUX_VERSION_CODE < 0x020100 -#define ioremap vremap -#define iounmap vfree - -/* simulate spin locks */ -typedef struct { - volatile char lock; -} spinlock_t; - -#define spin_lock_init(x) { (x)->lock = 0;} -#define spin_lock_irqsave(x,flags) { while ((x)->lock) barrier();\ - (x)->lock=1; save_flags(flags);\ - cli();} -#define spin_unlock_irqrestore(x,flags) { (x)->lock=0; restore_flags(flags);} - -#endif - -#if LINUX_VERSION_CODE >= 0x020100 #define queue_task_irq(a,b) queue_task(a,b) #define queue_task_irq_off(a,b) queue_task(a,b) -#endif #define MAX_SERBUF 160 #define COM_BASE 0x2f8 @@ -294,11 +269,9 @@ static int ser_printk (const char *fmt,...); XX scsi id on each channel. Used for Madrona motherboard, where SAF_TE processor id cannot be scanned */ static char *megaraid; -#if LINUX_VERSION_CODE > 0x20100 #ifdef MODULE MODULE_PARM(megaraid, "s"); #endif -#endif static int skip_id; static int numCtlrs = 0; @@ -318,12 +291,6 @@ volatile static spinlock_t serial_lock; #endif volatile static spinlock_t mega_lock; -struct proc_dir_entry proc_scsi_megaraid = -{ - PROC_SCSI_MEGARAID, 8, "megaraid", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - #if SERDEBUG static char strbuf[MAX_SERBUF + 1]; @@ -930,9 +897,7 @@ static void megaraid_isr (int irq, void *devp, struct pt_regs *regs) megaCfg = (mega_host_config *) devp; mbox = (mega_mailbox *)tmpBox; -#if LINUX_VERSION_CODE >= 0x20100 spin_lock_irqsave (&io_request_lock, flags); -#endif while (megaCfg->host->irq == irq) { @@ -1028,9 +993,7 @@ static void megaraid_isr (int irq, void *devp, struct pt_regs *regs) } -#if LINUX_VERSION_CODE >= 0x20100 spin_unlock_irqrestore (&io_request_lock, flags); -#endif } /*==================================================*/ @@ -1450,20 +1413,11 @@ int findCard (Scsi_Host_Template * pHostTmpl, u16 pciIdx = 0; u16 numFound = 0; -#if LINUX_VERSION_CODE < 0x20100 - while (!pcibios_find_device (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) { - -#if 0 - } /* keep auto-indenters happy */ -#endif -#else - struct pci_dev *pdev = pci_devices; while ((pdev = pci_find_device (pciVendor, pciDev, pdev))) { pciBus = pdev->bus->number; pciDevFun = pdev->devfn; -#endif if ((flag & BOARD_QUARTZ) && (skip_id == -1)) { u16 magic; pcibios_read_config_word (pciBus, pciDevFun, @@ -1555,14 +1509,8 @@ int megaraid_detect (Scsi_Host_Template * pHostTmpl) { int count = 0; - pHostTmpl->proc_dir = &proc_scsi_megaraid; + pHostTmpl->proc_name = "megaraid"; -#if LINUX_VERSION_CODE < 0x20100 - if (!pcibios_present ()) { - printk (KERN_WARNING "megaraid: PCI bios not present." CRLFSTR); - return 0; - } -#endif skip_id = -1; if (megaraid && !strncmp(megaraid,"skip",strlen("skip"))) { if (megaraid[4] != '\0') { diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h index 312be0385e7e..a4771100e286 100644 --- a/drivers/scsi/megaraid.h +++ b/drivers/scsi/megaraid.h @@ -605,8 +605,6 @@ typedef struct _mega_host_config { mega_scb scbList[MAX_COMMANDS]; } mega_host_config; -extern struct proc_dir_entry proc_scsi_megaraid; - const char *megaraid_info(struct Scsi_Host *); int megaraid_detect(Scsi_Host_Template *); int megaraid_release(struct Scsi_Host *); diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index 8cadff737909..7c14a6c3f962 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c @@ -65,11 +65,6 @@ unsigned char use_active_neg = 0; /* bit mask for SEQ_ACTIVE_NEG if used */ #define ALLOW_DEBUG(tgt) ((mesh_debug_targets >> (tgt)) & 1) #define DEBUG_TARGET(cmd) ((cmd) && ALLOW_DEBUG((cmd)->target)) -struct proc_dir_entry proc_scsi_mesh = { - PROC_SCSI_MESH, 4, "mesh", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - #undef MESH_DBG #define N_DBG_LOG 50 #define N_DBG_SLOG 20 diff --git a/drivers/scsi/mesh.h b/drivers/scsi/mesh.h index 30f66dad2835..7ceeaf1a4c5c 100644 --- a/drivers/scsi/mesh.h +++ b/drivers/scsi/mesh.h @@ -7,8 +7,6 @@ #ifndef _MESH_H #define _MESH_H -extern struct proc_dir_entry proc_scsi_mesh; - int mesh_detect(Scsi_Host_Template *); int mesh_command(Scsi_Cmnd *); int mesh_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); @@ -16,7 +14,7 @@ int mesh_abort(Scsi_Cmnd *); int mesh_reset(Scsi_Cmnd *, unsigned int); #define SCSI_MESH { \ - proc_dir: &proc_scsi_mesh, \ + proc_name: "mesh", \ name: "MESH", \ detect: mesh_detect, \ command: mesh_command, \ diff --git a/drivers/scsi/mvme16x.c b/drivers/scsi/mvme16x.c index 085b41615e42..71121b726fe8 100644 --- a/drivers/scsi/mvme16x.c +++ b/drivers/scsi/mvme16x.c @@ -21,11 +21,6 @@ #include -struct proc_dir_entry proc_scsi_mvme16x = { - PROC_SCSI_MVME16x, 7, "MVME16x", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - extern ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip, u32 base, int io_port, int irq, int dma, long long options, int clock); @@ -45,7 +40,7 @@ int mvme16x_scsi_detect(Scsi_Host_Template *tpnt) if (called) return 0; - tpnt->proc_dir = &proc_scsi_mvme16x; + tpnt->proc_name = "MVME16x" options = OPTION_MEMORY_MAPPED|OPTION_DEBUG_TEST1|OPTION_INTFLY|OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS|OPTION_DISCONNECT; diff --git a/drivers/scsi/mvme16x.h b/drivers/scsi/mvme16x.h index 16c9149ff1b7..172b82a74163 100644 --- a/drivers/scsi/mvme16x.h +++ b/drivers/scsi/mvme16x.h @@ -26,8 +26,6 @@ void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs); #if defined(HOSTS_C) || defined(MODULE) #include -extern struct proc_dir_entry proc_scsi_mvme16x; - #define MVME16x_SCSI {name: "MVME16x NCR53c710 SCSI", \ detect: mvme16x_scsi_detect, \ queuecommand: NCR53c7xx_queue_command, \ diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 0ed2fb997c74..837b4be833e7 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -733,10 +733,6 @@ static Scsi_Host_Template *the_template = NULL; ** /proc directory entry and proc_info function */ -static struct proc_dir_entry proc_scsi_ncr53c8xx = { - PROC_SCSI_NCR53C8XX, 9, "ncr53c8xx", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; #ifdef SCSI_NCR_PROC_INFO_SUPPORT static int ncr53c8xx_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int func); @@ -9383,7 +9379,7 @@ int __init ncr53c8xx_detect(Scsi_Host_Template *tpnt) ncr_debug = driver_setup.debug; #endif - tpnt->proc_dir = &proc_scsi_ncr53c8xx; + tpnt->proc_name = "ncr53c8xx"; #ifdef SCSI_NCR_PROC_INFO_SUPPORT tpnt->proc_info = ncr53c8xx_proc_info; #endif diff --git a/drivers/scsi/oktagon_esp.h b/drivers/scsi/oktagon_esp.h index 91a3a7cfedec..231cefcd338a 100644 --- a/drivers/scsi/oktagon_esp.h +++ b/drivers/scsi/oktagon_esp.h @@ -40,7 +40,7 @@ extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); #define SCSI_OKTAGON_ESP { \ - proc_dir: &proc_scsi_esp, \ + proc_name: "esp-oktagon", \ proc_info: &esp_proc_info, \ name: "BSC Oktagon SCSI", \ detect: oktagon_esp_detect, \ diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 4e3594a44a4b..3fedd3b4eea5 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -131,10 +131,6 @@ #include #include -struct proc_dir_entry proc_scsi_pas16 = { - PROC_SCSI_PAS16, 5, "pas16", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; static int pas_maxi = 0; static int pas_wmaxi = 0; static unsigned short pas16_addr = 0; @@ -392,7 +388,7 @@ int __init pas16_detect(Scsi_Host_Template * tpnt) unsigned short io_port; int count; - tpnt->proc_dir = &proc_scsi_pas16; + tpnt->proc_name = "pas16"; tpnt->proc_info = &pas16_proc_info; if (pas16_addr != 0) { diff --git a/drivers/scsi/pci2000.c b/drivers/scsi/pci2000.c index f05afc979de9..83efa5df6e35 100644 --- a/drivers/scsi/pci2000.c +++ b/drivers/scsi/pci2000.c @@ -53,15 +53,7 @@ #include "pci2000.h" #include "psi_roy.h" -#if LINUX_VERSION_CODE >= LINUXVERSION(2,1,95) #include -#endif -#if LINUX_VERSION_CODE < LINUXVERSION(2,1,93) -#include -#endif - -struct proc_dir_entry Proc_Scsi_Pci2000 = - { PROC_SCSI_PCI2000, 7, "pci2000", S_IFDIR | S_IRUGO | S_IXUGO, 2 }; //#define DEBUG 1 @@ -240,23 +232,13 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs) int pun; int bus; int z; -#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95) - int flags; -#else /* version >= v2.1.95 */ unsigned long flags; -#endif /* version >= v2.1.95 */ -#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95) - /* Disable interrupts, if they aren't already disabled. */ - save_flags (flags); - cli (); -#else /* version >= v2.1.95 */ /* * Disable interrupts, if they aren't already disabled and acquire * the I/O spinlock. */ spin_lock_irqsave (&io_request_lock, flags); -#endif /* version >= v2.1.95 */ DEB(printk ("\npci2000 recieved interrupt ")); for ( z = 0; z < NumAdapters; z++ ) // scan for interrupt to process @@ -345,20 +327,12 @@ irqProceed:; OpDone (SCpnt, DID_OK << 16); irq_return:; -#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95) - /* - * Restore the original flags which will enable interrupts - * if and only if they were enabled on entry. - */ - restore_flags (flags); -#else /* version >= v2.1.95 */ /* * Release the I/O spinlock and restore the original flags * which will enable interrupts if and only if they were * enabled on entry. */ spin_unlock_irqrestore (&io_request_lock, flags); -#endif /* version >= v2.1.95 */ } /**************************************************************** * Name: Pci2000_QueueCommand @@ -615,27 +589,15 @@ int Pci2000_Detect (Scsi_Host_Template *tpnt) PADAPTER2000 padapter; int z, zz; int setirq; -#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92) struct pci_dev *pdev = NULL; -#else - UCHAR pci_bus, pci_device_fn; -#endif -#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92) if ( !pci_present () ) -#else - if ( !pcibios_present () ) -#endif { printk ("pci2000: PCI BIOS not present\n"); return 0; } -#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92) while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_ROY_1, pdev)) != NULL ) -#else - while ( !pcibios_find_device (VENDOR_PSI, DEVICE_ROY_1, found, &pci_bus, &pci_device_fn) ) -#endif { pshost = scsi_register (tpnt, sizeof(ADAPTER2000)); padapter = HOSTDATA(pshost); @@ -658,11 +620,7 @@ int Pci2000_Detect (Scsi_Host_Template *tpnt) if ( WaitReady (padapter) ) goto unregister; -#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92) pshost->irq = pdev->irq; -#else - pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq); -#endif setirq = 1; padapter->irqOwned = 0; for ( z = 0; z < installed; z++ ) // scan for shared interrupts @@ -756,11 +714,7 @@ int Pci2000_Release (struct Scsi_Host *pshost) PADAPTER2000 padapter = HOSTDATA (pshost); if ( padapter->irqOwned ) -#if LINUX_VERSION_CODE < LINUXVERSION(1,3,70) - free_irq (pshost->irq); -#else /* version >= v1.3.70 */ free_irq (pshost->irq, padapter); -#endif /* version >= v1.3.70 */ release_region (pshost->io_port, pshost->n_io_port); scsi_unregister(pshost); return 0; diff --git a/drivers/scsi/pci2000.h b/drivers/scsi/pci2000.h index a3daa5f76304..9b80a489b07e 100644 --- a/drivers/scsi/pci2000.h +++ b/drivers/scsi/pci2000.h @@ -200,13 +200,10 @@ int Pci2000_BiosParam (Disk *disk, kdev_t dev, int geom[]); #define NULL 0 #endif -extern struct proc_dir_entry Proc_Scsi_Pci2000; - -#if LINUX_VERSION_CODE >= LINUXVERSION(2,1,75) #define PCI2000 { \ next: NULL, \ module: NULL, \ - proc_dir: &Proc_Scsi_Pci2000, \ + proc_name: "pci2000", \ proc_info: NULL, /* let's not bloat the kernel */ \ name: "PCI-2000 SCSI Intelligent Disk Controller",\ detect: Pci2000_Detect, \ @@ -232,27 +229,4 @@ extern struct proc_dir_entry Proc_Scsi_Pci2000; use_clustering: DISABLE_CLUSTERING, \ use_new_eh_code: 0 \ } -#else -#define PCI2000 { NULL, NULL, \ - &Proc_Scsi_Pci2000,/* proc_dir_entry */ \ - NULL, \ - "PCI-2000 SCSI Intelligent Disk Controller",\ - Pci2000_Detect, \ - Pci2000_Release, \ - NULL, \ - Pci2000_Command, \ - Pci2000_QueueCommand, \ - Pci2000_Abort, \ - Pci2000_Reset, \ - NULL, \ - Pci2000_BiosParam, \ - 16, \ - -1, \ - 16, \ - 1, \ - 0, \ - 0, \ - DISABLE_CLUSTERING } -#endif - #endif diff --git a/drivers/scsi/pci2220i.c b/drivers/scsi/pci2220i.c index bdc28518642e..e50ba45dc930 100644 --- a/drivers/scsi/pci2220i.c +++ b/drivers/scsi/pci2220i.c @@ -47,12 +47,7 @@ #include "hosts.h" #include "pci2220i.h" -#if LINUX_VERSION_CODE >= LINUXVERSION(2,1,95) #include -#endif -#if LINUX_VERSION_CODE < LINUXVERSION(2,1,93) -#include -#endif #define PCI2220I_VERSION "1.11" //#define READ_CMD IDE_COMMAND_READ @@ -62,10 +57,6 @@ #define WRITE_CMD IDE_CMD_WRITE_MULTIPLE #define MAX_BUS_MASTER_BLOCKS SECTORSXFER // This is the maximum we can bus master - -struct proc_dir_entry Proc_Scsi_Pci2220i = - { PROC_SCSI_PCI2220I, 8, "pci2220i", S_IFDIR | S_IRUGO | S_IXUGO, 2 }; - //#define DEBUG 1 #ifdef DEBUG @@ -725,23 +716,13 @@ static void TimerExpiry (unsigned long data) POUR_DEVICE pdev = padapter->pdev; UCHAR status = IDE_STATUS_BUSY; UCHAR temp, temp1; -#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95) - int flags; -#else /* version >= v2.1.95 */ unsigned long flags; -#endif /* version >= v2.1.95 */ -#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95) - /* Disable interrupts, if they aren't already disabled. */ - save_flags (flags); - cli (); -#else /* version >= v2.1.95 */ /* * Disable interrupts, if they aren't already disabled and acquire * the I/O spinlock. */ spin_lock_irqsave (&io_request_lock, flags); -#endif /* version >= v2.1.95 */ DEB (printk ("\nPCI2220I: Timeout expired ")); if ( padapter->failinprog ) @@ -866,20 +847,12 @@ static void TimerExpiry (unsigned long data) OpDone (padapter, DecodeError (padapter, status)); timerExpiryDone:; -#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95) - /* - * Restore the original flags which will enable interrupts - * if and only if they were enabled on entry. - */ - restore_flags (flags); -#else /* version >= v2.1.95 */ /* * Release the I/O spinlock and restore the original flags * which will enable interrupts if and only if they were * enabled on entry. */ spin_unlock_irqrestore (&io_request_lock, flags); -#endif /* version >= v2.1.95 */ } /**************************************************************** * Name: SetReconstruct :LOCAL @@ -920,23 +893,13 @@ static void ReconTimerExpiry (unsigned long data) USHORT minmode; ULONG zl; UCHAR zc; -#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95) - int flags; -#else /* version >= v2.1.95 */ unsigned long flags; -#endif /* version >= v2.1.95 */ -#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95) - /* Disable interrupts, if they aren't already disabled. */ - save_flags (flags); - cli (); -#else /* version >= v2.1.95 */ /* * Disable interrupts, if they aren't already disabled and acquire * the I/O spinlock. */ spin_lock_irqsave (&io_request_lock, flags); -#endif /* version >= v2.1.95 */ padapter = (PADAPTER2220I)data; if ( padapter->SCpnt ) @@ -1132,20 +1095,12 @@ static void ReconTimerExpiry (unsigned long data) padapter->reconPhase = RECON_PHASE_LAST; reconTimerExpiry:; -#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95) - /* - * Restore the original flags which will enable interrupts - * if and only if they were enabled on entry. - */ - restore_flags (flags); -#else /* version >= v2.1.95 */ /* * Release the I/O spinlock and restore the original flags * which will enable interrupts if and only if they were * enabled on entry. */ spin_unlock_irqrestore (&io_request_lock, flags); -#endif /* version >= v2.1.95 */ } /**************************************************************** * Name: Irq_Handler :LOCAL @@ -1169,23 +1124,13 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs) UCHAR status1; int z; ULONG zl; -#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95) - int flags; -#else /* version >= v2.1.95 */ unsigned long flags; -#endif /* version >= v2.1.95 */ -#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95) - /* Disable interrupts, if they aren't already disabled. */ - save_flags (flags); - cli (); -#else /* version >= v2.1.95 */ /* * Disable interrupts, if they aren't already disabled and acquire * the I/O spinlock. */ spin_lock_irqsave (&io_request_lock, flags); -#endif /* version >= v2.1.95 */ // DEB (printk ("\npci2220i recieved interrupt\n")); @@ -1513,20 +1458,12 @@ static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs) OpDone (padapter, zl); irq_return:; -#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95) - /* - * Restore the original flags which will enable interrupts - * if and only if they were enabled on entry. - */ - restore_flags (flags); -#else /* version >= v2.1.95 */ /* * Release the I/O spinlock and restore the original flags * which will enable interrupts if and only if they were * enabled on entry. */ spin_unlock_irqrestore (&io_request_lock, flags); -#endif /* version >= v2.1.95 */ } /**************************************************************** * Name: Pci2220i_QueueCommand @@ -1796,27 +1733,15 @@ int Pci2220i_Detect (Scsi_Host_Template *tpnt) int setirq; UCHAR spigot1 = FALSE; UCHAR spigot2 = FALSE; -#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92) struct pci_dev *pdev = NULL; -#else - UCHAR pci_bus, pci_device_fn; -#endif -#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92) if ( !pci_present () ) -#else - if ( !pcibios_present () ) -#endif { printk ("pci2220i: PCI BIOS not present\n"); return 0; } -#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92) while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_DALE_1, pdev)) != NULL ) -#else - while ( !pcibios_find_device (VENDOR_PSI, DEVICE_DALE_1, found, &pci_bus, &pci_device_fn) ) -#endif { pshost = scsi_register (tpnt, sizeof(ADAPTER2220I)); padapter = HOSTDATA(pshost); @@ -1854,11 +1779,7 @@ int Pci2220i_Detect (Scsi_Host_Template *tpnt) if ( !inb_p (padapter->regScratchPad + DALE_NUM_DRIVES) ) // if no devices on this board goto unregister; -#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92) pshost->irq = pdev->irq; -#else - pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq); -#endif setirq = 1; for ( z = 0; z < installed; z++ ) // scan for shared interrupts { @@ -1881,11 +1802,7 @@ int Pci2220i_Detect (Scsi_Host_Template *tpnt) if ( !padapter->kBuffer ) { printk ("Unable to allocate DMA buffer for PCI-2220I controller.\n"); -#if LINUX_VERSION_CODE < LINUXVERSION(1,3,70) - free_irq (pshost->irq); -#else /* version >= v1.3.70 */ free_irq (pshost->irq, padapter); -#endif /* version >= v1.3.70 */ goto unregister; } PsiHost[installed] = pshost; // save SCSI_HOST pointer @@ -2068,11 +1985,7 @@ int Pci2220i_Release (struct Scsi_Host *pshost) outb_p (DiskMirror[1].status, padapter->regScratchPad + DALE_RAID_1_STATUS); if ( padapter->irqOwned ) -#if LINUX_VERSION_CODE < LINUXVERSION(1,3,70) - free_irq (pshost->irq); -#else /* version >= v1.3.70 */ free_irq (pshost->irq, padapter); -#endif /* version >= v1.3.70 */ release_region (pshost->io_port, pshost->n_io_port); kfree (padapter->kBuffer); scsi_unregister(pshost); diff --git a/drivers/scsi/pci2220i.h b/drivers/scsi/pci2220i.h index 25735bdb5ec9..c3b80dd9ca7e 100644 --- a/drivers/scsi/pci2220i.h +++ b/drivers/scsi/pci2220i.h @@ -293,13 +293,10 @@ int Pci2220i_BiosParam (Disk *disk, kdev_t dev, int geom[]); #define NULL 0 #endif -extern struct proc_dir_entry Proc_Scsi_Pci2220i; - -#if LINUX_VERSION_CODE >= LINUXVERSION(2,1,75) #define PCI2220I { \ next: NULL, \ module: NULL, \ - proc_dir: &Proc_Scsi_Pci2220i, \ + proc_name: "pci2220i", \ proc_info: NULL, /* let's not bloat the kernel */\ name: "PCI-2220I EIDE Disk Controller", \ detect: Pci2220i_Detect, \ @@ -325,27 +322,4 @@ extern struct proc_dir_entry Proc_Scsi_Pci2220i; use_clustering: DISABLE_CLUSTERING, \ use_new_eh_code: 0 \ } -#else -#define PCI2220I { NULL, NULL, \ - &Proc_Scsi_Pci2220i,/* proc_dir_entry */\ - NULL, \ - "PCI-2220I EIDE Disk Controller", \ - Pci2220i_Detect, \ - Pci2220i_Release, \ - NULL, \ - Pci2220i_Command, \ - Pci2220i_QueueCommand, \ - Pci2220i_Abort, \ - Pci2220i_Reset, \ - NULL, \ - Pci2220i_BiosParam, \ - 1, \ - -1, \ - SG_NONE, \ - 1, \ - 0, \ - 0, \ - DISABLE_CLUSTERING } -#endif - #endif diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c index 0a19d9332ce5..1e6e51083d49 100644 --- a/drivers/scsi/pluto.c +++ b/drivers/scsi/pluto.c @@ -39,11 +39,6 @@ #define PLND(x) #endif -struct proc_dir_entry proc_scsi_pluto = { - PROC_SCSI_PLUTO, 5, "pluto", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - static struct ctrl_inquiry { struct Scsi_Host host; struct pluto pluto; @@ -98,7 +93,7 @@ int __init pluto_detect(Scsi_Host_Template *tpnt) fc_channel *fc; Scsi_Device dev; - tpnt->proc_dir = &proc_scsi_pluto; + tpnt->proc_name = "pluto"; fcscount = 0; for_each_online_fc_channel(fc) { if (!fc->posmap) diff --git a/drivers/scsi/ppa.h b/drivers/scsi/ppa.h index 58aba3473e29..e39aa67a9f8b 100644 --- a/drivers/scsi/ppa.h +++ b/drivers/scsi/ppa.h @@ -138,10 +138,7 @@ static int ppa_init(int); static void ppa_interrupt(void *); static int ppa_out(int, char *, int); -struct proc_dir_entry proc_scsi_ppa = -{PROC_SCSI_PPA, 3, "ppa", S_IFDIR | S_IRUGO | S_IXUGO, 2}; #else -extern struct proc_dir_entry proc_scsi_ppa; #define ppa_release 0 #endif @@ -154,7 +151,7 @@ int ppa_reset(Scsi_Cmnd *); int ppa_proc_info(char *, char **, off_t, int, int, int); int ppa_biosparam(Disk *, kdev_t, int *); -#define PPA { proc_dir: &proc_scsi_ppa, \ +#define PPA { proc_name: "ppa", \ proc_info: ppa_proc_info, \ name: "Iomega VPI0 (ppa) interface",\ detect: ppa_detect, \ diff --git a/drivers/scsi/psi240i.c b/drivers/scsi/psi240i.c index 2fa699576922..61cabd7c448d 100644 --- a/drivers/scsi/psi240i.c +++ b/drivers/scsi/psi240i.c @@ -46,9 +46,6 @@ #include -struct proc_dir_entry Proc_Scsi_Psi240i = - { PROC_SCSI_PSI240I, 7, "psi240i", S_IFDIR | S_IRUGO | S_IXUGO, 2 }; - //#define DEBUG 1 #ifdef DEBUG diff --git a/drivers/scsi/psi240i.h b/drivers/scsi/psi240i.h index 1aed96ec7d47..b15a6a075e96 100644 --- a/drivers/scsi/psi240i.h +++ b/drivers/scsi/psi240i.h @@ -318,9 +318,7 @@ int Psi240i_BiosParam (Disk *disk, kdev_t dev, int geom[]); #define NULL 0 #endif -extern struct proc_dir_entry Proc_Scsi_Psi240i; - -#define PSI240I { proc_dir: &Proc_Scsi_Psi240i,/* proc_dir_entry */ \ +#define PSI240I { proc_name: "psi240i", \ name: "PSI-240I EIDE Disk Controller",\ detect: Psi240i_Detect, \ command: Psi240i_Command, \ diff --git a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c index af76c3aa9883..6196d8eb2d20 100644 --- a/drivers/scsi/qlogicfas.c +++ b/drivers/scsi/qlogicfas.c @@ -131,11 +131,6 @@ #include "qlogicfas.h" #include -static struct proc_dir_entry proc_scsi_qlogicfas = { - PROC_SCSI_QLOGICFAS, 6, "qlogicfas", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - /*----------------------------------------------------------------*/ /* driver state info, local to driver */ static int qbase = 0; /* Port */ @@ -550,7 +545,7 @@ int qltyp; /* type of chip */ struct Scsi_Host *hreg; /* registered host structure */ unsigned long flags; -host->proc_dir = &proc_scsi_qlogicfas; +host->proc_name = "qlogicfas"; /* Qlogic Cards only exist at 0x230 or 0x330 (the chip itself decodes the address - I check 230 first since MIDI cards are typically at 330 diff --git a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c index cfaa96e5c329..8d7dfd26c2cb 100644 --- a/drivers/scsi/qlogicfc.c +++ b/drivers/scsi/qlogicfc.c @@ -698,13 +698,6 @@ static void isp2x00_print_scsi_cmd(Scsi_Cmnd *); static void isp2x00_print_status_entry(struct Status_Entry *); #endif -static struct proc_dir_entry proc_scsi_isp2x00 = -{ - PROC_SCSI_QLOGICFC, 7, "isp2x00", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - - static inline void isp2x00_enable_irqs(struct Scsi_Host *host) { outw(ISP_EN_INT | ISP_EN_RISC, host->io_port + PCI_INTER_CTL); @@ -733,7 +726,7 @@ int isp2x00_detect(Scsi_Host_Template * tmpt) device_ids[0] = PCI_DEVICE_ID_QLOGIC_ISP2100; device_ids[1] = PCI_DEVICE_ID_QLOGIC_ISP2200; - tmpt->proc_dir = &proc_scsi_isp2x00; + tmpt->proc_name = "isp2x00"; if (pci_present() == 0) { printk("qlogicfc : PCI not present\n"); diff --git a/drivers/scsi/qlogicisp.c b/drivers/scsi/qlogicisp.c index 1b5d772a2eaf..972dea19d7d7 100644 --- a/drivers/scsi/qlogicisp.c +++ b/drivers/scsi/qlogicisp.c @@ -535,12 +535,6 @@ static void isp1020_print_scsi_cmd(Scsi_Cmnd *); static void isp1020_print_status_entry(struct Status_Entry *); #endif -static struct proc_dir_entry proc_scsi_isp1020 = { - PROC_SCSI_QLOGICISP, 7, "isp1020", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - - static inline void isp1020_enable_irqs(struct Scsi_Host *host) { outw(ISP_EN_INT|ISP_EN_RISC, host->io_port + PCI_INTF_CTL); @@ -562,7 +556,7 @@ int isp1020_detect(Scsi_Host_Template *tmpt) ENTER("isp1020_detect"); - tmpt->proc_dir = &proc_scsi_isp1020; + tmpt->proc_name = "isp1020"; if (pci_present() == 0) { printk("qlogicisp : PCI not present\n"); diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index d2c00c285ff0..a42e90d404b0 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -132,11 +132,6 @@ const u_char mbox_param[] = { QLOGICISP_REQ_QUEUE_LEN) #define RES_QUEUE_DEPTH(in, out) QUEUE_DEPTH(in, out, RES_QUEUE_LEN) -static struct proc_dir_entry proc_scsi_qlogicpti = { - PROC_SCSI_QLOGICPTI, 7, "qlogicpti", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - static inline void qlogicpti_enable_irqs(struct qlogicpti_regs *qregs) { qregs->sbus_ctrl = SBUS_CTRL_ERIRQ | SBUS_CTRL_GENAB; @@ -596,7 +591,7 @@ int __init qlogicpti_detect(Scsi_Host_Template *tpnt) int qpti_node; int is_pti; - tpnt->proc_dir = &proc_scsi_qlogicpti; + tpnt->proc_name = "qlogicpti"; qptichain = 0; if(!SBus_chain) return 0; diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 6b818225ef42..6f7d51dbb0f2 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -2883,33 +2883,28 @@ static void scsi_unregister_host(Scsi_Host_Template * tpnt) for (shpnt = scsi_hostlist; shpnt; shpnt = sh1) { sh1 = shpnt->next; - if (shpnt->hostt == tpnt) { - if (shpnt->loaded_as_module) { - pcount = next_scsi_host; - /* Remove the /proc/scsi directory entry */ -#ifdef CONFIG_PROC_FS - proc_scsi_unregister(tpnt->proc_dir, - shpnt->host_no + PROC_SCSI_FILE); -#endif - if (tpnt->release) - (*tpnt->release) (shpnt); - else { - /* This is the default case for the release function. - * It should do the right thing for most correctly - * written host adapters. - */ - if (shpnt->irq) - free_irq(shpnt->irq, NULL); - if (shpnt->dma_channel != 0xff) - free_dma(shpnt->dma_channel); - if (shpnt->io_port && shpnt->n_io_port) - release_region(shpnt->io_port, shpnt->n_io_port); - } - if (pcount == next_scsi_host) - scsi_unregister(shpnt); - tpnt->present--; - } + if (shpnt->hostt != tpnt || !shpnt->loaded_as_module) + continue; + pcount = next_scsi_host; + /* Remove the /proc/scsi directory entry */ + remove_proc_entry(shpnt->proc_name, tpnt->proc_dir); + if (tpnt->release) + (*tpnt->release) (shpnt); + else { + /* This is the default case for the release function. + * It should do the right thing for most correctly + * written host adapters. + */ + if (shpnt->irq) + free_irq(shpnt->irq, NULL); + if (shpnt->dma_channel != 0xff) + free_dma(shpnt->dma_channel); + if (shpnt->io_port && shpnt->n_io_port) + release_region(shpnt->io_port, shpnt->n_io_port); } + if (pcount == next_scsi_host) + scsi_unregister(shpnt); + tpnt->present--; } /* @@ -2949,9 +2944,7 @@ static void scsi_unregister_host(Scsi_Host_Template * tpnt) break; } /* Rebuild the /proc/scsi directory entries */ -#ifdef CONFIG_PROC_FS - proc_scsi_unregister(tpnt->proc_dir, tpnt->proc_dir->low_ino); -#endif + remove_proc_entry(tpnt->proc_name, proc_scsi); MOD_DEC_USE_COUNT; } diff --git a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h index 0b42a14666f4..3921cf8e23a6 100644 --- a/drivers/scsi/scsi.h +++ b/drivers/scsi/scsi.h @@ -405,51 +405,8 @@ extern void scsi_release_command(Scsi_Cmnd *); extern int max_scsi_hosts; extern void proc_print_scsidevice(Scsi_Device *, char *, int *, int); -extern struct inode_operations proc_scsi_inode_operations; extern struct proc_dir_entry *proc_scsi; -#ifdef CONFIG_PROC_FS - -extern inline int proc_scsi_register(struct proc_dir_entry *driver, - struct proc_dir_entry *x) -{ - x->ops = &proc_scsi_inode_operations; - if(x->low_ino < PROC_SCSI_FILE){ - return(proc_register(proc_scsi, x)); - }else{ - return(proc_register(driver, x)); - } -} - -extern inline int proc_scsi_unregister(struct proc_dir_entry *driver, int x) -{ - extern void scsi_init_free(char *ptr, unsigned int size); - - if(x < PROC_SCSI_FILE) - return(proc_unregister(proc_scsi, x)); - else { - struct proc_dir_entry **p = &driver->subdir, *dp; - int ret; - - while ((dp = *p) != NULL) { - if (dp->low_ino == x) - break; - p = &dp->next; - } - ret = proc_unregister(driver, x); - scsi_init_free((char *) dp, sizeof(struct proc_dir_entry) + 4); - return(ret); - } -} - -#else - -extern inline int proc_scsi_register(struct proc_dir_entry *b, struct proc_dir_entry *c) { return 0; } -extern inline int proc_scsi_unregister(struct proc_dir_entry *a, int x) { return 0; } - -#endif /* CONFIG_PROC_FS */ - - extern void print_command(unsigned char *); extern void print_sense(const char *, Scsi_Cmnd *); extern void print_driverbyte(int scsiresult); diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index ac5c0904334c..2b23854b3fce 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -30,13 +30,6 @@ #include -struct proc_dir_entry proc_scsi_scsi_debug = -{ - PROC_SCSI_SCSI_DEBUG, 10, "scsi_debug", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - - /* A few options that we want selected */ #define NR_HOSTS_PRESENT 20 @@ -558,7 +551,7 @@ int scsi_debug_detect(Scsi_Host_Template * tpnt) int i; for (i = 0; i < NR_HOSTS_PRESENT; i++) { - tpnt->proc_dir = &proc_scsi_scsi_debug; + tpnt->proc_name = "scsi_debug"; /* Huh? In the loop??? */ scsi_register(tpnt, 0); } return NR_HOSTS_PRESENT; diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index d9abefc1b7a8..1671bd16cf38 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -404,7 +404,7 @@ int scsi_ioctl(Scsi_Device * dev, int cmd, void *arg) put_user(dev->id + (dev->lun << 8) + (dev->channel << 16) - + ((dev->host->hostt->proc_dir->low_ino & 0xff) << 24), + + ((dev->host->host_no & 0xff) << 24), &((Scsi_Idlun *) arg)->dev_id); put_user(dev->host->unique_id, &((Scsi_Idlun *) arg)->host_unique_id); return 0; diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index d64b15f448f8..6ea86256d939 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c @@ -39,25 +39,16 @@ #endif #ifdef CONFIG_PROC_FS -struct scsi_dir { - struct proc_dir_entry entry; - char name[4]; -}; - /* generic_proc_info * Used if the driver currently has no own support for /proc/scsi */ -int generic_proc_info(char *buffer, char **start, off_t offset, - int length, int inode, int inout, +int generic_proc_info(char *buffer, char **start, off_t offset, int length, const char *(*info) (struct Scsi_Host *), struct Scsi_Host *sh) { int len, pos, begin; - if (inout == TRUE) - return (-ENOSYS); /* This is a no-op */ - begin = 0; if (info && sh) { pos = len = sprintf(buffer, "%s\n", info(sh)); @@ -80,64 +71,70 @@ int generic_proc_info(char *buffer, char **start, off_t offset, /* dispatch_scsi_info is the central dispatcher * It is the interface between the proc-fs and the SCSI subsystem code */ -static int dispatch_scsi_info(int ino, char *buffer, char **start, - off_t offset, int length, int func) +static int proc_scsi_read(char *buffer, char **start, off_t offset, + int length, int *eof, void *data) { - struct Scsi_Host *hpnt = scsi_hostlist; + struct Scsi_Host *hpnt = data; + int n; - while (hpnt) { - if (ino == (hpnt->host_no + PROC_SCSI_FILE)) { - if (hpnt->hostt->proc_info == NULL) - return generic_proc_info(buffer, start, offset, length, - hpnt->host_no, func, - hpnt->hostt->info, - hpnt); - else - return (hpnt->hostt->proc_info(buffer, start, offset, - length, hpnt->host_no, func)); - } - hpnt = hpnt->next; - } - - return (-EBADF); + if (hpnt->hostt->proc_info == NULL) + n = generic_proc_info(buffer, start, offset, length, + hpnt->hostt->info, hpnt); + else + n = (hpnt->hostt->proc_info(buffer, start, offset, + length, hpnt->host_no, 0)); + *eof = (nproc_dir->low_ino != inode->i_ino) - shpnt = shpnt->next; - if (!shpnt || !shpnt->module) - return; - if (fill) - __MOD_INC_USE_COUNT(shpnt->module); + struct Scsi_Host *hpnt = data; + ssize_t ret = 0; + char * page; + char *start; + + if (count > PROC_BLOCK_SIZE) + return -EOVERFLOW; + + if (!(page = (char *) __get_free_page(GFP_KERNEL))) + return -ENOMEM; + copy_from_user(page, buf, count); + + if (hpnt->hostt->proc_info == NULL) + ret = -ENOSYS; else - __MOD_DEC_USE_COUNT(shpnt->module); + ret = hpnt->hostt->proc_info(page, &start, 0, count, + hpnt->host_no, 1); + free_page((ulong) page); + return(ret); } void build_proc_dir_entries(Scsi_Host_Template * tpnt) { struct Scsi_Host *hpnt; - struct scsi_dir *scsi_hba_dir; - proc_scsi_register(0, tpnt->proc_dir); - tpnt->proc_dir->fill_inode = &scsi_proc_fill_inode; + tpnt->proc_dir = create_proc_entry(tpnt->proc_name, S_IFDIR, proc_scsi); + tpnt->proc_dir->owner = tpnt->module; hpnt = scsi_hostlist; while (hpnt) { if (tpnt == hpnt->hostt) { - scsi_hba_dir = scsi_init_malloc(sizeof(struct scsi_dir), GFP_KERNEL); - if (scsi_hba_dir == NULL) + struct proc_dir_entry *p; + p = create_proc_read_entry(hpnt->proc_name, + S_IFREG | S_IRUGO | S_IWUSR, + tpnt->proc_dir, + proc_scsi_read, + (void *)hpnt); + if (!p) panic("Not enough memory to register SCSI HBA in /proc/scsi !\n"); - memset(scsi_hba_dir, 0, sizeof(struct scsi_dir)); - scsi_hba_dir->entry.low_ino = PROC_SCSI_FILE + hpnt->host_no; - scsi_hba_dir->entry.namelen = sprintf(scsi_hba_dir->name, "%d", - hpnt->host_no); - scsi_hba_dir->entry.name = scsi_hba_dir->name; - scsi_hba_dir->entry.mode = S_IFREG | S_IRUGO | S_IWUSR; - proc_scsi_register(tpnt->proc_dir, &scsi_hba_dir->entry); + p->write_proc=proc_scsi_write; + p->owner = tpnt->module; } hpnt = hpnt->next; } @@ -293,155 +290,12 @@ void proc_print_scsidevice(Scsi_Device * scd, char *buffer, int *size, int len) return; } -/* forward references */ -static ssize_t proc_readscsi(struct file * file, char * buf, - size_t count, loff_t *ppos); -static ssize_t proc_writescsi(struct file * file, const char * buf, - size_t count, loff_t *ppos); -static long long proc_scsilseek(struct file *, long long, int); - -extern void build_proc_dir_hba_entries(uint); - -static struct file_operations proc_scsi_operations = { - proc_scsilseek, /* lseek */ - proc_readscsi, /* read */ - proc_writescsi, /* write */ - proc_readdir, /* readdir */ - NULL, /* poll */ - NULL, /* ioctl */ - NULL, /* mmap */ - NULL, /* no special open code */ - NULL, /* flush */ - NULL, /* no special release code */ - NULL /* can't fsync */ -}; - -/* - * proc directories can do almost nothing.. - */ -struct inode_operations proc_scsi_inode_operations = { - &proc_scsi_operations, /* default scsi directory file-ops */ - NULL, /* create */ - proc_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, /* flushpage */ - NULL, /* truncate */ - NULL, /* permission */ - NULL, /* smap */ - NULL /* revalidate */ -}; - -#define PROC_BLOCK_SIZE (3*1024) /* 4K page size, but our output routines - * use some slack for overruns - */ - -static ssize_t proc_readscsi(struct file * file, char * buf, - size_t count, loff_t *ppos) -{ - struct inode * inode = file->f_dentry->d_inode; - ssize_t length; - ssize_t bytes = count; - ssize_t copied = 0; - ssize_t thistime; - char * page; - char * start; - - if (!(page = (char *) __get_free_page(GFP_KERNEL))) - return(-ENOMEM); - - while (bytes > 0) { - thistime = bytes; - if(bytes > PROC_BLOCK_SIZE) - thistime = PROC_BLOCK_SIZE; - - length = dispatch_scsi_info (inode->i_ino, page, &start, - *ppos, thistime, 0); - if(length < 0) { - free_page((ulong) page); - return(length); - } - - /* - * We have been given a non page aligned block of - * the data we asked for + a bit. We have been given - * the start pointer and we know the length.. - */ - if (length <= 0) - break; - /* - * Copy the bytes - */ - copy_to_user(buf + copied, start, length); - *ppos += length; /* Move down the file */ - bytes -= length; - copied += length; - - if(length < thistime) - break; /* End of file */ - - } - - free_page((ulong) page); - return(copied); -} - - -static ssize_t proc_writescsi(struct file * file, const char * buf, - size_t count, loff_t *ppos) -{ - struct inode * inode = file->f_dentry->d_inode; - ssize_t ret = 0; - char * page; - - if(count > PROC_BLOCK_SIZE) { - return(-EOVERFLOW); - } - - if (!(page = (char *) __get_free_page(GFP_KERNEL))) - return(-ENOMEM); - copy_from_user(page, buf, count); - ret = dispatch_scsi_info (inode->i_ino, page, 0, 0, count, 1); - - free_page((ulong) page); - return(ret); -} - - -static long long proc_scsilseek(struct file * file, long long offset, int orig) -{ - switch (orig) { - case 0: - file->f_pos = offset; - return(file->f_pos); - case 1: - file->f_pos += offset; - return(file->f_pos); - case 2: - return(-EINVAL); - default: - return(-EINVAL); - } -} - #else /* if !CONFIG_PROC_FS */ void proc_print_scsidevice(Scsi_Device * scd, char *buffer, int *size, int len) { } -struct inode_operations proc_scsi_inode_operations = { 0, }; - #endif /* CONFIG_PROC_FS */ /* diff --git a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c index 741b60710a2b..d3cb4a1031dc 100644 --- a/drivers/scsi/scsi_syms.c +++ b/drivers/scsi/scsi_syms.c @@ -74,7 +74,6 @@ EXPORT_SYMBOL(scsi_sleep); EXPORT_SYMBOL(proc_print_scsidevice); EXPORT_SYMBOL(proc_scsi); -EXPORT_SYMBOL(proc_scsi_inode_operations); /* * These are here only while I debug the rest of the scsi stuff. diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 9b4de06f3faf..6c3835089a10 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -106,79 +106,76 @@ static void sd_detach(Scsi_Device *); static int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { - kdev_t dev = inode->i_rdev; - int error; - struct Scsi_Host * host; - Scsi_Device * SDev; - int diskinfo[4]; - struct hd_geometry *loc = (struct hd_geometry *) arg; + kdev_t dev = inode->i_rdev; + struct Scsi_Host * host; + Scsi_Device * SDev; + int diskinfo[4]; + struct hd_geometry *loc = (struct hd_geometry *) arg; - SDev = rscsi_disks[DEVICE_NR(dev)].device; - /* - * If we are in the middle of error recovery, don't let anyone - * else try and use this device. Also, if error recovery fails, it - * may try and take the device offline, in which case all further - * access to the device is prohibited. - */ - if( !scsi_block_when_processing_errors(SDev) ) - { - return -ENODEV; - } - - switch (cmd) { - case HDIO_GETGEO: /* Return BIOS disk parameters */ - if (!loc) return -EINVAL; - error = verify_area(VERIFY_WRITE, loc, sizeof(*loc)); - if (error) - return error; - host = rscsi_disks[DEVICE_NR(dev)].device->host; - -/* default to most commonly used values */ - - diskinfo[0] = 0x40; - diskinfo[1] = 0x20; - diskinfo[2] = rscsi_disks[DEVICE_NR(dev)].capacity >> 11; - -/* override with calculated, extended default, or driver values */ - - if(host->hostt->bios_param != NULL) - host->hostt->bios_param(&rscsi_disks[DEVICE_NR(dev)], - dev, - &diskinfo[0]); - else scsicam_bios_param(&rscsi_disks[DEVICE_NR(dev)], - dev, &diskinfo[0]); - - put_user(diskinfo[0], &loc->heads); - put_user(diskinfo[1], &loc->sectors); - put_user(diskinfo[2], &loc->cylinders); - put_user(sd[SD_PARTITION(inode->i_rdev)].start_sect, &loc->start); - return 0; - case BLKGETSIZE: /* Return device size */ - if (!arg) return -EINVAL; - error = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); - if (error) - return error; - put_user(sd[SD_PARTITION(inode->i_rdev)].nr_sects, - (long *) arg); - return 0; + SDev = rscsi_disks[DEVICE_NR(dev)].device; + /* + * If we are in the middle of error recovery, don't let anyone + * else try and use this device. Also, if error recovery fails, it + * may try and take the device offline, in which case all further + * access to the device is prohibited. + */ + + if( !scsi_block_when_processing_errors(SDev) ) + { + return -ENODEV; + } - case BLKROSET: - case BLKROGET: - case BLKRASET: - case BLKRAGET: - case BLKFLSBUF: - case BLKSSZGET: - case BLKPG: - return blk_ioctl(inode->i_rdev, cmd, arg); - - case BLKRRPART: /* Re-read partition tables */ - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - return revalidate_scsidisk(dev, 1); - - default: - return scsi_ioctl(rscsi_disks[DEVICE_NR(dev)].device , cmd, (void *) arg); - } + switch (cmd) + { + case HDIO_GETGEO: /* Return BIOS disk parameters */ + if(!loc) + return -EINVAL; + + host = rscsi_disks[DEVICE_NR(dev)].device->host; + + /* default to most commonly used values */ + + diskinfo[0] = 0x40; + diskinfo[1] = 0x20; + diskinfo[2] = rscsi_disks[DEVICE_NR(dev)].capacity >> 11; + + /* override with calculated, extended default, or driver values */ + + if(host->hostt->bios_param != NULL) + host->hostt->bios_param(&rscsi_disks[DEVICE_NR(dev)], + dev, + &diskinfo[0]); + else scsicam_bios_param(&rscsi_disks[DEVICE_NR(dev)], + dev, &diskinfo[0]); + + if (put_user(diskinfo[0], &loc->heads) || + put_user(diskinfo[1], &loc->sectors) || + put_user(diskinfo[2], &loc->cylinders) || + put_user(sd[SD_PARTITION(inode->i_rdev)].start_sect, &loc->start)) + return -EFAULT; + return 0; + case BLKGETSIZE: /* Return device size */ + if (!arg) + return -EINVAL; + return put_user(sd[SD_PARTITION(inode->i_rdev)].nr_sects, (long *) arg); + + case BLKROSET: + case BLKROGET: + case BLKRASET: + case BLKRAGET: + case BLKFLSBUF: + case BLKSSZGET: + case BLKPG: + return blk_ioctl(inode->i_rdev, cmd, arg); + + case BLKRRPART: /* Re-read partition tables */ + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + return revalidate_scsidisk(dev, 1); + + default: + return scsi_ioctl(rscsi_disks[DEVICE_NR(dev)].device , cmd, (void *) arg); + } } static void sd_devname(unsigned int disknum, char *buffer) @@ -198,11 +195,11 @@ static void sd_devname(unsigned int disknum, char *buffer) } } -struct Scsi_Device_Template sd_template = -{NULL, "disk", "sd", NULL, TYPE_DISK, - SCSI_DISK0_MAJOR, 0, 0, 0, 1, - sd_detect, sd_init, - sd_finish, sd_attach, sd_detach +struct Scsi_Device_Template sd_template = { + NULL, "disk", "sd", NULL, TYPE_DISK, + SCSI_DISK0_MAJOR, 0, 0, 0, 1, + sd_detect, sd_init, + sd_finish, sd_attach, sd_detach }; static int sd_open(struct inode *inode, struct file *filp) diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c index f2575a211280..3047f9552131 100644 --- a/drivers/scsi/seagate.c +++ b/drivers/scsi/seagate.c @@ -108,12 +108,6 @@ #endif #define DANY( msg... ) DPRINTK( 0xffff, msg ); -static struct proc_dir_entry proc_scsi_seagate = -{ - PROC_SCSI_SEAGATE, 7, "seagate", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - #ifndef IRQ #define IRQ 5 #endif @@ -418,7 +412,7 @@ int __init seagate_st0x_detect (Scsi_Host_Template * tpnt) struct Scsi_Host *instance; int i, j; - tpnt->proc_dir = &proc_scsi_seagate; + tpnt->proc_name = "seagate"; /* * First, we try for the manual override. */ DANY ("Autodetecting ST0x / TMC-8xx\n"); diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c index a7f2310073c6..360ac591dc4a 100644 --- a/drivers/scsi/sgiwd93.c +++ b/drivers/scsi/sgiwd93.c @@ -37,11 +37,6 @@ struct hpc_chunk { unsigned long padding; }; -struct proc_dir_entry proc_scsi_sgiwd93 = { - PROC_SCSI_SGIWD93, 5, "SGIWD93", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - struct Scsi_Host *sgiwd93_host = NULL; /* Wuff wuff, wuff, wd33c93.c, wuff wuff, object oriented, bow wow. */ @@ -272,7 +267,7 @@ int __init sgiwd93_detect(Scsi_Host_Template *HPsUX) if(called) return 0; /* Should bitch on the console about this... */ - HPsUX->proc_dir = &proc_scsi_sgiwd93; + HPsUX->proc_name = "SGIWD93"; sgiwd93_host = scsi_register(HPsUX, sizeof(struct WD33C93_hostdata)); sgiwd93_host->base = (unsigned char *) hregs; diff --git a/drivers/scsi/sgiwd93.h b/drivers/scsi/sgiwd93.h index 9c1d850f42df..11bf09a0e131 100644 --- a/drivers/scsi/sgiwd93.h +++ b/drivers/scsi/sgiwd93.h @@ -25,9 +25,7 @@ int wd33c93_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int wd33c93_abort(Scsi_Cmnd *); int wd33c93_reset(Scsi_Cmnd *, unsigned int); -extern struct proc_dir_entry proc_scsi_sgiwd93; - -#define SGIWD93_SCSI {proc_dir: &proc_scsi_sgiwd93, \ +#define SGIWD93_SCSI {proc_name: "SGIWD93", \ name: "SGI WD93", \ detect: sgiwd93_detect, \ release: sgiwd93_release, \ diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c index 68785fea6282..f17662c293e4 100644 --- a/drivers/scsi/sim710.c +++ b/drivers/scsi/sim710.c @@ -172,12 +172,6 @@ int sim710_debug = 0; #define offsetof(t, m) ((size_t) (&((t *)0)->m)) #endif - -struct proc_dir_entry proc_scsi_sim710 = { - PROC_SCSI_SIM710, 6, "sim710", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - #define STATE_INITIALISED 0 #define STATE_HALTED 1 #define STATE_IDLE 2 @@ -1441,7 +1435,7 @@ sim710_detect(Scsi_Host_Template * tpnt) DEB(DEB_ANY, printk("sim710: hostdata %d bytes, size %d, order %d\n", sizeof(struct sim710_hostdata), size, order)); - tpnt->proc_dir = &proc_scsi_sim710; + tpnt->proc_name = "sim710"; for(indx = 0; indx < no_of_boards; indx++) { host = scsi_register(tpnt, 4); diff --git a/drivers/scsi/sim710.h b/drivers/scsi/sim710.h index 5511ed455777..9d86cea47960 100644 --- a/drivers/scsi/sim710.h +++ b/drivers/scsi/sim710.h @@ -24,9 +24,7 @@ int sim710_release(struct Scsi_Host *); #if defined(HOSTS_C) || defined(MODULE) #include -extern struct proc_dir_entry proc_scsi_sim710; - -#define SIM710_SCSI { proc_dir: &proc_scsi_sim710, \ +#define SIM710_SCSI { proc_name: "sim710", \ name: "Simple 53c710", \ detect: sim710_detect, \ release: sim710_release, \ diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index 76930a9e055d..ba0be94dd36a 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -115,10 +115,6 @@ static int polled_scsi_on = 0; #define AFTER_RESET_DELAY (HZ/2) -static struct proc_dir_entry proc_scsi_sun3_5380 = { - PROC_SCSI_MAC, 13, "Sun3 5380 SCSI", S_IFDIR | S_IRUGO, S_IXUGO, 2 -}; - static volatile unsigned char *sun3_scsi_regp = IOBASE_SUN3_SCSI; /* static volatile unsigned char *sun3_scsi_drq = NULL; @@ -179,7 +175,7 @@ int sun3scsi_detect(Scsi_Host_Template * tpnt) printk("sun3scsi_detect(0x%p)\n",tpnt); - tpnt->proc_dir = &proc_scsi_sun3_5380; + tpnt->proc_name = "Sun3 5380 SCSI"; /* Could you spell "ewww..."? */ /* setup variables */ tpnt->can_queue = diff --git a/drivers/scsi/sun3x_esp.h b/drivers/scsi/sun3x_esp.h index e00cd850d1de..63bbb69d5b24 100644 --- a/drivers/scsi/sun3x_esp.h +++ b/drivers/scsi/sun3x_esp.h @@ -18,12 +18,10 @@ extern int esp_reset(Scsi_Cmnd *, unsigned int); extern int esp_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); -extern struct proc_dir_entry proc_scsi_esp; - #define DMA_PORTS_P (dregs->cond_reg & DMA_INT_ENAB) #define SCSI_SUN3X_ESP { \ - proc_dir: &proc_scsi_esp, \ + proc_name: "esp", \ proc_info: &esp_proc_info, \ name: "Sun ESP 100/100a/200", \ detect: sun3x_esp_detect, \ diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c index 84d5706a95b1..e79f3381c9d7 100644 --- a/drivers/scsi/sym53c416.c +++ b/drivers/scsi/sym53c416.c @@ -170,7 +170,7 @@ #define PIO_MODE 0x80 #define IO_RANGE 0x20 /* 0x00 - 0x1F */ -#define ID "sym53c416" +#define ID "sym53c416" /* Attention: copied to the sym53c416.h */ #define PIO_SIZE 128 /* Size of PIO fifo is 128 bytes */ #define READ_TIMEOUT 150 @@ -237,8 +237,6 @@ static char info[120]; static Scsi_Cmnd *current_command = NULL; -struct proc_dir_entry proc_scsi_sym53c416 = {PROC_SCSI_SYM53C416, 7, ID, S_IFDIR | S_IRUGO | S_IXUGO, 2}; - int fastpio = 1; int probeaddrs[] = {0x200, 0x220, 0x240, 0}; @@ -809,13 +807,11 @@ int sym53c416_bios_param(Disk *disk, kdev_t dev, int *ip) /* Loadable module support */ #ifdef MODULE -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,26) MODULE_AUTHOR("Lieven Willems"); MODULE_PARM(sym53c416, "1-2i"); MODULE_PARM(sym53c416_1, "1-2i"); MODULE_PARM(sym53c416_2, "1-2i"); MODULE_PARM(sym53c416_3, "1-2i"); -#endif Scsi_Host_Template driver_template = SYM53C416; diff --git a/drivers/scsi/sym53c416.h b/drivers/scsi/sym53c416.h index 49abc83cac7a..6c660aa73749 100644 --- a/drivers/scsi/sym53c416.h +++ b/drivers/scsi/sym53c416.h @@ -29,8 +29,6 @@ #define SYM53C416_SCSI_ID 7 -extern struct proc_dir_entry proc_scsi_sym53c416; - extern int sym53c416_detect(Scsi_Host_Template *); extern const char *sym53c416_info(struct Scsi_Host *); extern int sym53c416_command(Scsi_Cmnd *); @@ -40,10 +38,8 @@ extern int sym53c416_reset(Scsi_Cmnd *, unsigned int); extern int sym53c416_bios_param(Disk *, kdev_t, int *); extern void sym53c416_setup(char *str, int *ints); -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,75) - #define SYM53C416 { \ - proc_dir: &proc_scsi_sym53c416, \ + proc_name: "sym53c416", \ name: "Symbios Logic 53c416", \ detect: sym53c416_detect, \ info: sym53c416_info, \ @@ -59,33 +55,4 @@ extern void sym53c416_setup(char *str, int *ints); unchecked_isa_dma: 1, \ use_clustering: ENABLE_CLUSTERING \ } - -#else - -#define SYM53C416 { \ - NULL, \ - NULL, \ - &proc_scsi_sym53c416, \ - NULL, \ - "Symbios Logic 53c416", \ - sym53c416_detect, \ - NULL, \ - sym53c416_info, \ - sym53c416_command, \ - sym53c416_queuecommand, \ - sym53c416_abort, \ - sym53c416_reset, \ - NULL, \ - sym53c416_bios_param, \ - 1, \ - SYM53C416_SCSI_ID, \ - 32, /* ???? */ \ - 1, \ - 0, \ - 1, \ - ENABLE_CLUSTERING \ - } - -#endif - #endif diff --git a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c index 83776573c1ef..d1443aeedd78 100644 --- a/drivers/scsi/sym53c8xx.c +++ b/drivers/scsi/sym53c8xx.c @@ -635,9 +635,9 @@ struct m_link { #endif #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,0) -#define get_pages(order) __get_free_pages(GFP_ATOMIC | GFP_DMA_32BIT, order) +#define sym53c8xx_get_pages(order) __get_free_pages(GFP_ATOMIC | GFP_DMA_32BIT, order) #else -#define get_pages(order) __get_free_pages(GFP_ATOMIC | GFP_DMA_32BIT, order, 0) +#define sym53c8xx_get_pages(order) __get_free_pages(GFP_ATOMIC | GFP_DMA_32BIT, order, 0) #endif /* @@ -668,7 +668,7 @@ static void *__m_alloc(int size) j = i; while (!h[j].next) { if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) { - h[j].next = (struct m_link *)get_pages(MEMO_PAGE_ORDER); + h[j].next = (struct m_link *)sym53c8xx_get_pages(MEMO_PAGE_ORDER); if (h[j].next) h[j].next->next = 0; break; @@ -828,10 +828,6 @@ static struct Scsi_Host *first_host = NULL; ** /proc directory entry and proc_info function */ -static struct proc_dir_entry proc_scsi_sym53c8xx = { - PROC_SCSI_SYM53C8XX, 9, NAME53C8XX, - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; #ifdef SCSI_NCR_PROC_INFO_SUPPORT static int sym53c8xx_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int func); @@ -11382,7 +11378,7 @@ int __init sym53c8xx_detect(Scsi_Host_Template *tpnt) ** Initialize driver general stuff. */ #ifdef SCSI_NCR_PROC_INFO_SUPPORT - tpnt->proc_dir = &proc_scsi_sym53c8xx; + tpnt->proc_name = NAME53C8XX; tpnt->proc_info = sym53c8xx_proc_info; #endif diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index 2fdf0c3cd781..2a71173e3205 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -121,12 +121,6 @@ #include #include -struct proc_dir_entry proc_scsi_t128 = { - PROC_SCSI_T128, 4, "t128", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - - static struct override { unsigned char *address; int irq; @@ -205,7 +199,7 @@ int __init t128_detect(Scsi_Host_Template * tpnt){ unsigned char *base; int sig, count; - tpnt->proc_dir = &proc_scsi_t128; + tpnt->proc_name = "t128"; tpnt->proc_info = &t128_proc_info; for (count = 0; current_override < NO_OVERRIDES; ++current_override) { diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index 1e153e40d046..9bc1c575bfeb 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c @@ -482,12 +482,6 @@ static char* dc390_adapname = "DC390"; UCHAR dc390_eepromBuf[MAX_ADAPTER_NUM][EE_LEN]; UCHAR dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20}; -struct proc_dir_entry DC390_proc_scsi_tmscsim ={ - PROC_SCSI_DC390T, 7 ,"tmscsim", - S_IFDIR | S_IRUGO | S_IXUGO, 2 - }; - - /*********************************************************************** * Functions for access to DC390 EEPROM * and some to emulate it @@ -2024,7 +2018,7 @@ int __init DC390_detect (Scsi_Host_Template *psht) printk (KERN_ERR "DC390: No PCI BIOS found!\n"); if (dc390_adapterCnt) - psht->proc_dir = &DC390_proc_scsi_tmscsim; + psht->proc_name = "tmscsim"; printk(KERN_INFO "DC390: %i adapters found\n", dc390_adapterCnt); DC390_UNLOCK_DRV; diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c index 4912846c0527..e65bbccaaad5 100644 --- a/drivers/scsi/u14-34f.c +++ b/drivers/scsi/u14-34f.c @@ -374,11 +374,6 @@ MODULE_AUTHOR("Dario Ballabio"); #define SPIN_UNLOCK_RESTORE \ spin_unlock_irqrestore(&io_request_lock, spin_flags); -struct proc_dir_entry proc_scsi_u14_34f = { - PROC_SCSI_U14_34F, 6, "u14_34f", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - /* Values for the PRODUCT_ID ports for the 14/34F */ #define PRODUCT_ID1 0x56 #define PRODUCT_ID2 0x40 /* NOTE: Only upper nibble is used */ @@ -955,7 +950,7 @@ int u14_34f_detect(Scsi_Host_Template *tpnt) { unsigned int j = 0, k; - tpnt->proc_dir = &proc_scsi_u14_34f; + tpnt->proc_name = "u14-34f"; if(boot_options) option_setup(boot_options); diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c index 1c97ad4fe32c..620b24748cd2 100644 --- a/drivers/scsi/ultrastor.c +++ b/drivers/scsi/ultrastor.c @@ -148,11 +148,6 @@ #include "sd.h" #include -struct proc_dir_entry proc_scsi_ultrastor = { - PROC_SCSI_ULTRASTOR, 9, "ultrastor", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; - #define FALSE 0 #define TRUE 1 @@ -631,7 +626,7 @@ static int ultrastor_24f_detect(Scsi_Host_Template * tpnt) int ultrastor_detect(Scsi_Host_Template * tpnt) { - tpnt->proc_dir = &proc_scsi_ultrastor; + tpnt->proc_name = "ultrastor"; return ultrastor_14f_detect(tpnt) || ultrastor_24f_detect(tpnt); } diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c index 14515a0186dc..dd1a9116b772 100644 --- a/drivers/scsi/wd7000.c +++ b/drivers/scsi/wd7000.c @@ -171,17 +171,6 @@ #include "wd7000.h" #include - -struct proc_dir_entry proc_scsi_wd7000 = -{ - PROC_SCSI_7000FASST, - 6, - "wd7000", - S_IFDIR | S_IRUGO | S_IXUGO, - 2 -}; - - /* * Mailbox structure sizes. * I prefer to keep the number of ICMBs much larger than the number of @@ -1542,7 +1531,7 @@ int wd7000_detect (Scsi_Host_Template *tpnt) for (i = 0; i < IRQS; wd7000_host[i++] = NULL) ; for (i = 0; i < NUM_CONFIGS; biosptr[i++] = -1) ; - tpnt->proc_dir = &proc_scsi_wd7000; + tpnt->proc_name = "wd7000"; tpnt->proc_info = &wd7000_proc_info; /* diff --git a/drivers/scsi/wd7000.h b/drivers/scsi/wd7000.h index 73679c24a4da..d941fdf2ce28 100644 --- a/drivers/scsi/wd7000.h +++ b/drivers/scsi/wd7000.h @@ -14,9 +14,6 @@ #include #include -extern struct proc_dir_entry proc_scsi_wd7000; - - int wd7000_set_info (char *buffer, int length, struct Scsi_Host *host); int wd7000_proc_info (char *buffer, char **start, off_t offset, int length, int hostno, int inout); int wd7000_detect (Scsi_Host_Template *); @@ -45,7 +42,7 @@ int wd7000_biosparam (Disk *, kdev_t, int *); #define WD7000_SG 16 #define WD7000 { \ - proc_dir: &proc_scsi_wd7000, \ + proc_name: "wd7000", \ proc_info: wd7000_proc_info, \ name: "Western Digital WD-7000", \ detect: wd7000_detect, \ diff --git a/drivers/sound/sb_card.c b/drivers/sound/sb_card.c index a21da2d69528..d0a08c0b2b03 100644 --- a/drivers/sound/sb_card.c +++ b/drivers/sound/sb_card.c @@ -16,6 +16,8 @@ #include #endif #include +#include +#include #include "sound_config.h" #include "soundmodule.h" @@ -138,6 +140,7 @@ int pas2 = 0; /* Set pas2=1 to load this as support for pas2 */ int support = 0; /* Set support to load this as a support module */ int sm_games = 0; /* Mixer - see sb_mixer.c */ int acer = 0; /* Do acer notebook init */ +int isapnp = 0; MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); @@ -151,24 +154,91 @@ MODULE_PARM(trix, "i"); MODULE_PARM(pas2, "i"); MODULE_PARM(sm_games, "i"); MODULE_PARM(esstype, "i"); +MODULE_PARM(isapnp, "i"); void *smw_free = NULL; +static struct { unsigned short vendor, function; char *name; } +isapnp_sb_list[] __initdata = { + {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), "Sound Blaster 16" }, + {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), "Sound Blaster 16" }, + {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), "Sound Blaster 16" }, + {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), "Sound Blaster 16" }, + {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043), "Sound Blaster 16" }, + {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), "Sound Blaster 16" }, + {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), "Sound Blaster 16" }, + {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868), "ESS 1868" }, + {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611), "ESS 1868" }, + {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), "ESS 1869" }, + {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878), "ESS 1878" }, + {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879), "ESS 1879" }, + {0,} +}; + + +static int __init sb_probe_isapnp(struct address_info *hw_config, struct address_info *mpu_config) { + int i; + + for (i = 0; isapnp_sb_list[i].vendor != 0; i++) { + struct pci_dev *idev = NULL; + + while ((idev = isapnp_find_dev(NULL, + isapnp_sb_list[i].vendor, + isapnp_sb_list[i].function, + idev))) { + idev->prepare(idev); + idev->activate(idev); + if (!idev->resource[0].start || check_region(idev->resource[0].start,16)) + continue; + hw_config->io_base = idev->resource[0].start; + hw_config->irq = idev->irq_resource[0].start; + hw_config->dma = idev->dma_resource[0].start; + hw_config->dma2 = idev->dma_resource[1].start; +#ifdef CONFIG_MIDI + if (isapnp_sb_list[i].vendor == ISAPNP_VENDOR('E','S','S')) + mpu_config->io_base = idev->resource[2].start; + else + mpu_config->io_base = idev->resource[1].start; +#endif + break; + } + if (!idev) + continue; + printk(KERN_INFO "ISAPnP reports %s at i/o %#x, irq %d, dma %d, %d\n", + isapnp_sb_list[i].name, + hw_config->io_base, hw_config->irq, hw_config->dma, + hw_config->dma2); + return 0; + } + return -ENODEV; +} + int init_module(void) { printk(KERN_INFO "Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996\n"); if (mad16 == 0 && trix == 0 && pas2 == 0 && support == 0) { - if (io == -1 || dma == -1 || irq == -1) + if (isapnp == 1) + { + if (sb_probe_isapnp(&config, &config_mpu)<0) + { + printk(KERN_ERR "sb_card: No ISAPnP cards found\n"); + return -EINVAL; + } + } + else { - printk(KERN_ERR "sb_card: I/O, IRQ, and DMA are mandatory\n"); - return -EINVAL; + if (io == -1 || dma == -1 || irq == -1) + { + printk(KERN_ERR "sb_card: I/O, IRQ, and DMA are mandatory\n"); + return -EINVAL; + } + config.io_base = io; + config.irq = irq; + config.dma = dma; + config.dma2 = dma16; } - config.io_base = io; - config.irq = irq; - config.dma = dma; - config.dma2 = dma16; config.card_subtype = type; if (!probe_sb(&config)) @@ -178,7 +248,8 @@ int init_module(void) if(config.slots[0]==-1) return -ENODEV; #ifdef CONFIG_MIDI - config_mpu.io_base = mpu_io; + if (isapnp == 0) + config_mpu.io_base = mpu_io; if (probe_sbmpu(&config_mpu)) sbmpu = 1; if (sbmpu) diff --git a/drivers/usb/proc_usb.c b/drivers/usb/proc_usb.c index 628f19555174..e11c528259a7 100644 --- a/drivers/usb/proc_usb.c +++ b/drivers/usb/proc_usb.c @@ -119,6 +119,7 @@ struct class_info clas_info [] = {USB_CLASS_HUB, "hub"}, {USB_CLASS_PRINTER, "print"}, {USB_CLASS_MASS_STORAGE, "stor."}, + {USB_CLASS_DATA, "data"}, {USB_CLASS_VENDOR_SPEC, "vend."}, {-1, "unk."} /* leave as last */ }; diff --git a/drivers/usb/usb_scsi.c b/drivers/usb/usb_scsi.c index 52a6b74ffbfe..94c0784f5c53 100644 --- a/drivers/usb/usb_scsi.c +++ b/drivers/usb/usb_scsi.c @@ -108,7 +108,7 @@ struct us_data { static struct proc_dir_entry proc_usb_scsi = { - PROC_SCSI_USB_SCSI, + PROC_SCSI_USB_SCSI, /* It's currently b0rken */ 0, NULL, S_IFDIR | S_IRUGO | S_IXUGO, diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 6143bd5d0f83..358890dbd194 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -471,24 +471,6 @@ static int entry_proc_setup(struct binfmt_entry *e) return 0; } -#ifdef MODULE -/* - * This is called as the fill_inode function when an inode - * is going into (fill = 1) or out of service (fill = 0). - * We use it here to manage the module use counts. - * - * Note: only the top-level directory needs to do this; if - * a lower level is referenced, the parent will be as well. - */ -static void bm_modcount(struct inode *inode, int fill) -{ - if (fill) - MOD_INC_USE_COUNT; - else - MOD_DEC_USE_COUNT; -} -#endif - static int __init init_misc_binfmt(void) { int error = -ENOENT; @@ -497,9 +479,7 @@ static int __init init_misc_binfmt(void) bm_dir = create_proc_entry("sys/fs/binfmt_misc", S_IFDIR, NULL); if (!bm_dir) goto out; -#ifdef MODULE - bm_dir->fill_inode = bm_modcount; -#endif + bm_dir->owner = THIS_MODULE; status = create_proc_entry("status", S_IFREG | S_IRUGO | S_IWUSR, bm_dir); diff --git a/fs/buffer.c b/fs/buffer.c index befe7bcecab3..0b1fd9c6198f 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -91,7 +91,7 @@ struct bh_free_head { }; static struct bh_free_head free_list[NR_SIZES]; -static kmem_cache_t *bh_cachep; +kmem_cache_t *bh_cachep; static int grow_buffers(int size); @@ -130,8 +130,6 @@ union bdflush_param { int bdflush_min[N_PARAM] = { 0, 10, 5, 25, 0, 1*HZ, 1*HZ, 1, 1}; int bdflush_max[N_PARAM] = {100,50000, 20000, 20000,600*HZ, 6000*HZ, 6000*HZ, 2047, 5}; -void wakeup_bdflush(int); - /* * Rewrote the wait-routines to use the "new" wait-queue functionality, * and getting rid of the cli-sti pairs. The wait-queue routines still @@ -707,7 +705,7 @@ static void end_buffer_io_async(struct buffer_head * bh, int uptodate) mark_buffer_uptodate(bh, uptodate); /* This is a temporary buffer used for page I/O. */ - page = mem_map + MAP_NR(bh->b_data); + page = bh->b_page; if (!uptodate) SetPageError(page); @@ -760,7 +758,6 @@ still_busy: return; } - /* * Ok, this is getblk, and it isn't very clear, again to hinder * race-conditions. Most of the code is seldom used, (ie repeating), @@ -1092,6 +1089,20 @@ static struct buffer_head * get_unused_buffer_head(int async) return NULL; } +void set_bh_page (struct buffer_head *bh, struct page *page, unsigned int offset) +{ + bh->b_page = page; + if (offset >= PAGE_SIZE) + BUG(); + if (PageHighMem(page)) + /* + * This catches illegal uses and preserves the offset: + */ + bh->b_data = (char *)(0 + offset); + else + bh->b_data = (char *)(page_address(page) + offset); +} + /* * Create the appropriate buffers when given a page for data area and * the size of each buffer.. Use the bh->b_this_page linked list to @@ -1101,7 +1112,7 @@ static struct buffer_head * get_unused_buffer_head(int async) * from ordinary buffer allocations, and only async requests are allowed * to sleep waiting for buffer heads. */ -static struct buffer_head * create_buffers(unsigned long page, unsigned long size, int async) +static struct buffer_head * create_buffers(struct page * page, unsigned long size, int async) { struct buffer_head *bh, *head; long offset; @@ -1124,7 +1135,8 @@ try_again: atomic_set(&bh->b_count, 0); bh->b_size = size; - bh->b_data = (char *) (page+offset); + set_bh_page(bh, page, offset); + bh->b_list = BUF_CLEAN; bh->b_end_io = end_buffer_io_bad; } @@ -1183,7 +1195,7 @@ static int create_page_buffers(int rw, struct page *page, kdev_t dev, int b[], i * They don't show up in the buffer hash table, but they *are* * registered in page->buffers. */ - head = create_buffers(page_address(page), size, 1); + head = create_buffers(page, size, 1); if (page->buffers) BUG(); if (!head) @@ -1273,7 +1285,7 @@ static void create_empty_buffers(struct page *page, struct inode *inode, unsigne { struct buffer_head *bh, *head, *tail; - head = create_buffers(page_address(page), blocksize, 1); + head = create_buffers(page, blocksize, 1); if (page->buffers) BUG(); @@ -1377,10 +1389,11 @@ int block_write_partial_page(struct file *file, struct page *page, unsigned long unsigned long start_offset, start_bytes, end_bytes; unsigned long bbits, blocks, i, len; struct buffer_head *bh, *head; - char * target_buf; + char *target_buf, *kaddr; int need_balance_dirty; - target_buf = (char *)page_address(page) + offset; + kaddr = (char *)kmap(page); + target_buf = kaddr + offset; if (!PageLocked(page)) BUG(); @@ -1445,7 +1458,7 @@ int block_write_partial_page(struct file *file, struct page *page, unsigned long if (!buffer_uptodate(bh) && (start_offset || (end_bytes && (i == end_block)))) { if (buffer_new(bh)) { - memset(bh->b_data, 0, bh->b_size); + memset(kaddr + i*blocksize, 0, blocksize); } else { ll_rw_block(READ, 1, &bh); wait_on_buffer(bh); @@ -1463,6 +1476,10 @@ int block_write_partial_page(struct file *file, struct page *page, unsigned long len = end_bytes; end_bytes = 0; } + if (target_buf >= kaddr + PAGE_SIZE) + BUG(); + if (target_buf+len-1 >= kaddr + PAGE_SIZE) + BUG(); err = copy_from_user(target_buf, buf, len); target_buf += len; buf += len; @@ -1511,9 +1528,11 @@ skip: */ if (!partial) SetPageUptodate(page); + kunmap(page); return bytes; out: ClearPageUptodate(page); + kunmap(page); return err; } @@ -1714,8 +1733,6 @@ static void end_buffer_io_kiobuf(struct buffer_head *bh, int uptodate) * for them to complete. Clean up the buffer_heads afterwards. */ -#define dprintk(x...) - static int do_kio(struct kiobuf *kiobuf, int rw, int nr, struct buffer_head *bh[], int size) { @@ -1726,8 +1743,6 @@ static int do_kio(struct kiobuf *kiobuf, struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); - dprintk ("do_kio start %d\n", rw); - if (rw == WRITE) rw = WRITERAW; atomic_add(nr, &kiobuf->io_count); @@ -1753,8 +1768,6 @@ static int do_kio(struct kiobuf *kiobuf, spin_unlock(&unused_list_lock); - dprintk ("do_kio end %d %d\n", iosize, err); - if (iosize) return iosize; if (kiobuf->errno) @@ -1808,12 +1821,6 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[], panic("brw_kiovec: iobuf not initialised"); } - /* DEBUG */ -#if 0 - return iobuf->length; -#endif - dprintk ("brw_kiovec: start\n"); - /* * OK to walk down the iovec doing page IO on each page we find. */ @@ -1822,7 +1829,6 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[], iobuf = iovec[i]; offset = iobuf->offset; length = iobuf->length; - dprintk ("iobuf %d %d %d\n", offset, length, size); for (pageind = 0; pageind < iobuf->nr_pages; pageind++) { map = iobuf->maplist[pageind]; @@ -1842,7 +1848,7 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[], tmp->b_dev = B_FREE; tmp->b_size = size; - tmp->b_data = (char *) (page + offset); + set_bh_page(tmp, map, offset); tmp->b_this_page = tmp; init_buffer(tmp, end_buffer_io_kiobuf, NULL); @@ -1856,8 +1862,6 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[], set_bit(BH_Dirty, &tmp->b_state); } - dprintk ("buffer %d (%d) at %p\n", - bhind, tmp->b_blocknr, tmp->b_data); bh[bhind++] = tmp; length -= size; offset += size; @@ -1892,7 +1896,6 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[], } finished: - dprintk ("brw_kiovec: end (%d, %d)\n", transferred, err); if (transferred) return transferred; return err; @@ -2002,7 +2005,8 @@ int block_read_full_page(struct file * file, struct page * page) unsigned long iblock; struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE]; unsigned int blocksize, blocks; - int nr; + unsigned long kaddr = 0; + int nr, i; if (!PageLocked(page)) PAGE_BUG(page); @@ -2015,6 +2019,7 @@ int block_read_full_page(struct file * file, struct page * page) iblock = page->index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); bh = head; nr = 0; + i = 0; do { if (buffer_uptodate(bh)) @@ -2023,7 +2028,9 @@ int block_read_full_page(struct file * file, struct page * page) if (!buffer_mapped(bh)) { inode->i_op->get_block(inode, iblock, bh, 0); if (!buffer_mapped(bh)) { - memset(bh->b_data, 0, blocksize); + if (!kaddr) + kaddr = kmap(page); + memset((char *)(kaddr + i*blocksize), 0, blocksize); set_bit(BH_Uptodate, &bh->b_state); continue; } @@ -2033,7 +2040,7 @@ int block_read_full_page(struct file * file, struct page * page) atomic_inc(&bh->b_count); arr[nr] = bh; nr++; - } while (iblock++, (bh = bh->b_this_page) != head); + } while (i++, iblock++, (bh = bh->b_this_page) != head); ++current->maj_flt; if (nr) { @@ -2048,6 +2055,8 @@ int block_read_full_page(struct file * file, struct page * page) SetPageUptodate(page); UnlockPage(page); } + if (kaddr) + kunmap(page); return 0; } @@ -2057,8 +2066,7 @@ int block_read_full_page(struct file * file, struct page * page) */ static int grow_buffers(int size) { - unsigned long page; - struct page * page_map; + struct page * page; struct buffer_head *bh, *tmp; struct buffer_head * insert_point; int isize; @@ -2068,8 +2076,9 @@ static int grow_buffers(int size) return 0; } - if (!(page = __get_free_page(GFP_BUFFER))) - return 0; + page = alloc_page(GFP_BUFFER); + if (!page) + goto out; bh = create_buffers(page, size, 0); if (!bh) goto no_buffer_head; @@ -2099,14 +2108,14 @@ static int grow_buffers(int size) free_list[isize].list = bh; spin_unlock(&free_list[isize].lock); - page_map = mem_map + MAP_NR(page); - page_map->buffers = bh; - lru_cache_add(page_map); + page->buffers = bh; + lru_cache_add(page); atomic_inc(&buffermem_pages); return 1; no_buffer_head: - free_page(page); + __free_page(page); +out: return 0; } diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c index 008088036ab7..42b0fafca582 100644 --- a/fs/coda/sysctl.c +++ b/fs/coda/sysctl.c @@ -478,15 +478,6 @@ int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset, struct proc_dir_entry* proc_fs_coda; -static void coda_proc_modcount(struct inode *inode, int fill) -{ - if (fill) - MOD_INC_USE_COUNT; - else - MOD_DEC_USE_COUNT; - -} - #endif #define coda_proc_create(name,get_info) \ @@ -502,7 +493,7 @@ void coda_sysctl_init() #ifdef CONFIG_PROC_FS proc_fs_coda = create_proc_entry("coda", S_IFDIR, proc_root_fs); - proc_fs_coda->fill_inode = &coda_proc_modcount; + proc_fs_coda->owner = THIS_MODULE; coda_proc_create("vfs_stats", coda_vfs_stats_get_info); coda_proc_create("upcall_stats", coda_upcall_stats_get_info); coda_proc_create("permission_stats", coda_permission_stats_get_info); diff --git a/fs/exec.c b/fs/exec.c index 8dda57102ac4..a7ca3dfaa762 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -225,19 +225,13 @@ int copy_strings(int argc,char ** argv, struct linux_binprm *bprm) page = bprm->page[i]; new = 0; if (!page) { - unsigned long pageaddr; - /* - * Cannot yet use highmem page because - * we cannot sleep with a kmap held. - */ - pageaddr = __get_free_page(GFP_USER); - if (!pageaddr) - return -ENOMEM; - page = mem_map + MAP_NR(pageaddr); + page = alloc_page(GFP_HIGHUSER); bprm->page[i] = page; + if (!page) + return -ENOMEM; new = 1; } - kaddr = (char *)kmap(page, KM_WRITE); + kaddr = (char *)kmap(page); if (new && offset) memset(kaddr, 0, offset); @@ -249,7 +243,7 @@ int copy_strings(int argc,char ** argv, struct linux_binprm *bprm) } err = copy_from_user(kaddr + offset, str, bytes_to_copy); flush_page_to_ram(page); - kunmap((unsigned long)kaddr, KM_WRITE); + kunmap(page); if (err) return -EFAULT; @@ -686,12 +680,12 @@ void remove_arg_zero(struct linux_binprm *bprm) if (offset != PAGE_SIZE) continue; offset = 0; - kunmap((unsigned long)kaddr, KM_WRITE); + kunmap(page); inside: page = bprm->page[bprm->p/PAGE_SIZE]; - kaddr = (char *)kmap(page, KM_WRITE); + kaddr = (char *)kmap(page); } - kunmap((unsigned long)kaddr, KM_WRITE); + kunmap(page); bprm->argc--; } } diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c index b4ff17851b4f..036e92e9378a 100644 --- a/fs/ncpfs/mmap.c +++ b/fs/ncpfs/mmap.c @@ -43,7 +43,7 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area, int bufsize; int pos; - page = __get_pages(GFP_KERNEL, 0); + page = alloc_page(GFP_KERNEL); if (!page) return page; pg_addr = page_address(page); diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 3cfdd631904e..8c575db4ea5d 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -256,21 +256,6 @@ MODULE_AUTHOR("Olaf Kirch "); extern int (*do_nfsservctl)(int, void *, void *); -/* - * This is called as the fill_inode function when an inode - * is going into (fill = 1) or out of service (fill = 0). - * - * We use it here to make sure the module can't be unloaded - * while a /proc inode is in use. - */ -void nfsd_modcount(struct inode *inode, int fill) -{ - if (fill) - MOD_INC_USE_COUNT; - else - MOD_DEC_USE_COUNT; -} - /* * Initialize the module */ diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c index accd0aadc3df..7e7eba9a9d9d 100644 --- a/fs/nfsd/stats.c +++ b/fs/nfsd/stats.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -77,9 +78,7 @@ nfsd_stat_init(void) if ((ent = svc_proc_register(&nfsd_svcstats)) != 0) { ent->read_proc = nfsd_proc_read; -#ifdef MODULE - ent->fill_inode = nfsd_modcount; -#endif + ent->owner = THIS_MODULE; } } diff --git a/fs/proc/inode-alloc.txt b/fs/proc/inode-alloc.txt index 748b2d3332ed..4af79966c465 100644 --- a/fs/proc/inode-alloc.txt +++ b/fs/proc/inode-alloc.txt @@ -3,17 +3,12 @@ Current inode allocations in the proc-fs (hex-numbers): 00000000 reserved 00000001-00000fff static entries (goners) 001 root-ino - 100 scsi/* - ... - fff end 00001000-00001fff dynamic entries 00002000-00002fff openprom entries 0001xxxx-7fffxxxx pid-dir entries for pid 1-7fff 80000000-ffffffff unused -Goals: - a) the only static inumber that will stay is root's. - b) scsi should go dynamic. - c) once we'll split the thing into several virtual filesystems we +Goal: + a) once we'll split the thing into several virtual filesystems we will get rid of magical ranges (and this file, BTW). diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 205f83fc45cb..8842cc253513 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -77,11 +78,8 @@ static void proc_delete_inode(struct inode *inode) return; if (de) { - /* - * Call the fill_inode hook to release module counts. - */ - if (de->fill_inode) - de->fill_inode(inode, 0); + if (de->owner) + __MOD_DEC_USE_COUNT(de->owner); de_put(de); } } @@ -178,12 +176,8 @@ printk("proc_iget: using deleted entry %s, count=%d\n", de->name, de->count); inode->i_op = de->ops; if (de->nlink) inode->i_nlink = de->nlink; - /* - * The fill_inode routine should use this call - * to increment module counts, if necessary. - */ - if (de->fill_inode) - de->fill_inode(inode, 1); + if (de->owner) + __MOD_INC_USE_COUNT(de->owner); } /* * Fixup the root inode's nlink value diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index c006ee6bca66..ec2a92db3796 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c @@ -5,7 +5,7 @@ * Jeremy Fitzhardinge * Implemented by David Howells * Modified and incorporated into 2.3.x by Tigran Aivazian - * Support to dump module's data structures (ELF only), Tigran Aivazian + * Support to dump vmalloc'd data structures (ELF only), Tigran Aivazian */ #include @@ -15,13 +15,35 @@ #include #include #include -#include -#include - +#include +#include #include + +static int open_kcore(struct inode * inode, struct file * filp) +{ + return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; +} + +static ssize_t read_kcore(struct file *, char *, size_t, loff_t *); + +static struct file_operations proc_kcore_operations = { + NULL, /* lseek */ + read_kcore, + NULL, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + NULL, /* ioctl */ + NULL, /* mmap */ + open_kcore +}; + +struct inode_operations proc_kcore_inode_operations = { + &proc_kcore_operations, +}; + #ifdef CONFIG_KCORE_AOUT -ssize_t read_kcore(struct file * file, char * buf, +static ssize_t read_kcore(struct file * file, char * buf, size_t count, loff_t *ppos) { unsigned long long p = *ppos, memsize; @@ -81,8 +103,7 @@ ssize_t read_kcore(struct file * file, char * buf, *ppos += read; return read; } -#else - +#else /* CONFIG_KCORE_AOUT */ #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) @@ -97,6 +118,31 @@ struct memelfnote extern char saved_command_line[]; +static size_t get_kcore_size(int *num_vma, int *elf_buflen) +{ + size_t try, size = 0; + struct vm_struct *m; + + *num_vma = 0; + if (!vmlist) { + *elf_buflen = PAGE_SIZE; + return ((size_t)high_memory - PAGE_OFFSET + PAGE_SIZE); + } + + for (m=vmlist; m; m=m->next) { + try = (size_t)m->addr + m->size; + if (try > size) + size = try; + *num_vma = *num_vma + 1; + } + *elf_buflen = sizeof(struct elfhdr) + + (*num_vma + 2)*sizeof(struct elf_phdr) + + 3 * sizeof(struct memelfnote); + *elf_buflen = PAGE_ALIGN(*elf_buflen); + return (size - PAGE_OFFSET + *elf_buflen); +} + + /*****************************************************************************/ /* * determine size of ELF note @@ -139,32 +185,29 @@ static char *storenote(struct memelfnote *men, char *bufp) return bufp; } /* end storenote() */ -/*****************************************************************************/ /* * store an ELF coredump header in the supplied buffer - * - assume the memory image is the size specified + * num_vma is the number of elements in vmlist */ -static void elf_kcore_store_hdr(char *bufp) +static void elf_kcore_store_hdr(char *bufp, int num_vma, int elf_buflen) { struct elf_prstatus prstatus; /* NT_PRSTATUS */ - struct elf_prpsinfo psinfo; /* NT_PRPSINFO */ - struct elf_phdr *nhdr, *dhdr; + struct elf_prpsinfo prpsinfo; /* NT_PRPSINFO */ + struct elf_phdr *nhdr, *phdr; struct elfhdr *elf; struct memelfnote notes[3]; off_t offset = 0; + struct vm_struct *m; - /* acquire an ELF header block from the buffer */ + /* setup ELF header */ elf = (struct elfhdr *) bufp; bufp += sizeof(struct elfhdr); offset += sizeof(struct elfhdr); - - /* set up header */ - memcpy(elf->e_ident,ELFMAG,SELFMAG); + memcpy(elf->e_ident, ELFMAG, SELFMAG); elf->e_ident[EI_CLASS] = ELF_CLASS; elf->e_ident[EI_DATA] = ELF_DATA; elf->e_ident[EI_VERSION]= EV_CURRENT; memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); - elf->e_type = ET_CORE; elf->e_machine = ELF_ARCH; elf->e_version = EV_CURRENT; @@ -174,17 +217,15 @@ static void elf_kcore_store_hdr(char *bufp) elf->e_flags = 0; elf->e_ehsize = sizeof(struct elfhdr); elf->e_phentsize= sizeof(struct elf_phdr); - elf->e_phnum = 1; /* no. of segments = 1 + Nmodules */ + elf->e_phnum = 2 + num_vma; elf->e_shentsize= 0; elf->e_shnum = 0; elf->e_shstrndx = 0; - /* acquire an ELF program header blocks from the buffer for notes */ + /* setup ELF PT_NOTE program header */ nhdr = (struct elf_phdr *) bufp; bufp += sizeof(struct elf_phdr); offset += sizeof(struct elf_phdr); - - /* store program headers for notes dump */ nhdr->p_type = PT_NOTE; nhdr->p_offset = 0; nhdr->p_vaddr = 0; @@ -194,43 +235,31 @@ static void elf_kcore_store_hdr(char *bufp) nhdr->p_flags = 0; nhdr->p_align = 0; - /* acquire an ELF program header blocks from the buffer for data */ - dhdr = (struct elf_phdr *) bufp; + /* setup ELF PT_LOAD program header */ + phdr = (struct elf_phdr *) bufp; bufp += sizeof(struct elf_phdr); offset += sizeof(struct elf_phdr); - - /* store program headers for data dump */ - dhdr->p_type = PT_LOAD; - dhdr->p_flags = PF_R|PF_W|PF_X; - dhdr->p_offset = PAGE_SIZE; - dhdr->p_vaddr = PAGE_OFFSET; - dhdr->p_paddr = __pa(PAGE_OFFSET); - dhdr->p_filesz = ((unsigned long)high_memory - PAGE_OFFSET + PAGE_SIZE); - dhdr->p_memsz = ((unsigned long)high_memory - PAGE_OFFSET + PAGE_SIZE); - dhdr->p_align = PAGE_SIZE; - -#ifdef CONFIG_MODULES - { - struct module *m; - lock_kernel(); - for (m=module_list; m; m=m->next) { - dhdr = (struct elf_phdr *) bufp; - bufp += sizeof(struct elf_phdr); - offset += sizeof(struct elf_phdr); - - dhdr->p_type = PT_LOAD; - dhdr->p_flags = PF_R|PF_W|PF_X; - dhdr->p_offset = (unsigned long)m - PAGE_OFFSET + PAGE_SIZE; - dhdr->p_vaddr = (unsigned long)m; - dhdr->p_paddr = __pa(m); - dhdr->p_filesz = m->size; - dhdr->p_memsz = m->size; - dhdr->p_align = 0; - elf->e_phnum++; - } - lock_kernel(); + phdr->p_type = PT_LOAD; + phdr->p_flags = PF_R|PF_W|PF_X; + phdr->p_offset = elf_buflen; + phdr->p_vaddr = PAGE_OFFSET; + phdr->p_paddr = __pa(PAGE_OFFSET); + phdr->p_filesz = phdr->p_memsz = ((unsigned long)high_memory - PAGE_OFFSET); + phdr->p_align = PAGE_SIZE; + + for (m=vmlist; m; m=m->next) { + phdr = (struct elf_phdr *) bufp; + bufp += sizeof(struct elf_phdr); + offset += sizeof(struct elf_phdr); + + phdr->p_type = PT_LOAD; + phdr->p_flags = PF_R|PF_W|PF_X; + phdr->p_offset = (size_t)m->addr - PAGE_OFFSET + elf_buflen; + phdr->p_vaddr = (size_t)m->addr; + phdr->p_paddr = __pa(m); + phdr->p_filesz = phdr->p_memsz = m->size; + phdr->p_align = PAGE_SIZE; } -#endif /* * Set up the notes in similar form to SVR4 core dumps made @@ -241,39 +270,39 @@ static void elf_kcore_store_hdr(char *bufp) /* set up the process status */ notes[0].name = "CORE"; notes[0].type = NT_PRSTATUS; - notes[0].datasz = sizeof(prstatus); + notes[0].datasz = sizeof(struct elf_prstatus); notes[0].data = &prstatus; - memset(&prstatus,0,sizeof(prstatus)); + memset(&prstatus, 0, sizeof(struct elf_prstatus)); nhdr->p_filesz = notesize(¬es[0]); - bufp = storenote(¬es[0],bufp); + bufp = storenote(¬es[0], bufp); /* set up the process info */ notes[1].name = "CORE"; notes[1].type = NT_PRPSINFO; - notes[1].datasz = sizeof(psinfo); - notes[1].data = &psinfo; + notes[1].datasz = sizeof(struct elf_prpsinfo); + notes[1].data = &prpsinfo; - memset(&psinfo,0,sizeof(psinfo)); - psinfo.pr_state = 0; - psinfo.pr_sname = 'R'; - psinfo.pr_zomb = 0; + memset(&prpsinfo, 0, sizeof(struct elf_prpsinfo)); + prpsinfo.pr_state = 0; + prpsinfo.pr_sname = 'R'; + prpsinfo.pr_zomb = 0; - strcpy(psinfo.pr_fname,"vmlinux"); - strncpy(psinfo.pr_psargs,saved_command_line,ELF_PRARGSZ); + strcpy(prpsinfo.pr_fname, "vmlinux"); + strncpy(prpsinfo.pr_psargs, saved_command_line, ELF_PRARGSZ); nhdr->p_filesz = notesize(¬es[1]); - bufp = storenote(¬es[1],bufp); + bufp = storenote(¬es[1], bufp); /* set up the task structure */ notes[2].name = "CORE"; notes[2].type = NT_TASKSTRUCT; - notes[2].datasz = sizeof(*current); + notes[2].datasz = sizeof(struct task_struct); notes[2].data = current; nhdr->p_filesz = notesize(¬es[2]); - bufp = storenote(¬es[2],bufp); + bufp = storenote(¬es[2], bufp); } /* end elf_kcore_store_hdr() */ @@ -281,85 +310,79 @@ static void elf_kcore_store_hdr(char *bufp) /* * read from the ELF header and then kernel memory */ -ssize_t read_kcore(struct file *file, char *buffer, size_t buflen, +static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen, loff_t *fpos) { - ssize_t acc; + ssize_t acc = 0; size_t size, tsz; - char *page; - - /* work out how much file we allow to be read */ - proc_root_kcore.size = size = get_kcore_size(); - acc = 0; + char * elf_buffer; + int elf_buflen = 0, num_vma = 0; - /* see if file pointer already beyond EOF */ - if (buflen==0 || *fpos>=size) + /* XXX we need to somehow lock vmlist between here + * and after elf_kcore_store_hdr() returns. + * For now assume that num_vma does not change (TA) + */ + proc_root_kcore.size = size = get_kcore_size(&num_vma, &elf_buflen); + if (buflen == 0 || *fpos >= size) return 0; /* trim buflen to not go beyond EOF */ - if (buflen > size-*fpos) + if (buflen > size - *fpos) buflen = size - *fpos; /* construct an ELF core header if we'll need some of it */ - if (*fpos #include #include -#include -#include #include #include #include @@ -164,6 +162,8 @@ static int meminfo_read_proc(char *page, char **start, off_t off, "Cached: %8u kB\n" "HighTotal: %8lu kB\n" "HighFree: %8lu kB\n" + "LowTotal: %8lu kB\n" + "LowFree: %8lu kB\n" "SwapTotal: %8lu kB\n" "SwapFree: %8lu kB\n", K(i.totalram), @@ -173,6 +173,8 @@ static int meminfo_read_proc(char *page, char **start, off_t off, K(atomic_read(&page_cache_size)), K(i.totalhigh), K(i.freehigh), + K(i.totalram-i.totalhigh), + K(i.freeram-i.freehigh), K(i.totalswap), K(i.freeswap)); @@ -546,28 +548,6 @@ static int memory_read_proc(char *page, char **start, off_t off, return len; } -static int open_kcore(struct inode * inode, struct file * filp) -{ - return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; -} - -extern ssize_t read_kcore(struct file *, char *, size_t, loff_t *); - -static struct file_operations proc_kcore_operations = { - NULL, /* lseek */ - read_kcore, - NULL, /* write */ - NULL, /* readdir */ - NULL, /* poll */ - NULL, /* ioctl */ - NULL, /* mmap */ - open_kcore -}; - -static struct inode_operations proc_kcore_inode_operations = { - &proc_kcore_operations, -}; - /* * This function accesses profiling information. The returned data is * binary: the sampling step and the actual contents of the profile @@ -704,7 +684,7 @@ void proc_misc_init(void) /* And now for trickier ones */ proc_register(&proc_root, &proc_root_kmsg); proc_register(&proc_root, &proc_root_kcore); - proc_root_kcore.size = get_kcore_size(); + proc_root_kcore.size = (size_t)high_memory - PAGE_OFFSET + PAGE_SIZE; if (prof_shift) { proc_register(&proc_root, &proc_root_profile); proc_root_profile.size = (1+prof_len) * sizeof(unsigned int); diff --git a/fs/proc/procfs_syms.c b/fs/proc/procfs_syms.c index 7a1732ae4d0a..fa2ee362ee0c 100644 --- a/fs/proc/procfs_syms.c +++ b/fs/proc/procfs_syms.c @@ -18,8 +18,6 @@ EXPORT_SYMBOL(proc_get_inode); EXPORT_SYMBOL(proc_dir_inode_operations); EXPORT_SYMBOL(proc_net); EXPORT_SYMBOL(proc_bus); -EXPORT_SYMBOL(proc_lookup); -EXPORT_SYMBOL(proc_readdir); #if defined(CONFIG_SUN_OPENPROMFS_MODULE) EXPORT_SYMBOL(proc_openprom_register); diff --git a/fs/proc/root.c b/fs/proc/root.c index 65feea14221e..b87b0fb4fd83 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -437,9 +437,6 @@ static struct proc_dir_entry proc_root_ppc_htab = { 0, 8, "ppc_htab", S_IFREG | S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 1, 0, 0, 0, &proc_ppc_htab_inode_operations, - NULL, NULL, /* get_info, fill_inode */ - NULL, /* next */ - NULL, NULL /* parent, subdir */ }; #endif diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 8802360fee7d..543d15ea9407 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h @@ -3,6 +3,8 @@ #define UDF_VERSION_NOTICE "v0.8.9.3" +#include + #ifdef __KERNEL__ #include @@ -113,7 +115,6 @@ extern int udf_sync_file(struct file *, struct dentry *); #endif /* __KERNEL__ */ -#include #include "udfend.h" /* structures */ diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index c75a3a405a51..2f156b42a62b 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -676,7 +676,7 @@ unsigned ufs_bitmap_search (struct super_block * sb, else start = ucpi->c_frotor >> 3; - length = howmany(uspi->s_fpg, 8) - start; + length = ((uspi->s_fpg + 7) >> 3) - start; location = ubh_scanc(UCPI_UBH, ucpi->c_freeoff + start, length, (uspi->s_fpb == 8) ? ufs_fragtable_8fpb : ufs_fragtable_other, 1 << (count - 1 + (uspi->s_fpb & 7))); diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index b93d04f0bb1b..0b23ad37fb35 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c @@ -168,7 +168,7 @@ int ufs_check_dir_entry (const char * function, struct inode * dir, error_msg = "inode out of bounds"; if (error_msg != NULL) - ufs_error (sb, function, "bad entry in directory #%lu, size %lu: %s - " + ufs_error (sb, function, "bad entry in directory #%lu, size %Lu: %s - " "offset=%lu, inode=%lu, reclen=%d, namlen=%d", dir->i_ino, dir->i_size, error_msg, offset, (unsigned long) SWAB32(de->d_ino), diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 3d9c8f6026e5..afcdcd600227 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -610,7 +610,7 @@ void ufs_read_inode (struct inode * inode) inode->u.ufs_i.i_gen = SWAB32(ufs_inode->ui_gen); inode->u.ufs_i.i_shadow = SWAB32(ufs_inode->ui_u3.ui_sun.ui_shadow); inode->u.ufs_i.i_oeftflag = SWAB32(ufs_inode->ui_u3.ui_sun.ui_oeftflag); - inode->u.ufs_i.i_lastfrag = howmany (inode->i_size, uspi->s_fsize); + inode->u.ufs_i.i_lastfrag = (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift; if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) ; diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 27d404ca1c43..a3419a5a85e0 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -328,7 +328,7 @@ int ufs_read_cylinder_structures (struct super_block * sb) { * on the device. */ size = uspi->s_cssize; - blks = howmany(size, uspi->s_fsize); + blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; base = space = kmalloc(size, GFP_KERNEL); if (!base) goto failed; @@ -405,7 +405,7 @@ void ufs_put_cylinder_structures (struct super_block * sb) { uspi = sb->u.ufs_sb.s_uspi; size = uspi->s_cssize; - blks = howmany(size, uspi->s_fsize); + blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; base = space = (char*) sb->u.ufs_sb.s_csp[0]; for (i = 0; i < blks; i += uspi->s_fpb) { size = uspi->s_bsize; diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c index 99069517eabe..2d33bd3c992e 100644 --- a/fs/ufs/truncate.c +++ b/fs/ufs/truncate.c @@ -59,8 +59,8 @@ * Linus */ -#define DIRECT_BLOCK howmany (inode->i_size, uspi->s_bsize) -#define DIRECT_FRAGMENT howmany (inode->i_size, uspi->s_fsize) +#define DIRECT_BLOCK ((inode->i_size + uspi->s_bsize - 1) >> uspi->s_bshift) +#define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift) #define DATA_BUFFER_USED(bh) \ (atomic_read(&bh->b_count) || buffer_locked(bh)) @@ -312,7 +312,7 @@ static int ufs_trunc_dindirect (struct inode * inode, unsigned offset, u32 * p) uspi = sb->u.ufs_sb.s_uspi; dindirect_block = (DIRECT_BLOCK > offset) - ? ((DIRECT_BLOCK - offset) / uspi->s_apb) : 0; + ? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0; retry = 0; tmp = SWAB32(*p); @@ -382,7 +382,7 @@ static int ufs_trunc_tindirect (struct inode * inode) retry = 0; tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb)) - ? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) / uspi->s_2apb) : 0; + ? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0; p = inode->u.ufs_i.i_u1.i_data + UFS_TIND_BLOCK; if (!(tmp = SWAB32(*p))) return 0; @@ -471,7 +471,7 @@ void ufs_truncate (struct inode * inode) } } inode->i_mtime = inode->i_ctime = CURRENT_TIME; - inode->u.ufs_i.i_lastfrag = howmany (inode->i_size, uspi->s_fsize); + inode->u.ufs_i.i_lastfrag = DIRECT_FRAGMENT; mark_inode_dirty(inode); UFSD(("EXIT\n")) } diff --git a/fs/ufs/util.h b/fs/ufs/util.h index cf26773ef041..049b194eeef5 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h @@ -14,7 +14,6 @@ * some useful macros */ #define in_range(b,first,len) ((b)>=(first)&&(b)<(first)+(len)) -#define howmany(x,y) (((x)+(y)-1)/(y)) #define min(x,y) ((x)<(y)?(x):(y)) #define max(x,y) ((x)>(y)?(x):(y)) diff --git a/include/asm-i386/highmem.h b/include/asm-i386/highmem.h index bd5564aea8c9..d17d108c73be 100644 --- a/include/asm-i386/highmem.h +++ b/include/asm-i386/highmem.h @@ -18,7 +18,12 @@ #ifndef _ASM_HIGHMEM_H #define _ASM_HIGHMEM_H +#ifdef __KERNEL__ + #include +#include +#include +#include /* undef for production */ #define HIGHMEM_DEBUG 1 @@ -28,58 +33,79 @@ extern unsigned long highstart_pfn, highend_pfn; extern pte_t *kmap_pte; extern pgprot_t kmap_prot; +extern pte_t *pkmap_page_table; extern void kmap_init(void) __init; -/* kmap helper functions necessary to access the highmem pages in kernel */ -#include -#include +#define PKMAP_BASE (0xff000000UL) + +extern unsigned long FASTCALL(kmap_high(struct page *page)); +extern void FASTCALL(kunmap_high(struct page *page)); -extern inline unsigned long kmap(struct page *page, enum km_type type) +extern inline unsigned long kmap(struct page *page) { + if (in_interrupt()) + BUG(); if (page < highmem_start_page) return page_address(page); - { - enum fixed_addresses idx = type+KM_TYPE_NR*smp_processor_id(); - unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN+idx); - -#if HIGHMEM_DEBUG - if (!pte_none(*(kmap_pte-idx))) - { - __label__ here; - here: - printk(KERN_ERR "not null pte on CPU %d from %p\n", - smp_processor_id(), &&here); - } -#endif - set_pte(kmap_pte-idx, mk_pte(page, kmap_prot)); - __flush_tlb_one(vaddr); + return kmap_high(page); +} - return vaddr; - } +extern inline void kunmap(struct page *page) +{ + if (in_interrupt()) + BUG(); + if (page < highmem_start_page) + return; + kunmap_high(page); } -extern inline void kunmap(unsigned long vaddr, enum km_type type) +/* + * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap + * gives a more generic (and caching) interface. But kmap_atomic can + * be used in IRQ contexts, so in some (very limited) cases we need + * it. + */ +extern inline unsigned long kmap_atomic(struct page *page, enum km_type type) { + enum fixed_addresses idx; + unsigned long vaddr; + + if (page < highmem_start_page) + return page_address(page); + + idx = type + KM_TYPE_NR*smp_processor_id(); + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); #if HIGHMEM_DEBUG - enum fixed_addresses idx = type+KM_TYPE_NR*smp_processor_id(); - if ((vaddr & PAGE_MASK) == __fix_to_virt(FIX_KMAP_BEGIN+idx)) - { - /* force other mappings to Oops if they'll try to access - this pte without first remap it */ - pte_clear(kmap_pte-idx); - __flush_tlb_one(vaddr); - } + if (!pte_none(*(kmap_pte-idx))) + BUG(); #endif + set_pte(kmap_pte-idx, mk_pte(page, kmap_prot)); + __flush_tlb_one(vaddr); + + return vaddr; } -extern inline void kmap_check(void) +extern inline void kunmap_atomic(unsigned long vaddr, enum km_type type) { #if HIGHMEM_DEBUG - int idx_base = KM_TYPE_NR*smp_processor_id(), i; - for (i = idx_base; i < idx_base+KM_TYPE_NR; i++) - if (!pte_none(*(kmap_pte-i))) - BUG(); + enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); + + if (vaddr < FIXADDR_START) // FIXME + return; + + if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx)) + BUG(); + + /* + * force other mappings to Oops if they'll try to access + * this pte without first remap it + */ + pte_clear(kmap_pte-idx); + __flush_tlb_one(vaddr); #endif } + +#endif /* __KERNEL__ */ + #endif /* _ASM_HIGHMEM_H */ diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h index ad25dcbbcd7e..75cfb939b5bd 100644 --- a/include/asm-i386/io.h +++ b/include/asm-i386/io.h @@ -103,9 +103,8 @@ __OUTS(l) #ifdef __KERNEL__ -#include -#include #include +#include /* * Temporary debugging check to catch old code using diff --git a/include/asm-i386/kmap_types.h b/include/asm-i386/kmap_types.h index b3f16e29ba21..d92d81b203f4 100644 --- a/include/asm-i386/kmap_types.h +++ b/include/asm-i386/kmap_types.h @@ -2,9 +2,9 @@ #define _ASM_KMAP_TYPES_H enum km_type { - KM_READ, - KM_WRITE, - KM_TYPE_NR, + KM_BOUNCE_READ, + KM_BOUNCE_WRITE, + KM_TYPE_NR }; #endif diff --git a/include/asm-ppc/fcntl.h b/include/asm-ppc/fcntl.h index 6fe5596e378d..c1b149d47345 100644 --- a/include/asm-ppc/fcntl.h +++ b/include/asm-ppc/fcntl.h @@ -3,23 +3,23 @@ /* open/fcntl - O_SYNC is only implemented on blocks devices and on files located on an ext2 file system */ -#define O_ACCMODE 0003 -#define O_RDONLY 00 -#define O_WRONLY 01 -#define O_RDWR 02 -#define O_CREAT 0100 /* not fcntl */ -#define O_EXCL 0200 /* not fcntl */ -#define O_NOCTTY 0400 /* not fcntl */ -#define O_TRUNC 01000 /* not fcntl */ -#define O_APPEND 02000 -#define O_NONBLOCK 04000 +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 #define O_NDELAY O_NONBLOCK -#define O_SYNC 010000 -#define FASYNC 020000 /* fcntl, for BSD compatibility */ -#define O_DIRECTORY 040000 /* must be a directory */ -#define O_NOFOLLOW 100000 /* don't follow links */ -#define O_LARGEFILE 200000 -#define O_DIRECT 400000 /* direct disk access hint - currently ignored */ +#define O_SYNC 010000 +#define FASYNC 020000 /* fcntl, for BSD compatibility */ +#define O_DIRECTORY 040000 /* must be a directory */ +#define O_NOFOLLOW 0100000 /* don't follow links */ +#define O_LARGEFILE 0200000 +#define O_DIRECT 0400000 /* direct disk access hint - currently ignored */ #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 9be978d203dc..138831b4a021 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -34,15 +34,15 @@ */ enum { - ACPI_SYS_DEV, /* system device (fan, KB controller, ...) */ - ACPI_PCI_DEV, /* generic PCI device */ - ACPI_PCI_BUS, /* PCI bus */ - ACPI_ISA_DEV, /* generic ISA device */ - ACPI_ISA_BUS, /* ISA bus */ - ACPI_USB_DEV, /* generic USB device */ - ACPI_USB_HUB, /* USB hub device */ - ACPI_USB_CTRL, /* USB controller */ - ACPI_SCSI_DEV, /* generic SCSI device */ + ACPI_SYS_DEV, /* system device (fan, KB controller, ...) */ + ACPI_PCI_DEV, /* generic PCI device */ + ACPI_PCI_BUS, /* PCI bus */ + ACPI_ISA_DEV, /* generic ISA device */ + ACPI_ISA_BUS, /* ISA bus */ + ACPI_USB_DEV, /* generic USB device */ + ACPI_USB_HUB, /* USB hub device */ + ACPI_USB_CTRL, /* USB controller */ + ACPI_SCSI_DEV, /* generic SCSI device */ ACPI_SCSI_CTRL, /* SCSI controller */ }; @@ -59,13 +59,13 @@ typedef int acpi_dev_t; enum { ACPI_UNKNOWN_HID = 0x00000000, /* generic */ - ACPI_KBC_HID = 0x41d00303, /* keyboard controller */ - ACPI_COM_HID = 0x41d00500, /* serial port */ - ACPI_FDC_HID = 0x41d00700, /* floppy controller */ - ACPI_VGA_HID = 0x41d00900, /* VGA controller */ - ACPI_ISA_HID = 0x41d00a00, /* ISA bus */ - ACPI_EISA_HID = 0x41d00a01, /* EISA bus */ - ACPI_PCI_HID = 0x41d00a03, /* PCI bus */ + ACPI_KBC_HID = 0x41d00303, /* keyboard controller */ + ACPI_COM_HID = 0x41d00500, /* serial port */ + ACPI_FDC_HID = 0x41d00700, /* floppy controller */ + ACPI_VGA_HID = 0x41d00900, /* VGA controller */ + ACPI_ISA_HID = 0x41d00a00, /* ISA bus */ + ACPI_EISA_HID = 0x41d00a01, /* EISA bus */ + ACPI_PCI_HID = 0x41d00a03, /* PCI bus */ }; typedef int acpi_hid_t; @@ -91,18 +91,31 @@ struct acpi_dev; typedef int (*acpi_transition)(struct acpi_dev *dev, acpi_dstate_t state); /* - * ACPI device information + * Static device information + */ +struct acpi_dev_info +{ + acpi_dev_t type; /* device type */ + acpi_hid_t hid; /* PnP identifier */ + acpi_transition transition; /* state transition callback */ + + /* other information like D-states supported, + * D-state latencies, and in-rush current needs + * will go here + */ +}; + +/* + * Dynamic device information */ struct acpi_dev { - acpi_dev_t type; /* device type */ - unsigned long adr; /* bus address or unique id */ - acpi_hid_t hid; /* P&P identifier */ - acpi_transition transition; /* state transition callback */ - acpi_dstate_t state; /* current D-state */ - unsigned long accessed; /* last access time */ - unsigned long idle; /* last idle time */ - struct list_head entry; /* linked list entry */ + struct acpi_dev_info info; /* static device info */ + unsigned long adr; /* bus address or unique id */ + acpi_dstate_t state; /* current D-state */ + unsigned long accessed; /* last access time */ + unsigned long idle; /* last idle time */ + struct list_head entry; /* linked list entry */ }; #ifdef CONFIG_ACPI @@ -112,10 +125,7 @@ extern wait_queue_head_t acpi_idle_wait; /* * Register a device with the ACPI subsystem */ -struct acpi_dev *acpi_register(acpi_dev_t type, - unsigned long adr, - acpi_hid_t hid, - acpi_transition trans); +struct acpi_dev *acpi_register(struct acpi_dev_info *info, unsigned long adr); /* * Unregister a device with ACPI @@ -127,10 +137,12 @@ void acpi_unregister(struct acpi_dev *dev); */ extern inline void acpi_access(struct acpi_dev *dev) { - extern void acpi_wakeup(struct acpi_dev *dev); - if (dev->state != ACPI_D0) - acpi_wakeup(dev); - dev->accessed = jiffies; + extern void acpi_wakeup(struct acpi_dev*); + if (dev) { + if (dev->state != ACPI_D0) + acpi_wakeup(dev); + dev->accessed = jiffies; + } } /* @@ -138,18 +150,17 @@ extern inline void acpi_access(struct acpi_dev *dev) */ extern inline void acpi_dev_idle(struct acpi_dev *dev) { - dev->idle = jiffies; - if (waitqueue_active(&acpi_idle_wait)) - wake_up(&acpi_idle_wait); + if (dev) { + dev->idle = jiffies; + if (waitqueue_active(&acpi_idle_wait)) + wake_up(&acpi_idle_wait); + } } #else /* CONFIG_ACPI */ extern inline struct acpi_dev* -acpi_register(acpi_dev_t type, - unsigned long adr, - acpi_hid_t hid, - acpi_transition trans) +acpi_register(struct acpi_dev_info *info, unsigned long adr) { return 0; } @@ -175,6 +186,7 @@ extern void (*acpi_power_off)(void); #define ACPI_RSDT_SIG 0x54445352 /* 'RSDT' */ #define ACPI_FACP_SIG 0x50434146 /* 'FACP' */ #define ACPI_DSDT_SIG 0x54445344 /* 'DSDT' */ +#define ACPI_FACS_SIG 0x53434146 /* 'FACS' */ /* PM1_STS/EN flags */ #define ACPI_TMR 0x0001 @@ -235,7 +247,7 @@ struct acpi_rsdp { __u8 oem[6]; __u8 reserved; __u32 rsdt; -}; +} __attribute__ ((packed)); struct acpi_table { __u32 signature; @@ -247,7 +259,7 @@ struct acpi_table { __u32 oem_rev; __u32 creator; __u32 creator_rev; -}; +} __attribute__ ((packed)); struct acpi_facp { struct acpi_table hdr; @@ -290,7 +302,7 @@ struct acpi_facp { __u8 reserved5; __u8 reserved6; __u32 flags; -}; +} __attribute__ ((packed)); struct acpi_facs { __u32 signature; @@ -299,7 +311,7 @@ struct acpi_facs { __u32 fw_wake_vector; __u32 global_lock; __u32 flags; -}; +} __attribute__ ((packed)); /* * Sysctl declarations @@ -323,7 +335,6 @@ enum ACPI_P_LVL2_LAT, ACPI_P_LVL3_LAT, ACPI_S5_SLP_TYP, - ACPI_KBD, }; #define ACPI_P_LVL_DISABLED 0x80 diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index a0727169eeab..c789e769caca 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h @@ -1,7 +1,6 @@ #ifndef _LINUX_BOOTMEM_H #define _LINUX_BOOTMEM_H -#include #include #include diff --git a/include/linux/fs.h b/include/linux/fs.h index a7efa4ea0b79..348cf02e2a0d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -224,7 +224,8 @@ struct buffer_head { struct buffer_head *b_reqnext; /* request queue */ struct buffer_head **b_pprev; /* doubly linked list of hash-queue */ - char *b_data; /* pointer to data block (1024 bytes) */ + char * b_data; /* pointer to data block (512 byte) */ + struct page *b_page; /* the page this bh is mapped to */ void (*b_end_io)(struct buffer_head *bh, int uptodate); /* I/O completion */ void *b_dev_id; @@ -246,8 +247,11 @@ void init_buffer(struct buffer_head *, bh_end_io_t *, void *); #define buffer_new(bh) __buffer_state(bh,New) #define buffer_protected(bh) __buffer_state(bh,Protected) -#define buffer_page(bh) (mem_map + MAP_NR((bh)->b_data)) -#define touch_buffer(bh) set_bit(PG_referenced, &buffer_page(bh)->flags) +#define bh_offset(bh) ((unsigned long)(bh)->b_data & ~PAGE_MASK) + +extern void set_bh_page(struct buffer_head *bh, struct page *page, unsigned int offset); + +#define touch_buffer(bh) set_bit(PG_referenced, &bh->b_page->flags) #include #include @@ -935,6 +939,7 @@ extern void set_blocksize(kdev_t, int); extern unsigned int get_hardblocksize(kdev_t); extern struct buffer_head * bread(kdev_t, int, int); extern struct buffer_head * breada(kdev_t, int, int, unsigned int, unsigned int); +extern void wakeup_bdflush(int wait); extern int brw_page(int, struct page *, kdev_t, int [], int); diff --git a/include/linux/highmem.h b/include/linux/highmem.h index 48e87859b0e2..4e8e98224681 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -17,14 +17,15 @@ FASTCALL(unsigned int nr_free_highpages(void)); extern struct page * prepare_highmem_swapout(struct page *); extern struct page * replace_with_highmem(struct page *); +extern struct buffer_head * create_bounce(int rw, struct buffer_head * bh_orig); #else /* CONFIG_HIGHMEM */ extern inline unsigned int nr_free_highpages(void) { return 0; } #define prepare_highmem_swapout(page) page #define replace_with_highmem(page) page -#define kmap(page, type) page_address(page) -#define kunmap(vaddr, type) do { } while (0) +#define kmap(page) page_address(page) +#define kunmap(page) do { } while (0) #endif /* CONFIG_HIGHMEM */ @@ -33,9 +34,9 @@ extern inline void clear_highpage(struct page *page) { unsigned long kaddr; - kaddr = kmap(page, KM_WRITE); + kaddr = kmap(page); clear_page((void *)kaddr); - kunmap(kaddr, KM_WRITE); + kunmap(page); } extern inline void memclear_highpage(struct page *page, unsigned int offset, unsigned int size) @@ -44,9 +45,9 @@ extern inline void memclear_highpage(struct page *page, unsigned int offset, uns if (offset + size > PAGE_SIZE) BUG(); - kaddr = kmap(page, KM_WRITE); + kaddr = kmap(page); memset((void *)(kaddr + offset), 0, size); - kunmap(kaddr, KM_WRITE); + kunmap(page); } /* @@ -58,21 +59,21 @@ extern inline void memclear_highpage_flush(struct page *page, unsigned int offse if (offset + size > PAGE_SIZE) BUG(); - kaddr = kmap(page, KM_WRITE); + kaddr = kmap(page); memset((void *)(kaddr + offset), 0, size); flush_page_to_ram(page); - kunmap(kaddr, KM_WRITE); + kunmap(page); } extern inline void copy_highpage(struct page *to, struct page *from) { unsigned long vfrom, vto; - vfrom = kmap(from, KM_READ); - vto = kmap(to, KM_WRITE); + vfrom = kmap(from); + vto = kmap(to); copy_page((void *)vto, (void *)vfrom); - kunmap(vfrom, KM_READ); - kunmap(vto, KM_WRITE); + kunmap(from); + kunmap(to); } #endif /* _LINUX_HIGHMEM_H */ diff --git a/include/linux/mm.h b/include/linux/mm.h index 5683f062d010..a62e7975fe9e 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -138,6 +138,7 @@ typedef struct page { wait_queue_head_t wait; struct page **pprev_hash; struct buffer_head * buffers; + unsigned long virtual; /* nonzero if kmapped */ } mem_map_t; #define get_page(p) atomic_inc(&(p)->count) @@ -285,11 +286,16 @@ extern mem_map_t * mem_map; * This is timing-critical - most of the time in getting a new page * goes to clearing the page. If you want a page without the clearing * overhead, just use __get_free_page() directly.. + * + * We have two allocation namespaces - the *get*page*() variants + * return virtual kernel addresses to the allocated page(s), the + * alloc_page*() variants return 'struct page *'. */ #define __get_free_page(gfp_mask) __get_free_pages((gfp_mask),0) #define __get_dma_pages(gfp_mask, order) __get_free_pages((gfp_mask) | GFP_DMA,(order)) -extern unsigned long FASTCALL(__get_free_pages(int gfp_mask, unsigned long gfp_order)); -extern struct page * get_free_highpage(int gfp_mask); +extern unsigned long FASTCALL(__get_free_pages(int gfp_mask, unsigned long order)); +extern struct page * FASTCALL(alloc_pages(int gfp_mask, unsigned long order)); +#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0) extern inline unsigned long get_zeroed_page(int gfp_mask) { diff --git a/include/linux/module.h b/include/linux/module.h index 3046cd391fdf..a0fc64c887a8 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -287,5 +287,4 @@ __attribute__((section("__ksymtab"))) = \ #define EXPORT_NO_SYMBOLS #endif /* MODULE */ -extern unsigned long get_kcore_size(void); #endif /* _LINUX_MODULE_H */ diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 15a0c6d20230..66b558627766 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -27,7 +27,7 @@ #define PAGE_CACHE_MASK PAGE_MASK #define PAGE_CACHE_ALIGN(addr) (((addr)+PAGE_CACHE_SIZE-1)&PAGE_CACHE_MASK) -#define page_cache_alloc() (mem_map+MAP_NR(__get_free_pages(GFP_USER, 0))) +#define page_cache_alloc() alloc_pages(GFP_HIGHUSER, 0) #define page_cache_free(x) __free_page(x) #define page_cache_release(x) __free_page(x) diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index d3edb886b044..d0e57016f98b 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -22,74 +22,6 @@ enum { PROC_ROOT_INO = 1, }; -enum scsi_directory_inos { - PROC_SCSI_ADVANSYS = 256, - PROC_SCSI_PCI2000, - PROC_SCSI_PCI2220I, - PROC_SCSI_PSI240I, - PROC_SCSI_EATA, - PROC_SCSI_EATA_PIO, - PROC_SCSI_AHA152X, - PROC_SCSI_AHA1542, - PROC_SCSI_AHA1740, - PROC_SCSI_AIC7XXX, - PROC_SCSI_BUSLOGIC, - PROC_SCSI_U14_34F, - PROC_SCSI_FDOMAIN, - PROC_SCSI_GDTH, - PROC_SCSI_GENERIC_NCR5380, - PROC_SCSI_IN2000, - PROC_SCSI_PAS16, - PROC_SCSI_QLOGICFAS, - PROC_SCSI_QLOGICISP, - PROC_SCSI_QLOGICFC, - PROC_SCSI_SEAGATE, - PROC_SCSI_T128, - PROC_SCSI_NCR53C7xx, - PROC_SCSI_SYM53C8XX, - PROC_SCSI_NCR53C8XX, - PROC_SCSI_ULTRASTOR, - PROC_SCSI_7000FASST, - PROC_SCSI_IBMMCA, - PROC_SCSI_FD_MCS, - PROC_SCSI_EATA2X, - PROC_SCSI_DC390T, - PROC_SCSI_AM53C974, - PROC_SCSI_SSC, - PROC_SCSI_NCR53C406A, - PROC_SCSI_SYM53C416, - PROC_SCSI_MEGARAID, - PROC_SCSI_PPA, - PROC_SCSI_ATP870U, - PROC_SCSI_ESP, - PROC_SCSI_QLOGICPTI, - PROC_SCSI_AMIGA7XX, - PROC_SCSI_MVME147, - PROC_SCSI_MVME16x, - PROC_SCSI_BVME6000, - PROC_SCSI_SIM710, - PROC_SCSI_A3000, - PROC_SCSI_A2091, - PROC_SCSI_GVP11, - PROC_SCSI_ATARI, - PROC_SCSI_MAC, - PROC_SCSI_IDESCSI, - PROC_SCSI_SGIWD93, - PROC_SCSI_MESH, - PROC_SCSI_53C94, - PROC_SCSI_PLUTO, - PROC_SCSI_INI9100U, - PROC_SCSI_INIA100, - PROC_SCSI_IPH5526_FC, - PROC_SCSI_FCAL, - PROC_SCSI_I2O, - PROC_SCSI_USB_SCSI, - PROC_SCSI_SCSI_DEBUG, - PROC_SCSI_NOT_PRESENT, - PROC_SCSI_FILE, /* I'm assuming here that we */ - PROC_SCSI_LAST = (PROC_SCSI_FILE + 16) /* won't ever see more than */ -}; /* 16 HBAs in one machine */ - /* Finally, the dynamically allocatable proc entries are reserved: */ #define PROC_DYNAMIC_FIRST 4096 @@ -113,9 +45,8 @@ enum scsi_directory_inos { * /proc file has a parent, but "subdir" is NULL for all * non-directory entries). * - * "get_info" is called at "read", while "fill_inode" is used to - * fill in file type/protection/owner information specific to the - * particular /proc file. + * "get_info" is called at "read", while "owner" is used to protect module + * from unloading while proc_dir_entry is in use */ typedef int (read_proc_t)(char *page, char **start, off_t off, @@ -135,7 +66,7 @@ struct proc_dir_entry { unsigned long size; struct inode_operations * ops; get_info_t *get_info; - void (*fill_inode)(struct inode *, int); + struct module *owner; struct proc_dir_entry *next, *parent, *subdir; void *data; read_proc_t *read_proc; diff --git a/include/linux/swap.h b/include/linux/swap.h index b3ddba42d3e8..8e9e729890e4 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -114,8 +114,10 @@ extern unsigned int nr_swapfiles; extern struct swap_info_struct swap_info[]; extern int is_swap_partition(kdev_t); extern void si_swapinfo(struct sysinfo *); -extern swp_entry_t get_swap_page(void); -extern void swap_free(swp_entry_t); +extern swp_entry_t __get_swap_page(unsigned short); +#define get_swap_page() __get_swap_page(1) +extern void __swap_free(swp_entry_t, unsigned short); +#define swap_free(entry) __swap_free((entry), 1) struct swap_list_t { int head; /* head of priority-ordered swapfile list */ int next; /* swapfile to be used next */ diff --git a/include/linux/videodev.h b/include/linux/videodev.h index bff574aac740..f58bf97ddc1b 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -55,6 +55,10 @@ extern void video_unregister_device(struct video_device *); #define VID_TYPE_SCALES 128 /* Scalable */ #define VID_TYPE_MONOCHROME 256 /* Monochrome only */ #define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ +#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ +#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ +#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ +#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ struct video_capability { @@ -230,6 +234,36 @@ struct video_unit int teletext; /* Teletext minor */ }; +/* video_info is biased towards hardware mpeg encode/decode */ +/* but it could apply generically to any hardware compressor/decompressor */ +struct video_info +{ + __u32 frame_count; /* frames output since decode/encode began */ + __u32 h_size; /* current unscaled horizontal size */ + __u32 v_size; /* current unscaled veritcal size */ + __u32 smpte_timecode; /* current SMPTE timecode (for current GOP) */ + __u32 picture_type; /* current picture type */ + __u32 temporal_reference; /* current temporal reference */ + __u8 user_data[256]; /* user data last found in compressed stream */ + /* user_data[0] contains user data flags, user_data[1] has count */ +}; + +/* generic structure for setting playback modes */ +struct video_play_mode +{ + int mode; + int p1; + int p2; +}; + +/* for loading microcode / fpga programming */ +struct video_code +{ + char loadwhat[16]; /* name or tag of file being passed */ + int datasize; + __u8 *data; +}; + #define VIDIOCGCAP _IOR('v',1,struct video_capability) /* Get capabilities */ #define VIDIOCGCHAN _IOWR('v',2,struct video_channel) /* Get channel info (sources) */ #define VIDIOCSCHAN _IOW('v',3,struct video_channel) /* Set channel */ @@ -253,9 +287,47 @@ struct video_unit #define VIDIOCGUNIT _IOR('v', 21, struct video_unit) /* Get attached units */ #define VIDIOCGCAPTURE _IOR('v',22, struct video_capture) /* Get frame buffer */ #define VIDIOCSCAPTURE _IOW('v',23, struct video_capture) /* Set frame buffer - root only */ +#define VIDIOCSPLAYMODE _IOW('v',24, struct video_play_mode) /* Set output video mode/feature */ +#define VIDIOCSWRITEMODE _IOW('v',25, int) /* Set write mode */ +#define VIDIOCGPLAYINFO _IOR('v',26, struct video_info) /* Get current playback info from hardware */ +#define VIDIOCSMICROCODE _IOW('v',27, struct video_code) /* Load microcode into hardware */ #define BASE_VIDIOCPRIVATE 192 /* 192-255 are private */ +/* VIDIOCSWRITEMODE */ +#define VID_WRITE_MPEG_AUD 0 +#define VID_WRITE_MPEG_VID 1 +#define VID_WRITE_OSD 2 +#define VID_WRITE_TTX 3 +#define VID_WRITE_CC 4 +#define VID_WRITE_MJPEG 5 + +/* VIDIOCSPLAYMODE */ +#define VID_PLAY_VID_OUT_MODE 0 + /* p1: = VIDEO_MODE_PAL, VIDEO_MODE_NTSC, etc ... */ +#define VID_PLAY_GENLOCK 1 + /* p1: 0 = OFF, 1 = ON */ + /* p2: GENLOCK FINE DELAY value */ +#define VID_PLAY_NORMAL 2 +#define VID_PLAY_PAUSE 3 +#define VID_PLAY_SINGLE_FRAME 4 +#define VID_PLAY_FAST_FORWARD 5 +#define VID_PLAY_SLOW_MOTION 6 +#define VID_PLAY_IMMEDIATE_NORMAL 7 +#define VID_PLAY_SWITCH_CHANNELS 8 +#define VID_PLAY_FREEZE_FRAME 9 +#define VID_PLAY_STILL_MODE 10 +#define VID_PLAY_MASTER_MODE 11 + /* p1: see below */ +#define VID_PLAY_MASTER_NONE 1 +#define VID_PLAY_MASTER_VIDEO 2 +#define VID_PLAY_MASTER_AUDIO 3 +#define VID_PLAY_ACTIVE_SCANLINES 12 + /* p1 = first active; p2 = last active */ +#define VID_PLAY_RESET 13 +#define VID_PLAY_END_MARK 14 + + #define VID_HARDWARE_BT848 1 #define VID_HARDWARE_QCAM_BW 2 @@ -276,7 +348,7 @@ struct video_unit #define VID_HARDWARE_BROADWAY 17 /* Broadway project */ #define VID_HARDWARE_GEMTEK 18 #define VID_HARDWARE_TYPHOON 19 -#define VID_HARDWARE_VINO 20 /* Reserved for SGI Indy Vino */ +#define VID_HARDWARE_VINO 20 /* SGI Indy Vino */ #define VID_HARDWARE_CADET 21 /* Cadet radio */ #define VID_HARDWARE_TRUST 22 /* Trust FM Radio */ #define VID_HARDWARE_TERRATEC 23 /* TerraTec ActiveRadio */ diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 340544fd6e55..b89c788f3adb 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -20,5 +20,6 @@ long vread(char *buf, char *addr, unsigned long count); void vmfree_area_pages(unsigned long address, unsigned long size); int vmalloc_area_pages(unsigned long address, unsigned long size); +extern struct vm_struct * vmlist; #endif diff --git a/include/pcmcia/bulkmem.h b/include/pcmcia/bulkmem.h index 634693c4d2b1..09f0a4ddd284 100644 --- a/include/pcmcia/bulkmem.h +++ b/include/pcmcia/bulkmem.h @@ -1,7 +1,7 @@ /* * Definitions for bulk memory services * - * bulkmem.h 1.10 1999/08/28 04:12:33 + * bulkmem.h 1.11 1999/10/25 20:23:16 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -14,7 +14,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/bus_ops.h b/include/pcmcia/bus_ops.h index 867ad832c271..bdbd34312e0f 100644 --- a/include/pcmcia/bus_ops.h +++ b/include/pcmcia/bus_ops.h @@ -1,5 +1,5 @@ /* - * bus_ops.h 1.7 1999/09/10 06:22:33 + * bus_ops.h 1.8 1999/10/25 20:23:16 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/ciscode.h b/include/pcmcia/ciscode.h index 32915c16763a..904fba0b8275 100644 --- a/include/pcmcia/ciscode.h +++ b/include/pcmcia/ciscode.h @@ -1,5 +1,5 @@ /* - * ciscode.h 1.38 1999/08/28 04:12:32 + * ciscode.h 1.39 1999/10/25 20:23:17 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/cisreg.h b/include/pcmcia/cisreg.h index 16c3dee31dab..20373545cf15 100644 --- a/include/pcmcia/cisreg.h +++ b/include/pcmcia/cisreg.h @@ -1,5 +1,5 @@ /* - * cisreg.h 1.13 1999/08/28 04:12:32 + * cisreg.h 1.14 1999/10/25 20:23:17 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/cistpl.h b/include/pcmcia/cistpl.h index 200665387368..9ab70257c9fb 100644 --- a/include/pcmcia/cistpl.h +++ b/include/pcmcia/cistpl.h @@ -1,5 +1,5 @@ /* - * cistpl.h 1.30 1999/08/28 04:12:32 + * cistpl.h 1.31 1999/10/25 20:23:17 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index f8e6b970566a..bd99686304b1 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h @@ -1,5 +1,5 @@ /* - * cs.h 1.68 1999/10/20 18:59:32 + * cs.h 1.69 1999/10/25 20:23:17 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/cs_types.h b/include/pcmcia/cs_types.h index 5e2a688a0c01..63f56430e928 100644 --- a/include/pcmcia/cs_types.h +++ b/include/pcmcia/cs_types.h @@ -1,5 +1,5 @@ /* - * cs_types.h 1.15 1999/08/28 04:12:32 + * cs_types.h 1.16 1999/10/25 20:23:17 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/driver_ops.h b/include/pcmcia/driver_ops.h index 88bcaa9dd7b4..337076a24307 100644 --- a/include/pcmcia/driver_ops.h +++ b/include/pcmcia/driver_ops.h @@ -1,5 +1,5 @@ /* - * driver_ops.h 1.13 1999/08/28 04:12:33 + * driver_ops.h 1.14 1999/10/25 20:23:17 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index 2663780b5222..ddb271ec9c43 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -1,5 +1,5 @@ /* - * ds.h 1.54 1999/09/03 16:44:49 + * ds.h 1.55 1999/10/25 20:23:17 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/ftl.h b/include/pcmcia/ftl.h index 8bf70a5b81af..0fb527845d7b 100644 --- a/include/pcmcia/ftl.h +++ b/include/pcmcia/ftl.h @@ -1,5 +1,5 @@ /* - * ftl.h 1.6 1999/08/28 04:12:33 + * ftl.h 1.7 1999/10/25 20:23:17 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/mem_op.h b/include/pcmcia/mem_op.h index 8e8e0df79c7c..38101ab10d73 100644 --- a/include/pcmcia/mem_op.h +++ b/include/pcmcia/mem_op.h @@ -1,5 +1,5 @@ /* - * mem_op.h 1.11 1999/09/15 07:14:03 + * mem_op.h 1.12 1999/10/25 20:23:17 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/memory.h b/include/pcmcia/memory.h index 8324ac4f691a..5c0cdb69fe76 100644 --- a/include/pcmcia/memory.h +++ b/include/pcmcia/memory.h @@ -1,5 +1,5 @@ /* - * memory.h 1.5 1999/08/28 04:12:33 + * memory.h 1.6 1999/10/25 20:23:17 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index e39477e2e4a1..6912cd5c8b14 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -1,5 +1,5 @@ /* - * ss.h 1.24 1999/08/28 04:12:33 + * ss.h 1.25 1999/10/25 20:23:17 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in @@ -12,7 +12,7 @@ * limitations under the License. * * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds + * . Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * Alternatively, the contents of this file may be used under the diff --git a/include/pcmcia/version.h b/include/pcmcia/version.h index bb0b27e40af2..2a3cd252385a 100644 --- a/include/pcmcia/version.h +++ b/include/pcmcia/version.h @@ -1,4 +1,4 @@ -/* version.h 1.74 1999/09/29 20:41:44 (David Hinds) */ +/* version.h 1.76 1999/10/26 18:55:56 (David Hinds) */ -#define CS_RELEASE "3.1.2" -#define CS_RELEASE_CODE 0x3102 +#define CS_RELEASE "3.1.4" +#define CS_RELEASE_CODE 0x3104 diff --git a/ipc/shm.c b/ipc/shm.c index 34ec74877cc8..23710eedc956 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -36,6 +36,7 @@ struct shmid_kernel /* extend struct shmis_ds with private fields */ pte_t **shm_dir; /* ptr to array of ptrs to frames -> SHMMAX */ struct vm_area_struct *attaches; /* descriptors for attaches */ int id; /* backreference to id for shm_close */ + struct semaphore sem; }; static int findkey (key_t key); @@ -50,7 +51,7 @@ static int shm_swapout(struct page *, struct file *); static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data); #endif -size_t shm_prm[3] = {SHMMAX, SHMALL, SHMMNI}; +unsigned int shm_prm[3] = {SHMMAX, SHMALL, SHMMNI}; static int shm_tot = 0; /* total number of shared memory pages */ static int shm_rss = 0; /* number of shared memory pages that are in memory */ @@ -61,6 +62,9 @@ static struct shmid_kernel **shm_segs = NULL; static unsigned int num_segs = 0; static unsigned short shm_seq = 0; /* incremented, for recognizing stale ids */ +/* locks order: + shm_lock -> pagecache_lock (end of shm_swap) + shp->sem -> other spinlocks (shm_nopage) */ spinlock_t shm_lock = SPIN_LOCK_UNLOCKED; /* some statistics */ @@ -260,6 +264,7 @@ found: shp->u.shm_ctime = CURRENT_TIME; shp->shm_npages = numpages; shp->id = id; + init_MUTEX(&shp->sem); spin_lock(&shm_lock); @@ -770,19 +775,20 @@ static struct page * shm_nopage(struct vm_area_struct * shmd, unsigned long addr idx = (address - shmd->vm_start) >> PAGE_SHIFT; idx += shmd->vm_pgoff; + down(&shp->sem); spin_lock(&shm_lock); -again: pte = SHM_ENTRY(shp,idx); if (!pte_present(pte)) { + /* page not present so shm_swap can't race with us + and the semaphore protects us by other tasks that + could potentially fault on our pte under us */ if (pte_none(pte)) { spin_unlock(&shm_lock); - page = get_free_highpage(GFP_HIGHUSER); + page = alloc_page(GFP_HIGHUSER); if (!page) goto oom; clear_highpage(page); spin_lock(&shm_lock); - if (pte_val(pte) != pte_val(SHM_ENTRY(shp, idx))) - goto changed; } else { swp_entry_t entry = pte_to_swp_entry(pte); @@ -803,9 +809,6 @@ again: unlock_kernel(); spin_lock(&shm_lock); shm_swp--; - pte = SHM_ENTRY(shp, idx); - if (pte_present(pte)) - goto present; } shm_rss++; pte = pte_mkdirty(mk_pte(page, PAGE_SHARED)); @@ -813,21 +816,15 @@ again: } else --current->maj_flt; /* was incremented in do_no_page */ -done: /* pte_val(pte) == SHM_ENTRY (shp, idx) */ get_page(pte_page(pte)); spin_unlock(&shm_lock); + up(&shp->sem); current->min_flt++; return pte_page(pte); -changed: - __free_page(page); - goto again; -present: - if (page) - free_page_and_swap_cache(page); - goto done; oom: + up(&shp->sem); return NOPAGE_OOM; } @@ -851,7 +848,11 @@ int shm_swap (int prio, int gfp_mask) if (!counter) return 0; lock_kernel(); - swap_entry = get_swap_page(); + /* subtle: preload the swap count for the swap cache. We can't + increase the count inside the critical section as we can't release + the shm_lock there. And we can't acquire the big lock with the + shm_lock held (otherwise we would deadlock too easily). */ + swap_entry = __get_swap_page(2); if (!swap_entry.val) { unlock_kernel(); return 0; @@ -893,7 +894,7 @@ int shm_swap (int prio, int gfp_mask) failed: spin_unlock(&shm_lock); lock_kernel(); - swap_free(swap_entry); + __swap_free(swap_entry, 2); unlock_kernel(); return 0; } @@ -905,11 +906,16 @@ failed: swap_successes++; shm_swp++; shm_rss--; + + /* add the locked page to the swap cache before allowing + the swapin path to run lookup_swap_cache(). This avoids + reading a not yet uptodate block from disk. + NOTE: we just accounted the swap space reference for this + swap cache page at __get_swap_page() time. */ + add_to_swap_cache(page_map, swap_entry); spin_unlock(&shm_lock); lock_kernel(); - swap_duplicate(swap_entry); - add_to_swap_cache(page_map, swap_entry); rw_swap_page(WRITE, page_map, 0); unlock_kernel(); diff --git a/kernel/module.c b/kernel/module.c index 08f44a42b126..6f4ad977d846 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -53,25 +53,6 @@ static struct module *find_module(const char *name); static void free_module(struct module *, int tag_freed); -/* needed for /proc/kcore, here because kernel_module is static (TA) */ -unsigned long get_kcore_size(void) -{ - unsigned long try, size = 0; - struct module * m; - - if (module_list == &kernel_module) - return ((unsigned long)high_memory - PAGE_OFFSET + PAGE_SIZE); - - lock_kernel(); - for (m=module_list; m; m=m->next) { - try = (unsigned long)m + m->size; - if (try > size) - size = try; - } - unlock_kernel(); - return (size - PAGE_OFFSET + PAGE_SIZE); -} - /* * Called at boot time */ @@ -988,13 +969,6 @@ get_module_symbol(char *modname, char *symname) #else /* CONFIG_MODULES */ -/* no MODULES so high_memory is good enough for /proc/kcore (TA) */ -unsigned long get_kcore_size(void) -{ - return ((unsigned long)high_memory - PAGE_OFFSET + PAGE_SIZE); -} - - /* Dummy syscalls for people who don't want modules */ asmlinkage unsigned long diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 4945a0223e61..2980059b2492 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -50,15 +50,15 @@ repeat: flush_cache_page(vma, addr); if (write) { - maddr = kmap(page, KM_WRITE); + maddr = kmap(page); memcpy((char *)maddr + (addr & ~PAGE_MASK), buf, len); flush_page_to_ram(page); - kunmap(maddr, KM_WRITE); + kunmap(page); } else { - maddr = kmap(page, KM_READ); + maddr = kmap(page); memcpy(buf, (char *)maddr + (addr & ~PAGE_MASK), len); flush_page_to_ram(page); - kunmap(maddr, KM_READ); + kunmap(page); } return len; diff --git a/mm/filemap.c b/mm/filemap.c index b7d976dc62f7..3bb4d89deb9a 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -21,11 +21,13 @@ #include #include #include -#include +#include #include #include +#include + /* * Shared mappings implemented 30.11.1994. It's not fully working yet, * though. @@ -1142,12 +1144,10 @@ static int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned if (size > count) size = count; - /* - * FIXME: We cannot yet sleep with kmaps held. - */ - kaddr = kmap(page, KM_READ); - left = __copy_to_user(desc->buf, (void *)(kaddr+offset), size); - kunmap(kaddr, KM_READ); + + kaddr = kmap(page); + left = __copy_to_user(desc->buf, (void *)(kaddr + offset), size); + kunmap(page); if (left) { size -= left; @@ -1200,9 +1200,11 @@ static int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned size = count; old_fs = get_fs(); set_fs(KERNEL_DS); - kaddr = kmap(page, KM_READ); - written = file->f_op->write(file, (char *)kaddr + offset, size, &file->f_pos); - kunmap(kaddr, KM_READ); + + kaddr = kmap(page); + written = file->f_op->write(file, (char *)kaddr + offset, + size, &file->f_pos); + kunmap(page); set_fs(old_fs); if (written < 0) { desc->error = written; @@ -1347,8 +1349,6 @@ success: struct page *new_page = page_cache_alloc(); if (new_page) { - if (PageHighMem(new_page) || PageHighMem(old_page)) - BUG(); copy_highpage(new_page, old_page); flush_page_to_ram(new_page); } else @@ -1530,8 +1530,6 @@ static inline int filemap_sync_pte(pte_t * ptep, struct vm_area_struct *vma, return 0; } } - if (PageHighMem(page)) - BUG(); pgoff = (address - vma->vm_start) >> PAGE_CACHE_SHIFT; pgoff += vma->vm_pgoff; if (page->index != pgoff) { diff --git a/mm/highmem.c b/mm/highmem.c index 863691221dc9..248688c23829 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -4,10 +4,15 @@ * (C) 1999 Andrea Arcangeli, SuSE GmbH, andrea@suse.de * Gerhard Wichert, Siemens AG, Gerhard.Wichert@pdb.siemens.de * + * * Redesigned the x86 32-bit VM architecture to deal with * 64-bit physical space. With current x86 CPUs this * means up to 64 Gigabytes physical RAM. * + * Rewrote high memory support to move the page cache into + * high memory. Implemented permanent (schedulable) kmaps + * based on Linus' idea. + * * Copyright (C) 1999 Ingo Molnar */ @@ -15,6 +20,7 @@ #include #include #include +#include unsigned long highmem_mapnr; @@ -34,9 +40,9 @@ struct page * prepare_highmem_swapout(struct page * page) if (!regular_page) return NULL; - vaddr = kmap(page, KM_READ); + vaddr = kmap(page); copy_page((void *)regular_page, (void *)vaddr); - kunmap(vaddr, KM_READ); + kunmap(page); /* * ok, we can just forget about our highmem page since @@ -55,7 +61,7 @@ struct page * replace_with_highmem(struct page * page) if (PageHighMem(page) || !nr_free_highpages()) return page; - highpage = get_free_highpage(GFP_ATOMIC|__GFP_HIGHMEM); + highpage = alloc_page(GFP_ATOMIC|__GFP_HIGHMEM); if (!highpage) return page; if (!PageHighMem(highpage)) { @@ -63,9 +69,9 @@ struct page * replace_with_highmem(struct page * page) return page; } - vaddr = kmap(highpage, KM_WRITE); + vaddr = kmap(page); copy_page((void *)vaddr, (void *)page_address(page)); - kunmap(vaddr, KM_WRITE); + kunmap(page); /* Preserve the caching of the swap_entry. */ highpage->index = page->index; @@ -79,3 +85,275 @@ struct page * replace_with_highmem(struct page * page) return highpage; } + +/* + * Right now we initialize only a single pte table. It can be extended + * easily, subsequent pte tables have to be allocated in one physical + * chunk of RAM. + */ +#ifdef CONFIG_X86_PAE +#define LAST_PKMAP 2048 +#else +#define LAST_PKMAP 4096 +#endif +#define LAST_PKMAP_MASK (LAST_PKMAP-1) +#define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT) +#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) + +/* + * Virtual_count is not a pure "count". + * 0 means that it is not mapped, and has not been mapped + * since a TLB flush - it is usable. + * 1 means that there are no users, but it has been mapped + * since the last TLB flush - so we can't use it. + * n means that there are (n-1) current users of it. + */ +static int pkmap_count[LAST_PKMAP]; +static unsigned int last_pkmap_nr = 0; +static spinlock_t kmap_lock; + +pte_t * pkmap_page_table; + +static DECLARE_WAIT_QUEUE_HEAD(pkmap_map_wait); + +static void flush_all_zero_pkmaps(void) +{ + int i; + + for (i = 0; i < LAST_PKMAP; i++) { + struct page *page; + pte_t pte; + /* + * zero means we don't have anything to do, + * >1 means that it is still in use. Only + * a count of 1 means that it is free but + * needs to be unmapped + */ + if (pkmap_count[i] != 1) + continue; + pkmap_count[i] = 0; + pte = pkmap_page_table[i]; + if (pte_none(pte)) + continue; + pte_clear(pkmap_page_table+i); + page = pte_page(pte); + page->virtual = 0; + } + flush_tlb_all(); +} + +static unsigned long map_new_virtual(struct page *page) +{ + unsigned long vaddr; + int count = LAST_PKMAP; + + /* Find an empty entry */ + for (;;) { + last_pkmap_nr = (last_pkmap_nr + 1) & LAST_PKMAP_MASK; + if (!last_pkmap_nr) + flush_all_zero_pkmaps(); + if (!pkmap_count[last_pkmap_nr]) + break; /* Found a usable entry */ + if (--count) + continue; + + /* + * Sleep for somebody else to unmap their entries + */ + { + DECLARE_WAITQUEUE(wait, current); + + current->state = TASK_UNINTERRUPTIBLE; + add_wait_queue(&pkmap_map_wait, &wait); + spin_unlock(&kmap_lock); + // it's not quite possible to saturate the + // pkmap pool right now. + BUG(); + schedule(); + remove_wait_queue(&pkmap_map_wait, &wait); + spin_lock(&kmap_lock); + } + + /* Somebody else might have mapped it while we slept */ + if (page->virtual) + return page->virtual; + + /* Re-start */ + count = LAST_PKMAP; + } + vaddr = PKMAP_ADDR(last_pkmap_nr); + pkmap_page_table[last_pkmap_nr] = mk_pte(page, kmap_prot); + + /* + * Subtle! For some reason if we dont do this TLB flush then + * we get data corruption and weird behavior in dbench runs. + * But invlpg this should not be necessery ... Any ideas? + */ + __flush_tlb_one(vaddr); + pkmap_count[last_pkmap_nr] = 1; + page->virtual = vaddr; + + return vaddr; +} + +unsigned long kmap_high(struct page *page) +{ + unsigned long vaddr; + + if (!PageHighMem(page)) + BUG(); + /* + * For highmem pages, we can't trust "virtual" until + * after we have the lock. + * + * We cannot call this from interrupts, as it may block + */ + spin_lock(&kmap_lock); + vaddr = page->virtual; + if (!vaddr) + vaddr = map_new_virtual(page); + pkmap_count[PKMAP_NR(vaddr)]++; + if (pkmap_count[PKMAP_NR(vaddr)] < 2) + BUG(); + spin_unlock(&kmap_lock); + return vaddr; +} + +void kunmap_high(struct page *page) +{ + unsigned long vaddr; + unsigned long nr; + + spin_lock(&kmap_lock); + vaddr = page->virtual; + if (!vaddr) + BUG(); + nr = PKMAP_NR(vaddr); + + /* + * A count must never go down to zero + * without a TLB flush! + */ + switch (--pkmap_count[nr]) { + case 0: + BUG(); + case 1: + wake_up(&pkmap_map_wait); + } + spin_unlock(&kmap_lock); +} + +/* + * Simple bounce buffer support for highmem pages. + * This will be moved to the block layer in 2.5. + */ + +extern kmem_cache_t *bh_cachep; + +static inline void copy_from_high_bh (struct buffer_head *to, + struct buffer_head *from) +{ + struct page *p_from; + unsigned long vfrom; + + p_from = from->b_page; + vfrom = kmap_atomic(p_from, KM_BOUNCE_WRITE); + memcpy(to->b_data, (char *)vfrom + bh_offset(from), to->b_size); + kunmap_atomic(vfrom, KM_BOUNCE_WRITE); +} + +static inline void copy_to_high_bh_irq (struct buffer_head *to, + struct buffer_head *from) +{ + struct page *p_to; + unsigned long vto; + + p_to = to->b_page; + vto = kmap_atomic(p_to, KM_BOUNCE_WRITE); + memcpy((char *)vto + bh_offset(to), from->b_data, to->b_size); + kunmap_atomic(vto, KM_BOUNCE_WRITE); +} + +static inline void bounce_end_io (struct buffer_head *bh, int uptodate) +{ + struct buffer_head *bh_orig = (struct buffer_head *)(bh->b_dev_id); + + bh_orig->b_end_io(bh_orig, uptodate); + __free_page(bh->b_page); + kmem_cache_free(bh_cachep, bh); +} + +static void bounce_end_io_write (struct buffer_head *bh, int uptodate) +{ + bounce_end_io(bh, uptodate); +} + +static void bounce_end_io_read (struct buffer_head *bh, int uptodate) +{ + struct buffer_head *bh_orig = (struct buffer_head *)(bh->b_dev_id); + + if (uptodate) + copy_to_high_bh_irq(bh_orig, bh); + bounce_end_io(bh, uptodate); +} + +struct buffer_head * create_bounce(int rw, struct buffer_head * bh_orig) +{ + struct page *page; + struct buffer_head *bh; + + if (!PageHighMem(bh_orig->b_page)) + return bh_orig; + +repeat_bh: + bh = kmem_cache_alloc(bh_cachep, SLAB_BUFFER); + if (!bh) { + wakeup_bdflush(1); + current->policy |= SCHED_YIELD; + schedule(); + goto repeat_bh; + } + /* + * This is wasteful for 1k buffers, but this is a stopgap measure + * and we are being ineffective anyway. This approach simplifies + * things immensly. On boxes with more than 4GB RAM this should + * not be an issue anyway. + */ +repeat_page: + page = alloc_page(GFP_BUFFER); + if (!page) { + wakeup_bdflush(1); + current->policy |= SCHED_YIELD; + schedule(); + goto repeat_page; + } + set_bh_page(bh, page, 0); + + bh->b_next = NULL; + bh->b_blocknr = bh_orig->b_blocknr; + bh->b_size = bh_orig->b_size; + bh->b_list = -1; + bh->b_dev = bh_orig->b_dev; + bh->b_count = bh_orig->b_count; + bh->b_rdev = bh_orig->b_rdev; + bh->b_state = bh_orig->b_state; + bh->b_flushtime = 0; + bh->b_next_free = NULL; + bh->b_prev_free = NULL; + /* bh->b_this_page */ + bh->b_reqnext = NULL; + bh->b_pprev = NULL; + /* bh->b_page */ + if (rw == WRITE) { + bh->b_end_io = bounce_end_io_write; + copy_from_high_bh(bh, bh_orig); + } else + bh->b_end_io = bounce_end_io_read; + bh->b_dev_id = (void *)bh_orig; + bh->b_rsector = -1; + memset(&bh->b_wait, -1, sizeof(bh->b_wait)); + bh->b_kiobuf = NULL; + + return bh; +} + diff --git a/mm/memory.c b/mm/memory.c index a0452b335a86..a4eb697173a6 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -808,7 +808,7 @@ static int do_wp_page(struct task_struct * tsk, struct vm_area_struct * vma, * Ok, we need to copy. Oh, well.. */ spin_unlock(&tsk->mm->page_table_lock); - new_page = get_free_highpage(GFP_HIGHUSER); + new_page = alloc_page(GFP_HIGHUSER); if (!new_page) return -1; spin_lock(&tsk->mm->page_table_lock); @@ -1025,7 +1025,7 @@ static int do_anonymous_page(struct task_struct * tsk, struct vm_area_struct * v struct page *page = NULL; pte_t entry = pte_wrprotect(mk_pte(ZERO_PAGE(addr), vma->vm_page_prot)); if (write_access) { - page = get_free_highpage(GFP_HIGHUSER); + page = alloc_page(GFP_HIGHUSER); if (!page) return -1; if (PageHighMem(page)) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index d59a08a7729d..95a2bc436fc5 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -89,13 +89,6 @@ static zone_t zones[NR_ZONES] = * for the normal case, giving better asm-code. */ -/* - * Buddy system. Hairy. You really aren't expected to understand this - * - * Hint: -mask = 1+~mask - */ -spinlock_t page_alloc_lock = SPIN_LOCK_UNLOCKED; - #define memlist_init(x) INIT_LIST_HEAD(x) #define memlist_add_head list_add #define memlist_add_tail list_add_tail @@ -109,8 +102,13 @@ spinlock_t page_alloc_lock = SPIN_LOCK_UNLOCKED; */ #define BAD_RANGE(zone,x) ((((x)-mem_map) < zone->offset) || (((x)-mem_map) >= zone->offset+zone->size)) +/* + * Buddy system. Hairy. You really aren't expected to understand this + * + * Hint: -mask = 1+~mask + */ -static inline void free_pages_ok(struct page *page, unsigned long map_nr, unsigned long order) +static inline void free_pages_ok (struct page *page, unsigned long map_nr, unsigned long order) { struct free_area_struct *area; unsigned long index, page_idx, mask, offset; @@ -180,7 +178,7 @@ static inline void free_pages_ok(struct page *page, unsigned long map_nr, unsign change_bit((index) >> (1+(order)), (area)->map) #define ADDRESS(x) (PAGE_OFFSET + ((x) << PAGE_SHIFT)) -int __free_page(struct page *page) +int __free_page (struct page *page) { if (!PageReserved(page) && put_page_testzero(page)) { if (PageSwapCache(page)) @@ -194,7 +192,7 @@ int __free_page(struct page *page) return 0; } -int free_pages(unsigned long addr, unsigned long order) +int free_pages (unsigned long addr, unsigned long order) { unsigned long map_nr = MAP_NR(addr); @@ -232,7 +230,7 @@ static inline unsigned long EXPAND (zone_t *zone, struct page *map, unsigned lon return index; } -static inline struct page * rmqueue (zone_t *zone, int order) +static inline struct page * rmqueue (zone_t *zone, unsigned long order) { struct free_area_struct * area = zone->free_area + order; unsigned long curr_order = order, map_nr; @@ -297,7 +295,7 @@ static inline int balance_memory (zone_t *zone, int gfp_mask) return 1; } -struct page * __get_pages(zone_t *zone, unsigned int gfp_mask, +static inline struct page * __get_pages (zone_t *zone, unsigned int gfp_mask, unsigned long order) { struct page *page; @@ -345,27 +343,35 @@ nopage: return NULL; } -unsigned long __get_free_pages(int gfp_mask, unsigned long order) +static inline zone_t * gfp_mask_to_zone (int gfp_mask) { - struct page *page; zone_t *zone; - if (gfp_mask & __GFP_DMA) - zone = zones + ZONE_DMA; +#if CONFIG_HIGHMEM + if (gfp_mask & __GFP_HIGHMEM) + zone = zones + ZONE_HIGHMEM; else - zone = zones + ZONE_NORMAL; - page = __get_pages(zone, gfp_mask, order); - if (gfp_mask & __GFP_DMA) - if (!PageDMA(page)) - BUG(); +#endif + if (gfp_mask & __GFP_DMA) + zone = zones + ZONE_DMA; + else + zone = zones + ZONE_NORMAL; + return zone; +} + +unsigned long __get_free_pages (int gfp_mask, unsigned long order) +{ + struct page *page; + + page = __get_pages(gfp_mask_to_zone(gfp_mask), gfp_mask, order); if (!page) return 0; return page_address(page); } -struct page * get_free_highpage(int gfp_mask) +struct page * alloc_pages (int gfp_mask, unsigned long order) { - return __get_pages(zones + NR_ZONES-1, gfp_mask, 0); + return __get_pages(gfp_mask_to_zone(gfp_mask), gfp_mask, order); } /* @@ -410,10 +416,9 @@ unsigned int nr_free_highpages (void) */ void show_free_areas(void) { - unsigned long order, flags; + unsigned long order; unsigned type; - spin_lock_irqsave(&page_alloc_lock, flags); printk("Free pages: %6dkB (%6dkB HighMem)\n", nr_free_pages()<<(PAGE_SHIFT-10), nr_free_highpages()<<(PAGE_SHIFT-10)); @@ -444,7 +449,6 @@ void show_free_areas(void) } printk("= %lukB)\n", total); } - spin_unlock_irqrestore(&page_alloc_lock, flags); #ifdef SWAP_CACHE_INFO show_swap_cache_info(); diff --git a/mm/swapfile.c b/mm/swapfile.c index bc661dc2fc2c..c34a5316ac6b 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -25,7 +25,7 @@ struct swap_info_struct swap_info[MAX_SWAPFILES]; #define SWAPFILE_CLUSTER 256 -static inline int scan_swap_map(struct swap_info_struct *si) +static inline int scan_swap_map(struct swap_info_struct *si, unsigned short count) { unsigned long offset; /* @@ -73,7 +73,7 @@ static inline int scan_swap_map(struct swap_info_struct *si) si->lowest_bit++; if (offset == si->highest_bit) si->highest_bit--; - si->swap_map[offset] = 1; + si->swap_map[offset] = count; nr_swap_pages--; si->cluster_next = offset+1; return offset; @@ -81,7 +81,7 @@ static inline int scan_swap_map(struct swap_info_struct *si) return 0; } -swp_entry_t get_swap_page(void) +swp_entry_t __get_swap_page(unsigned short count) { struct swap_info_struct * p; unsigned long offset; @@ -94,11 +94,13 @@ swp_entry_t get_swap_page(void) goto out; if (nr_swap_pages == 0) goto out; + if (count >= SWAP_MAP_MAX) + goto bad_count; while (1) { p = &swap_info[type]; if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) { - offset = scan_swap_map(p); + offset = scan_swap_map(p, count); if (offset) { entry = SWP_ENTRY(type,offset); type = swap_info[type].next; @@ -123,10 +125,15 @@ swp_entry_t get_swap_page(void) } out: return entry; + +bad_count: + printk(KERN_ERR "get_swap_page: bad count %hd from %p\n", + count, __builtin_return_address(0)); + goto out; } -void swap_free(swp_entry_t entry) +void __swap_free(swp_entry_t entry, unsigned short count) { struct swap_info_struct * p; unsigned long offset, type; @@ -148,7 +155,9 @@ void swap_free(swp_entry_t entry) if (!p->swap_map[offset]) goto bad_free; if (p->swap_map[offset] < SWAP_MAP_MAX) { - if (!--p->swap_map[offset]) { + if (p->swap_map[offset] < count) + goto bad_count; + if (!(p->swap_map[offset] -= count)) { if (offset < p->lowest_bit) p->lowest_bit = offset; if (offset > p->highest_bit) @@ -171,6 +180,9 @@ bad_offset: bad_free: printk("VM: Bad swap entry %08lx\n", entry.val); goto out; +bad_count: + printk(KERN_ERR "VM: Bad count %hd current count %hd\n", count, p->swap_map[offset]); + goto out; } /* needs the big kernel lock */ diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 2c95bedaa9a0..310613cc4dbe 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -10,7 +10,7 @@ #include -static struct vm_struct * vmlist = NULL; +struct vm_struct * vmlist = NULL; static inline void free_area_pte(pmd_t * pmd, unsigned long address, unsigned long size) { @@ -97,7 +97,7 @@ static inline int alloc_area_pte(pte_t * pte, unsigned long address, unsigned lo struct page * page; if (!pte_none(*pte)) printk(KERN_ERR "alloc_area_pte: page already exists\n"); - page = get_free_highpage(GFP_KERNEL|__GFP_HIGHMEM); + page = alloc_page(GFP_KERNEL|__GFP_HIGHMEM); if (!page) return -ENOMEM; set_pte(pte, mk_pte(page, PAGE_KERNEL)); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 2f6bd37c9f9a..0472ba4f85b0 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1401,11 +1401,6 @@ static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th) tcp_send_ack(sk); - if (!sk->dead) { - wake_up_interruptible(sk->sleep); - sock_wake_async(sk->socket, 1, POLL_HUP); - } - switch(sk->state) { case TCP_SYN_RECV: case TCP_ESTABLISHED: @@ -1440,7 +1435,11 @@ static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th) */ printk("tcp_fin: Impossible, sk->state=%d\n", sk->state); break; - }; + } + if (!sk->dead) { + wake_up_interruptible(sk->sleep); + sock_wake_async(sk->socket, 1, POLL_HUP); + } } /* These routines update the SACK block as out-of-order packets arrive or diff --git a/net/irda/irmod.c b/net/irda/irmod.c index c04566e75c65..80c71d998858 100644 --- a/net/irda/irmod.c +++ b/net/irda/irmod.c @@ -525,24 +525,6 @@ void irda_mod_dec_use_count(void) #endif } -/* - * Function irda_proc_modcount (inode, fill) - * - * Use by the proc file system functions to prevent the irda module - * being removed while the use is standing in the net/irda directory - */ -void irda_proc_modcount(struct inode *inode, int fill) -{ -#ifdef MODULE -#ifdef CONFIG_PROC_FS - if (fill) - MOD_INC_USE_COUNT; - else - MOD_DEC_USE_COUNT; -#endif /* CONFIG_PROC_FS */ -#endif /* MODULE */ -} - #ifdef MODULE MODULE_AUTHOR("Dag Brattli "); diff --git a/net/irda/irproc.c b/net/irda/irproc.c index e19d1fe4c08e..820fbd275878 100644 --- a/net/irda/irproc.c +++ b/net/irda/irproc.c @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -70,9 +71,7 @@ void irda_proc_register(void) int i; proc_irda = create_proc_entry("net/irda", S_IFDIR, NULL); -#ifdef MODULE - proc_irda->fill_inode = &irda_proc_modcount; -#endif /* MODULE */ + proc_irda->owner = THIS_MODULE; for (i=0;ifill_inode = rpc_modcount; -#endif + ent->owner = THIS_MODULE; proc_net_rpc = ent; } } @@ -183,21 +181,6 @@ rpc_proc_exit(void) } #ifdef MODULE -/* - * This is called as the proc_dir_entry fill_inode function - * when an inode is going into or out of service (fill == 1 - * or 0 respectively). - * - * We use it here to keep the module from being unloaded - * while /proc inodes are in use. - */ -void rpc_modcount(struct inode *inode, int fill) -{ - if (fill) - MOD_INC_USE_COUNT; - else - MOD_DEC_USE_COUNT; -} int init_module(void) diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c index 03bedba709cc..7f588a1c6e11 100644 --- a/net/sunrpc/sysctl.c +++ b/net/sunrpc/sysctl.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -38,11 +39,9 @@ rpc_register_sysctl(void) { if (!sunrpc_table_header) { sunrpc_table_header = register_sysctl_table(sunrpc_table, 1); -#ifdef MODULE #ifdef CONFIG_PROC_FS if (sunrpc_table[0].de) - sunrpc_table[0].de->fill_inode = rpc_modcount; -#endif + sunrpc_table[0].de->owner = THIS_MODULE; #endif } diff --git a/scripts/usb/procusb b/scripts/usb/procusb new file mode 100644 index 000000000000..f88f35fcc751 --- /dev/null +++ b/scripts/usb/procusb @@ -0,0 +1,44 @@ +#!/usr/bin/perl + +# Reads /proc/bus/usb/devices and selectively lists and/or +# interprets it. + +$DEVFILENAME = "/proc/bus/usb/devices"; +$PROGNAME = $0; + +print "\n"; + +$TAGS = $ARGV[0]; # save user TAGS +if (length ($TAGS) == 0) +{ + print "usage: $PROGNAME tags\n"; + print " where 'tags' can be any number of 'TBDPCIE' or 'A(LL)'\n"; + exit 1; +} + +$ALL = ($TAGS =~ /all/i) || ($TAGS =~ /a/i); + +# TBD: Check that $TAGS is valid. +if (! $ALL) +{ +} + +if (! open (DEVNUM, "<$DEVFILENAME")) +{ + print "$PROGNAME: cannot open '$DEVFILENAME'\n"; + exit 1; +} + +while ($line = ) # read a text line from DEVNUM +{ + if (($ALL) || ($line =~ /^[$TAGS]:/i)) # any of TAGS at beg. of line? + { + print "$line"; # still has newline char on it + # TBD: add more/paging functionality. + } +} # end while DEVNUM + +close (DEVNUM); +print "\n"; + +# END. diff --git a/scripts/usb/usbtree b/scripts/usb/usbtree new file mode 100644 index 000000000000..54b9e64fd169 --- /dev/null +++ b/scripts/usb/usbtree @@ -0,0 +1,90 @@ +#!/usr/bin/perl + +# Reads /proc/bus/usb/devices and selectively lists and/or +# interprets it. + +$DEVFILENAME = "/proc/bus/usb/devices"; +$PROGNAME = $0; + +print "\n"; + +$TAGS = $ARGV[0]; # save user TAGS +if (length ($TAGS) == 0) +{ +} + +if (! open (DEVNUM, "<$DEVFILENAME")) +{ + print "$PROGNAME: cannot open '$DEVFILENAME'\n"; + exit 1; +} + +while ($line = ) # read a text line from DEVNUM +{ + # skip all lines except those that begin with "T:" or "D:" or "I:". + if (($line !~ "^T:") && ($line !~ "^I:") && ($line !~ "^D:")) + { + next; # to the next line + } + + chomp $line; # remove line endings + + # First convert '=' signs to spaces. + $line =~ tr/=/ /; + + # and convert all ( and ) to spaces. + $line =~ tr/(/ /; + $line =~ tr/)/ /; + + # split the line at spaces. + @fields = split / +/, $line; + + if ($line =~ "^T:") + { + # split yields: $level, $port, $devnum, $speed, $maxchild. + + $level = @fields [2]; + $port = @fields [6]; + $devnum = @fields [10]; + $speed = @fields [12]; + $maxchild = @fields [14]; + $devclass = "?"; + $intclass = "?"; + $driver = "?"; + + if (($devnum == -1) && ($level == 0)) + { + print "/: Dev# -1, root hub/$maxchild ports, $speed Mbps\n"; + } + next; + } # end T: line + elsif ($line =~ "^D:") + { # for D: line + $devclass = @fields [5]; + next; + } + else + { # for I: line + $intclass = @fields [9]; + $ifnum = @fields [2]; + $driver = @fields [15]; + } # end I: line + + if ($level > 1) + { + $temp = $level; + while ($temp > 1) + { + print " "; + $temp--; + } + } + + print sprintf ("|__ Port# $port: Dev# $devnum, If# $ifnum, Class=$devclass, Ifc=$intclass, Driver=$driver%s, $speed Mbps\n", + ($maxchild == 0) ? "" : ("/" . $maxchild . " ports")); +} # end while DEVNUM + +close (DEVNUM); +print "\n"; + +# END. -- 2.39.5