From d4598417b45e6c291b55eb41110b292ac7d25c64 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:39:48 -0500 Subject: [PATCH] =?utf8?q?-=20pre1:=20=20=20=20=20-=20Linus:=20make=20PCMC?= =?utf8?q?IA=20work=20even=20in=20the=20absense=20of=20PCI=20irq's=20=20?= =?utf8?q?=20=20=20-=20Linus:=20add=20irq=20mapping=20capabilities=20for?= =?utf8?q?=20Cyrix=20southbridges=20=20=20=20=20-=20Linus:=20make=20IBMMCA?= =?utf8?q?=20compile=20right=20as=20a=20module=20=20=20=20=20-=20Linus:=20?= =?utf8?q?uhhuh.=20Major=20atomic-PTE=20SMP=20race=20boo-boo.=20Fixed.=20?= =?utf8?q?=20=20=20=20-=20Andrea=20Arkangeli:=20don't=20allow=20people=20t?= =?utf8?q?o=20set=20security-conscious=20=20=20=20=20=20=20bits=20in=20mxc?= =?utf8?q?sr=20through=20ptrace=20SETFPXREGS.=20=20=20=20=20-=20J=C3=BCrge?= =?utf8?q?n=20Fischer:=20aha152x=20update=20=20=20=20=20-=20Andrew=20Morto?= =?utf8?q?n,=20Trond=20Myklebust:=20file=20locking=20fixes=20=20=20=20=20-?= =?utf8?q?=20Linus:=20TLB=20invalidate=20race=20with=20highmem=20=20=20=20?= =?utf8?q?=20-=20Paul=20Fulghum:=20synclink/n=5Fhdlc=20driver=20updates=20?= =?utf8?q?=20=20=20=20-=20David=20Miller:=20export=20sysctl=5Fjiffies,=20a?= =?utf8?q?nd=20have=20the=20proper=20no-sysctl=20=20=20=20=20=20=20version?= =?utf8?q?=20handy=20=20=20=20=20-=20Neil=20Brown:=20RAID=20driver=20deadl?= =?utf8?q?ock=20and=20nsfd=20read=20access=20to=20=20=20=20=20=20=20execut?= =?utf8?q?e-only=20files=20fix=20=20=20=20=20-=20Keith=20Owens:=20clean=20?= =?utf8?q?up=20module=20information=20passing,=20remove=20=20=20=20=20=20?= =?utf8?q?=20"get=5Fmodule=5Fsymbol()".=20=20=20=20=20-=20Jeff=20Garzik:?= =?utf8?q?=20network=20(and=20other)=20driver=20fixes=20and=20cleanups=20?= =?utf8?q?=20=20=20=20-=20Andrea=20Arkangeli:=20scheduler=20cleanup.=20=20?= =?utf8?q?=20=20=20-=20Ching-Ling=20Li:=20fix=20ALi=20sound=20driver=20mem?= =?utf8?q?ory=20leak=20=20=20=20=20-=20Anton=20Altaparmakov:=20upcase=20fi?= =?utf8?q?x=20for=20NTFS=20=20=20=20=20-=20Thomas=20Woller:=20CS4281=20aud?= =?utf8?q?io=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- CREDITS | 7 +- Documentation/kbuild/makefiles.txt | 6 + Documentation/networking/tulip.txt | 29 +- Makefile | 4 +- arch/i386/defconfig | 3 +- arch/i386/kernel/i387.c | 2 + arch/i386/kernel/pci-irq.c | 15 + arch/ppc/kernel/pci.c | 5 - arch/sparc/kernel/pcic.c | 17 - arch/sparc64/kernel/pci.c | 6 - drivers/acorn/net/etherh.c | 7 - drivers/char/agp/agp.h | 2 - drivers/char/agp/agpgart_be.c | 19 +- drivers/char/drm/agpsupport.c | 83 +- drivers/char/drm/drmP.h | 12 - drivers/char/drm/i810_drv.c | 4 +- drivers/char/drm/memory.c | 20 +- drivers/char/drm/mga_drv.c | 4 +- drivers/char/drm/r128_drv.c | 4 +- drivers/char/drm/tdfx_drv.c | 2 +- drivers/char/ftape/lowlevel/ftape-ctl.c | 21 +- drivers/char/n_hdlc.c | 196 +- drivers/char/rtc.c | 8 +- drivers/char/synclink.c | 603 ++--- drivers/ide/alim15x3.c | 2 +- drivers/ide/amd7409.c | 2 +- drivers/ide/hd.c | 2 +- drivers/ide/hpt366.c | 2 +- drivers/ide/icside.c | 8 +- drivers/ide/ide-pci.c | 5 +- drivers/ide/opti621.c | 2 +- drivers/ide/sis5513.c | 4 +- drivers/ide/sl82c105.c | 4 +- drivers/ide/via82cxxx.c | 2 +- drivers/md/raid1.c | 25 +- drivers/media/radio/radio-cadet.c | 62 +- drivers/mtd/Makefile | 2 +- drivers/mtd/cfi_cmdset_0001.c | 38 +- drivers/mtd/cfi_cmdset_0002.c | 31 +- drivers/mtd/cfi_probe.c | 44 +- drivers/mtd/doc2000.c | 23 +- drivers/mtd/doc2001.c | 21 +- drivers/mtd/docprobe.c | 45 +- drivers/mtd/map_ram.c | 30 +- drivers/net/3c503.c | 9 +- drivers/net/3c509.c | 7 + drivers/net/3c59x.c | 47 +- drivers/net/ac3200.c | 25 +- drivers/net/acenic.c | 4 +- drivers/net/aironet4500_card.c | 24 +- drivers/net/am79c961a.c | 6 +- drivers/net/apne.c | 15 +- drivers/net/appletalk/cops.c | 11 +- drivers/net/ariadne2.c | 12 +- drivers/net/arlan.c | 5 +- drivers/net/at1700.c | 49 +- drivers/net/atp.c | 12 +- drivers/net/bmac.c | 47 +- drivers/net/cs89x0.c | 4 +- drivers/net/e2100.c | 5 - drivers/net/es3210.c | 5 - drivers/net/fmv18x.c | 58 +- drivers/net/hp-plus.c | 5 - drivers/net/hp.c | 9 +- drivers/net/lne390.c | 5 - drivers/net/ne.c | 241 +- drivers/net/ne2k-pci.c | 186 +- drivers/net/ne3210.c | 65 +- drivers/net/oaknet.c | 18 +- drivers/net/pcmcia/xircom_tulip_cb.c | 4 +- drivers/net/pppoe.c | 4 +- drivers/net/seeq8005.c | 4 +- drivers/net/sis900.c | 105 +- drivers/net/smc-mca.c | 5 - drivers/net/smc-ultra.c | 5 - drivers/net/smc-ultra32.c | 5 - drivers/net/stnic.c | 7 +- drivers/net/tulip/21142.c | 2 +- drivers/net/tulip/ChangeLog | 29 + drivers/net/tulip/interrupt.c | 41 +- drivers/net/tulip/timer.c | 9 +- drivers/net/tulip/tulip.h | 6 +- drivers/net/tulip/tulip_core.c | 196 +- drivers/net/wd.c | 30 +- drivers/pci/pci.ids | 3 +- drivers/pcmcia/cs.c | 2 + drivers/pcmcia/yenta.c | 2 +- drivers/scsi/AM53C974.c | 69 +- drivers/scsi/AM53C974.h | 18 +- drivers/scsi/Config.in | 2 +- drivers/scsi/aha152x.c | 115 +- drivers/scsi/aha152x.h | 4 +- drivers/scsi/ibmmca.c | 4 - drivers/sound/cs4281.c | 3112 +++++++++++++++-------- drivers/sound/dmasound/dmasound.h | 1 - drivers/sound/dmasound/dmasound_atari.c | 5 +- drivers/sound/emu10k1/emu_wrapper.h | 4 +- drivers/sound/trident.c | 236 +- drivers/usb/acm.c | 2 +- drivers/usb/microtek.c | 1 + drivers/usb/pegasus.c | 90 +- drivers/video/S3triofb.c | 2 - drivers/video/amifb.c | 4 +- drivers/video/atafb.c | 4 +- drivers/video/clgenfb.c | 8 +- drivers/video/cyberfb.c | 4 +- drivers/video/fm2fb.c | 2 - drivers/video/g364fb.c | 2 - drivers/video/hpfb.c | 4 +- drivers/video/retz3fb.c | 4 +- drivers/video/tgafb.c | 4 +- drivers/video/vfb.c | 3 - drivers/video/virgefb.c | 4 +- fs/lockd/clntlock.c | 4 +- fs/lockd/clntproc.c | 4 - fs/lockd/svclock.c | 2 - fs/locks.c | 115 +- fs/nfsd/vfs.c | 2 + fs/ntfs/super.c | 2 +- fs/proc/proc_misc.c | 178 +- include/asm-alpha/module.h | 11 + include/asm-alpha/pgtable.h | 3 - include/asm-arm/module.h | 11 + include/asm-arm/pgtable.h | 3 - include/asm-i386/module.h | 11 + include/asm-i386/pgtable.h | 3 - include/asm-m68k/module.h | 11 + include/asm-m68k/pgtable.h | 3 - include/asm-mips/module.h | 11 + include/asm-mips/pgtable.h | 3 - include/asm-mips64/module.h | 11 + include/asm-mips64/pgtable.h | 3 - include/asm-ppc/module.h | 11 + include/asm-ppc/pgtable.h | 3 - include/asm-s390/module.h | 11 + include/asm-s390/pgtable.h | 3 - include/asm-sh/module.h | 11 + include/asm-sh/pgtable.h | 3 - include/asm-sparc/module.h | 11 + include/asm-sparc/pgtable.h | 2 - include/asm-sparc64/module.h | 11 + include/asm-sparc64/pgtable.h | 2 - include/linux/agp_backend.h | 19 + include/linux/fs.h | 1 - include/linux/module.h | 49 +- include/linux/mtd/cfi.h | 1 + include/linux/mtd/map.h | 17 +- include/linux/pci_ids.h | 5 + include/linux/synclink.h | 5 +- include/linux/wrapper.h | 7 - kernel/Makefile | 6 +- kernel/kmod.c | 23 +- kernel/ksyms.c | 20 +- kernel/module.c | 343 ++- kernel/sched.c | 7 +- kernel/sysctl.c | 11 +- mm/memory.c | 31 +- mm/vmscan.c | 3 +- 158 files changed, 4258 insertions(+), 3223 deletions(-) create mode 100644 drivers/net/tulip/ChangeLog create mode 100644 include/asm-alpha/module.h create mode 100644 include/asm-arm/module.h create mode 100644 include/asm-i386/module.h create mode 100644 include/asm-m68k/module.h create mode 100644 include/asm-mips/module.h create mode 100644 include/asm-mips64/module.h create mode 100644 include/asm-ppc/module.h create mode 100644 include/asm-s390/module.h create mode 100644 include/asm-sh/module.h create mode 100644 include/asm-sparc/module.h create mode 100644 include/asm-sparc64/module.h diff --git a/CREDITS b/CREDITS index ced88f564fab..db47eeb14042 100644 --- a/CREDITS +++ b/CREDITS @@ -1425,9 +1425,10 @@ D: bits and pieces of USB core code. N: Russell Kroll E: rkroll@exploits.org W: http://www.exploits.org/ -D: V4L Aztech radio card driver, mods to Aimslab driver -S: Post Office Box 49458 -S: Colorado Springs, Colorado 80949-9458 +D: V4L radio cards: radio-aztech (new), others (bugfixes/features) +D: Loopback block device: dynamic sizing ("max_loop" as module) +S: Post Office Box 691886 +S: San Antonio, Texas 78269-1886 S: USA N: Andrzej M. Krzysztofowicz diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index 13a663e3e1be..1b63892c61e2 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt @@ -640,6 +640,12 @@ The public interface of Rules.make consists of the following variables: but then you will notice a lot of extra compiles when you edit any source file. Blame CONFIG_MODVERSIONS for this.] + Data that is passed to other objects via registration functions + (e.g. pci_register_driver, pm_register) does not need to be marked + as EXPORT_SYMBOL. The objects that pass data via registration + functions do not need to be marked as OX_OBJS, unless they also have + exported symbols. + Rules.make compiles all the $(O_OBJS) and $(OX_OBJS) files. It then calls "$(LD) -r" to merge these files into one .o file with the name $(O_TARGET). This $(O_TARGET) name also appears diff --git a/Documentation/networking/tulip.txt b/Documentation/networking/tulip.txt index 5363811cb58c..bd104e11d840 100644 --- a/Documentation/networking/tulip.txt +++ b/Documentation/networking/tulip.txt @@ -1,20 +1,26 @@ Tulip Ethernet Card Driver Maintained by Jeff Garzik -The Tulip driver is developed by Donald Becker and changed by +The Tulip driver was developed by Donald Becker and changed by Takashi Manabe and a cast of thousands. +For 2.4.x and later kernels, the Linux Tulip driver is available at +http://sourceforge.net/projects/tulip/ + 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 + The author may be reached as becker@scyld.com, or C/O Center of Excellence in Space Data and Information Sciences Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - Additional information available at - http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html - + Additional information on Donald Becker's tulip.c + is available at http://www.scyld.com/network/tulip.html + + + + Theory of Operation Board Compatibility @@ -24,7 +30,7 @@ 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. +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 @@ -43,7 +49,7 @@ 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. +autonegotiation. Driver operation ================ @@ -142,6 +148,15 @@ tulip_core.c - Driver core (a.k.a. where "everything else" goes) Version history =============== +0.9.11 (November 3, 2000): +* Eliminate extra bus accesses when sharing interrupts (prumpf) +* Barrier following ownership descriptor bit flip (prumpf) +* Endianness fixes for >14 addresses in setup frames (prumpf) +* Report link beat to kernel/userspace via netif_carrier_*. (kuznet) +* Better spinlocking in set_rx_mode. +* Fix I/O resource request failure error messages (DaveM catch) +* Handle DMA allocation failure. + 0.9.10 (September 6, 2000): * Simple interrupt mitigation (via jamal) * More PCI ids diff --git a/Makefile b/Makefile index 63fc29da8366..ccd736426afb 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 0 -EXTRAVERSION = -test10 +EXTRAVERSION = -test11 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -206,7 +206,7 @@ vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs $(LIBS) \ --end-group \ -o vmlinux - $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map + $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map symlinks: rm -f include/asm diff --git a/arch/i386/defconfig b/arch/i386/defconfig index b22c770db525..c2e9c07bb055 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -143,11 +143,12 @@ CONFIG_PACKET=y # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set +CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set # CONFIG_IP_PNP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set diff --git a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c index c3d052e8a2e1..3031432d0194 100644 --- a/arch/i386/kernel/i387.c +++ b/arch/i386/kernel/i387.c @@ -442,6 +442,8 @@ int set_fpxregs( struct task_struct *tsk, struct user_fxsr_struct *buf ) if ( HAVE_FXSR ) { __copy_from_user( &tsk->thread.i387.fxsave, (void *)buf, sizeof(struct user_fxsr_struct) ); + /* mxcsr bit 6 and 31-16 must be zero for security reasons */ + tsk->thread.i387.fxsave.mxcsr &= 0xffbf; return 0; } else { return -EIO; diff --git a/arch/i386/kernel/pci-irq.c b/arch/i386/kernel/pci-irq.c index 9a5fe89580c5..bd3f3c96501d 100644 --- a/arch/i386/kernel/pci-irq.c +++ b/arch/i386/kernel/pci-irq.c @@ -265,6 +265,20 @@ static int pirq_opti_set(struct pci_dev *router, struct pci_dev *dev, int pirq, return 1; } +/* + * Cyrix: nibble offset 0x5C + */ +static int pirq_cyrix_get(struct pci_dev *router, struct pci_dev *dev, int pirq) +{ + return read_config_nybble(router, 0x5C, pirq-1); +} + +static int pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) +{ + write_config_nybble(router, 0x5C, pirq-1, irq); + return 1; +} + #ifdef CONFIG_PCI_BIOS static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) @@ -289,6 +303,7 @@ static struct irq_router pirq_routers[] = { { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, pirq_via_get, pirq_via_set }, { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, pirq_via_get, pirq_via_set }, { "OPTI", PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C700, pirq_opti_get, pirq_opti_set }, + { "NatSemi", PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, pirq_cyrix_get, pirq_cyrix_set }, { "default", 0, 0, NULL, NULL } }; diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index 84faa0e1df9e..6d6f775f22d8 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -344,11 +344,6 @@ pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ra ranges->mem_end -= bus->resource[1]->start; } -unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, - unsigned long start, unsigned long size) -{ - return start; -} void __init pcibios_fixup_bus(struct pci_bus *bus) { diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 028612687585..ba86e3d64bfc 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -866,23 +866,6 @@ void pcibios_update_resource(struct pci_dev *pdev, struct resource *res1, { } -#if 0 -void pcibios_update_irq(struct pci_dev *pdev, int irq) -{ -} - -unsigned long resource_fixup(struct pci_dev *pdev, struct resource *res, - unsigned long start, unsigned long size) -{ - return start; -} - -void pcibios_fixup_pbus_ranges(struct pci_bus *pbus, - struct pbus_set_ranges_data *pranges) -{ -} -#endif - void pcibios_align_resource(void *data, struct resource *res, unsigned long size) { } diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index dd153a24e5d9..626615da0015 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -202,12 +202,6 @@ void pcibios_update_irq(struct pci_dev *pdev, int irq) { } -unsigned long resource_fixup(struct pci_dev *pdev, struct resource *res, - unsigned long start, unsigned long size) -{ - return start; -} - void pcibios_fixup_pbus_ranges(struct pci_bus *pbus, struct pbus_set_ranges_data *pranges) { diff --git a/drivers/acorn/net/etherh.c b/drivers/acorn/net/etherh.c index bf84fca568d0..9c450549441e 100644 --- a/drivers/acorn/net/etherh.c +++ b/drivers/acorn/net/etherh.c @@ -622,9 +622,6 @@ static int __init etherh_init(void) { int i, ret = -ENODEV; - if (load_8390_module("etherh.c")) - return -ENOSYS; - ecard_startfind(); for (i = 0; i < MAX_ECARDS; i++) { @@ -644,9 +641,6 @@ static int __init etherh_init(void) ret = 0; } - if (ret) - unload_8390_module(); - return ret; } @@ -667,7 +661,6 @@ static void __exit etherh_exit(void) e_card[i] = NULL; } } - unload_8390_module(); } module_init(etherh_init); diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index acad5947acec..a054af74583b 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -144,8 +144,6 @@ struct agp_bridge_data { #define min(a,b) (((a)<(b))?(a):(b)) #endif -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - #define AGPGART_MODULE_NAME "agpgart" #define PFX AGPGART_MODULE_NAME ": " diff --git a/drivers/char/agp/agpgart_be.c b/drivers/char/agp/agpgart_be.c index 44bd3bfb471b..f114ab3cf4b2 100644 --- a/drivers/char/agp/agpgart_be.c +++ b/drivers/char/agp/agpgart_be.c @@ -2182,16 +2182,16 @@ static int __init agp_lookup_host_bridge (struct pci_dev *pdev) { int i; - for (i = 0; i < arraysize (agp_bridge_info); i++) + for (i = 0; i < ARRAY_SIZE (agp_bridge_info); i++) if (pdev->vendor == agp_bridge_info[i].vendor_id) break; - if (i >= arraysize (agp_bridge_info)) { + if (i >= ARRAY_SIZE (agp_bridge_info)) { printk (KERN_DEBUG PFX "unsupported bridge\n"); return -ENODEV; } - while ((i < arraysize (agp_bridge_info)) && + while ((i < ARRAY_SIZE (agp_bridge_info)) && (agp_bridge_info[i].vendor_id == pdev->vendor)) { if (pdev->device == agp_bridge_info[i].device_id) { printk (KERN_INFO PFX "Detected %s %s chipset\n", @@ -2490,6 +2490,17 @@ static void agp_backend_cleanup(void) extern int agp_frontend_initialize(void); extern void agp_frontend_cleanup(void); +static const drm_agp_t drm_agp = { + &agp_free_memory, + &agp_allocate_memory, + &agp_bind_memory, + &agp_unbind_memory, + &agp_enable, + &agp_backend_acquire, + &agp_backend_release, + &agp_copy_info +}; + static int __init agp_init(void) { int ret_val; @@ -2509,6 +2520,7 @@ static int __init agp_init(void) return ret_val; } + inter_module_register("drm_agp", THIS_MODULE, &drm_agp); return 0; } @@ -2516,6 +2528,7 @@ static void __exit agp_cleanup(void) { agp_frontend_cleanup(); agp_backend_cleanup(); + inter_module_unregister("drm_agp"); } module_init(agp_init); diff --git a/drivers/char/drm/agpsupport.c b/drivers/char/drm/agpsupport.c index 24fd59cdfe42..ef7e252b584e 100644 --- a/drivers/char/drm/agpsupport.c +++ b/drivers/char/drm/agpsupport.c @@ -32,47 +32,7 @@ #include "drmP.h" #include -drm_agp_func_t drm_agp = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; - -/* The C standard says that 'void *' is not guaranteed to hold a function - pointer, so we use this union to define a generic pointer that is - guaranteed to hold any of the function pointers we care about. */ -typedef union { - void (*free_memory)(agp_memory *); - agp_memory *(*allocate_memory)(size_t, u32); - int (*bind_memory)(agp_memory *, off_t); - int (*unbind_memory)(agp_memory *); - void (*enable)(u32); - int (*acquire)(void); - void (*release)(void); - void (*copy_info)(agp_kern_info *); - unsigned long address; -} drm_agp_func_u; - -typedef struct drm_agp_fill { - const char *name; - drm_agp_func_u *f; -} drm_agp_fill_t; - -static drm_agp_fill_t drm_agp_fill[] = { - { __MODULE_STRING(agp_free_memory), - (drm_agp_func_u *)&drm_agp.free_memory }, - { __MODULE_STRING(agp_allocate_memory), - (drm_agp_func_u *)&drm_agp.allocate_memory }, - { __MODULE_STRING(agp_bind_memory), - (drm_agp_func_u *)&drm_agp.bind_memory }, - { __MODULE_STRING(agp_unbind_memory), - (drm_agp_func_u *)&drm_agp.unbind_memory }, - { __MODULE_STRING(agp_enable), - (drm_agp_func_u *)&drm_agp.enable }, - { __MODULE_STRING(agp_backend_acquire), - (drm_agp_func_u *)&drm_agp.acquire }, - { __MODULE_STRING(agp_backend_release), - (drm_agp_func_u *)&drm_agp.release }, - { __MODULE_STRING(agp_copy_info), - (drm_agp_func_u *)&drm_agp.copy_info }, - { NULL, NULL } -}; +const drm_agp_t *drm_agp_p; int drm_agp_info(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) @@ -82,7 +42,7 @@ int drm_agp_info(struct inode *inode, struct file *filp, unsigned int cmd, agp_kern_info *kern; drm_agp_info_t info; - if (!dev->agp->acquired || !drm_agp.copy_info) return -EINVAL; + if (!dev->agp->acquired || !(drm_agp_p->copy_info)) return -EINVAL; kern = &dev->agp->agp_info; info.agp_version_major = kern->version.major; @@ -107,8 +67,8 @@ int drm_agp_acquire(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; int retcode; - if (dev->agp->acquired || !drm_agp.acquire) return -EINVAL; - if ((retcode = (*drm_agp.acquire)())) return retcode; + if (dev->agp->acquired || !(drm_agp_p->acquire)) return -EINVAL; + if ((retcode = (*(drm_agp_p->acquire))())) return retcode; dev->agp->acquired = 1; return 0; } @@ -119,8 +79,8 @@ int drm_agp_release(struct inode *inode, struct file *filp, unsigned int cmd, drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - if (!dev->agp->acquired || !drm_agp.release) return -EINVAL; - (*drm_agp.release)(); + if (!dev->agp->acquired || !(drm_agp_p->release)) return -EINVAL; + (*(drm_agp_p->release))(); dev->agp->acquired = 0; return 0; @@ -133,13 +93,13 @@ int drm_agp_enable(struct inode *inode, struct file *filp, unsigned int cmd, drm_device_t *dev = priv->dev; drm_agp_mode_t mode; - if (!dev->agp->acquired || !drm_agp.enable) return -EINVAL; + if (!dev->agp->acquired || !(drm_agp_p->enable)) return -EINVAL; if (copy_from_user(&mode, (drm_agp_mode_t *)arg, sizeof(mode))) return -EFAULT; dev->agp->mode = mode.mode; - (*drm_agp.enable)(mode.mode); + (*(drm_agp_p->enable))(mode.mode); dev->agp->base = dev->agp->agp_info.aper_base; dev->agp->enabled = 1; return 0; @@ -231,7 +191,7 @@ int drm_agp_bind(struct inode *inode, struct file *filp, unsigned int cmd, int retcode; int page; - if (!dev->agp->acquired || !drm_agp.bind_memory) return -EINVAL; + if (!dev->agp->acquired || !(drm_agp_p->bind_memory)) return -EINVAL; if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request))) return -EFAULT; if (!(entry = drm_agp_lookup_entry(dev, request.handle))) @@ -270,24 +230,16 @@ int drm_agp_free(struct inode *inode, struct file *filp, unsigned int cmd, drm_agp_head_t *drm_agp_init(void) { - drm_agp_fill_t *fill; drm_agp_head_t *head = NULL; - int agp_available = 1; - for (fill = &drm_agp_fill[0]; fill->name; fill++) { - char *n = (char *)fill->name; - *fill->f = (drm_agp_func_u)get_module_symbol(NULL, n); - DRM_DEBUG("%s resolves to 0x%08lx\n", n, (*fill->f).address); - if (!(*fill->f).address) agp_available = 0; - } - - DRM_DEBUG("agp_available = %d\n", agp_available); + drm_agp_p = (drm_agp_t *)inter_module_get("drm_agp"); + DRM_DEBUG("drm_agp_p = %p\n", drm_agp_p); - if (agp_available) { + if (drm_agp_p) { if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS))) return NULL; memset((void *)head, 0, sizeof(*head)); - (*drm_agp.copy_info)(&head->agp_info); + (*(drm_agp_p->copy_info))(&head->agp_info); if (head->agp_info.chipset == NOT_SUPPORTED) { drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS); return NULL; @@ -337,12 +289,5 @@ drm_agp_head_t *drm_agp_init(void) void drm_agp_uninit(void) { - drm_agp_fill_t *fill; - - for (fill = &drm_agp_fill[0]; fill->name; fill++) { -#if LINUX_VERSION_CODE >= 0x020400 - if ((*fill->f).address) put_module_symbol((*fill->f).address); -#endif - (*fill->f).address = 0; - } + inter_module_put("drm_agp"); } diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 6be90c51624e..28001c3814e5 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -511,18 +511,6 @@ typedef struct drm_agp_head { int agp_mtrr; } drm_agp_head_t; -typedef struct { - void (*free_memory)(agp_memory *); - agp_memory *(*allocate_memory)(size_t, u32); - int (*bind_memory)(agp_memory *, off_t); - int (*unbind_memory)(agp_memory *); - void (*enable)(u32); - int (*acquire)(void); - void (*release)(void); - void (*copy_info)(agp_kern_info *); -} drm_agp_func_t; - -extern drm_agp_func_t drm_agp; #endif typedef struct drm_sigdata { diff --git a/drivers/char/drm/i810_drv.c b/drivers/char/drm/i810_drv.c index ed880c41a203..42f9cbbc7963 100644 --- a/drivers/char/drm/i810_drv.c +++ b/drivers/char/drm/i810_drv.c @@ -255,8 +255,8 @@ static int i810_takedown(drm_device_t *dev) } dev->agp->memory = NULL; - if (dev->agp->acquired && drm_agp.release) - (*drm_agp.release)(); + if (dev->agp->acquired && drm_agp_p->release) + (*(drm_agp_p->release))(); dev->agp->acquired = 0; dev->agp->enabled = 0; diff --git a/drivers/char/drm/memory.c b/drivers/char/drm/memory.c index 34d19b203665..4a8cb8b5c738 100644 --- a/drivers/char/drm/memory.c +++ b/drivers/char/drm/memory.c @@ -352,8 +352,8 @@ agp_memory *drm_alloc_agp(int pages, u32 type) return NULL; } - if (drm_agp.allocate_memory) { - if ((handle = (*drm_agp.allocate_memory)(pages, + if (drm_agp_p->allocate_memory) { + if ((handle = (*(drm_agp_p->allocate_memory))(pages, type))) { spin_lock(&drm_mem_lock); ++drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count; @@ -381,8 +381,8 @@ int drm_free_agp(agp_memory *handle, int pages) return retval;; } - if (drm_agp.free_memory) { - (*drm_agp.free_memory)(handle); + if (drm_agp_p->free_memory) { + (*(drm_agp_p->free_memory))(handle); spin_lock(&drm_mem_lock); free_count = ++drm_mem_stats[DRM_MEM_TOTALAGP].free_count; alloc_count = drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count; @@ -410,15 +410,15 @@ int drm_bind_agp(agp_memory *handle, unsigned int start) return retcode; } - DRM_DEBUG("drm_agp.bind_memory : %p\n", drm_agp.bind_memory); - if (drm_agp.bind_memory) { - if (!(retcode = (*drm_agp.bind_memory)(handle, start))) { + DRM_DEBUG("drm_agp_p->bind_memory : %p\n", drm_agp_p->bind_memory); + if (drm_agp_p->bind_memory) { + if (!(retcode = (*(drm_agp_p->bind_memory))(handle, start))) { spin_lock(&drm_mem_lock); ++drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count; drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_allocated += handle->page_count << PAGE_SHIFT; spin_unlock(&drm_mem_lock); - DRM_DEBUG("drm_agp.bind_memory: retcode %d\n", retcode); + DRM_DEBUG("drm_agp_p->bind_memory: retcode %d\n", retcode); return retcode; } } @@ -440,9 +440,9 @@ int drm_unbind_agp(agp_memory *handle) return retcode; } - if (drm_agp.unbind_memory) { + if (drm_agp_p->unbind_memory) { int c = handle->page_count; - if ((retcode = (*drm_agp.unbind_memory)(handle))) + if ((retcode = (*(drm_agp_p->unbind_memory))(handle))) return retcode; spin_lock(&drm_mem_lock); free_count = ++drm_mem_stats[DRM_MEM_BOUNDAGP].free_count; diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c index 4aaac62542b1..f6a38d2ff234 100644 --- a/drivers/char/drm/mga_drv.c +++ b/drivers/char/drm/mga_drv.c @@ -255,8 +255,8 @@ static int mga_takedown(drm_device_t *dev) } dev->agp->memory = NULL; - if (dev->agp->acquired && drm_agp.release) - (*drm_agp.release)(); + if (dev->agp->acquired && drm_agp_p->release) + (*(drm_agp_p->release))(); dev->agp->acquired = 0; dev->agp->enabled = 0; diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c index 7ae4980143f6..bbef428df356 100644 --- a/drivers/char/drm/r128_drv.c +++ b/drivers/char/drm/r128_drv.c @@ -252,8 +252,8 @@ static int r128_takedown(drm_device_t *dev) } dev->agp->memory = NULL; - if (dev->agp->acquired && drm_agp.release) - (*drm_agp.release)(); + if (dev->agp->acquired && drm_agp_p->release) + (*(drm_agp_p->release))(); dev->agp->acquired = 0; dev->agp->enabled = 0; diff --git a/drivers/char/drm/tdfx_drv.c b/drivers/char/drm/tdfx_drv.c index 5f2c804af4d0..1a90610b7d9f 100644 --- a/drivers/char/drm/tdfx_drv.c +++ b/drivers/char/drm/tdfx_drv.c @@ -235,7 +235,7 @@ static int tdfx_takedown(drm_device_t *dev) drm_free(temp, sizeof(*temp), DRM_MEM_AGPLISTS); temp = temp_next; } - if (dev->agp->acquired) (*drm_agp.release)(); + if (dev->agp->acquired) (*(drm_agp_p->release))(); } #endif /* Clear vma list (only built for debugging) */ diff --git a/drivers/char/ftape/lowlevel/ftape-ctl.c b/drivers/char/ftape/lowlevel/ftape-ctl.c index 4196458d0bd8..6c1ef5235053 100644 --- a/drivers/char/ftape/lowlevel/ftape-ctl.c +++ b/drivers/char/ftape/lowlevel/ftape-ctl.c @@ -40,6 +40,9 @@ #endif #include +/* ease porting between pre-2.4.x and later kernels */ +#define vma_get_pgoff(v) ((v)->vm_pgoff) + #include "../lowlevel/ftape-tracing.h" #include "../lowlevel/ftape-io.h" #include "../lowlevel/ftape-ctl.h" @@ -701,23 +704,23 @@ int ftape_mmap(struct vm_area_struct *vma) if (ft_failure) { TRACE_EXIT -ENODEV; } - if ((vma_get_flags(vma) & (VM_READ|VM_WRITE)) == 0) { + if (!(vma->vm_flags & (VM_READ|VM_WRITE))) { TRACE_ABORT(-EINVAL, ft_t_err, "Undefined mmap() access"); } if (vma_get_pgoff(vma) != 0) { TRACE_ABORT(-EINVAL, ft_t_err, "page offset must be 0"); } - if ((vma_get_end (vma) - vma_get_start (vma)) % FT_BUFF_SIZE != 0) { + if ((vma->vm_end - vma->vm_start) % FT_BUFF_SIZE != 0) { TRACE_ABORT(-EINVAL, ft_t_err, "size = %ld, should be a multiple of %d", - vma_get_end (vma) - vma_get_start (vma), + vma->vm_end - vma->vm_start, FT_BUFF_SIZE); } - num_buffers = (vma_get_end (vma) - vma_get_start (vma)) / FT_BUFF_SIZE; + num_buffers = (vma->vm_end - vma->vm_start) / FT_BUFF_SIZE; if (num_buffers > ft_nr_buffers) { TRACE_ABORT(-EINVAL, ft_t_err, "size = %ld, should be less than %d", - vma_get_end (vma) - vma_get_start (vma), + vma->vm_end - vma->vm_start, ft_nr_buffers * FT_BUFF_SIZE); } if (ft_driver_state != idle) { @@ -728,15 +731,15 @@ int ftape_mmap(struct vm_area_struct *vma) ftape_reset_buffer(); } for (i = 0; i < num_buffers; i++) { - TRACE_CATCH(remap_page_range(vma_get_start (vma) + + TRACE_CATCH(remap_page_range(vma->vm_start + i * FT_BUFF_SIZE, - virt_to_phys(ft_buffer[i]->address), + virt_to_phys(ft_buffer[i]->address), FT_BUFF_SIZE, - vma_get_page_prot (vma)), + vma->vm_page_prot), _res = -EAGAIN); TRACE(ft_t_noise, "remapped dma buffer @ %p to location @ %p", ft_buffer[i]->address, - (void *)(vma_get_start(vma) + i * FT_BUFF_SIZE)); + (void *)(vma->vm_start + i * FT_BUFF_SIZE)); } for (i = 0; i < num_buffers; i++) { memset(ft_buffer[i]->address, 0xAA, FT_BUFF_SIZE); diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index e9585bcaa70b..3427c1421e31 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c @@ -9,7 +9,7 @@ * Al Longyear , Paul Mackerras * * Original release 01/11/99 - * ==FILEDATE 20000706== + * $Id: n_hdlc.c,v 3.2 2000/11/06 22:34:38 paul Exp $ * * This code is released under the GNU General Public License (GPL) * @@ -78,11 +78,12 @@ */ #define HDLC_MAGIC 0x239e -#define HDLC_VERSION "1.16" +#define HDLC_VERSION "3.2" #include #include #include +#include #include #include #include @@ -93,14 +94,7 @@ #undef VERSION #define VERSION(major,minor,patch) (((((major)<<8)+(minor))<<8)+(patch)) -#if LINUX_VERSION_CODE < VERSION(2,1,14) -#include -#endif - -#if LINUX_VERSION_CODE >= VERSION(2,1,23) #include -#endif - #include #include #include @@ -118,86 +112,16 @@ #include #endif -#if LINUX_VERSION_CODE < VERSION(2,3,0) -typedef struct wait_queue *wait_queue_head_t; -#define DECLARE_WAITQUEUE(name,task) struct wait_queue (name) = {(task),NULL} -#define init_waitqueue_head(head) *(head) = NULL -#define set_current_state(a) current->state = (a) -#endif - -#if LINUX_VERSION_CODE >= VERSION(2,1,4) #include #define GET_USER(error,value,addr) error = get_user(value,addr) #define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0 #define PUT_USER(error,value,addr) error = put_user(value,addr) #define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0 -#if LINUX_VERSION_CODE >= VERSION(2,1,5) #include -#endif - -#else /* 2.0.x and 2.1.x before 2.1.4 */ - -#define GET_USER(error,value,addr) \ -do { \ - error = verify_area (VERIFY_READ, (void *) addr, sizeof (value)); \ - if (error == 0) \ - value = get_user(addr); \ -} while (0) - -#define COPY_FROM_USER(error,dest,src,size) \ -do { \ - error = verify_area (VERIFY_READ, (void *) src, size); \ - if (error == 0) \ - memcpy_fromfs (dest, src, size); \ -} while (0) - -#define PUT_USER(error,value,addr) \ -do { \ - error = verify_area (VERIFY_WRITE, (void *) addr, sizeof (value)); \ - if (error == 0) \ - put_user (value, addr); \ -} while (0) - -#define COPY_TO_USER(error,dest,src,size) \ -do { \ - error = verify_area (VERIFY_WRITE, (void *) dest, size); \ - if (error == 0) \ - memcpy_tofs (dest, src, size); \ -} while (0) - -#endif -#if LINUX_VERSION_CODE < VERSION(2,1,0) -#define __init -typedef int spinlock_t; -#define spin_lock_init(a) -#define spin_lock_irqsave(a,b) {save_flags((b));cli();} -#define spin_unlock_irqrestore(a,b) {restore_flags((b));} -#define spin_lock(a) -#define spin_unlock(a) -#define schedule_timeout(a){current->timeout = jiffies + (a); schedule();} -#endif - -#if LINUX_VERSION_CODE < VERSION(2,1,37) -#define test_and_set_bit(nr, addr) set_bit(nr, addr) -#endif - -#if LINUX_VERSION_CODE < VERSION(2,1,57) -#define signal_pending(p) ((p)->signal & ~(p)->blocked) -#endif - -#if LINUX_VERSION_CODE < VERSION(2,1,25) -#define net_device_stats enet_statistics -#endif - -#if LINUX_VERSION_CODE < VERSION(2,1,60) -typedef int rw_ret_t; -typedef unsigned int rw_count_t; -#else typedef ssize_t rw_ret_t; typedef size_t rw_count_t; -#endif /* * Buffers for individual HDLC frames @@ -261,10 +185,9 @@ N_HDLC_BUF* n_hdlc_buf_get(N_HDLC_BUF_LIST *list); static struct n_hdlc *n_hdlc_alloc (void); -#if LINUX_VERSION_CODE >= VERSION(2,1,19) MODULE_PARM(debuglevel, "i"); MODULE_PARM(maxframe, "i"); -#endif + /* debug level can be set by insmod for debugging purposes */ #define DEBUG_LEVEL_INFO 1 @@ -281,13 +204,8 @@ static rw_ret_t n_hdlc_tty_write(struct tty_struct *, struct file *, const __u8 *, rw_count_t); static int n_hdlc_tty_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long); -#if LINUX_VERSION_CODE < VERSION(2,1,23) -static int n_hdlc_tty_select (struct tty_struct *tty, struct inode *inode, - struct file *filp, int sel_type, select_table * wait); -#else static unsigned int n_hdlc_tty_poll (struct tty_struct *tty, struct file *filp, poll_table * wait); -#endif static int n_hdlc_tty_open (struct tty_struct *); static void n_hdlc_tty_close (struct tty_struct *); static int n_hdlc_tty_room (struct tty_struct *tty); @@ -660,11 +578,8 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, wake_up_interruptible (&n_hdlc->read_wait); wake_up_interruptible (&n_hdlc->poll_wait); if (n_hdlc->tty->fasync != NULL) -#if LINUX_VERSION_CODE < VERSION(2,3,0) - kill_fasync (n_hdlc->tty->fasync, SIGIO); -#else kill_fasync (&n_hdlc->tty->fasync, SIGIO, POLL_IN); -#endif + } /* end of n_hdlc_tty_receive() */ /* n_hdlc_tty_read() @@ -893,73 +808,6 @@ static int n_hdlc_tty_ioctl (struct tty_struct *tty, struct file * file, } /* end of n_hdlc_tty_ioctl() */ -#if LINUX_VERSION_CODE < VERSION(2,1,23) -/* n_hdlc_tty_select() - * - * Device select method. Determine if operation requires - * blocking and if so put appropriate wait queue in select - * table and return 0, otherwise return 1. - * - * Arguments: - * - * tty pointer to tty device instance data - * inode pointer to inode for device - * filp pointer to file object - * sel_type identified the select type (read/write/exception) - * wait select table for adding wait queue if appropriate - * - * Return Value: - * - * 1 if no need to block on operation - * 0 if must block and wait queue added to select table - */ -static int n_hdlc_tty_select (struct tty_struct *tty, struct inode *inode, - struct file *filp, int sel_type, select_table * wait) -{ - struct n_hdlc *n_hdlc = tty2n_hdlc(tty); - int result = 1; - - if (debuglevel >= DEBUG_LEVEL_INFO) - printk("%s(%d)n_hdlc_tty_select() called\n",__FILE__,__LINE__); - - /* Verify the status of the device */ - if (!n_hdlc) - return -EBADF; - - if (n_hdlc->magic != HDLC_MAGIC || tty != n_hdlc->tty) - return -EBADF; - - switch (sel_type) { - case SEL_IN: - if (n_hdlc->rx_buf_list.head) - break; - - case SEL_EX: /* Exceptions or read errors */ - /* Is this a pty link and the remote disconnected? */ - if (tty->flags & (1 << TTY_OTHER_CLOSED)) - break; - - /* Is this a local link and the modem disconnected? */ - if (tty_hung_up_p (filp)) - break; - - select_wait (&n_hdlc->read_wait, wait); - result = 0; - break; - - /* Write mode. A write is allowed if there is no current transmission */ - case SEL_OUT: - if (!n_hdlc->tx_free_buf_list.head) { - select_wait (&n_hdlc->write_wait, wait); - result = 0; - } - break; - } - return result; -} /* end of n_hdlc_tty_select() */ - -#else /* 2.1.23 or later */ - /* n_hdlc_tty_poll() * * TTY callback for poll system call. Determine which @@ -988,11 +836,8 @@ static unsigned int n_hdlc_tty_poll (struct tty_struct *tty, if (n_hdlc && n_hdlc->magic == HDLC_MAGIC && tty == n_hdlc->tty) { /* queue current process into any wait queue that */ /* may awaken in the future (read and write) */ -#if LINUX_VERSION_CODE < VERSION(2,1,89) - poll_wait(&n_hdlc->poll_wait, wait); -#else poll_wait(filp, &n_hdlc->poll_wait, wait); -#endif + /* set bits for operations that wont block */ if(n_hdlc->rx_buf_list.head) mask |= POLLIN | POLLRDNORM; /* readable */ @@ -1006,8 +851,6 @@ static unsigned int n_hdlc_tty_poll (struct tty_struct *tty, return mask; } /* end of n_hdlc_tty_poll() */ -#endif - /* n_hdlc_alloc() * * Allocate an n_hdlc instance data structure @@ -1135,14 +978,7 @@ N_HDLC_BUF* n_hdlc_buf_get(N_HDLC_BUF_LIST *list) } /* end of n_hdlc_buf_get() */ -/* init_module() - * - * called when module is loading to register line discipline - * - * Arguments: None - * Return Value: 0 if success, otherwise error code - */ -int init_module(void) +static int __init n_hdlc_init(void) { static struct tty_ldisc n_hdlc_ldisc; int status; @@ -1160,19 +996,13 @@ int init_module(void) memset(&n_hdlc_ldisc, 0, sizeof (n_hdlc_ldisc)); n_hdlc_ldisc.magic = TTY_LDISC_MAGIC; -#if LINUX_VERSION_CODE >= VERSION(2,1,28) n_hdlc_ldisc.name = "hdlc"; -#endif n_hdlc_ldisc.open = n_hdlc_tty_open; n_hdlc_ldisc.close = n_hdlc_tty_close; n_hdlc_ldisc.read = n_hdlc_tty_read; n_hdlc_ldisc.write = n_hdlc_tty_write; n_hdlc_ldisc.ioctl = n_hdlc_tty_ioctl; -#if LINUX_VERSION_CODE < VERSION(2,1,23) - n_hdlc_ldisc.select = n_hdlc_tty_select; -#else n_hdlc_ldisc.poll = n_hdlc_tty_poll; -#endif n_hdlc_ldisc.receive_room = n_hdlc_tty_room; n_hdlc_ldisc.receive_buf = n_hdlc_tty_receive; n_hdlc_ldisc.write_wakeup = n_hdlc_tty_wakeup; @@ -1189,14 +1019,7 @@ int init_module(void) } /* end of init_module() */ -/* cleanup_module() - * - * called when module is unloading to unregister line discipline - * - * Arguments: None - * Return Value: None - */ -void cleanup_module(void) +static void __exit n_hdlc_exit(void) { int status; /* Release tty registration of line discipline */ @@ -1205,3 +1028,6 @@ void cleanup_module(void) else printk("N_HDLC: line discipline unregistered\n"); } + +module_init(n_hdlc_init); +module_exit(n_hdlc_exit); diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 7f7431a8a0cf..029f5df658e0 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -634,7 +634,7 @@ static int __init rtc_init(void) } } } - printk("rtc_init: no PC rtc found\n"); + printk(KERN_ERR "rtc_init: no PC rtc found\n"); return -EIO; found: @@ -650,7 +650,7 @@ found: * Standard way for sparc to print irq's is to use * __irq_itoa(). I think for EBus it's ok to use %d. */ - printk("rtc: cannot register IRQ %d\n", rtc_irq); + printk(KERN_ERR "rtc: cannot register IRQ %d\n", rtc_irq); return -EIO; } #else @@ -705,7 +705,7 @@ found: guess = "Digital DECstation"; } if (guess) - printk("rtc: %s epoch (%lu) detected\n", guess, epoch); + printk(KERN_INFO "rtc: %s epoch (%lu) detected\n", guess, epoch); #endif #if RTC_IRQ init_timer(&rtc_irq_timer); @@ -772,7 +772,7 @@ static void rtc_dropped_irq(unsigned long data) spin_unlock_irq(&rtc_lock); - printk(KERN_INFO "rtc: lost some interrupts at %ldHz.\n", freq); + printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq); /* Now we have new data */ wake_up_interruptible(&rtc_wait); diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 6da32381efb4..156c683e4d5e 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -1,7 +1,7 @@ /* * linux/drivers/char/synclink.c * - * ==FILEDATE 20000707== + * $Id: synclink.c,v 3.2 2000/11/06 22:34:38 paul Exp $ * * Device driver for Microgate SyncLink ISA and PCI * high speed multiprotocol serial adapters. @@ -82,13 +82,9 @@ #include -#if LINUX_VERSION_CODE >= VERSION(2,1,0) #include #include #include -#else -#include -#endif #include #include @@ -102,98 +98,21 @@ #include #include -#if LINUX_VERSION_CODE < VERSION(2,3,0) -typedef struct wait_queue *wait_queue_head_t; -#define DECLARE_WAITQUEUE(name,task) struct wait_queue (name) = {(task),NULL} -#define init_waitqueue_head(head) *(head) = NULL -#define DECLARE_MUTEX(name) struct semaphore (name) = MUTEX -#define set_current_state(a) current->state = (a) -#endif - #ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE #define CONFIG_SYNCLINK_SYNCPPP 1 #endif #ifdef CONFIG_SYNCLINK_SYNCPPP -#if LINUX_VERSION_CODE < VERSION(2,3,43) -#include "../net/syncppp.h" -#define net_device device -#define netif_stop_queue(a) (a)->tbusy = 1 -#define netif_start_queue(a) (a)->tbusy = 0 -#define netif_wake_queue(a) (a)->tbusy = 0; mark_bh(NET_BH) -#define netif_queue_stopped(a) ((a)->tbusy) -#else #include "../net/wan/syncppp.h" #endif -#endif -#if LINUX_VERSION_CODE >= VERSION(2,1,4) #include #define GET_USER(error,value,addr) error = get_user(value,addr) #define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0 #define PUT_USER(error,value,addr) error = put_user(value,addr) #define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0 -#if LINUX_VERSION_CODE >= VERSION(2,1,5) #include -#endif - -#else /* 2.0.x and 2.1.x before 2.1.4 */ - -#define GET_USER(error,value,addr) \ -do { \ - error = verify_area (VERIFY_READ, (void *) addr, sizeof (value)); \ - if (error == 0) \ - value = get_user(addr); \ -} while (0) - -#define COPY_FROM_USER(error,dest,src,size) \ -do { \ - error = verify_area (VERIFY_READ, (void *) src, size); \ - if (error == 0) \ - memcpy_fromfs (dest, src, size); \ -} while (0) - -#define PUT_USER(error,value,addr) \ -do { \ - error = verify_area (VERIFY_WRITE, (void *) addr, sizeof (value)); \ - if (error == 0) \ - put_user (value, addr); \ -} while (0) - -#define COPY_TO_USER(error,dest,src,size) \ -do { \ - error = verify_area (VERIFY_WRITE, (void *) dest, size); \ - if (error == 0) \ - memcpy_tofs (dest, src, size); \ -} while (0) - -#endif - -#if LINUX_VERSION_CODE < VERSION(2,1,0) -/* - * This is used to figure out the divisor speeds and the timeouts - */ -static int baud_table[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 }; - -#define __init -#define ioremap(a,b) vremap((a),(b)) -#define iounmap(a) vfree((a)) -#define SERIAL_TYPE_NORMAL 1 -#define SERIAL_TYPE_CALLOUT 2 -typedef int spinlock_t; -#define spin_lock_init(a) -#define spin_lock_irqsave(a,b) {save_flags((b));cli();} -#define spin_unlock_irqrestore(a,b) {restore_flags((b));} -#define spin_lock(a) -#define spin_unlock(a) -#define schedule_timeout(a){current->timeout = jiffies + (a); schedule();} -#define signal_pending(a) ((a)->signal & ~(a)->blocked) -#endif - - #include "linux/synclink.h" @@ -365,10 +284,12 @@ struct mgsl_struct { u32 last_mem_alloc; unsigned char* memory_base; /* shared memory address (PCI only) */ u32 phys_memory_base; + int shared_mem_requested; unsigned char* lcr_base; /* local config registers (PCI only) */ u32 phys_lcr_base; u32 lcr_offset; + int lcr_mem_requested; u32 misc_ctrl_value; char flag_buf[MAX_ASYNC_BUFFER_SIZE]; @@ -389,10 +310,8 @@ struct mgsl_struct { char netname[10]; struct net_device *netdev; struct net_device_stats netstats; -#if LINUX_VERSION_CODE >= VERSION(2,2,16) struct net_device netdevice; #endif -#endif }; #define MGSL_MAGIC 0x5401 @@ -845,7 +764,7 @@ int mgsl_claim_resources(struct mgsl_struct *info); void mgsl_release_resources(struct mgsl_struct *info); void mgsl_add_device(struct mgsl_struct *info); struct mgsl_struct* mgsl_allocate_device(void); -int mgsl_enumerate_devices(void); +int mgsl_enum_isa_devices(void); /* * DMA buffer manupulation functions. @@ -952,7 +871,6 @@ static int debug_level = 0; static int maxframe[MAX_TOTAL_DEVICES] = {0,}; static int dosyncppp[MAX_TOTAL_DEVICES] = {0,}; -#if LINUX_VERSION_CODE >= VERSION(2,1,0) MODULE_PARM(break_on_load,"i"); MODULE_PARM(ttymajor,"i"); MODULE_PARM(cuamajor,"i"); @@ -962,10 +880,26 @@ MODULE_PARM(dma,"1-" __MODULE_STRING(MAX_ISA_DEVICES) "i"); MODULE_PARM(debug_level,"i"); MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i"); MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i"); -#endif static char *driver_name = "SyncLink serial driver"; -static char *driver_version = "1.21"; +static char *driver_version = "3.2"; + +static int __init synclink_init_one (struct pci_dev *dev, + const struct pci_device_id *ent); +static void __exit synclink_remove_one (struct pci_dev *dev); + +static struct pci_device_id synclink_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_MICROGATE, PCI_DEVICE_ID_MICROGATE_USC, PCI_ANY_ID, PCI_ANY_ID, }, + { 0, }, /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, synclink_pci_tbl); + +static struct pci_driver synclink_pci_driver = { + name: "synclink", + id_table: synclink_pci_tbl, + probe: synclink_init_one, + remove: synclink_remove_one, +}; static struct tty_driver serial_driver, callout_driver; static int serial_refcount; @@ -977,9 +911,9 @@ static int serial_refcount; static void mgsl_change_params(struct mgsl_struct *info); static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout); -static struct tty_struct **serial_table = NULL; -static struct termios **serial_termios = NULL; -static struct termios **serial_termios_locked = NULL; +static struct tty_struct *serial_table[MAX_TOTAL_DEVICES]; +static struct termios *serial_termios[MAX_TOTAL_DEVICES]; +static struct termios *serial_termios_locked[MAX_TOTAL_DEVICES]; #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) @@ -1591,16 +1525,9 @@ void mgsl_isr_receive_data( struct mgsl_struct *info ) icount->parity,icount->frame,icount->overrun); } - if ( tty->flip.count ) { -#if LINUX_VERSION_CODE >= VERSION(2,1,0) + if ( tty->flip.count ) tty_flip_buffer_push(tty); -#else - queue_task(&tty->flip.tqueue, &tq_timer); -#endif - } - - -} /* end of mgsl_isr_receive_data() */ +} /* mgsl_isr_misc() * @@ -1795,11 +1722,7 @@ static int startup(struct mgsl_struct * info) retval = mgsl_adapter_test(info); if ( retval ) { -#if LINUX_VERSION_CODE >= VERSION(2,1,0) if (capable(CAP_SYS_ADMIN) && info->tty) -#else - if (suser() && info->tty) -#endif set_bit(TTY_IO_ERROR, &info->tty->flags); mgsl_release_resources(info); return retval; @@ -1974,21 +1897,8 @@ static void mgsl_change_params(struct mgsl_struct *info) * allow tty settings to override, otherwise keep the * current data rate. */ - if (info->params.data_rate <= 460800) { -#if LINUX_VERSION_CODE >= VERSION(2,1,0) + if (info->params.data_rate <= 460800) info->params.data_rate = tty_get_baud_rate(info->tty); -#else - int i = cflag & CBAUD; - if (i & CBAUDEX) { - i &= ~CBAUDEX; - if (i < 1 || i > 4) - info->tty->termios->c_cflag &= ~CBAUDEX; - else - i += 15; - } - info->params.data_rate = baud_table[i]; -#endif - } if ( info->params.data_rate ) { info->timeout = (32*HZ*bits_per_char) / @@ -2950,7 +2860,6 @@ static int set_modem_info(struct mgsl_struct * info, unsigned int cmd, } /* end of set_modem_info() */ -#if LINUX_VERSION_CODE >= VERSION(2,1,0) /* mgsl_break() Set or clear transmit break condition * * Arguments: tty pointer to tty instance data @@ -2977,7 +2886,6 @@ static void mgsl_break(struct tty_struct *tty, int break_state) spin_unlock_irqrestore(&info->irq_spinlock,flags); } /* end of mgsl_break() */ -#endif /* mgsl_ioctl() Service an IOCTL request * @@ -3100,7 +3008,6 @@ int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long if (error) return error; PUT_USER(error,cnow.dcd, &p_cuser->dcd); if (error) return error; -#if LINUX_VERSION_CODE >= VERSION(2,1,0) PUT_USER(error,cnow.rx, &p_cuser->rx); if (error) return error; PUT_USER(error,cnow.tx, &p_cuser->tx); @@ -3115,7 +3022,6 @@ int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long if (error) return error; PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun); if (error) return error; -#endif return 0; default: return -ENOIOCTLCMD; @@ -3596,9 +3502,7 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp) tmp_buf = (unsigned char *) page; } -#if LINUX_VERSION_CODE >= VERSION(2,1,0) info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; -#endif spin_lock_irqsave(&info->netlock, flags); if (info->netcount) { @@ -3985,22 +3889,14 @@ int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) } /* end of mgsl_alloc_buffer_list_memory() */ -/* - * mgsl_free_buffer_list_memory() - * - * Free the common DMA buffer allocated for use as the - * receive and transmit buffer lists. The associated Memory - * Descriptor List (MDL) is also freed. - * +/* Free DMA buffers allocated for use as the + * receive and transmit buffer lists. * Warning: * * The data transfer buffers associated with the buffer list * MUST be freed before freeing the buffer list itself because * the buffer list contains the information necessary to free * the individual buffers! - * - * Arguments: info pointer to device extension - * Return Value: None */ void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) { @@ -4138,67 +4034,61 @@ int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info) void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info) { if ( info->intermediate_rxbuffer ) - kfree( info->intermediate_rxbuffer ); + kfree(info->intermediate_rxbuffer); info->intermediate_rxbuffer = NULL; } /* end of mgsl_free_intermediate_rxbuffer_memory() */ -/* mgsl_claim_resources() - * - * Claim all resources used by a device - * - * Arguments: info pointer to device instance data - * Return Value: 0 if success, otherwise -ENODEV - */ int mgsl_claim_resources(struct mgsl_struct *info) { - /* claim 16C32 I/O base address */ - - if ( check_region(info->io_base,info->io_addr_size) < 0 ) { + if (request_region(info->io_base,info->io_addr_size,"synclink") == NULL) { printk( "%s(%d):I/O address conflict on device %s Addr=%08X\n", - __FILE__,__LINE__,info->device_name, info->io_base ); + __FILE__,__LINE__,info->device_name, info->io_base); return -ENODEV; } - request_region(info->io_base,info->io_addr_size,"synclink.o"); info->io_addr_requested = 1; - /* claim interrupt level */ - if ( request_irq(info->irq_level,mgsl_interrupt,info->irq_flags, info->device_name, info ) < 0 ) { printk( "%s(%d):Cant request interrupt on device %s IRQ=%d\n", __FILE__,__LINE__,info->device_name, info->irq_level ); - mgsl_release_resources( info ); - return -ENODEV; + goto errout; } info->irq_requested = 1; if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - /* claim shared memory range */ + if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) { + printk( "%s(%d):mem addr conflict device %s Addr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_memory_base); + goto errout; + } + info->shared_mem_requested = 1; + if (request_mem_region(info->phys_lcr_base,128,"synclink") == NULL) { + printk( "%s(%d):lcr mem addr conflict device %s Addr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_lcr_base); + goto errout; + } + info->lcr_mem_requested = 1; + info->memory_base = ioremap(info->phys_memory_base,0x40000); if (!info->memory_base) { printk( "%s(%d):Cant map shared memory on device %s MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_memory_base ); - mgsl_release_resources( info ); - return -ENODEV; + goto errout; } - /* test the shared memory range */ if ( !mgsl_memory_test(info) ) { printk( "%s(%d):Failed shared memory test %s MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_memory_base ); - mgsl_release_resources( info ); - return -ENODEV; + goto errout; } - /* claim LCR memory range */ info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE) + info->lcr_offset; if (!info->lcr_base) { printk( "%s(%d):Cant map LCR memory on device %s MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_lcr_base ); - mgsl_release_resources( info ); - return -ENODEV; + goto errout; } } else { @@ -4220,21 +4110,16 @@ int mgsl_claim_resources(struct mgsl_struct *info) if ( mgsl_allocate_dma_buffers(info) < 0 ) { printk( "%s(%d):Cant allocate DMA buffers on device %s DMA=%d\n", __FILE__,__LINE__,info->device_name, info->dma_level ); - mgsl_release_resources( info ); - return -ENODEV; + goto errout; } return 0; - +errout: + mgsl_release_resources(info); + return ENODEV; + } /* end of mgsl_claim_resources() */ -/* mgsl_release_resources() - * - * Release all resources used by a device - * - * Arguments: info pointer to device instance data - * Return Value: None - */ void mgsl_release_resources(struct mgsl_struct *info) { if ( debug_level >= DEBUG_LEVEL_INFO ) @@ -4245,7 +4130,6 @@ void mgsl_release_resources(struct mgsl_struct *info) free_irq(info->irq_level, info); info->irq_requested = 0; } - if ( info->dma_requested ) { disable_dma(info->dma_level); free_dma(info->dma_level); @@ -4258,12 +4142,18 @@ void mgsl_release_resources(struct mgsl_struct *info) release_region(info->io_base,info->io_addr_size); info->io_addr_requested = 0; } - + if ( info->shared_mem_requested ) { + release_mem_region(info->phys_memory_base,0x40000); + info->shared_mem_requested = 0; + } + if ( info->lcr_mem_requested ) { + release_mem_region(info->phys_lcr_base,128); + info->lcr_mem_requested = 0; + } if (info->memory_base){ iounmap(info->memory_base); info->memory_base = 0; } - if (info->lcr_base){ iounmap(info->lcr_base - info->lcr_offset); info->lcr_base = 0; @@ -4367,210 +4257,23 @@ struct mgsl_struct* mgsl_allocate_device() } /* end of mgsl_allocate_device()*/ -/* mgsl_enumerate_devices() - * - * Enumerate SyncLink serial devices based on user specified - * options for ISA adapters and autodetected PCI adapters. - * - * Arguments: None - * Return Value: 0 if success, otherwise error code - */ -int mgsl_enumerate_devices() -{ - struct mgsl_struct *info; - int i; - - /* Check for user specified ISA devices */ - - for (i=0 ;(i < MAX_ISA_DEVICES) && io[i] && irq[i]; i++){ - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk("ISA device specified io=%04X,irq=%d,dma=%d\n", - io[i], irq[i], dma[i] ); - - info = mgsl_allocate_device(); - if ( !info ) { - /* error allocating device instance data */ - if ( debug_level >= DEBUG_LEVEL_ERROR ) - printk( "can't allocate device instance data.\n"); - continue; - } - - /* Copy user configuration info to device instance data */ - info->io_base = (unsigned int)io[i]; - info->irq_level = (unsigned int)irq[i]; -#if LINUX_VERSION_CODE >= VERSION(2,1,0) - info->irq_level = irq_cannonicalize(info->irq_level); -#else - if (info->irq_level == 2) - info->irq_level = 9; -#endif - info->dma_level = (unsigned int)dma[i]; - info->bus_type = MGSL_BUS_TYPE_ISA; - info->io_addr_size = 16; - info->irq_flags = 0; - - mgsl_add_device( info ); - } - - -#ifdef CONFIG_PCI - /* Auto detect PCI adapters */ - - if ( pcibios_present() ) { - unsigned char bus; - unsigned char func; - unsigned int shared_mem_base; - unsigned int lcr_mem_base; - unsigned int io_base; - unsigned char irq_line; - - for(i=0;;i++){ - if ( PCIBIOS_SUCCESSFUL == pcibios_find_device( - MICROGATE_VENDOR_ID, SYNCLINK_DEVICE_ID, i, &bus, &func) ) { - -#if LINUX_VERSION_CODE >= VERSION(2,1,0) - struct pci_dev *pdev = pci_find_slot(bus,func); - irq_line = pdev->irq; -#else - if (pcibios_read_config_byte(bus,func, - PCI_INTERRUPT_LINE,&irq_line) ) { - printk( "%s(%d):USC I/O addr not set.\n", - __FILE__,__LINE__); - continue; - } -#endif - - if (pcibios_read_config_dword(bus,func, - PCI_BASE_ADDRESS_3,&shared_mem_base) ) { - printk( "%s(%d):Shared mem addr not set.\n", - __FILE__,__LINE__); - continue; - } - - if (pcibios_read_config_dword(bus,func, - PCI_BASE_ADDRESS_0,&lcr_mem_base) ) { - printk( "%s(%d):LCR mem addr not set.\n", - __FILE__,__LINE__); - continue; - } - - if (pcibios_read_config_dword(bus,func, - PCI_BASE_ADDRESS_2,&io_base) ) { - printk( "%s(%d):USC I/O addr not set.\n", - __FILE__,__LINE__); - continue; - } - - info = mgsl_allocate_device(); - if ( !info ) { - /* error allocating device instance data */ - if ( debug_level >= DEBUG_LEVEL_ERROR ) - printk( "can't allocate device instance data.\n"); - continue; - } - - /* Copy user configuration info to device instance data */ - - info->io_base = io_base & PCI_BASE_ADDRESS_IO_MASK; - info->irq_level = (unsigned int)irq_line; -#if LINUX_VERSION_CODE >= VERSION(2,1,0) - info->irq_level = irq_cannonicalize(info->irq_level); -#else - if (info->irq_level == 2) - info->irq_level = 9; -#endif - info->phys_memory_base = shared_mem_base & PCI_BASE_ADDRESS_MEM_MASK; - - /* Because veremap only works on page boundaries we must map - * a larger area than is actually implemented for the LCR - * memory range. We map a full page starting at the page boundary. - */ - info->phys_lcr_base = lcr_mem_base & PCI_BASE_ADDRESS_MEM_MASK; - info->lcr_offset = info->phys_lcr_base & (PAGE_SIZE-1); - info->phys_lcr_base &= ~(PAGE_SIZE-1); - - info->bus_type = MGSL_BUS_TYPE_PCI; - info->io_addr_size = 8; - info->irq_flags = SA_SHIRQ; - info->bus = bus; - info->function = func; - - /* Store the PCI9050 misc control register value because a flaw - * in the PCI9050 prevents LCR registers from being read if - * BIOS assigns an LCR base address with bit 7 set. - * - * Only the misc control register is accessed for which only - * write access is needed, so set an initial value and change - * bits to the device instance data as we write the value - * to the actual misc control register. - */ - info->misc_ctrl_value = 0x087e4546; - - /* add new device to device list */ - mgsl_add_device( info ); - } else { - break; - } - } - } -#endif - - /* - * Allocate memory to hold the following tty/termios arrays - * with an element for each enumerated device. - */ - - serial_table = (struct tty_struct**)kmalloc(sizeof(struct tty_struct*)*mgsl_device_count, GFP_KERNEL); - serial_termios = (struct termios**)kmalloc(sizeof(struct termios*)*mgsl_device_count, GFP_KERNEL); - serial_termios_locked = (struct termios**)kmalloc(sizeof(struct termios*)*mgsl_device_count, GFP_KERNEL); - - if (!serial_table || !serial_termios || !serial_termios_locked){ - printk("%s(%d):Can't allocate tty/termios arrays.\n", - __FILE__,__LINE__); - return -ENOMEM; - } - - memset(serial_table,0,sizeof(struct tty_struct*)*mgsl_device_count); - memset(serial_termios,0,sizeof(struct termios*)*mgsl_device_count); - memset(serial_termios_locked,0,sizeof(struct termios*)*mgsl_device_count); - - return 0; - -} /* end of mgsl_enumerate_devices() */ - -/* mgsl_init() - * - * Driver initialization entry point. - * - * Arguments: None - * Return Value: 0 if success, otherwise error code +/* + * perform tty device initialization */ -int __init mgsl_init(void) +int mgsl_init_tty(void); +int mgsl_init_tty() { struct mgsl_struct *info; -#if LINUX_VERSION_CODE >= VERSION(2,1,0) - EXPORT_NO_SYMBOLS; -#else - register_symtab(NULL); -#endif - - printk("%s version %s\n", driver_name, driver_version); - - /* determine how many SyncLink devices are installed */ - mgsl_enumerate_devices(); - if ( !mgsl_device_list ) { - printk("%s(%d):No SyncLink devices found.\n",__FILE__,__LINE__); - return -ENODEV; - } + memset(serial_table,0,sizeof(struct tty_struct*)*MAX_TOTAL_DEVICES); + memset(serial_termios,0,sizeof(struct termios*)*MAX_TOTAL_DEVICES); + memset(serial_termios_locked,0,sizeof(struct termios*)*MAX_TOTAL_DEVICES); /* Initialize the tty_driver structure */ memset(&serial_driver, 0, sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; -#if LINUX_VERSION_CODE >= VERSION(2,1,0) serial_driver.driver_name = "synclink"; -#endif serial_driver.name = "ttySL"; serial_driver.major = ttymajor; serial_driver.minor_start = 64; @@ -4597,12 +4300,10 @@ int __init mgsl_init(void) serial_driver.ioctl = mgsl_ioctl; serial_driver.throttle = mgsl_throttle; serial_driver.unthrottle = mgsl_unthrottle; -#if LINUX_VERSION_CODE >= VERSION(2,1,0) serial_driver.send_xchar = mgsl_send_xchar; serial_driver.break_ctl = mgsl_break; serial_driver.wait_until_sent = mgsl_wait_until_sent; serial_driver.read_proc = mgsl_read_proc; -#endif serial_driver.set_termios = mgsl_set_termios; serial_driver.stop = mgsl_stop; serial_driver.start = mgsl_start; @@ -4616,10 +4317,8 @@ int __init mgsl_init(void) callout_driver.name = "cuaSL"; callout_driver.major = cuamajor; callout_driver.subtype = SERIAL_TYPE_CALLOUT; -#if LINUX_VERSION_CODE >= VERSION(2,1,0) callout_driver.read_proc = 0; callout_driver.proc_entry = 0; -#endif if (tty_register_driver(&serial_driver) < 0) printk("%s(%d):Couldn't register serial driver\n", @@ -4641,13 +4340,76 @@ int __init mgsl_init(void) info->normal_termios = serial_driver.init_termios; info = info->next_device; } + + return 0; +} + +/* enumerate user specified ISA adapters + */ +int mgsl_enum_isa_devices() +{ + struct mgsl_struct *info; + int i; + + /* Check for user specified ISA devices */ + + for (i=0 ;(i < MAX_ISA_DEVICES) && io[i] && irq[i]; i++){ + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk("ISA device specified io=%04X,irq=%d,dma=%d\n", + io[i], irq[i], dma[i] ); + + info = mgsl_allocate_device(); + if ( !info ) { + /* error allocating device instance data */ + if ( debug_level >= DEBUG_LEVEL_ERROR ) + printk( "can't allocate device instance data.\n"); + continue; + } + + /* Copy user configuration info to device instance data */ + info->io_base = (unsigned int)io[i]; + info->irq_level = (unsigned int)irq[i]; + info->irq_level = irq_cannonicalize(info->irq_level); + info->dma_level = (unsigned int)dma[i]; + info->bus_type = MGSL_BUS_TYPE_ISA; + info->io_addr_size = 16; + info->irq_flags = 0; + + mgsl_add_device( info ); + } return 0; +} + +/* mgsl_init() + * + * Driver initialization entry point. + * + * Arguments: None + * Return Value: 0 if success, otherwise error code + */ +int __init mgsl_init(void) +{ + int rc; + + EXPORT_NO_SYMBOLS; + + printk("%s version %s\n", driver_name, driver_version); -} /* end of mgsl_init() */ + mgsl_enum_isa_devices(); + pci_register_driver(&synclink_pci_driver); -#ifdef MODULE -int init_module(void) + if ( !mgsl_device_list ) { + printk("%s(%d):No SyncLink devices found.\n",__FILE__,__LINE__); + return -ENODEV; + } + if ((rc = mgsl_init_tty())) + return rc; + + return 0; +} + +static int __init synclink_init(void) { /* Uncomment this to kernel debug module. * mgsl_get_text_ptr() leaves the .text address in eax @@ -4661,7 +4423,7 @@ int init_module(void) return mgsl_init(); } -void cleanup_module(void) +static void __exit synclink_exit(void) { unsigned long flags; int rc; @@ -4693,19 +4455,11 @@ void cleanup_module(void) tmp_buf = NULL; } - if (serial_table) - kfree(serial_table); - - if (serial_termios) - kfree(serial_termios); - - if (serial_termios_locked) - kfree(serial_termios_locked); - -} /* end of cleanup_module() */ - -#endif /* MODULE */ + pci_unregister_driver(&synclink_pci_driver); +} +module_init(synclink_init); +module_exit(synclink_exit); /* * usc_RTCmd() @@ -6953,7 +6707,6 @@ BOOLEAN mgsl_irq_test( struct mgsl_struct *info ) while( EndTime-- && !info->irq_occurred ) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(jiffies_from_ms(10)); - set_current_state(TASK_RUNNING); } spin_lock_irqsave(&info->irq_spinlock,flags); @@ -7567,16 +7320,13 @@ void mgsl_sppp_init(struct mgsl_struct *info) sprintf(info->netname,"mgsl%d",info->line); -#if LINUX_VERSION_CODE < VERSION(2,2,16) - info->netdev = &info->pppdev.dev; -#else info->if_ptr = &info->pppdev; info->netdev = info->pppdev.dev = &info->netdevice; -#endif + sppp_attach(&info->pppdev); d = info->netdev; - strcpy(d->name, info->netname); + strcpy(d->name,info->netname); d->base_addr = info->io_base; d->irq = info->irq_level; d->dma = info->dma_level; @@ -7587,10 +7337,9 @@ void mgsl_sppp_init(struct mgsl_struct *info) d->hard_start_xmit = mgsl_sppp_tx; d->do_ioctl = mgsl_sppp_ioctl; d->get_stats = mgsl_net_stats; -#if LINUX_VERSION_CODE >= VERSION(2,3,43) d->tx_timeout = mgsl_sppp_tx_timeout; d->watchdog_timeo = 10*HZ; -#endif + dev_init_buffers(d); if (register_netdev(d) == -1) { @@ -7680,17 +7429,7 @@ int mgsl_sppp_tx(struct sk_buff *skb, struct net_device *dev) if (debug_level >= DEBUG_LEVEL_INFO) printk("mgsl_sppp_tx(%s)\n",info->netname); -#if LINUX_VERSION_CODE < VERSION(2,3,43) - if (dev->tbusy) { - if (time_before(jiffies, dev->trans_start+10*HZ)) - return -EBUSY; /* 10 seconds timeout */ - mgsl_sppp_tx_timeout(dev); - } - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) - return -EBUSY; -#else netif_stop_queue(dev); -#endif info->xmit_cnt = skb->len; mgsl_load_tx_dma_buffer(info, skb->data, skb->len); @@ -7777,3 +7516,57 @@ int mgsl_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) } #endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */ + +static int __init synclink_init_one (struct pci_dev *dev, + const struct pci_device_id *ent) +{ + struct mgsl_struct *info; + + if (pci_enable_device(dev)) { + printk("error enabling pci device %p\n", dev); + return -EIO; + } + + if (!(info = mgsl_allocate_device())) { + printk("can't allocate device instance data.\n"); + return -EIO; + } + + /* Copy user configuration info to device instance data */ + + info->io_base = pci_resource_start(dev, 2); + info->irq_level = dev->irq; + info->phys_memory_base = pci_resource_start(dev, 3); + + /* Because veremap only works on page boundaries we must map + * a larger area than is actually implemented for the LCR + * memory range. We map a full page starting at the page boundary. + */ + info->phys_lcr_base = pci_resource_start(dev, 0); + info->lcr_offset = info->phys_lcr_base & (PAGE_SIZE-1); + info->phys_lcr_base &= ~(PAGE_SIZE-1); + + info->bus_type = MGSL_BUS_TYPE_PCI; + info->io_addr_size = 8; + info->irq_flags = SA_SHIRQ; + + /* Store the PCI9050 misc control register value because a flaw + * in the PCI9050 prevents LCR registers from being read if + * BIOS assigns an LCR base address with bit 7 set. + * + * Only the misc control register is accessed for which only + * write access is needed, so set an initial value and change + * bits to the device instance data as we write the value + * to the actual misc control register. + */ + info->misc_ctrl_value = 0x087e4546; + + mgsl_add_device(info); + + return 0; +} + +static void __exit synclink_remove_one (struct pci_dev *dev) +{ +} + diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c index 813aecd3b46e..abf08c5a0b36 100644 --- a/drivers/ide/alim15x3.c +++ b/drivers/ide/alim15x3.c @@ -691,7 +691,7 @@ void __init ide_init_ali15x3 (ide_hwif_t *hwif) } } -void ide_dmacapable_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase) +void __init ide_dmacapable_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase) { if ((dmabase) && (m5229_revision < 0x20)) { return; diff --git a/drivers/ide/amd7409.c b/drivers/ide/amd7409.c index ca23d3af4563..d03f63b9fb38 100644 --- a/drivers/ide/amd7409.c +++ b/drivers/ide/amd7409.c @@ -464,7 +464,7 @@ void __init ide_init_amd7409 (ide_hwif_t *hwif) #endif /* CONFIG_BLK_DEV_IDEDMA */ } -void ide_dmacapable_amd7409 (ide_hwif_t *hwif, unsigned long dmabase) +void __init ide_dmacapable_amd7409 (ide_hwif_t *hwif, unsigned long dmabase) { ide_setup_dma(hwif, dmabase, 8); } diff --git a/drivers/ide/hd.c b/drivers/ide/hd.c index 698112b3503f..ca3a5c72bffb 100644 --- a/drivers/ide/hd.c +++ b/drivers/ide/hd.c @@ -723,7 +723,7 @@ static struct block_device_operations hd_fops = { * We enable interrupts in some of the routines after making sure it's * safe. */ -static void hd_geninit(void) +static void __init hd_geninit(void) { int drive; diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c index 270cacc61fcd..abd6d8ac75e7 100644 --- a/drivers/ide/hpt366.c +++ b/drivers/ide/hpt366.c @@ -698,7 +698,7 @@ void __init ide_init_hpt366 (ide_hwif_t *hwif) #endif /* CONFIG_BLK_DEV_IDEDMA */ } -void ide_dmacapable_hpt366 (ide_hwif_t *hwif, unsigned long dmabase) +void __init ide_dmacapable_hpt366 (ide_hwif_t *hwif, unsigned long dmabase) { byte masterdma = 0, slavedma = 0; byte dma_new = 0, dma_old = inb(dmabase+2); diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c index fb15adc4db3a..c727cb889bc2 100644 --- a/drivers/ide/icside.c +++ b/drivers/ide/icside.c @@ -163,7 +163,7 @@ static const expansioncard_ops_t icside_ops_arcin_v6 = { * Purpose : identify IDE interface type * Notes : checks the description string */ -static iftype_t icside_identifyif (struct expansion_card *ec) +static iftype_t __init icside_identifyif (struct expansion_card *ec) { unsigned int addr; iftype_t iftype; @@ -505,7 +505,7 @@ icside_setup(unsigned long base, struct cardinfo *info, int irq) return hwif; } -static int icside_register_v5(struct expansion_card *ec, int autodma) +static int __init icside_register_v5(struct expansion_card *ec, int autodma) { unsigned long slot_port; ide_hwif_t *hwif; @@ -527,7 +527,7 @@ static int icside_register_v5(struct expansion_card *ec, int autodma) return hwif ? 0 : -1; } -static int icside_register_v6(struct expansion_card *ec, int autodma) +static int __init icside_register_v6(struct expansion_card *ec, int autodma) { unsigned long slot_port, port; ide_hwif_t *hwif, *mate; @@ -585,7 +585,7 @@ no_dma: return hwif || mate ? 0 : -1; } -int icside_init(void) +int __init icside_init(void) { int autodma = 0; diff --git a/drivers/ide/ide-pci.c b/drivers/ide/ide-pci.c index f1304a4a0619..6e99442fa4ac 100644 --- a/drivers/ide/ide-pci.c +++ b/drivers/ide/ide-pci.c @@ -528,10 +528,7 @@ static void __init ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t * autodma = 1; #endif -#if 1 /* what do do with this useful tool ??? */ - if (pci_enable_device(dev)) - return; -#endif + pci_enable_device(dev); check_if_enabled: if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) { diff --git a/drivers/ide/opti621.c b/drivers/ide/opti621.c index f11c41d99b95..1e1b57f26bb4 100644 --- a/drivers/ide/opti621.c +++ b/drivers/ide/opti621.c @@ -308,7 +308,7 @@ static void opti621_tune_drive (ide_drive_t *drive, byte pio) /* * ide_init_opti621() is called once for each hwif found at boot. */ -void ide_init_opti621 (ide_hwif_t *hwif) +void __init ide_init_opti621 (ide_hwif_t *hwif) { hwif->drives[0].drive_data = PIO_DONT_KNOW; hwif->drives[1].drive_data = PIO_DONT_KNOW; diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c index c00f3305a23a..571cae56377a 100644 --- a/drivers/ide/sis5513.c +++ b/drivers/ide/sis5513.c @@ -33,8 +33,6 @@ static struct pci_dev *host_dev = NULL; -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - #define SIS5513_FLAG_ATA_00 0x00000000 #define SIS5513_FLAG_ATA_16 0x00000001 #define SIS5513_FLAG_ATA_33 0x00000002 @@ -545,7 +543,7 @@ unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name) pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency); - for (i = 0; i < arraysize (SiSHostChipInfo) && !host_dev; i++) { + for (i = 0; i < ARRAY_SIZE (SiSHostChipInfo) && !host_dev; i++) { host = pci_find_device (PCI_VENDOR_ID_SI, SiSHostChipInfo[i].host_id, NULL); diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c index c58c612ed5c2..2451e801d1e2 100644 --- a/drivers/ide/sl82c105.c +++ b/drivers/ide/sl82c105.c @@ -91,7 +91,7 @@ static void tune_sl82c105(ide_drive_t *drive, byte pio) } #endif -void ide_dmacapable_sl82c105(ide_hwif_t *hwif, unsigned long dmabase) +void __init ide_dmacapable_sl82c105(ide_hwif_t *hwif, unsigned long dmabase) { unsigned char rev; @@ -107,7 +107,7 @@ void ide_dmacapable_sl82c105(ide_hwif_t *hwif, unsigned long dmabase) ide_setup_dma(hwif, dmabase, 8); } -void ide_init_sl82c105(ide_hwif_t *hwif) +void __init ide_init_sl82c105(ide_hwif_t *hwif) { struct pci_dev *dev = hwif->pci_dev; diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c index 566dcc4d5f81..3ea1e261ece4 100644 --- a/drivers/ide/via82cxxx.c +++ b/drivers/ide/via82cxxx.c @@ -611,7 +611,7 @@ void __init ide_init_via82cxxx(ide_hwif_t *hwif) * We allow the BM-DMA driver only work on enabled interfaces. */ -void ide_dmacapable_via82cxxx(ide_hwif_t *hwif, unsigned long dmabase) +void __init ide_dmacapable_via82cxxx(ide_hwif_t *hwif, unsigned long dmabase) { if ((via_enabled >> hwif->channel) & 1) ide_setup_dma(hwif, dmabase, 8); diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index b39c87e0e797..3f68a8e0a455 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -91,7 +91,8 @@ static struct buffer_head *raid1_alloc_bh(raid1_conf_t *conf, int cnt) static inline void raid1_free_bh(raid1_conf_t *conf, struct buffer_head *bh) { - md_spin_lock_irq(&conf->device_lock); + unsigned long flags; + spin_lock_irqsave(&conf->device_lock, flags); while (bh) { struct buffer_head *t = bh; bh=bh->b_next; @@ -103,7 +104,7 @@ static inline void raid1_free_bh(raid1_conf_t *conf, struct buffer_head *bh) conf->freebh_cnt++; } } - md_spin_unlock_irq(&conf->device_lock); + spin_unlock_irqrestore(&conf->device_lock, flags); wake_up(&conf->wait_buffer); } @@ -182,10 +183,11 @@ static inline void raid1_free_r1bh(struct raid1_bh *r1_bh) r1_bh->mirror_bh_list = NULL; if (test_bit(R1BH_PreAlloc, &r1_bh->state)) { - md_spin_lock_irq(&conf->device_lock); + unsigned long flags; + spin_lock_irqsave(&conf->device_lock, flags); r1_bh->next_r1 = conf->freer1; conf->freer1 = r1_bh; - md_spin_unlock_irq(&conf->device_lock); + spin_unlock_irqrestore(&conf->device_lock, flags); } else { kfree(r1_bh); } @@ -229,14 +231,15 @@ static void raid1_shrink_r1bh(raid1_conf_t *conf) static inline void raid1_free_buf(struct raid1_bh *r1_bh) { + unsigned long flags; struct buffer_head *bh = r1_bh->mirror_bh_list; raid1_conf_t *conf = mddev_to_conf(r1_bh->mddev); r1_bh->mirror_bh_list = NULL; - md_spin_lock_irq(&conf->device_lock); + spin_lock_irqsave(&conf->device_lock, flags); r1_bh->next_r1 = conf->freebuf; conf->freebuf = r1_bh; - md_spin_unlock_irq(&conf->device_lock); + spin_unlock_irqrestore(&conf->device_lock, flags); raid1_free_bh(conf, bh); } @@ -371,7 +374,7 @@ static void raid1_end_bh_io (struct raid1_bh *r1_bh, int uptodate) { struct buffer_head *bh = r1_bh->master_bh; - io_request_done(bh->b_rsector, mddev_to_conf(r1_bh->mddev), + io_request_done(bh->b_blocknr*(bh->b_size>>9), mddev_to_conf(r1_bh->mddev), test_bit(R1BH_SyncPhase, &r1_bh->state)); bh->b_end_io(bh, uptodate); @@ -599,7 +602,7 @@ static int raid1_make_request (mddev_t *mddev, int rw, bh_req = &r1_bh->bh_req; memcpy(bh_req, bh, sizeof(*bh)); - bh_req->b_blocknr = bh->b_rsector * sectors; + bh_req->b_blocknr = bh->b_rsector / sectors; bh_req->b_dev = mirror->dev; bh_req->b_rdev = mirror->dev; /* bh_req->b_rsector = bh->n_rsector; */ @@ -643,7 +646,7 @@ static int raid1_make_request (mddev_t *mddev, int rw, /* * prepare mirrored mbh (fields ordered for max mem throughput): */ - mbh->b_blocknr = bh->b_rsector * sectors; + mbh->b_blocknr = bh->b_rsector / sectors; mbh->b_dev = conf->mirrors[i].dev; mbh->b_rdev = conf->mirrors[i].dev; mbh->b_rsector = bh->b_rsector; @@ -1181,7 +1184,7 @@ static void raid1d (void *data) struct buffer_head *bh1 = mbh; mbh = mbh->b_next; generic_make_request(WRITE, bh1); - md_sync_acct(bh1->b_rdev, bh1->b_size/512); + md_sync_acct(bh1->b_dev, bh1->b_size/512); } } else { dev = bh->b_dev; @@ -1406,7 +1409,7 @@ static int raid1_sync_request (mddev_t *mddev, unsigned long block_nr) init_waitqueue_head(&bh->b_wait); generic_make_request(READ, bh); - md_sync_acct(bh->b_rdev, bh->b_size/512); + md_sync_acct(bh->b_dev, bh->b_size/512); return (bsize >> 10); diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index ed2056deaff6..f2b1367bbb16 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -12,6 +12,10 @@ * Scott McGrath (smcgrath@twilight.vtc.vsc.edu) * William McGrath (wmcgrath@twilight.vtc.vsc.edu) * + * History: + * 2000-04-29 Russell Kroll + * Added ISAPnP detection for Linux 2.3/2.4 + * */ #include /* Modules */ @@ -40,6 +44,17 @@ static __u8 rdsin=0,rdsout=0,rdsstat=0; static unsigned char rdsbuf[RDS_BUFFER]; static int cadet_lock=0; +#ifndef MODULE +static int cadet_probe(void); +#endif + +#ifdef CONFIG_ISAPNP +#include + +struct pci_dev *dev; +static int isapnp_cadet_probe(void); +#endif + /* * Signal Strength Threshold Values * The V4L API spec does not define any particular unit for the signal @@ -47,8 +62,6 @@ static int cadet_lock=0; */ static __u16 sigtable[2][4]={{5,10,30,150},{28,40,63,1000}}; - - void cadet_wake(unsigned long qnum) { switch(qnum) { @@ -542,7 +555,32 @@ static struct video_device cadet_radio= NULL }; -#ifndef MODULE +#ifdef CONFIG_ISAPNP +static int isapnp_cadet_probe(void) +{ + dev = isapnp_find_dev (NULL, ISAPNP_VENDOR('M','S','M'), + ISAPNP_FUNCTION(0x0c24), NULL); + + if (!dev) + return -ENODEV; + if (dev->prepare(dev)<0) + return -EAGAIN; + if (!(dev->resource[0].flags & IORESOURCE_IO)) + return -ENODEV; + if (dev->activate(dev)<0) { + printk ("radio-cadet: isapnp configure failed (out of resources?)\n"); + return -ENOMEM; + } + + io = dev->resource[0].start; + + printk ("radio-cadet: ISAPnP reports card at %#x\n", io); + + return io; +} +#endif /* CONFIG_ISAPNP */ + +#ifdef MODULE static int cadet_probe(void) { static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e}; @@ -559,13 +597,20 @@ static int cadet_probe(void) } return -1; } -#endif +#endif /* MODULE */ static int __init cadet_init(void) { -#ifndef MODULE +#ifdef CONFIG_ISAPNP + io = isapnp_cadet_probe(); + + if (io < 0) + return (io); +#else +#ifndef MODULE /* only probe on non-ISAPnP monolithic compiles */ io = cadet_probe (); -#endif +#endif /* MODULE */ +#endif /* CONFIG_ISAPNP */ if(io < 0) { #ifdef MODULE @@ -596,6 +641,11 @@ static void __exit cadet_cleanup_module(void) { video_unregister_device(&cadet_radio); release_region(io,2); + +#ifdef CONFIG_ISAPNP + if (dev) + dev->deactivate(dev); +#endif } module_init(cadet_init); diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index fcbfd3175b65..3f28868e3899 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -44,7 +44,7 @@ SUB_DIRS := ALL_SUB_DIRS := MOD_SUB_DIRS := -export-objs := mtdcore.o doc2000.o doc2001.o cfi_probe.o cfi_cmdset_0001.o cfi_cmdset_0002.o +export-objs := mtdcore.o list-multi := # MTD devices diff --git a/drivers/mtd/cfi_cmdset_0001.c b/drivers/mtd/cfi_cmdset_0001.c index 8c26d43b4f4b..c2662fbb06da 100644 --- a/drivers/mtd/cfi_cmdset_0001.c +++ b/drivers/mtd/cfi_cmdset_0001.c @@ -32,12 +32,20 @@ static void cfi_intelext_resume (struct mtd_info *); static void cfi_intelext_destroy(struct mtd_info *); -void cfi_cmdset_0001(struct map_info *, int, unsigned long); -EXPORT_SYMBOL(cfi_cmdset_0001); +static void cfi_cmdset_0001(struct map_info *, int, unsigned long); -struct mtd_info *cfi_intelext_setup (struct map_info *); +static struct mtd_info *cfi_intelext_setup (struct map_info *); -void cfi_cmdset_0001(struct map_info *map, int primary, unsigned long base) +static const char im_name[] = "cfi_cmdset_0001"; + +/* This routine is made available to other mtd code via + * inter_module_register. It must only be accessed through + * inter_module_get which will bump the use count of this module. The + * addresses passed back in cfi are valid as long as the use count of + * this module is non-zero, i.e. between inter_module_get and + * inter_module_put. Keith Owens 29 Oct 2000. + */ +static void cfi_cmdset_0001(struct map_info *map, int primary, unsigned long base) { struct cfi_private *cfi = map->fldrv_priv; int i; @@ -144,7 +152,7 @@ void cfi_cmdset_0001(struct map_info *map, int primary, unsigned long base) /* If there was an old setup function, decrease its use count */ if (cfi->cmdset_setup) - put_module_symbol((unsigned long)cfi->cmdset_setup); + inter_module_put(cfi->im_name); if (cfi->cmdset_priv) kfree(cfi->cmdset_priv); @@ -156,14 +164,13 @@ void cfi_cmdset_0001(struct map_info *map, int primary, unsigned long base) cfi->cmdset_setup = cfi_intelext_setup; + cfi->im_name = im_name; cfi->cmdset_priv = extp; - MOD_INC_USE_COUNT; /* So the setup function is still there - * by the time it's called */ return; } -struct mtd_info *cfi_intelext_setup(struct map_info *map) +static struct mtd_info *cfi_intelext_setup(struct map_info *map) { struct cfi_private *cfi = map->fldrv_priv; struct mtd_info *mtd; @@ -862,6 +869,21 @@ static void cfi_intelext_destroy(struct mtd_info *mtd) struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; kfree(cfi->cmdset_priv); + inter_module_put(cfi->im_name); kfree(cfi); } + +static int __init cfi_intelext_init(void) +{ + inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0001); + return 0; +} + +static void __exit cfi_intelext_exit(void) +{ + inter_module_unregister(im_name); +} + +module_init(cfi_intelext_init); +module_exit(cfi_intelext_exit); diff --git a/drivers/mtd/cfi_cmdset_0002.c b/drivers/mtd/cfi_cmdset_0002.c index 2797c768e509..176bcbcc0aca 100644 --- a/drivers/mtd/cfi_cmdset_0002.c +++ b/drivers/mtd/cfi_cmdset_0002.c @@ -36,12 +36,13 @@ static void cfi_amdext_resume (struct mtd_info *); static void cfi_amdext_destroy(struct mtd_info *); -void cfi_cmdset_0002(struct map_info *, int, unsigned long); -EXPORT_SYMBOL(cfi_cmdset_0002); +static void cfi_cmdset_0002(struct map_info *, int, unsigned long); -struct mtd_info *cfi_amdext_setup (struct map_info *); +static struct mtd_info *cfi_amdext_setup (struct map_info *); -void cfi_cmdset_0002(struct map_info *map, int primary, unsigned long base) +static const char im_name[] = "cfi_cmdset_0002"; + +static void cfi_cmdset_0002(struct map_info *map, int primary, unsigned long base) { struct cfi_private *cfi = map->fldrv_priv; int i; @@ -54,7 +55,7 @@ void cfi_cmdset_0002(struct map_info *map, int primary, unsigned long base) /* If there was an old setup function, decrease its use count */ if (cfi->cmdset_setup) - put_module_symbol((unsigned long)cfi->cmdset_setup); + inter_module_put(cfi->im_name); if (cfi->cmdset_priv) kfree(cfi->cmdset_priv); @@ -66,14 +67,13 @@ void cfi_cmdset_0002(struct map_info *map, int primary, unsigned long base) cfi->cmdset_setup = cfi_amdext_setup; + cfi->im_name = im_name; // cfi->cmdset_priv = extp; - MOD_INC_USE_COUNT; /* So the setup function is still there - * by the time it's called */ return; } -struct mtd_info *cfi_amdext_setup(struct map_info *map) +static struct mtd_info *cfi_amdext_setup(struct map_info *map) { struct cfi_private *cfi = map->fldrv_priv; struct mtd_info *mtd; @@ -605,6 +605,21 @@ static void cfi_amdext_destroy(struct mtd_info *mtd) struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; kfree(cfi->cmdset_priv); + inter_module_put(cfi->im_name); kfree(cfi); } + +static int __init cfi_amdext_init(void) +{ + inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0002); + return 0; +} + +static void __exit cfi_amdext_exit(void) +{ + inter_module_unregister(im_name); +} + +module_init(cfi_amdext_init); +module_exit(cfi_amdext_exit); diff --git a/drivers/mtd/cfi_probe.c b/drivers/mtd/cfi_probe.c index ccd33fb3cabd..392f7aa57469 100644 --- a/drivers/mtd/cfi_probe.c +++ b/drivers/mtd/cfi_probe.c @@ -17,14 +17,22 @@ #include -struct mtd_info *cfi_probe(struct map_info *); -EXPORT_SYMBOL(cfi_probe); +static struct mtd_info *cfi_probe(struct map_info *); static void print_cfi_ident(struct cfi_ident *); static void check_cmd_set(struct map_info *, int, unsigned long); static struct cfi_private *cfi_cfi_probe(struct map_info *); -struct mtd_info *cfi_probe(struct map_info *map) +static const char im_name[] = "cfi_probe"; + +/* This routine is made available to other mtd code via + * inter_module_register. It must only be accessed through + * inter_module_get which will bump the use count of this module. The + * addresses passed back in mtd are valid as long as the use count of + * this module is non-zero, i.e. between inter_module_get and + * inter_module_put. Keith Owens 29 Oct 2000. + */ +static struct mtd_info *cfi_probe(struct map_info *map) { struct mtd_info *mtd = NULL; struct cfi_private *cfi; @@ -35,13 +43,14 @@ struct mtd_info *cfi_probe(struct map_info *map) return NULL; map->fldrv_priv = cfi; + map->im_name = im_name; /* OK we liked it. Now find a driver for the command set it talks */ check_cmd_set(map, 1, cfi->chips[0].start); /* First the primary cmdset */ check_cmd_set(map, 0, cfi->chips[0].start); /* Then the secondary */ - /* check_cmd_set() will have used get_module_symbol to increase + /* check_cmd_set() will have used inter_module_get to increase the use count of the module which provides the command set driver. If we're quitting, we have to decrease it again. */ @@ -51,7 +60,7 @@ struct mtd_info *cfi_probe(struct map_info *map) if (mtd) return mtd; - put_module_symbol((unsigned long)cfi->cmdset_setup); + inter_module_put(cfi->im_name); } printk("No supported Vendor Command Set found\n"); @@ -239,7 +248,7 @@ static int cfi_probe_new_chip(struct map_info *map, unsigned long base, } } default: - printk(KERN_WARNING "cfi_cfi_probe called with strange buswidth %d\n", map->buswidth); + printk(KERN_WARNING "cfi_probe called with strange buswidth %d\n", map->buswidth); return 0; } } @@ -465,16 +474,9 @@ static void check_cmd_set(struct map_info *map, int primary, unsigned long base) sprintf(probename, "cfi_cmdset_%4.4X", type); - probe_function = (void *)get_module_symbol(NULL, probename); - if (!probe_function) { - request_module(probename); - - probe_function = (void *)get_module_symbol(NULL, probename); - } - + probe_function = inter_module_get_request(probename, probename); if (probe_function) { (*probe_function)(map, primary, base); - put_module_symbol((unsigned long)probe_function); return; } @@ -499,3 +501,17 @@ static void check_cmd_set(struct map_info *map, int primary, unsigned long base) map->read8(map,base+((adr+4)*map->buswidth))); } } + +static int __init cfi_probe_init(void) +{ + inter_module_register(im_name, THIS_MODULE, &cfi_probe); + return 0; +} + +static void __exit cfi_probe_exit(void) +{ + inter_module_unregister(im_name); +} + +module_init(cfi_probe_init); +module_exit(cfi_probe_exit); diff --git a/drivers/mtd/doc2000.c b/drivers/mtd/doc2000.c index eeb49a4eb2ce..cef67512b0d7 100644 --- a/drivers/mtd/doc2000.c +++ b/drivers/mtd/doc2000.c @@ -392,7 +392,16 @@ static int DoC2k_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2) } -void DoC2k_init(struct mtd_info *mtd) +static const char im_name[] = "DoC2k_init"; + +/* This routine is made available to other mtd code via + * inter_module_register. It must only be accessed through + * inter_module_get which will bump the use count of this module. The + * addresses passed back in mtd are valid as long as the use count of + * this module is non-zero, i.e. between inter_module_get and + * inter_module_put. Keith Owens 29 Oct 2000. + */ +static void DoC2k_init(struct mtd_info *mtd) { struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; struct DiskOnChip *old = NULL; @@ -460,8 +469,6 @@ void DoC2k_init(struct mtd_info *mtd) } -EXPORT_SYMBOL(DoC2k_init); - static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { /* Just a special case of doc_read_ecc */ @@ -805,6 +812,12 @@ int doc_erase (struct mtd_info *mtd, struct erase_info *instr) * ****************************************************************************/ +static int __init init_doc2000(void) +{ + inter_module_register(im_name, THIS_MODULE, &DoC2k_init); + return 0; +} + #if LINUX_VERSION_CODE < 0x20300 #ifdef MODULE #define cleanup_doc2000 cleanup_module @@ -828,10 +841,12 @@ static void __exit cleanup_doc2000(void) kfree(this->chips); kfree(mtd); } + inter_module_unregister(im_name); } +module_init(init_doc2000); + #if LINUX_VERSION_CODE > 0x20300 module_exit(cleanup_doc2000); #endif - diff --git a/drivers/mtd/doc2001.c b/drivers/mtd/doc2001.c index 26a10772269f..8a9f032357f4 100644 --- a/drivers/mtd/doc2001.c +++ b/drivers/mtd/doc2001.c @@ -321,6 +321,15 @@ static int DoCMil_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2) return retval; } +static const char im_name[] = "DoCMil_init"; + +/* This routine is made available to other mtd code via + * inter_module_register. It must only be accessed through + * inter_module_get which will bump the use count of this module. The + * addresses passed back in mtd are valid as long as the use count of + * this module is non-zero, i.e. between inter_module_get and + * inter_module_put. Keith Owens 29 Oct 2000. + */ void DoCMil_init(struct mtd_info *mtd) { struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; @@ -386,8 +395,6 @@ void DoCMil_init(struct mtd_info *mtd) } } -EXPORT_SYMBOL(DoCMil_init); - static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { @@ -780,6 +787,12 @@ int doc_erase (struct mtd_info *mtd, struct erase_info *instr) * ****************************************************************************/ +static int __init init_doc2001(void) +{ + inter_module_register(im_name, THIS_MODULE, &DoCMil_init); + return 0; +} + #if LINUX_VERSION_CODE < 0x20300 #ifdef MODULE #define cleanup_doc2001 cleanup_module @@ -803,10 +816,12 @@ static void __exit cleanup_doc2001(void) kfree(this->chips); kfree(mtd); } + inter_module_unregister(im_name); } +module_init(init_doc2001); + #if LINUX_VERSION_CODE > 0x20300 module_exit(cleanup_doc2001); #endif - diff --git a/drivers/mtd/docprobe.c b/drivers/mtd/docprobe.c index 7ab0a2d74ea5..3dce6dc97c0f 100644 --- a/drivers/mtd/docprobe.c +++ b/drivers/mtd/docprobe.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -62,12 +61,6 @@ static unsigned long __initdata doc_locations[] = { #warning Unknown architecture for DiskOnChip. No default probe locations defined #endif -#ifdef CONFIG_MTD_DOC2000 -extern void DoC2k_init(struct mtd_info *); -#endif -#ifdef CONFIG_MTD_DOC2001 -extern void DoCMil_init(struct mtd_info *); -#endif /* doccheck: Probe a given memory window to see if there's a DiskOnChip present */ @@ -157,8 +150,9 @@ static void DoC_Probe(unsigned long physadr) int ChipID; char namebuf[15]; char *name = namebuf; + char *im_funcname = NULL; + char *im_modname = NULL; void (*initroutine)(struct mtd_info *) = NULL; - int initroutinedynamic = 0; docptr = (unsigned long)ioremap(physadr, 0x2000); @@ -189,42 +183,21 @@ static void DoC_Probe(unsigned long physadr) switch(ChipID) { case DOC_ChipID_Doc2k: name="2000"; -#ifdef CONFIG_MTD_DOC2000 - initroutine = &DoC2k_init; -#elif CONFIG_MODULES - initroutinedynamic=1; - initroutine = (void *)get_module_symbol(NULL, "DoC2k_init"); -#ifdef CONFIG_KMOD - if (!initroutine) { - request_module("doc2000"); - initroutine = (void *)get_module_symbol("doc2000", "DoC2k_init"); - } -#endif /* CONFIG_KMOD */ -#endif + im_funcname = "DoC2k_init"; + im_modname = "doc2000"; break; case DOC_ChipID_DocMil: name="Millennium"; -#ifdef CONFIG_MTD_DOC2001 - initroutine = &DoCMil_init; -#elif CONFIG_MODULES - initroutinedynamic=1; - initroutine = (void *)get_module_symbol(NULL, "DoCMil_init"); -#ifdef CONFIG_KMOD - if (!initroutine) { - request_module("doc2001"); - initroutine = (void *)get_module_symbol("doc2001", "DoCMil_init"); - } -#endif /* CONFIG_KMOD */ -#endif + im_funcname = "DoCMil_init"; + im_modname = "doc2001"; break; } + if (im_funcname) + initroutine = inter_module_get_request(im_funcname, im_modname); if (initroutine) { (*initroutine)(mtd); -#if defined(CONFIG_MODULES) && LINUX_VERSION_CODE >= 0x20400 - if (initroutinedynamic) - put_module_symbol(initroutine); -#endif + inter_module_put(im_funcname); return; } printk("Cannot find driver for DiskOnChip %s at 0x%X\n", name, physadr); diff --git a/drivers/mtd/map_ram.c b/drivers/mtd/map_ram.c index 706f7f5ff43d..c62515406cea 100644 --- a/drivers/mtd/map_ram.c +++ b/drivers/mtd/map_ram.c @@ -20,10 +20,16 @@ static int mapram_write (struct mtd_info *, loff_t, size_t, size_t *, const u_ch static int mapram_erase (struct mtd_info *, struct erase_info *); static void mapram_nop (struct mtd_info *); -struct mtd_info *map_ram_probe(struct map_info *); -EXPORT_SYMBOL(map_ram_probe); - -struct mtd_info *map_ram_probe(struct map_info *map) +static const char im_name[] = "map_ram_probe"; + +/* This routine is made available to other mtd code via + * inter_module_register. It must only be accessed through + * inter_module_get which will bump the use count of this module. The + * addresses passed back in mtd are valid as long as the use count of + * this module is non-zero, i.e. between inter_module_get and + * inter_module_put. Keith Owens 29 Oct 2000. + */ +static struct mtd_info *map_ram_probe(struct map_info *map) { struct mtd_info *mtd; @@ -63,9 +69,9 @@ struct mtd_info *map_ram_probe(struct map_info *map) mtd->read = mapram_read; mtd->write = mapram_write; mtd->sync = mapram_nop; + mtd->im_name = im_name; mtd->flags = MTD_CAP_RAM | MTD_VOLATILE; - MOD_INC_USE_COUNT; return mtd; } @@ -108,3 +114,17 @@ static void mapram_nop(struct mtd_info *mtd) { /* Nothing to see here */ } + +static int __init map_ram_init(void) +{ + inter_module_register(im_name, THIS_MODULE, &map_ram_probe); + return 0; +} + +static void __exit map_ram_exit(void) +{ + inter_module_unregister(im_name); +} + +module_init(map_ram_init); +module_exit(map_ram_exit); diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c index 06745646cad3..bdc1c53da359 100644 --- a/drivers/net/3c503.c +++ b/drivers/net/3c503.c @@ -324,10 +324,10 @@ el2_open(struct net_device *dev) do { if (request_irq (*irqp, NULL, 0, "bogus", dev) != -EBUSY) { /* Twinkle the interrupt, and check if it's seen. */ - autoirq_setup(0); + unsigned long cookie = probe_irq_on(); outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR); outb_p(0x00, E33G_IDCFR); - if (*irqp == autoirq_report(0) /* It's a good IRQ line! */ + if (*irqp == probe_irq_off(cookie) /* It's a good IRQ line! */ && request_irq (dev->irq = *irqp, ei_interrupt, 0, ei_status.name, dev) == 0) break; } @@ -625,9 +625,6 @@ init_module(void) { int this_dev, found = 0; - if (load_8390_module("3c503.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) { struct net_device *dev = &dev_el2[this_dev]; dev->irq = irq[this_dev]; @@ -643,7 +640,6 @@ init_module(void) if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); return -ENXIO; } found++; @@ -666,7 +662,6 @@ cleanup_module(void) kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index ae3523a7cd0e..02af4f34a0a4 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -434,6 +434,13 @@ no_pnp: /* Free the interrupt so that some other card can use it. */ outw(0x0f00, ioaddr + WN0_IRQ); found: + if (dev == NULL) { + dev = init_etherdev(dev, sizeof(struct el3_private)); + if (dev == NULL) { + release_region(ioaddr, EL3_IO_EXTENT); + return -ENOMEM; + } + } memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr)); dev->base_addr = ioaddr; dev->irq = irq; diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 1eefdfb7116d..8e6379e38563 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -98,7 +98,7 @@ - Added INVERT_LED_PWR, used it. - Backed out the extra_reset stuff - LK1.1.9 2 Sep 2000 andrewm + LK1.1.9 12 Sep 2000 andrewm - Backed out the tx_reset_resume flags. It was a no-op. - In vortex_error, don't reset the Tx on txReclaim errors - In vortex_error, don't reset the Tx on maxCollisions errors. @@ -110,6 +110,11 @@ is downed, it remains set when the interface is upped. Bad things happen. + LK1.1.10 17 Sep 2000 andrewm + - Added EEPROM_8BIT for 3c555 (Fred Maciel) + - Added experimental support for the 3c556B Laptop Hurricane (Louis Gerbarg) + - Add HAS_NWAY to "3c900 Cyclone 10Mbps TPO" + - See http://www.uow.edu.au/~andrewm/linux/#3c59x-2.3 for more details. - Also see Documentation/networking/vortex.txt */ @@ -195,7 +200,7 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits; #include static char version[] __devinitdata = -"3c59x.c:LK1.1.9 2 Sep 2000 Donald Becker and others. http://www.scyld.com/network/vortex.html " "$Revision: 1.102.2.38 $\n"; +"3c59x.c:LK1.1.10 17 Sep 2000 Donald Becker and others. http://www.scyld.com/network/vortex.html " "$Revision: 1.102.2.40 $\n"; MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("3Com 3c59x/3c90x/3c575 series Vortex/Boomerang/Cyclone driver"); @@ -315,8 +320,8 @@ enum pci_flags_bit { enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4, IS_TORNADO=8, EEPROM_8BIT=0x10, /* AKPM: Uses 0x230 as the base bitmaps for EEPROM reads */ HAS_PWR_CTRL=0x20, HAS_MII=0x40, HAS_NWAY=0x80, HAS_CB_FNS=0x100, - INVERT_MII_PWR=0x200, INVERT_LED_PWR=0x400, MAX_COLLISION_RESET=0x800 }; - + INVERT_MII_PWR=0x200, INVERT_LED_PWR=0x400, MAX_COLLISION_RESET=0x800, + EEPROM_OFFSET=0x1000 }; enum vortex_chips { CH_3C590 = 0, @@ -346,15 +351,16 @@ enum vortex_chips { CH_3CSOHO100_TX, CH_3C555, CH_3C556, + CH_3C556B, CH_3C575, - CH_3C575_1, + CH_3C575_1, CH_3CCFE575, CH_3CCFE575CT, CH_3CCFE656, CH_3CCFEM656, - CH_3CCFEM656_1, + CH_3CCFEM656_1, CH_3C450, }; @@ -388,7 +394,7 @@ static struct vortex_chip_info { {"3c900 Boomerang 10Mbps Combo", PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, }, {"3c900 Cyclone 10Mbps TPO", /* AKPM: from Don's 0.99M */ - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, }, + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, }, {"3c900 Cyclone 10Mbps Combo", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, }, @@ -417,14 +423,16 @@ static struct vortex_chip_info { {"3cSOHO100-TX Hurricane", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, }, {"3c555 Laptop Hurricane", - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, }, - {"3c556 10/100 Mini PCI Adapter", - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|EEPROM_8BIT|HAS_CB_FNS|INVERT_MII_PWR, 128, }, + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|EEPROM_8BIT, 128, }, + {"3c556 Laptop Tornado", + PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_8BIT|HAS_CB_FNS|INVERT_MII_PWR, 128, }, + {"3c556B Laptop Hurricane", + PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_OFFSET|HAS_CB_FNS|INVERT_MII_PWR, 128, }, {"3c575 [Megahertz] 10/100 LAN CardBus", PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, }, + {"3c575 Boomerang CardBus", PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, }, - {"3CCFE575BT Cyclone CardBus", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_LED_PWR, 128, }, {"3CCFE575CT Tornado CardBus", @@ -433,9 +441,9 @@ static struct vortex_chip_info { PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|INVERT_LED_PWR, 128, }, {"3CCFEM656B Cyclone+Winmodem CardBus", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|INVERT_LED_PWR, 128, }, + {"3CXFEM656C Tornado+Winmodem CardBus", /* From pcmcia-cs-3.1.5 */ PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|MAX_COLLISION_RESET, 128, }, - {"3c450 HomePNA Tornado", /* AKPM: from Don's 0.99Q */ PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY, 128, }, {0,}, /* 0 terminated list. */ @@ -470,15 +478,16 @@ static struct pci_device_id vortex_pci_tbl[] __devinitdata = { { 0x10B7, 0x7646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CSOHO100_TX }, { 0x10B7, 0x5055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C555 }, { 0x10B7, 0x6055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C556 }, + { 0x10B7, 0x6056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C556B }, { 0x10B7, 0x5b57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575 }, - { 0x10B7, 0x5057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575_1 }, + { 0x10B7, 0x5057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575_1 }, { 0x10B7, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575 }, { 0x10B7, 0x5257, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575CT }, { 0x10B7, 0x6560, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE656 }, { 0x10B7, 0x6562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656 }, - { 0x10B7, 0x6564, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656_1 }, + { 0x10B7, 0x6564, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656_1 }, { 0x10B7, 0x4500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C450 }, {0,} /* 0 terminated list. */ }; @@ -963,7 +972,15 @@ static int __devinit vortex_probe1(struct pci_dev *pdev, /* Read the station address from the EEPROM. */ EL3WINDOW(0); { - int base = (vci->drv_flags & EEPROM_8BIT) ? 0x230 : EEPROM_Read; + int base; + + if (vci->drv_flags & EEPROM_8BIT) + base = 0x230; + else if (vci->drv_flags & EEPROM_OFFSET) + base = EEPROM_Read + 0x30; + else + base = EEPROM_Read; + for (i = 0; i < 0x40; i++) { int timer; outw(base + i, ioaddr + Wn0EepromCmd); diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c index 0e1c40bd4186..c883d6d284c1 100644 --- a/drivers/net/ac3200.c +++ b/drivers/net/ac3200.c @@ -107,12 +107,9 @@ int __init ac3200_probe(struct net_device *dev) if ( ! EISA_bus) return -ENXIO; - for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) { - if (check_region(ioaddr, AC_IO_EXTENT)) - continue; + for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) if (ac_probe1(ioaddr, dev) == 0) return 0; - } return -ENODEV; } @@ -121,8 +118,8 @@ static int __init ac_probe1(int ioaddr, struct net_device *dev) { int i, retval; - if (!request_region(ioaddr, AC_IO_EXTENT, "ac3200")) - return -ENODEV; + if (!request_region(ioaddr, AC_IO_EXTENT, dev->name)) + return -EBUSY; if (inb_p(ioaddr + AC_ID_PORT) == 0xff) { retval = -ENODEV; @@ -172,9 +169,9 @@ static int __init ac_probe1(int ioaddr, struct net_device *dev) printk(", assigning"); } - if (request_irq(dev->irq, ei_interrupt, 0, "ac3200", dev)) { + retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev); + if (retval) { printk (" nothing! Unable to get IRQ %d.\n", dev->irq); - retval = -EAGAIN; goto out1; } @@ -262,9 +259,6 @@ static int ac_open(struct net_device *dev) #ifdef notyet /* Someday we may enable the IRQ and shared memory here. */ int ioaddr = dev->base_addr; - - if (request_irq(dev->irq, ei_interrupt, 0, "ac3200", dev)) - return -EAGAIN; #endif ei_open(dev); @@ -360,9 +354,6 @@ init_module(void) { int this_dev, found = 0; - if (load_8390_module("ac3200.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) { struct net_device *dev = &dev_ac32[this_dev]; dev->irq = irq[this_dev]; @@ -376,7 +367,6 @@ init_module(void) if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); return -ENXIO; } found++; @@ -392,17 +382,16 @@ cleanup_module(void) for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) { struct net_device *dev = &dev_ac32[this_dev]; if (dev->priv != NULL) { - void *priv = dev->priv; /* Someday free_irq may be in ac_close_card() */ free_irq(dev->irq, dev); release_region(dev->base_addr, AC_IO_EXTENT); if (ei_status.reg0) iounmap((void *)dev->mem_start); unregister_netdev(dev); - kfree(priv); + kfree(dev->priv); + dev->priv = NULL; } } - unload_8390_module(); } #endif /* MODULE */ diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 844961396128..511e1d3a333c 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -1145,10 +1145,10 @@ static int __init ace_init(struct net_device *dev) goto init_error; } - if (request_irq(dev->irq, ace_interrupt, SA_SHIRQ, ap->name, dev)) { + ecode = request_irq(dev->irq, ace_interrupt, SA_SHIRQ, dev->name, dev); + if (ecode) { printk(KERN_WARNING "%s: Requested IRQ %d is busy\n", dev->name, dev->irq); - ecode = -EAGAIN; goto init_error; } diff --git a/drivers/net/aironet4500_card.c b/drivers/net/aironet4500_card.c index 11b6e2773c8e..e581d6e3236f 100644 --- a/drivers/net/aironet4500_card.c +++ b/drivers/net/aironet4500_card.c @@ -164,16 +164,23 @@ int awc4500_pci_probe(struct net_device *dev) static int awc_pci_init(struct net_device * dev, struct pci_dev *pdev, int ioaddr, int cis_addr, int mem_addr, u8 pci_irq_line) { - int i; + int i, allocd_dev = 0; if (!dev) { - dev = init_etherdev(dev, 0 ); + dev = init_etherdev(NULL, 0); + if (!dev) + return -ENOMEM; + allocd_dev = 1; } dev->priv = kmalloc(sizeof(struct awc_private),GFP_KERNEL ); memset(dev->priv,0,sizeof(struct awc_private)); if (!dev->priv) { printk(KERN_CRIT "aironet4x00: could not allocate device private, some unstability may follow\n"); - return -1; + if (allocd_dev) { + unregister_netdev(dev); + kfree(dev); + } + return -ENOMEM; }; // ether_setup(dev); @@ -194,7 +201,16 @@ static int awc_pci_init(struct net_device * dev, struct pci_dev *pdev, dev->watchdog_timeo = AWC_TX_TIMEOUT; - request_irq(dev->irq,awc_interrupt, SA_SHIRQ | SA_INTERRUPT ,"Aironet 4X00",dev); + i = request_irq(dev->irq,awc_interrupt, SA_SHIRQ | SA_INTERRUPT, dev->name, dev); + if (i) { + kfree(dev->priv); + dev->priv = NULL; + if (allocd_dev) { + unregister_netdev(dev); + kfree(dev); + } + return i; + } awc_private_init( dev); awc_init(dev); diff --git a/drivers/net/am79c961a.c b/drivers/net/am79c961a.c index cd84f0f56a73..beea30afb779 100644 --- a/drivers/net/am79c961a.c +++ b/drivers/net/am79c961a.c @@ -285,14 +285,16 @@ static int am79c961_open(struct net_device *dev) { struct dev_priv *priv = (struct dev_priv *)dev->priv; + int ret; MOD_INC_USE_COUNT; memset (&priv->stats, 0, sizeof (priv->stats)); - if (request_irq(dev->irq, am79c961_interrupt, 0, "am79c961", dev)) { + ret = request_irq(dev->irq, am79c961_interrupt, 0, dev->name, dev); + if (ret) { MOD_DEC_USE_COUNT; - return -EAGAIN; + return ret; } am79c961_init_for_open(dev); diff --git a/drivers/net/apne.c b/drivers/net/apne.c index df60ad6b879b..15ef3cc4818b 100644 --- a/drivers/net/apne.c +++ b/drivers/net/apne.c @@ -285,10 +285,8 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr) dev->base_addr = ioaddr; /* Install the Interrupt handler */ - if (request_irq(IRQ_AMIGA_PORTS, apne_interrupt, SA_SHIRQ, - "apne Ethernet", dev)) - return -EAGAIN; - + i = request_irq(IRQ_AMIGA_PORTS, apne_interrupt, SA_SHIRQ, dev->name, dev); + if (i) return i; /* Allocate dev->priv and fill in 8390 specific dev fields. */ if (ethdev_init(dev)) { @@ -301,8 +299,7 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr) dev->dev_addr[i] = SA_prom[i]; } - printk("\n%s: %s found.\n", - dev->name, name); + printk("\n%s: %s found.\n", dev->name, name); ei_status.name = name; ei_status.tx_start_page = start_page; @@ -556,13 +553,9 @@ int init_module(void) { int err; - if (load_8390_module("apne.c")) - return -ENOSYS; - if ((err = register_netdev(&apne_dev))) { if (err == -EIO) printk("No PCMCIA NEx000 ethernet card found.\n"); - unload_8390_module(); return (err); } return (0); @@ -578,8 +571,6 @@ void cleanup_module(void) pcmcia_reset(); - unload_8390_module(); - apne_owned = 0; } diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c index 255d845fd6ed..5c00406b4881 100644 --- a/drivers/net/appletalk/cops.c +++ b/drivers/net/appletalk/cops.c @@ -100,7 +100,6 @@ static int io = 0x240; /* Default IO for Dayna */ static int irq = 5; /* Default IRQ */ #else static int io = 0; /* Default IO for Dayna */ -static int irq = 0; /* Default IRQ */ #endif /* @@ -1009,15 +1008,7 @@ static struct net_device_stats *cops_get_stats(struct net_device *dev) } #ifdef MODULE -static struct net_device cops0_dev = -{ - "", /* device name */ - 0, 0, 0, 0, - 0x0, 0, /* I/O address, IRQ */ - 0, 0, 0, NULL, cops_probe -}; - - +static struct net_device cops0_dev = { init: cops_probe }; MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); MODULE_PARM(board_type, "i"); diff --git a/drivers/net/ariadne2.c b/drivers/net/ariadne2.c index 2197d067ce34..fb4dcf5e8199 100644 --- a/drivers/net/ariadne2.c +++ b/drivers/net/ariadne2.c @@ -89,7 +89,7 @@ int __init ariadne2_probe(struct net_device *dev) while ((z = zorro_find_device(ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, z))) { board = z->resource.start; ioaddr = board+ARIADNE2_BASE*2; - if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, "RTL8019AS")) + if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, dev->name)) continue; if ((err = ariadne2_init(dev, ZTWO_VADDR(board)))) { release_mem_region(ioaddr, NE_IO_EXTENT*2); @@ -170,9 +170,8 @@ static int __init ariadne2_init(struct net_device *dev, unsigned long board) dev->irq = IRQ_AMIGA_PORTS; /* Install the Interrupt handler */ - if (request_irq(IRQ_AMIGA_PORTS, ei_interrupt, SA_SHIRQ, - "AriadNE2 Ethernet", dev)) - return -EAGAIN; + i = request_irq(IRQ_AMIGA_PORTS, ei_interrupt, SA_SHIRQ, dev->name, dev); + if (i) return i; /* Allocate dev->priv and fill in 8390 specific dev fields. */ if (ethdev_init(dev)) { @@ -387,13 +386,9 @@ int init_module(void) { int err; - if (load_8390_module("ariadne2.c")) - return -ENOSYS; - if ((err = register_netdev(&ariadne2_dev))) { if (err == -EIO) printk("No AriadNE2 ethernet card found.\n"); - unload_8390_module(); return err; } return 0; @@ -404,7 +399,6 @@ void cleanup_module(void) free_irq(IRQ_AMIGA_PORTS, &ariadne2_dev); release_mem_region(ZTWO_PADDR(ariadne2_dev.base_addr), NE_IO_EXTENT*2); unregister_netdev(&ariadne2_dev); - unload_8390_module(); } #endif /* MODULE */ diff --git a/drivers/net/arlan.c b/drivers/net/arlan.c index dfa7c218b38a..5271b5be4d81 100644 --- a/drivers/net/arlan.c +++ b/drivers/net/arlan.c @@ -1276,11 +1276,12 @@ static int arlan_open(struct net_device *dev) return ret; arlan = ((struct arlan_private *) dev->priv)->card; - if (request_irq(dev->irq, &arlan_interrupt, 0, dev->name, dev)) + ret = request_irq(dev->irq, &arlan_interrupt, 0, dev->name, dev); + if (ret) { printk(KERN_ERR "%s: unable to get IRQ %d .\n", dev->name, dev->irq); - return -EAGAIN; + return ret; } diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c index 42b4d118a072..b33e8157808f 100644 --- a/drivers/net/at1700.c +++ b/drivers/net/at1700.c @@ -117,7 +117,6 @@ struct net_local { uint tx_started:1; /* Packets are on the Tx queue. */ uint tx_queue_ready:1; /* Tx queue is ready to be sent. */ uint rx_started:1; /* Packets are Rxing. */ - uint invalid_irq:1; uchar tx_queue; /* Number of packet on the Tx queue. */ char mca_slot; /* -1 means ISA */ ushort tx_queue_len; /* Current length of the Tx queue. */ @@ -203,8 +202,6 @@ int at1700_probe(struct net_device *dev) for (i = 0; at1700_probe_list[i]; i++) { int ioaddr = at1700_probe_list[i]; - if (check_region(ioaddr, AT1700_IO_EXTENT)) - continue; if (at1700_probe1(dev, ioaddr) == 0) return 0; } @@ -219,15 +216,18 @@ int at1700_probe(struct net_device *dev) that can be done is checking a few bits and then diving right into an EEPROM read. */ -int at1700_probe1(struct net_device *dev, int ioaddr) +static int at1700_probe1(struct net_device *dev, int ioaddr) { char fmv_irqmap[4] = {3, 7, 10, 15}; char fmv_irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15}; char at1700_irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15}; unsigned int i, irq, is_fmv18x = 0, is_at1700 = 0; - int slot; + int slot, ret = -ENODEV; struct net_local *lp; + if (!request_region(ioaddr, AT1700_IO_EXTENT, dev->name)) + return -EBUSY; + /* Resetting the chip doesn't reset the ISA interface, so don't bother. That means we have to be careful with the register values we probe for. */ @@ -306,8 +306,10 @@ int at1700_probe1(struct net_device *dev, int ioaddr) && inb(ioaddr + SAPROM + 1) == 0x00 && inb(ioaddr + SAPROM + 2) == 0x0e) is_fmv18x = 1; - else - return -ENODEV; + else { + ret = -ENODEV; + goto err_out; + } #ifdef CONFIG_MCA found: @@ -328,8 +330,10 @@ found: if (irq == fmv_irqmap_pnp[i]) break; } - if (i == 8) - return -ENODEV; + if (i == 8) { + goto err_out; + ret = -ENODEV; + } } else { if (fmv18x_probe_list[inb(ioaddr + IOCONFIG) & 0x07] != ioaddr) return -ENODEV; @@ -337,10 +341,6 @@ found: } } - /* Grab the region so that we can find another board if the IRQ request - fails. */ - request_region(ioaddr, AT1700_IO_EXTENT, dev->name); - printk("%s: %s found at %#3x, IRQ %d, address ", dev->name, is_at1700 ? "AT1700" : "FMV-18X", ioaddr, irq); @@ -413,8 +413,10 @@ found: /* Initialize the device structure. */ dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; + if (dev->priv == NULL) { + ret = -ENOMEM; + goto err_out; + } memset(dev->priv, 0, sizeof(struct net_local)); dev->open = net_open; @@ -434,14 +436,21 @@ found: lp->jumpered = is_fmv18x; lp->mca_slot = slot; /* Snarf the interrupt vector now. */ - if (request_irq(irq, &net_interrupt, 0, dev->name, dev)) { + ret = request_irq(irq, &net_interrupt, 0, dev->name, dev); + if (ret) { printk (" AT1700 at %#3x is unusable due to a conflict on" "IRQ %d.\n", ioaddr, irq); - lp->invalid_irq = 1; - return 0; + goto err_out_priv; } return 0; + +err_out_priv: + kfree(dev->priv); + dev->priv = NULL; +err_out: + release_region(ioaddr, AT1700_IO_EXTENT); + return ret; } @@ -866,8 +875,7 @@ set_rx_mode(struct net_device *dev) } #ifdef MODULE -static struct net_device dev_at1700 = { init: at1700_probe }; - +static struct net_device dev_at1700; static int io = 0x260; static int irq; @@ -881,6 +889,7 @@ int init_module(void) printk("at1700: You should not use auto-probing with insmod!\n"); dev_at1700.base_addr = io; dev_at1700.irq = irq; + dev_at1700.init = at1700_probe; if (register_netdev(&dev_at1700) != 0) { printk("at1700: register_netdev() returned non-zero.\n"); return -EIO; diff --git a/drivers/net/atp.c b/drivers/net/atp.c index 25d2dbd629ab..976bcc9f36dc 100644 --- a/drivers/net/atp.c +++ b/drivers/net/atp.c @@ -46,9 +46,9 @@ static int max_interrupt_work = 15; #define NUM_UNITS 2 /* The standard set of ISA module parameters. */ -static int io[NUM_UNITS] = {0, 0}; -static int irq[NUM_UNITS] = {0, 0}; -static int xcvr[NUM_UNITS] = {0, 0}; /* The data transfer mode. */ +static int io[NUM_UNITS]; +static int irq[NUM_UNITS]; +static int xcvr[NUM_UNITS]; /* The data transfer mode. */ /* Operational parameters that are set at compile time. */ @@ -425,15 +425,17 @@ static unsigned short __init eeprom_op(long ioaddr, unsigned int cmd) static int net_open(struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; + int ret; MOD_INC_USE_COUNT; /* The interrupt line is turned off (tri-stated) when the device isn't in use. That's especially important for "attached" interfaces where the port or interrupt may be shared. */ - if (request_irq(dev->irq, &atp_interrupt, 0, "ATP Ethernet", dev)) { + ret = request_irq(dev->irq, &atp_interrupt, 0, dev->name, dev); + if (ret) { MOD_DEC_USE_COUNT; - return -EAGAIN; + return ret; } hardware_init(dev); diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index 2542fa2d0b42..9efd94827c7b 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -1270,7 +1270,7 @@ static int __init bmac_probe(void) static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus) { - int j, rev; + int j, rev, ret; struct bmac_data *bp; unsigned char *addr; struct net_device *dev; @@ -1291,7 +1291,6 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus) } dev = init_etherdev(NULL, PRIV_BYTES); - if (!dev) { printk(KERN_ERR "init_etherdev failed, out of memory for BMAC %s\n", bmac->full_name); @@ -1300,6 +1299,8 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus) dev->base_addr = (unsigned long) ioremap(bmac->addrs[0].address, bmac->addrs[0].size); + if (!dev->base_addr) + goto err_out; dev->irq = bmac->intrs[0].line; bmwrite(dev, INTDISABLE, DisableAll); @@ -1322,18 +1323,19 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus) bmac_get_station_address(dev, addr); if (bmac_verify_checksum(dev) != 0) - return; - - ether_setup(dev); + goto err_out_iounmap; bp = (struct bmac_data *) dev->priv; - memset(bp, 0, sizeof(struct bmac_data)); bp->is_bmac_plus = is_bmac_plus; bp->tx_dma = (volatile struct dbdma_regs *) ioremap(bmac->addrs[1].address, bmac->addrs[1].size); + if (!bp->tx_dma) + goto err_out_iounmap; bp->tx_dma_intr = bmac->intrs[1].line; bp->rx_dma = (volatile struct dbdma_regs *) ioremap(bmac->addrs[2].address, bmac->addrs[2].size); + if (!bp->rx_dma) + goto err_out_iounmap_tx; bp->rx_dma_intr = bmac->intrs[2].line; bp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(bp + 1); @@ -1343,23 +1345,44 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus) skb_queue_head_init(bp->queue); bp->node = bmac; - memset(&bp->stats, 0, sizeof(bp->stats)); memset((char *) bp->tx_cmds, 0, (N_TX_RING + N_RX_RING + 2) * sizeof(struct dbdma_cmd)); /* init_timer(&bp->tx_timeout); */ /* bp->timeout_active = 0; */ - if (request_irq(dev->irq, bmac_misc_intr, 0, "BMAC-misc", dev)) + ret = request_irq(dev->irq, bmac_misc_intr, 0, "BMAC-misc", dev); + if (ret) { printk(KERN_ERR "BMAC: can't get irq %d\n", dev->irq); - if (request_irq(bmac->intrs[1].line, bmac_txdma_intr, 0, "BMAC-txdma", - dev)) + goto err_out_iounmap_rx; + } + ret = request_irq(bmac->intrs[1].line, bmac_txdma_intr, 0, "BMAC-txdma", dev); + if (ret) { printk(KERN_ERR "BMAC: can't get irq %d\n", bmac->intrs[1].line); - if (request_irq(bmac->intrs[2].line, bmac_rxdma_intr, 0, "BMAC-rxdma", - dev)) + goto err_out_irq0; + } + ret = request_irq(bmac->intrs[2].line, bmac_rxdma_intr, 0, "BMAC-rxdma", dev); + if (ret) { printk(KERN_ERR "BMAC: can't get irq %d\n", bmac->intrs[2].line); + goto err_out_irq1; + } bp->next_bmac = bmac_devs; bmac_devs = dev; + return; + +err_out_irq1: + free_irq(bmac->intrs[1].line); +err_out_irq0: + free_irq(dev->irq); +err_out_iounmap_rx: + iounmap((void *)bp->rx_dma); +err_out_iounmap_tx: + iounmap((void *)bp->tx_dma); +err_out_iounmap: + iounmap((void *)dev->base_addr); +err_out: + unregister_netdev(dev); + kfree(dev); } static int bmac_open(struct net_device *dev) diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 9577b4ffae42..dc315ec124df 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -1058,10 +1058,10 @@ net_open(struct net_device *dev) writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON); #endif write_irq(dev, lp->chip_type, dev->irq); - if (request_irq(dev->irq, &net_interrupt, 0, "cs89x0", dev)) { + ret = request_irq(dev->irq, &net_interrupt, 0, dev->name, dev); + if (ret) { if (net_debug) printk("cs89x0: request_irq(%d) failed\n", dev->irq); - ret = -EAGAIN; goto bad_out; } } diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c index 53ded875ab42..3d632145cb74 100644 --- a/drivers/net/e2100.c +++ b/drivers/net/e2100.c @@ -395,9 +395,6 @@ init_module(void) { int this_dev, found = 0; - if (load_8390_module("e2100.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) { struct net_device *dev = &dev_e21[this_dev]; dev->irq = irq[this_dev]; @@ -414,7 +411,6 @@ init_module(void) if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); return -ENXIO; } found++; @@ -437,7 +433,6 @@ cleanup_module(void) kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c index 6a825f4363ec..86a09b4d4834 100644 --- a/drivers/net/es3210.c +++ b/drivers/net/es3210.c @@ -401,9 +401,6 @@ init_module(void) { int this_dev, found = 0; - if (load_8390_module("es3210.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_ES_CARDS; this_dev++) { struct net_device *dev = &dev_es3210[this_dev]; dev->irq = irq[this_dev]; @@ -417,7 +414,6 @@ init_module(void) if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); return -ENXIO; } found++; @@ -440,6 +436,5 @@ cleanup_module(void) kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff --git a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c index 8e76e9f6b6bc..9c1423965719 100644 --- a/drivers/net/fmv18x.c +++ b/drivers/net/fmv18x.c @@ -132,20 +132,16 @@ static void set_multicast_list(struct net_device *dev); int __init fmv18x_probe(struct net_device *dev) { int i; - int base_addr = dev ? dev->base_addr : 0; + int base_addr = dev->base_addr; if (base_addr > 0x1ff) /* Check a single specified location. */ return fmv18x_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ return -ENXIO; - for (i = 0; fmv18x_probe_list[i]; i++) { - int ioaddr = fmv18x_probe_list[i]; - if (check_region(ioaddr, FMV18X_IO_EXTENT)) - continue; - if (fmv18x_probe1(dev, ioaddr) == 0) + for (i = 0; fmv18x_probe_list[i]; i++) + if (fmv18x_probe1(dev, fmv18x_probe_list[i]) == 0) return 0; - } return -ENODEV; } @@ -158,21 +154,26 @@ int __init fmv18x_probe(struct net_device *dev) that can be done is checking a few bits and then diving right into MAC address check. */ -int __init fmv18x_probe1(struct net_device *dev, short ioaddr) +static int __init fmv18x_probe1(struct net_device *dev, short ioaddr) { char irqmap[4] = {3, 7, 10, 15}; char irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15}; - unsigned int i, irq; + unsigned int i, irq, retval; /* Resetting the chip doesn't reset the ISA interface, so don't bother. That means we have to be careful with the register values we probe for. */ + if (!request_region(ioaddr, FMV18X_IO_EXTENT, dev->name)) + return -EBUSY; + /* Check I/O address configuration and Fujitsu vendor code */ if (inb(ioaddr+FJ_MACADDR ) != 0x00 || inb(ioaddr+FJ_MACADDR+1) != 0x00 - || inb(ioaddr+FJ_MACADDR+2) != 0x0e) - return -ENODEV; + || inb(ioaddr+FJ_MACADDR+2) != 0x0e) { + retval = -ENODEV; + goto out; + } /* Check PnP mode for FMV-183/184/183A/184A. */ /* This PnP routine is very poor. IO and IRQ should be known. */ @@ -182,8 +183,10 @@ int __init fmv18x_probe1(struct net_device *dev, short ioaddr) if (irq == irqmap_pnp[i]) break; } - if (i == 8) - return -ENODEV; + if (i == 8) { + retval = -ENODEV; + goto out; + } } else { if (fmv18x_probe_list[inb(ioaddr + FJ_CONFIG0) & 0x07] != ioaddr) return -ENODEV; @@ -191,16 +194,13 @@ int __init fmv18x_probe1(struct net_device *dev, short ioaddr) } /* Snarf the interrupt vector now. */ - if (request_irq(irq, &net_interrupt, 0, "fmv18x", dev)) { + retval = request_irq(irq, &net_interrupt, 0, dev->name, dev); + if (retval) { printk ("FMV-18x found at %#3x, but it's unusable due to a conflict on" "IRQ %d.\n", ioaddr, irq); - return -EAGAIN; + goto out; } - /* Grab the region so that we can find another board if the IRQ request - fails. */ - request_region(ioaddr, FMV18X_IO_EXTENT, "fmv18x"); - printk("%s: FMV-18x found at %#3x, IRQ %d, address ", dev->name, ioaddr, irq); @@ -261,8 +261,10 @@ int __init fmv18x_probe1(struct net_device *dev, short ioaddr) /* Initialize the device structure. */ dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; + if (!dev->priv) { + retval = -ENOMEM; + goto out_irq; + } memset(dev->priv, 0, sizeof(struct net_local)); dev->open = net_open; @@ -277,6 +279,12 @@ int __init fmv18x_probe1(struct net_device *dev, short ioaddr) ether_setup(dev); return 0; + +out_irq: + free_irq(irq, dev); +out: + release_region(ioaddr, FMV18X_IO_EXTENT); + return retval; } @@ -603,8 +611,7 @@ static void set_multicast_list(struct net_device *dev) } #ifdef MODULE -static struct net_device dev_fmv18x = { init: fmv18x_probe }; - +static struct net_device dev_fmv18x; static int io = 0x220; static int irq; @@ -616,8 +623,9 @@ int init_module(void) { if (io == 0) printk("fmv18x: You should not use auto-probing with insmod!\n"); - dev_fmv18x.base_addr = io; - dev_fmv18x.irq = irq; + dev_fmv18x.base_addr = io; + dev_fmv18x.irq = irq; + dev_fmv18x.init = fmv18x_probe; if (register_netdev(&dev_fmv18x) != 0) { printk("fmv18x: register_netdev() returned non-zero.\n"); return -EIO; diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c index 9d278a1cc39f..48c01f0b372d 100644 --- a/drivers/net/hp-plus.c +++ b/drivers/net/hp-plus.c @@ -423,9 +423,6 @@ init_module(void) { int this_dev, found = 0; - if (load_8390_module("hp-plus.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_HPP_CARDS; this_dev++) { struct net_device *dev = &dev_hpp[this_dev]; dev->irq = irq[this_dev]; @@ -440,7 +437,6 @@ init_module(void) if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); return -ENXIO; } found++; @@ -464,7 +460,6 @@ cleanup_module(void) kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff --git a/drivers/net/hp.c b/drivers/net/hp.c index f36c341d2120..bd3ef30dd638 100644 --- a/drivers/net/hp.c +++ b/drivers/net/hp.c @@ -150,11 +150,11 @@ int __init hp_probe1(struct net_device *dev, int ioaddr) do { int irq = *irqp; if (request_irq (irq, NULL, 0, "bogus", NULL) != -EBUSY) { - autoirq_setup(0); + unsigned long cookie = probe_irq_on(); /* Twinkle the interrupt, and check if it's seen. */ outb_p(irqmap[irq] | HP_RUN, ioaddr + HP_CONFIGURE); outb_p( 0x00 | HP_RUN, ioaddr + HP_CONFIGURE); - if (irq == autoirq_report(0) /* It's a good IRQ line! */ + if (irq == probe_irq_off(cookie) /* It's a good IRQ line! */ && request_irq (irq, ei_interrupt, 0, "hp", dev) == 0) { printk(" selecting IRQ %d.\n", irq); dev->irq = *irqp; @@ -396,9 +396,6 @@ init_module(void) { int this_dev, found = 0; - if (load_8390_module("hp.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_HP_CARDS; this_dev++) { struct net_device *dev = &dev_hp[this_dev]; dev->irq = irq[this_dev]; @@ -413,7 +410,6 @@ init_module(void) if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); return -ENXIO; } found++; @@ -437,7 +433,6 @@ cleanup_module(void) kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c index c1674c550ee7..d524b5ef607d 100644 --- a/drivers/net/lne390.c +++ b/drivers/net/lne390.c @@ -394,9 +394,6 @@ int init_module(void) { int this_dev, found = 0; - if (load_8390_module("lne390.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_LNE_CARDS; this_dev++) { struct net_device *dev = &dev_lne[this_dev]; dev->irq = irq[this_dev]; @@ -410,7 +407,6 @@ int init_module(void) if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); return -ENXIO; } found++; @@ -434,7 +430,6 @@ void cleanup_module(void) kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff --git a/drivers/net/ne.c b/drivers/net/ne.c index 806f1e1148ff..133e8d1a199c 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c @@ -29,21 +29,22 @@ occur after memory is allocated for dev->priv. Deallocated memory last in cleanup_modue() Richard Guenther : Added support for ISAPnP cards - + Paul Gortmaker : Discontinued PCI support - use ne2k-pci.c instead. + */ /* Routines for the NatSemi-based designs (NE[12]000). */ -static const char *version = - "ne.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; +static const char version1[] = +"ne.c:v1.10 9/23/94 Donald Becker (becker@scyld.com)\n"; +static const char version2[] = +"Last modified Nov 1, 2000 by Paul Gortmaker\n"; #include -#include #include #include #include -#include #include #include #include @@ -70,28 +71,11 @@ static const char *version = /* A zero-terminated list of I/O addresses to be probed at boot. */ #ifndef MODULE -static unsigned int netcard_portlist[] __initdata = { +static unsigned int netcard_portlist[] __initdata = { 0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0 }; #endif -#ifdef CONFIG_PCI -/* Ack! People are making PCI ne2000 clones! Oh the horror, the horror... */ -static struct { unsigned short vendor, dev_id; char *name; } -pci_clone_list[] __initdata = { - {PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8029, "Realtek 8029" }, - {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C940, "Winbond 89C940" }, - {PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_RL2000, "Compex ReadyLink 2000" }, - {PCI_VENDOR_ID_KTI, PCI_DEVICE_ID_KTI_ET32P2, "KTI ET32P2" }, - {PCI_VENDOR_ID_NETVIN, PCI_DEVICE_ID_NETVIN_NV5000SC, "NetVin NV5000" }, - {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C926, "VIA 82C926 Amazon" }, - {PCI_VENDOR_ID_SURECOM, PCI_DEVICE_ID_SURECOM_NE34, "SureCom NE34"}, - {0,} -}; - -static int probe_pci = 1; -#endif - static struct { unsigned short vendor, function; char *name; } isapnp_clone_list[] __initdata = { {ISAPNP_VENDOR('E','D','I'), ISAPNP_FUNCTION(0x0216), "NN NE2000" }, @@ -114,7 +98,9 @@ bad_clone_list[] __initdata = { {"ET-100","ET-200", {0x00, 0x45, 0x54}}, /* YANG and YA clone */ {"COMPEX","COMPEX16",{0x00,0x80,0x48}}, /* Broken ISA Compex cards */ {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */ - {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */ + {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */ + {"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */ + {"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */ {0,} }; #endif @@ -132,15 +118,9 @@ bad_clone_list[] __initdata = { #define NESM_START_PG 0x40 /* First page of TX buffer */ #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ -/* Non-zero only if the current card is a PCI with BIOS-set IRQ. */ -static unsigned int pci_irq_line = 0; - int ne_probe(struct net_device *dev); static int ne_probe1(struct net_device *dev, int ioaddr); static int ne_probe_isapnp(struct net_device *dev); -#ifdef CONFIG_PCI -static int ne_probe_pci(struct net_device *dev); -#endif static int ne_open(struct net_device *dev); static int ne_close(struct net_device *dev); @@ -175,16 +155,9 @@ static void ne_block_output(struct net_device *dev, const int count, E2010 starts at 0x100 and ends at 0x4000. E2010-x starts at 0x100 and ends at 0xffff. */ -/* - * Note that at boot, this probe only picks up one card at a time, even for - * multiple PCI ne2k cards. Use "ether=0,0,eth1" if you have a second PCI - * ne2k card. This keeps things consistent regardless of the bus type of - * the card. - */ - int __init ne_probe(struct net_device *dev) { - int base_addr = dev ? dev->base_addr : 0; + unsigned int base_addr = dev ? dev->base_addr : 0; /* First check any supplied i/o locations. User knows best. */ if (base_addr > 0x1ff) /* Check a single specified location. */ @@ -192,12 +165,6 @@ int __init ne_probe(struct net_device *dev) else if (base_addr != 0) /* Don't probe at all. */ return -ENXIO; -#ifdef CONFIG_PCI - /* Then look for any installed PCI clones */ - if (probe_pci && pci_present() && (ne_probe_pci(dev) == 0)) - return 0; -#endif - /* Then look for any installed ISAPnP clones */ if (isapnp_present() && (ne_probe_isapnp(dev) == 0)) return 0; @@ -206,8 +173,6 @@ int __init ne_probe(struct net_device *dev) /* Last resort. The semi-risky ISA auto-probe. */ for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) { int ioaddr = netcard_portlist[base_addr]; - if (check_region(ioaddr, NE_IO_EXTENT)) - continue; if (ne_probe1(dev, ioaddr) == 0) return 0; } @@ -216,47 +181,10 @@ int __init ne_probe(struct net_device *dev) return -ENODEV; } -#ifdef CONFIG_PCI -static int __init ne_probe_pci(struct net_device *dev) -{ - int i; - - for (i = 0; pci_clone_list[i].vendor != 0; i++) { - struct pci_dev *pdev = NULL; - unsigned int pci_ioaddr = 0; - - while ((pdev = pci_find_device(pci_clone_list[i].vendor, pci_clone_list[i].dev_id, pdev))) { - if (pci_enable_device(pdev)) - continue; - pci_ioaddr = pci_resource_start (pdev, 0); - /* Avoid already found cards from previous calls */ - if (check_region(pci_ioaddr, NE_IO_EXTENT)) - continue; - pci_irq_line = pdev->irq; - if (pci_irq_line) break; /* Found it */ - } - if (!pdev) - continue; - printk(KERN_INFO "ne.c: PCI BIOS reports %s at i/o %#x, irq %d.\n", - pci_clone_list[i].name, - pci_ioaddr, pci_irq_line); - printk("*\n* Use of the PCI-NE2000 driver with this card is recommended!\n*\n"); - if (ne_probe1(dev, pci_ioaddr) != 0) { /* Shouldn't happen. */ - printk(KERN_ERR "ne.c: Probe of PCI card at %#x failed.\n", pci_ioaddr); - pci_irq_line = 0; - return -ENXIO; - } - pci_irq_line = 0; - return 0; - } - return -ENODEV; -} -#endif /* CONFIG_PCI */ - static int __init ne_probe_isapnp(struct net_device *dev) { int i; - + for (i = 0; isapnp_clone_list[i].vendor != 0; i++) { struct pci_dev *idev = NULL; @@ -269,14 +197,18 @@ static int __init ne_probe_isapnp(struct net_device *dev) continue; if (idev->activate(idev)) continue; - pci_irq_line = idev->irq_resource[0].start; /* if no irq, search for next */ - if (!pci_irq_line) + if (idev->irq_resource[0].start == 0) continue; /* found it */ - if (ne_probe1(dev, idev->resource[0].start) != 0) { /* Shouldn't happen. */ - printk(KERN_ERR "ne.c: Probe of ISAPnP card at %#lx failed.\n", - idev->resource[0].start); + dev->base_addr = idev->resource[0].start; + dev->irq = idev->irq_resource[0].start; + printk(KERN_INFO "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n", + isapnp_clone_list[i].name, + + dev->base_addr, dev->irq); + if (ne_probe1(dev, dev->base_addr) != 0) { /* Shouldn't happen. */ + printk(KERN_ERR "ne.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr); return -ENXIO; } ei_status.priv = (unsigned long)idev; @@ -284,9 +216,6 @@ static int __init ne_probe_isapnp(struct net_device *dev) } if (!idev) continue; - printk(KERN_INFO "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n", - isapnp_clone_list[i].name, - dev->base_addr, dev->irq); return 0; } @@ -301,11 +230,17 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) const char *name = NULL; int start_page, stop_page; int neX000, ctron, copam, bad_card; - int reg0 = inb_p(ioaddr); + int reg0, ret; static unsigned version_printed = 0; - if (reg0 == 0xFF) - return -ENODEV; + if (!request_region(ioaddr, NE_IO_EXTENT, dev->name)) + return -EBUSY; + + reg0 = inb_p(ioaddr); + if (reg0 == 0xFF) { + ret = -ENODEV; + goto err_out; + } /* Do a preliminary verification that we have a 8390. */ { @@ -318,12 +253,13 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) if (inb_p(ioaddr + EN0_COUNTER0) != 0) { outb_p(reg0, ioaddr); outb_p(regd, ioaddr + 0x0d); /* Restore the old values. */ - return -ENODEV; + ret = -ENODEV; + goto err_out; } } if (ei_debug && version_printed++ == 0) - printk(version); + printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2); printk(KERN_INFO "NE*000 ethercard probe at %#3x:", ioaddr); @@ -350,10 +286,11 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) break; } else { printk(" not found (no reset ack).\n"); - return -ENODEV; + ret = -ENODEV; + goto err_out; } } - + outb_p(0xff, ioaddr + EN0_ISR); /* Ack all intr. */ } @@ -362,7 +299,7 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) We can't reliably read the SAPROM address without this. (I learned the hard way!). */ { - struct {unsigned char value, offset; } program_seq[] = + struct {unsigned char value, offset; } program_seq[] = { {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/ {0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */ @@ -390,20 +327,10 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) wordlength = 1; } - /* At this point, wordlength *only* tells us if the SA_prom is doubled - up or not because some broken PCI cards don't respect the byte-wide - request in program_seq above, and hence don't have doubled up values. - These broken cards would otherwise be detected as an ne1000. */ - if (wordlength == 2) + { for (i = 0; i < 16; i++) SA_prom[i] = SA_prom[i+i]; - - if (pci_irq_line || ioaddr >= 0x400) - wordlength = 2; /* Catch broken PCI cards mentioned above. */ - - if (wordlength == 2) - { /* We must set the 8390 for word mode. */ outb_p(0x49, ioaddr + EN0_DCFG); start_page = NESM_START_PG; @@ -416,13 +343,12 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57); ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d); copam = (SA_prom[14] == 0x49 && SA_prom[15] == 0x00); - /* Set up the rest of the parameters. */ if (neX000 || bad_card || copam) { name = (wordlength == 2) ? "NE2000" : "NE1000"; } - else if (ctron) + else if (ctron) { name = (wordlength == 2) ? "Ctron-8" : "Ctron-16"; start_page = 0x01; @@ -433,13 +359,13 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) #ifdef SUPPORT_NE_BAD_CLONES /* Ack! Well, there might be a *bad* NE*000 clone there. Check for total bogus addresses. */ - for (i = 0; bad_clone_list[i].name8; i++) + for (i = 0; bad_clone_list[i].name8; i++) { if (SA_prom[0] == bad_clone_list[i].SAprefix[0] && SA_prom[1] == bad_clone_list[i].SAprefix[1] && - SA_prom[2] == bad_clone_list[i].SAprefix[2]) + SA_prom[2] == bad_clone_list[i].SAprefix[2]) { - if (wordlength == 2) + if (wordlength == 2) { name = bad_clone_list[i].name16; } else { @@ -448,31 +374,30 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) break; } } - if (bad_clone_list[i].name8 == NULL) + if (bad_clone_list[i].name8 == NULL) { printk(" not found (invalid signature %2.2x %2.2x).\n", SA_prom[14], SA_prom[15]); - return -ENXIO; + ret = -ENXIO; + goto err_out; } #else printk(" not found.\n"); - return -ENXIO; + ret = -ENXIO; + goto err_out; #endif } - if (pci_irq_line) - dev->irq = pci_irq_line; - - if (dev->irq < 2) + if (dev->irq < 2) { - autoirq_setup(0); + unsigned long cookie = probe_irq_on(); outb_p(0x50, ioaddr + EN0_IMR); /* Enable one interrupt. */ outb_p(0x00, ioaddr + EN0_RCNTLO); outb_p(0x00, ioaddr + EN0_RCNTHI); outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */ mdelay(10); /* wait 10ms for interrupt to propagate */ outb_p(0x00, ioaddr + EN0_IMR); /* Mask it again. */ - dev->irq = autoirq_report(0); + dev->irq = probe_irq_off(cookie); if (ei_debug > 2) printk(" autoirq is %d\n", dev->irq); } else if (dev->irq == 2) @@ -482,31 +407,27 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) if (! dev->irq) { printk(" failed to detect IRQ line.\n"); - return -EAGAIN; + ret = -EAGAIN; + goto err_out; } /* Allocate dev->priv and fill in 8390 specific dev fields. */ - if (ethdev_init(dev)) + if (ethdev_init(dev)) { printk (" unable to get memory for dev->priv.\n"); - return -ENOMEM; + ret = -ENOMEM; + goto err_out; } - + /* Snarf the interrupt now. There's no point in waiting since we cannot share and the board will usually be enabled. */ - - { - int irqval = request_irq(dev->irq, ei_interrupt, - pci_irq_line ? SA_SHIRQ : 0, name, dev); - if (irqval) { - printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval); - kfree(dev->priv); - dev->priv = NULL; - return -EAGAIN; - } + ret = request_irq(dev->irq, ei_interrupt, 0, name, dev); + if (ret) { + printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret); + goto err_out_kfree; } + dev->base_addr = ioaddr; - request_region(ioaddr, NE_IO_EXTENT, name); for(i = 0; i < ETHER_ADDR_LEN; i++) { printk(" %2.2x", SA_prom[i]); @@ -536,6 +457,13 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) dev->stop = &ne_close; NS8390_init(dev, 0); return 0; + +err_out_kfree: + kfree(dev->priv); + dev->priv = NULL; +err_out: + release_region(ioaddr, NE_IO_EXTENT); + return ret; } static int ne_open(struct net_device *dev) @@ -589,7 +517,7 @@ static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, i /* This *shouldn't* happen. If it does, it's the last thing you'll see */ - if (ei_status.dmaing) + if (ei_status.dmaing) { printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr " "[DMAstat:%d][irqlock:%d].\n", @@ -628,7 +556,7 @@ static void ne_block_input(struct net_device *dev, int count, struct sk_buff *sk char *buf = skb->data; /* This *shouldn't* happen. If it does, it's the last thing you'll see */ - if (ei_status.dmaing) + if (ei_status.dmaing) { printk(KERN_EMERG "%s: DMAing conflict in ne_block_input " "[DMAstat:%d][irqlock:%d].\n", @@ -642,10 +570,10 @@ static void ne_block_input(struct net_device *dev, int count, struct sk_buff *sk outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO); outb_p(ring_offset >> 8, nic_base + EN0_RSARHI); outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD); - if (ei_status.word16) + if (ei_status.word16) { insw(NE_BASE + NE_DATAPORT,buf,count>>1); - if (count & 0x01) + if (count & 0x01) { buf[count-1] = inb(NE_BASE + NE_DATAPORT); #ifdef NE_SANITY_CHECK @@ -662,7 +590,7 @@ static void ne_block_input(struct net_device *dev, int count, struct sk_buff *sk this message you either 1) have a slightly incompatible clone or 2) have noise/speed problems with your bus. */ - if (ei_debug > 1) + if (ei_debug > 1) { /* DMA termination address check... */ int addr, tries = 20; @@ -697,12 +625,12 @@ static void ne_block_output(struct net_device *dev, int count, /* Round the count up for word writes. Do we need to do this? What effect will an odd byte count have on the 8390? I should check someday. */ - + if (ei_status.word16 && (count & 0x01)) count++; /* This *shouldn't* happen. If it does, it's the last thing you'll see */ - if (ei_status.dmaing) + if (ei_status.dmaing) { printk(KERN_EMERG "%s: DMAing conflict in ne_block_output." "[DMAstat:%d][irqlock:%d]\n", @@ -722,7 +650,7 @@ retry: Crynwr packet driver -- the NatSemi method doesn't work. Actually this doesn't always work either, but if you have problems with your NEx000 this is better than nothing! */ - + outb_p(0x42, nic_base + EN0_RCNTLO); outb_p(0x00, nic_base + EN0_RCNTHI); outb_p(0x42, nic_base + EN0_RSARLO); @@ -752,8 +680,8 @@ retry: #ifdef NE_SANITY_CHECK /* This was for the ALPHA version only, but enough people have been encountering problems so it is still here. */ - - if (ei_debug > 1) + + if (ei_debug > 1) { /* DMA termination address check... */ int addr, tries = 20; @@ -765,7 +693,7 @@ retry: break; } while (--tries > 0); - if (tries <= 0) + if (tries <= 0) { printk(KERN_WARNING "%s: Tx packet transfer address mismatch," "%#4.4x (expected) vs. %#4.4x (actual).\n", @@ -801,10 +729,6 @@ MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); MODULE_PARM(bad, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); -#ifdef CONFIG_PCI -MODULE_PARM(probe_pci, "i"); -#endif - /* This is set up so that no ISA autoprobe takes place. We can't guarantee that the ne2k probe is the last 8390 based probe to take place (as it is at boot) and so the probe will get confused by any other 8390 cards. @@ -814,9 +738,6 @@ int init_module(void) { int this_dev, found = 0; - if (load_8390_module("ne.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { struct net_device *dev = &dev_ne[this_dev]; dev->irq = irq[this_dev]; @@ -833,8 +754,7 @@ int init_module(void) if (io[this_dev] != 0) printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]); else - printk(KERN_NOTICE "ne.c: No PCI cards found. Use \"io=0xNNN\" value(s) for ISA cards.\n"); - unload_8390_module(); + printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n"); return -ENXIO; } return 0; @@ -857,7 +777,6 @@ void cleanup_module(void) kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c index f43082c7f1e1..3ba20f197fbb 100644 --- a/drivers/net/ne2k-pci.c +++ b/drivers/net/ne2k-pci.c @@ -2,29 +2,48 @@ /* A Linux device driver for PCI NE2000 clones. - Authorship and other copyrights: - 1992-1998 by Donald Becker, NE2000 core and various modifications. + Authors and other copyright holders: + 1992-2000 by Donald Becker, NE2000 core and various modifications. 1995-1998 by Paul Gortmaker, core modifications and PCI support. - Copyright 1993 assigned to the United States Government as represented by the Director, National Security Agency. - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - 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 + This software may be used and distributed according to the terms of + the GNU General Public License (GPL), incorporated herein by reference. + Drivers based on or derived from this code fall under the GPL and must + retain the authorship, copyright and license notice. This file is not + a complete program and may only be used when the entire operating + system is licensed under the GPL. - People are making PCI ne2000 clones! Oh the horror, the horror... + The author may be reached as becker@scyld.com, or C/O + Scyld Computing Corporation + 410 Severn Ave., Suite 210 + Annapolis MD 21403 Issues remaining: - No full-duplex support. + People are making PCI ne2000 clones! Oh the horror, the horror... + Limited full-duplex support. */ -/* Our copyright info must remain in the binary. */ -static const char *version = -"ne2k-pci.c:vpre-1.00e 5/27/99 D. Becker/P. Gortmaker http://cesdis.gsfc.nasa.gov/linux/drivers/ne2k-pci.html\n"; +/* These identify the driver base version and may not be removed. */ +static const char version1[] = +"ne2k-pci.c:v1.02 10/19/2000 D. Becker/P. Gortmaker\n"; +static const char version2[] = +" http://www.scyld.com/network/ne2k-pci.html\n"; + +/* The user-configurable values. + These may be modified when a driver module is loaded.*/ + +static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ + +#define MAX_UNITS 8 /* More are supported, limit only on options */ +/* Used to pass the full-duplex flag, etc. */ +static int full_duplex[MAX_UNITS]; +static int options[MAX_UNITS]; + +/* Force a non std. amount of memory. Units are 256 byte pages. */ +/* #define PACKETBUF_MEMSIZE 0x40 */ + #include #include @@ -48,8 +67,11 @@ static const char *version = #define outsl outsl_ns #endif -/* Set statically or when loading the driver module. */ -static int debug = 1; +MODULE_AUTHOR("Donald Becker / Paul Gortmaker"); +MODULE_DESCRIPTION("PCI NE2000 clone driver"); +MODULE_PARM(debug, "i"); +MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); /* Some defines that people can play with if so inclined. */ @@ -59,19 +81,16 @@ static int debug = 1; /* Do we implement the read before write bugfix ? */ /* #define NE_RW_BUGFIX */ -/* Do we have a non std. amount of memory? (in units of 256 byte pages) */ -/* #define PACKETBUF_MEMSIZE 0x40 */ - -#define ne2k_flags reg0 /* Rename an existing field to store flags! */ - -/* Only the low 8 bits are usable for non-init-time flags! */ +/* Flags. We rename an existing ei_status field to store flags! */ +/* Thus only the low 8 bits are usable for non-init-time flags. */ +#define ne2k_flags reg0 enum { - HOLTEK_FDX=1, /* Full duplex -> set 0x80 at offset 0x20. */ - ONLY_16BIT_IO=2, ONLY_32BIT_IO=4, /* Chip can do only 16/32-bit xfers. */ + ONLY_16BIT_IO=8, ONLY_32BIT_IO=4, /* Chip can do only 16/32-bit xfers. */ + FORCE_FDX=0x20, /* User override. */ + REALTEK_FDX=0x40, HOLTEK_FDX=0x80, STOP_PG_0x60=0x100, }; - enum ne2k_pci_chipsets { CH_RealTek_RTL_8029 = 0, CH_Winbond_89C940, @@ -90,7 +109,7 @@ static struct { char *name; int flags; } pci_clone_list[] __devinitdata = { - {"RealTek RTL-8029", 0}, + {"RealTek RTL-8029", REALTEK_FDX}, {"Winbond 89C940", 0}, {"Compex RL2000", 0}, {"KTI ET32P2", 0}, @@ -145,7 +164,8 @@ static void ne2k_pci_block_output(struct net_device *dev, const int count, -/* No room in the standard 8390 structure for extra info we need. */ +/* There is no room in the standard 8390 structure for extra info we need, + so we build a meta/outer-wrapper structure.. */ struct ne2k_pci_card { struct net_device *dev; struct pci_dev *pci_dev; @@ -171,33 +191,35 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev; - int i, irq, reg0, start_page, stop_page; + int i; unsigned char SA_prom[32]; - int chip_idx = ent->driver_data; - static unsigned version_printed = 0; + int start_page, stop_page; + int irq, reg0, chip_idx = ent->driver_data; + static unsigned int fnd_cnt; long ioaddr; - - if (version_printed++ == 0) - printk(KERN_INFO "%s", version); + int flags = pci_clone_list[chip_idx].flags; + + if (fnd_cnt++ == 0) + printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2); ioaddr = pci_resource_start (pdev, 0); irq = pdev->irq; - + if (!ioaddr || ((pci_resource_flags (pdev, 0) & IORESOURCE_IO) == 0)) { printk (KERN_ERR "ne2k-pci: no I/O resource at PCI BAR #0\n"); return -ENODEV; } - + i = pci_enable_device (pdev); if (i) return i; - + if (request_region (ioaddr, NE_IO_EXTENT, "ne2k-pci") == NULL) { printk (KERN_ERR "ne2k-pci: I/O resource 0x%x @ 0x%lx busy\n", NE_IO_EXTENT, ioaddr); return -EBUSY; } - + reg0 = inb(ioaddr); if (reg0 == 0xFF) goto err_out_free_res; @@ -222,7 +244,7 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev, printk (KERN_ERR "ne2k-pci: cannot allocate ethernet device\n"); goto err_out_free_res; } - + /* Reset card. Who knows what dain-bramaged state it was left in. */ { unsigned long reset_start_time = jiffies; @@ -238,7 +260,7 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev, printk("ne2k-pci: Card failure (no reset ack).\n"); goto err_out_free_netdev; } - + outb(0xff, ioaddr + EN0_ISR); /* Ack all intr. */ } @@ -269,7 +291,7 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev, /* Note: all PCI cards have at least 16 bit access, so we don't have to check for 8 bit cards. Most cards permit 32 bit access. */ - if (pci_clone_list[chip_idx].flags & ONLY_32BIT_IO) { + if (flags & ONLY_32BIT_IO) { for (i = 0; i < 4 ; i++) ((u32 *)SA_prom)[i] = le32_to_cpu(inl(ioaddr + NE_DATAPORT)); } else @@ -280,8 +302,7 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev, outb(0x49, ioaddr + EN0_DCFG); start_page = NESM_START_PG; - stop_page = - pci_clone_list[chip_idx].flags&STOP_PG_0x60 ? 0x60 : NESM_STOP_PG; + stop_page = flags & STOP_PG_0x60 ? 0x60 : NESM_STOP_PG; /* Set up the rest of the parameters. */ dev->irq = irq; @@ -305,7 +326,11 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev, ei_status.tx_start_page = start_page; ei_status.stop_page = stop_page; ei_status.word16 = 1; - ei_status.ne2k_flags = pci_clone_list[chip_idx].flags; + ei_status.ne2k_flags = flags; + if (fnd_cnt < MAX_UNITS) { + if (full_duplex[fnd_cnt] > 0 || (options[fnd_cnt] & FORCE_FDX)) + ei_status.ne2k_flags |= FORCE_FDX; + } ei_status.rx_start_page = start_page + TX_PAGES; #ifdef PACKETBUF_MEMSIZE @@ -331,20 +356,27 @@ err_out_free_res: } -static int -ne2k_pci_open(struct net_device *dev) +static int ne2k_pci_open(struct net_device *dev) { MOD_INC_USE_COUNT; if (request_irq(dev->irq, ei_interrupt, SA_SHIRQ, dev->name, dev)) { MOD_DEC_USE_COUNT; return -EAGAIN; } + /* Set full duplex for the chips that we know about. */ + if (ei_status.ne2k_flags & FORCE_FDX) { + long ioaddr = dev->base_addr; + if (ei_status.ne2k_flags & REALTEK_FDX) { + outb(0xC0 + E8390_NODMA, ioaddr + NE_CMD); /* Page 3 */ + outb(inb(ioaddr + 0x20) | 0x80, ioaddr + 0x20); + } else if (ei_status.ne2k_flags & HOLTEK_FDX) + outb(inb(ioaddr + 0x20) | 0x80, ioaddr + 0x20); + } ei_open(dev); return 0; } -static int -ne2k_pci_close(struct net_device *dev) +static int ne2k_pci_close(struct net_device *dev) { ei_close(dev); free_irq(dev->irq, dev); @@ -354,8 +386,7 @@ ne2k_pci_close(struct net_device *dev) /* Hard reset the card. This used to pause for the same period that a 8390 reset command required, but that shouldn't be necessary. */ -static void -ne2k_pci_reset_8390(struct net_device *dev) +static void ne2k_pci_reset_8390(struct net_device *dev) { unsigned long reset_start_time = jiffies; @@ -380,8 +411,7 @@ ne2k_pci_reset_8390(struct net_device *dev) we don't need to be concerned with ring wrap as the header will be at the start of a page, so we optimize accordingly. */ -static void -ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) +static void ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) { long nic_base = dev->base_addr; @@ -418,8 +448,8 @@ ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int rin The NEx000 doesn't share the on-board packet memory -- you have to put the packet out through the "remote DMA" dataport using outb. */ -static void -ne2k_pci_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) +static void ne2k_pci_block_input(struct net_device *dev, int count, + struct sk_buff *skb, int ring_offset) { long nic_base = dev->base_addr; char *buf = skb->data; @@ -461,9 +491,8 @@ ne2k_pci_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ei_status.dmaing &= ~0x01; } -static void -ne2k_pci_block_output(struct net_device *dev, int count, - const unsigned char *buf, const int start_page) +static void ne2k_pci_block_output(struct net_device *dev, int count, + const unsigned char *buf, const int start_page) { long nic_base = NE_BASE; unsigned long dma_start; @@ -520,8 +549,8 @@ ne2k_pci_block_output(struct net_device *dev, int count, dma_start = jiffies; while ((inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) - if (jiffies - dma_start > 2) { /* Avoid clock roll-over. */ - printk("%s: timeout waiting for Tx RDC.\n", dev->name); + if (jiffies - dma_start > 2) { /* Avoid clock roll-over. */ + printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name); ne2k_pci_reset_8390(dev); NS8390_init(dev,1); break; @@ -536,12 +565,10 @@ ne2k_pci_block_output(struct net_device *dev, int count, static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - - if (!dev) { - printk (KERN_ERR "bug! ne2k_pci_remove_one called w/o net_device\n"); - return; - } - + + if (!dev) + BUG(); + unregister_netdev(dev); release_region(dev->base_addr, NE_IO_EXTENT); kfree(dev); @@ -559,43 +586,14 @@ static struct pci_driver ne2k_driver = { static int __init ne2k_pci_init(void) { - int rc; - - if (load_8390_module("ne2k-pci.c")) - return -ENOSYS; - - rc = pci_module_init (&ne2k_driver); - - /* XXX should this test CONFIG_HOTPLUG like pci_module_init? */ - - /* YYY No. If we're returning non-zero, we're being unloaded - * immediately. dwmw2 - */ - if (rc <= 0) - unload_8390_module(); - - return rc; + return pci_module_init (&ne2k_driver); } static void __exit ne2k_pci_cleanup(void) { pci_unregister_driver (&ne2k_driver); - unload_8390_module(); } module_init(ne2k_pci_init); module_exit(ne2k_pci_cleanup); - - -/* - * Local variables: - * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/ -c ne2k-pci.c" - * alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/ -c ne2k-pci.c" - * c-indent-level: 4 - * c-basic-offset: 4 - * tab-width: 4 - * version-control: t - * kept-new-versions: 5 - * End: - */ diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c index 02b70351b5a8..e57551271df5 100644 --- a/drivers/net/ne3210.c +++ b/drivers/net/ne3210.c @@ -44,7 +44,7 @@ static const char *version = #include "8390.h" int ne3210_probe(struct net_device *dev); -int ne3210_probe1(struct net_device *dev, int ioaddr); +static int ne3210_probe1(struct net_device *dev, int ioaddr); static int ne3210_open(struct net_device *dev); static int ne3210_close(struct net_device *dev); @@ -112,23 +112,26 @@ int __init ne3210_probe(struct net_device *dev) } /* EISA spec allows for up to 16 slots, but 8 is typical. */ - for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) { - if (check_region(ioaddr , NE3210_IO_EXTENT)) - continue; + for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) if (ne3210_probe1(dev, ioaddr) == 0) return 0; - } return -ENODEV; } -int __init ne3210_probe1(struct net_device *dev, int ioaddr) +static int __init ne3210_probe1(struct net_device *dev, int ioaddr) { - int i; + int i, retval; unsigned long eisa_id; const char *ifmap[] = {"UTP", "?", "BNC", "AUI"}; - if (inb_p(ioaddr + NE3210_ID_PORT) == 0xff) return -ENODEV; + if (!request_region(dev->base_addr, NE3210_IO_EXTENT, dev->name)) + return -EBUSY; + + if (inb_p(ioaddr + NE3210_ID_PORT) == 0xff) { + retval = -ENODEV; + goto out; + } #if NE3210_DEBUG & NE3210_D_PROBE printk("ne3210-debug: probe at %#x, ID %#8x\n", ioaddr, inl(ioaddr + NE3210_ID_PORT)); @@ -140,7 +143,8 @@ int __init ne3210_probe1(struct net_device *dev, int ioaddr) /* Check the EISA ID of the card. */ eisa_id = inl(ioaddr + NE3210_ID_PORT); if (eisa_id != NE3210_ID) { - return -ENODEV; + retval = -ENODEV; + goto out; } @@ -153,14 +157,16 @@ int __init ne3210_probe1(struct net_device *dev, int ioaddr) for(i = 0; i < ETHER_ADDR_LEN; i++) printk(" %02x", inb(ioaddr + NE3210_SA_PROM + i)); printk(" (invalid prefix).\n"); - return -ENODEV; + retval = -ENODEV; + goto out; } #endif /* Allocate dev->priv and fill in 8390 specific dev fields. */ if (ethdev_init(dev)) { printk ("ne3210.c: unable to allocate memory for dev->priv!\n"); - return -ENOMEM; + retval = -ENOMEM; + goto out; } printk("ne3210.c: NE3210 in EISA slot %d, media: %s, addr:", @@ -181,11 +187,10 @@ int __init ne3210_probe1(struct net_device *dev, int ioaddr) } printk(" IRQ %d,", dev->irq); - if (request_irq(dev->irq, ei_interrupt, 0, "ne3210", dev)) { + retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev); + if (retval) { printk (" unable to get IRQ %d.\n", dev->irq); - kfree(dev->priv); - dev->priv = NULL; - return -EAGAIN; + goto out1; } if (dev->mem_start == 0) { @@ -211,20 +216,16 @@ int __init ne3210_probe1(struct net_device *dev, int ioaddr) printk(KERN_CRIT "ne3210.c: Use EISA SCU to set card memory below 1MB,\n"); printk(KERN_CRIT "ne3210.c: or to an address above 0x%lx.\n", virt_to_bus(high_memory)); printk(KERN_CRIT "ne3210.c: Driver NOT installed.\n"); - free_irq(dev->irq, dev); - kfree(dev->priv); - dev->priv = NULL; - return -EINVAL; + retval = -EINVAL; + goto out2; } dev->mem_start = (unsigned long)ioremap(dev->mem_start, NE3210_STOP_PG*0x100); if (dev->mem_start == 0) { printk(KERN_ERR "ne3210.c: Unable to remap card memory above 1MB !!\n"); printk(KERN_ERR "ne3210.c: Try using EISA SCU to set memory below 1MB.\n"); printk(KERN_ERR "ne3210.c: Driver NOT installed.\n"); - free_irq(dev->irq, dev); - kfree(dev->priv); - dev->priv = NULL; - return -EAGAIN; + retval = -EAGAIN; + goto out2; } ei_status.reg0 = 1; /* Use as remap flag */ printk("ne3210.c: remapped %dkB card memory to virtual address %#lx\n", @@ -237,7 +238,6 @@ int __init ne3210_probe1(struct net_device *dev, int ioaddr) /* The 8390 offset is zero for the NE3210 */ dev->base_addr = ioaddr; - request_region(dev->base_addr, NE3210_IO_EXTENT, "ne3210"); ei_status.name = "NE3210"; ei_status.tx_start_page = NE3210_START_PG; @@ -257,6 +257,14 @@ int __init ne3210_probe1(struct net_device *dev, int ioaddr) dev->stop = &ne3210_close; NS8390_init(dev, 0); return 0; +out2: + free_irq(dev->irq, dev); +out1: + kfree(dev->priv); + dev->priv = NULL; +out: + release_region(ioaddr, NE3210_IO_EXTENT); + return retval; } /* @@ -367,9 +375,6 @@ int init_module(void) { int this_dev, found = 0; - if (load_8390_module("ne3210.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_NE3210_CARDS; this_dev++) { struct net_device *dev = &dev_ne3210[this_dev]; dev->irq = irq[this_dev]; @@ -383,7 +388,6 @@ int init_module(void) if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); return -ENXIO; } found++; @@ -398,16 +402,15 @@ void cleanup_module(void) for (this_dev = 0; this_dev < MAX_NE3210_CARDS; this_dev++) { struct net_device *dev = &dev_ne3210[this_dev]; if (dev->priv != NULL) { - void *priv = dev->priv; free_irq(dev->irq, dev); release_region(dev->base_addr, NE3210_IO_EXTENT); if (ei_status.reg0) iounmap((void *)dev->mem_start); unregister_netdev(dev); - kfree(priv); + kfree(dev->priv); + dev->priv = NULL; } } - unload_8390_module(); } #endif /* MODULE */ diff --git a/drivers/net/oaknet.c b/drivers/net/oaknet.c index e24e0e4f0498..f3d2c5426a72 100644 --- a/drivers/net/oaknet.c +++ b/drivers/net/oaknet.c @@ -664,25 +664,10 @@ oaknet_dma_error(struct net_device *dev, const char *name) */ static int __init oaknet_init_module (void) { - int status; - - /* - * We're dependent on the 8390 generic driver module, make - * sure its symbols are loaded. - */ - - if (load_8390_module("oaknet.c")) - return (-ENOSYS); - if (oaknet_devs != NULL) return (-EBUSY); - status = oaknet_init() - - if (status != 0) - unload_8390_module(); - - return (status); + return (oaknet_init()); } /* @@ -704,7 +689,6 @@ static void __exit oaknet_cleanup_module (void) oaknet_devs = NULL; - unload_8390_module(); } module_init(oaknet_init_module); diff --git a/drivers/net/pcmcia/xircom_tulip_cb.c b/drivers/net/pcmcia/xircom_tulip_cb.c index c5f5d34de6c2..1b9d83417fd1 100644 --- a/drivers/net/pcmcia/xircom_tulip_cb.c +++ b/drivers/net/pcmcia/xircom_tulip_cb.c @@ -466,7 +466,7 @@ static void outl_CSR6 (u32 newcsr6, long ioaddr, int chip_idx) restore_flags(flags); return; } - newcsr6 &= 0x726cfeca; /* mask out the reserved CSR6 bits that always */ + newcsr6 &= 0x726cfecb; /* 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); @@ -1350,7 +1350,7 @@ tulip_up(struct net_device *dev) 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].buffer1 = virt_to_bus(tp->setup_frame); tp->tx_ring[0].status = DescOwned; tp->cur_tx++; diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 05d0c06d1a56..7714370c9dab 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -292,9 +292,7 @@ static int pppoe_device_event(struct notifier_block *this, static struct notifier_block pppoe_notifier = { - pppoe_device_event, - NULL, - 0 + notifier_call: pppoe_device_event, }; diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c index 532a0f9e7aaa..e60c41f74982 100644 --- a/drivers/net/seeq8005.c +++ b/drivers/net/seeq8005.c @@ -279,11 +279,11 @@ static int __init seeq8005_probe1(struct net_device *dev, int ioaddr) if (dev->irq == 0xff) ; /* Do nothing: a user-level program will set it. */ else if (dev->irq < 2) { /* "Auto-IRQ" */ - autoirq_setup(0); + unsigned long cookie = probe_irq_on(); outw( SEEQCMD_RX_INT_EN | SEEQCMD_SET_RX_ON | SEEQCMD_SET_RX_OFF, SEEQ_CMD ); - dev->irq = autoirq_report(0); + dev->irq = probe_irq_off(cookie); if (net_debug >= 2) printk(" autoirq is %d\n", dev->irq); diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 9185f428f4bc..bf64b5e1aa27 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -62,15 +62,13 @@ static int max_interrupt_work = 20; static int multicast_filter_limit = 128; #define sis900_debug debug -static int sis900_debug = 0; +static int sis900_debug; /* Time in jiffies before concluding the transmitter is hung. */ #define TX_TIMEOUT (4*HZ) /* SiS 900 is capable of 32 bits BM DMA */ #define SIS900_DMA_MASK 0xffffffff -static struct net_device * sis900_mac_probe (struct pci_dev * pci_dev, - char *card_name); enum { SIS_900 = 0, SIS_7016 @@ -172,38 +170,8 @@ static void set_rx_mode(struct net_device *net_dev); static void sis900_reset(struct net_device *net_dev); static void sis630e_set_eq(struct net_device *net_dev); -/* walk through every ethernet PCI devices to see if some of them are matched with our card list*/ -static int __init sis900_probe (struct pci_dev *pci_dev, const struct pci_device_id *pci_id) -{ - u32 pci_io_base; - - if (!pci_dma_supported(pci_dev, SIS900_DMA_MASK)) { - printk(KERN_ERR "sis900.c: architecture does not support " - "32bit PCI busmaster DMA\n"); - return -ENODEV; - } - - pci_io_base = pci_resource_start(pci_dev, 0); - if (check_region(pci_io_base, SIS900_TOTAL_SIZE)) { - printk(KERN_ERR "sis900.c: can't allocate I/O space at 0x%08x\n", - pci_io_base); - return -ENODEV; - } - - /* setup various bits in PCI command register */ - if (pci_enable_device (pci_dev)) - return -ENODEV; - pci_set_master(pci_dev); - - /* do the real low level jobs */ - if (sis900_mac_probe(pci_dev, card_names[pci_id->driver_data]) == NULL) - return -ENODEV; - - return 0; -} - /* older SiS900 and friends, use EEPROM to store MAC address */ -static int sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev) +static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev) { long ioaddr = pci_resource_start(pci_dev, 0); u16 signature; @@ -225,7 +193,7 @@ static int sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_ } /* SiS630E model, use APC CMOS RAM to store MAC address */ -static int sis630e_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev) +static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev) { struct pci_dev *isa_bridge = NULL; u8 reg; @@ -247,17 +215,36 @@ static int sis630e_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net return 1; } -static struct net_device * __init sis900_mac_probe (struct pci_dev * pci_dev, char * card_name) +static int __devinit sis900_probe (struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { struct sis900_private *sis_priv; long ioaddr = pci_resource_start(pci_dev, 0); - struct net_device *net_dev = NULL; + struct net_device *net_dev; int irq = pci_dev->irq; int i, ret = 0; u8 revision; + char *card_name = card_names[pci_id->driver_data]; + + if (!pci_dma_supported(pci_dev, SIS900_DMA_MASK)) { + printk(KERN_ERR "sis900.c: architecture does not support " + "32bit PCI busmaster DMA\n"); + return -ENODEV; + } + + /* setup various bits in PCI command register */ + if (pci_enable_device (pci_dev)) + return -ENODEV; + pci_set_master(pci_dev); - if ((net_dev = init_etherdev(net_dev, 0)) == NULL) - return NULL; + net_dev = init_etherdev(NULL, sizeof(struct sis900_private)); + if (!net_dev) + return -ENOMEM; + + if (!request_region(ioaddr, SIS900_TOTAL_SIZE, net_dev->name)) { + printk(KERN_ERR "sis900.c: can't allocate I/O space at 0x%lX\n", ioaddr); + ret = -EBUSY; + goto err_out; + } pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision); if (revision == SIS630E_REV || revision == SIS630EA1_REV) @@ -268,8 +255,8 @@ static struct net_device * __init sis900_mac_probe (struct pci_dev * pci_dev, ch ret = sis900_get_mac_addr(pci_dev, net_dev); if (ret == 0) { - unregister_netdevice(net_dev); - return NULL; + ret = -ENODEV; + goto err_out_region; } /* print some information about our NIC */ @@ -279,16 +266,9 @@ static struct net_device * __init sis900_mac_probe (struct pci_dev * pci_dev, ch printk("%2.2x:", (u8)net_dev->dev_addr[i]); printk("%2.2x.\n", net_dev->dev_addr[i]); - if ((net_dev->priv = kmalloc(sizeof(struct sis900_private), GFP_KERNEL)) == NULL) { - unregister_netdevice(net_dev); - return NULL; - } - sis_priv = net_dev->priv; - memset(sis_priv, 0, sizeof(struct sis900_private)); /* We do a request_region() to register /proc/ioports info. */ - request_region(ioaddr, SIS900_TOTAL_SIZE, net_dev->name); net_dev->base_addr = ioaddr; net_dev->irq = irq; sis_priv->pci_dev = pci_dev; @@ -296,10 +276,8 @@ static struct net_device * __init sis900_mac_probe (struct pci_dev * pci_dev, ch /* probe for mii transciver */ if (sis900_mii_probe(net_dev) == 0) { - unregister_netdev(net_dev); - kfree(sis_priv); - release_region(ioaddr, SIS900_TOTAL_SIZE); - return NULL; + ret = -ENODEV; + goto err_out_region; } pci_dev->driver_data = net_dev; @@ -315,7 +293,14 @@ static struct net_device * __init sis900_mac_probe (struct pci_dev * pci_dev, ch net_dev->tx_timeout = sis900_tx_timeout; net_dev->watchdog_timeo = TX_TIMEOUT; - return net_dev; + return 0; + +err_out_region: + release_region(ioaddr, SIS900_TOTAL_SIZE); +err_out: + unregister_netdev(net_dev); + kfree(net_dev); + return ret; } static int __init sis900_mii_probe (struct net_device * net_dev) @@ -1431,15 +1416,12 @@ static void sis900_reset(struct net_device *net_dev) outl(PESEL, ioaddr + cfg); } -static void __exit sis900_remove(struct pci_dev *pci_dev) +static void __devexit sis900_remove(struct pci_dev *pci_dev) { struct net_device *net_dev = pci_dev->driver_data; - struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv; unregister_netdev(net_dev); release_region(net_dev->base_addr, SIS900_TOTAL_SIZE); - - kfree(sis_priv); kfree(net_dev); } @@ -1454,16 +1436,9 @@ static struct pci_driver sis900_pci_driver = { static int __init sis900_init_module(void) { - if (!pci_present()) /* No PCI bus in this machine! */ - return -ENODEV; - printk(KERN_INFO "%s", version); - if (!pci_register_driver(&sis900_pci_driver)) { - pci_unregister_driver(&sis900_pci_driver); - return -ENODEV; - } - return 0; + return pci_module_init(&sis900_pci_driver); } static void __exit sis900_cleanup_module(void) diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c index 0f41a233db1f..c36f2f379e15 100644 --- a/drivers/net/smc-mca.c +++ b/drivers/net/smc-mca.c @@ -455,9 +455,6 @@ int init_module(void) { int this_dev, found = 0; - if (load_8390_module("wd.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_ULTRAMCA_CARDS; this_dev++) { struct net_device *dev = &dev_ultra[this_dev]; dev->irq = irq[this_dev]; @@ -468,7 +465,6 @@ int init_module(void) if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); printk(KERN_NOTICE "smc-mca.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]); return -ENXIO; } @@ -493,7 +489,6 @@ void cleanup_module(void) kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c index f106732a7d94..e5632db93745 100644 --- a/drivers/net/smc-ultra.c +++ b/drivers/net/smc-ultra.c @@ -429,9 +429,6 @@ init_module(void) { int this_dev, found = 0; - if (load_8390_module("smc-ultra.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) { struct net_device *dev = &dev_ultra[this_dev]; dev->irq = irq[this_dev]; @@ -444,7 +441,6 @@ init_module(void) if (register_netdev(dev) != 0) { printk(KERN_WARNING "smc-ultra.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]); if (found != 0) return 0; /* Got at least one. */ - unload_8390_module(); return -ENXIO; } found++; @@ -468,7 +464,6 @@ cleanup_module(void) kfree(dev->priv); } } - unload_8390_module(); } #endif /* MODULE */ diff --git a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c index 9d54e2d05c63..ba387049ce94 100644 --- a/drivers/net/smc-ultra32.c +++ b/drivers/net/smc-ultra32.c @@ -365,9 +365,6 @@ int init_module(void) { int this_dev, found = 0; - if (load_8390_module("smc-ultra32.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_ULTRA32_CARDS; this_dev++) { struct net_device *dev = &dev_ultra[this_dev]; dev->init = ultra32_probe; @@ -375,7 +372,6 @@ int init_module(void) if (found > 0) { /* Got at least one. */ return 0; } - unload_8390_module(); printk(KERN_WARNING "smc-ultra32.c: No SMC Ultra32 found.\n"); return -ENXIO; } @@ -399,6 +395,5 @@ void cleanup_module(void) kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff --git a/drivers/net/stnic.c b/drivers/net/stnic.c index e652711197e9..12c8b2b554a1 100644 --- a/drivers/net/stnic.c +++ b/drivers/net/stnic.c @@ -105,9 +105,6 @@ int __init stnic_probe(void) if (! MACH_SE) return -ENODEV; - if (load_8390_module ("stnic.c")) - return -ENOSYS; - /* New style probing API */ dev = init_etherdev (0, 0); stnic_dev = dev; @@ -313,6 +310,4 @@ do_stnic_intr (int irq, void *dev_id, struct pt_regs *regs) } module_init(stnic_probe); -/* No cleanup routine - if there were one, it should do a: - unload_8390_module() -*/ +/* No cleanup routine. */ diff --git a/drivers/net/tulip/21142.c b/drivers/net/tulip/21142.c index 8398e1bea4ed..60cc79b7583c 100644 --- a/drivers/net/tulip/21142.c +++ b/drivers/net/tulip/21142.c @@ -115,7 +115,7 @@ void t21142_start_nway(struct net_device *dev) outl(csr14, ioaddr + CSR14); if (tp->chip_id == PNIC2) tp->csr6 = 0x01a80000 | (tp->to_advertise & 0x0040 ? 0x0200 : 0); - else + else tp->csr6 = 0x82420000 | (tp->to_advertise & 0x0040 ? 0x0200 : 0); tulip_outl_csr(tp, tp->csr6, CSR6); if (tp->mtable && tp->mtable->csr15dir) { diff --git a/drivers/net/tulip/ChangeLog b/drivers/net/tulip/ChangeLog new file mode 100644 index 000000000000..6c37fb68326f --- /dev/null +++ b/drivers/net/tulip/ChangeLog @@ -0,0 +1,29 @@ +2000-11-02 Jeff Garzik + + * tulip_core.c (set_rx_mode): This is synchronized via + dev->xmit_lock, so only the queueing of the setup frame needs to + be locked, against tulip_interrupt. + +2000-11-02 Alexey Kuznetov + + * timer.c (tulip_timer): Call netif_carrier_{on,off} to report + link state to the rest of the kernel, and userspace. + * interrupt.c (tulip_interrupt): Remove tx_full. + * tulip.h: Likewise. + * tulip_core.c (tulip_init_ring, tulip_start_xmit, set_rx_mode): + Likewise. + +2000-10-18 Jeff Garzik + + * tulip_core.c: (tulip_init_one) Print out ethernet interface + on error. Print out a message when pci_enable_device fails. + Handle DMA alloc failure. + +2000-10-18 Jeff Garzik + + * Makefile: New file. + * tulip_core.c (tulip_init_one): Correct error messages + on PIO/MMIO region reserve failure. + (tulip_init_one) Add new check to ensure that PIO region is + sufficient for our needs. + diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c index 2a4a7c2012a6..5014726c3031 100644 --- a/drivers/net/tulip/interrupt.c +++ b/drivers/net/tulip/interrupt.c @@ -19,7 +19,7 @@ int tulip_rx_copybreak; -int tulip_max_interrupt_work; +unsigned int tulip_max_interrupt_work; @@ -177,12 +177,17 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) int maxrx = RX_RING_SIZE; int maxtx = TX_RING_SIZE; int maxoi = TX_RING_SIZE; - int work_count = tulip_max_interrupt_work; - + unsigned int work_count = tulip_max_interrupt_work; + + /* Let's see whether the interrupt really is for us */ + csr5 = inl(ioaddr + CSR5); + + if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) + return; + tp->nir++; do { - csr5 = inl(ioaddr + CSR5); /* Acknowledge all of the current interrupt sources ASAP. */ outl(csr5 & 0x0001ffff, ioaddr + CSR5); @@ -190,9 +195,6 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", dev->name, csr5, inl(dev->base_addr + CSR5)); - if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) - break; - if (csr5 & (RxIntr | RxNoBuf)) { rx += tulip_rx(dev); tulip_refill_rx(dev); @@ -221,7 +223,7 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) PCI_DMA_TODEVICE); continue; } - + if (status & 0x8000) { /* There was an major error, log it. */ #ifndef final_version @@ -256,17 +258,14 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) #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); + printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d.\n", + dev->name, dirty_tx, tp->cur_tx); dirty_tx += TX_RING_SIZE; } #endif - if (tp->tx_full && tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) { - /* The ring is no longer full, clear tbusy. */ - tp->tx_full = 0; + if (tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) netif_wake_queue(dev); - } tp->dirty_tx = dirty_tx; if (csr5 & TxDied) { @@ -330,22 +329,28 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) /* Acknowledge all interrupt sources. */ outl(0x8001ffff, ioaddr + CSR5); if (tp->flags & HAS_INTR_MITIGATION) { - /* Josip Loncaric at ICASE did extensive experimentation + /* Josip Loncaric at ICASE did extensive experimentation to develop a good interrupt mitigation setting.*/ outl(0x8b240000, ioaddr + CSR11); } else { - /* Mask all interrupting sources, set timer to + /* Mask all interrupting sources, set timer to re-enable. */ outl(((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt, ioaddr + CSR7); outl(0x0012, ioaddr + CSR11); } break; } - } while (work_count-- > 0); + + work_count--; + if (work_count == 0) + break; + + csr5 = inl(ioaddr + CSR5); + } while ((csr5 & (NormalIntr|AbnormalIntr)) != 0); tulip_refill_rx(dev); - /* check if we card is in suspend mode */ + /* check if the card is in suspend mode */ entry = tp->dirty_rx % RX_RING_SIZE; if (tp->rx_buffers[entry].skb == NULL) { if (tulip_debug > 1) diff --git a/drivers/net/tulip/timer.c b/drivers/net/tulip/timer.c index f8b06c58f0fa..357454359d44 100644 --- a/drivers/net/tulip/timer.c +++ b/drivers/net/tulip/timer.c @@ -130,13 +130,15 @@ void tulip_timer(unsigned long data) /* Check that the specified bit has the proper value. */ if ((bitnum < 0) != ((csr12 & (1 << ((bitnum >> 1) & 7))) != 0)) { - if (tulip_debug > 1) + if (tulip_debug > 2) 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; + netif_carrier_on(dev); break; } + netif_carrier_off(dev); if (tp->medialock) break; select_next_media: @@ -160,7 +162,10 @@ void tulip_timer(unsigned long data) } case 1: case 3: /* 21140, 21142 MII */ actually_mii: - tulip_check_duplex(dev); + if (tulip_check_duplex(dev) < 0) + netif_carrier_off(dev); + else + netif_carrier_on(dev); next_tick = 60*HZ; break; case 2: /* 21142 serial block has no link beat. */ diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h index 4e21319ba4e1..d0668cf42d82 100644 --- a/drivers/net/tulip/tulip.h +++ b/drivers/net/tulip/tulip.h @@ -208,7 +208,7 @@ enum t21143_csr6_bits { csr6_ho = (1<<2), /* Hash-only filtering mode: can't be set */ csr6_sr = (1<<1), /* Start(1)/Stop(0) Receive */ csr6_hp = (1<<0), /* Hash/Perfect Receive Filtering Mode: can't be set */ - + csr6_mask_capture = (csr6_sc | csr6_ca), csr6_mask_defstate = (csr6_mask_capture | csr6_mbo), csr6_mask_hdcap = (csr6_mask_defstate | csr6_hbd | csr6_ps), @@ -340,7 +340,6 @@ struct tulip_private { spinlock_t lock; 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. */ @@ -389,7 +388,7 @@ void tulip_parse_eeprom(struct net_device *dev); int tulip_read_eeprom(long ioaddr, int location, int addr_len); /* interrupt.c */ -extern int tulip_max_interrupt_work; +extern unsigned int tulip_max_interrupt_work; extern int tulip_rx_copybreak; void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs); @@ -436,5 +435,4 @@ static inline void tulip_restart_rxtx(struct tulip_private *tp, u32 csr6mask) tulip_outl_csr(tp, csr6mask | csr6_st | csr6_sr, CSR6); } - #endif /* __NET_TULIP_H__ */ diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 19d4f8f5e5f5..de4af6890a68 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -7,11 +7,11 @@ This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference. - + Please read Documentation/networking/tulip.txt for more information. - For this specific driver variant please use linux-kernel for + For this specific driver variant please use linux-kernel for bug reports. Additional information available at @@ -28,13 +28,13 @@ #include static char version[] __devinitdata = - "Linux Tulip driver version 0.9.10 (September 6, 2000)\n"; + "Linux Tulip driver version 0.9.11 (November 3, 2000)\n"; /* A few user-configurable values. */ /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static int max_interrupt_work = 25; +static unsigned int max_interrupt_work = 25; #define MAX_UNITS 8 /* Used to pass the full-duplex flag, etc. */ @@ -415,11 +415,11 @@ tulip_open(struct net_device *dev) } tulip_init_ring (dev); - + tulip_up (dev); - + netif_start_queue (dev); - + return 0; } @@ -429,7 +429,7 @@ static void tulip_tx_timeout(struct net_device *dev) struct tulip_private *tp = (struct tulip_private *)dev->priv; long ioaddr = dev->base_addr; unsigned long flags; - + DPRINTK("ENTER\n"); spin_lock_irqsave (&tp->lock, flags); @@ -541,7 +541,6 @@ static void tulip_init_ring(struct net_device *dev) DPRINTK("ENTER\n"); - tp->tx_full = 0; tp->cur_rx = tp->cur_tx = 0; tp->dirty_rx = tp->dirty_tx = 0; tp->susp_rx = 0; @@ -597,9 +596,6 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) u32 flag; dma_addr_t mapping; - /* Caution: the write order is important here, set the field - with the ownership bits last. */ - spin_lock_irq(&tp->lock); /* Calculate the next Tx descriptor entry. */ @@ -618,7 +614,6 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) } 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. */ - tp->tx_full = 1; flag = 0xe0000000; /* Tx-done intr. */ netif_stop_queue(dev); } @@ -626,7 +621,11 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev) flag = 0xe0000000 | DESC_RING_WRAP; tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); + /* if we were using Transmit Automatic Polling, we would need a + * wmb() here. */ tp->tx_ring[entry].status = cpu_to_le32(DescOwned); + wmb(); + tp->cur_tx++; /* Trigger an immediate transmit demand. */ @@ -670,14 +669,14 @@ static void tulip_down (struct net_device *dev) if (tp->flags & HAS_ACPI) pci_write_config_dword (tp->pdev, 0x40, 0x40000000); } - - + + static int tulip_close (struct net_device *dev) { long ioaddr = dev->base_addr; struct tulip_private *tp = (struct tulip_private *) dev->priv; int i; - + netif_stop_queue (dev); tulip_down (dev); @@ -846,18 +845,77 @@ static inline u32 ether_crc(int length, unsigned char *data) return crc; } +#undef set_bit_le +#define set_bit_le(i,p) do { ((char *)(p))[(i)/8] |= (1<<((i)%8)); } while(0) + +static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) +{ + struct tulip_private *tp = (struct tulip_private *)dev->priv; + u16 hash_table[32]; + struct dev_mc_list *mclist; + int i; + u16 *eaddrs; + + memset(hash_table, 0, sizeof(hash_table)); + set_bit_le(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) { + int index = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff; + + set_bit_le(index, 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]; + } + + /* 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]; +} + +static void build_setup_frame_perfect(u16 *setup_frm, struct net_device *dev) +{ + struct tulip_private *tp = (struct tulip_private *)dev->priv; + struct dev_mc_list *mclist; + int i; + u16 *eaddrs; + + /* 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; *setup_frm++ = *eaddrs++; + *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; + *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; + } + /* 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]; +} + + static void set_rx_mode(struct net_device *dev) { struct tulip_private *tp = (struct tulip_private *)dev->priv; long ioaddr = dev->base_addr; - int csr6, need_lock = 0; - unsigned long flags; + int csr6; DPRINTK("ENTER\n"); - spin_lock_irqsave(&tp->lock, flags); csr6 = inl(ioaddr + CSR6) & ~0x00D5; - spin_unlock_irqrestore(&tp->lock, flags); tp->csr6 &= ~0x00D5; if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ @@ -865,14 +923,10 @@ static void set_rx_mode(struct net_device *dev) csr6 |= 0x00C0; /* Unconditionally log net taps. */ printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name); - - need_lock = 1; } else if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) { /* Too many to filter well -- accept all multicasts. */ tp->csr6 |= 0x0080; csr6 |= 0x0080; - - need_lock = 1; } else if (tp->flags & MC_HASH_ONLY) { /* Some work-alikes have only a 64-entry hash filter table. */ /* Should verify correctness on big-endian/__powerpc__ */ @@ -882,7 +936,6 @@ static void set_rx_mode(struct net_device *dev) if (dev->mc_count > 64) { /* Arbitrary non-effective limit. */ tp->csr6 |= 0x0080; csr6 |= 0x0080; - need_lock = 1; } else { mc_filter[1] = mc_filter[0] = 0; for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; @@ -890,71 +943,32 @@ static void set_rx_mode(struct net_device *dev) set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr)>>26, mc_filter); if (tp->chip_id == AX88140) { - spin_lock_irqsave(&tp->lock, flags); outl(2, ioaddr + CSR13); outl(mc_filter[0], ioaddr + CSR14); outl(3, ioaddr + CSR13); outl(mc_filter[1], ioaddr + CSR14); - /* need_lock = 0; */ } else if (tp->chip_id == COMET) { /* Has a simple hash filter. */ - spin_lock_irqsave(&tp->lock, flags); outl(mc_filter[0], ioaddr + 0xAC); outl(mc_filter[1], ioaddr + 0xB0); - /* need_lock = 0; */ - } else { - need_lock = 1; } } - } else { - u16 *eaddrs, *setup_frm = tp->setup_frame; - struct dev_mc_list *mclist; - u32 tx_flags = 0x08000000 | 192; - int i; + unsigned long flags; /* 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) { /* 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]; + build_setup_frame_hash(tp->setup_frame, dev); } else { - /* 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) { - u16 *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]; + build_setup_frame_perfect(tp->setup_frame, dev); } - /* 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]; - spin_lock_irqsave(&tp->lock, flags); if (tp->cur_tx - tp->dirty_tx > TX_RING_SIZE - 2) { /* Same setup recently queued, we need not add it. */ } else { + u32 tx_flags = 0x08000000 | 192; unsigned int entry; int dummy = -1; @@ -988,24 +1002,18 @@ static void set_rx_mode(struct net_device *dev) tp->tx_ring[entry].status = cpu_to_le32(DescOwned); if (dummy >= 0) tp->tx_ring[dummy].status = cpu_to_le32(DescOwned); - if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) { + if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) netif_stop_queue(dev); - tp->tx_full = 1; - } /* Trigger an immediate transmit demand. */ outl(0, ioaddr + CSR1); - } + + spin_unlock_irqrestore(&tp->lock, flags); } - - if (need_lock) - spin_lock_irqsave(&tp->lock, flags); /* Can someone explain to me what the OR here is supposed to accomplish???? */ tulip_outl_csr(tp, csr6 | 0x0000, CSR6); - - spin_unlock_irqrestore(&tp->lock, flags); } @@ -1026,7 +1034,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, long ioaddr; static int board_idx = -1; int chip_idx = ent->driver_data; - + board_idx++; if (tulip_debug > 0 && did_version++ == 0) @@ -1036,7 +1044,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, printk (KERN_ERR PFX "skipping LMC card.\n"); return -ENODEV; } - + ioaddr = pci_resource_start (pdev, 0); irq = pdev->irq; @@ -1047,25 +1055,37 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, return -ENOMEM; } + if (pci_resource_len (pdev, 0) < tulip_tbl[chip_idx].io_size) { + printk (KERN_ERR PFX "%s: I/O region (0x%lx@0x%lx) too small, " + "aborting\n", dev->name, pci_resource_len (pdev, 0), + pci_resource_start (pdev, 0)); + goto err_out_free_netdev; + } + /* grab all resources from both PIO and MMIO regions, as we * don't want anyone else messing around with our hardware */ if (!request_region (pci_resource_start (pdev, 0), pci_resource_len (pdev, 0), dev->name)) { - printk (KERN_ERR PFX "I/O ports (0x%x@0x%lx) unavailable, " - "aborting\n", tulip_tbl[chip_idx].io_size, ioaddr); + printk (KERN_ERR PFX "%s: I/O region (0x%lx@0x%lx) unavailable, " + "aborting\n", dev->name, pci_resource_len (pdev, 0), + pci_resource_start (pdev, 0)); goto err_out_free_netdev; } if (!request_mem_region (pci_resource_start (pdev, 1), pci_resource_len (pdev, 1), dev->name)) { - printk (KERN_ERR PFX "MMIO resource (0x%x@0x%lx) unavailable, " - "aborting\n", tulip_tbl[chip_idx].io_size, ioaddr); + printk (KERN_ERR PFX "%s: MMIO region (0x%lx@0x%lx) unavailable, " + "aborting\n", dev->name, pci_resource_len (pdev, 1), + pci_resource_start (pdev, 1)); goto err_out_free_pio_res; } - if (pci_enable_device(pdev)) + if (pci_enable_device(pdev)) { + printk (KERN_ERR PFX "%s: Cannot enable PCI device, aborting\n", + dev->name); goto err_out_free_mmio_res; + } pci_set_master(pdev); @@ -1081,6 +1101,8 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, sizeof(struct tulip_rx_desc) * RX_RING_SIZE + sizeof(struct tulip_tx_desc) * TX_RING_SIZE, &tp->rx_ring_dma); + if (!tp->rx_ring) + goto err_out_free_mmio_res; tp->tx_ring = (struct tulip_tx_desc *)(tp->rx_ring + RX_RING_SIZE); tp->tx_ring_dma = tp->rx_ring_dma + sizeof(struct tulip_rx_desc) * RX_RING_SIZE; @@ -1122,7 +1144,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, tulip_stop_rxtx(tp, inl(ioaddr + CSR6)); /* Clear the missed-packet counter. */ - (volatile int)inl(ioaddr + CSR8); + inl(ioaddr + CSR8); if (chip_idx == DC21041) { if (inl(ioaddr + CSR9) & 0x8000) { @@ -1240,7 +1262,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, tp->to_advertise = media2advert[tp->default_port - 9]; } else if (tp->flags & HAS_8023X) tp->to_advertise = 0x05e1; - else + else tp->to_advertise = 0x01e1; /* This is logically part of _init_one(), but too complex to write inline. */ @@ -1455,7 +1477,7 @@ static int __init tulip_init (void) /* copy module parms into globals */ tulip_rx_copybreak = rx_copybreak; tulip_max_interrupt_work = max_interrupt_work; - + /* probe for and init boards */ return pci_module_init (&tulip_driver); } diff --git a/drivers/net/wd.c b/drivers/net/wd.c index e4d53f88feb1..e46844b598da 100644 --- a/drivers/net/wd.c +++ b/drivers/net/wd.c @@ -34,6 +34,7 @@ static const char *version = #include #include #include +#include #include #include @@ -84,19 +85,33 @@ static int wd_close(struct net_device *dev); int __init wd_probe(struct net_device *dev) { int i; + struct resource *r; int base_addr = dev ? dev->base_addr : 0; - if (base_addr > 0x1ff) /* Check a single specified location. */ - return wd_probe1(dev, base_addr); + if (base_addr > 0x1ff) { /* Check a user specified location. */ + r = request_region(base_addr, WD_IO_EXTENT, "wd-probe"); + if ( r == NULL) + return -EBUSY; + i = wd_probe1(dev, base_addr); + if (i != 0) + release_resource(r); + else + r->name = ei_status.name; + return i; + } else if (base_addr != 0) /* Don't probe at all. */ return -ENXIO; for (i = 0; wd_portlist[i]; i++) { int ioaddr = wd_portlist[i]; - if (check_region(ioaddr, WD_IO_EXTENT)) + r = request_region(ioaddr, WD_IO_EXTENT, "wd-probe"); + if (r == NULL) continue; - if (wd_probe1(dev, ioaddr) == 0) + if (wd_probe1(dev, ioaddr) == 0) { + r->name = ei_status.name; return 0; + } + release_resource(r); } return -ENODEV; @@ -256,8 +271,6 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr) } /* OK, were are certain this is going to work. Setup the device. */ - request_region(ioaddr, WD_IO_EXTENT, model_name); - ei_status.name = model_name; ei_status.word16 = word16; ei_status.tx_start_page = WD_START_PG; @@ -444,9 +457,6 @@ init_module(void) { int this_dev, found = 0; - if (load_8390_module("wd.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) { struct net_device *dev = &dev_wd[this_dev]; dev->irq = irq[this_dev]; @@ -463,7 +473,6 @@ init_module(void) if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); return -ENXIO; } found++; @@ -487,7 +496,6 @@ cleanup_module(void) kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff --git a/drivers/pci/pci.ids b/drivers/pci/pci.ids index bfb9de0be552..df9937fd2123 100644 --- a/drivers/pci/pci.ids +++ b/drivers/pci/pci.ids @@ -1472,7 +1472,8 @@ 10b7 3590 TokenLink Velocity XL Adapter 4500 3c450 Cyclone/unknown 5055 3c555 Laptop Hurricane - 6055 3c556 Laptop Hurricane + 6055 3c556 Laptop Tornado + 6056 3c556B Laptop Hurricane 5057 3c575 [Megahertz] 10/100 LAN CardBus 10b7 5a57 3C575 Megahertz 10/100 LAN Cardbus PC Card 5157 3CCFE575BT Cyclone CardBus diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 21482915a401..b6e99d212948 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -319,6 +319,8 @@ socket_info_t *pcmcia_register_socket (int slot, DEBUG(0, "cs: pcmcia_register_socket(0x%p)\n", ss_entry); s = kmalloc(sizeof(struct socket_info_t), GFP_KERNEL); + if (!s) + return NULL; memset(s, 0, sizeof(socket_info_t)); s->ss_entry = ss_entry; diff --git a/drivers/pcmcia/yenta.c b/drivers/pcmcia/yenta.c index c9a3ddab3ea0..8cee76d3b0ab 100644 --- a/drivers/pcmcia/yenta.c +++ b/drivers/pcmcia/yenta.c @@ -559,7 +559,7 @@ static int yenta_socket_thread(void * data) daemonize(); strcpy(current->comm, "CardBus Watcher"); - if (request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->name, socket)) { + if (socket->cb_irq && request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->name, socket)) { printk ("Yenta: unable to register irq %d\n", socket->cb_irq); MOD_DEC_USE_COUNT; return (1); diff --git a/drivers/scsi/AM53C974.c b/drivers/scsi/AM53C974.c index 8d92082aaaa6..4edc3d0b9e29 100644 --- a/drivers/scsi/AM53C974.c +++ b/drivers/scsi/AM53C974.c @@ -381,11 +381,11 @@ static void AM53C974_dma_blast(struct Scsi_Host *instance, unsigned char dmastat unsigned char statreg); static void AM53C974_intr_bus_reset(struct Scsi_Host *instance); -static struct Scsi_Host *first_instance = NULL; -static Scsi_Host_Template *the_template = NULL; -static struct Scsi_Host *first_host = NULL; /* Head of list of AMD boards */ -static volatile int main_running = 0; -static int commandline_current = 0; +static struct Scsi_Host *first_instance; +static Scsi_Host_Template *the_template; +static struct Scsi_Host *first_host; /* Head of list of AMD boards */ +static volatile int main_running; +static int commandline_current; override_t overrides[7] = { {-1, 0, 0, 0},}; /* LILO overrides */ @@ -571,19 +571,25 @@ static void AM53C974_keywait(void) restore_flags(flags); } +#ifndef MODULE /************************************************************************** -* Function : AM53C974_setup(char *str, int *ints) +* Function : AM53C974_setup(char *str) * * Purpose : LILO command line initialization of the overrides array, * -* Inputs : str - unused, ints - array of integer parameters with ints[0] -* equal to the number of ints. +* Input : str - parameter string. +* +* Returns : 1. * * NOTE : this function needs to be declared as an external function * in init/main.c and included there in the bootsetups list ***************************************************************************/ -void AM53C974_setup(char *str, int *ints) +static int AM53C974_setup(char *str) { + int ints[5]; + + get_options(str, ARRAY_SIZE(ints), ints); + if (ints[0] < 4) printk("AM53C974_setup: wrong number of parameters;\n correct syntax is: AM53C974=host-scsi-id, target-scsi-id, max-rate, max-offset\n"); else { @@ -604,9 +610,13 @@ void AM53C974_setup(char *str, int *ints) } else printk("AM53C974_setup: too many overrides\n"); } + + return 1; } +__setup("AM53C974=", AM53C974_setup); + +#endif /* !MODULE */ -#if defined (CONFIG_PCI) /************************************************************************** * Function : int AM53C974_pci_detect(Scsi_Host_Template *tpnt) * @@ -616,7 +626,7 @@ void AM53C974_setup(char *str, int *ints) * * Returns : number of host adapters detected **************************************************************************/ -static inline int AM53C974_pci_detect(Scsi_Host_Template * tpnt) +static int __init AM53C974_pci_detect(Scsi_Host_Template * tpnt) { int count = 0; /* number of boards detected */ struct pci_dev *pdev = NULL; @@ -639,29 +649,6 @@ static inline int AM53C974_pci_detect(Scsi_Host_Template * tpnt) } return (count); } -#endif - -/************************************************************************** -* Function : int AM53C974_detect(Scsi_Host_Template *tpnt) -* -* Purpose : detects and initializes AM53C974 SCSI chips -* -* Inputs : tpnt - host template -* -* Returns : number of host adapters detected -**************************************************************************/ -int __init AM53C974_detect(Scsi_Host_Template * tpnt) -{ - int count = 0; /* number of boards detected */ - - tpnt->proc_name = "am53c974"; - -#if defined (CONFIG_PCI) - if (pci_present()) - count = AM53C974_pci_detect(tpnt); -#endif - return (count); -} /************************************************************************** * Function : int AM53C974_init(Scsi_Host_Template *tpnt, struct pci_dev *pdev) @@ -810,7 +797,7 @@ static void AM53C974_config_after_reset(struct Scsi_Host *instance) * * * Returns : info string * ************************************************************************/ -const char *AM53C974_info(struct Scsi_Host *instance) +static const char *AM53C974_info(struct Scsi_Host *instance) { static char info[100]; @@ -830,7 +817,7 @@ const char *AM53C974_info(struct Scsi_Host *instance) * * * Returns :status, see hosts.h for details * ***************************************************************************/ -int AM53C974_command(Scsi_Cmnd * SCpnt) +static int AM53C974_command(Scsi_Cmnd * SCpnt) { DEB(printk("AM53C974_command called\n")); return 0; @@ -903,7 +890,7 @@ static __inline__ void run_main(void) * twiddling done to the host specific fields of cmd. If the * main coroutine is not running, it is restarted. **************************************************************************/ -int AM53C974_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) +static int AM53C974_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) { unsigned long flags; struct Scsi_Host *instance = cmd->host; @@ -2283,7 +2270,7 @@ static void AM53C974_intr_bus_reset(struct Scsi_Host *instance) * * Returns : 0 - success, -1 on failure. **************************************************************************/ -int AM53C974_abort(Scsi_Cmnd * cmd) +static int AM53C974_abort(Scsi_Cmnd * cmd) { AM53C974_local_declare(); unsigned long flags; @@ -2391,7 +2378,7 @@ int AM53C974_abort(Scsi_Cmnd * cmd) * * FIXME(eric) the reset_flags are ignored. **************************************************************************/ -int AM53C974_reset(Scsi_Cmnd * cmd, unsigned int reset_flags) +static int AM53C974_reset(Scsi_Cmnd * cmd, unsigned int reset_flags) { AM53C974_local_declare(); unsigned long flags; @@ -2447,7 +2434,7 @@ int AM53C974_reset(Scsi_Cmnd * cmd, unsigned int reset_flags) * * Release resources allocated for a single AM53C974 adapter. */ -int AM53C974_release(struct Scsi_Host *shp) +static int AM53C974_release(struct Scsi_Host *shp) { free_irq(shp->irq, shp); scsi_unregister(shp); @@ -2455,11 +2442,9 @@ int AM53C974_release(struct Scsi_Host *shp) } -#ifdef MODULE /* You can specify overrides=a,b,c,d in the same format at AM53C974=a,b,c,d on boot up */ MODULE_PARM(overrides, "1-32i"); -#endif static Scsi_Host_Template driver_template = AM53C974; #include "scsi_module.c" diff --git a/drivers/scsi/AM53C974.h b/drivers/scsi/AM53C974.h index 78c6d21f8e10..e7a494b5c3a3 100644 --- a/drivers/scsi/AM53C974.h +++ b/drivers/scsi/AM53C974.h @@ -53,7 +53,7 @@ struct AM53C974_hostdata { #define AM53C974 { \ proc_name: "am53c974", \ name: "AM53C974", \ - detect: AM53C974_detect, \ + detect: AM53C974_pci_detect, \ release: AM53C974_release, \ info: AM53C974_info, \ command: AM53C974_command, \ @@ -68,14 +68,12 @@ struct AM53C974_hostdata { use_clustering: DISABLE_CLUSTERING \ } -void AM53C974_setup(char *str, int *ints); -int AM53C974_detect(Scsi_Host_Template * tpnt); -int AM53C974_release(struct Scsi_Host *shp); -int AM53C974_biosparm(Disk * disk, int dev, int *info_array); -const char *AM53C974_info(struct Scsi_Host *); -int AM53C974_command(Scsi_Cmnd * SCpnt); -int AM53C974_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)); -int AM53C974_abort(Scsi_Cmnd * cmd); -int AM53C974_reset(Scsi_Cmnd * cmd, unsigned int); +static int AM53C974_pci_detect(Scsi_Host_Template * tpnt); +static int AM53C974_release(struct Scsi_Host *shp); +static const char *AM53C974_info(struct Scsi_Host *); +static int AM53C974_command(Scsi_Cmnd * SCpnt); +static int AM53C974_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)); +static int AM53C974_abort(Scsi_Cmnd * cmd); +static int AM53C974_reset(Scsi_Cmnd * cmd, unsigned int); #endif /* AM53C974_H */ diff --git a/drivers/scsi/Config.in b/drivers/scsi/Config.in index e2a954f77c9c..4feaecacec29 100644 --- a/drivers/scsi/Config.in +++ b/drivers/scsi/Config.in @@ -57,7 +57,7 @@ if [ "$CONFIG_SCSI_AIC7XXX" != "n" ]; then fi dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI dep_tristate 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 $CONFIG_SCSI -dep_tristate 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974 $CONFIG_SCSI +dep_tristate 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974 $CONFIG_SCSI $CONFIG_PCI dep_tristate 'AMI MegaRAID support' CONFIG_SCSI_MEGARAID $CONFIG_SCSI dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC $CONFIG_SCSI diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index 667eedd3cd89..c22be78c0d71 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -13,9 +13,16 @@ * General Public License for more details. * * - * $Id: aha152x.c,v 2.1 2000/05/17 16:23:17 fischer Exp fischer $ + * $Id: aha152x.c,v 2.3 2000/11/04 16:40:26 fischer Exp $ * * $Log: aha152x.c,v $ + * Revision 2.3 2000/11/04 16:40:26 fischer + * - handle data overruns + * - extend timeout for data phases + * + * Revision 2.2 2000/08/08 19:54:53 fischer + * - minor changes + * * Revision 2.1 2000/05/17 16:23:17 fischer * - signature update * - fix for data out w/o scatter gather @@ -256,7 +263,7 @@ #define DO_LOCK(flags) \ do { \ - if(QLOCK.lock) { \ + if(spin_is_locked(&QLOCK)) { \ DPRINTK(debug_intr, DEBUG_LEAD "(%s:%d) already locked at %s:%d\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__, QLOCKER, QLOCKERL); \ } \ DPRINTK(debug_locks, DEBUG_LEAD "(%s:%d) locking\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__); \ @@ -293,7 +300,6 @@ (cmd) ? ((cmd)->lun & 0x07) : -1 #define DELAY_DEFAULT 100 -#define DEBUG_DEFAULT 0 /* possible irq range */ #if defined(PCMCIA) @@ -357,11 +363,11 @@ static int exttrans[] = {0, 0}; #if !defined(AHA152X_DEBUG) MODULE_PARM(aha152x, "1-8i"); MODULE_PARM_DESC(aha152x, "parameters for first controller"); -static int aha152x[] = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT}; +static int aha152x[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0}; MODULE_PARM(aha152x1, "1-8i"); MODULE_PARM_DESC(aha152x1, "parameters for second controller"); -static int aha152x1[] = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT}; +static int aha152x1[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0}; #else MODULE_PARM(debug, "1-2i"); MODULE_PARM_DESC(debug, "flags for driver debugging"); @@ -369,11 +375,11 @@ static int debug[] = {DEBUG_DEFAULT, DEBUG_DEFAULT}; MODULE_PARM(aha152x, "1-9i"); MODULE_PARM_DESC(aha152x, "parameters for first controller"); -static int aha152x[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0}; +static int aha152x[] = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT}; MODULE_PARM(aha152x1, "1-9i"); MODULE_PARM_DESC(aha152x1, "parameters for second controller"); -static int aha152x1[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0}; +static int aha152x1[] = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT}; #endif /* !defined(AHA152X_DEBUG) */ #endif /* MODULE */ @@ -954,7 +960,7 @@ int aha152x_detect(Scsi_Host_Template * tpnt) if (setup_count < 2) { struct aha152x_setup override = SETUP0; - if (setup_count == 0 || (override.io_port != setup[0].io_port)) + if (setup_count == 0 || (override.io_port != setup[0].io_port)) { if (!checksetup(&override)) { printk(KERN_ERR "\naha152x: invalid override SETUP0={0x%x,%d,%d,%d,%d,%d,%d,%d}\n", override.io_port, @@ -967,6 +973,7 @@ int aha152x_detect(Scsi_Host_Template * tpnt) override.ext_trans); } else setup[setup_count++] = override; + } } #endif @@ -974,7 +981,7 @@ int aha152x_detect(Scsi_Host_Template * tpnt) if (setup_count < 2) { struct aha152x_setup override = SETUP1; - if (setup_count == 0 || (override.io_port != setup[0].io_port)) + if (setup_count == 0 || (override.io_port != setup[0].io_port)) { if (!checksetup(&override)) { printk(KERN_ERR "\naha152x: invalid override SETUP1={0x%x,%d,%d,%d,%d,%d,%d,%d}\n", override.io_port, @@ -987,6 +994,7 @@ int aha152x_detect(Scsi_Host_Template * tpnt) override.ext_trans); } else setup[setup_count++] = override; + } } #endif @@ -2436,8 +2444,13 @@ static void msgo_run(struct Scsi_Host *shpnt) static void msgo_end(struct Scsi_Host *shpnt) { - if(MSGO_I0 && CURRENT_SC->SCp.this_residual>0) { - data_count = fifodata>CURRENT_SC->SCp.this_residual ? - CURRENT_SC->SCp.this_residual : - fifodata; - fifodata -= data_count; - - if(data_count & 1) { - DPRINTK(debug_datai, DEBUG_LEAD "8bit\n", CMDINFO(CURRENT_SC)); - SETPORT(DMACNTRL0, ENDMA|_8BIT); - *CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT); - CURRENT_SC->SCp.this_residual--; - DATA_LEN++; - SETPORT(DMACNTRL0, ENDMA); - } - - if(data_count > 1) { - DPRINTK(debug_datai, DEBUG_LEAD "16bit(%d)\n", CMDINFO(CURRENT_SC), data_count); - data_count >>= 1; - insw(DATAPORT, CURRENT_SC->SCp.ptr, data_count); - CURRENT_SC->SCp.ptr += 2 * data_count; - CURRENT_SC->SCp.this_residual -= 2 * data_count; - DATA_LEN += 2 * data_count; - } - - if(CURRENT_SC->SCp.this_residual==0 && CURRENT_SC->SCp.buffers_residual>0) { - /* advance to next buffer */ - CURRENT_SC->SCp.buffers_residual--; - CURRENT_SC->SCp.buffer++; - CURRENT_SC->SCp.ptr = CURRENT_SC->SCp.buffer->address; - CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length; - } - } - - if(fifodata>0 && CURRENT_SC->SCp.this_residual==0) { + if(CURRENT_SC->SCp.this_residual>0) { + while(fifodata>0 && CURRENT_SC->SCp.this_residual>0) { + data_count = fifodata>CURRENT_SC->SCp.this_residual ? + CURRENT_SC->SCp.this_residual : + fifodata; + fifodata -= data_count; + + if(data_count & 1) { + DPRINTK(debug_datai, DEBUG_LEAD "8bit\n", CMDINFO(CURRENT_SC)); + SETPORT(DMACNTRL0, ENDMA|_8BIT); + *CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT); + CURRENT_SC->SCp.this_residual--; + DATA_LEN++; + SETPORT(DMACNTRL0, ENDMA); + } + + if(data_count > 1) { + DPRINTK(debug_datai, DEBUG_LEAD "16bit(%d)\n", CMDINFO(CURRENT_SC), data_count); + data_count >>= 1; + insw(DATAPORT, CURRENT_SC->SCp.ptr, data_count); + CURRENT_SC->SCp.ptr += 2 * data_count; + CURRENT_SC->SCp.this_residual -= 2 * data_count; + DATA_LEN += 2 * data_count; + } + + if(CURRENT_SC->SCp.this_residual==0 && CURRENT_SC->SCp.buffers_residual>0) { + /* advance to next buffer */ + CURRENT_SC->SCp.buffers_residual--; + CURRENT_SC->SCp.buffer++; + CURRENT_SC->SCp.ptr = CURRENT_SC->SCp.buffer->address; + CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length; + } + } + } else if(fifodata>0) { printk(ERR_LEAD "no buffers left for %d(%d) bytes (data overrun!?)\n", CMDINFO(CURRENT_SC), fifodata, GETPORT(FIFOSTAT)); - break; + SETPORT(DMACNTRL0, ENDMA|_8BIT); + while(fifodata>0) { + int data; + data=GETPORT(DATAPORT); + DPRINTK(debug_datai, DEBUG_LEAD "data=%02x\n", CMDINFO(CURRENT_SC), data); + fifodata--; + DATA_LEN++; + } + SETPORT(DMACNTRL0, ENDMA|_8BIT); } } @@ -2714,7 +2735,7 @@ static void datao_run(struct Scsi_Host *shpnt) CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length; } - the_time=jiffies+100; + the_time=jiffies+1000; while(TESTLO(DMASTAT, DFIFOEMP|INTSTAT) && time_before(jiffies,the_time)) barrier(); diff --git a/drivers/scsi/aha152x.h b/drivers/scsi/aha152x.h index 910f1668bf63..86f84cbe2aa0 100644 --- a/drivers/scsi/aha152x.h +++ b/drivers/scsi/aha152x.h @@ -2,7 +2,7 @@ #define _AHA152X_H /* - * $Id: aha152x.h,v 2.0 1999/12/25 15:08:35 fischer Exp fischer $ + * $Id: aha152x.h,v 2.3 2000/11/04 16:41:37 fischer Exp $ */ #if defined(__KERNEL__) @@ -27,7 +27,7 @@ int aha152x_proc_info(char *buffer, char **start, off_t offset, int length, int (unless we support more than 1 cmd_per_lun this should do) */ #define AHA152X_MAXQUEUE 7 -#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 2.0 $" +#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 2.3 $" /* Initial value of Scsi_Host entry */ #define AHA152X { proc_name: "aha152x", \ diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index 3e425043ab1e..46591840e9da 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c @@ -1796,8 +1796,6 @@ static int device_exists (int host_index, int ldn, int *block_length, /*--------------------------------------------------------------------*/ -#ifdef CONFIG_SCSI_IBMMCA - void internal_ibmmca_scsi_setup (char *str, int *ints) { int i, j, io_base, id_base; @@ -1852,8 +1850,6 @@ void internal_ibmmca_scsi_setup (char *str, int *ints) return; } -#endif - /*--------------------------------------------------------------------*/ static int ibmmca_getinfo (char *buf, int slot, void *dev) diff --git a/drivers/sound/cs4281.c b/drivers/sound/cs4281.c index 913cf55c12a0..5d2810129f19 100644 --- a/drivers/sound/cs4281.c +++ b/drivers/sound/cs4281.c @@ -30,11 +30,21 @@ // /dev/mixer standard /dev/mixer device, (mostly) OSS compatible // /dev/midi simple MIDI UART interface, no ioctl // +// Modification History +// 08/20/00 trw - silence and no stopping DAC until release +// 08/23/00 trw - added CS_DBG statements, fix interrupt hang issue on DAC stop. +// 09/18/00 trw - added 16bit only record with conversion +// 09/24/00 trw - added Enhanced Full duplex (separate simultaneous +// capture/playback rates) +// 10/03/00 trw - fixed mmap (fixed GRECORD and the XMMS mmap test plugin +// libOSSm.so) +// 10/11/00 trw - modified for 2.4.0-test9 kernel enhancements (NR_MAP removal) +// 11/03/00 trw - fixed interrupt loss/stutter, added debug. // -// - // ***************************************************************************** +#include +#include #include #include #include @@ -50,9 +60,11 @@ #include #include #include +#include +#include #include #include -#include +//#include #include "dm.h" #include "cs4281_hwdefs.h" @@ -71,10 +83,12 @@ EXPORT_NO_SYMBOLS; #define CS4281_MAGIC ((PCI_DEVICE_ID_CRYSTAL_CS4281<<16) | PCI_VENDOR_ID_CIRRUS) -#define CSDEBUG 1 -// +#include + // Turn on/off debugging compilation by using 1/0 respectively for CSDEBUG // +#define CSDEBUG_INTERFACE 1 +#define CSDEBUG 1 // // CSDEBUG is usual mode is set to 1, then use the // cs_debuglevel and cs_debugmask to turn on or off debugging. @@ -82,36 +96,39 @@ EXPORT_NO_SYMBOLS; // that should be printed on any released driver. // #if CSDEBUG -extern unsigned cs_debugmask; -extern unsigned cs_debuglevel; -#define CS_DBGOUT(mask,level,x) if((cs_debuglevel >= (level)) && ((mask) & cs_debugmask)) {x;} +extern unsigned long cs_debugmask; +extern unsigned long cs_debuglevel; +#define CS_DBGOUT(mask,level,x) if((cs_debuglevel >= (level)) && ((mask) & cs_debugmask) ) {x;} #else -#define CS_DBGOUT(mask,level,x) +#define CS_DBGOUT(mask,level,x) #endif // // cs_debugmask areas // -#define CS_INIT 0x00000001 // initialization and probe functions -#define CS_ERROR 0x00000002 // tmp debugging bit placeholder -#define CS_INTERRUPT 0x00000004 // interrupt handler (separate from all other) -#define CS_FUNCTION 0x00000008 // enter/leave functions -#define CS_WAVE_WRITE 0x00000010 // write information for wave -#define CS_WAVE_READ 0x00000020 // read information for wave -#define CS_MIDI_WRITE 0x00000040 // write information for midi -#define CS_MIDI_READ 0x00000080 // read information for midi -#define CS_MPU401_WRITE 0x00000100 // write information for mpu401 -#define CS_MPU401_READ 0x00000200 // read information for mpu401 -#define CS_OPEN 0x00000400 // all open functions in the driver -#define CS_RELEASE 0x00000800 // all release functions in the driver -#define CS_PARMS 0x00001000 // functional and operational parameters -#define CS_TMP 0x10000000 // tmp debug mask bit - -unsigned cs_debuglevel=1; // levels range from 1-9 -unsigned cs_debugmask=CS_INIT | CS_ERROR; // use CS_DBGOUT with various mask values +#define CS_INIT 0x00000001 // initialization and probe functions +#define CS_ERROR 0x00000002 // tmp debugging bit placeholder +#define CS_INTERRUPT 0x00000004 // interrupt handler (separate from all other) +#define CS_FUNCTION 0x00000008 // enter/leave functions +#define CS_WAVE_WRITE 0x00000010 // write information for wave +#define CS_WAVE_READ 0x00000020 // read information for wave +#define CS_MIDI_WRITE 0x00000040 // write information for midi +#define CS_MIDI_READ 0x00000080 // read information for midi +#define CS_MPU401_WRITE 0x00000100 // write information for mpu401 +#define CS_MPU401_READ 0x00000200 // read information for mpu401 +#define CS_OPEN 0x00000400 // all open functions in the driver +#define CS_RELEASE 0x00000800 // all release functions in the driver +#define CS_PARMS 0x00001000 // functional and operational parameters +#define CS_IOCTL 0x00002000 // ioctl (non-mixer) +#define CS_TMP 0x10000000 // tmp debug mask bit + +#if CSDEBUG +static unsigned long cs_debuglevel = 1; // levels range from 1-9 +static unsigned long cs_debugmask = CS_INIT | CS_ERROR; // use CS_DBGOUT with various mask values #if MODULE MODULE_PARM(cs_debuglevel, "i"); MODULE_PARM(cs_debugmask, "i"); #endif +#endif // MIDI buffer sizes #define MIDIINBUF 500 @@ -127,14 +144,17 @@ MODULE_PARM(cs_debugmask, "i"); ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) #define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start) -#define CS4281_MAJOR_VERSION 0 -#define CS4281_MINOR_VERSION 4 +#define CS4281_MAJOR_VERSION 1 +#define CS4281_MINOR_VERSION 1 #ifdef __ia64__ -#define CS4281_ARCH 64 //architecture key +#define CS4281_ARCH 64 //architecture key #else -#define CS4281_ARCH 32 //architecture key +#define CS4281_ARCH 32 //architecture key #endif +#define CS_TYPE_ADC 0 +#define CS_TYPE_DAC 1 + struct cs4281_state { // magic unsigned int magic; @@ -152,9 +172,8 @@ struct cs4281_state { // hardware resources unsigned int pBA0phys, pBA1phys; - char *pBA0, *pBA1; + char *pBA0, *pBA1; unsigned int irq; - int endofbuffer; // mixer registers struct { @@ -164,38 +183,50 @@ struct cs4281_state { unsigned short micpreamp; } mix; - // wave stuff // Note that play & record formats must be the same *wb. - unsigned fmt; - unsigned channels; - unsigned rate; - unsigned char clkdiv; + // wave stuff + struct properties { + unsigned fmt; + unsigned fmt_original; // original requested format + unsigned channels; + unsigned rate; + unsigned char clkdiv; + } prop_dac, prop_adc; + unsigned conversion:1; // conversion from 16 to 8 bit in progress + void *tmpbuff; // tmp buffer for sample conversions unsigned ena; - spinlock_t lock; struct semaphore open_sem; + struct semaphore open_sem_adc; + struct semaphore open_sem_dac; mode_t open_mode; wait_queue_head_t open_wait; + wait_queue_head_t open_wait_adc; + wait_queue_head_t open_wait_dac; + dma_addr_t dmaaddr_tmpbuff; + unsigned buforder_tmpbuff; // Log base 2 of 'rawbuf' size in bytes.. struct dmabuf { - void *rawbuf; // Physical address of - dma_addr_t dmaaddr; - unsigned buforder; // Log base 2 of 'rawbuf' size in bytes.. - unsigned numfrag; // # of 'fragments' in the buffer. - unsigned fragshift; // Log base 2 of fragment size. + void *rawbuf; // Physical address of + dma_addr_t dmaaddr; + unsigned buforder; // Log base 2 of 'rawbuf' size in bytes.. + unsigned numfrag; // # of 'fragments' in the buffer. + unsigned fragshift; // Log base 2 of fragment size. unsigned hwptr, swptr; - unsigned total_bytes; // # bytes process since open. - unsigned blocks; // last returned blocks value GETOPTR + unsigned total_bytes; // # bytes process since open. + unsigned blocks; // last returned blocks value GETOPTR + unsigned wakeup; // interrupt occurred on block int count; - unsigned error; // over/underrun + unsigned error; // over/underrun wait_queue_head_t wait; // redundant, but makes calculations easier - unsigned fragsize; // 2**fragshift.. - unsigned dmasize; // 2**buforder. + unsigned fragsize; // 2**fragshift.. + unsigned dmasize; // 2**buforder. unsigned fragsamples; // OSS stuff - unsigned mapped:1; // Buffer mapped in cs4281_mmap()? - unsigned ready:1; // prog_dmabuf_dac()/adc() successful? + unsigned mapped:1; // Buffer mapped in cs4281_mmap()? + unsigned ready:1; // prog_dmabuf_dac()/adc() successful? unsigned endcleared:1; + unsigned type:1; // adc or dac buffer (CS_TYPE_XXX) unsigned ossfragshift; int ossmaxfrags; unsigned subdivision; @@ -214,11 +245,250 @@ struct cs4281_state { }; +#if CSDEBUG + +// DEBUG ROUTINES + +#define SOUND_MIXER_CS_GETDBGLEVEL _SIOWR('M',120, int) +#define SOUND_MIXER_CS_SETDBGLEVEL _SIOWR('M',121, int) +#define SOUND_MIXER_CS_GETDBGMASK _SIOWR('M',122, int) +#define SOUND_MIXER_CS_SETDBGMASK _SIOWR('M',123, int) + +#define SNDCTL_DSP_CS_GETDBGLEVEL _SIOWR('P', 50, int) +#define SNDCTL_DSP_CS_SETDBGLEVEL _SIOWR('P', 51, int) +#define SNDCTL_DSP_CS_GETDBGMASK _SIOWR('P', 52, int) +#define SNDCTL_DSP_CS_SETDBGMASK _SIOWR('P', 53, int) + +void printioctl(unsigned int x) +{ + unsigned int i; + unsigned char vidx; + // Index of mixtable1[] member is Device ID + // and must be <= SOUND_MIXER_NRDEVICES. + // Value of array member is index into s->mix.vol[] + static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = { + [SOUND_MIXER_PCM] = 1, // voice + [SOUND_MIXER_LINE1] = 2, // AUX + [SOUND_MIXER_CD] = 3, // CD + [SOUND_MIXER_LINE] = 4, // Line + [SOUND_MIXER_SYNTH] = 5, // FM + [SOUND_MIXER_MIC] = 6, // Mic + [SOUND_MIXER_SPEAKER] = 7, // Speaker + [SOUND_MIXER_RECLEV] = 8, // Recording level + [SOUND_MIXER_VOLUME] = 9 // Master Volume + }; -struct cs4281_state *devs = NULL; + switch (x) { + case SOUND_MIXER_CS_GETDBGMASK: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_CS_GETDBGMASK:\n")); + break; + case SOUND_MIXER_CS_GETDBGLEVEL: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_CS_GETDBGLEVEL:\n")); + break; + case SOUND_MIXER_CS_SETDBGMASK: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_CS_SETDBGMASK:\n")); + break; + case SOUND_MIXER_CS_SETDBGLEVEL: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_CS_SETDBGLEVEL:\n")); + break; + case OSS_GETVERSION: + CS_DBGOUT(CS_IOCTL, 4, printk("OSS_GETVERSION:\n")); + break; + case SNDCTL_DSP_SYNC: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SYNC:\n")); + break; + case SNDCTL_DSP_SETDUPLEX: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETDUPLEX:\n")); + break; + case SNDCTL_DSP_GETCAPS: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETCAPS:\n")); + break; + case SNDCTL_DSP_RESET: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_RESET:\n")); + break; + case SNDCTL_DSP_SPEED: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SPEED:\n")); + break; + case SNDCTL_DSP_STEREO: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_STEREO:\n")); + break; + case SNDCTL_DSP_CHANNELS: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CHANNELS:\n")); + break; + case SNDCTL_DSP_GETFMTS: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETFMTS:\n")); + break; + case SNDCTL_DSP_SETFMT: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFMT:\n")); + break; + case SNDCTL_DSP_POST: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_POST:\n")); + break; + case SNDCTL_DSP_GETTRIGGER: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETTRIGGER:\n")); + break; + case SNDCTL_DSP_SETTRIGGER: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETTRIGGER:\n")); + break; + case SNDCTL_DSP_GETOSPACE: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOSPACE:\n")); + break; + case SNDCTL_DSP_GETISPACE: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETISPACE:\n")); + break; + case SNDCTL_DSP_NONBLOCK: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_NONBLOCK:\n")); + break; + case SNDCTL_DSP_GETODELAY: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETODELAY:\n")); + break; + case SNDCTL_DSP_GETIPTR: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETIPTR:\n")); + break; + case SNDCTL_DSP_GETOPTR: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOPTR:\n")); + break; + case SNDCTL_DSP_GETBLKSIZE: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETBLKSIZE:\n")); + break; + case SNDCTL_DSP_SETFRAGMENT: + CS_DBGOUT(CS_IOCTL, 4, + printk("SNDCTL_DSP_SETFRAGMENT:\n")); + break; + case SNDCTL_DSP_SUBDIVIDE: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SUBDIVIDE:\n")); + break; + case SOUND_PCM_READ_RATE: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_RATE:\n")); + break; + case SOUND_PCM_READ_CHANNELS: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_PCM_READ_CHANNELS:\n")); + break; + case SOUND_PCM_READ_BITS: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_BITS:\n")); + break; + case SOUND_PCM_WRITE_FILTER: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_PCM_WRITE_FILTER:\n")); + break; + case SNDCTL_DSP_SETSYNCRO: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETSYNCRO:\n")); + break; + case SOUND_PCM_READ_FILTER: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_FILTER:\n")); + break; + case SNDCTL_DSP_CS_GETDBGMASK: + CS_DBGOUT(CS_IOCTL, 4, + printk("SNDCTL_DSP_CS_GETDBGMASK:\n")); + break; + case SNDCTL_DSP_CS_GETDBGLEVEL: + CS_DBGOUT(CS_IOCTL, 4, + printk("SNDCTL_DSP_CS_GETDBGLEVEL:\n")); + break; + case SNDCTL_DSP_CS_SETDBGMASK: + CS_DBGOUT(CS_IOCTL, 4, + printk("SNDCTL_DSP_CS_SETDBGMASK:\n")); + break; + case SNDCTL_DSP_CS_SETDBGLEVEL: + CS_DBGOUT(CS_IOCTL, 4, + printk("SNDCTL_DSP_CS_SETDBGLEVEL:\n")); + break; + + case SOUND_MIXER_PRIVATE1: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE1:\n")); + break; + case SOUND_MIXER_PRIVATE2: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE2:\n")); + break; + case SOUND_MIXER_PRIVATE3: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE3:\n")); + break; + case SOUND_MIXER_PRIVATE4: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE4:\n")); + break; + case SOUND_MIXER_PRIVATE5: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE5:\n")); + break; + case SOUND_MIXER_INFO: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_INFO:\n")); + break; + case SOUND_OLD_MIXER_INFO: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_OLD_MIXER_INFO:\n")); + break; + + default: + switch (_IOC_NR(x)) { + case SOUND_MIXER_VOLUME: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_VOLUME:\n")); + break; + case SOUND_MIXER_SPEAKER: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_SPEAKER:\n")); + break; + case SOUND_MIXER_RECLEV: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_RECLEV:\n")); + break; + case SOUND_MIXER_MIC: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_MIC:\n")); + break; + case SOUND_MIXER_SYNTH: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_SYNTH:\n")); + break; + case SOUND_MIXER_RECSRC: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_RECSRC:\n")); + break; + case SOUND_MIXER_DEVMASK: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_DEVMASK:\n")); + break; + case SOUND_MIXER_RECMASK: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_RECMASK:\n")); + break; + case SOUND_MIXER_STEREODEVS: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_STEREODEVS:\n")); + break; + case SOUND_MIXER_CAPS: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_CAPS:\n")); + break; + default: + i = _IOC_NR(x); + if (i >= SOUND_MIXER_NRDEVICES + || !(vidx = mixtable1[i])) { + CS_DBGOUT(CS_IOCTL, 4, + printk + ("UNKNOWN IOCTL: 0x%.8x NR=%d\n", + x, i)); + } else { + CS_DBGOUT(CS_IOCTL, 4, + printk + ("SOUND_MIXER_IOCTL AC9x: 0x%.8x NR=%d\n", + x, i)); + } + break; + } + } +} +#endif +static int prog_dmabuf_adc(struct cs4281_state *s); +static void prog_codec(struct cs4281_state *s, unsigned type); + +static struct cs4281_state *devs = NULL; // --------------------------------------------------------------------- // -// Hardware Interfaces For the CS4281 +// Hardware Interfaces For the CS4281 // @@ -227,18 +497,16 @@ struct cs4281_state *devs = NULL; //****************************************************************************** static void delayus(u32 delay) { - u32 j; - if(delay > 9999) - { - j = (delay * HZ)/1000000; /* calculate delay in jiffies */ - if(j<1) - j=1; /* minimum one jiffy. */ - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(j); - } - else + u32 j; + if (delay > 9999) { + j = (delay * HZ) / 1000000; /* calculate delay in jiffies */ + if (j < 1) + j = 1; /* minimum one jiffy. */ + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(j); + } else udelay(delay); - return; + return; } @@ -254,14 +522,15 @@ static void delayus(u32 delay) // 5. if DCV not cleared, break and return error // 6. Read ACSTS = Status Register = 464h, check VSTS bit //**************************************************************************** -static int cs4281_read_ac97(struct cs4281_state *card, u32 offset, u32 *value) +static int cs4281_read_ac97(struct cs4281_state *card, u32 offset, + u32 * value) { u32 count, status; // Make sure that there is not data sitting // around from a previous uncompleted access. // ACSDA = Status Data Register = 47Ch - status = readl(card->pBA0+BA0_ACSDA); + status = readl(card->pBA0 + BA0_ACSDA); // Setup the AC97 control registers on the CS4281 to send the // appropriate command to the AC97 to perform the read. @@ -274,51 +543,50 @@ static int cs4281_read_ac97(struct cs4281_state *card, u32 offset, u32 *value) // bit ESYN - ASYNC generation enabled // Get the actual AC97 register from the offset - writel(offset - BA0_AC97_RESET, card->pBA0+BA0_ACCAD); - writel(0, card->pBA0+BA0_ACCDA); - writel(ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN, card->pBA0+BA0_ACCTL); + writel(offset - BA0_AC97_RESET, card->pBA0 + BA0_ACCAD); + writel(0, card->pBA0 + BA0_ACCDA); + writel(ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN, + card->pBA0 + BA0_ACCTL); - // Wait for the read to occur. - for(count = 0; count < 10; count++) - { + // Wait for the read to occur. + for (count = 0; count < 10; count++) { // First, we want to wait for a short time. udelay(25); // Now, check to see if the read has completed. // ACCTL = 460h, DCV should be reset by now and 460h = 17h - if( !(readl(card->pBA0+BA0_ACCTL) & ACCTL_DCV)) + if (!(readl(card->pBA0 + BA0_ACCTL) & ACCTL_DCV)) break; } - // Make sure the read completed. - if(readl(card->pBA0+BA0_ACCTL) & ACCTL_DCV) - return 1; + // Make sure the read completed. + if (readl(card->pBA0 + BA0_ACCTL) & ACCTL_DCV) + return 1; - // Wait for the valid status bit to go active. - for(count = 0; count < 10; count++) - { + // Wait for the valid status bit to go active. + for (count = 0; count < 10; count++) { // Read the AC97 status register. // ACSTS = Status Register = 464h - status = readl(card->pBA0+BA0_ACSTS); + status = readl(card->pBA0 + BA0_ACSTS); // See if we have valid status. // VSTS - Valid Status - if(status & ACSTS_VSTS) + if (status & ACSTS_VSTS) break; // Wait for a short while. udelay(25); } - // Make sure we got valid status. - if(!(status & ACSTS_VSTS)) + // Make sure we got valid status. + if (!(status & ACSTS_VSTS)) return 1; // Read the data returned from the AC97 register. // ACSDA = Status Data Register = 474h - *value = readl(card->pBA0+BA0_ACSDA); + *value = readl(card->pBA0 + BA0_ACSDA); // Success. - return(0); + return (0); } @@ -334,49 +602,51 @@ static int cs4281_read_ac97(struct cs4281_state *card, u32 offset, u32 *value) // 5. if DCV not cleared, break and return error // //**************************************************************************** -static int cs4281_write_ac97(struct cs4281_state *card, u32 offset, u32 value) +static int cs4281_write_ac97(struct cs4281_state *card, u32 offset, + u32 value) { u32 count, status; - CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs4281: cs_4281_write_ac97()+ \n") ); + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: cs_4281_write_ac97()+ \n")); - // Setup the AC97 control registers on the CS4281 to send the - // appropriate command to the AC97 to perform the read. - // ACCAD = Command Address Register = 46Ch - // ACCDA = Command Data Register = 470h - // ACCTL = Control Register = 460h - // set DCV - will clear when process completed - // reset CRW - Write command - // set VFRM - valid frame enabled - // set ESYN - ASYNC generation enabled - // set RSTN - ARST# inactive, AC97 codec not reset + // Setup the AC97 control registers on the CS4281 to send the + // appropriate command to the AC97 to perform the read. + // ACCAD = Command Address Register = 46Ch + // ACCDA = Command Data Register = 470h + // ACCTL = Control Register = 460h + // set DCV - will clear when process completed + // reset CRW - Write command + // set VFRM - valid frame enabled + // set ESYN - ASYNC generation enabled + // set RSTN - ARST# inactive, AC97 codec not reset - // Get the actual AC97 register from the offset + // Get the actual AC97 register from the offset - writel(offset - BA0_AC97_RESET, card->pBA0+BA0_ACCAD); - writel(value, card->pBA0+BA0_ACCDA); - writel(ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN, card->pBA0+BA0_ACCTL); + writel(offset - BA0_AC97_RESET, card->pBA0 + BA0_ACCAD); + writel(value, card->pBA0 + BA0_ACCDA); + writel(ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN, + card->pBA0 + BA0_ACCTL); - // Wait for the write to occur. - for(count = 0; count < 10; count++) - { + // Wait for the write to occur. + for (count = 0; count < 10; count++) { // First, we want to wait for a short time. udelay(25); // Now, check to see if the write has completed. // ACCTL = 460h, DCV should be reset by now and 460h = 07h - status = readl(card->pBA0+BA0_ACCTL); - if(!(status & ACCTL_DCV)) + status = readl(card->pBA0 + BA0_ACCTL); + if (!(status & ACCTL_DCV)) break; } // Make sure the write completed. - if(status & ACCTL_DCV) - { - CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO - "cs4281: cs_4281_write_ac97()- unable to write. ACCTL_DCV active\n") ); + if (status & ACCTL_DCV) { + CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO + "cs4281: cs_4281_write_ac97()- unable to write. ACCTL_DCV active\n")); return 1; } - CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs4281: cs_4281_write_ac97()- 0\n") ); + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: cs_4281_write_ac97()- 0\n")); // Success. return 0; } @@ -390,67 +660,66 @@ static int cs4281_hw_init(struct cs4281_state *card) u32 ac97_slotid; u32 temp1, temp2; - CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs4281: cs4281_hw_init()+ \n") ); + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: cs4281_hw_init()+ \n")); //***************************************7 // Set up the Sound System Configuration //*************************************** - // Set the 'Configuration Write Protect' register - // to 4281h. Allows vendor-defined configuration - // space between 0e4h and 0ffh to be written. + // Set the 'Configuration Write Protect' register + // to 4281h. Allows vendor-defined configuration + // space between 0e4h and 0ffh to be written. - writel(0x4281, card->pBA0+BA0_CWPR); // (3e0h) + writel(0x4281, card->pBA0 + BA0_CWPR); // (3e0h) - // (0), Blast the clock control register to zero so that the - // PLL starts out in a known state, and blast the master serial - // port control register to zero so that the serial ports also - // start out in a known state. + // (0), Blast the clock control register to zero so that the + // PLL starts out in a known state, and blast the master serial + // port control register to zero so that the serial ports also + // start out in a known state. - writel(0, card->pBA0+BA0_CLKCR1); // (400h) - writel(0, card->pBA0+BA0_SERMC); // (420h) + writel(0, card->pBA0 + BA0_CLKCR1); // (400h) + writel(0, card->pBA0 + BA0_SERMC); // (420h) - // (1), Make ESYN go to zero to turn off - // the Sync pulse on the AC97 link. + // (1), Make ESYN go to zero to turn off + // the Sync pulse on the AC97 link. - writel(0, card->pBA0+BA0_ACCTL); + writel(0, card->pBA0 + BA0_ACCTL); udelay(50); - // (2) Drive the ARST# pin low for a minimum of 1uS (as defined in - // the AC97 spec) and then drive it high. This is done for non - // AC97 modes since there might be logic external to the CS461x - // that uses the ARST# line for a reset. + // (2) Drive the ARST# pin low for a minimum of 1uS (as defined in + // the AC97 spec) and then drive it high. This is done for non + // AC97 modes since there might be logic external to the CS461x + // that uses the ARST# line for a reset. - writel(0, card->pBA0+BA0_SPMC); // (3ech) + writel(0, card->pBA0 + BA0_SPMC); // (3ech) udelay(100); - writel(SPMC_RSTN, card->pBA0+BA0_SPMC); - delayus(50000); // Wait 50 ms for ABITCLK to become stable. + writel(SPMC_RSTN, card->pBA0 + BA0_SPMC); + delayus(50000); // Wait 50 ms for ABITCLK to become stable. // (3) Turn on the Sound System Clocks. - writel(CLKCR1_PLLP, card->pBA0+BA0_CLKCR1); // (400h) - delayus(50000); // Wait for the PLL to stabilize. + writel(CLKCR1_PLLP, card->pBA0 + BA0_CLKCR1); // (400h) + delayus(50000); // Wait for the PLL to stabilize. // Turn on clocking of the core (CLKCR1(400h) = 0x00000030) - writel(CLKCR1_PLLP | CLKCR1_SWCE, card->pBA0+BA0_CLKCR1); + writel(CLKCR1_PLLP | CLKCR1_SWCE, card->pBA0 + BA0_CLKCR1); // (4) Power on everything for now.. - writel(0x7E, card->pBA0 + BA0_SSPM); // (740h) + writel(0x7E, card->pBA0 + BA0_SSPM); // (740h) // (5) Wait for clock stabilization. - for(temp1=0; temp1<1000; temp1++) - { + for (temp1 = 0; temp1 < 1000; temp1++) { udelay(1000); - if(readl(card->pBA0+BA0_CLKCR1) & CLKCR1_DLLRDY) + if (readl(card->pBA0 + BA0_CLKCR1) & CLKCR1_DLLRDY) break; } - if(!(readl(card->pBA0+BA0_CLKCR1) & CLKCR1_DLLRDY)) - { - CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR "cs4281: DLLRDY failed!\n") ); + if (!(readl(card->pBA0 + BA0_CLKCR1) & CLKCR1_DLLRDY)) { + CS_DBGOUT(CS_ERROR, 1, + printk(KERN_ERR "cs4281: DLLRDY failed!\n")); return -EIO; } - // (6) Enable ASYNC generation. - writel(ACCTL_ESYN, card->pBA0+BA0_ACCTL); // (460h) + writel(ACCTL_ESYN, card->pBA0 + BA0_ACCTL); // (460h) // Now wait 'for a short while' to allow the AC97 // part to start generating bit clock. (so we don't @@ -459,99 +728,95 @@ static int cs4281_hw_init(struct cs4281_state *card) // Set the serial port timing configuration, so that the // clock control circuit gets its clock from the right place. - writel(SERMC_PTC_AC97, card->pBA0+BA0_SERMC); // (420h)=2. + writel(SERMC_PTC_AC97, card->pBA0 + BA0_SERMC); // (420h)=2. // (7) Wait for the codec ready signal from the AC97 codec. - for(temp1=0; temp1<1000; temp1++) - { + for (temp1 = 0; temp1 < 1000; temp1++) { // Delay a mil to let things settle out and // to prevent retrying the read too quickly. udelay(1000); - if( readl(card->pBA0+BA0_ACSTS) & ACSTS_CRDY ) // If ready, (464h) - break; // exit the 'for' loop. + if (readl(card->pBA0 + BA0_ACSTS) & ACSTS_CRDY) // If ready, (464h) + break; // exit the 'for' loop. } - if( !(readl(card->pBA0+BA0_ACSTS) & ACSTS_CRDY) ) // If never came ready, - { - CS_DBGOUT(CS_FUNCTION, 2, - printk(KERN_ERR "cs4281: ACSTS never came ready!\n") ); - return -EIO; // exit initialization. - } - - // (8) Assert the 'valid frame' signal so we can - // begin sending commands to the AC97 codec. - writel(ACCTL_VFRM | ACCTL_ESYN, card->pBA0+BA0_ACCTL); // (460h) - - // (9), Wait until CODEC calibration is finished. - // Print an error message if it doesn't. - for(temp1 = 0; temp1 < 1000; temp1++) + if (!(readl(card->pBA0 + BA0_ACSTS) & ACSTS_CRDY)) // If never came ready, { + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_ERR + "cs4281: ACSTS never came ready!\n")); + return -EIO; // exit initialization. + } + // (8) Assert the 'valid frame' signal so we can + // begin sending commands to the AC97 codec. + writel(ACCTL_VFRM | ACCTL_ESYN, card->pBA0 + BA0_ACCTL); // (460h) + + // (9), Wait until CODEC calibration is finished. + // Print an error message if it doesn't. + for (temp1 = 0; temp1 < 1000; temp1++) { delayus(10000); // Read the AC97 Powerdown Control/Status Register. cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp2); - if( (temp2 & 0x0000000F) == 0x0000000F ) + if ((temp2 & 0x0000000F) == 0x0000000F) break; } - if ( (temp2 & 0x0000000F) != 0x0000000F ) - { - CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR - "cs4281: Codec failed to calibrate. Status = %.8x.\n", temp2) ); + if ((temp2 & 0x0000000F) != 0x0000000F) { + CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR + "cs4281: Codec failed to calibrate. Status = %.8x.\n", + temp2)); return -EIO; } - - // (10), Set the serial port timing configuration, so that the - // clock control circuit gets its clock from the right place. - writel(SERMC_PTC_AC97, card->pBA0+BA0_SERMC); // (420h)=2. + // (10), Set the serial port timing configuration, so that the + // clock control circuit gets its clock from the right place. + writel(SERMC_PTC_AC97, card->pBA0 + BA0_SERMC); // (420h)=2. - // (11) Wait until we've sampled input slots 3 & 4 as valid, meaning - // that the codec is pumping ADC data across the AC link. - for(temp1=0; temp1<1000; temp1++) - { + // (11) Wait until we've sampled input slots 3 & 4 as valid, meaning + // that the codec is pumping ADC data across the AC link. + for (temp1 = 0; temp1 < 1000; temp1++) { // Delay a mil to let things settle out and // to prevent retrying the read too quickly. - delayus(1000); //(test) + delayus(1000); //(test) // Read the input slot valid register; See // if input slots 3 and 4 are valid yet. - if( (readl(card->pBA0+BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4) ) - == (ACISV_ISV3 | ACISV_ISV4)) - break; // Exit the 'for' if slots are valid. - } - // If we never got valid data, exit initialization. - if( (readl(card->pBA0+BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4) ) - != (ACISV_ISV3 | ACISV_ISV4)) - { - CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR "cs4281: Never got valid data!\n")); - return -EIO; // If no valid data, exit initialization. + if ( + (readl(card->pBA0 + BA0_ACISV) & + (ACISV_ISV3 | ACISV_ISV4)) == + (ACISV_ISV3 | ACISV_ISV4)) break; // Exit the 'for' if slots are valid. + } + // If we never got valid data, exit initialization. + if ((readl(card->pBA0 + BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) + != (ACISV_ISV3 | ACISV_ISV4)) { + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_ERR + "cs4281: Never got valid data!\n")); + return -EIO; // If no valid data, exit initialization. } - // (12), Start digital data transfer of audio data to the codec. - writel(ACOSV_SLV3 | ACOSV_SLV4, card->pBA0+BA0_ACOSV); // (468h) + writel(ACOSV_SLV3 | ACOSV_SLV4, card->pBA0 + BA0_ACOSV); // (468h) //************************************** // Unmute the Master and Alternate // (headphone) volumes. Set to max. //************************************** - cs4281_write_ac97(card,BA0_AC97_HEADPHONE_VOLUME, 0); - cs4281_write_ac97(card,BA0_AC97_MASTER_VOLUME, 0); + cs4281_write_ac97(card, BA0_AC97_HEADPHONE_VOLUME, 0); + cs4281_write_ac97(card, BA0_AC97_MASTER_VOLUME, 0); //****************************************** // Power on the DAC(AddDACUser()from main()) //****************************************** - cs4281_read_ac97(card,BA0_AC97_POWERDOWN, &temp1); - cs4281_write_ac97(card,BA0_AC97_POWERDOWN, temp1 &= 0xfdff); + cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1); + cs4281_write_ac97(card, BA0_AC97_POWERDOWN, temp1 &= 0xfdff); // Wait until we sample a DAC ready state. - for(temp2=0; temp2<32; temp2++) - { + for (temp2 = 0; temp2 < 32; temp2++) { // Let's wait a mil to let things settle. delayus(1000); // Read the current state of the power control reg. cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1); // If the DAC ready state bit is set, stop waiting. - if(temp1 & 0x2) + if (temp1 & 0x2) break; } @@ -562,14 +827,13 @@ static int cs4281_hw_init(struct cs4281_state *card) cs4281_write_ac97(card, BA0_AC97_POWERDOWN, temp1 &= 0xfeff); // Wait until we sample ADC ready state. - for(temp2=0; temp2<32; temp2++) - { + for (temp2 = 0; temp2 < 32; temp2++) { // Let's wait a mil to let things settle. delayus(1000); // Read the current state of the power control reg. cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1); // If the ADC ready state bit is set, stop waiting. - if(temp1 & 0x1) + if (temp1 & 0x1) break; } // Set up 4281 Register contents that @@ -580,19 +844,19 @@ static int cs4281_hw_init(struct cs4281_state *card) // Set the fifo to be 15 bytes at offset zero. ac97_slotid = 0x01000f00; // FCR0.RS[4:0]=1(=>slot4, right PCM playback). - // FCR0.LS[4:0]=0(=>slot3, left PCM playback). - // FCR0.SZ[6-0]=15; FCR0.OF[6-0]=0. - writel(ac97_slotid, card->pBA0 + BA0_FCR0); // (180h) - writel(ac97_slotid | FCRn_FEN, card->pBA0 + BA0_FCR0); // Turn on FIFO Enable. + // FCR0.LS[4:0]=0(=>slot3, left PCM playback). + // FCR0.SZ[6-0]=15; FCR0.OF[6-0]=0. + writel(ac97_slotid, card->pBA0 + BA0_FCR0); // (180h) + writel(ac97_slotid | FCRn_FEN, card->pBA0 + BA0_FCR0); // Turn on FIFO Enable. // For capture, we map AC97 slot 10 and 11(Left // and Right PCM Record) to DMA Channel 1. // Set the fifo to be 15 bytes at offset sixteen. ac97_slotid = 0x0B0A0f10; // FCR1.RS[4:0]=11(=>slot11, right PCM record). - // FCR1.LS[4:0]=10(=>slot10, left PCM record). - // FCR1.SZ[6-0]=15; FCR1.OF[6-0]=16. - writel(ac97_slotid | FCRn_PSH, card->pBA0 + BA0_FCR1); // (184h) - writel(ac97_slotid | FCRn_FEN, card->pBA0 + BA0_FCR1); // Turn on FIFO Enable. + // FCR1.LS[4:0]=10(=>slot10, left PCM record). + // FCR1.SZ[6-0]=15; FCR1.OF[6-0]=16. + writel(ac97_slotid | FCRn_PSH, card->pBA0 + BA0_FCR1); // (184h) + writel(ac97_slotid | FCRn_FEN, card->pBA0 + BA0_FCR1); // Turn on FIFO Enable. // Map the Playback SRC to the same AC97 slots(3 & 4-- // --Playback left & right)as DMA channel 0. @@ -600,33 +864,34 @@ static int cs4281_hw_init(struct cs4281_state *card) // -- Record left & right) as DMA channel 1. ac97_slotid = 0x0b0a0100; // SCRSA.PRSS[4:0]=1(=>slot4, right PCM playback). - // SCRSA.PLSS[4:0]=0(=>slot3, left PCM playback). - // SCRSA.CRSS[4:0]=11(=>slot11, right PCM record) - // SCRSA.CLSS[4:0]=10(=>slot10, left PCM record). - writel(ac97_slotid, card->pBA0 + BA0_SRCSA); // (75ch) + // SCRSA.PLSS[4:0]=0(=>slot3, left PCM playback). + // SCRSA.CRSS[4:0]=11(=>slot11, right PCM record) + // SCRSA.CLSS[4:0]=10(=>slot10, left PCM record). + writel(ac97_slotid, card->pBA0 + BA0_SRCSA); // (75ch) // Set 'Half Terminal Count Interrupt Enable' and 'Terminal // Count Interrupt Enable' in DMA Control Registers 0 & 1. // Set 'MSK' flag to 1 to keep the DMA engines paused. - temp1 = (DCRn_HTCIE | DCRn_TCIE | DCRn_MSK); // (00030001h) - writel(temp1, card->pBA0 + BA0_DCR0); // (154h - writel(temp1, card->pBA0 + BA0_DCR1); // (15ch) + temp1 = (DCRn_HTCIE | DCRn_TCIE | DCRn_MSK); // (00030001h) + writel(temp1, card->pBA0 + BA0_DCR0); // (154h + writel(temp1, card->pBA0 + BA0_DCR1); // (15ch) // Set 'Auto-Initialize Control' to 'enabled'; For playback, // set 'Transfer Type Control'(TR[1:0]) to 'read transfer', // for record, set Transfer Type Control to 'write transfer'. // All other bits set to zero; Some will be changed @ transfer start. - temp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_READ); // (20000018h) - writel(temp1, card->pBA0 + BA0_DMR0); // (150h) - temp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE); // (20000014h) - writel(temp1, card->pBA0 + BA0_DMR1); // (158h) + temp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_READ); // (20000018h) + writel(temp1, card->pBA0 + BA0_DMR0); // (150h) + temp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE); // (20000014h) + writel(temp1, card->pBA0 + BA0_DMR1); // (158h) // Enable DMA interrupts generally, and // DMA0 & DMA1 interrupts specifically. - temp1 = readl(card->pBA0 + BA0_HIMR) & 0xfffbfcff; - writel(temp1, card->pBA0+BA0_HIMR); + temp1 = readl(card->pBA0 + BA0_HIMR) & 0xfffbfcff; + writel(temp1, card->pBA0 + BA0_HIMR); - CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs4281: cs4281_hw_init()- 0\n") ); + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: cs4281_hw_init()- 0\n")); return 0; } @@ -638,29 +903,30 @@ static void cs4281_play_rate(struct cs4281_state *card, u32 playrate) { u32 DACSRvalue = 1; - // Based on the sample rate, program the DACSR register. - if(playrate == 8000) + // Based on the sample rate, program the DACSR register. + if (playrate == 8000) DACSRvalue = 5; - if(playrate == 11025) + if (playrate == 11025) DACSRvalue = 4; - else if(playrate == 22050) + else if (playrate == 22050) DACSRvalue = 2; - else if(playrate == 44100) + else if (playrate == 44100) DACSRvalue = 1; - else if((playrate <= 48000) && (playrate >= 6023)) - DACSRvalue = 24576000/(playrate*16); - else if(playrate < 6023) + else if ((playrate <= 48000) && (playrate >= 6023)) + DACSRvalue = 24576000 / (playrate * 16); + else if (playrate < 6023) // Not allowed by open. return; - else if(playrate > 48000) + else if (playrate > 48000) // Not allowed by open. return; - CS_DBGOUT(CS_WAVE_WRITE | CS_PARMS, 2, printk(KERN_INFO - "cs4281: cs4281_play_rate(): DACSRvalue=0x%.8x playrate=%d\n", - DACSRvalue,playrate)); - // Write the 'sample rate select code' - // to the 'DAC Sample Rate' register. - writel(DACSRvalue, card->pBA0 + BA0_DACSR); // (744h) + CS_DBGOUT(CS_WAVE_WRITE | CS_PARMS, 2, printk(KERN_INFO + "cs4281: cs4281_play_rate(): DACSRvalue=0x%.8x playrate=%d\n", + DACSRvalue, + playrate)); + // Write the 'sample rate select code' + // to the 'DAC Sample Rate' register. + writel(DACSRvalue, card->pBA0 + BA0_DACSR); // (744h) } //****************************************************************************** @@ -670,35 +936,32 @@ static void cs4281_record_rate(struct cs4281_state *card, u32 outrate) { u32 ADCSRvalue = 1; - // - // Based on the sample rate, program the ADCSR register - // - if(outrate == 8000) + // + // Based on the sample rate, program the ADCSR register + // + if (outrate == 8000) ADCSRvalue = 5; - if(outrate == 11025) + if (outrate == 11025) ADCSRvalue = 4; - else if(outrate == 22050) + else if (outrate == 22050) ADCSRvalue = 2; - else if(outrate == 44100) + else if (outrate == 44100) ADCSRvalue = 1; - else if((outrate <= 48000) && (outrate >= 6023)) - ADCSRvalue = 24576000/(outrate*16); - else if(outrate < 6023) - { + else if ((outrate <= 48000) && (outrate >= 6023)) + ADCSRvalue = 24576000 / (outrate * 16); + else if (outrate < 6023) { // Not allowed by open. return; - } - else if(outrate > 48000) - { + } else if (outrate > 48000) { // Not allowed by open. return; } - CS_DBGOUT(CS_WAVE_READ | CS_PARMS, 2, printk(KERN_INFO - "cs4281: cs4281_record_rate(): ADCSRvalue=0x%.8x outrate=%d\n", - ADCSRvalue,outrate) ); + CS_DBGOUT(CS_WAVE_READ | CS_PARMS, 2, printk(KERN_INFO + "cs4281: cs4281_record_rate(): ADCSRvalue=0x%.8x outrate=%d\n", + ADCSRvalue, outrate)); // Write the 'sample rate select code // to the 'ADC Sample Rate' register. - writel(ADCSRvalue, card->pBA0 + BA0_ADCSR); // (748h) + writel(ADCSRvalue, card->pBA0 + BA0_ADCSR); // (748h) } @@ -708,11 +971,12 @@ static void stop_dac(struct cs4281_state *s) unsigned long flags; unsigned temp1; - CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO "cs4281: stop_dac():\n") ); + CS_DBGOUT(CS_WAVE_WRITE, 3, + printk(KERN_INFO "cs4281: stop_dac():\n")); spin_lock_irqsave(&s->lock, flags); s->ena &= ~FMODE_WRITE; - temp1 = readl(s->pBA0+ BA0_DCR0) | DCRn_MSK; - writel(temp1, s->pBA0+BA0_DCR0); + temp1 = readl(s->pBA0 + BA0_DCR0) | DCRn_MSK; + writel(temp1, s->pBA0 + BA0_DCR0); spin_unlock_irqrestore(&s->lock, flags); } @@ -723,20 +987,27 @@ static void start_dac(struct cs4281_state *s) unsigned long flags; unsigned temp1; - CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO "cs4281: start_dac():\n") ); + CS_DBGOUT(CS_FUNCTION, 3, + printk(KERN_INFO "cs4281: start_dac()+\n")); spin_lock_irqsave(&s->lock, flags); if (!(s->ena & FMODE_WRITE) && (s->dma_dac.mapped || - s->dma_dac.count > 0) && s->dma_dac.ready) { + s->dma_dac.count > 0) + && s->dma_dac.ready) { s->ena |= FMODE_WRITE; - temp1 = readl(s->pBA0+BA0_DCR0) & ~DCRn_MSK; // Clear DMA0 channel mask. - writel(temp1, s->pBA0+BA0_DCR0); // Start DMA'ing. - writel(HICR_IEV | HICR_CHGM, s->pBA0+BA0_HICR); // Enable interrupts. - - writel(7, s->pBA0+BA0_PPRVC); - writel(7, s->pBA0+BA0_PPLVC); - + temp1 = readl(s->pBA0 + BA0_DCR0) & ~DCRn_MSK; // Clear DMA0 channel mask. + writel(temp1, s->pBA0 + BA0_DCR0); // Start DMA'ing. + writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR); // Enable interrupts. + + writel(7, s->pBA0 + BA0_PPRVC); + writel(7, s->pBA0 + BA0_PPLVC); + CS_DBGOUT(CS_WAVE_WRITE | CS_PARMS, 8, printk(KERN_INFO + "cs4281: start_dac(): writel 0x%x start dma\n", + temp1)); + } spin_unlock_irqrestore(&s->lock, flags); + CS_DBGOUT(CS_FUNCTION, 3, + printk(KERN_INFO "cs4281: start_dac()-\n")); } @@ -745,13 +1016,21 @@ static void stop_adc(struct cs4281_state *s) unsigned long flags; unsigned temp1; - CS_DBGOUT(CS_WAVE_READ, 3, printk(KERN_INFO "cs4281: stop_adc():\n") ); + CS_DBGOUT(CS_FUNCTION, 3, + printk(KERN_INFO "cs4281: stop_adc()+\n")); spin_lock_irqsave(&s->lock, flags); s->ena &= ~FMODE_READ; - temp1 = readl(s->pBA0+ BA0_DCR1) | DCRn_MSK; - writel(temp1, s->pBA0+BA0_DCR1); + + if (s->conversion == 1) { + s->conversion = 0; + s->prop_adc.fmt = s->prop_adc.fmt_original; + } + temp1 = readl(s->pBA0 + BA0_DCR1) | DCRn_MSK; + writel(temp1, s->pBA0 + BA0_DCR1); spin_unlock_irqrestore(&s->lock, flags); + CS_DBGOUT(CS_FUNCTION, 3, + printk(KERN_INFO "cs4281: stop_adc()-\n")); } @@ -760,41 +1039,92 @@ static void start_adc(struct cs4281_state *s) unsigned long flags; unsigned temp1; - CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO "cs4281: start_adc():\n") ); + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: start_adc()+\n")); spin_lock_irqsave(&s->lock, flags); - if (!(s->ena & FMODE_READ) && (s->dma_adc.mapped - || s->dma_adc.count <= - (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize)) - && s->dma_adc.ready) - { + if (!(s->ena & FMODE_READ) && + (s->dma_adc.mapped || s->dma_adc.count <= + (signed) (s->dma_adc.dmasize - 2 * s->dma_adc.fragsize)) + && s->dma_adc.ready) { + if (s->prop_adc.fmt & AFMT_S8 || s->prop_adc.fmt & AFMT_U8) { + // + // now only use 16 bit capture, due to truncation issue + // in the chip, noticable distortion occurs. + // allocate buffer and then convert from 16 bit to + // 8 bit for the user buffer. + // + s->prop_adc.fmt_original = s->prop_adc.fmt; + if (s->prop_adc.fmt & AFMT_S8) { + s->prop_adc.fmt &= ~AFMT_S8; + s->prop_adc.fmt |= AFMT_S16_LE; + } + if (s->prop_adc.fmt & AFMT_U8) { + s->prop_adc.fmt &= ~AFMT_U8; + s->prop_adc.fmt |= AFMT_U16_LE; + } + // + // prog_dmabuf_adc performs a stop_adc() but that is + // ok since we really haven't started the DMA yet. + // + prog_codec(s, CS_TYPE_ADC); + + if (prog_dmabuf_adc(s) != 0) { + CS_DBGOUT(CS_ERROR, 3, + printk(KERN_INFO + "cs4281: start_adc(): error in prog_dmabuf_adc\n")); + } + s->conversion = 1; + } s->ena |= FMODE_READ; - temp1 = readl(s->pBA0+BA0_DCR1) & ~ DCRn_MSK; // Clear DMA1 channel mask bit. - writel(temp1, s->pBA0+BA0_DCR1); // Start recording - writel(HICR_IEV | HICR_CHGM, s->pBA0+BA0_HICR); // Enable interrupts. + temp1 = readl(s->pBA0 + BA0_DCR1) & ~DCRn_MSK; // Clear DMA1 channel mask bit. + writel(temp1, s->pBA0 + BA0_DCR1); // Start recording + writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR); // Enable interrupts. + CS_DBGOUT(CS_PARMS, 6, + printk(KERN_INFO + "cs4281: start_adc(): writel 0x%x \n", + temp1)); } spin_unlock_irqrestore(&s->lock, flags); + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: start_adc()-\n")); } // --------------------------------------------------------------------- -#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT) // == 3(for PC), = log base 2( buff sz = 32k). -#define DMABUF_MINORDER 1 // ==> min buffer size = 8K. +// use 64k (+1) rather than 32k as some of the higher frequencies need a larger buffer. +// comments reflect 32k. +#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT+1) // == 3(for PC), = log base 2( buff sz = 32k). +#define DMABUF_MINORDER 1 // ==> min buffer size = 8K. -extern void dealloc_dmabuf(struct cs4281_state *s, struct dmabuf *db) +extern void dealloc_dmabuf(struct cs4281_state *s, struct dmabuf *db) { struct page *map, *mapend; if (db->rawbuf) { // Undo prog_dmabuf()'s marking the pages as reserved - mapend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); + mapend = + virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - + 1); for (map = virt_to_page(db->rawbuf); map <= mapend; map++) - clear_bit(PG_reserved, &map->flags); - pci_free_consistent(s->pcidev,PAGE_SIZE<buforder, - db->rawbuf,db->dmaaddr); + mem_map_unreserve(map); + pci_free_consistent(s->pcidev, PAGE_SIZE << db->buforder, + db->rawbuf, db->dmaaddr); } + if (s->tmpbuff && (db->type == CS_TYPE_ADC)) { + // Undo prog_dmabuf()'s marking the pages as reserved + mapend = + virt_to_page(s->tmpbuff + + (PAGE_SIZE << s->buforder_tmpbuff) - 1); + for (map = virt_to_page(s->tmpbuff); map <= mapend; map++) + mem_map_unreserve(map); + pci_free_consistent(s->pcidev, + PAGE_SIZE << s->buforder_tmpbuff, + s->tmpbuff, s->dmaaddr_tmpbuff); + } + s->tmpbuff = NULL; db->rawbuf = NULL; db->mapped = db->ready = 0; } @@ -806,91 +1136,165 @@ static int prog_dmabuf(struct cs4281_state *s, struct dmabuf *db) unsigned bufs, sample_shift = 0; struct page *map, *mapend; - db->hwptr = db->swptr = db->total_bytes = db->count = - db->error = db->endcleared = db->blocks = 0; + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: prog_dmabuf()+\n")); + db->hwptr = db->swptr = db->total_bytes = db->count = db->error = + db->endcleared = db->blocks = db->wakeup = 0; + if (!db->rawbuf) { db->ready = db->mapped = 0; - for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) - if ((db->rawbuf = (void *)pci_alloc_consistent( - s->pcidev, PAGE_SIZE << order, &db->dmaaddr))) - break; - if (!db->rawbuf) - { - CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR - "cs4281: prog_dmabuf(): unable to allocate rawbuf\n") ); + for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; + order--) + if ( + (db->rawbuf = + (void *) pci_alloc_consistent(s->pcidev, + PAGE_SIZE << + order, + &db-> + dmaaddr))) + break; + if (!db->rawbuf) { + CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR + "cs4281: prog_dmabuf(): unable to allocate rawbuf\n")); return -ENOMEM; } db->buforder = order; // Now mark the pages as reserved; otherwise the // remap_page_range() in cs4281_mmap doesn't work. - // 1. get index to last page in mem_map array for rawbuf. - mapend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); - - // 2. mark each physical page in range as 'reserved'. + // 1. get index to last page in mem_map array for rawbuf. + mapend = + virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - + 1); + + // 2. mark each physical page in range as 'reserved'. for (map = virt_to_page(db->rawbuf); map <= mapend; map++) - set_bit(PG_reserved, &map->flags); + mem_map_reserve(map); + } + if (!s->tmpbuff && (db->type == CS_TYPE_ADC)) { + for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; + order--) + if ( + (s->tmpbuff = + (void *) pci_alloc_consistent(s->pcidev, + PAGE_SIZE << + order, + &s-> + dmaaddr_tmpbuff))) + break; + if (!s->tmpbuff) { + CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR + "cs4281: prog_dmabuf(): unable to allocate tmpbuff\n")); + return -ENOMEM; + } + s->buforder_tmpbuff = order; + // Now mark the pages as reserved; otherwise the + // remap_page_range() in cs4281_mmap doesn't work. + // 1. get index to last page in mem_map array for rawbuf. + mapend = + virt_to_page(s->tmpbuff + + (PAGE_SIZE << s->buforder_tmpbuff) - 1); + + // 2. mark each physical page in range as 'reserved'. + for (map = virt_to_page(s->tmpbuff); map <= mapend; map++) + mem_map_reserve(map); + } + if (db->type == CS_TYPE_DAC) { + if (s->prop_dac.fmt & (AFMT_S16_LE | AFMT_U16_LE)) + sample_shift++; + if (s->prop_dac.channels > 1) + sample_shift++; + bytespersec = s->prop_dac.rate << sample_shift; + } else // CS_TYPE_ADC + { + if (s->prop_adc.fmt & (AFMT_S16_LE | AFMT_U16_LE)) + sample_shift++; + if (s->prop_adc.channels > 1) + sample_shift++; + bytespersec = s->prop_adc.rate << sample_shift; } - if (s->fmt & (AFMT_S16_LE | AFMT_U16_LE)) - sample_shift++; - if (s->channels > 1) - sample_shift++; - bytespersec = s->rate << sample_shift; bufs = PAGE_SIZE << db->buforder; -#define INTERRUPT_RATE_MS 100 // Interrupt rate in milliseconds. +#define INTERRUPT_RATE_MS 100 // Interrupt rate in milliseconds. db->numfrag = 2; - temp1 = bytespersec/(1000/INTERRUPT_RATE_MS); // Nominal frag size(bytes/interrupt) - db->fragshift = 8; // Min 256 bytes. - while( 1 << db->fragshift < temp1) // Calc power of 2 frag size. - db->fragshift +=1; - db->fragsize = 1 << db->fragshift; + temp1 = bytespersec / (1000 / INTERRUPT_RATE_MS); // Nominal frag size(bytes/interrupt) + db->fragshift = 8; // Min 256 bytes. + while (1 << db->fragshift < temp1) // Calc power of 2 frag size. + db->fragshift += 1; + db->fragsize = 1 << db->fragshift; db->dmasize = db->fragsize * 2; - - // If the calculated size is larger than the allocated - // buffer, divide the allocated buffer into 2 fragments. - if(db->dmasize > bufs) { - db->numfrag = 2; // Two fragments. - db->fragsize = bufs >> 1; // Each 1/2 the alloc'ed buffer. - db->fragsamples = db->fragsize >> sample_shift; // # samples/fragment. - db->dmasize = bufs; // Use all the alloc'ed buffer. - - db->fragshift = 0; // Calculate 'fragshift'. - temp1 = db->fragsize; // update_ptr() uses it - while( (temp1 >>=1) > 1) // to calc 'total-bytes' - db->fragshift +=1; // returned in DSP_GETI/OPTR. - } - CS_DBGOUT(CS_PARMS, 3, printk(KERN_INFO - "cs4281: prog_dmabuf(): numfrag=%d fragsize=%d fragsamples=%d fragshift=%d\n", - db->numfrag,db->fragsize,db->fragsamples,db->fragshift) ); + db->fragsamples = db->fragsize >> sample_shift; // # samples/fragment. + +// If the calculated size is larger than the allocated +// buffer, divide the allocated buffer into 2 fragments. + if (db->dmasize > bufs) { + + db->numfrag = 2; // Two fragments. + db->fragsize = bufs >> 1; // Each 1/2 the alloc'ed buffer. + db->fragsamples = db->fragsize >> sample_shift; // # samples/fragment. + db->dmasize = bufs; // Use all the alloc'ed buffer. + + db->fragshift = 0; // Calculate 'fragshift'. + temp1 = db->fragsize; // update_ptr() uses it + while ((temp1 >>= 1) > 1) // to calc 'total-bytes' + db->fragshift += 1; // returned in DSP_GETI/OPTR. + } + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: prog_dmabuf()-\n")); + CS_DBGOUT(CS_PARMS, 8, + printk(KERN_INFO + "cs4281: prog_dmabuf(): numfrag=%d fragsize=%d fragsamples=%d fragshift=%d bufs=%d fmt=0x%x ch=%d\n", + db->numfrag, db->fragsize, db->fragsamples, + db->fragshift, bufs, + (db->type == + CS_TYPE_DAC) ? s->prop_dac.fmt : s->prop_adc.fmt, + (db->type == + CS_TYPE_DAC) ? s->prop_dac.channels : s-> + prop_adc.channels)); return 0; -} +} static int prog_dmabuf_adc(struct cs4281_state *s) { unsigned long va; - unsigned count; + unsigned count; int c; stop_adc(s); + s->dma_adc.type = CS_TYPE_ADC; if ((c = prog_dmabuf(s, &s->dma_adc))) return c; - + + if (s->dma_adc.rawbuf) { + memset(s->dma_adc.rawbuf, + (s->prop_adc. + fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0, + s->dma_adc.dmasize); + } + if (s->tmpbuff) { + memset(s->tmpbuff, + (s->prop_adc. + fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0, + PAGE_SIZE << s->buforder_tmpbuff); + } + va = virt_to_bus(s->dma_adc.rawbuf); - - count = s->dma_adc.dmasize; - - if(s->fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) - count /= 2; // 16-bit. - - if(s->channels > 1) - count /= 2; // Assume stereo. - - CS_DBGOUT(CS_WAVE_READ, 3, printk(KERN_INFO - "cs4281: prog_dmabuf_adc(): count=%d va=0x%.8x\n", count,(unsigned)va) ); - - writel(va, s->pBA0+BA0_DBA1); // Set buffer start address. - writel(count-1, s->pBA0+BA0_DBC1); // Set count. + + count = s->dma_adc.dmasize; + + if (s->prop_adc. + fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) + count /= 2; // 16-bit. + + if (s->prop_adc.channels > 1) + count /= 2; // Assume stereo. + + CS_DBGOUT(CS_WAVE_READ, 3, printk(KERN_INFO + "cs4281: prog_dmabuf_adc(): count=%d va=0x%.8x\n", + count, (unsigned) va)); + + writel(va, s->pBA0 + BA0_DBA1); // Set buffer start address. + writel(count - 1, s->pBA0 + BA0_DBC1); // Set count. s->dma_adc.ready = 1; return 0; } @@ -902,43 +1306,50 @@ static int prog_dmabuf_dac(struct cs4281_state *s) unsigned count; int c; stop_dac(s); + s->dma_dac.type = CS_TYPE_DAC; if ((c = prog_dmabuf(s, &s->dma_dac))) return c; - memset(s->dma_dac.rawbuf, (s->fmt & (AFMT_U8 | AFMT_U16_LE)) - ? 0x80 : 0, s->dma_dac.dmasize); + memset(s->dma_dac.rawbuf, + (s->prop_dac.fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0, + s->dma_dac.dmasize); va = virt_to_bus(s->dma_dac.rawbuf); - count = s->dma_dac.dmasize; - if(s->fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) - count /= 2; // 16-bit. - - if(s->channels > 1) - count /= 2; // Assume stereo. - - writel(va, s->pBA0+BA0_DBA0); // Set buffer start address. - writel(count-1, s->pBA0+BA0_DBC0); // Set count. + count = s->dma_dac.dmasize; + if (s->prop_dac. + fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) + count /= 2; // 16-bit. + + if (s->prop_dac.channels > 1) + count /= 2; // Assume stereo. + + writel(va, s->pBA0 + BA0_DBA0); // Set buffer start address. + writel(count - 1, s->pBA0 + BA0_DBC0); // Set count. - CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO - "cs4281: prog_dmabuf_dac(): count=%d va=0x%.8x\n", count,(unsigned)va) ); + CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO + "cs4281: prog_dmabuf_dac(): count=%d va=0x%.8x\n", + count, (unsigned) va)); s->dma_dac.ready = 1; return 0; } -static void clear_advance(void *buf, unsigned bsize, unsigned bptr, unsigned len, unsigned char c) +static void clear_advance(void *buf, unsigned bsize, unsigned bptr, + unsigned len, unsigned char c) { if (bptr + len > bsize) { unsigned x = bsize - bptr; - memset(((char *)buf) + bptr, c, x); + memset(((char *) buf) + bptr, c, x); bptr = 0; len -= x; } - CS_DBGOUT(CS_WAVE_WRITE, 4, printk(KERN_INFO - "cs4281: clear_advance(): memset %d at 0x%.8x for %d size \n", - (unsigned)c,(unsigned)((char *)buf) + bptr, len) ); - memset(((char *)buf) + bptr, c, len); + CS_DBGOUT(CS_WAVE_WRITE, 4, printk(KERN_INFO + "cs4281: clear_advance(): memset %d at 0x%.8x for %d size \n", + (unsigned) c, + (unsigned) ((char *) buf) + + bptr, len)); + memset(((char *) buf) + bptr, c, len); } @@ -947,156 +1358,219 @@ static void clear_advance(void *buf, unsigned bsize, unsigned bptr, unsigned len static void cs4281_update_ptr(struct cs4281_state *s) { int diff; - unsigned hwptr, va, temp1; + unsigned hwptr, va; // update ADC pointer if (s->ena & FMODE_READ) { - hwptr = readl(s->pBA0+BA0_DCA1); // Read capture DMA address. + hwptr = readl(s->pBA0 + BA0_DCA1); // Read capture DMA address. va = virt_to_bus(s->dma_adc.rawbuf); - hwptr -= (unsigned)va; - diff = (s->dma_adc.dmasize + hwptr - s->dma_adc.hwptr) % s->dma_adc.dmasize; + hwptr -= (unsigned) va; + diff = + (s->dma_adc.dmasize + hwptr - + s->dma_adc.hwptr) % s->dma_adc.dmasize; s->dma_adc.hwptr = hwptr; s->dma_adc.total_bytes += diff; s->dma_adc.count += diff; + if (s->dma_adc.count > s->dma_adc.dmasize) + s->dma_adc.count = s->dma_adc.dmasize; if (s->dma_adc.mapped) { - if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) - wake_up(&s->dma_adc.wait); + if (s->dma_adc.count >= + (signed) s->dma_adc.fragsize) wake_up(&s-> + dma_adc. + wait); } else { if (s->dma_adc.count > 0) wake_up(&s->dma_adc.wait); } - CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO - "cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n", - (unsigned)s,s->dma_adc.hwptr,s->dma_adc.total_bytes,s->dma_adc.count) ); + CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO + "cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n", + (unsigned) s, + s->dma_adc.hwptr, + s->dma_adc.total_bytes, + s->dma_adc.count)); } // update DAC pointer // // check for end of buffer, means that we are going to wait for another interrupt // to allow silence to fill the fifos on the part, to keep pops down to a minimum. // - if ( (s->ena & FMODE_WRITE) && (!s->endofbuffer) ) - { - hwptr = readl(s->pBA0+BA0_DCA0); // Read play DMA address. + if (s->ena & FMODE_WRITE) { + hwptr = readl(s->pBA0 + BA0_DCA0); // Read play DMA address. va = virt_to_bus(s->dma_dac.rawbuf); - hwptr -= (unsigned)va; - diff = (s->dma_dac.dmasize + hwptr - s->dma_dac.hwptr) % s->dma_dac.dmasize; + hwptr -= (unsigned) va; + diff = + (s->dma_dac.dmasize + hwptr - + s->dma_dac.hwptr) % s->dma_dac.dmasize; s->dma_dac.hwptr = hwptr; s->dma_dac.total_bytes += diff; if (s->dma_dac.mapped) { s->dma_dac.count += diff; - if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) + if (s->dma_dac.count >= s->dma_dac.fragsize) { + s->dma_dac.wakeup = 1; wake_up(&s->dma_dac.wait); + if (s->dma_dac.count > s->dma_dac.dmasize) + s->dma_dac.count &= + s->dma_dac.dmasize - 1; + } } else { + s->dma_dac.count -= diff; if (s->dma_dac.count <= 0) { - s->ena &= ~FMODE_WRITE; - temp1 = readl(s->pBA0+BA0_DCR0); - // - // fill with silence, and wait on turning off the DAC until interrupt routine. - // wait on "Poke(pBA0+BA0_DCR0, temp1 | DCRn_MSK); // Stop Play DMA" - // - CS_DBGOUT(CS_WAVE_WRITE, 6, printk(KERN_INFO - "cs4281: cs4281_update_ptr(): memset %d at 0x%.8x for %d size \n", - (unsigned)(s->fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0, - (unsigned)s->dma_dac.rawbuf, s->dma_dac.dmasize) ); - memset(s->dma_dac.rawbuf, (s->fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0, - s->dma_dac.dmasize); - s->endofbuffer = 1; - } else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize - && !s->dma_dac.endcleared) { - clear_advance(s->dma_dac.rawbuf, - s->dma_dac.dmasize, s->dma_dac.swptr, + // + // fill with silence, and do not shut down the DAC. + // Continue to play silence until the _release. + // + CS_DBGOUT(CS_WAVE_WRITE, 6, + printk(KERN_INFO + "cs4281: cs4281_update_ptr(): memset %d at 0x%.8x for %d size \n", + (unsigned) (s->prop_dac. + fmt & (AFMT_U8 + | + AFMT_U16_LE)) + ? 0x80 : 0, + (unsigned) s->dma_dac. + rawbuf, + s->dma_dac.dmasize)); + memset(s->dma_dac.rawbuf, + (s->prop_dac. + fmt & (AFMT_U8 | AFMT_U16_LE)) ? + 0x80 : 0, s->dma_dac.dmasize); + } else if (s->dma_dac.count <= + (signed) s->dma_dac.fragsize + && !s->dma_dac.endcleared) { + clear_advance(s->dma_dac.rawbuf, + s->dma_dac.dmasize, + s->dma_dac.swptr, s->dma_dac.fragsize, - (s->fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0); + (s->prop_dac. + fmt & (AFMT_U8 | + AFMT_U16_LE)) ? 0x80 + : 0); s->dma_dac.endcleared = 1; } - if (s->dma_dac.count < (signed)s->dma_dac.dmasize) + if (s->dma_dac.count < (signed) s->dma_dac.dmasize) wake_up(&s->dma_dac.wait); } - CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO - "cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n", - (unsigned)s,s->dma_dac.hwptr,s->dma_dac.total_bytes,s->dma_dac.count) ); + CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO + "cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n", + (unsigned) s, + s->dma_dac.hwptr, + s->dma_dac.total_bytes, + s->dma_dac.count)); } } // --------------------------------------------------------------------- -static void prog_codec(struct cs4281_state *s) +static void prog_codec(struct cs4281_state *s, unsigned type) { unsigned long flags; unsigned temp1, format; - CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO "cs4281: prog_codec()+ \n") ); + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: prog_codec()+ \n")); spin_lock_irqsave(&s->lock, flags); - temp1 = readl(s->pBA0+BA0_DCR0); - writel(temp1 | DCRn_MSK, s->pBA0+BA0_DCR0); // Stop play DMA, if active. - temp1 = readl(s->pBA0+BA0_DCR1); - writel(temp1 | DCRn_MSK, s->pBA0+BA0_DCR1); // Stop capture DMA, if active. - - // program sampling rates - // Note, for CS4281, capture & play rates can be set independently. - cs4281_record_rate(s, s->rate); - - // program ADC parameters - format = DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE; - if(s->fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) { // 16-bit - if(s->fmt & (AFMT_S16_BE | AFMT_U16_BE)) // Big-endian? - format |= DMRn_BEND; - if(s->fmt & (AFMT_U16_LE | AFMT_U16_BE)) - format |= DMRn_USIGN; // Unsigned. - } - else - format |= DMRn_SIZE8 | DMRn_USIGN; // 8-bit, unsigned - if(s->channels < 2) - format |= DMRn_MONO; - - writel(format, s->pBA0+BA0_DMR1); - - - // program DAC parameters - format = DMRn_DMA | DMRn_AUTO | DMRn_TR_READ; - if(s->fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) { // 16-bit - if(s->fmt & (AFMT_S16_BE | AFMT_U16_BE)) - format |= DMRn_BEND; // Big Endian. - if(s->fmt & (AFMT_U16_LE | AFMT_U16_BE)) - format |= DMRn_USIGN; // Unsigned. - } - else - format |= DMRn_SIZE8 | DMRn_USIGN; // 8-bit, unsigned - - if(s->channels < 2) - format |= DMRn_MONO; - - writel(format, s->pBA0+BA0_DMR0); + if (type == CS_TYPE_ADC) { + temp1 = readl(s->pBA0 + BA0_DCR1); + writel(temp1 | DCRn_MSK, s->pBA0 + BA0_DCR1); // Stop capture DMA, if active. + + // program sampling rates + // Note, for CS4281, capture & play rates can be set independently. + cs4281_record_rate(s, s->prop_adc.rate); + + // program ADC parameters + format = DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE; + if (s->prop_adc. + fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) { // 16-bit + if (s->prop_adc.fmt & (AFMT_S16_BE | AFMT_U16_BE)) // Big-endian? + format |= DMRn_BEND; + if (s->prop_adc.fmt & (AFMT_U16_LE | AFMT_U16_BE)) + format |= DMRn_USIGN; // Unsigned. + } else + format |= DMRn_SIZE8 | DMRn_USIGN; // 8-bit, unsigned + if (s->prop_adc.channels < 2) + format |= DMRn_MONO; + + writel(format, s->pBA0 + BA0_DMR1); + + CS_DBGOUT(CS_PARMS, 2, printk(KERN_INFO + "cs4281: prog_codec(): adc %s %s %s rate=%d DMR0 format=0x%.8x\n", + (format & DMRn_SIZE8) ? "8" : + "16", + (format & DMRn_USIGN) ? + "Unsigned" : "Signed", + (format & DMRn_MONO) ? "Mono" + : "Stereo", s->prop_adc.rate, + format)); + + s->ena &= ~FMODE_READ; // not capturing data yet + } + + + if (type == CS_TYPE_DAC) { + temp1 = readl(s->pBA0 + BA0_DCR0); + writel(temp1 | DCRn_MSK, s->pBA0 + BA0_DCR0); // Stop play DMA, if active. + + // program sampling rates + // Note, for CS4281, capture & play rates can be set independently. + cs4281_play_rate(s, s->prop_dac.rate); + + // program DAC parameters + format = DMRn_DMA | DMRn_AUTO | DMRn_TR_READ; + if (s->prop_dac. + fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) { // 16-bit + if (s->prop_dac.fmt & (AFMT_S16_BE | AFMT_U16_BE)) + format |= DMRn_BEND; // Big Endian. + if (s->prop_dac.fmt & (AFMT_U16_LE | AFMT_U16_BE)) + format |= DMRn_USIGN; // Unsigned. + } else + format |= DMRn_SIZE8 | DMRn_USIGN; // 8-bit, unsigned + + if (s->prop_dac.channels < 2) + format |= DMRn_MONO; + + writel(format, s->pBA0 + BA0_DMR0); + + + CS_DBGOUT(CS_PARMS, 2, printk(KERN_INFO + "cs4281: prog_codec(): dac %s %s %s rate=%d DMR0 format=0x%.8x\n", + (format & DMRn_SIZE8) ? "8" : + "16", + (format & DMRn_USIGN) ? + "Unsigned" : "Signed", + (format & DMRn_MONO) ? "Mono" + : "Stereo", s->prop_dac.rate, + format)); + + s->ena &= ~FMODE_WRITE; // not capturing data yet - CS_DBGOUT(CS_PARMS, 2, printk(KERN_INFO - "cs4281: prog_codec(): format=0x%.8x rate=%d\n", format,s->rate) ); - - cs4281_play_rate(s, s->rate); - - s->ena = 0; // Neither writing or reading. + } spin_unlock_irqrestore(&s->lock, flags); + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: prog_codec()- \n")); } // --------------------------------------------------------------------- -static const char invalid_magic[] = KERN_CRIT "cs4281: invalid magic value\n"; +static const char invalid_magic[] = + KERN_CRIT "cs4281: invalid magic value\n"; #define VALIDATE_STATE(s) \ ({ \ - if (!(s) || (s)->magic != CS4281_MAGIC) { \ - printk(invalid_magic); \ - return -ENXIO; \ - } \ + if (!(s) || (s)->magic != CS4281_MAGIC) { \ + printk(invalid_magic); \ + return -ENXIO; \ + } \ }) // --------------------------------------------------------------------- -static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd, unsigned long arg) +static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd, + unsigned long arg) { // Index to mixer_src[] is value of AC97 Input Mux Select Reg. // Value of array member is recording source Device ID Mask. @@ -1104,39 +1578,81 @@ static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd, unsigned long a SOUND_MASK_MIC, SOUND_MASK_CD, 0, SOUND_MASK_LINE1, SOUND_MASK_LINE, SOUND_MASK_VOLUME, 0, 0 }; - + // Index of mixtable1[] member is Device ID // and must be <= SOUND_MIXER_NRDEVICES. // Value of array member is index into s->mix.vol[] static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = { - [SOUND_MIXER_PCM] = 1, // voice - [SOUND_MIXER_LINE1] = 2, // AUX - [SOUND_MIXER_CD] = 3, // CD - [SOUND_MIXER_LINE] = 4, // Line - [SOUND_MIXER_SYNTH] = 5, // FM - [SOUND_MIXER_MIC] = 6, // Mic - [SOUND_MIXER_SPEAKER] = 7, // Speaker - [SOUND_MIXER_RECLEV] = 8, // Recording level - [SOUND_MIXER_VOLUME] = 9 // Master Volume + [SOUND_MIXER_PCM] = 1, // voice + [SOUND_MIXER_LINE1] = 2, // AUX + [SOUND_MIXER_CD] = 3, // CD + [SOUND_MIXER_LINE] = 4, // Line + [SOUND_MIXER_SYNTH] = 5, // FM + [SOUND_MIXER_MIC] = 6, // Mic + [SOUND_MIXER_SPEAKER] = 7, // Speaker + [SOUND_MIXER_RECLEV] = 8, // Recording level + [SOUND_MIXER_VOLUME] = 9 // Master Volume }; - - + + static const unsigned mixreg[] = { BA0_AC97_PCM_OUT_VOLUME, - BA0_AC97_AUX_VOLUME, - BA0_AC97_CD_VOLUME, + BA0_AC97_AUX_VOLUME, + BA0_AC97_CD_VOLUME, BA0_AC97_LINE_IN_VOLUME }; unsigned char l, r, rl, rr, vidx; - unsigned char attentbl[11] = {63,42,26,17,14,11,8,6,4,2,0}; + unsigned char attentbl[11] = + { 63, 42, 26, 17, 14, 11, 8, 6, 4, 2, 0 }; unsigned temp1; int i, val; VALIDATE_STATE(s); - + CS_DBGOUT(CS_FUNCTION, 4, + printk(KERN_INFO + "cs4281: mixer_ioctl(): s=0x%.8x cmd=0x%.8x\n", + (unsigned) s, cmd)); +#if CSDEBUG + printioctl(cmd); +#endif +#if CSDEBUG_INTERFACE + + if ((cmd == SOUND_MIXER_CS_GETDBGMASK) || + (cmd == SOUND_MIXER_CS_SETDBGMASK) || + (cmd == SOUND_MIXER_CS_GETDBGLEVEL) || + (cmd == SOUND_MIXER_CS_SETDBGLEVEL)) { + switch (cmd) { + + case SOUND_MIXER_CS_GETDBGMASK: + return put_user(cs_debugmask, + (unsigned long *) arg); + + case SOUND_MIXER_CS_GETDBGLEVEL: + return put_user(cs_debuglevel, + (unsigned long *) arg); + + case SOUND_MIXER_CS_SETDBGMASK: + if (get_user(val, (unsigned long *) arg)) + return -EFAULT; + cs_debugmask = val; + return 0; + + case SOUND_MIXER_CS_SETDBGLEVEL: + if (get_user(val, (unsigned long *) arg)) + return -EFAULT; + cs_debuglevel = val; + return 0; + default: + CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO + "cs4281: mixer_ioctl(): ERROR unknown debug cmd\n")); + return 0; + } + } +#endif + if (cmd == SOUND_MIXER_PRIVATE1) { // enable/disable/query mixer preamp - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; if (val != -1) { cs4281_read_ac97(s, BA0_AC97_MIC_VOLUME, &temp1); @@ -1145,27 +1661,29 @@ static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd, unsigned long a } cs4281_read_ac97(s, BA0_AC97_MIC_VOLUME, &temp1); val = (temp1 & 0x40) ? 1 : 0; - return put_user(val, (int *)arg); + return put_user(val, (int *) arg); } if (cmd == SOUND_MIXER_PRIVATE2) { // enable/disable/query spatializer - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; if (val != -1) { temp1 = (val & 0x3f) >> 2; cs4281_write_ac97(s, BA0_AC97_3D_CONTROL, temp1); - cs4281_read_ac97(s, BA0_AC97_GENERAL_PURPOSE, &temp1); - cs4281_write_ac97(s, BA0_AC97_GENERAL_PURPOSE,temp1 | 0x2000); + cs4281_read_ac97(s, BA0_AC97_GENERAL_PURPOSE, + &temp1); + cs4281_write_ac97(s, BA0_AC97_GENERAL_PURPOSE, + temp1 | 0x2000); } cs4281_read_ac97(s, BA0_AC97_3D_CONTROL, &temp1); - return put_user((temp1 << 2) | 3, (int *)arg); + return put_user((temp1 << 2) | 3, (int *) arg); } if (cmd == SOUND_MIXER_INFO) { mixer_info info; strncpy(info.id, "CS4281", sizeof(info.id)); strncpy(info.name, "Crystal CS4281", sizeof(info.name)); info.modify_counter = s->mix.modcnt; - if (copy_to_user((void *)arg, &info, sizeof(info))) + if (copy_to_user((void *) arg, &info, sizeof(info))) return -EFAULT; return 0; } @@ -1173,138 +1691,142 @@ static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd, unsigned long a _old_mixer_info info; strncpy(info.id, "CS4281", sizeof(info.id)); strncpy(info.name, "Crystal CS4281", sizeof(info.name)); - if (copy_to_user((void *)arg, &info, sizeof(info))) + if (copy_to_user((void *) arg, &info, sizeof(info))) return -EFAULT; return 0; } if (cmd == OSS_GETVERSION) - return put_user(SOUND_VERSION, (int *)arg); - + return put_user(SOUND_VERSION, (int *) arg); + if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int)) return -EINVAL; - - // If ioctl has only the IOC_READ bit(bit 31) - // on, process the only-read commands. + + // If ioctl has only the IOC_READ bit(bit 31) + // on, process the only-read commands. if (_IOC_DIR(cmd) == _IOC_READ) { switch (_IOC_NR(cmd)) { - case SOUND_MIXER_RECSRC: // Arg contains a bit for each recording source - cs4281_read_ac97(s, BA0_AC97_RECORD_SELECT, &temp1); - return put_user(mixer_src[temp1 & 7], (int *)arg); - - case SOUND_MIXER_DEVMASK: // Arg contains a bit for each supported device - return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH | SOUND_MASK_CD | - SOUND_MASK_LINE | SOUND_MASK_LINE1 | SOUND_MASK_MIC | - SOUND_MASK_VOLUME | SOUND_MASK_RECLEV | - SOUND_MASK_SPEAKER, (int *)arg); - - case SOUND_MIXER_RECMASK: // Arg contains a bit for each supported recording source - return put_user(SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD - | SOUND_MASK_VOLUME | SOUND_MASK_LINE1, (int *)arg); - - case SOUND_MIXER_STEREODEVS: // Mixer channels supporting stereo - return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH | SOUND_MASK_CD | - SOUND_MASK_LINE | SOUND_MASK_LINE1 | SOUND_MASK_MIC | - SOUND_MASK_VOLUME | SOUND_MASK_RECLEV, (int *)arg); + case SOUND_MIXER_RECSRC: // Arg contains a bit for each recording source + cs4281_read_ac97(s, BA0_AC97_RECORD_SELECT, + &temp1); + return put_user(mixer_src[temp1 & 7], (int *) arg); + + case SOUND_MIXER_DEVMASK: // Arg contains a bit for each supported device + return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH | + SOUND_MASK_CD | SOUND_MASK_LINE | + SOUND_MASK_LINE1 | SOUND_MASK_MIC | + SOUND_MASK_VOLUME | + SOUND_MASK_RECLEV | + SOUND_MASK_SPEAKER, (int *) arg); + + case SOUND_MIXER_RECMASK: // Arg contains a bit for each supported recording source + return put_user(SOUND_MASK_LINE | SOUND_MASK_MIC | + SOUND_MASK_CD | SOUND_MASK_VOLUME | + SOUND_MASK_LINE1, (int *) arg); + + case SOUND_MIXER_STEREODEVS: // Mixer channels supporting stereo + return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH | + SOUND_MASK_CD | SOUND_MASK_LINE | + SOUND_MASK_LINE1 | SOUND_MASK_MIC | + SOUND_MASK_VOLUME | + SOUND_MASK_RECLEV, (int *) arg); case SOUND_MIXER_CAPS: - return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg); + return put_user(SOUND_CAP_EXCL_INPUT, (int *) arg); default: i = _IOC_NR(cmd); - if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i])) + if (i >= SOUND_MIXER_NRDEVICES + || !(vidx = mixtable1[i])) return -EINVAL; - return put_user(s->mix.vol[vidx-1], (int *)arg); + return put_user(s->mix.vol[vidx - 1], (int *) arg); } } - - // If ioctl doesn't have both the IOC_READ and - // the IOC_WRITE bit set, return invalid. - if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) + // If ioctl doesn't have both the IOC_READ and + // the IOC_WRITE bit set, return invalid. + if (_IOC_DIR(cmd) != (_IOC_READ | _IOC_WRITE)) return -EINVAL; - - // Increment the count of volume writes. + + // Increment the count of volume writes. s->mix.modcnt++; - - // Isolate the command; it must be a write. + + // Isolate the command; it must be a write. switch (_IOC_NR(cmd)) { - - case SOUND_MIXER_RECSRC: // Arg contains a bit for each recording source - if (get_user(val, (int *)arg)) + + case SOUND_MIXER_RECSRC: // Arg contains a bit for each recording source + if (get_user(val, (int *) arg)) return -EFAULT; - i = hweight32(val); // i = # bits on in val. - if (i != 1) // One & only 1 bit must be on. + i = hweight32(val); // i = # bits on in val. + if (i != 1) // One & only 1 bit must be on. return 0; - for(i=0; i 100) - l = 100; // Max soundcard.h vol is 100. - if(l < 6) { + if (l > 100) + l = 100; // Max soundcard.h vol is 100. + if (l < 6) { rl = 63; - l = 0; - } - else - rl = attentbl[(10*l)/100]; // Convert 0-100 vol to 63-0 atten. - - r = (val >> 8) & 0xff; - if (r > 100) - r = 100; // Max right volume is 100, too - if(r < 6) { - rr = 63; - r = 0; - } - else - rr = attentbl[(10*r)/100]; // Convert volume to attenuation. - - if ((rl > 60 ) && (rr > 60)) // If both l & r are 'low', - temp1 = 0x8000; // turn on the mute bit. + l = 0; + } else + rl = attentbl[(10 * l) / 100]; // Convert 0-100 vol to 63-0 atten. + + r = (val >> 8) & 0xff; + if (r > 100) + r = 100; // Max right volume is 100, too + if (r < 6) { + rr = 63; + r = 0; + } else + rr = attentbl[(10 * r) / 100]; // Convert volume to attenuation. + + if ((rl > 60) && (rr > 60)) // If both l & r are 'low', + temp1 = 0x8000; // turn on the mute bit. else temp1 = 0; - + temp1 |= (rl << 8) | rr; - + cs4281_write_ac97(s, BA0_AC97_MASTER_VOLUME, temp1); cs4281_write_ac97(s, BA0_AC97_HEADPHONE_VOLUME, temp1); #ifdef OSS_DOCUMENTED_MIXER_SEMANTICS - s->mix.vol[8] = ((unsigned int)r << 8) | l; + s->mix.vol[8] = ((unsigned int) r << 8) | l; #else s->mix.vol[8] = val; #endif - return put_user(s->mix.vol[8], (int *)arg); + return put_user(s->mix.vol[8], (int *) arg); case SOUND_MIXER_SPEAKER: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; l = val & 0xff; if (l > 100) l = 100; - if(l < 3 ) { + if (l < 3) { rl = 0; l = 0; - } - else { - rl = (l*2 - 5)/13; // Convert 0-100 range to 0-15. - l = (rl*13 +5)/2; + } else { + rl = (l * 2 - 5) / 13; // Convert 0-100 range to 0-15. + l = (rl * 13 + 5) / 2; } - if (rl < 3){ - temp1 = 0x8000; - rl = 0; - } - else - temp1 = 0; - rl = 15 - rl; // Convert volume to attenuation. + if (rl < 3) { + temp1 = 0x8000; + rl = 0; + } else + temp1 = 0; + rl = 15 - rl; // Convert volume to attenuation. temp1 |= rl << 1; cs4281_write_ac97(s, BA0_AC97_PC_BEEP_VOLUME, temp1); @@ -1313,10 +1835,10 @@ static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd, unsigned long a #else s->mix.vol[6] = val; #endif - return put_user(s->mix.vol[6], (int *)arg); + return put_user(s->mix.vol[6], (int *) arg); case SOUND_MIXER_RECLEV: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; l = val & 0xff; if (l > 100) @@ -1324,25 +1846,25 @@ static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd, unsigned long a r = (val >> 8) & 0xff; if (r > 100) r = 100; - rl = (l*2 - 5) / 13; // Convert 0-100 scale to 0-15. - rr = (r*2 - 5) / 13; - if (rl <3 && rr <3) + rl = (l * 2 - 5) / 13; // Convert 0-100 scale to 0-15. + rr = (r * 2 - 5) / 13; + if (rl < 3 && rr < 3) temp1 = 0x8000; else temp1 = 0; temp1 = temp1 | (rl << 8) | rr; - cs4281_write_ac97(s, BA0_AC97_RECORD_GAIN, temp1); + cs4281_write_ac97(s, BA0_AC97_RECORD_GAIN, temp1); #ifdef OSS_DOCUMENTED_MIXER_SEMANTICS - s->mix.vol[7] = ((unsigned int)r << 8) | l; + s->mix.vol[7] = ((unsigned int) r << 8) | l; #else s->mix.vol[7] = val; #endif - return put_user(s->mix.vol[7], (int *)arg); + return put_user(s->mix.vol[7], (int *) arg); case SOUND_MIXER_MIC: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; l = val & 0xff; if (l > 100) @@ -1350,19 +1872,18 @@ static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd, unsigned long a if (l < 1) { l = 0; rl = 0; - } - else { - rl = ((unsigned)l*5 - 4)/16; // Convert 0-100 range to 0-31. - l = (rl*16 +4)/5; + } else { + rl = ((unsigned) l * 5 - 4) / 16; // Convert 0-100 range to 0-31. + l = (rl * 16 + 4) / 5; } cs4281_read_ac97(s, BA0_AC97_MIC_VOLUME, &temp1); - temp1 &= 0x40; // Isolate 20db gain bit. - if (rl < 3){ - temp1 |= 0x8000; - rl = 0; + temp1 &= 0x40; // Isolate 20db gain bit. + if (rl < 3) { + temp1 |= 0x8000; + rl = 0; } - rl = 31 - rl; // Convert volume to attenuation. - temp1 |= rl; + rl = 31 - rl; // Convert volume to attenuation. + temp1 |= rl; cs4281_write_ac97(s, BA0_AC97_MIC_VOLUME, temp1); #ifdef OSS_DOCUMENTED_MIXER_SEMANTICS @@ -1370,49 +1891,52 @@ static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd, unsigned long a #else s->mix.vol[5] = val; #endif - return put_user(s->mix.vol[5], (int *)arg); - - + return put_user(s->mix.vol[5], (int *) arg); + + case SOUND_MIXER_SYNTH: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; l = val & 0xff; if (l > 100) l = 100; - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; r = (val >> 8) & 0xff; if (r > 100) r = 100; - rl = (l * 2 - 11)/3; // Convert 0-100 range to 0-63. - rr = (r * 2 - 11)/3; - if (rl < 3) // If l is low, turn on - temp1 = 0x0080; // the mute bit. + rl = (l * 2 - 11) / 3; // Convert 0-100 range to 0-63. + rr = (r * 2 - 11) / 3; + if (rl < 3) // If l is low, turn on + temp1 = 0x0080; // the mute bit. else temp1 = 0; - rl = 63 - rl; // Convert vol to attenuation. - writel(temp1|rl, s->pBA0+BA0_FMLVC); - if (rr < 3) // If rr is low, turn on - temp1 = 0x0080; // the mute bit. + rl = 63 - rl; // Convert vol to attenuation. + writel(temp1 | rl, s->pBA0 + BA0_FMLVC); + if (rr < 3) // If rr is low, turn on + temp1 = 0x0080; // the mute bit. else temp1 = 0; - rr = 63 - rr; // Convert vol to attenuation. - writel(temp1 | rr, s->pBA0+BA0_FMRVC); + rr = 63 - rr; // Convert vol to attenuation. + writel(temp1 | rr, s->pBA0 + BA0_FMRVC); #ifdef OSS_DOCUMENTED_MIXER_SEMANTICS s->mix.vol[4] = (r << 8) | l; #else s->mix.vol[4] = val; #endif - return put_user(s->mix.vol[4], (int *)arg); + return put_user(s->mix.vol[4], (int *) arg); + - default: + CS_DBGOUT(CS_IOCTL, 4, printk(KERN_INFO + "cs4281: mixer_ioctl(): default\n")); + i = _IOC_NR(cmd); if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i])) return -EINVAL; - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; l = val & 0xff; if (l > 100) @@ -1420,32 +1944,30 @@ static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd, unsigned long a if (l < 1) { l = 0; rl = 31; - } - else - rl = (attentbl[(l*10)/100])>>1; - + } else + rl = (attentbl[(l * 10) / 100]) >> 1; + r = (val >> 8) & 0xff; if (r > 100) r = 100; if (r < 1) { r = 0; rr = 31; - } - else - rr = (attentbl[(r*10)/100])>>1; + } else + rr = (attentbl[(r * 10) / 100]) >> 1; if ((rl > 30) && (rr > 30)) temp1 = 0x8000; else temp1 = 0; - temp1 = temp1 | (rl << 8) | rr; - cs4281_write_ac97(s, mixreg[vidx-1], temp1); - + temp1 = temp1 | (rl << 8) | rr; + cs4281_write_ac97(s, mixreg[vidx - 1], temp1); + #ifdef OSS_DOCUMENTED_MIXER_SEMANTICS - s->mix.vol[vidx-1] = ((unsigned int)r << 8) | l; + s->mix.vol[vidx - 1] = ((unsigned int) r << 8) | l; #else - s->mix.vol[vidx-1] = val; + s->mix.vol[vidx - 1] = val; #endif - return put_user(s->mix.vol[vidx-1], (int *)arg); + return put_user(s->mix.vol[vidx - 1], (int *) arg); } } @@ -1478,7 +2000,8 @@ static int cs4281_open_mixdev(struct inode *inode, struct file *file) static int cs4281_release_mixdev(struct inode *inode, struct file *file) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; VALIDATE_STATE(s); MOD_DEC_USE_COUNT; @@ -1489,22 +2012,72 @@ static int cs4281_release_mixdev(struct inode *inode, struct file *file) static int cs4281_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - return mixer_ioctl((struct cs4281_state *)file->private_data, cmd, arg); + return mixer_ioctl((struct cs4281_state *) file->private_data, cmd, + arg); } // ****************************************************************************************** // Mixer file operations struct. // ****************************************************************************************** -static /*const*/ struct file_operations cs4281_mixer_fops = { - llseek: cs4281_llseek, - ioctl: cs4281_ioctl_mixdev, - open: cs4281_open_mixdev, - release: cs4281_release_mixdev, +static /*const */ struct file_operations cs4281_mixer_fops = { + llseek:cs4281_llseek, + ioctl:cs4281_ioctl_mixdev, + open:cs4281_open_mixdev, + release:cs4281_release_mixdev, }; // --------------------------------------------------------------------- + +static int drain_adc(struct cs4281_state *s, int nonblock) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long flags; + int count; + unsigned tmo; + + if (s->dma_adc.mapped) + return 0; + current->state = TASK_INTERRUPTIBLE; + add_wait_queue(&s->dma_adc.wait, &wait); + for (;;) { + spin_lock_irqsave(&s->lock, flags); + count = s->dma_adc.count; + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: drain_adc() %d\n", + count)); + spin_unlock_irqrestore(&s->lock, flags); + if (count <= 0) { + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO + "cs4281: drain_adc() count<0\n")); + break; + } + if (signal_pending(current)) + break; + if (nonblock) { + remove_wait_queue(&s->dma_adc.wait, &wait); + current->state = TASK_RUNNING; + return -EBUSY; + } + tmo = + 3 * HZ * (count + + s->dma_adc.fragsize) / 2 / s->prop_adc.rate; + if (s->prop_adc.fmt & (AFMT_S16_LE | AFMT_U16_LE)) + tmo >>= 1; + if (s->prop_adc.channels > 1) + tmo >>= 1; + if (!schedule_timeout(tmo + 1)) + printk(KERN_DEBUG "cs4281: dma timed out??\n"); + } + remove_wait_queue(&s->dma_adc.wait, &wait); + current->state = TASK_RUNNING; + if (signal_pending(current)) + return -ERESTARTSYS; + return 0; +} + static int drain_dac(struct cs4281_state *s, int nonblock) { DECLARE_WAITQUEUE(wait, current); @@ -1529,10 +2102,12 @@ static int drain_dac(struct cs4281_state *s, int nonblock) current->state = TASK_RUNNING; return -EBUSY; } - tmo = 3 * HZ * (count + s->dma_dac.fragsize) / 2 / s->rate; - if (s->fmt & (AFMT_S16_LE | AFMT_U16_LE)) + tmo = + 3 * HZ * (count + + s->dma_dac.fragsize) / 2 / s->prop_dac.rate; + if (s->prop_dac.fmt & (AFMT_S16_LE | AFMT_U16_LE)) tmo >>= 1; - if (s->channels > 1) + if (s->prop_dac.channels > 1) tmo >>= 1; if (!schedule_timeout(tmo + 1)) printk(KERN_DEBUG "cs4281: dma timed out??\n"); @@ -1544,19 +2119,189 @@ static int drain_dac(struct cs4281_state *s, int nonblock) return 0; } +//**************************************************************************** +// +// CopySamples copies 16-bit stereo samples from the source to the +// destination, possibly converting down to either 8-bit or mono or both. +// count specifies the number of output bytes to write. +// +// Arguments: +// +// dst - Pointer to a destination buffer. +// src - Pointer to a source buffer +// count - The number of bytes to copy into the destination buffer. +// iChannels - Stereo - 2 +// Mono - 1 +// fmt - AFMT_xxx (soundcard.h formats) +// +// NOTES: only call this routine for conversion to 8bit from 16bit +// +//**************************************************************************** +static void CopySamples(char *dst, char *src, int count, int iChannels, + unsigned fmt) +{ + + unsigned short *psSrc; + long lAudioSample; + + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: CopySamples()+ ")); + CS_DBGOUT(CS_WAVE_READ, 8, + printk(KERN_INFO + " dst=0x%x src=0x%x count=%d iChannels=%d fmt=0x%x\n", + (unsigned) dst, (unsigned) src, (unsigned) count, + (unsigned) iChannels, (unsigned) fmt)); + + // Gershwin does format conversion in hardware so normally + // we don't do any host based coversion. The data formatter + // truncates 16 bit data to 8 bit and that causes some hiss. + // We have already forced the HW to do 16 bit sampling and + // 2 channel so that we can use software to round instead + // of truncate + + // + // See if the data should be output as 8-bit unsigned stereo. + // + if ((iChannels == 2) && (fmt & AFMT_U8)) { + // + // Convert each 16-bit unsigned stereo sample to 8-bit unsigned + // stereo using rounding. + // + psSrc = (unsigned short *) src; + count = count / 2; + while (count--) { + lAudioSample = (long) psSrc[count] + (long) 0x80; + if (lAudioSample > 0xffff) { + lAudioSample = 0xffff; + } + dst[count] = (char) (lAudioSample >> 8); + } + } + // + // check for 8-bit signed stereo. + // + else if ((iChannels == 2) && (fmt & AFMT_S8)) { + // + // Convert each 16-bit stereo sample to 8-bit stereo using rounding. + // + psSrc = (short *) src; + while (count--) { + lAudioSample = + (((long) psSrc[0] + (long) psSrc[1]) / 2); + psSrc += 2; + *dst++ = (char) ((short) lAudioSample >> 8); + } + } + // + // See if the data should be output at 8-bit unsigned mono. + // + else if ((iChannels == 1) && (fmt & AFMT_U8)) { + // + // Convert each 16-bit unsigned mono sample to 8-bit unsigned + // mono using rounding. + // + + psSrc = (short *) src; + while (count--) { + lAudioSample = (long) *psSrc++ + (long) 0x80; + if (lAudioSample > 0x7fff) { + lAudioSample = 0x7fff; + } + // + // Convert Signed to Unsigned. + // + + *dst++ = + (unsigned + char) (((short) lAudioSample + + (short) 0x8000) >> 8); + } + } + // + // Otherwise, the data should be output as 8-bit signed mono. + // + else if ((iChannels == 1) && (fmt & AFMT_S8)) { + // + // Convert each 16-bit signed mono sample to 8-bit signed mono + // using rounding. + // + psSrc = (short *) src; + while (count--) { + lAudioSample = + (((long) psSrc[0] + (long) psSrc[1]) / 2); + if (lAudioSample > 0x7fff) { + lAudioSample = 0x7fff; + } + psSrc += 2; + *dst++ = (char) ((short) lAudioSample >> 8); + } + } +} + +// +// cs_copy_to_user() +// replacement for the standard copy_to_user, to allow for a conversion from +// 16 bit to 8 bit if the record conversion is active. the cs4281 has some +// issues with 8 bit capture, so the driver always captures data in 16 bit +// and then if the user requested 8 bit, converts from 16 to 8 bit. +// +static unsigned cs_copy_to_user(struct cs4281_state *s, void *dest, + unsigned *hwsrc, unsigned cnt, + unsigned *copied) +{ + void *src = hwsrc; //default to the standard destination buffer addr + + CS_DBGOUT(CS_FUNCTION, 6, printk(KERN_INFO + "cs_copy_to_user()+ fmt=0x%x fmt_o=0x%x cnt=%d dest=0x%.8x\n", + s->prop_adc.fmt, + s->prop_adc.fmt_original, + (unsigned) cnt, (unsigned) dest)); + + if (cnt > s->dma_adc.dmasize) { + cnt = s->dma_adc.dmasize; + } + if (!cnt) { + *copied = 0; + return 0; + } + if (s->conversion) { + if (!s->tmpbuff) { + *copied = cnt / 2; + return 0; + } + CopySamples(s->tmpbuff, (void *) hwsrc, cnt, + (unsigned) s->prop_adc.channels, + s->prop_adc.fmt_original); + src = s->tmpbuff; + cnt = cnt / 2; + } + + if (copy_to_user(dest, src, cnt)) { + *copied = 0; + return -EFAULT; + } + *copied = cnt; + CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO + "cs4281: cs_copy_to_user()- copied bytes is %d \n", + cnt)); + return 0; +} // --------------------------------------------------------------------- -static ssize_t cs4281_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +static ssize_t cs4281_read(struct file *file, char *buffer, size_t count, + loff_t * ppos) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; ssize_t ret; unsigned long flags; unsigned swptr; int cnt; + unsigned copied = 0; - CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2, - printk(KERN_INFO "cs4281: cs4281_read()+ \n") ); + CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2, + printk(KERN_INFO "cs4281: cs4281_read()+ %d \n", count)); VALIDATE_STATE(s); if (ppos != &file->f_pos) @@ -1568,52 +2313,115 @@ static ssize_t cs4281_read(struct file *file, char *buffer, size_t count, loff_t if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; ret = 0; +// +// "count" is the amount of bytes to read (from app), is decremented each loop +// by the amount of bytes that have been returned to the user buffer. +// "cnt" is the running total of each read from the buffer (changes each loop) +// "buffer" points to the app's buffer +// "ret" keeps a running total of the amount of bytes that have been copied +// to the user buffer. +// "copied" is the total bytes copied into the user buffer for each loop. +// while (count > 0) { + CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO + "_read() count>0 count=%d .count=%d .swptr=%d .hwptr=%d \n", + count, s->dma_adc.count, + s->dma_adc.swptr, + s->dma_adc.hwptr)); spin_lock_irqsave(&s->lock, flags); + + // get the current copy point of the sw buffer swptr = s->dma_adc.swptr; - cnt = s->dma_adc.dmasize-swptr; + + // cnt is the amount of unread bytes from the end of the + // hw buffer to the current sw pointer + cnt = s->dma_adc.dmasize - swptr; + + // dma_adc.count is the current total bytes that have not been read. + // if the amount of unread bytes from the current sw pointer to the + // end of the buffer is greater than the current total bytes that + // have not been read, then set the "cnt" (unread bytes) to the + // amount of unread bytes. + if (s->dma_adc.count < cnt) cnt = s->dma_adc.count; spin_unlock_irqrestore(&s->lock, flags); - if (cnt > count) - cnt = count; + // + // if we are converting from 8/16 then we need to copy + // twice the number of 16 bit bytes then 8 bit bytes. + // + if (s->conversion) { + if (cnt > (count * 2)) + cnt = (count * 2); + } else { + if (cnt > count) + cnt = count; + } + // + // "cnt" NOW is the smaller of the amount that will be read, + // and the amount that is requested in this read (or partial). + // if there are no bytes in the buffer to read, then start the + // ADC and wait for the interrupt handler to wake us up. + // if (cnt <= 0) { + + // start up the dma engine and then continue back to the top of + // the loop when wake up occurs. start_adc(s); - if (file->f_flags & O_NONBLOCK) + if (file->f_flags & O_NONBLOCK) return ret ? ret : -EAGAIN; interruptible_sleep_on(&s->dma_adc.wait); if (signal_pending(current)) return ret ? ret : -ERESTARTSYS; continue; } - if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) + // there are bytes in the buffer to read. + // copy from the hw buffer over to the user buffer. + // user buffer is designated by "buffer" + // virtual address to copy from is rawbuf+swptr + // the "cnt" is the number of bytes to read. + + CS_DBGOUT(CS_WAVE_READ, 2, printk(KERN_INFO + "_read() copy_to cnt=%d count=%d ", + cnt, count)); + CS_DBGOUT(CS_WAVE_READ, 8, + printk(KERN_INFO + " .dmasize=%d .count=%d buffer=0x%.8x ret=%d\n", + s->dma_adc.dmasize, s->dma_adc.count, + (unsigned) buffer, ret)); + + if (cs_copy_to_user + (s, buffer, s->dma_adc.rawbuf + swptr, cnt, &copied)) return ret ? ret : -EFAULT; swptr = (swptr + cnt) % s->dma_adc.dmasize; spin_lock_irqsave(&s->lock, flags); s->dma_adc.swptr = swptr; s->dma_adc.count -= cnt; spin_unlock_irqrestore(&s->lock, flags); - count -= cnt; - buffer += cnt; - ret += cnt; + count -= copied; + buffer += copied; + ret += copied; start_adc(s); } - CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2, - printk(KERN_INFO "cs4281: cs4281_read()- %d\n",ret) ); + CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2, + printk(KERN_INFO "cs4281: cs4281_read()- %d\n", ret)); return ret; } -static ssize_t cs4281_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) +static ssize_t cs4281_write(struct file *file, const char *buffer, + size_t count, loff_t * ppos) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; ssize_t ret; unsigned long flags; unsigned swptr; int cnt; - CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2, - printk(KERN_INFO "cs4281: cs4281_write()+ \n") ); + CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2, + printk(KERN_INFO "cs4281: cs4281_write()+ count=%d\n", + count)); VALIDATE_STATE(s); if (ppos != &file->f_pos) @@ -1632,13 +2440,14 @@ static ssize_t cs4281_write(struct file *file, const char *buffer, size_t count, s->dma_dac.swptr = s->dma_dac.hwptr; } swptr = s->dma_dac.swptr; - cnt = s->dma_dac.dmasize-swptr; + cnt = s->dma_dac.dmasize - swptr; if (s->dma_dac.count + cnt > s->dma_dac.dmasize) cnt = s->dma_dac.dmasize - s->dma_dac.count; spin_unlock_irqrestore(&s->lock, flags); if (cnt > count) cnt = count; if (cnt <= 0) { + start_dac(s); if (file->f_flags & O_NONBLOCK) return ret ? ret : -EAGAIN; @@ -1660,61 +2469,79 @@ static ssize_t cs4281_write(struct file *file, const char *buffer, size_t count, ret += cnt; start_dac(s); } - CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2, - printk(KERN_INFO "cs4281: cs4281_write()- %d\n",ret) ); + CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2, + printk(KERN_INFO "cs4281: cs4281_write()- %d\n", ret)); return ret; } -static unsigned int cs4281_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int cs4281_poll(struct file *file, + struct poll_table_struct *wait) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; unsigned long flags; unsigned int mask = 0; - CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4, - printk(KERN_INFO "cs4281: cs4281_poll()+\n") ); + CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4, + printk(KERN_INFO "cs4281: cs4281_poll()+\n")); VALIDATE_STATE(s); - if (file->f_mode & FMODE_WRITE) + if (file->f_mode & FMODE_WRITE) { + CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4, + printk(KERN_INFO + "cs4281: cs4281_poll() wait on FMODE_WRITE\n")); poll_wait(file, &s->dma_dac.wait, wait); - if (file->f_mode & FMODE_READ) + } + if (file->f_mode & FMODE_READ) { + CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4, + printk(KERN_INFO + "cs4281: cs4281_poll() wait on FMODE_READ\n")); poll_wait(file, &s->dma_adc.wait, wait); + } spin_lock_irqsave(&s->lock, flags); cs4281_update_ptr(s); - if (file->f_mode & FMODE_READ) { - if (s->dma_adc.mapped) { - if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) - mask |= POLLIN | POLLRDNORM; - } else { - if (s->dma_adc.count > 0) - mask |= POLLIN | POLLRDNORM; - } - } if (file->f_mode & FMODE_WRITE) { if (s->dma_dac.mapped) { - if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) - mask |= POLLOUT | POLLWRNORM; + if (s->dma_dac.count >= + (signed) s->dma_dac.fragsize) { + if (s->dma_dac.wakeup) + mask |= POLLOUT | POLLWRNORM; + else + mask = 0; + s->dma_dac.wakeup = 0; + } } else { - if ((signed)s->dma_dac.dmasize > s->dma_dac.count) + if ((signed) s->dma_dac.dmasize > s->dma_dac.count) mask |= POLLOUT | POLLWRNORM; } + } else if (file->f_mode & FMODE_READ) { + if (s->dma_adc.mapped) { + if (s->dma_adc.count >= + (signed) s->dma_adc.fragsize) mask |= + POLLIN | POLLRDNORM; + } else { + if (s->dma_adc.count > 0) + mask |= POLLIN | POLLRDNORM; + } } spin_unlock_irqrestore(&s->lock, flags); - CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4, - printk(KERN_INFO "cs4281: cs4281_poll()- 0x%.8x\n",mask) ); + CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4, + printk(KERN_INFO "cs4281: cs4281_poll()- 0x%.8x\n", + mask)); return mask; } static int cs4281_mmap(struct file *file, struct vm_area_struct *vma) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; struct dmabuf *db; int ret; unsigned long size; - CS_DBGOUT(CS_FUNCTION | CS_PARMS | CS_OPEN, 4, - printk(KERN_INFO "cs4281: cs4281_mmap()+\n") ); + CS_DBGOUT(CS_FUNCTION | CS_PARMS | CS_OPEN, 4, + printk(KERN_INFO "cs4281: cs4281_mmap()+\n")); VALIDATE_STATE(s); if (vma->vm_flags & VM_WRITE) { @@ -1727,131 +2554,253 @@ static int cs4281_mmap(struct file *file, struct vm_area_struct *vma) db = &s->dma_adc; } else return -EINVAL; +// +// only support PLAYBACK for now +// + db = &s->dma_dac; + if (vma->vm_pgoff != 0) return -EINVAL; size = vma->vm_end - vma->vm_start; if (size > (PAGE_SIZE << db->buforder)) return -EINVAL; - if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot)) - return -EAGAIN; + if (remap_page_range + (vma->vm_start, virt_to_phys(db->rawbuf), size, + vma->vm_page_prot)) return -EAGAIN; db->mapped = 1; - CS_DBGOUT(CS_FUNCTION | CS_PARMS | CS_OPEN, 4, - printk(KERN_INFO "cs4281: cs4281_mmap()- 0 size=%d\n", - (unsigned)size) ); + CS_DBGOUT(CS_FUNCTION | CS_PARMS | CS_OPEN, 4, + printk(KERN_INFO "cs4281: cs4281_mmap()- 0 size=%d\n", + (unsigned) size)); return 0; } -static int cs4281_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static int cs4281_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; unsigned long flags; audio_buf_info abinfo; count_info cinfo; int val, mapped, ret; - - CS_DBGOUT(CS_FUNCTION, 4, - printk(KERN_INFO "cs4281: cs4281_ioctl(): file=0x%.8x cmd=0x%.8x\n", - (unsigned)file,cmd) ); + + CS_DBGOUT(CS_FUNCTION, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): file=0x%.8x cmd=0x%.8x\n", + (unsigned) file, cmd)); +#if CSDEBUG + printioctl(cmd); +#endif VALIDATE_STATE(s); mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) || - ((file->f_mode & FMODE_READ) && s->dma_adc.mapped); + ((file->f_mode & FMODE_READ) && s->dma_adc.mapped); switch (cmd) { case OSS_GETVERSION: - CS_DBGOUT(CS_FUNCTION | CS_PARMS, 4, printk(KERN_INFO - "cs4281: cs4281_ioctl(): SOUND_VERSION=0x%.8x\n", SOUND_VERSION) ); - return put_user(SOUND_VERSION, (int *)arg); + CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(KERN_INFO + "cs4281: cs4281_ioctl(): SOUND_VERSION=0x%.8x\n", + SOUND_VERSION)); + return put_user(SOUND_VERSION, (int *) arg); case SNDCTL_DSP_SYNC: + CS_DBGOUT(CS_IOCTL, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): DSP_SYNC\n")); if (file->f_mode & FMODE_WRITE) - return drain_dac(s, 0/*file->f_flags & O_NONBLOCK*/); + return drain_dac(s, + 0 /*file->f_flags & O_NONBLOCK */ + ); return 0; case SNDCTL_DSP_SETDUPLEX: return 0; case SNDCTL_DSP_GETCAPS: - return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg); + return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | + DSP_CAP_TRIGGER | DSP_CAP_MMAP, + (int *) arg); case SNDCTL_DSP_RESET: + CS_DBGOUT(CS_IOCTL, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): DSP_RESET\n")); if (file->f_mode & FMODE_WRITE) { stop_dac(s); synchronize_irq(); - s->dma_dac.swptr = s->dma_dac.hwptr = s->dma_dac.count = - s->dma_dac.total_bytes = s->dma_dac.blocks = 0; + s->dma_dac.swptr = s->dma_dac.hwptr = + s->dma_dac.count = s->dma_dac.total_bytes = + s->dma_dac.blocks = s->dma_dac.wakeup = 0; + prog_codec(s, CS_TYPE_DAC); } if (file->f_mode & FMODE_READ) { stop_adc(s); synchronize_irq(); - s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = - s->dma_adc.total_bytes = s->dma_adc.blocks = 0; + s->dma_adc.swptr = s->dma_adc.hwptr = + s->dma_adc.count = s->dma_adc.total_bytes = + s->dma_adc.blocks = s->dma_dac.wakeup = 0; + prog_codec(s, CS_TYPE_ADC); } - prog_codec(s); return 0; case SNDCTL_DSP_SPEED: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; - if (val >= 0) { - stop_adc(s); - stop_dac(s); - s->dma_adc.ready = s->dma_dac.ready = 0; - // program sampling rates - if (val > 48000) - val = 48000; - if (val < 6300) - val = 6300; - s->rate = val; - prog_codec(s); + CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): DSP_SPEED val=%d\n", + val)); + // + // support independent capture and playback channels + // assume that the file mode bit determines the + // direction of the data flow. + // + if (file->f_mode & FMODE_READ) { + if (val >= 0) { + stop_adc(s); + s->dma_adc.ready = 0; + // program sampling rates + if (val > 48000) + val = 48000; + if (val < 6300) + val = 6300; + s->prop_adc.rate = val; + prog_codec(s, CS_TYPE_ADC); + } + } + if (file->f_mode & FMODE_WRITE) { + if (val >= 0) { + stop_dac(s); + s->dma_dac.ready = 0; + // program sampling rates + if (val > 48000) + val = 48000; + if (val < 6300) + val = 6300; + s->prop_dac.rate = val; + prog_codec(s, CS_TYPE_DAC); + } } - return put_user(s->rate, (int *)arg); + + if (file->f_mode & FMODE_WRITE) + val = s->prop_dac.rate; + else if (file->f_mode & FMODE_READ) + val = s->prop_adc.rate; + + return put_user(val, (int *) arg); case SNDCTL_DSP_STEREO: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; - stop_adc(s); - stop_dac(s); - s->dma_adc.ready = s->dma_dac.ready = 0; - // program channels - s->channels = val ? 2 : 1; - prog_codec(s); + CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): DSP_STEREO val=%d\n", + val)); + if (file->f_mode & FMODE_READ) { + stop_adc(s); + s->dma_adc.ready = 0; + s->prop_adc.channels = val ? 2 : 1; + prog_codec(s, CS_TYPE_ADC); + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + s->dma_dac.ready = 0; + s->prop_dac.channels = val ? 2 : 1; + prog_codec(s, CS_TYPE_DAC); + } return 0; case SNDCTL_DSP_CHANNELS: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; + CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): DSP_CHANNELS val=%d\n", + val)); if (val != 0) { - stop_adc(s); - stop_dac(s); - s->dma_adc.ready = s->dma_dac.ready = 0; - // program channels - s->channels = val ? 2 : 1; - prog_codec(s); + if (file->f_mode & FMODE_READ) { + stop_adc(s); + s->dma_adc.ready = 0; + if (val >= 2) + s->prop_adc.channels = 2; + else + s->prop_adc.channels = 1; + prog_codec(s, CS_TYPE_ADC); + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + s->dma_dac.ready = 0; + if (val >= 2) + s->prop_dac.channels = 2; + else + s->prop_dac.channels = 1; + prog_codec(s, CS_TYPE_DAC); + } } - return put_user(s->channels, (int *)arg); - case SNDCTL_DSP_GETFMTS: // Returns a mask - return put_user(AFMT_S16_LE|AFMT_U16_LE|AFMT_S8|AFMT_U8, (int *)arg); - - case SNDCTL_DSP_SETFMT: // Selects ONE fmt - if (get_user(val, (int *)arg)) + if (file->f_mode & FMODE_WRITE) + val = s->prop_dac.channels; + else if (file->f_mode & FMODE_READ) + val = s->prop_adc.channels; + + return put_user(val, (int *) arg); + + case SNDCTL_DSP_GETFMTS: // Returns a mask + CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): DSP_GETFMT val=0x%.8x\n", + AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 | + AFMT_U8)); + return put_user(AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 | + AFMT_U8, (int *) arg); + + case SNDCTL_DSP_SETFMT: + if (get_user(val, (int *) arg)) return -EFAULT; + CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): DSP_SETFMT val=0x%.8x\n", + val)); if (val != AFMT_QUERY) { - stop_adc(s); - stop_dac(s); - s->dma_adc.ready = s->dma_dac.ready = 0; - // program format - if (val != AFMT_S16_LE && val != AFMT_U16_LE && - val != AFMT_S8 && val != AFMT_U8) - val = AFMT_U8; - s->fmt = val; - prog_codec(s); + if (file->f_mode & FMODE_READ) { + stop_adc(s); + s->dma_adc.ready = 0; + if (val != AFMT_S16_LE + && val != AFMT_U16_LE && val != AFMT_S8 + && val != AFMT_U8) + val = AFMT_U8; + s->prop_adc.fmt = val; + s->prop_adc.fmt_original = s->prop_adc.fmt; + prog_codec(s, CS_TYPE_ADC); + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + s->dma_dac.ready = 0; + if (val != AFMT_S16_LE + && val != AFMT_U16_LE && val != AFMT_S8 + && val != AFMT_U8) + val = AFMT_U8; + s->prop_dac.fmt = val; + s->prop_dac.fmt_original = s->prop_dac.fmt; + prog_codec(s, CS_TYPE_DAC); + } + } else { + if (file->f_mode & FMODE_WRITE) + val = s->prop_dac.fmt_original; + else if (file->f_mode & FMODE_READ) + val = s->prop_adc.fmt_original; } - return put_user(s->fmt, (int *)arg); + CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): DSP_SETFMT return val=0x%.8x\n", + val)); + return put_user(val, (int *) arg); case SNDCTL_DSP_POST: + CS_DBGOUT(CS_IOCTL, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): DSP_POST\n")); return 0; case SNDCTL_DSP_GETTRIGGER: @@ -1860,14 +2809,15 @@ static int cs4281_ioctl(struct inode *inode, struct file *file, unsigned int cmd val |= PCM_ENABLE_INPUT; if (file->f_mode & s->ena & FMODE_WRITE) val |= PCM_ENABLE_OUTPUT; - return put_user(val, (int *)arg); + return put_user(val, (int *) arg); case SNDCTL_DSP_SETTRIGGER: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; if (file->f_mode & FMODE_READ) { if (val & PCM_ENABLE_INPUT) { - if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s))) + if (!s->dma_adc.ready + && (ret = prog_dmabuf_adc(s))) return ret; start_adc(s); } else @@ -1875,7 +2825,8 @@ static int cs4281_ioctl(struct inode *inode, struct file *file, unsigned int cmd } if (file->f_mode & FMODE_WRITE) { if (val & PCM_ENABLE_OUTPUT) { - if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s))) + if (!s->dma_dac.ready + && (ret = prog_dmabuf_dac(s))) return ret; start_dac(s); } else @@ -1886,30 +2837,55 @@ static int cs4281_ioctl(struct inode *inode, struct file *file, unsigned int cmd case SNDCTL_DSP_GETOSPACE: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; - if (!(s->ena & FMODE_WRITE) && (val = prog_dmabuf_dac(s)) != 0) + if (!(s->ena & FMODE_WRITE) + && (val = prog_dmabuf_dac(s)) != 0) return val; spin_lock_irqsave(&s->lock, flags); cs4281_update_ptr(s); abinfo.fragsize = s->dma_dac.fragsize; - abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count; + if (s->dma_dac.mapped) + abinfo.bytes = s->dma_dac.dmasize; + else + abinfo.bytes = + s->dma_dac.dmasize - s->dma_dac.count; abinfo.fragstotal = s->dma_dac.numfrag; - abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift; + abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift; + CS_DBGOUT(CS_FUNCTION | CS_PARMS, 4, printk(KERN_INFO + "cs4281: cs4281_ioctl(): GETOSPACE .fragsize=%d .bytes=%d .fragstotal=%d .fragments=%d\n", + abinfo. + fragsize, + abinfo.bytes, + abinfo. + fragstotal, + abinfo. + fragments)); spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; + return copy_to_user((void *) arg, &abinfo, + sizeof(abinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETISPACE: if (!(file->f_mode & FMODE_READ)) return -EINVAL; - if (!(s->ena & FMODE_READ) && (val = prog_dmabuf_adc(s)) != 0) - return val; + if (!(s->ena & FMODE_READ) + && (val = prog_dmabuf_adc(s)) != 0) return val; spin_lock_irqsave(&s->lock, flags); cs4281_update_ptr(s); - abinfo.fragsize = s->dma_adc.fragsize; - abinfo.bytes = s->dma_adc.count; - abinfo.fragstotal = s->dma_adc.numfrag; - abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift; + if (s->conversion) { + abinfo.fragsize = s->dma_adc.fragsize / 2; + abinfo.bytes = s->dma_adc.count / 2; + abinfo.fragstotal = s->dma_adc.numfrag; + abinfo.fragments = + abinfo.bytes >> (s->dma_adc.fragshift - 1); + } else { + abinfo.fragsize = s->dma_adc.fragsize; + abinfo.bytes = s->dma_adc.count; + abinfo.fragstotal = s->dma_adc.numfrag; + abinfo.fragments = + abinfo.bytes >> s->dma_adc.fragshift; + } spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; + return copy_to_user((void *) arg, &abinfo, + sizeof(abinfo)) ? -EFAULT : 0; case SNDCTL_DSP_NONBLOCK: file->f_flags |= O_NONBLOCK; @@ -1922,7 +2898,7 @@ static int cs4281_ioctl(struct inode *inode, struct file *file, unsigned int cmd cs4281_update_ptr(s); val = s->dma_dac.count; spin_unlock_irqrestore(&s->lock, flags); - return put_user(val, (int *)arg); + return put_user(val, (int *) arg); case SNDCTL_DSP_GETIPTR: if (!(file->f_mode & FMODE_READ)) @@ -1930,12 +2906,30 @@ static int cs4281_ioctl(struct inode *inode, struct file *file, unsigned int cmd spin_lock_irqsave(&s->lock, flags); cs4281_update_ptr(s); cinfo.bytes = s->dma_adc.total_bytes; - cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift; - cinfo.ptr = s->dma_adc.hwptr; + if (s->dma_adc.mapped) { + cinfo.blocks = + (cinfo.bytes >> s->dma_adc.fragshift) - + s->dma_adc.blocks; + s->dma_adc.blocks = + cinfo.bytes >> s->dma_adc.fragshift; + } else { + if (s->conversion) { + cinfo.blocks = + s->dma_adc.count / + 2 >> (s->dma_adc.fragshift - 1); + } else + cinfo.blocks = + s->dma_adc.count >> s->dma_adc. + fragshift; + } + if (s->conversion) + cinfo.ptr = s->dma_adc.hwptr / 2; + else + cinfo.ptr = s->dma_adc.hwptr; if (s->dma_adc.mapped) - s->dma_adc.count &= s->dma_adc.fragsize-1; + s->dma_adc.count &= s->dma_adc.fragsize - 1; spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); case SNDCTL_DSP_GETOPTR: if (!(file->f_mode & FMODE_WRITE)) @@ -1943,65 +2937,107 @@ static int cs4281_ioctl(struct inode *inode, struct file *file, unsigned int cmd spin_lock_irqsave(&s->lock, flags); cs4281_update_ptr(s); cinfo.bytes = s->dma_dac.total_bytes; - if (s->dma_dac.mapped) - { - cinfo.blocks = (cinfo.bytes >> s->dma_dac.fragshift) - - s->dma_adc.blocks; - s->dma_dac.blocks = cinfo.bytes >> s->dma_dac.fragshift; - } - else - { - cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift; + if (s->dma_dac.mapped) { + cinfo.blocks = + (cinfo.bytes >> s->dma_dac.fragshift) - + s->dma_dac.blocks; + s->dma_dac.blocks = + cinfo.bytes >> s->dma_dac.fragshift; + } else { + cinfo.blocks = + s->dma_dac.count >> s->dma_dac.fragshift; } cinfo.ptr = s->dma_dac.hwptr; if (s->dma_dac.mapped) - s->dma_dac.count &= s->dma_dac.fragsize-1; + s->dma_dac.count &= s->dma_dac.fragsize - 1; spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); case SNDCTL_DSP_GETBLKSIZE: if (file->f_mode & FMODE_WRITE) { if ((val = prog_dmabuf_dac(s))) return val; - return put_user(s->dma_dac.fragsize, (int *)arg); + return put_user(s->dma_dac.fragsize, (int *) arg); } if ((val = prog_dmabuf_adc(s))) return val; - return put_user(s->dma_adc.fragsize, (int *)arg); + if (s->conversion) + return put_user(s->dma_adc.fragsize / 2, + (int *) arg); + else + return put_user(s->dma_adc.fragsize, (int *) arg); case SNDCTL_DSP_SETFRAGMENT: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; - return 0; // Say OK, but do nothing. + return 0; // Say OK, but do nothing. case SNDCTL_DSP_SUBDIVIDE: - if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || - (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision)) - return -EINVAL; - if (get_user(val, (int *)arg)) + if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) + || (file->f_mode & FMODE_WRITE + && s->dma_dac.subdivision)) return -EINVAL; + if (get_user(val, (int *) arg)) return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; if (file->f_mode & FMODE_READ) s->dma_adc.subdivision = val; - if (file->f_mode & FMODE_WRITE) + else if (file->f_mode & FMODE_WRITE) s->dma_dac.subdivision = val; return 0; case SOUND_PCM_READ_RATE: - return put_user(s->rate, (int *)arg); + if (file->f_mode & FMODE_READ) + return put_user(s->prop_adc.rate, (int *) arg); + else if (file->f_mode & FMODE_WRITE) + return put_user(s->prop_dac.rate, (int *) arg); case SOUND_PCM_READ_CHANNELS: - return put_user(s->channels, (int *)arg); + if (file->f_mode & FMODE_READ) + return put_user(s->prop_adc.channels, (int *) arg); + else if (file->f_mode & FMODE_WRITE) + return put_user(s->prop_dac.channels, (int *) arg); case SOUND_PCM_READ_BITS: - return put_user((s->fmt & (AFMT_S8|AFMT_U8)) ? 8 : 16, (int *)arg); + if (file->f_mode & FMODE_READ) + return + put_user( + (s->prop_adc. + fmt & (AFMT_S8 | AFMT_U8)) ? 8 : 16, + (int *) arg); + else if (file->f_mode & FMODE_WRITE) + return + put_user( + (s->prop_dac. + fmt & (AFMT_S8 | AFMT_U8)) ? 8 : 16, + (int *) arg); case SOUND_PCM_WRITE_FILTER: case SNDCTL_DSP_SETSYNCRO: case SOUND_PCM_READ_FILTER: return -EINVAL; +#if CSDEBUG_INTERFACE + + case SNDCTL_DSP_CS_GETDBGMASK: + return put_user(cs_debugmask, (unsigned long *) arg); + + case SNDCTL_DSP_CS_GETDBGLEVEL: + return put_user(cs_debuglevel, (unsigned long *) arg); + + case SNDCTL_DSP_CS_SETDBGMASK: + if (get_user(val, (unsigned long *) arg)) + return -EFAULT; + cs_debugmask = val; + return 0; + + case SNDCTL_DSP_CS_SETDBGLEVEL: + if (get_user(val, (unsigned long *) arg)) + return -EFAULT; + cs_debuglevel = val; + return 0; +#endif + } return mixer_ioctl(s, cmd, arg); } @@ -2009,29 +3045,36 @@ static int cs4281_ioctl(struct inode *inode, struct file *file, unsigned int cmd static int cs4281_release(struct inode *inode, struct file *file) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; - CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, - printk(KERN_INFO "cs4281: cs4281_release(): inode=0x%.8x file=0x%.8x\n", - (unsigned)inode,(unsigned)file) ); + CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 2, + printk(KERN_INFO + "cs4281: cs4281_release(): inode=0x%.8x file=0x%.8x f_mode=%d\n", + (unsigned) inode, (unsigned) file, file->f_mode)); VALIDATE_STATE(s); - if (file->f_mode & FMODE_WRITE) - drain_dac(s, file->f_flags & O_NONBLOCK); - down(&s->open_sem); if (file->f_mode & FMODE_WRITE) { + drain_dac(s, file->f_flags & O_NONBLOCK); + down(&s->open_sem_dac); stop_dac(s); - dealloc_dmabuf(s,&s->dma_dac); + dealloc_dmabuf(s, &s->dma_dac); + s->open_mode &= ~FMODE_WRITE; + up(&s->open_sem_dac); + wake_up(&s->open_wait_dac); + MOD_DEC_USE_COUNT; } if (file->f_mode & FMODE_READ) { + drain_adc(s, file->f_flags & O_NONBLOCK); + down(&s->open_sem_adc); stop_adc(s); - dealloc_dmabuf(s,&s->dma_adc); + dealloc_dmabuf(s, &s->dma_adc); + s->open_mode &= ~FMODE_READ; + up(&s->open_sem_adc); + wake_up(&s->open_wait_adc); + MOD_DEC_USE_COUNT; } - s->open_mode &= ~(FMODE_READ | FMODE_WRITE); - up(&s->open_sem); - wake_up(&s->open_wait); - MOD_DEC_USE_COUNT; return 0; } @@ -2040,54 +3083,102 @@ static int cs4281_open(struct inode *inode, struct file *file) int minor = MINOR(inode->i_rdev); struct cs4281_state *s = devs; - CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, - printk(KERN_INFO "cs4281: cs4281_open(): inode=0x%.8x file=0x%.8x\n", - (unsigned)inode,(unsigned)file) ); + CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, + printk(KERN_INFO + "cs4281: cs4281_open(): inode=0x%.8x file=0x%.8x f_mode=0x%x\n", + (unsigned) inode, (unsigned) file, file->f_mode)); while (s && ((s->dev_audio ^ minor) & ~0xf)) s = s->next; - if (!s) - { - CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO - "cs4281: cs4281_open(): ERROR unable to find audio state struct\n") ); + if (!s) { + CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO + "cs4281: cs4281_open(): Error - unable to find audio state struct\n")); return -ENODEV; } VALIDATE_STATE(s); file->private_data = s; - - // wait for device to become free - down(&s->open_sem); - while (s->open_mode & (FMODE_READ | FMODE_WRITE)) { - if (file->f_flags & O_NONBLOCK) { - up(&s->open_sem); - return -EBUSY; + + // wait for device to become free + if (!(file->f_mode & (FMODE_WRITE | FMODE_READ))) { + CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2, + printk(KERN_INFO + "cs4281: cs4281_open(): Error - must open READ and/or WRITE\n")); + return -ENODEV; + } + if (file->f_mode & FMODE_WRITE) { + down(&s->open_sem_dac); + while (s->open_mode & FMODE_WRITE) { + if (file->f_flags & O_NONBLOCK) { + up(&s->open_sem_dac); + return -EBUSY; + } + up(&s->open_sem_dac); + interruptible_sleep_on(&s->open_wait_dac); + + if (signal_pending(current)) + return -ERESTARTSYS; + down(&s->open_sem_dac); } - up(&s->open_sem); - interruptible_sleep_on(&s->open_wait); - if (signal_pending(current)) - return -ERESTARTSYS; - down(&s->open_sem); } - s->fmt = AFMT_U8; - s->channels = 1; - s->rate = 8000; - s->clkdiv = 96 | 0x80; - s->ena = s->endofbuffer = 0; - s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0; - s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = s->dma_dac.subdivision = 0; - s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); - up(&s->open_sem); - MOD_INC_USE_COUNT; + if (file->f_mode & FMODE_READ) { + down(&s->open_sem_adc); + while (s->open_mode & FMODE_READ) { + if (file->f_flags & O_NONBLOCK) { + up(&s->open_sem_adc); + return -EBUSY; + } + up(&s->open_sem_adc); + interruptible_sleep_on(&s->open_wait_adc); - if (prog_dmabuf_dac(s) || prog_dmabuf_adc(s)) { - - printk(KERN_ERR "cs4281: Program dmabufs failed.\n"); - cs4281_release(inode, file); - - return -ENOMEM; + if (signal_pending(current)) + return -ERESTARTSYS; + down(&s->open_sem_adc); + } + } + s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); + if (file->f_mode & FMODE_READ) { + s->prop_adc.fmt = AFMT_U8; + s->prop_adc.fmt_original = s->prop_adc.fmt; + s->prop_adc.channels = 1; + s->prop_adc.rate = 8000; + s->prop_adc.clkdiv = 96 | 0x80; + s->conversion = 0; + s->ena &= ~FMODE_READ; + s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = + s->dma_adc.subdivision = 0; + up(&s->open_sem_adc); + MOD_INC_USE_COUNT; + + if (prog_dmabuf_adc(s)) { + CS_DBGOUT(CS_OPEN | CS_ERROR, 2, printk(KERN_ERR + "cs4281: adc Program dmabufs failed.\n")); + cs4281_release(inode, file); + return -ENOMEM; + } + prog_codec(s, CS_TYPE_ADC); } - prog_codec(s); - CS_DBGOUT(CS_INIT | CS_FUNCTION | CS_OPEN, 2, - printk(KERN_INFO "cs4281: cs4281_open()- 0\n") ); + if (file->f_mode & FMODE_WRITE) { + s->prop_dac.fmt = AFMT_U8; + s->prop_dac.fmt_original = s->prop_dac.fmt; + s->prop_dac.channels = 1; + s->prop_dac.rate = 8000; + s->prop_dac.clkdiv = 96 | 0x80; + s->conversion = 0; + s->ena &= ~FMODE_WRITE; + s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = + s->dma_dac.subdivision = 0; + up(&s->open_sem_dac); + MOD_INC_USE_COUNT; + + if (prog_dmabuf_dac(s)) { + CS_DBGOUT(CS_OPEN | CS_ERROR, 2, printk(KERN_ERR + "cs4281: dac Program dmabufs failed.\n")); + cs4281_release(inode, file); + return -ENOMEM; + } + prog_codec(s, CS_TYPE_DAC); + } + CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, + printk(KERN_INFO "cs4281: cs4281_open()- 0\n")); return 0; } @@ -2095,15 +3186,15 @@ static int cs4281_open(struct inode *inode, struct file *file) // ****************************************************************************************** // Wave (audio) file operations struct. // ****************************************************************************************** -static /*const*/ struct file_operations cs4281_audio_fops = { - llseek: cs4281_llseek, - read: cs4281_read, - write: cs4281_write, - poll: cs4281_poll, - ioctl: cs4281_ioctl, - mmap: cs4281_mmap, - open: cs4281_open, - release: cs4281_release, +static /*const */ struct file_operations cs4281_audio_fops = { + llseek:cs4281_llseek, + read:cs4281_read, + write:cs4281_write, + poll:cs4281_poll, + ioctl:cs4281_ioctl, + mmap:cs4281_mmap, + open:cs4281_open, + release:cs4281_release, }; // --------------------------------------------------------------------- @@ -2116,8 +3207,8 @@ static void cs4281_handle_midi(struct cs4281_state *s) unsigned temp1; wake = 0; - while (!(readl(s->pBA0+ BA0_MIDSR) & 0x80)) { - ch = readl(s->pBA0+BA0_MIDRP); + while (!(readl(s->pBA0 + BA0_MIDSR) & 0x80)) { + ch = readl(s->pBA0 + BA0_MIDRP); if (s->midi.icnt < MIDIINBUF) { s->midi.ibuf[s->midi.iwr] = ch; s->midi.iwr = (s->midi.iwr + 1) % MIDIINBUF; @@ -2128,12 +3219,12 @@ static void cs4281_handle_midi(struct cs4281_state *s) if (wake) wake_up(&s->midi.iwait); wake = 0; - while (!(readl(s->pBA0+ BA0_MIDSR) & 0x40) && s->midi.ocnt > 0) { - temp1 = ( s->midi.obuf[s->midi.ord] ) & 0x000000ff; - writel(temp1, s->pBA0+BA0_MIDWP); + while (!(readl(s->pBA0 + BA0_MIDSR) & 0x40) && s->midi.ocnt > 0) { + temp1 = (s->midi.obuf[s->midi.ord]) & 0x000000ff; + writel(temp1, s->pBA0 + BA0_MIDWP); s->midi.ord = (s->midi.ord + 1) % MIDIOUTBUF; s->midi.ocnt--; - if (s->midi.ocnt < MIDIOUTBUF-16) + if (s->midi.ocnt < MIDIOUTBUF - 16) wake = 1; } if (wake) @@ -2144,48 +3235,32 @@ static void cs4281_handle_midi(struct cs4281_state *s) static void cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - struct cs4281_state *s = (struct cs4281_state *)dev_id; + struct cs4281_state *s = (struct cs4281_state *) dev_id; unsigned int temp1; // fastpath out, to ease interrupt sharing - temp1 = readl(s->pBA0+BA0_HISR); // Get Int Status reg. + temp1 = readl(s->pBA0 + BA0_HISR); // Get Int Status reg. - CS_DBGOUT(CS_INTERRUPT, 6, printk(KERN_INFO - "cs4281: cs4281_interrupt() BA0_HISR=0x%.8x\n",temp1) ); + CS_DBGOUT(CS_INTERRUPT, 6, printk(KERN_INFO + "cs4281: cs4281_interrupt() BA0_HISR=0x%.8x\n", + temp1)); - if (!(temp1 & (HISR_DMA0 | HISR_DMA1 | HISR_MIDI))) { // If not DMA or MIDI int, - writel(HICR_IEV| HICR_CHGM, s->pBA0+BA0_HICR); // reenable interrupts - CS_DBGOUT(CS_INTERRUPT, 4, printk(KERN_INFO - "cs4281: cs4281_interrupt(): returning not cs4281 interrupt.\n") ); - return; // and return. + if (!(temp1 & (HISR_DMA0 | HISR_DMA1 | HISR_MIDI))) { // If not DMA or MIDI int, + writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR); // reenable interrupts + CS_DBGOUT(CS_INTERRUPT, 4, printk(KERN_INFO + "cs4281: cs4281_interrupt(): returning not cs4281 interrupt.\n")); + return; // and return. } - - if(temp1 & HISR_DMA0) // If play interrupt, - readl(s->pBA0+BA0_HDSR0); // clear the source. - if(temp1 & HISR_DMA1) // Same for play. - readl(s->pBA0+BA0_HDSR1); - writel(HICR_IEV| HICR_CHGM, s->pBA0+BA0_HICR); // Local EOI - + if (temp1 & HISR_DMA0) // If play interrupt, + readl(s->pBA0 + BA0_HDSR0); // clear the source. + + if (temp1 & HISR_DMA1) // Same for play. + readl(s->pBA0 + BA0_HDSR1); + writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR); // Local EOI + spin_lock(&s->lock); - // - // ok, at this point we assume that the fifos have been filled - // with silence and so we now turn off the DMA engine. - // if FMODE_WRITE is set that means that some thread - // attempted to start_dac, which probably means that an open - // occurred, so do not stop the dac in this case. - // - if(s->endofbuffer && !(s->ena & FMODE_WRITE)) - { - CS_DBGOUT(CS_INTERRUPT, 2, printk(KERN_INFO - "cs4281: cs4281_interrupt() stopping play DMA\n") ); - writel(temp1|DCRn_MSK, s->pBA0+BA0_DCR0); // Stop Play DMA - s->endofbuffer = 0; - } - else - { - cs4281_update_ptr(s); - } + cs4281_update_ptr(s); cs4281_handle_midi(s); spin_unlock(&s->lock); } @@ -2194,22 +3269,24 @@ static void cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs) static void cs4281_midi_timer(unsigned long data) { - struct cs4281_state *s = (struct cs4281_state *)data; + struct cs4281_state *s = (struct cs4281_state *) data; unsigned long flags; spin_lock_irqsave(&s->lock, flags); cs4281_handle_midi(s); spin_unlock_irqrestore(&s->lock, flags); - s->midi.timer.expires = jiffies+1; + s->midi.timer.expires = jiffies + 1; add_timer(&s->midi.timer); } // --------------------------------------------------------------------- -static ssize_t cs4281_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +static ssize_t cs4281_midi_read(struct file *file, char *buffer, + size_t count, loff_t * ppos) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; ssize_t ret; unsigned long flags; unsigned ptr; @@ -2253,9 +3330,11 @@ static ssize_t cs4281_midi_read(struct file *file, char *buffer, size_t count, l } -static ssize_t cs4281_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) +static ssize_t cs4281_midi_write(struct file *file, const char *buffer, + size_t count, loff_t * ppos) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; ssize_t ret; unsigned long flags; unsigned ptr; @@ -2304,9 +3383,11 @@ static ssize_t cs4281_midi_write(struct file *file, const char *buffer, size_t c } -static unsigned int cs4281_midi_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int cs4281_midi_poll(struct file *file, + struct poll_table_struct *wait) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; unsigned long flags; unsigned int mask = 0; @@ -2333,7 +3414,7 @@ static int cs4281_midi_open(struct inode *inode, struct file *file) { int minor = MINOR(inode->i_rdev); struct cs4281_state *s = devs; - unsigned long flags,temp1; + unsigned long flags, temp1; while (s && s->dev_midi != minor) s = s->next; if (!s) @@ -2357,16 +3438,16 @@ static int cs4281_midi_open(struct inode *inode, struct file *file) if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) { s->midi.ird = s->midi.iwr = s->midi.icnt = 0; s->midi.ord = s->midi.owr = s->midi.ocnt = 0; - writel(1, s->pBA0+BA0_MIDCR); // Reset the interface. - writel(0, s->pBA0+BA0_MIDCR); // Return to normal mode. + writel(1, s->pBA0 + BA0_MIDCR); // Reset the interface. + writel(0, s->pBA0 + BA0_MIDCR); // Return to normal mode. s->midi.ird = s->midi.iwr = s->midi.icnt = 0; - writel(0x0000000f, s->pBA0+BA0_MIDCR); // Enable transmit, record, ints. - temp1 = readl(s->pBA0+BA0_HIMR); - writel(temp1 & 0xffbfffff, s->pBA0+BA0_HIMR); // Enable midi int. recognition. - writel(HICR_IEV | HICR_CHGM, s->pBA0+BA0_HICR); // Enable interrupts + writel(0x0000000f, s->pBA0 + BA0_MIDCR); // Enable transmit, record, ints. + temp1 = readl(s->pBA0 + BA0_HIMR); + writel(temp1 & 0xffbfffff, s->pBA0 + BA0_HIMR); // Enable midi int. recognition. + writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR); // Enable interrupts init_timer(&s->midi.timer); - s->midi.timer.expires = jiffies+1; - s->midi.timer.data = (unsigned long)s; + s->midi.timer.expires = jiffies + 1; + s->midi.timer.data = (unsigned long) s; s->midi.timer.function = cs4281_midi_timer; add_timer(&s->midi.timer); } @@ -2377,7 +3458,10 @@ static int cs4281_midi_open(struct inode *inode, struct file *file) s->midi.ord = s->midi.owr = s->midi.ocnt = 0; } spin_unlock_irqrestore(&s->lock, flags); - s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE); + s->open_mode |= + (file-> + f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | + FMODE_MIDI_WRITE); up(&s->open_sem); MOD_INC_USE_COUNT; return 0; @@ -2386,7 +3470,8 @@ static int cs4281_midi_open(struct inode *inode, struct file *file) static int cs4281_midi_release(struct inode *inode, struct file *file) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; DECLARE_WAITQUEUE(wait, current); unsigned long flags; unsigned count, tmo; @@ -2411,16 +3496,19 @@ static int cs4281_midi_release(struct inode *inode, struct file *file) } tmo = (count * HZ) / 3100; if (!schedule_timeout(tmo ? : 1) && tmo) - printk(KERN_DEBUG "cs4281: midi timed out??\n"); + printk(KERN_DEBUG + "cs4281: midi timed out??\n"); } remove_wait_queue(&s->midi.owait, &wait); current->state = TASK_RUNNING; } down(&s->open_sem); - s->open_mode &= (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE); + s->open_mode &= + (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ | + FMODE_MIDI_WRITE); spin_lock_irqsave(&s->lock, flags); if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) { - writel(0, s->pBA0+BA0_MIDCR); // Disable Midi interrupts. + writel(0, s->pBA0 + BA0_MIDCR); // Disable Midi interrupts. del_timer(&s->midi.timer); } spin_unlock_irqrestore(&s->lock, flags); @@ -2433,20 +3521,20 @@ static int cs4281_midi_release(struct inode *inode, struct file *file) // ****************************************************************************************** // Midi file operations struct. // ****************************************************************************************** -static /*const*/ struct file_operations cs4281_midi_fops = { - llseek: cs4281_llseek, - read: cs4281_midi_read, - write: cs4281_midi_write, - poll: cs4281_midi_poll, - open: cs4281_midi_open, - release: cs4281_midi_release, +static /*const */ struct file_operations cs4281_midi_fops = { + llseek:cs4281_llseek, + read:cs4281_midi_read, + write:cs4281_midi_write, + poll:cs4281_midi_poll, + open:cs4281_midi_open, + release:cs4281_midi_release, }; // --------------------------------------------------------------------- // maximum number of devices -#define NR_DEVICE 8 // Only eight devices supported currently. +#define NR_DEVICE 8 // Only eight devices supported currently. // --------------------------------------------------------------------- @@ -2454,127 +3542,144 @@ static struct initvol { int mixch; int vol; } initvol[] __initdata = { - { SOUND_MIXER_WRITE_VOLUME, 0x4040 }, - { SOUND_MIXER_WRITE_PCM, 0x4040 }, - { SOUND_MIXER_WRITE_SYNTH, 0x4040 }, - { SOUND_MIXER_WRITE_CD, 0x4040 }, - { SOUND_MIXER_WRITE_LINE, 0x4040 }, - { SOUND_MIXER_WRITE_LINE1, 0x4040 }, - { SOUND_MIXER_WRITE_RECLEV, 0x0000 }, - { SOUND_MIXER_WRITE_SPEAKER, 0x4040 }, - { SOUND_MIXER_WRITE_MIC, 0x0000 } + + { + SOUND_MIXER_WRITE_VOLUME, 0x4040}, { + SOUND_MIXER_WRITE_PCM, 0x4040}, { + SOUND_MIXER_WRITE_SYNTH, 0x4040}, { + SOUND_MIXER_WRITE_CD, 0x4040}, { + SOUND_MIXER_WRITE_LINE, 0x4040}, { + SOUND_MIXER_WRITE_LINE1, 0x4040}, { + SOUND_MIXER_WRITE_RECLEV, 0x0000}, { + SOUND_MIXER_WRITE_SPEAKER, 0x4040}, { + SOUND_MIXER_WRITE_MIC, 0x0000} }; -static int __devinit cs4281_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) +static int __devinit cs4281_probe(struct pci_dev *pcidev, + const struct pci_device_id *pciid) { struct cs4281_state *s; dma_addr_t dma_mask; mm_segment_t fs; int i, val, index = 0; unsigned int temp1, temp2; - - CS_DBGOUT(CS_INIT, 2, printk(KERN_INFO "cs4281: probe()+\n") ); + + CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, + printk(KERN_INFO "cs4281: probe()+\n")); if (!RSRCISMEMORYREGION(pcidev, 0) || - !RSRCISMEMORYREGION(pcidev, 1)) - { + !RSRCISMEMORYREGION(pcidev, 1)) { CS_DBGOUT(CS_ERROR, 1, - printk(KERN_ERR "cs4281: probe()- Memory region not assigned\n") ); + printk(KERN_ERR + "cs4281: probe()- Memory region not assigned\n")); return -1; } if (pcidev->irq == 0) { CS_DBGOUT(CS_ERROR, 1, - printk(KERN_ERR "cs4281: probe() IRQ not assigned\n") ); + printk(KERN_ERR + "cs4281: probe() IRQ not assigned\n")); return -1; - } + } if (!pci_dma_supported(pcidev, 0xffffffff)) { - CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR - "cs4281: probe() architecture does not support 32bit PCI busmaster DMA\n") ); + CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR + "cs4281: probe() architecture does not support 32bit PCI busmaster DMA\n")); return -1; - } - dma_mask = 0xffffffff; /* this enables playback and recording */ + } + dma_mask = 0xffffffff; /* this enables playback and recording */ if (!(s = kmalloc(sizeof(struct cs4281_state), GFP_KERNEL))) { - CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR - "cs4281: probe() no memory for state struct.\n") ); + CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR + "cs4281: probe() no memory for state struct.\n")); return -1; } memset(s, 0, sizeof(struct cs4281_state)); init_waitqueue_head(&s->dma_adc.wait); init_waitqueue_head(&s->dma_dac.wait); init_waitqueue_head(&s->open_wait); + init_waitqueue_head(&s->open_wait_adc); + init_waitqueue_head(&s->open_wait_dac); init_waitqueue_head(&s->midi.iwait); init_waitqueue_head(&s->midi.owait); init_MUTEX(&s->open_sem); + init_MUTEX(&s->open_sem_adc); + init_MUTEX(&s->open_sem_dac); spin_lock_init(&s->lock); s->pBA0phys = RSRCADDRESS(pcidev, 0); s->pBA1phys = RSRCADDRESS(pcidev, 1); - s->pBA0 = ioremap_nocache(s->pBA0phys, 4096); // Convert phys - s->pBA1 = ioremap_nocache(s->pBA1phys, 65536); // to linear. - temp1 = readl(s->pBA0+ BA0_PCICFG00); - temp2 = readl(s->pBA0+ BA0_PCICFG04); - - CS_DBGOUT(CS_INIT, 2, - printk(KERN_INFO "cs4281: probe() BA0=0x%.8x BA1=0x%.8x pBA0=0x%.8x pBA1=0x%.8x \n", - (unsigned)temp1,(unsigned)temp2,(unsigned)s->pBA0,(unsigned)s->pBA1) ); - - CS_DBGOUT(CS_INIT, 2, - printk(KERN_INFO "cs4281: probe() pBA0phys=0x%.8x pBA1phys=0x%.8x\n", - (unsigned)s->pBA0phys,(unsigned)s->pBA1phys) ); + s->pBA0 = ioremap_nocache(s->pBA0phys, 4096); // Convert phys + s->pBA1 = ioremap_nocache(s->pBA1phys, 65536); // to linear. + temp1 = readl(s->pBA0 + BA0_PCICFG00); + temp2 = readl(s->pBA0 + BA0_PCICFG04); + + CS_DBGOUT(CS_INIT, 2, + printk(KERN_INFO + "cs4281: probe() BA0=0x%.8x BA1=0x%.8x pBA0=0x%.8x pBA1=0x%.8x \n", + (unsigned) temp1, (unsigned) temp2, + (unsigned) s->pBA0, (unsigned) s->pBA1)); + + CS_DBGOUT(CS_INIT, 2, + printk(KERN_INFO + "cs4281: probe() pBA0phys=0x%.8x pBA1phys=0x%.8x\n", + (unsigned) s->pBA0phys, (unsigned) s->pBA1phys)); temp1 = cs4281_hw_init(s); - if(temp1){ - CS_DBGOUT(CS_ERROR | CS_INIT, 1, - printk(KERN_ERR "cs4281: cs4281_hw_init() failed. Skipping part.\n") ); + if (temp1) { + CS_DBGOUT(CS_ERROR | CS_INIT, 1, + printk(KERN_ERR + "cs4281: cs4281_hw_init() failed. Skipping part.\n")); return -1; - } + } s->magic = CS4281_MAGIC; s->pcidev = pcidev; s->irq = pcidev->irq; - if (pci_enable_device(pcidev)) - { - CS_DBGOUT(CS_INIT | CS_ERROR, 1, - printk(KERN_ERR "cs4281: pci_enable_device() failed\n") ); + if (pci_enable_device(pcidev)) { + CS_DBGOUT(CS_INIT | CS_ERROR, 1, + printk(KERN_ERR + "cs4281: pci_enable_device() failed\n")); goto err_irq; } - if(request_irq(s->irq, cs4281_interrupt, SA_SHIRQ, "Crystal CS4281", s)){ - CS_DBGOUT(CS_INIT | CS_ERROR, 1, - printk(KERN_ERR "cs4281: irq %u in use\n", s->irq) ); + if (request_irq + (s->irq, cs4281_interrupt, SA_SHIRQ, "Crystal CS4281", s)) { + CS_DBGOUT(CS_INIT | CS_ERROR, 1, + printk(KERN_ERR "cs4281: irq %u in use\n", + s->irq)); goto err_irq; } - if ((s->dev_audio = register_sound_dsp(&cs4281_audio_fops, -1)) < 0) - { - CS_DBGOUT(CS_INIT | CS_ERROR, 1, - printk(KERN_ERR "cs4281: probe() register_sound_dsp() failed.\n") ); + if ((s->dev_audio = register_sound_dsp(&cs4281_audio_fops, -1)) < + 0) { + CS_DBGOUT(CS_INIT | CS_ERROR, 1, + printk(KERN_ERR + "cs4281: probe() register_sound_dsp() failed.\n")); goto err_dev1; } - if ((s->dev_mixer = register_sound_mixer(&cs4281_mixer_fops, -1)) < 0) - { - CS_DBGOUT(CS_INIT | CS_ERROR, 1, - printk(KERN_ERR "cs4281: probe() register_sound_mixer() failed.\n") ); + if ((s->dev_mixer = register_sound_mixer(&cs4281_mixer_fops, -1)) < + 0) { + CS_DBGOUT(CS_INIT | CS_ERROR, 1, + printk(KERN_ERR + "cs4281: probe() register_sound_mixer() failed.\n")); goto err_dev2; } - if ((s->dev_midi = register_sound_midi(&cs4281_midi_fops, -1)) < 0) - { - CS_DBGOUT(CS_INIT | CS_ERROR, 1, - printk(KERN_ERR "cs4281: probe() register_sound_midi() failed.\n") ); + if ((s->dev_midi = register_sound_midi(&cs4281_midi_fops, -1)) < 0) { + CS_DBGOUT(CS_INIT | CS_ERROR, 1, + printk(KERN_ERR + "cs4281: probe() register_sound_midi() failed.\n")); goto err_dev3; } - - pci_set_master(pcidev); // enable bus mastering + + pci_set_master(pcidev); // enable bus mastering fs = get_fs(); set_fs(KERNEL_DS); val = SOUND_MASK_LINE; - mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val); - for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) { + mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long) &val); + for (i = 0; i < sizeof(initvol) / sizeof(initvol[0]); i++) { val = initvol[i].vol; - mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val); + mixer_ioctl(s, initvol[i].mixch, (unsigned long) &val); } - val = 1; // enable mic preamp - mixer_ioctl(s, SOUND_MIXER_PRIVATE1, (unsigned long)&val); + val = 1; // enable mic preamp + mixer_ioctl(s, SOUND_MIXER_PRIVATE1, (unsigned long) &val); set_fs(fs); - + // queue it for later freeing s->next = devs; pcidev->driver_data = s; @@ -2583,32 +3688,33 @@ static int __devinit cs4281_probe(struct pci_dev *pcidev, const struct pci_devic index++; return 0; -err_dev3: + err_dev3: unregister_sound_mixer(s->dev_mixer); -err_dev2: + err_dev2: unregister_sound_dsp(s->dev_audio); -err_dev1: + err_dev1: free_irq(s->irq, s); -err_irq: + err_irq: kfree(s); - if (!devs) - { + if (!devs) { CS_DBGOUT(CS_INIT | CS_ERROR, 1, - printk(KERN_INFO "cs4281: probe()- no device allocated\n") ); + printk(KERN_INFO + "cs4281: probe()- no device allocated\n")); return -ENODEV; } CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, - printk(KERN_INFO "cs4281: probe()- device allocated successfully\n") ); + printk(KERN_INFO + "cs4281: probe()- device allocated successfully\n")); return 0; -} // probe_cs4281 +} // probe_cs4281 // --------------------------------------------------------------------- static void __devinit cs4281_remove(struct pci_dev *dev) { - struct cs4281_state *s = (struct cs4281_state *)dev->driver_data; + struct cs4281_state *s = (struct cs4281_state *) dev->driver_data; // stop DMA controller synchronize_irq(); free_irq(s->irq, s); @@ -2616,44 +3722,51 @@ static void __devinit cs4281_remove(struct pci_dev *dev) unregister_sound_mixer(s->dev_mixer); unregister_sound_midi(s->dev_midi); kfree(s); - dev->driver_data = NULL; - CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, - printk(KERN_INFO "cs4281: cs4281_remove(): remove successful\n") ); + dev->driver_data = NULL; + CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, + printk(KERN_INFO + "cs4281: cs4281_remove(): remove successful\n")); } static struct pci_device_id id_table[] __devinitdata = { - { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CRYSTAL_CS4281, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, - { 0, } + + {PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CRYSTAL_CS4281, + PCI_ANY_ID, PCI_ANY_ID, 0, 0}, + {0,} }; MODULE_DEVICE_TABLE(pci, id_table); static struct pci_driver cs4281_driver = { - name: "cs4281", - id_table: id_table, - probe: cs4281_probe, - remove: cs4281_remove + name:"cs4281", + id_table:id_table, + probe:cs4281_probe, + remove:cs4281_remove }; static int __init init_cs4281(void) { - - CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO "cs4281: init_cs4281()+ \n") ); - if (!pci_present()) /* No PCI bus in this machine! */ - { - CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, - printk(KERN_INFO "cs4281: init_cs4281()- no pci bus found\n") ); + + CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: init_cs4281()+ \n")); + if (!pci_present()) { /* No PCI bus in this machine! */ + CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, + printk(KERN_INFO + "cs4281: init_cs4281()- no pci bus found\n")); return -ENODEV; } - printk(KERN_INFO "cs4281: version v%d.%02d.%d time " __TIME__ " " __DATE__ "\n", - CS4281_MAJOR_VERSION, CS4281_MINOR_VERSION, CS4281_ARCH); + printk(KERN_INFO "cs4281: version v%d.%02d.%d time " __TIME__ " " + __DATE__ "\n", CS4281_MAJOR_VERSION, CS4281_MINOR_VERSION, + CS4281_ARCH); if (!pci_register_driver(&cs4281_driver)) { pci_unregister_driver(&cs4281_driver); - CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, - printk(KERN_INFO "cs4281: init_cs4281()- unable to register pci device \n") ); + CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, + printk(KERN_INFO + "cs4281: init_cs4281()- unable to register pci device \n")); return -ENODEV; } - CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO "cs4281: init_cs4281()- 0\n") ); + CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: init_cs4281()- 0\n")); return 0; } @@ -2667,12 +3780,11 @@ MODULE_DESCRIPTION("Cirrus Logic CS4281 Driver"); static void __exit cleanup_cs4281(void) { pci_unregister_driver(&cs4281_driver); - CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, - printk(KERN_INFO "cs4281: cleanup_cs4281() finished\n") ); + CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: cleanup_cs4281() finished\n")); } // --------------------------------------------------------------------- module_init(init_cs4281); module_exit(cleanup_cs4281); - diff --git a/drivers/sound/dmasound/dmasound.h b/drivers/sound/dmasound/dmasound.h index 6bce7b4f6faf..ff799552269d 100644 --- a/drivers/sound/dmasound/dmasound.h +++ b/drivers/sound/dmasound/dmasound.h @@ -47,7 +47,6 @@ #define MAX_BUFSIZE 128 /* Limit for Amiga in KB */ -#define arraysize(x) (sizeof(x)/sizeof(*(x))) #define min(x, y) ((x) < (y) ? (x) : (y)) #define le2be16(x) (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff)) #define le2be16dbl(x) (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff)) diff --git a/drivers/sound/dmasound/dmasound_atari.c b/drivers/sound/dmasound/dmasound_atari.c index fd15eae0aee3..faf00d79868b 100644 --- a/drivers/sound/dmasound/dmasound_atari.c +++ b/drivers/sound/dmasound/dmasound_atari.c @@ -9,6 +9,7 @@ #include +#include #include #include #include @@ -895,7 +896,7 @@ static void TTInit(void) /* search a frequency that fits into the allowed error range */ idx = -1; - for (i = 0; i < arraysize(freq); i++) + for (i = 0; i < ARRAY_SIZE(freq); i++) /* this isn't as much useful for a TT than for a Falcon, but * then it doesn't hurt very much to implement it for a TT too. */ @@ -1021,7 +1022,7 @@ static void FalconInit(void) /* search a frequency that fits into the allowed error range */ idx = -1; - for (i = 0; i < arraysize(freq); i++) + for (i = 0; i < ARRAY_SIZE(freq); i++) /* if we will tolerate 3% error 8000Hz->8195Hz (2.38%) would * be playable without expanding, but that now a kernel runtime * option diff --git a/drivers/sound/emu10k1/emu_wrapper.h b/drivers/sound/emu10k1/emu_wrapper.h index 3a9862832bbe..16461fd017cd 100644 --- a/drivers/sound/emu10k1/emu_wrapper.h +++ b/drivers/sound/emu10k1/emu_wrapper.h @@ -1,8 +1,8 @@ #ifndef __EMU_WRAPPER_H #define __EMU_WRAPPER_H -#include +#define vma_get_pgoff(v) ((v)->vm_pgoff) -#define PCI_SET_DMA_MASK(pdev,mask) (((pdev)->dma_mask) = (mask)) +#define PCI_SET_DMA_MASK(pdev,mask) (((pdev)->dma_mask) = (mask)) #endif diff --git a/drivers/sound/trident.c b/drivers/sound/trident.c index b4db5bb5fc5f..b6e870d32a99 100644 --- a/drivers/sound/trident.c +++ b/drivers/sound/trident.c @@ -31,6 +31,9 @@ * * History * v0.14.6 + * Nov 1 2000 Ching-Ling Lee + * Fix the bug of memory leak when swithing 5.1-channels to 2 channels. + * Add lock protection into dynamic changing format of data. * Oct 18 2000 Ching-Ling Lee * 5.1-channels support for ALi * June 28 2000 Ching-Ling Lee @@ -142,7 +145,7 @@ /* minor number of /dev/swmodem (temporary, experimental) */ #define SND_DEV_SWMODEM 7 -static const unsigned ali_multi_channels[] = { ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL,ALI_CENTER_CHANNEL, ALI_LEF_CHANNEL/*, ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL*/}; +static const unsigned ali_multi_channels_5_1[] = { ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL,ALI_CENTER_CHANNEL, ALI_LEF_CHANNEL/*, ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL*/}; static const unsigned sample_size[] = { 1, 2, 2, 4 }; static const unsigned sample_shift[] = { 0, 1, 1, 2 }; @@ -225,12 +228,14 @@ struct trident_state { unsigned ossfragshift; int ossmaxfrags; unsigned subdivision; + } dmabuf; /* 5.1channels */ struct trident_state *other_states[4]; int multi_channels_adjust_count; unsigned chans_num; + unsigned fmt_flag:1; }; /* hardware channels */ @@ -341,7 +346,6 @@ static struct trident_channel *ali_alloc_pcm_channel(struct trident_card *card); static int ali_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data); static void ali_restore_regs(struct trident_card *card); static void ali_save_regs(struct trident_card *card); -static int ali_allocate_multi_channels(struct trident_state *state, int chan_nums); static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel); static int ali_setup_multi_channels(struct trident_card *card, int chan_nums); static unsigned int ali_get_spdif_in_rate(struct trident_card *card); @@ -349,7 +353,9 @@ static void ali_setup_spdif_in(struct trident_card *card); static void ali_disable_spdif_in(struct trident_card *card); static void ali_disable_special_channel(struct trident_card *card, int ch); static void ali_setup_spdif_out(struct trident_card *card, int flag); -static unsigned int ali_write_5_1(struct trident_state *state, const char *buffer,int cnt_for_multi_channel); +static int ali_write_5_1(struct trident_state *state, const char *buffer,int cnt_for_multi_channel, unsigned int *copy_count, unsigned int *state_cnt); +static int ali_allocate_other_states_resources(struct trident_state *state, int chan_nums); +static void ali_free_other_states_resources(struct trident_state *state); /* save registers for ALi Power Management */ @@ -359,9 +365,22 @@ static struct ali_saved_registers { unsigned mixer_regs[ALI_MIXER_REGS]; } ali_registers; -#define seek_offset(dma_ptr, buffer, cnt, offset) (dma_ptr) += (offset); \ +#define seek_offset(dma_ptr, buffer, cnt, offset, copy_count) (dma_ptr) += (offset); \ (buffer) += (offset); \ - (cnt) -= (offset); + (cnt) -= (offset); \ + (copy_count) += (offset); + +#define lock_set_fmt(state) {spin_lock_irqsave(&state->card->lock, flags); \ + if (state->fmt_flag) { \ + spin_unlock_irqrestore(&state->card->lock, flags); \ + return -EFAULT; \ + } \ + state->fmt_flag = 1; \ + spin_unlock_irqrestore(&state->card->lock, flags);} + +#define unlock_set_fmt(state) {spin_lock_irqsave(&state->card->lock, flags); \ + state->fmt_flag = 0; \ + spin_unlock_irqrestore(&state->card->lock, flags);} static int trident_enable_loop_interrupts(struct trident_card * card) { @@ -993,18 +1012,15 @@ static int prog_dmabuf(struct trident_state *state, unsigned rec) struct dmabuf *dmabuf = &state->dmabuf; unsigned bytepersec; struct trident_state *s = state; - unsigned bufsize, dma_nums, default_order; + unsigned bufsize, dma_nums; unsigned long flags; int ret, i, order; struct page *page, *pend; - default_order = DMABUF_DEFAULTORDER; - if (s->chans_num == 6) { + lock_set_fmt(state); + if (state->chans_num == 6) dma_nums = 5; - } - else { - dma_nums = 1; - } + else dma_nums = 1; for (i = 0; i < dma_nums; i++) { if (i > 0) { @@ -1022,8 +1038,10 @@ static int prog_dmabuf(struct trident_state *state, unsigned rec) /* allocate DMA buffer if not allocated yet */ if (!dmabuf->rawbuf) { if (i == 0) { - if ((ret = alloc_dmabuf(state))) + if ((ret = alloc_dmabuf(state))) { + unlock_set_fmt(state); return ret; + } } else { if ((order = state->dmabuf.buforder - 1) >= DMABUF_MINORDER) @@ -1034,6 +1052,7 @@ static int prog_dmabuf(struct trident_state *state, unsigned rec) i-=2; for (; i >= 0; i--) free_pages((unsigned long)state->other_states[i]->dmabuf.rawbuf, state->other_states[i]->dmabuf.buforder); + unlock_set_fmt(state); return -ENOMEM; } dmabuf->ready = dmabuf->mapped = 0; @@ -1087,6 +1106,7 @@ static int prog_dmabuf(struct trident_state *state, unsigned rec) dmabuf->fragsize, dmabuf->dmasize); #endif } + unlock_set_fmt(state); return 0; } @@ -1451,6 +1471,7 @@ static ssize_t trident_write(struct file *file, const char *buffer, size_t count unsigned swptr; int cnt; unsigned int state_cnt; + unsigned int copy_count; #ifdef DEBUG printk("trident: trident_write called, count = %d\n", count); @@ -1493,8 +1514,10 @@ static ssize_t trident_write(struct file *file, const char *buffer, size_t count } /* No matter how much data left in the buffer, we have to wait untill CSO == ESO/2 or CSO == ESO when address engine interrupts */ + lock_set_fmt(state); tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2); tmo >>= sample_shift[dmabuf->fmt]; + unlock_set_fmt(state); /* There are two situations when sleep_on_timeout returns, one is when the interrupt is serviced correctly and the process is waked up by ISR ON TIME. Another is when timeout is expired, which means that @@ -1518,17 +1541,34 @@ static ssize_t trident_write(struct file *file, const char *buffer, size_t count } continue; } - + lock_set_fmt(state); if (state->chans_num == 6) { - state_cnt = ali_write_5_1(state, buffer, cnt); + copy_count = 0; + state_cnt = 0; + if (ali_write_5_1(state, buffer, cnt, ©_count, &state_cnt) == -EFAULT) { + if (state_cnt){ + swptr = (swptr + state_cnt) % dmabuf->dmasize; + spin_lock_irqsave(&state->card->lock, flags); + dmabuf->swptr = swptr; + dmabuf->count += state_cnt; + dmabuf->endcleared = 0; + spin_unlock_irqrestore(&state->card->lock, flags); + } + ret += copy_count; + if (!ret) ret = -EFAULT; + unlock_set_fmt(state); + return ret; + } } else { if (copy_from_user(dmabuf->rawbuf + swptr, buffer, cnt)) { if (!ret) ret = -EFAULT; + unlock_set_fmt(state); return ret; } state_cnt = cnt; } + unlock_set_fmt(state); swptr = (swptr + state_cnt) % dmabuf->dmasize; @@ -1684,6 +1724,7 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ if (get_user(val, (int *)arg)) return -EFAULT; + lock_set_fmt(state); if (file->f_mode & FMODE_WRITE) { stop_dac(state); dmabuf->ready = 0; @@ -1700,6 +1741,7 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm else dmabuf->fmt &= ~TRIDENT_FMT_STEREO; } + unlock_set_fmt(state); return 0; case SNDCTL_DSP_GETBLKSIZE: @@ -1720,6 +1762,7 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm case SNDCTL_DSP_SETFMT: /* Select sample format */ if (get_user(val, (int *)arg)) return -EFAULT; + lock_set_fmt(state); if (val != AFMT_QUERY) { if (file->f_mode & FMODE_WRITE) { stop_dac(state); @@ -1738,6 +1781,7 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm dmabuf->fmt &= ~TRIDENT_FMT_16BIT; } } + unlock_set_fmt(state); return put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE : AFMT_U8, (int *)arg); @@ -1745,40 +1789,49 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm if (get_user(val, (int *)arg)) return -EFAULT; if (val != 0) { + lock_set_fmt(state); if (file->f_mode & FMODE_WRITE) { stop_dac(state); dmabuf->ready = 0; + + //prevent from memory leak + if ((state->chans_num > 2) && (state->chans_num != val)) { + ali_free_other_states_resources(state); + state->chans_num = 1; + } + if (val >= 2) { dmabuf->fmt |= TRIDENT_FMT_STEREO; - if (val == 6) { - val = ali_setup_multi_channels(state->card, 6); - if (val < 0) - return val; + if ((val == 6) && (state->card->pci_id == PCI_DEVICE_ID_ALI_5451)) { + ali_setup_multi_channels(state->card, 6); down(&state->card->open_sem); - val = ali_allocate_multi_channels(state, 6); + ret = ali_allocate_other_states_resources(state, 6); up(&state->card->open_sem); - if (val < 0) - return val; - val = 6; + if (ret < 0) { + unlock_set_fmt(state); + return ret; + } } - else val = 2; + else val = 2; /*yield to 2-channels*/ } else dmabuf->fmt &= ~TRIDENT_FMT_STEREO; + state->chans_num = val; } if (file->f_mode & FMODE_READ) { stop_adc(state); dmabuf->ready = 0; if (val >= 2) { - if (val!=6) + if (!((file->f_mode & FMODE_WRITE) && (val == 6))) val = 2; dmabuf->fmt |= TRIDENT_FMT_STEREO; } else dmabuf->fmt &= ~TRIDENT_FMT_STEREO; + state->chans_num = val; } + unlock_set_fmt(state); } - state->chans_num = val; return put_user(val, (int *)arg); case SNDCTL_DSP_POST: @@ -2059,6 +2112,7 @@ static int trident_release(struct inode *inode, struct file *file) struct trident_state *state = (struct trident_state *)file->private_data; struct trident_card *card; struct dmabuf *dmabuf; + unsigned long flags; lock_kernel(); card = state->card; @@ -2075,24 +2129,10 @@ static int trident_release(struct inode *inode, struct file *file) if (file->f_mode & FMODE_WRITE) { stop_dac(state); - if (state->chans_num == 6) { - dealloc_dmabuf(state->other_states[0]); - dealloc_dmabuf(state->other_states[1]); - dealloc_dmabuf(state->other_states[2]); - dealloc_dmabuf(state->other_states[3]); - state->card->free_pcm_channel(state->card, state->other_states[0]->dmabuf.channel->num); - state->card->free_pcm_channel(state->card, state->other_states[1]->dmabuf.channel->num); - state->card->free_pcm_channel(state->card, state->other_states[2]->dmabuf.channel->num); - state->card->free_pcm_channel(state->card, state->other_states[3]->dmabuf.channel->num); - card->states[state->other_states[0]->virt] = NULL; - kfree(state->other_states[0]); - card->states[state->other_states[1]->virt] = NULL; - kfree(state->other_states[1]); - card->states[state->other_states[2]->virt] = NULL; - kfree(state->other_states[2]); - card->states[state->other_states[3]->virt] = NULL; - kfree(state->other_states[3]); - } + lock_set_fmt(state); + if (state->chans_num > 2) + ali_free_other_states_resources(state); + unlock_set_fmt(state); dealloc_dmabuf(state); state->card->free_pcm_channel(state->card, dmabuf->channel->num); } @@ -2495,11 +2535,10 @@ static unsigned int ali_get_spdif_in_rate(struct trident_card *card) static int ali_setup_multi_channels(struct trident_card *card, int chan_nums) { unsigned long dwValue; + if (chan_nums == 6) { dwValue = inl(TRID_REG(card, ALI_SCTRL)) | 0x000f0000; outl(dwValue, TRID_REG(card, ALI_SCTRL)); - dwValue = inl(TRID_REG(card, ALI_GLOBAL_CONTROL)) | 0x07800000; - outl(dwValue, TRID_REG(card, ALI_GLOBAL_CONTROL)); } return 1; } @@ -2517,7 +2556,7 @@ static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel card->banks[bank].bitmap &= ~(1 << (channel)); } -static int ali_allocate_multi_channels(struct trident_state *state, int chan_nums) +static int ali_allocate_other_states_resources(struct trident_state *state, int chan_nums) { struct trident_card *card = state->card; struct trident_state *s; @@ -2530,26 +2569,26 @@ static int ali_allocate_multi_channels(struct trident_state *state, int chan_num if (chan_nums == 6) { for(i = 0;(i < ALI_CHANNELS) && (state_count != 4); i++) { if (!card->states[i]) { - if (!(bank->bitmap & (1 << ali_multi_channels[state_count]))) { - bank->bitmap |= (1 << ali_multi_channels[state_count]); - channel = &bank->channels[ali_multi_channels[state_count]]; - channel->num = ali_multi_channels[state_count]; + if (!(bank->bitmap & (1 << ali_multi_channels_5_1[state_count]))) { + bank->bitmap |= (1 << ali_multi_channels_5_1[state_count]); + channel = &bank->channels[ali_multi_channels_5_1[state_count]]; + channel->num = ali_multi_channels_5_1[state_count]; } else { state_count--; for (; state_count >= 0; state_count--) { kfree(state->other_states[state_count]); - ali_free_pcm_channel(card, ali_multi_channels[state_count]); + ali_free_pcm_channel(card, ali_multi_channels_5_1[state_count]); } return -EBUSY; } s = card->states[i] = (struct trident_state *) kmalloc(sizeof(struct trident_state), GFP_KERNEL); if (!s) { - ali_free_pcm_channel(card, ali_multi_channels[state_count]); + ali_free_pcm_channel(card, ali_multi_channels_5_1[state_count]); state_count--; for (; state_count >= 0; state_count--) { - ali_free_pcm_channel(card, ali_multi_channels[state_count]); + ali_free_pcm_channel(card, ali_multi_channels_5_1[state_count]); kfree(state->other_states[state_count]); } return -ENOMEM; @@ -2562,7 +2601,7 @@ static int ali_allocate_multi_channels(struct trident_state *state, int chan_num s->magic = card->magic; s->card = card; s->virt = i; - + ali_enable_special_channel(s); state->other_states[state_count++] = s; } } @@ -2571,7 +2610,7 @@ static int ali_allocate_multi_channels(struct trident_state *state, int chan_num state_count--; for (; state_count >= 0; state_count--) { kfree(state->other_states[state_count]); - ali_free_pcm_channel(card, ali_multi_channels[state_count]); + ali_free_pcm_channel(card, ali_multi_channels_5_1[state_count]); } return -EBUSY; } @@ -2791,32 +2830,34 @@ protection is no harm because all DMAs of multi-channels and interrupt depend on a master state's DMA, and changing the counters of the master state DMA is protected by a spinlock. */ -static unsigned int ali_write_5_1(struct trident_state *state, const char *buf, int cnt_for_multi_channel) +static int ali_write_5_1(struct trident_state *state, const char *buf, int cnt_for_multi_channel, unsigned int *copy_count, unsigned int *state_cnt) { struct dmabuf *dmabuf = &state->dmabuf; struct dmabuf *dmabuf_temp; const char *buffer = buf; unsigned swptr, other_dma_nums, sample_s; - unsigned int i, loop, state_cnt = 0; + unsigned int i, loop; other_dma_nums = 4; sample_s = sample_size[dmabuf->fmt] >> 1; swptr = dmabuf->swptr; - + if ((i = state->multi_channels_adjust_count) > 0) { if (i == 1) { - copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s); - seek_offset(swptr, buffer, cnt_for_multi_channel, sample_s); + if (copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s)) + return -EFAULT; + seek_offset(swptr, buffer, cnt_for_multi_channel, sample_s, *copy_count); i--; - state_cnt += sample_s; + (*state_cnt) += sample_s; state->multi_channels_adjust_count++; } else i = i - (state->chans_num - other_dma_nums); for (; (i < other_dma_nums) && (cnt_for_multi_channel > 0); i++) { dmabuf_temp = &state->other_states[i]->dmabuf; - copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s); - seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s); + if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s)) + return -EFAULT; + seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s, *copy_count); } if (cnt_for_multi_channel == 0) state->multi_channels_adjust_count += i; @@ -2824,46 +2865,53 @@ static unsigned int ali_write_5_1(struct trident_state *state, const char *buf, if (cnt_for_multi_channel > 0) { loop = cnt_for_multi_channel / (state->chans_num * sample_s); for (i = 0; i < loop; i++) { - copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s * 2); - seek_offset(swptr, buffer, cnt_for_multi_channel, sample_s * 2); + if (copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s * 2)) + return -EFAULT; + seek_offset(swptr, buffer, cnt_for_multi_channel, sample_s * 2, *copy_count); + (*state_cnt) += (sample_s * 2); dmabuf_temp = &state->other_states[0]->dmabuf; - copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s); - seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s); + if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s)) + return -EFAULT; + seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s, *copy_count); dmabuf_temp = &state->other_states[1]->dmabuf; - copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s); - seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s); + if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s)) + return -EFAULT; + seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s, *copy_count); dmabuf_temp = &state->other_states[2]->dmabuf; - copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s); - seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s); + if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s)) + return -EFAULT; + seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s, *copy_count); dmabuf_temp = &state->other_states[3]->dmabuf; - copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s); - seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s); + if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s)) + return -EFAULT; + seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s, *copy_count); } - state_cnt += (sample_s * 2 * loop); - if (cnt_for_multi_channel > 0) { state->multi_channels_adjust_count = cnt_for_multi_channel / sample_s; - copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s); - seek_offset(swptr, buffer, cnt_for_multi_channel, sample_s); - state_cnt += sample_s; + if (copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s)) + return -EFAULT; + seek_offset(swptr, buffer, cnt_for_multi_channel, sample_s, *copy_count); + (*state_cnt) += sample_s; if (cnt_for_multi_channel > 0) { - copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s); - seek_offset(swptr, buffer, cnt_for_multi_channel, sample_s); - state_cnt += sample_s; + if (copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s)) + return -EFAULT; + seek_offset(swptr, buffer, cnt_for_multi_channel, sample_s, *copy_count); + (*state_cnt) += sample_s; if (cnt_for_multi_channel > 0) { loop = state->multi_channels_adjust_count - (state->chans_num - other_dma_nums); for (i = 0; i < loop; i++) { dmabuf_temp = &state->other_states[i]->dmabuf; - copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s); - seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s); + if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s)) + return -EFAULT; + seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s, *copy_count); } } } @@ -2875,7 +2923,25 @@ static unsigned int ali_write_5_1(struct trident_state *state, const char *buf, dmabuf_temp = &state->other_states[i]->dmabuf; dmabuf_temp->swptr = dmabuf_temp->swptr % dmabuf_temp->dmasize; } - return state_cnt; + return *state_cnt; +} + +static void ali_free_other_states_resources(struct trident_state *state) +{ + int i; + struct trident_card *card = state->card; + struct trident_state *s; + unsigned other_states_count; + + other_states_count = state->chans_num - 2; /* except PCM L/R channels*/ + for ( i = 0; i < other_states_count; i++) { + s = state->other_states[i]; + dealloc_dmabuf(s); + ali_disable_special_channel(s->card, s->dmabuf.channel->num); + state->card->free_pcm_channel(s->card, s->dmabuf.channel->num); + card->states[s->virt] = NULL; + kfree(s); + } } #ifdef CONFIG_PROC_FS diff --git a/drivers/usb/acm.c b/drivers/usb/acm.c index 24ca4858d3ed..65a1bbbb0402 100644 --- a/drivers/usb/acm.c +++ b/drivers/usb/acm.c @@ -511,7 +511,7 @@ static void *acm_probe(struct usb_device *dev, unsigned int ifnum) } if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 || - ifcom->bInterfaceProtocol != 1 || ifcom->bNumEndpoints != 1) + ifcom->bInterfaceProtocol != 1 || ifcom->bNumEndpoints < 1) continue; epctrl = ifcom->endpoint + 0; diff --git a/drivers/usb/microtek.c b/drivers/usb/microtek.c index ab37860cd4aa..d7ecc441fe29 100644 --- a/drivers/usb/microtek.c +++ b/drivers/usb/microtek.c @@ -338,6 +338,7 @@ static inline void mts_wait_abort(struct mts_desc* desc) while( !atomic_read(&desc->lock.count) ) { /* Is there a function to check if the semaphore is locked? */ + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout( MTS_ABORT_TIMEOUT ); MTS_DEBUG_GOT_HERE(); mts_urb_abort(desc); diff --git a/drivers/usb/pegasus.c b/drivers/usb/pegasus.c index 02c1eff8056a..2c9fd8b829e3 100644 --- a/drivers/usb/pegasus.c +++ b/drivers/usb/pegasus.c @@ -40,7 +40,6 @@ */ -#include #include #include #include @@ -48,6 +47,7 @@ #include #include #include +#include static const char *version = __FILE__ ": v0.4.13 2000/10/13 (C) 1999-2000 Petko Manolov (petkan@dce.bg)"; @@ -111,7 +111,6 @@ static const char *version = __FILE__ ": v0.4.13 2000/10/13 (C) 1999-2000 Petko #define PEGASUS_REQ_GET_REGS 0xf0 #define PEGASUS_REQ_SET_REGS 0xf1 #define PEGASUS_REQ_SET_REG PEGASUS_REQ_SET_REGS -#define NUM_CTRL_URBS 0x10 #define ALIGN(x) x __attribute__((aligned(L1_CACHE_BYTES))) enum pegasus_registers { @@ -172,36 +171,58 @@ static int multicast_filter_limit = 32; MODULE_AUTHOR("Petko Manolov "); MODULE_DESCRIPTION("ADMtek AN986 Pegasus USB Ethernet driver"); MODULE_PARM(loopback, "i"); -MODULE_PARM(mode, "i"); +MODULE_PARM(mii_mode, "i"); MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)"); -MODULE_PARM_DESC(mode, "Enable HomePNA mode (bit 0) - default = MII mode = 0"); +MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0) - default = MII mode = 0"); static struct usb_eth_dev usb_dev_id[] = { - {"Billionton USB-100", 0x08dd, 0x0986, DEFAULT_GPIO_RESET}, - {"Corega FEter USB-TX", 0x7aa, 0x0004, DEFAULT_GPIO_RESET}, - {"MELCO/BUFFALO LUA-TX", 0x0411, 0x0001, DEFAULT_GPIO_RESET}, - {"D-Link DSB-650TX", 0x2001, 0x4001, LINKSYS_GPIO_RESET}, - {"D-Link DSB-650TX", 0x2001, 0x4002, LINKSYS_GPIO_RESET}, + {"Billionton USB-100", 0x08dd, 0x0986, + DEFAULT_GPIO_RESET}, + {"Billionton USBLP-100", 0x08dd, 0x0987, + DEFAULT_GPIO_RESET | HAS_HOME_PNA}, + {"Billionton USBEL-100", 0x08dd, 0x0988, + DEFAULT_GPIO_RESET}, + {"Billionton USBE-100", 0x08dd, 0x8511, + DEFAULT_GPIO_RESET | PEGASUS_II}, + {"Corega FEter USB-TX", 0x7aa, 0x0004, + DEFAULT_GPIO_RESET}, + {"MELCO/BUFFALO LUA-TX", 0x0411, 0x0001, + DEFAULT_GPIO_RESET}, + {"D-Link DSB-650TX", 0x2001, 0x4001, + LINKSYS_GPIO_RESET}, + {"D-Link DSB-650TX", 0x2001, 0x4002, + LINKSYS_GPIO_RESET}, {"D-Link DSB-650TX(PNA)", 0x2001, 0x4003, - HAS_HOME_PNA | DEFAULT_GPIO_RESET}, - {"D-Link DSB-650", 0x2001, 0xabc1, DEFAULT_GPIO_RESET}, - {"D-Link DU-E10", 0x07b8, 0xabc1, DEFAULT_GPIO_RESET}, - {"D-Link DU-E100", 0x07b8, 0x4002, DEFAULT_GPIO_RESET}, - {"Linksys USB10TX", 0x066b, 0x2202, LINKSYS_GPIO_RESET}, - {"Linksys USB100TX", 0x066b, 0x2203, LINKSYS_GPIO_RESET}, - {"Linksys USB100TX", 0x066b, 0x2204, HAS_HOME_PNA | LINKSYS_GPIO_RESET}, - {"Linksys USB Ethernet Adapter", 0x066b, 0x2206, LINKSYS_GPIO_RESET}, - {"SMC 202 USB Ethernet", 0x0707, 0x0200, DEFAULT_GPIO_RESET}, - {"ADMtek AN986 \"Pegasus\" USB Ethernet (eval board)", 0x07a6, 0x0986, - HAS_HOME_PNA | DEFAULT_GPIO_RESET}, + DEFAULT_GPIO_RESET | HAS_HOME_PNA}, + {"D-Link DSB-650", 0x2001, 0xabc1, + DEFAULT_GPIO_RESET}, + {"D-Link DU-E10", 0x07b8, 0xabc1, + DEFAULT_GPIO_RESET}, + {"D-Link DU-E100", 0x07b8, 0x4002, + DEFAULT_GPIO_RESET}, + {"Linksys USB10TX", 0x066b, 0x2202, + LINKSYS_GPIO_RESET}, + {"Linksys USB100TX", 0x066b, 0x2203, + LINKSYS_GPIO_RESET}, + {"Linksys USB100TX", 0x066b, 0x2204, + LINKSYS_GPIO_RESET | HAS_HOME_PNA}, + {"Linksys USB Ethernet Adapter", 0x066b, 0x2206, + LINKSYS_GPIO_RESET}, + {"SMC 202 USB Ethernet", 0x0707, 0x0200, + DEFAULT_GPIO_RESET}, + {"ADMtek AN986 \"Pegasus\" USB Ethernet (eval board)", 0x07a6, 0x0986, + DEFAULT_GPIO_RESET | HAS_HOME_PNA}, {"Accton USB 10/100 Ethernet Adapter", 0x083a, 0x1046, DEFAULT_GPIO_RESET}, - {"IO DATA USB ET/TX", 0x04bb, 0x0904, DEFAULT_GPIO_RESET}, - {"LANEED USB Ethernet LD-USB/TX", 0x056e, 0x4002, DEFAULT_GPIO_RESET}, - {"SOHOware NUB100 Ethernet", 0x15e8, 0x9100, DEFAULT_GPIO_RESET}, + {"IO DATA USB ET/TX", 0x04bb, 0x0904, + DEFAULT_GPIO_RESET}, + {"LANEED USB Ethernet LD-USB/TX", 0x056e, 0x4002, + DEFAULT_GPIO_RESET}, + {"SOHOware NUB100 Ethernet", 0x15e8, 0x9100, + DEFAULT_GPIO_RESET}, {"ADMtek ADM8511 \"Pegasus II\" USB Ethernet", 0x07a6, 0x8511, - PEGASUS_II | DEFAULT_GPIO_RESET}, + DEFAULT_GPIO_RESET | PEGASUS_II}, {NULL, 0, 0, 0} }; @@ -536,7 +557,7 @@ static int enable_net_traffic( struct net_device *dev, struct usb_device *usb ) data[1] = 0; data[2] = (loopback & 1) ? 0x09 : 0x01; - *(unsigned *)pegasus->eth_regs = *(unsigned *)data; + memcpy( pegasus->eth_regs, data, sizeof(data) ); set_registers( pegasus, EthCtrl0, 3, data ); @@ -629,6 +650,7 @@ static void write_bulk_callback( struct urb *urb ) if ( urb->status ) info("%s: TX status %d", pegasus->net->name, urb->status); + pegasus->net->trans_start = jiffies; netif_wake_queue( pegasus->net ); } @@ -671,13 +693,11 @@ static void pegasus_tx_timeout( struct net_device *net ) if ( !pegasus ) return; - - usb_unlink_urb( &pegasus->tx_urb ); + warn("%s: Tx timed out.", net->name); + pegasus->tx_urb.transfer_flags |= USB_ASYNC_UNLINK; + usb_unlink_urb( &pegasus->tx_urb ); pegasus->stats.tx_errors++; - net->trans_start = jiffies; - - netif_wake_queue( net ); } @@ -696,7 +716,6 @@ static int pegasus_start_xmit( struct sk_buff *skb, struct net_device *net ) pegasus->tx_buff, PEGASUS_MAX_MTU, write_bulk_callback, pegasus ); pegasus->tx_urb.transfer_buffer_length = count; - pegasus->tx_urb.transfer_flags |= USB_ASYNC_UNLINK; if ((res = usb_submit_urb(&pegasus->tx_urb))) { warn("failed tx_urb %d", res); pegasus->stats.tx_errors++; @@ -781,8 +800,9 @@ static int pegasus_close( struct net_device *net ) usb_unlink_urb( &pegasus->rx_urb ); usb_unlink_urb( &pegasus->tx_urb ); usb_unlink_urb( &pegasus->ctrl_urb ); +#ifdef PEGASUS_USE_INTR usb_unlink_urb( &pegasus->intr_urb ); - +#endif MOD_DEC_USE_COUNT; return 0; @@ -935,8 +955,10 @@ static void * pegasus_probe( struct usb_device *dev, unsigned int ifnum ) return NULL; } + info( "%s: %s", net->name, usb_dev_id[dev_indx].name ); + set_ethernet_addr( pegasus ); - + if ( pegasus->features & PEGASUS_II ) { info( "setup Pegasus II specific registers" ); setup_pegasus_II( pegasus ); @@ -948,8 +970,6 @@ static void * pegasus_probe( struct usb_device *dev, unsigned int ifnum ) pegasus->phy = 1; } - info( "%s: %s", net->name, usb_dev_id[dev_indx].name ); - return pegasus; } diff --git a/drivers/video/S3triofb.c b/drivers/video/S3triofb.c index bcc2b9b7bca0..e8c0c97daeb2 100644 --- a/drivers/video/S3triofb.c +++ b/drivers/video/S3triofb.c @@ -60,8 +60,6 @@ #define IO_OUT16VAL(v, r) (((v) << 8) | (r)) -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - static int currcon = 0; static struct display disp; static struct fb_info fb_info; diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index 20cf8ef70299..e6ad28fcff1c 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -598,8 +598,6 @@ static u_short maxfmode, chipset; #define highw(x) ((u_long)(x)>>16 & 0xffff) #define loww(x) ((u_long)(x) & 0xffff) -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - #define VBlankOn() custom.intena = IF_SETCLR|IF_COPER #define VBlankOff() custom.intena = IF_COPER @@ -921,7 +919,7 @@ static struct fb_videomode ami_modedb[] __initdata = { #endif }; -#define NUM_TOTAL_MODES arraysize(ami_modedb) +#define NUM_TOTAL_MODES ARRAY_SIZE(ami_modedb) static const char *mode_option __initdata = NULL; static int round_down_bpp = 1; /* for mode probing */ diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index 3ad46bc68e77..c09a691a864a 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c @@ -86,8 +86,6 @@ #define SWITCH_NONE 0x00 -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - #define up(x, r) (((x) + (r) - 1) & ~((r)-1)) @@ -429,7 +427,7 @@ static struct fb_var_screeninfo atafb_predefined[] = { 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, }; -static int num_atafb_predefined=arraysize(atafb_predefined); +static int num_atafb_predefined=ARRAY_SIZE(atafb_predefined); static int diff --git a/drivers/video/clgenfb.c b/drivers/video/clgenfb.c index 57626f05c356..e490910c9b47 100644 --- a/drivers/video/clgenfb.c +++ b/drivers/video/clgenfb.c @@ -99,8 +99,6 @@ #define assert(expr) #endif -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - #ifdef TRUE #undef TRUE #endif @@ -450,7 +448,7 @@ static const struct { } }; -#define NUM_TOTAL_MODES arraysize(clgenfb_predefined) +#define NUM_TOTAL_MODES ARRAY_SIZE(clgenfb_predefined) static struct fb_var_screeninfo clgenfb_default; /* @@ -2431,7 +2429,7 @@ static struct pci_dev * __init clgen_pci_dev_get (clgen_board_t *btype) DPRINTK ("ENTER\n"); - for (i = 0; i < arraysize(clgen_pci_probe_list); i++) { + for (i = 0; i < ARRAY_SIZE(clgen_pci_probe_list); i++) { pdev = NULL; while ((pdev = pci_find_device (PCI_VENDOR_ID_CIRRUS, clgen_pci_probe_list[i].device, pdev)) != NULL) { @@ -2582,7 +2580,7 @@ static int __init clgen_zorro_find (struct zorro_dev **z_o, assert (z_o != NULL); assert (btype != NULL); - for (i = 0; i < arraysize(clgen_zorro_probe_list); i++) + for (i = 0; i < ARRAY_SIZE(clgen_zorro_probe_list); i++) if ((z = zorro_find_device(clgen_zorro_probe_list[i].id, NULL))) break; diff --git a/drivers/video/cyberfb.c b/drivers/video/cyberfb.c index 5c4af6bf0925..4510d116550d 100644 --- a/drivers/video/cyberfb.c +++ b/drivers/video/cyberfb.c @@ -107,8 +107,6 @@ static void cv64_dump(void); #define DPRINTK(fmt, args...) #endif -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - #define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat) #define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg)) @@ -221,7 +219,7 @@ static struct { }} }; -#define NUM_TOTAL_MODES arraysize(cyberfb_predefined) +#define NUM_TOTAL_MODES ARRAY_SIZE(cyberfb_predefined) static int Cyberfb_inverse = 0; diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c index d9f5c0579298..12bd1e526ddc 100644 --- a/drivers/video/fm2fb.c +++ b/drivers/video/fm2fb.c @@ -144,8 +144,6 @@ static void *fm2fb_mem; static unsigned long fm2fb_reg_phys; static volatile unsigned char *fm2fb_reg; -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - static int currcon = 0; static struct display disp; static struct fb_info fb_info; diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c index 1bbcc3fbdaa2..43829e53c585 100644 --- a/drivers/video/g364fb.c +++ b/drivers/video/g364fb.c @@ -77,8 +77,6 @@ #define MON_ID_REG 0xe4100000 /* unused */ #define RESET_REG 0xe4180000 /* Write only */ -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - static int currcon = 0; static struct display disp; static struct fb_info fb_info; diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c index 9e3be3e2709c..df23d1aff883 100644 --- a/drivers/video/hpfb.c +++ b/drivers/video/hpfb.c @@ -28,8 +28,6 @@ #include